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,1469 @@
1
+ // LibretroHost — Node-side host for a single Emscripten libretro core.
2
+ //
3
+ // One instance = one platform's core loaded + (optionally) one ROM. The host
4
+ // exposes a small public API the MCP layer wraps:
5
+ //
6
+ // loadCore(jsPath, wasmPath?)
7
+ // loadMedia({ platform, path, mediaKind? })
8
+ // unloadMedia()
9
+ // stepFrames(n)
10
+ // getFramebuffer() / screenshot()
11
+ // setInput(frameInput)
12
+ // saveState(name) / loadState(name) / listStates()
13
+ // readMemory(region, offset, length) / writeMemory(region, offset, bytes)
14
+ // reset() / pause() / resume() / getStatus()
15
+ //
16
+ // Patterns drawn from retroemu/LibretroHost.js + wasmcart-libretro/libretro.c.
17
+ // See memory `libretro-wasm-patterns`.
18
+
19
+ import { readFile } from "node:fs/promises";
20
+ import path from "node:path";
21
+ import os from "node:os";
22
+ import { mkdtempSync, readdirSync, statSync, readFileSync, existsSync } from "node:fs";
23
+ import { fileURLToPath } from "node:url";
24
+ import { loadLibretroCore } from "./coreLoader.js";
25
+ import { newCallbackState, registerCallbacks } from "./callbacks.js";
26
+ import { framebufferToRgba, framebufferToScreenshot } from "./framebuffer.js";
27
+ import {
28
+ MemoryRegionToRetro,
29
+ defaultMediaKind,
30
+ portInputToMask,
31
+ } from "./types.js";
32
+
33
+ /**
34
+ * Per-platform core-option overrides applied before retro_load_game.
35
+ * Most cores work with their menu-defaults; a few need explicit values
36
+ * to function headlessly (no menu = no user pick). Empty today — all
37
+ * shipped cores load with their defaults.
38
+ */
39
+ const PLATFORM_CORE_OPTIONS = {
40
+ // blueMSX defaults its machine to "SEGA - SC-3000" (an SG-1000 clone, wrong for
41
+ // MSX carts). Force the open MSX2+ C-BIOS machine — a superset that also runs
42
+ // MSX1 carts — so homebrew boots with no proprietary BIOS. The matching
43
+ // `… - C-BIOS` machine tree ships in romdev-core-bluemsx/bios and is mirrored
44
+ // into the wasm FS as the system dir (see loadMedia + resolveSystemDir).
45
+ msx: { bluemsx_msxtype: "MSX2+ - C-BIOS" },
46
+ };
47
+
48
+ /**
49
+ * Platforms whose core fopen()s a BIOS / machine-config tree from the system
50
+ * directory, mapped to the @romdev package + subdir that ships it. When the
51
+ * caller passes no systemDir, the host resolves the bundled tree from here so
52
+ * the platform boots with zero setup.
53
+ */
54
+ const PLATFORM_SYSTEM_DIR = {
55
+ msx: { pkg: "romdev-core-bluemsx", export: "biosDir" },
56
+ };
57
+
58
+ /**
59
+ * Resolve the absolute path of a platform's bundled system/BIOS dir, or null if
60
+ * the platform needs none / the package isn't resolvable. Best-effort: any
61
+ * failure falls back to null (the core then boots with whatever default it has).
62
+ * @param {string} platform
63
+ * @returns {string | null}
64
+ */
65
+ function resolvePlatformSystemDir(platform) {
66
+ const entry = PLATFORM_SYSTEM_DIR[platform];
67
+ if (!entry) return null;
68
+ try {
69
+ const dir = path.dirname(fileURLToPath(import.meta.resolve(entry.pkg)));
70
+ const biosDir = path.join(dir, "bios");
71
+ if (existsSync(biosDir)) return biosDir;
72
+ } catch { /* package not resolvable */ }
73
+ return null;
74
+ }
75
+
76
+ /**
77
+ * Recursively copy a host directory into the emscripten virtual FS so a core's
78
+ * fopen() can read it (BIOS / machine-config trees). emscripten FILESYSTEM=1
79
+ * MEMFS is enough — no NODEFS rebuild needed.
80
+ * @param {any} FS the core module's FS
81
+ * @param {string} hostDir absolute host path
82
+ * @param {string} fsDir destination path inside the wasm FS (e.g. "/system")
83
+ */
84
+ function mirrorDirToFS(FS, hostDir, fsDir) {
85
+ try { FS.mkdir(fsDir); } catch { /* exists */ }
86
+ for (const name of readdirSync(hostDir)) {
87
+ const hostPath = path.join(hostDir, name);
88
+ const fsPath = fsDir + "/" + name;
89
+ const st = statSync(hostPath);
90
+ if (st.isDirectory()) {
91
+ mirrorDirToFS(FS, hostPath, fsPath);
92
+ } else if (st.isFile()) {
93
+ try { FS.writeFile(fsPath, readFileSync(hostPath)); } catch { /* skip */ }
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * When loadMedia is called with `bytes:` and no `virtualName`, this is
100
+ * the extension we tack onto "/rom" so the core knows which platform
101
+ * it's looking at. Critical for shared cores — genesis_plus_gx looks
102
+ * at the path extension to pick SMS vs GG vs Genesis vs Master System.
103
+ * Round 26 fix: pre-r26, in-memory GG loads landed as SMS because the
104
+ * default virtualName was "/rom" with no extension.
105
+ */
106
+ export const PLATFORM_VIRTUAL_EXT = {
107
+ nes: ".nes",
108
+ snes: ".sfc",
109
+ genesis: ".md",
110
+ megadrive: ".md",
111
+ md: ".md",
112
+ sms: ".sms",
113
+ gg: ".gg",
114
+ gb: ".gb",
115
+ gbc: ".gbc",
116
+ gba: ".gba",
117
+ c64: ".prg",
118
+ lynx: ".lnx",
119
+ atari2600: ".a26",
120
+ atari7800: ".a78",
121
+ pce: ".pce",
122
+ msx: ".rom",
123
+ };
124
+ import { RETRO_DEVICE_JOYPAD } from "./retroConstants.js";
125
+
126
+ export class LibretroHost {
127
+ /**
128
+ * @param {Object} [opts]
129
+ * @param {string} [opts.systemDir] absolute path the core can ask about
130
+ * @param {string} [opts.saveDir] absolute path the core can ask about
131
+ * @param {(level: number, msg: string) => void} [opts.log]
132
+ */
133
+ constructor(opts = {}) {
134
+ const tmp = mkdtempSync(path.join(os.tmpdir(), "romdev-"));
135
+ /** @type {any | null} */
136
+ this.mod = null;
137
+ // The host-disk system dir (BIOS / machine configs). Mirrored into the wasm
138
+ // FS on first loadMedia for cores that fopen() from it (blueMSX C-BIOS).
139
+ this.systemDir = opts.systemDir ?? null;
140
+ this._systemDirMounted = false;
141
+ this.state = newCallbackState({
142
+ systemDir: opts.systemDir ?? tmp,
143
+ saveDir: opts.saveDir ?? tmp,
144
+ });
145
+ this.log = opts.log;
146
+ this.status = {
147
+ platform: null,
148
+ corePath: null,
149
+ mediaPath: null,
150
+ mediaKind: null,
151
+ loaded: false,
152
+ paused: false,
153
+ frameCount: 0,
154
+ fbWidth: 0,
155
+ fbHeight: 0,
156
+ };
157
+ /** @type {Map<string, Uint8Array>} */
158
+ this.namedStates = new Map();
159
+ }
160
+
161
+ /**
162
+ * Load a libretro core module. Registers callbacks then runs retro_init.
163
+ * @param {string} jsPath
164
+ * @param {string} [wasmPath]
165
+ */
166
+ async loadCore(jsPath, wasmPath) {
167
+ if (this.mod) throw new Error("core already loaded; create a new host");
168
+ const mod = await loadLibretroCore({ jsPath, wasmPath });
169
+ this.mod = mod;
170
+ registerCallbacks({ mod, state: this.state, log: this.log });
171
+ mod._retro_init();
172
+ this.status.corePath = jsPath;
173
+ }
174
+
175
+ /**
176
+ * Load media (ROM, disk, tape, program). Reads the file from disk,
177
+ * writes a copy into Emscripten's virtual FS so cores that `fopen` the path
178
+ * can find it, and calls `retro_load_game` with a populated `retro_game_info`.
179
+ *
180
+ * `retro_game_info` layout on wasm32:
181
+ * offset 0: const char *path (4 bytes)
182
+ * offset 4: const void *data (4 bytes)
183
+ * offset 8: size_t size (4 bytes)
184
+ * offset 12: const char *meta (4 bytes)
185
+ *
186
+ * @param {import("./types.js").LoadMediaArgs} args
187
+ */
188
+ async loadMedia(args) {
189
+ const mod = this._needMod();
190
+ const { platform } = args;
191
+ const mediaKind = args.mediaKind ?? defaultMediaKind(platform);
192
+
193
+ // Apply per-platform core option defaults BEFORE retro_load_game.
194
+ // Most cores work with their option defaults; a few need explicit
195
+ // overrides for headless use (none today, but the hook stays wired).
196
+ const overrides = PLATFORM_CORE_OPTIONS[platform];
197
+ if (overrides) {
198
+ for (const [key, value] of Object.entries(overrides)) {
199
+ this.state.coreVariables.set(key, { value });
200
+ }
201
+ // Cores poll GET_VARIABLE_UPDATE to know when to re-read options.
202
+ this.state.variablesUpdated = true;
203
+ }
204
+
205
+ // Some cores fopen() BIOS / machine-config files from the system directory
206
+ // (e.g. blueMSX reads `<systemDir>/Machines/<name>/cbios_*.rom`). When the
207
+ // caller didn't pass a systemDir, resolve the platform's bundled BIOS tree
208
+ // (romdev-core-bluemsx ships the open C-BIOS machines) so MSX "just works".
209
+ if (!this.systemDir) {
210
+ const bundled = resolvePlatformSystemDir(platform);
211
+ if (bundled) this.systemDir = bundled;
212
+ }
213
+
214
+ // The emscripten FS is virtual, so the host-disk systemDir isn't visible to
215
+ // the core's fopen unless we mirror it INTO the wasm FS. Do that once per
216
+ // host, and point the core's GET_SYSTEM_DIRECTORY at the in-FS path.
217
+ if (this.systemDir && !this._systemDirMounted && mod.FS) {
218
+ try {
219
+ const FS_SYS = "/system";
220
+ mirrorDirToFS(mod.FS, this.systemDir, FS_SYS);
221
+ // Redirect the core's reported system dir to the in-FS copy.
222
+ if (this.state) this.state.systemDir = FS_SYS;
223
+ this._systemDirMounted = true;
224
+ } catch (e) {
225
+ if (this.log) this.log(3, `system dir mirror failed: ${e.message}`);
226
+ }
227
+ }
228
+
229
+ let data, mediaPath, ext;
230
+ if (args.bytes) {
231
+ // In-memory load — no disk involved.
232
+ data = args.bytes instanceof Uint8Array ? args.bytes : new Uint8Array(args.bytes);
233
+ // Round 26 fix: when the caller doesn't pass a virtualName, default
234
+ // the virtual filename's EXTENSION to one the core uses to
235
+ // distinguish platforms it multiplexes. genesis_plus_gx shares one
236
+ // .wasm across SMS/GG/Genesis and dispatches off the extension —
237
+ // without `.gg` the core treats a GG ROM as SMS, silently. Same
238
+ // shape for any shared-core platform.
239
+ const defaultExt = PLATFORM_VIRTUAL_EXT[platform] ?? "";
240
+ mediaPath = args.virtualName ?? ("/rom" + defaultExt);
241
+ ext = path.extname(mediaPath);
242
+ // Synthesize a stable status path that still encodes the platform
243
+ // when the user didn't supply a name (helpful in logs).
244
+ if (!args.virtualName) mediaPath = "<memory" + defaultExt + ">";
245
+ } else if (args.path) {
246
+ mediaPath = args.path;
247
+ data = await readFile(mediaPath);
248
+ ext = path.extname(mediaPath);
249
+ } else {
250
+ throw new Error("loadMedia requires either `path` or `bytes`");
251
+ }
252
+ const vfsPath = "/rom" + ext;
253
+ if (mod.FS) {
254
+ try {
255
+ mod.FS.writeFile(vfsPath, data);
256
+ } catch (e) {
257
+ if (this.log) this.log(3, `FS.writeFile failed: ${e.message}`);
258
+ }
259
+ }
260
+
261
+ // Allocate ROM data into the WASM heap (the core may keep this pointer).
262
+ const dataPtr = mod._malloc(data.length);
263
+ mod.HEAPU8.set(data, dataPtr);
264
+
265
+ // Allocate path string.
266
+ const pathStr = mod.FS ? vfsPath : mediaPath;
267
+ const pathBytes = Buffer.from(pathStr + "\0", "utf-8");
268
+ const pathPtr = mod._malloc(pathBytes.length);
269
+ mod.HEAPU8.set(pathBytes, pathPtr);
270
+
271
+ // retro_game_info struct (16 bytes on wasm32).
272
+ const infoPtr = mod._malloc(16);
273
+ mod.setValue(infoPtr + 0, pathPtr, "i32");
274
+ mod.setValue(infoPtr + 4, dataPtr, "i32");
275
+ mod.setValue(infoPtr + 8, data.length, "i32");
276
+ mod.setValue(infoPtr + 12, 0, "i32"); // meta = null
277
+
278
+ const ok = mod._retro_load_game(infoPtr);
279
+
280
+ // Free the struct itself. Don't free pathPtr or dataPtr — the core may
281
+ // retain pointers into them for the life of the loaded game.
282
+ mod._free(infoPtr);
283
+
284
+ if (!ok) {
285
+ throw new Error(`retro_load_game failed for ${mediaPath}`);
286
+ }
287
+
288
+ this.status.platform = platform;
289
+ this.status.mediaPath = mediaPath;
290
+ this.status.mediaKind = mediaKind;
291
+ this.status.loaded = true;
292
+ this.status.frameCount = 0;
293
+
294
+ // Cache enough to re-load this exact media for a true power-cycle
295
+ // (reset({hard:true})). `retro_reset` is only a console RESET-button reset —
296
+ // it does NOT clear work RAM on most cores, so boot-seeded state persists.
297
+ // Stash the raw bytes (a copy, so a later free of the caller's buffer can't
298
+ // corrupt it) + the load descriptor; hardReset() replays loadMedia with it.
299
+ this._loadArgs = {
300
+ bytes: data instanceof Uint8Array ? data.slice() : new Uint8Array(data),
301
+ platform,
302
+ mediaKind,
303
+ virtualName: args.virtualName,
304
+ };
305
+
306
+ // Read system_av_info to seed framebuffer dimensions.
307
+ // struct retro_system_av_info {
308
+ // struct retro_game_geometry {
309
+ // unsigned base_width; // +0
310
+ // unsigned base_height; // +4
311
+ // unsigned max_width; // +8
312
+ // unsigned max_height; // +12
313
+ // float aspect_ratio; // +16
314
+ // }; // 20 bytes
315
+ // /* 4 bytes pad to align double */
316
+ // struct retro_system_timing {
317
+ // double fps; // +24
318
+ // double sample_rate; // +32
319
+ // };
320
+ // };
321
+ const avInfoPtr = mod._malloc(64);
322
+ mod._retro_get_system_av_info(avInfoPtr);
323
+ this.status.fbWidth = mod.getValue(avInfoPtr + 0, "i32");
324
+ this.status.fbHeight = mod.getValue(avInfoPtr + 4, "i32");
325
+ // aspect_ratio (+16) is the intended DISPLAY aspect (what a CRT would
326
+ // show). Cores often report a non-square value here because the
327
+ // framebuffer doesn't have square pixels — e.g. Atari 2600 ships a
328
+ // 160×210 buffer but the TV showed it ~4:3, SNES ships 256×224 but
329
+ // the CRT stretched it to ~8:7. Falls back to fb shape for cores that
330
+ // report 0 (meaning "pixels are square, just use base_width/height").
331
+ const reportedAspect = mod.getValue(avInfoPtr + 16, "float");
332
+ this.status.displayAspect = reportedAspect > 0
333
+ ? reportedAspect
334
+ : this.status.fbWidth / this.status.fbHeight;
335
+ // timing.sample_rate is at offset +32 (double).
336
+ this.status.audioSampleRate = mod.getValue(avInfoPtr + 32, "double");
337
+ mod._free(avInfoPtr);
338
+
339
+ // Configure controller port 0 as joypad (some cores default to NONE).
340
+ mod._retro_set_controller_port_device(0, RETRO_DEVICE_JOYPAD);
341
+
342
+ // ---- Settle the framebuffer to the ROM's chosen geometry ----
343
+ //
344
+ // av_info above gives the core's GEOMETRIC DEFAULT for the
345
+ // platform, NOT the dimensions the ROM ends up rendering. Most
346
+ // cores ship a power-on default that the ROM overrides during
347
+ // its own VDP/PPU init in the first few frames. Examples:
348
+ // - genesis_plus_gx defaults to 256×192 (H32, no border) but
349
+ // most Genesis games switch to 320×224 (H40) in their first
350
+ // init frame.
351
+ // - snes9x defaults to 256×224 but games select 256×239 or
352
+ // 512×448 (interlaced) based on PPU regs the ROM sets up.
353
+ //
354
+ // The rom-games agent reasonably expected fbWidth/Height after
355
+ // loadMedia to reflect "what screenshot will show me". Step a
356
+ // small number of frames here so the agent sees the ROM-chosen
357
+ // geometry, not the pre-init default.
358
+ //
359
+ // 8 frames is generous — Genesis games typically settle their
360
+ // VDP in 1-3 frames; SNES in 1; NES in 1-2. The cost is ~5-30 ms
361
+ // on loadMedia, paid once. Skip when loaded paused (caller is
362
+ // already in control).
363
+ if (!this.status.paused) {
364
+ // Settle frames are core warm-up, not agent-visible gameplay
365
+ // frames — don't increment frameCount. From the agent's POV the
366
+ // first stepFrames(N) should advance the count by exactly N.
367
+ //
368
+ // Strategy: step until the core emits its FIRST video_refresh
369
+ // (proven ROM-rendered geometry — pre-init av_info values are
370
+ // useless), THEN step a few more to let any same-frame mode-switch
371
+ // settle (e.g. Genesis ROMs that fire video_refresh in 256×192
372
+ // mode then immediately switch to 320×224 on the next frame).
373
+ //
374
+ // Cap aggressively — 64 frames is just over 1 second on a 60Hz
375
+ // platform and we don't want a pathological ROM blocking
376
+ // loadMedia indefinitely.
377
+ const MAX_SETTLE = 64;
378
+ const FRAMES_AFTER_FIRST_REFRESH = 4;
379
+ const beforeRefreshSnapshot = this.state.lastFrame;
380
+ let stepped = 0;
381
+ let firstRefreshAt = -1;
382
+ while (stepped < MAX_SETTLE) {
383
+ mod._retro_run();
384
+ stepped++;
385
+ if (firstRefreshAt < 0 && this.state.lastFrame && this.state.lastFrame !== beforeRefreshSnapshot) {
386
+ firstRefreshAt = stepped;
387
+ }
388
+ if (firstRefreshAt > 0 && stepped >= firstRefreshAt + FRAMES_AFTER_FIRST_REFRESH) break;
389
+ }
390
+ if (this.state.lastFrame) {
391
+ this.status.fbWidth = this.state.lastFrame.width;
392
+ this.status.fbHeight = this.state.lastFrame.height;
393
+ }
394
+ // Diagnostic: surface what happened in case agents want to know
395
+ // why loadMedia took longer than expected.
396
+ this.status.settleFramesUsed = stepped;
397
+ this.status.settleFirstRefreshAt = firstRefreshAt;
398
+ }
399
+ }
400
+
401
+ unloadMedia() {
402
+ const mod = this._needMod();
403
+ if (this.status.loaded) {
404
+ mod._retro_unload_game();
405
+ this.status.loaded = false;
406
+ this.status.platform = null;
407
+ this.status.mediaPath = null;
408
+ this.status.mediaKind = null;
409
+ this.status.frameCount = 0;
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Run N frames as fast as possible (no pacing — agent loop, not playback).
415
+ * @param {number} n
416
+ * @returns {number} frames actually run
417
+ */
418
+ stepFrames(n) {
419
+ const mod = this._needMod();
420
+ if (!this.status.loaded) throw new Error("no media loaded");
421
+ if (this.status.paused) return 0;
422
+ for (let i = 0; i < n; i++) {
423
+ mod._retro_run();
424
+ this.status.frameCount++;
425
+ }
426
+ if (this.state.lastFrame) {
427
+ this.status.fbWidth = this.state.lastFrame.width;
428
+ this.status.fbHeight = this.state.lastFrame.height;
429
+ }
430
+ return n;
431
+ }
432
+
433
+ /** Run exactly ONE frame to refresh the framebuffer, even while paused — for a
434
+ * deterministic "restore → screenshot" without un-pausing (so the real-time
435
+ * playtest loop can't race). Advances the (monotonic) frame counter by 1.
436
+ * Returns the frame count after. */
437
+ renderOneFrame() {
438
+ const mod = this._needMod();
439
+ if (!this.status.loaded) throw new Error("no media loaded");
440
+ mod._retro_run();
441
+ this.status.frameCount++;
442
+ if (this.state.lastFrame) {
443
+ this.status.fbWidth = this.state.lastFrame.width;
444
+ this.status.fbHeight = this.state.lastFrame.height;
445
+ }
446
+ return this.status.frameCount;
447
+ }
448
+
449
+ /** @returns {{ width: number, height: number, pitch: number, format: number, pixels: Uint8Array }} */
450
+ getFramebuffer() {
451
+ if (!this.state.lastFrame) throw new Error("no frame produced yet — step frames first");
452
+ return this.state.lastFrame;
453
+ }
454
+
455
+ /**
456
+ * The loaded cartridge ROM as the CPU's program space starts from, derived
457
+ * from the bytes handed to retro_load_game (the file image, header-stripped
458
+ * per platform). This is NOT a live core memory region — it's the loaded image
459
+ * — but for un-banked platforms (Genesis/GB/SMS/GG: file base == CPU $000000 /
460
+ * $0000) reading offset N here IS "what the CPU fetches at ROM address N", which
461
+ * is exactly what you need to confirm a patch is actually running. For banked
462
+ * platforms (NES PRG, SNES LoROM/HiROM) the file image is correct bytes but the
463
+ * CPU sees them through a mapper, so a file offset is not a flat CPU address.
464
+ *
465
+ * @returns {{ bytes: Uint8Array, base: number, headerSkipped: number, mapped: boolean, platform: string, note: string }}
466
+ */
467
+ getCartRom() {
468
+ if (!this._loadArgs || !this._loadArgs.bytes) {
469
+ throw new Error("no ROM loaded — call loadMedia first");
470
+ }
471
+ const platform = this._loadArgs.platform;
472
+ const raw = this._loadArgs.bytes;
473
+ let headerSkipped = 0;
474
+ let mapped = false;
475
+ let base = 0;
476
+ let note = "File image == CPU ROM space (un-banked): offset N is the byte the CPU fetches at ROM address N.";
477
+
478
+ if (platform === "nes") {
479
+ // iNES / NES2.0: 16-byte header, then PRG (then CHR). The CPU sees PRG via
480
+ // the mapper at $8000-$FFFF — file offset is NOT a flat CPU address.
481
+ if (raw.length >= 4 && raw[0] === 0x4e && raw[1] === 0x45 && raw[2] === 0x53 && raw[3] === 0x1a) headerSkipped = 16;
482
+ mapped = true;
483
+ note = "NES PRG-ROM (iNES header skipped). Bytes are correct but the CPU sees them through the mapper at $8000-$FFFF — a file offset is not a flat CPU address. Use findWriter's prgOffset/bank to map a CPU PC to a PRG offset.";
484
+ } else if (platform === "snes") {
485
+ // Copier header: 512 bytes iff (len % 1024) == 512. After that, LoROM/HiROM
486
+ // banking maps the image into $00:8000+ — also not a flat CPU address.
487
+ if ((raw.length % 1024) === 512) headerSkipped = 512;
488
+ mapped = true;
489
+ note = "SNES ROM (copier header skipped if present). Bytes are correct but LoROM/HiROM banking maps them into $xx:8000+ — a file offset is not a flat CPU address.";
490
+ } else if (platform === "gba") {
491
+ mapped = true;
492
+ base = 0x08000000;
493
+ note = "GBA ROM is mapped flat at 0x08000000 — CPU address = 0x08000000 + file offset.";
494
+ }
495
+ // genesis/megadrive, gb, gbc, sms, gg, lynx, pce, c64, msx, atari*: file base
496
+ // is the CPU ROM base (un-banked or banked-from-0), default note applies.
497
+
498
+ const bytes = headerSkipped ? raw.subarray(headerSkipped) : raw;
499
+ return { bytes, base, headerSkipped, mapped, platform, note };
500
+ }
501
+
502
+ /**
503
+ * Cheap fingerprint of the current frame (FNV-1a over the pixel bytes), for
504
+ * "did the screen change?" checks without retaining a full base64 copy. 0 if
505
+ * no frame yet. Two identical frames hash identically; any pixel diff changes it.
506
+ * @returns {number}
507
+ */
508
+ framebufferHash() {
509
+ if (!this.state.lastFrame) return 0;
510
+ const px = this.state.lastFrame.pixels;
511
+ let h = 0x811c9dc5;
512
+ // Sample stride 1 (every byte) — frames are small (≤256x240x4); the whole
513
+ // buffer hashes in well under a frame's worth of time.
514
+ for (let i = 0; i < px.length; i++) {
515
+ h ^= px[i];
516
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0; // h * 16777619 mod 2^32
517
+ }
518
+ return h >>> 0;
519
+ }
520
+
521
+ /** Returns the latest frame as a base64 PNG. */
522
+ screenshot() {
523
+ const f = this.getFramebuffer();
524
+ return framebufferToScreenshot(f.width, f.height, f.pixels, f.pitch, f.format);
525
+ }
526
+
527
+ /** Returns the latest frame as flat RGBA8888 bytes — for piping into
528
+ * chafa-wasm or other pixel-consuming tools without the PNG round trip. */
529
+ screenshotRgba() {
530
+ const f = this.getFramebuffer();
531
+ return {
532
+ width: f.width,
533
+ height: f.height,
534
+ rgba: framebufferToRgba(f.width, f.height, f.pixels, f.pitch, f.format),
535
+ };
536
+ }
537
+
538
+ /** @param {import("./types.js").FrameInput} input */
539
+ setInput(input) {
540
+ const platform = this.status.platform ?? undefined;
541
+ for (let port = 0; port < this.state.inputPorts.length; port++) {
542
+ const portInput = input.ports[port];
543
+ this.state.inputPorts[port][0] = portInputToMask(portInput, platform);
544
+ }
545
+ }
546
+
547
+ /** @param {string} name */
548
+ saveState(name) {
549
+ const snapshot = this.serializeState();
550
+ this.namedStates.set(name, snapshot);
551
+ }
552
+
553
+ /**
554
+ * Return the raw save-state blob — every libretro core implements this,
555
+ * so it's the one cross-platform way to peek at internal state the
556
+ * standard memory-region API doesn't expose (e.g. SNES SPC700 + ARAM,
557
+ * Genesis Z80 RAM, GB hardware regs). The blob's layout is core-specific;
558
+ * callers typically grep for known byte patterns to locate regions.
559
+ * @returns {Uint8Array}
560
+ */
561
+ serializeState() {
562
+ const mod = this._needMod();
563
+ const size = mod._retro_serialize_size();
564
+ if (!size) throw new Error("core reports zero serialize size");
565
+ const ptr = mod._malloc(size);
566
+ try {
567
+ const ok = mod._retro_serialize(ptr, size);
568
+ if (!ok) throw new Error("retro_serialize failed");
569
+ return new Uint8Array(mod.HEAPU8.buffer, ptr, size).slice();
570
+ } finally {
571
+ mod._free(ptr);
572
+ }
573
+ }
574
+
575
+ /** @param {string} name */
576
+ loadState(name) {
577
+ const snapshot = this.namedStates.get(name);
578
+ if (!snapshot) throw new Error(`no save state named '${name}'`);
579
+ return this.unserializeState(snapshot); // returns # cheats cleared
580
+ }
581
+
582
+ /**
583
+ * Restore the emulator from a raw save-state blob (the inverse of
584
+ * serializeState). Used by both the in-memory loadState and the
585
+ * load-from-disk path so they share one code path. The blob must come from
586
+ * the SAME core/platform that produced it — retro_unserialize rejects a
587
+ * size/format mismatch and we surface that as a clear error.
588
+ * @param {Uint8Array} blob
589
+ */
590
+ unserializeState(blob) {
591
+ const mod = this._needMod();
592
+ if (!blob || !blob.byteLength) throw new Error("unserializeState: empty blob");
593
+ const expected = mod._retro_serialize_size();
594
+ if (expected && blob.byteLength !== expected) {
595
+ throw new Error(
596
+ `save-state size mismatch: blob is ${blob.byteLength} bytes but this core expects ${expected}. ` +
597
+ "The state was almost certainly saved from a different platform/ROM — load the matching ROM first.",
598
+ );
599
+ }
600
+ const ptr = mod._malloc(blob.byteLength);
601
+ try {
602
+ mod.HEAPU8.set(blob, ptr);
603
+ const ok = mod._retro_unserialize(ptr, blob.byteLength);
604
+ if (!ok) throw new Error("retro_unserialize failed (core rejected the blob)");
605
+ } finally {
606
+ mod._free(ptr);
607
+ }
608
+ // A save-state restore replaces RAM/CPU/PPU but does NOT carry frontend cheat
609
+ // state — and our active cheats were applied for the PRE-restore run. Clear
610
+ // them so loadState honors its documented "cheats are removed" contract
611
+ // (matches reset()). Returns how many were cleared so callers can report it.
612
+ const cleared = this._activeCheats ? this._activeCheats.size : 0;
613
+ if (cleared) this.clearCheats();
614
+ return cleared;
615
+ }
616
+
617
+ listStates() {
618
+ return Array.from(this.namedStates.keys());
619
+ }
620
+
621
+ /** Return a named in-memory slot's raw blob (for exporting to disk WITHOUT
622
+ * disturbing the live host). Throws if the slot doesn't exist. */
623
+ getStateBlob(name) {
624
+ const blob = this.namedStates.get(name);
625
+ if (!blob) throw new Error(`no save state named '${name}'`);
626
+ return blob;
627
+ }
628
+
629
+ /**
630
+ * @param {import("./types.js").MemoryRegion} region
631
+ * @param {number} offset
632
+ * @param {number} length
633
+ * @returns {Uint8Array}
634
+ */
635
+ /**
636
+ * Byte size of a memory region (0 if the core doesn't expose it). Lets tools
637
+ * read "the whole region from offset" without guessing a length.
638
+ * @param {import("./types.js").MemoryRegion} region
639
+ * @returns {number}
640
+ */
641
+ regionSize(region) {
642
+ const mod = this._needMod();
643
+ const id = MemoryRegionToRetro[region];
644
+ if (id === undefined) return 0;
645
+ return mod._retro_get_memory_size(id) || 0;
646
+ }
647
+
648
+ readMemory(region, offset, length) {
649
+ const mod = this._needMod();
650
+ const id = MemoryRegionToRetro[region];
651
+ if (id === undefined) throw new Error(`unknown memory region '${region}'`);
652
+ const ptr = mod._retro_get_memory_data(id);
653
+ const size = mod._retro_get_memory_size(id);
654
+ if (!ptr || !size) throw new Error(this._emptyRegionError(region));
655
+ if (offset < 0 || offset + length > size) {
656
+ throw new RangeError(`read out of bounds: offset=${offset} len=${length} size=${size}`);
657
+ }
658
+ return new Uint8Array(mod.HEAPU8.buffer, ptr + offset, length).slice();
659
+ }
660
+
661
+ /**
662
+ * @param {import("./types.js").MemoryRegion} region
663
+ * @param {number} offset
664
+ * @param {Uint8Array} bytes
665
+ */
666
+ writeMemory(region, offset, bytes) {
667
+ const mod = this._needMod();
668
+ const id = MemoryRegionToRetro[region];
669
+ if (id === undefined) throw new Error(`unknown memory region '${region}'`);
670
+ const ptr = mod._retro_get_memory_data(id);
671
+ const size = mod._retro_get_memory_size(id);
672
+ if (!ptr || !size) throw new Error(this._emptyRegionError(region));
673
+ if (offset < 0 || offset + bytes.length > size) {
674
+ throw new RangeError(`write out of bounds: offset=${offset} len=${bytes.length} size=${size}`);
675
+ }
676
+ mod.HEAPU8.set(bytes, ptr + offset);
677
+ }
678
+
679
+ reset() {
680
+ const mod = this._needMod();
681
+ mod._retro_reset();
682
+ this.status.frameCount = 0;
683
+ // A reset clears the core's active cheats (they live in volatile core
684
+ // state, never in the ROM) — keep our mirror in sync.
685
+ this._activeCheats = new Map();
686
+ }
687
+
688
+ /**
689
+ * True power-cycle: re-load the ROM from scratch so work RAM is cleared and
690
+ * all boot-seeded state is fresh — what `retro_reset` does NOT do (it's only
691
+ * the RESET button; RAM persists on most cores). Falls back to a soft reset
692
+ * if the load args weren't cached (shouldn't happen after a normal load).
693
+ * @returns {Promise<boolean>} true if a full reload happened
694
+ */
695
+ async hardReset() {
696
+ if (!this._loadArgs) {
697
+ this.reset();
698
+ return false;
699
+ }
700
+ await this.loadMedia(this._loadArgs);
701
+ return true;
702
+ }
703
+
704
+ /** True when this core's WASM build exposes the libretro cheat interface.
705
+ * (Older bundled cores predate the cheat-export build flag.) */
706
+ cheatsSupported() {
707
+ const mod = this.mod;
708
+ return !!(mod && typeof mod._retro_cheat_set === "function");
709
+ }
710
+
711
+ /**
712
+ * Enable (or update) a cheat via the libretro cheat interface — the SAME
713
+ * mechanism RetroArch uses. NON-DESTRUCTIVE: the code is applied in volatile
714
+ * core state (RAM write each frame for RAM cheats; an in-core read-intercept
715
+ * for ROM/compare cheats). The ROM file on disk is NEVER modified, and a
716
+ * reset/unload/loadState clears it. `code` is the RAW cheat string (e.g.
717
+ * "00C7:FF", "SXIOPO", "AJ9T-CA5Y") — the CORE decodes it, so this works for
718
+ * every format the core understands without us decoding first.
719
+ * @param {number} index slot index (0-based; reuse to overwrite a slot)
720
+ * @param {string} code raw cheat code string
721
+ * @param {boolean} [enabled=true]
722
+ */
723
+ setCheat(index, code, enabled = true) {
724
+ const mod = this._needMod();
725
+ if (typeof mod._retro_cheat_set !== "function") {
726
+ throw new Error(
727
+ "this core build does not expose the cheat interface (retro_cheat_set). " +
728
+ "Rebuild the core with the cheat exports, or apply RAM cheats via writeMemory.",
729
+ );
730
+ }
731
+ const bytes = Buffer.from(String(code) + "\0", "utf-8");
732
+ const ptr = mod._malloc(bytes.length);
733
+ try {
734
+ mod.HEAPU8.set(bytes, ptr);
735
+ mod._retro_cheat_set(index >>> 0, enabled ? 1 : 0, ptr);
736
+ } finally {
737
+ mod._free(ptr);
738
+ }
739
+ if (!this._activeCheats) this._activeCheats = new Map();
740
+ if (enabled) this._activeCheats.set(index, code);
741
+ else this._activeCheats.delete(index);
742
+ }
743
+
744
+ /** Clear ALL active cheats (calls retro_cheat_reset). Non-destructive. */
745
+ clearCheats() {
746
+ const mod = this._needMod();
747
+ if (typeof mod._retro_cheat_reset === "function") mod._retro_cheat_reset();
748
+ this._activeCheats = new Map();
749
+ }
750
+
751
+ /** The cheats currently enabled in this session: [{ index, code }]. */
752
+ listActiveCheats() {
753
+ return Array.from((this._activeCheats ?? new Map()).entries())
754
+ .map(([index, code]) => ({ index, code }))
755
+ .sort((a, b) => a.index - b.index);
756
+ }
757
+
758
+ /** True when this core build exposes the instruction-level write watchpoint. */
759
+ watchpointSupported() {
760
+ const mod = this.mod;
761
+ return !!(mod && typeof mod._romdev_watchpoint_set === "function" && typeof mod._romdev_watchpoint_get === "function");
762
+ }
763
+
764
+ /**
765
+ * Arm (or disarm) the instruction-level write watchpoint on a CPU address.
766
+ * Unlike the frame-sampled watchMemory PC, this records the EXACT writing
767
+ * instruction's PC (captured inside the core's CPU write path), so it's
768
+ * correct even for NMI/IRQ-driven writes. One watchpoint at a time.
769
+ * @param {number} address CPU address to watch
770
+ * @param {boolean} [enabled=true]
771
+ */
772
+ setWatchpoint(address, enabled = true) {
773
+ const mod = this._needMod();
774
+ if (typeof mod._romdev_watchpoint_set !== "function") {
775
+ throw new Error("this core build does not expose the write watchpoint (rebuild with romdev_watchpoint_* exports).");
776
+ }
777
+ mod._romdev_watchpoint_set(address >>> 0, enabled ? 1 : 0);
778
+ }
779
+
780
+ /** Read the watchpoint state: { enabled, address, lastPC, lastValue, hits,
781
+ * prgOffset? }. lastPC is 0xFFFFFFFF (reported as null) until a write is seen.
782
+ * prgOffset (when the core reports it — fceumm/NES) is the ABSOLUTE PRG-ROM
783
+ * offset of the writing instruction, which disambiguates the BANK for a
784
+ * $8000-$BFFF PC on a banked mapper. Pass clearHits to reset after reading. */
785
+ getWatchpoint(clearHits = false) {
786
+ const mod = this._needMod();
787
+ if (typeof mod._romdev_watchpoint_get !== "function") {
788
+ throw new Error("this core build does not expose the write watchpoint.");
789
+ }
790
+ const ptr = mod._malloc(24); // up to 6 × uint32 (older cores write only 5)
791
+ try {
792
+ // Pre-seed slot 6 so a 5-element core leaves prgOffset = "none".
793
+ new Uint32Array(mod.HEAPU8.buffer, ptr, 6).fill(0xFFFFFFFF);
794
+ mod._romdev_watchpoint_get(ptr, clearHits ? 1 : 0);
795
+ const u = new Uint32Array(mod.HEAPU8.buffer, ptr, 6);
796
+ const lastPC = u[2];
797
+ const prgOffset = u[5];
798
+ return {
799
+ enabled: !!u[0],
800
+ address: u[1],
801
+ lastPC: lastPC === 0xFFFFFFFF ? null : lastPC,
802
+ lastValue: u[3] & 0xFF,
803
+ hits: u[4],
804
+ ...(prgOffset !== 0xFFFFFFFF ? { prgOffset } : {}),
805
+ };
806
+ } finally {
807
+ mod._free(ptr);
808
+ }
809
+ }
810
+
811
+ // ── PC breakpoint + read watchpoint + single-step (core-side, exact) ────────
812
+ // Symmetric to the write watchpoint. The PC breakpoint freezes the CPU at the
813
+ // target instruction mid-frame (the core's execute loop bails on hit); the
814
+ // read watchpoint records the PC that READ an address. Both require a core
815
+ // patched with the romdev_pcbreak_*/romdev_readwatch_* exports (Genesis today;
816
+ // other cores as they're patched). Capability is feature-detected per core.
817
+
818
+ /** True when this core build exposes the PC breakpoint + single-step. */
819
+ pcBreakSupported() {
820
+ const mod = this.mod;
821
+ return !!(mod && typeof mod._romdev_pcbreak_set === "function" && typeof mod._romdev_pcbreak_get === "function");
822
+ }
823
+
824
+ /** True when this core build exposes the instruction-level read watchpoint. */
825
+ readWatchSupported() {
826
+ const mod = this.mod;
827
+ return !!(mod && typeof mod._romdev_readwatch_set === "function" && typeof mod._romdev_readwatch_get === "function");
828
+ }
829
+
830
+ /** Arm/disarm the PC breakpoint. `step:true` arms a one-instruction
831
+ * single-step (the address is ignored). One breakpoint at a time. */
832
+ setPCBreak(address, enabled = true, step = false) {
833
+ const mod = this._needMod();
834
+ if (typeof mod._romdev_pcbreak_set !== "function") {
835
+ throw new Error("this core build does not expose the PC breakpoint (rebuild with romdev_pcbreak_* exports).");
836
+ }
837
+ mod._romdev_pcbreak_set(address >>> 0, enabled ? 1 : 0, step ? 1 : 0);
838
+ }
839
+
840
+ /** Read the breakpoint state: { enabled, address, hit, lastPC, hits }.
841
+ * lastPC is null until a hit. Pass clearHit to re-arm (clears the hit flag). */
842
+ getPCBreak(clearHit = false) {
843
+ const mod = this._needMod();
844
+ if (typeof mod._romdev_pcbreak_get !== "function") {
845
+ throw new Error("this core build does not expose the PC breakpoint.");
846
+ }
847
+ const ptr = mod._malloc(24); // up to 6 × uint32 (older cores write 5)
848
+ try {
849
+ // Pre-seed slot 5 (watchdog) so a 5-element older core leaves it 0.
850
+ new Uint32Array(mod.HEAPU8.buffer, ptr, 6).fill(0);
851
+ mod._romdev_pcbreak_get(ptr, clearHit ? 1 : 0);
852
+ const u = new Uint32Array(mod.HEAPU8.buffer, ptr, 6);
853
+ const lastPC = u[3];
854
+ return {
855
+ enabled: !!u[0],
856
+ address: u[1],
857
+ hit: !!u[2],
858
+ lastPC: lastPC === 0xFFFFFFFF ? null : lastPC,
859
+ hits: u[4],
860
+ watchdog: !!u[5], // the run was force-stopped by the instruction watchdog
861
+ };
862
+ } finally {
863
+ mod._free(ptr);
864
+ }
865
+ }
866
+
867
+ /** Arm the instruction watchdog (force-stop a runaway after `limit` instructions
868
+ * so callSubroutine can't hang the WASM; 0 = disable). No-op on cores that lack
869
+ * it (older builds) — the per-frame maxFrames is the fallback there. */
870
+ setWatchdog(limit) {
871
+ const mod = this._needMod();
872
+ if (typeof mod._romdev_watchdog_set === "function") mod._romdev_watchdog_set(limit >>> 0);
873
+ }
874
+ watchdogSupported() {
875
+ return !!(this.mod && typeof this.mod._romdev_watchdog_set === "function");
876
+ }
877
+
878
+ /** Arm/disarm the read watchpoint on a CPU address. */
879
+ setReadWatch(address, enabled = true) {
880
+ const mod = this._needMod();
881
+ if (typeof mod._romdev_readwatch_set !== "function") {
882
+ throw new Error("this core build does not expose the read watchpoint (rebuild with romdev_readwatch_* exports).");
883
+ }
884
+ mod._romdev_readwatch_set(address >>> 0, enabled ? 1 : 0);
885
+ }
886
+
887
+ /** Read the read-watchpoint state: { enabled, address, lastPC, lastValue, hits }. */
888
+ getReadWatch(clearHits = false) {
889
+ const mod = this._needMod();
890
+ if (typeof mod._romdev_readwatch_get !== "function") {
891
+ throw new Error("this core build does not expose the read watchpoint.");
892
+ }
893
+ const ptr = mod._malloc(20); // 5 × uint32
894
+ try {
895
+ mod._romdev_readwatch_get(ptr, clearHits ? 1 : 0);
896
+ const u = new Uint32Array(mod.HEAPU8.buffer, ptr, 5);
897
+ const lastPC = u[2];
898
+ return {
899
+ enabled: !!u[0],
900
+ address: u[1],
901
+ lastPC: lastPC === 0xFFFFFFFF ? null : lastPC,
902
+ lastValue: u[3] & 0xFF,
903
+ hits: u[4],
904
+ };
905
+ } finally {
906
+ mod._free(ptr);
907
+ }
908
+ }
909
+
910
+ /**
911
+ * Run until the CPU PC reaches `address` (or until `maxFrames` frames elapse),
912
+ * then stop with the CPU frozen exactly at that instruction. Returns
913
+ * { hit, frame, pc?, hits? }. On hit the registers are readable via getCPUState.
914
+ * The breakpoint is auto-disarmed after the run so normal stepping resumes.
915
+ */
916
+ /**
917
+ * Drive `_retro_run()` in a tight loop while making THIS call the sole driver
918
+ * of the core. If a playtest window is open, its 60fps setInterval tick is
919
+ * ALSO calling stepFrames(1) on this same shared host — two drivers racing
920
+ * would let the tick step past a breakpoint between our iterations and corrupt
921
+ * frame timing. The playtest tick skips stepping whenever `status.paused`, so
922
+ * we mark the host paused for the duration (and restore the prior state after),
923
+ * giving us exclusive control. We drive `_retro_run()` directly here rather
924
+ * than via stepFrames() precisely because stepFrames() no-ops while paused.
925
+ * The window keeps RENDERING the frozen frame, so the human still sees state.
926
+ * @param {(i:number)=>boolean} body called per frame; return true to stop early.
927
+ * @param {number} maxFrames
928
+ * @returns {number} frames actually run
929
+ */
930
+ _runFramesExclusive(body, maxFrames) {
931
+ const mod = this._needMod();
932
+ // Suspend ONLY the playtest window's render-tick stepping for the duration —
933
+ // not `status.paused` (the agent's pause is a separate concept, and the core
934
+ // run must be identical whether or not the user paused). The playtest tick
935
+ // checks `_renderTickSuspended` and renders-only while it's set; we own the
936
+ // core's frame advance here so the two never race past a breakpoint.
937
+ const prevSuspended = this._renderTickSuspended;
938
+ this._renderTickSuspended = true;
939
+ let framesRun = 0;
940
+ try {
941
+ for (let i = 0; i < maxFrames; i++) {
942
+ mod._retro_run();
943
+ this.status.frameCount++;
944
+ framesRun++;
945
+ if (body(i)) break;
946
+ }
947
+ } finally {
948
+ this._renderTickSuspended = prevSuspended;
949
+ if (this.state.lastFrame) {
950
+ this.status.fbWidth = this.state.lastFrame.width;
951
+ this.status.fbHeight = this.state.lastFrame.height;
952
+ }
953
+ }
954
+ return framesRun;
955
+ }
956
+
957
+ runUntilPC(address, maxFrames = 600) {
958
+ this._needMod();
959
+ if (!this.status.loaded) throw new Error("no media loaded");
960
+ if (!this.pcBreakSupported()) {
961
+ throw new Error("PC breakpoint not supported by this core (Genesis today; other cores as patched).");
962
+ }
963
+ this.setPCBreak(address, true, false);
964
+ let hit = false;
965
+ let framesRun = 0;
966
+ try {
967
+ framesRun = this._runFramesExclusive(() => {
968
+ if (this.getPCBreak(false).hit) { hit = true; return true; }
969
+ return false;
970
+ }, maxFrames);
971
+ } finally {
972
+ // Disarm so subsequent stepFrames/runUntil* run normally.
973
+ this.setPCBreak(0, false, false);
974
+ }
975
+ const st = this.getPCBreak(true); // read final state + clear hit
976
+ return {
977
+ hit,
978
+ frame: this.status.frameCount,
979
+ framesRun,
980
+ ...(hit ? { pc: st.lastPC, hits: st.hits } : {}),
981
+ };
982
+ }
983
+
984
+ /**
985
+ * Run until a watched address is READ (or maxFrames elapse). Unlike the PC
986
+ * break this does NOT freeze mid-frame — it records the reading PC and the run
987
+ * completes the frame it was found in. Returns { hit, frame, pc?, value?, hits? }.
988
+ */
989
+ runUntilRead(address, maxFrames = 600) {
990
+ this._needMod();
991
+ if (!this.status.loaded) throw new Error("no media loaded");
992
+ if (!this.readWatchSupported()) {
993
+ throw new Error("read watchpoint not supported by this core (Genesis today; other cores as patched).");
994
+ }
995
+ this.setReadWatch(address, true);
996
+ let hit = false;
997
+ let framesRun = 0;
998
+ try {
999
+ framesRun = this._runFramesExclusive(() => {
1000
+ if (this.getReadWatch(false).hits > 0) { hit = true; return true; }
1001
+ return false;
1002
+ }, maxFrames);
1003
+ } finally {
1004
+ this.setReadWatch(0, false);
1005
+ }
1006
+ const st = this.getReadWatch(true);
1007
+ return {
1008
+ hit,
1009
+ frame: this.status.frameCount,
1010
+ framesRun,
1011
+ ...(hit ? { pc: st.lastPC, value: st.lastValue, hits: st.hits } : {}),
1012
+ };
1013
+ }
1014
+
1015
+ /**
1016
+ * Execute exactly ONE CPU instruction and stop (single-step). Freezes the CPU
1017
+ * right after the stepped instruction. Returns { pc } — the PC the CPU is now
1018
+ * poised at. Note: a frame may advance other subsystems; this is a CPU-level
1019
+ * single-step, the finest granularity the core exposes.
1020
+ */
1021
+ stepInstruction() {
1022
+ this._needMod();
1023
+ if (!this.status.loaded) throw new Error("no media loaded");
1024
+ if (!this.pcBreakSupported()) {
1025
+ throw new Error("single-step not supported by this core (Genesis today; other cores as patched).");
1026
+ }
1027
+ this.setPCBreak(0, false, true); // step mode (one-shot)
1028
+ // Exclusive driver (suspends the playtest tick); the step fires on the very
1029
+ // next instruction, so one frame is more than enough for the core to dispatch
1030
+ // it. Stop after that one frame regardless.
1031
+ this._runFramesExclusive(() => true, 1);
1032
+ const st = this.getPCBreak(true);
1033
+ return { pc: st.lastPC, hit: st.hit };
1034
+ }
1035
+
1036
+ // ── Register write + callSubroutine (item 1) ────────────────────────────────
1037
+ // romdev reg-id convention (stable across all patched cores): for the m68k
1038
+ // family 0..7=D0..D7, 8..15=A0..A7, 16=PC, 17=SR, 18=SP. Other CPU families map
1039
+ // their own registers onto the same id space (documented per core).
1040
+
1041
+ /** True when this core build exposes register-write + callSubroutine. */
1042
+ setRegSupported() {
1043
+ const mod = this.mod;
1044
+ return !!(mod && typeof mod._romdev_setreg === "function" && typeof mod._romdev_getreg === "function");
1045
+ }
1046
+
1047
+ /** Write one CPU register by romdev reg-id. */
1048
+ setReg(regId, value) {
1049
+ const mod = this._needMod();
1050
+ if (typeof mod._romdev_setreg !== "function") {
1051
+ throw new Error("register write not supported by this core (rebuild with romdev_setreg).");
1052
+ }
1053
+ mod._romdev_setreg(regId | 0, value >>> 0);
1054
+ }
1055
+
1056
+ /** Read one CPU register by romdev reg-id. */
1057
+ getReg(regId) {
1058
+ const mod = this._needMod();
1059
+ if (typeof mod._romdev_getreg !== "function") {
1060
+ throw new Error("register read not supported by this core (rebuild with romdev_getreg).");
1061
+ }
1062
+ return mod._romdev_getreg(regId | 0) >>> 0;
1063
+ }
1064
+
1065
+ /**
1066
+ * Call a subroutine in the live core and run until it returns: set the given
1067
+ * registers (by romdev reg-id), push a SENTINEL return address on the stack,
1068
+ * set PC, then run with a PC breakpoint armed on the sentinel until the routine
1069
+ * RTSes back to it. Sandboxed by default — snapshots full core state first and
1070
+ * restores it after, so the live game is untouched (the dst buffer the routine
1071
+ * wrote is captured into a savestate-independent copy? no — it lives in core
1072
+ * RAM; the caller reads it via readMemory BEFORE restore by passing a `capture`
1073
+ * callback). Returns { returned, framesRun, finalRegs } (+ whatever `capture`
1074
+ * returns). The general primitive behind decompressWith / "drive the ROM's own
1075
+ * codec." regIds map per the convention above. sentinelPC must be an address
1076
+ * that won't otherwise be executed (default: 0 — the ROM's reset/0 vector area,
1077
+ * unlikely mid-run; override if it collides).
1078
+ *
1079
+ * @param {object} a
1080
+ * @param {number} a.pc entry PC of the subroutine
1081
+ * @param {Record<number,number>} a.regs reg-id → value to set before the call
1082
+ * @param {number} [a.spReg=18] the reg-id of the stack pointer (m68k: 18)
1083
+ * @param {number} [a.pcReg=16] the reg-id of the program counter (m68k: 16)
1084
+ * @param {number} [a.sentinelPC=0] return address pushed on the stack (4 bytes for m68k)
1085
+ * @param {number} [a.sentinelBytes=4] how wide the return address is on the stack
1086
+ * @param {number} [a.maxFrames=600] cap so a runaway can't hang
1087
+ * @param {boolean} [a.sandbox=true] snapshot+restore around the call
1088
+ * @param {(host:LibretroHost)=>any} [a.capture] read result from core RAM BEFORE restore
1089
+ */
1090
+ callSubroutine(a) {
1091
+ const mod = this._needMod();
1092
+ if (!this.status.loaded) throw new Error("no media loaded");
1093
+ if (!this.setRegSupported()) {
1094
+ throw new Error("cpu({op:'call'}) not supported by this core (rebuild with romdev_setreg/romdev_getreg).");
1095
+ }
1096
+ if (!this.pcBreakSupported()) {
1097
+ throw new Error("cpu({op:'call'}) needs the PC breakpoint (romdev_pcbreak) too.");
1098
+ }
1099
+ const prof = this._cpuCallProfile();
1100
+ const {
1101
+ pc, regs = {}, spReg = prof.spReg, pcReg = prof.pcReg, sentinelPC = prof.defaultSentinel,
1102
+ sentinelBytes = prof.retBytes, maxFrames = 600, sandbox = true, capture,
1103
+ // presetMemory: [{addr, bytes}] CPU-space writes applied before the call
1104
+ // (codecs that read a global from RAM — a dest stride, a mode flag, etc).
1105
+ presetMemory = [],
1106
+ // stopAtPC: an additional PC to halt on (returns partial output even if the
1107
+ // routine never reaches the sentinel). Use for "run into the codec, stop at
1108
+ // a known mid-point, see what it produced so far."
1109
+ stopAtPC,
1110
+ // maxInstructions: the instruction watchdog budget — the real cap that
1111
+ // catches a runaway, whether it's a tight infinite loop OR a wrong-setup
1112
+ // entry (e.g. a WRAPPER PC with a bad source) that falls back into the
1113
+ // game's own main loop and free-runs forever instead of returning.
1114
+ //
1115
+ // The budget MUST trip BEFORE maxFrames is exhausted on such a free-run —
1116
+ // otherwise the run silently hits maxFrames and the agent can't tell
1117
+ // "wrong entry" from "legitimately long." Two failure modes the default
1118
+ // has to dodge, and why it's PER-CPU rather than a flat constant:
1119
+ // • too LOW relative to a real codec → cuts off a legit decompress.
1120
+ // • too HIGH relative to maxFrames-worth of execution → never trips
1121
+ // before the frame cap. A flat 4M does this on the ~1MHz 8-bit CPUs
1122
+ // (6507/6510 run only ~3-3.8M instructions in 600 frames), so the
1123
+ // watchdog could never fire there.
1124
+ // Derive it from the CPU's instrPerFrame (set in _cpuCallProfile): 80% of
1125
+ // maxFrames-worth, capped at 4M for the fast cores (GBA/Genesis). Any real
1126
+ // decompressor finishes in <~1M instructions on every one of these CPUs,
1127
+ // so even the slow-CPU floor (~2.9M for c64/atari2600) keeps 2-3x headroom
1128
+ // while guaranteeing the watchdog beats the frame cap. Callers who KNOW a
1129
+ // routine is genuinely huge pass an explicit maxInstructions to override.
1130
+ maxInstructions = Math.max(
1131
+ 200_000,
1132
+ Math.min(4_000_000, Math.floor(maxFrames * (prof.instrPerFrame ?? 50000) * 0.8)),
1133
+ ),
1134
+ } = a;
1135
+
1136
+ const snapshot = sandbox ? this.serializeState() : null;
1137
+ let captured, returned = false, framesRun = 0, watchdogTripped = false, stoppedAtPC = false;
1138
+ try {
1139
+ // Apply pre-call memory writes (CPU-space).
1140
+ for (const m of presetMemory) {
1141
+ const bytes = m.bytes instanceof Uint8Array ? m.bytes
1142
+ : new Uint8Array((m.hex || "").match(/../g)?.map((h) => parseInt(h, 16)) || []);
1143
+ if (bytes.length) this.writeMemoryCpuAddr(m.addr >>> 0, bytes);
1144
+ }
1145
+ // Set caller-supplied registers.
1146
+ for (const [id, val] of Object.entries(regs)) this.setReg(Number(id), val);
1147
+ // Push the sentinel return address per the CPU's stack discipline, then set
1148
+ // SP + PC. The return address width + push direction + byte order all come
1149
+ // from the per-CPU profile (m68k pushes 4 BE bytes, predecrement; the 6502
1150
+ // pushes 2 bytes high-then-low at $0100+SP and SP grows DOWN; SM83 pushes 2
1151
+ // LE bytes predecrement; 65816 RTL pops 3 bytes).
1152
+ let sp = this.getReg(spReg) >>> 0;
1153
+ // The 6502/65816 RTS/RTL return to (popped address + 1) — they push PC-1. So
1154
+ // to land the run on `sentinelPC`, push sentinelPC + retAdjust (-1 there, 0
1155
+ // for m68k RTS / SM83 RET / Z80 RET which return to the exact pushed addr).
1156
+ const pushed = (sentinelPC + (prof.retAdjust ?? 0)) >>> 0;
1157
+ const buf = new Uint8Array(sentinelBytes);
1158
+ if (prof.retBigEndian) {
1159
+ for (let i = 0; i < sentinelBytes; i++) buf[i] = (pushed >>> (8 * (sentinelBytes - 1 - i))) & 0xFF;
1160
+ } else {
1161
+ for (let i = 0; i < sentinelBytes; i++) buf[i] = (pushed >>> (8 * i)) & 0xFF;
1162
+ }
1163
+ if (prof.stackPage !== undefined) {
1164
+ // 6502/65816-style page stack: bytes go at $page + SP, SP decremented after
1165
+ // each byte (push order = the bytes as written, SP ends below them).
1166
+ const base = prof.stackPage;
1167
+ let s = sp & 0xFF;
1168
+ for (let i = 0; i < sentinelBytes; i++) {
1169
+ this.writeMemoryCpuAddr(base + s, buf.subarray(i, i + 1));
1170
+ s = (s - 1) & 0xFF;
1171
+ }
1172
+ this.setReg(spReg, s);
1173
+ } else {
1174
+ // Predecrement stack (m68k/SM83): SP -= width, write the block, set SP.
1175
+ sp = (sp - sentinelBytes) >>> 0;
1176
+ this.writeMemoryCpuAddr(sp, buf);
1177
+ this.setReg(spReg, sp);
1178
+ }
1179
+ this.setReg(pcReg, pc >>> 0);
1180
+
1181
+ // Arm the instruction watchdog so a runaway codec force-stops mid-frame
1182
+ // instead of hanging the WASM (the core check between frames can't catch a
1183
+ // tight infinite loop). The breakpoint stops on the sentinel return; if
1184
+ // `stopAtPC` is given we break THERE instead (run-to-a-mid-point + return
1185
+ // partial). The watchdog catches everything else.
1186
+ this.setWatchdog(maxInstructions);
1187
+ const target = (stopAtPC !== undefined ? stopAtPC : sentinelPC) >>> 0;
1188
+ this.setPCBreak(target, true, false);
1189
+ let finalState = null;
1190
+ try {
1191
+ framesRun = this._runFramesExclusive(() => {
1192
+ const st = this.getPCBreak(false);
1193
+ if (st.hit) {
1194
+ finalState = st;
1195
+ if (st.watchdog) watchdogTripped = true;
1196
+ else if (stopAtPC !== undefined) stoppedAtPC = true;
1197
+ else returned = true;
1198
+ return true;
1199
+ }
1200
+ return false;
1201
+ }, maxFrames);
1202
+ } finally {
1203
+ this.setPCBreak(0, false, false);
1204
+ this.setWatchdog(0);
1205
+ if (!finalState) finalState = this.getPCBreak(true); else this.getPCBreak(true);
1206
+ }
1207
+ // Capture the result from core RAM BEFORE any restore — always, so a partial
1208
+ // (watchdog/stopAtPC) result still hands back whatever the codec wrote.
1209
+ if (capture) captured = capture(this);
1210
+ // Read the final register file + PC for progress reporting (entry-exact when
1211
+ // the breakpoint fired before-dispatch, which is the m68k default).
1212
+ let finalPC = finalState && finalState.lastPC != null ? finalState.lastPC : null;
1213
+ let finalRegs = null;
1214
+ try { finalRegs = this._readCallRegs(); } catch { /* best effort */ }
1215
+ this._lastCallResult = { finalPC, finalRegs };
1216
+ } finally {
1217
+ if (snapshot) this.unserializeState(snapshot);
1218
+ }
1219
+ const fin = this._lastCallResult || {};
1220
+ return {
1221
+ returned, framesRun,
1222
+ ...(watchdogTripped ? { watchdog: true, reason: "watchdog: hit the instruction budget (likely a runaway loop — wrong A0/regs, a needed preset, or legitimately huge; raise maxInstructions or check the entry setup)" } : {}),
1223
+ ...(stoppedAtPC ? { stoppedAtPC: "$" + (stopAtPC >>> 0).toString(16).toUpperCase() } : {}),
1224
+ ...(fin.finalPC != null ? { finalPC: "$" + fin.finalPC.toString(16).toUpperCase(), finalPCRaw: fin.finalPC } : {}),
1225
+ ...(fin.finalRegs ? { finalRegs: fin.finalRegs } : {}),
1226
+ ...(captured !== undefined ? { captured } : {}),
1227
+ };
1228
+ }
1229
+
1230
+ /** Read the small set of registers most useful for callSubroutine progress
1231
+ * reporting (m68k A0/A1/D0/D1 + PC/SP), by reg-id, best-effort. */
1232
+ _readCallRegs() {
1233
+ const out = {};
1234
+ const ids = { D0: 0, D1: 1, A0: 8, A1: 9, PC: 16, SP: 18 };
1235
+ for (const [name, id] of Object.entries(ids)) {
1236
+ try { out[name] = "0x" + (this.getReg(id) >>> 0).toString(16).toUpperCase(); } catch { /* skip */ }
1237
+ }
1238
+ return out;
1239
+ }
1240
+
1241
+ /**
1242
+ * Per-CPU calling profile for callSubroutine: how the stack/return work for the
1243
+ * loaded platform's CPU. reg-ids match each core's romdev_setreg convention.
1244
+ * - retBytes: width of the return address pushed (RTS/RTL pop width)
1245
+ * - retBigEndian: byte order of the pushed return address
1246
+ * - stackPage: if set, a page-relative stack ($0100 for 6502) — SP is an 8-bit
1247
+ * index into that page (push writes at page+SP, decrement); if undefined the
1248
+ * stack is a full predecrement stack (m68k/SM83) addressed by SP directly.
1249
+ * - ramMask / ramRegion: CPU-addr → memory region mapping for the stack writes.
1250
+ */
1251
+ _cpuCallProfile() {
1252
+ const p = this.status.platform;
1253
+ // `instrPerFrame`: a CONSERVATIVE estimate of how many instructions one frame
1254
+ // of this CPU executes (clock ÷ avg-cycles-per-instr ÷ ~60fps). Used to size
1255
+ // the callSubroutine watchdog budget so it trips BEFORE the per-frame cap even
1256
+ // on the slow ~1MHz 8-bit CPUs (a fixed 4M never trips inside 600 frames on a
1257
+ // 6507/6510 — only ~3-3.8M instructions run in 600 frames there). Real codecs
1258
+ // finish in <~1M instructions on any of these, so 0.8×maxFrames×instrPerFrame
1259
+ // still clears a legit decompress with margin. See the watchdog budget below.
1260
+ switch (p) {
1261
+ case "genesis": case "megadrive": case "md":
1262
+ // m68k: SP=18, PC=16; RTS pops a 4-byte big-endian return; work RAM
1263
+ // $FF0000-$FFFFFF → system_ram (& 0xFFFF). Sentinel 0 (vector area).
1264
+ // 7.67MHz / ~10 cyc/instr / 60 ≈ 12.8k; use 50k (tight loops are denser).
1265
+ return { spReg: 18, pcReg: 16, retBytes: 4, retBigEndian: true, defaultSentinel: 0, ramMask: 0xFFFF, instrPerFrame: 50000 };
1266
+ case "nes": case "atari2600": case "atari7800": case "lynx": case "c64": case "pce":
1267
+ // 6502/65C02/HuC6280/6510: A=0,X=1,Y=2,P=3,SP=4,PC=16. RTS pops 2 bytes
1268
+ // (PCL,PCH) from the $0100 page. system_ram is the low RAM; the stack page
1269
+ // $0100-$01FF maps to system_ram offset 0x100-0x1FF on most of these.
1270
+ // The slowest cores live here (atari2600 6507 ~1.19MHz, c64 6510 ~1MHz):
1271
+ // ~5-6k instr/frame → 600 frames ≈ 3-3.8M, BELOW a flat 4M. 6k keeps the
1272
+ // per-CPU budget under the frame cap so the watchdog actually trips.
1273
+ return { spReg: 4, pcReg: 16, retBytes: 2, retBigEndian: true, defaultSentinel: 0, stackPage: 0x100, ramMask: 0xFFFF, retAdjust: -1, instrPerFrame: 6000 };
1274
+ case "gb": case "gbc":
1275
+ // SM83: PC=16, SP=18. CALL/RET push 2 little-endian bytes, predecrement
1276
+ // SP. Stack lives in WRAM ($C000-$DFFF, also high RAM); SP & 0x1FFF →
1277
+ // system_ram (the 8KB WRAM window). Sentinel 0 (rst vector area).
1278
+ // 4.19MHz / ~10 cyc / 60 ≈ 7k.
1279
+ return { spReg: 18, pcReg: 16, retBytes: 2, retBigEndian: false, defaultSentinel: 0, ramMask: 0x1FFF, instrPerFrame: 8000 };
1280
+ case "snes":
1281
+ // 65816: SP=4, PC=16. A long subroutine (JSL/RTL) pushes a 3-byte return
1282
+ // (the 65816 stack is in bank 0, page-relative is the 8-bit/16-bit S). We
1283
+ // push 3 bytes at the 16-bit S in bank 0 (predecrement); WRAM low mirror.
1284
+ // ~3.58MHz / ~6 cyc / 60 ≈ 10k.
1285
+ return { spReg: 4, pcReg: 16, retBytes: 3, retBigEndian: false, defaultSentinel: 0, ramMask: 0x1FFF, retAdjust: -1, instrPerFrame: 12000 };
1286
+ case "sms": case "gg": case "msx":
1287
+ // Z80: PC=16, SP=18. CALL/RET push 2 LE bytes predecrement. Work RAM
1288
+ // window varies (SMS $C000-$DFFF → sms low RAM); SP & 0x1FFF.
1289
+ // 3.58MHz / ~7 cyc / 60 ≈ 8.5k (tight JR-loops denser → use 7k floor).
1290
+ // NOTE: on SMS/GG the Z80 is the active CPU and the gpgx watchdog counter
1291
+ // is wired into z80_run as of the matching core patch (was m68k-only).
1292
+ return { spReg: 18, pcReg: 16, retBytes: 2, retBigEndian: false, defaultSentinel: 0, ramMask: 0x1FFF, instrPerFrame: 7000 };
1293
+ case "gba":
1294
+ // ARM7TDMI: SP=r13 (reg-id 13), PC=r15 (reg-id 15). No implicit return-on-
1295
+ // stack (BL uses LR). callSubroutine on ARM would set LR=sentinel instead
1296
+ // of pushing — handled by the ARM branch (lrReg). EWRAM mapping.
1297
+ // 16.78MHz / ~2 cyc / 60 ≈ 140k → the fixed 4M cap applies first.
1298
+ return { spReg: 13, pcReg: 15, retBytes: 4, retBigEndian: false, defaultSentinel: 0, ramMask: 0x3FFFF, lrReg: 14, instrPerFrame: 140000 };
1299
+ default:
1300
+ // Unknown — m68k-shaped fallback (Genesis defaults).
1301
+ return { spReg: 18, pcReg: 16, retBytes: 4, retBigEndian: true, defaultSentinel: 0, ramMask: 0xFFFF, instrPerFrame: 50000 };
1302
+ }
1303
+ }
1304
+
1305
+ /** Write bytes to a CPU address, resolving the platform's CPU-space→region map
1306
+ * (used by callSubroutine to seed the stack). Uses the per-CPU profile's mask. */
1307
+ writeMemoryCpuAddr(cpuAddr, bytes) {
1308
+ const prof = this._cpuCallProfile();
1309
+ const off = (cpuAddr & (prof.ramMask ?? 0xFFFF)) >>> 0;
1310
+ this.writeMemory("system_ram", off, bytes);
1311
+ }
1312
+
1313
+ // ── Range watch + PC coverage (item 2, discovery) ───────────────────────────
1314
+
1315
+ /** True when this core exposes the range watch + coverage log. */
1316
+ rangeWatchSupported() {
1317
+ const mod = this.mod;
1318
+ return !!(mod && typeof mod._romdev_range_set === "function" && typeof mod._romdev_cov_set === "function");
1319
+ }
1320
+
1321
+ /**
1322
+ * Run `frames` frames logging EVERY read/write touching [lo,hi] (mode 1=read,
1323
+ * 2=write, 3=both) — the list-all-hits discovery tool. Returns
1324
+ * { events:[{pc,address,value}], total, stored, truncated }.
1325
+ */
1326
+ watchRange(lo, hi, mode, frames) {
1327
+ const mod = this._needMod();
1328
+ if (!this.status.loaded) throw new Error("no media loaded");
1329
+ if (!this.rangeWatchSupported()) throw new Error("range watch not supported by this core.");
1330
+ const m = mode === "read" ? 1 : mode === "write" ? 2 : 3;
1331
+ mod._romdev_range_set(lo >>> 0, hi >>> 0, m, 1);
1332
+ try {
1333
+ this._runFramesExclusive(() => false, frames);
1334
+ } finally {
1335
+ // leave armed=0 after draining
1336
+ }
1337
+ // Drain: out2=[total,stored]; out=packed triples.
1338
+ const CAP = 4096;
1339
+ const outPtr = mod._malloc(CAP * 3 * 4);
1340
+ const out2Ptr = mod._malloc(8);
1341
+ try {
1342
+ const n = mod._romdev_range_get(outPtr, CAP, out2Ptr);
1343
+ const out2 = new Uint32Array(mod.HEAPU8.buffer, out2Ptr, 2);
1344
+ const total = out2[0], stored = out2[1];
1345
+ const u = new Uint32Array(mod.HEAPU8.buffer, outPtr, n * 3);
1346
+ const events = [];
1347
+ for (let i = 0; i < n; i++) events.push({ pc: u[i * 3], address: u[i * 3 + 1], value: u[i * 3 + 2] & 0xFF });
1348
+ mod._romdev_range_set(0, 0, 0, 0); // disarm
1349
+ return { events, total, stored, truncated: total > stored };
1350
+ } finally {
1351
+ mod._free(outPtr); mod._free(out2Ptr);
1352
+ }
1353
+ }
1354
+
1355
+ /**
1356
+ * Run `frames` frames recording every DISTINCT PC executed within [lo,hi] — the
1357
+ * coverage trace ("what code runs here?"). Returns { pcs:[...], distinct, total, truncated }.
1358
+ */
1359
+ logPCRange(lo, hi, frames) {
1360
+ const mod = this._needMod();
1361
+ if (!this.status.loaded) throw new Error("no media loaded");
1362
+ if (!this.rangeWatchSupported()) throw new Error("coverage trace not supported by this core.");
1363
+ mod._romdev_cov_set(lo >>> 0, hi >>> 0, 1);
1364
+ this._runFramesExclusive(() => false, frames);
1365
+ const CAP = 8192;
1366
+ const outPtr = mod._malloc(CAP * 4);
1367
+ const out2Ptr = mod._malloc(8);
1368
+ try {
1369
+ const n = mod._romdev_cov_get(outPtr, CAP, out2Ptr);
1370
+ const out2 = new Uint32Array(mod.HEAPU8.buffer, out2Ptr, 2);
1371
+ const distinct = out2[0], total = out2[1];
1372
+ const u = new Uint32Array(mod.HEAPU8.buffer, outPtr, n);
1373
+ const pcs = Array.from(u.slice(0, n));
1374
+ mod._romdev_cov_set(0, 0, 0); // disarm
1375
+ return { pcs, distinct, total, truncated: distinct > n };
1376
+ } finally {
1377
+ mod._free(outPtr); mod._free(out2Ptr);
1378
+ }
1379
+ }
1380
+
1381
+ // ── Targeted VDP-DMA watch (item 3, Genesis only) ───────────────────────────
1382
+
1383
+ /** True when VDP-DMA logging applies to the LOADED platform. The gpgx core
1384
+ * exports the DMA hooks, but only GENESIS has VDP DMA — SMS/GG (also gpgx) use
1385
+ * a different VDP with no DMA, so the hook never fires there. Gate on the
1386
+ * loaded platform, not just the export's presence. */
1387
+ dmaWatchSupported() {
1388
+ const mod = this.mod;
1389
+ const p = this.status.platform;
1390
+ const isGenesis = p === "genesis" || p === "megadrive" || p === "md";
1391
+ return isGenesis && !!(mod && typeof mod._romdev_dmawatch_set === "function" && typeof mod._romdev_dmawatch_get === "function");
1392
+ }
1393
+
1394
+ /**
1395
+ * Run `frames` frames logging every mem→VDP DMA. Returns
1396
+ * { dmas:[{vramDest, source, lengthWords, code}], total, stored, truncated }.
1397
+ * The caller filters by vramDest. Genesis-only.
1398
+ */
1399
+ watchDma(frames) {
1400
+ const mod = this._needMod();
1401
+ if (!this.status.loaded) throw new Error("no media loaded");
1402
+ if (!this.dmaWatchSupported()) throw new Error("VDP-DMA watch not supported by this core (Genesis only).");
1403
+ mod._romdev_dmawatch_set(1);
1404
+ this._runFramesExclusive(() => false, frames);
1405
+ const CAP = 1024;
1406
+ const outPtr = mod._malloc(CAP * 4 * 4);
1407
+ const out2Ptr = mod._malloc(8);
1408
+ try {
1409
+ const n = mod._romdev_dmawatch_get(outPtr, CAP, out2Ptr);
1410
+ const out2 = new Uint32Array(mod.HEAPU8.buffer, out2Ptr, 2);
1411
+ const total = out2[0], stored = out2[1];
1412
+ const u = new Uint32Array(mod.HEAPU8.buffer, outPtr, n * 4);
1413
+ const dmas = [];
1414
+ for (let i = 0; i < n; i++) dmas.push({ vramDest: u[i * 4], source: u[i * 4 + 1], lengthWords: u[i * 4 + 2], code: u[i * 4 + 3] });
1415
+ mod._romdev_dmawatch_set(0); // disarm
1416
+ return { dmas, total, stored, truncated: total > stored };
1417
+ } finally {
1418
+ mod._free(outPtr); mod._free(out2Ptr);
1419
+ }
1420
+ }
1421
+
1422
+ pause() {
1423
+ this.status.paused = true;
1424
+ }
1425
+
1426
+ resume() {
1427
+ this.status.paused = false;
1428
+ }
1429
+
1430
+ getStatus() {
1431
+ return { ...this.status };
1432
+ }
1433
+
1434
+ _needMod() {
1435
+ if (!this.mod) throw new Error("no core loaded — call loadCore first");
1436
+ return this.mod;
1437
+ }
1438
+
1439
+ /**
1440
+ * Build a friendly error message when a memory region is empty (the
1441
+ * core didn't expose it). Includes per-platform suggestions when we
1442
+ * know a sibling region likely has what the caller wanted.
1443
+ *
1444
+ * Round 26 footgun: an agent debugging GB read `video_ram` (the
1445
+ * generic libretro id 3), got "empty", and started a multi-iteration
1446
+ * "my VRAM writes are being optimized away" spiral — when in fact
1447
+ * gambatte exposes VRAM as `gb_vram`, not the generic id.
1448
+ */
1449
+ _emptyRegionError(region) {
1450
+ const plat = this.status && this.status.platform;
1451
+ const suggestions = {
1452
+ // platform → { generic-region-name: "use this instead" }
1453
+ gb: { video_ram: "gb_vram", save_ram: "save_ram (likely empty on cartless ROMs — try gb_oam / gb_io / gb_hram for non-VRAM state)" },
1454
+ gbc: { video_ram: "gb_vram", save_ram: "save_ram (try gb_oam / gb_io / gb_hram for non-VRAM state)" },
1455
+ sms: { video_ram: "sms_vram (or sms_cram for palette, sms_vdp_regs for VDP regs)" },
1456
+ gg: { video_ram: "gg_vram (or gg_cram for the 64-byte 12-bit palette, sms_vdp_regs for VDP regs)" },
1457
+ snes: { video_ram: "snes_oam (sprite OAM), snes_cgram (palette), snes_aram (SPC700), or snes_fillram (PPU/DMA reg shadow). The libretro generic 'video_ram' id isn't wired in snes9x." },
1458
+ genesis: { video_ram: "genesis_cram / genesis_vsram / genesis_vdp_regs — the generic 'video_ram' id isn't wired in gpgx for Genesis. VRAM itself isn't exposed; use inspectPatternTiles / inspectBackgroundMap / getRenderingContext instead." },
1459
+ c64: { video_ram: "c64_color_ram (1 KB) / c64_vic_regs / c64_sid_regs / c64_cia1_regs / c64_cia2_regs. The C64 has no separate VRAM — the VIC-II reads from main system_ram." },
1460
+ };
1461
+ const hint = suggestions[plat] && suggestions[plat][region];
1462
+ if (hint) {
1463
+ return `memory region '${region}' is empty on platform '${plat}'. Try: ${hint}. ` +
1464
+ `Or use inspectPatternTiles / inspectBackgroundMap / inspectSprites / inspectPalette which abstract over per-platform memory layout.`;
1465
+ }
1466
+ return `memory region '${region}' is empty (core didn't expose it on platform '${plat || "?"}'). ` +
1467
+ `If you need raw bytes, see the platform-specific regions in src/host/types.js or the inspect* tools which know the right region per platform.`;
1468
+ }
1469
+ }