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.
- package/AGENTS.md +1110 -0
- package/CHANGELOG.md +525 -0
- package/LICENSE +45 -0
- package/NOTICE +102 -0
- package/README.md +84 -0
- package/examples/README.md +36 -0
- package/examples/art-first-workflow/README.md +209 -0
- package/examples/atari2600/main.asm +143 -0
- package/examples/atari2600/templates/default.asm +183 -0
- package/examples/atari2600/templates/mini_invaders.asm +381 -0
- package/examples/atari2600/templates/music_demo.asm +322 -0
- package/examples/atari2600/templates/paddle.asm +345 -0
- package/examples/atari2600/templates/single_screen.asm +242 -0
- package/examples/atari7800/main.c +88 -0
- package/examples/atari7800/templates/default.c +183 -0
- package/examples/atari7800/templates/hello_sprite.c +141 -0
- package/examples/atari7800/templates/music_demo.c +123 -0
- package/examples/atari7800/templates/platformer.c +159 -0
- package/examples/atari7800/templates/puzzle.c +164 -0
- package/examples/atari7800/templates/racing.c +139 -0
- package/examples/atari7800/templates/shmup.c +148 -0
- package/examples/atari7800/templates/sports.c +207 -0
- package/examples/c64/main.c +63 -0
- package/examples/c64/templates/hello_sprite.c +117 -0
- package/examples/c64/templates/music_demo.c +131 -0
- package/examples/c64/templates/platformer.c +194 -0
- package/examples/c64/templates/puzzle.c +178 -0
- package/examples/c64/templates/racing.c +140 -0
- package/examples/c64/templates/shmup.c +201 -0
- package/examples/c64/templates/sports.c +109 -0
- package/examples/c64/templates/tile_engine.c +174 -0
- package/examples/gb/main.asm +106 -0
- package/examples/gb/main.c +49 -0
- package/examples/gb/templates/default.c +58 -0
- package/examples/gb/templates/hello_sprite.c +130 -0
- package/examples/gb/templates/music_demo.c +52 -0
- package/examples/gb/templates/platformer.c +178 -0
- package/examples/gb/templates/puzzle.c +217 -0
- package/examples/gb/templates/racing.c +158 -0
- package/examples/gb/templates/shmup.c +172 -0
- package/examples/gb/templates/sports.c +136 -0
- package/examples/gb/templates/tile_engine.c +280 -0
- package/examples/gba/templates/gba_hello.c +64 -0
- package/examples/gba/templates/maxmod_demo.c +105 -0
- package/examples/gba/templates/platformer.c +215 -0
- package/examples/gba/templates/puzzle.c +237 -0
- package/examples/gba/templates/racing.c +175 -0
- package/examples/gba/templates/shmup.c +197 -0
- package/examples/gba/templates/sports.c +177 -0
- package/examples/gba/templates/tonc_hello.c +72 -0
- package/examples/gba/templates/tonc_hello_sprite.c +109 -0
- package/examples/gbc/main.asm +123 -0
- package/examples/gbc/templates/default.c +61 -0
- package/examples/gbc/templates/hello_sprite.c +140 -0
- package/examples/gbc/templates/music_demo.c +63 -0
- package/examples/gbc/templates/platformer.c +181 -0
- package/examples/gbc/templates/puzzle.c +217 -0
- package/examples/gbc/templates/racing.c +164 -0
- package/examples/gbc/templates/shmup.c +188 -0
- package/examples/gbc/templates/sports.c +142 -0
- package/examples/gbc/templates/tile_engine.c +280 -0
- package/examples/genesis/main.s +161 -0
- package/examples/genesis/templates/hello_sprite.c +75 -0
- package/examples/genesis/templates/platformer.c +166 -0
- package/examples/genesis/templates/puzzle.c +240 -0
- package/examples/genesis/templates/racing.c +170 -0
- package/examples/genesis/templates/sgdk_hello.c +41 -0
- package/examples/genesis/templates/shmup.c +188 -0
- package/examples/genesis/templates/shmup_2p.c +244 -0
- package/examples/genesis/templates/sports.c +172 -0
- package/examples/genesis/templates/tile_engine.c +135 -0
- package/examples/genesis/templates/xgm2_demo.c +53 -0
- package/examples/genesis/templates/xgm2_demo_data.s +27 -0
- package/examples/gg/main.c +10 -0
- package/examples/gg/templates/default.c +156 -0
- package/examples/gg/templates/hello_sprite.c +90 -0
- package/examples/gg/templates/music_demo.c +156 -0
- package/examples/gg/templates/platformer.c +220 -0
- package/examples/gg/templates/puzzle.c +204 -0
- package/examples/gg/templates/racing.c +161 -0
- package/examples/gg/templates/shmup.c +188 -0
- package/examples/gg/templates/sports.c +137 -0
- package/examples/gg/templates/tile_engine.c +137 -0
- package/examples/lynx/main.c +4 -0
- package/examples/lynx/templates/default.c +41 -0
- package/examples/lynx/templates/hello_sprite.c +39 -0
- package/examples/lynx/templates/music_demo.c +37 -0
- package/examples/lynx/templates/platformer.c +72 -0
- package/examples/lynx/templates/puzzle.c +142 -0
- package/examples/lynx/templates/racing.c +94 -0
- package/examples/lynx/templates/shmup.c +132 -0
- package/examples/lynx/templates/sports.c +59 -0
- package/examples/msx/catch_game/README.md +75 -0
- package/examples/msx/catch_game/_verify.mjs +93 -0
- package/examples/msx/catch_game/main.c +249 -0
- package/examples/msx/catch_game/shot_after_left.png +0 -0
- package/examples/msx/catch_game/shot_after_right.png +0 -0
- package/examples/msx/catch_game/shot_before.png +0 -0
- package/examples/msx/catch_game/shot_scored.png +0 -0
- package/examples/msx/music_sfx/README.md +38 -0
- package/examples/msx/music_sfx/main.c +164 -0
- package/examples/msx/sprite_move/README.md +44 -0
- package/examples/msx/sprite_move/main.c +100 -0
- package/examples/nes/main.c +143 -0
- package/examples/nes/space-shooter/README.md +69 -0
- package/examples/nes/space-shooter/main.c +441 -0
- package/examples/nes/space-shooter/nes_runtime.c +347 -0
- package/examples/nes/space-shooter/nes_runtime.h +141 -0
- package/examples/nes/templates/default.c +41 -0
- package/examples/nes/templates/hello_sprite.c +104 -0
- package/examples/nes/templates/music_demo.c +80 -0
- package/examples/nes/templates/platformer.c +171 -0
- package/examples/nes/templates/puzzle.c +232 -0
- package/examples/nes/templates/racing.c +203 -0
- package/examples/nes/templates/shmup.c +228 -0
- package/examples/nes/templates/sports.c +205 -0
- package/examples/nes/templates/tile_engine.c +224 -0
- package/examples/pce/catch_game/README.md +8 -0
- package/examples/pce/catch_game/_verify.mjs +75 -0
- package/examples/pce/catch_game/main.c +327 -0
- package/examples/pce/catch_game/shot_after.png +0 -0
- package/examples/pce/catch_game/shot_before.png +0 -0
- package/examples/pce/main.c +37 -0
- package/examples/pce/music_sfx/README.md +8 -0
- package/examples/pce/music_sfx/main.c +154 -0
- package/examples/pce/sprite_move/README.md +19 -0
- package/examples/pce/sprite_move/main.c +155 -0
- package/examples/porting-across-platforms/README.md +59 -0
- package/examples/sms/main.c +129 -0
- package/examples/sms/templates/default.c +110 -0
- package/examples/sms/templates/hello_sprite.c +90 -0
- package/examples/sms/templates/music_demo.c +151 -0
- package/examples/sms/templates/platformer.c +215 -0
- package/examples/sms/templates/puzzle.c +204 -0
- package/examples/sms/templates/racing.c +161 -0
- package/examples/sms/templates/shmup.c +167 -0
- package/examples/sms/templates/shmup_2p.c +219 -0
- package/examples/sms/templates/sports.c +147 -0
- package/examples/sms/templates/tile_engine.c +137 -0
- package/examples/snes/main.asm +70 -0
- package/examples/snes/templates/c-hello-data.asm +28 -0
- package/examples/snes/templates/c-hello.c +71 -0
- package/examples/snes/templates/default-data.asm +36 -0
- package/examples/snes/templates/default.c +74 -0
- package/examples/snes/templates/hello_sprite-data.asm +45 -0
- package/examples/snes/templates/hello_sprite.c +76 -0
- package/examples/snes/templates/music_demo-data.asm +20 -0
- package/examples/snes/templates/music_demo.c +83 -0
- package/examples/snes/templates/platformer-data.asm +27 -0
- package/examples/snes/templates/platformer.c +142 -0
- package/examples/snes/templates/puzzle-data.asm +14 -0
- package/examples/snes/templates/puzzle.c +199 -0
- package/examples/snes/templates/racing-data.asm +33 -0
- package/examples/snes/templates/racing.c +146 -0
- package/examples/snes/templates/shmup-data.asm +61 -0
- package/examples/snes/templates/shmup.c +199 -0
- package/examples/snes/templates/sports-data.asm +28 -0
- package/examples/snes/templates/sports.c +144 -0
- package/package.json +97 -0
- package/src/cheats/gamegenie.js +506 -0
- package/src/cheats/lookup.js +262 -0
- package/src/cheats/parse-cht.js +92 -0
- package/src/cli/smoke.js +283 -0
- package/src/cores/registry.js +99 -0
- package/src/cores/wasm/bluemsx_libretro.js +2 -0
- package/src/cores/wasm/bluemsx_libretro.wasm +0 -0
- package/src/cores/wasm/fceumm_libretro.js +2 -0
- package/src/cores/wasm/fceumm_libretro.wasm +0 -0
- package/src/cores/wasm/gambatte_libretro.js +2 -0
- package/src/cores/wasm/gambatte_libretro.wasm +0 -0
- package/src/cores/wasm/geargrafx_libretro.js +2 -0
- package/src/cores/wasm/geargrafx_libretro.wasm +0 -0
- package/src/cores/wasm/genesis_plus_gx_libretro.js +2 -0
- package/src/cores/wasm/genesis_plus_gx_libretro.wasm +0 -0
- package/src/cores/wasm/handy_libretro.js +2 -0
- package/src/cores/wasm/handy_libretro.wasm +0 -0
- package/src/cores/wasm/mgba_libretro.js +2 -0
- package/src/cores/wasm/mgba_libretro.wasm +0 -0
- package/src/cores/wasm/prosystem_libretro.js +2 -0
- package/src/cores/wasm/prosystem_libretro.wasm +0 -0
- package/src/cores/wasm/snes9x_libretro.js +2 -0
- package/src/cores/wasm/snes9x_libretro.wasm +0 -0
- package/src/cores/wasm/stella2014_libretro.js +2 -0
- package/src/cores/wasm/stella2014_libretro.wasm +0 -0
- package/src/cores/wasm/vice_x64_libretro.js +2 -0
- package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
- package/src/host/LibretroHost.js +1469 -0
- package/src/host/c64-sid-state.js +161 -0
- package/src/host/callbacks.js +444 -0
- package/src/host/chafa-render.js +170 -0
- package/src/host/coreLoader.js +57 -0
- package/src/host/cpu-state.js +543 -0
- package/src/host/dsp-state.js +188 -0
- package/src/host/framebuffer.js +115 -0
- package/src/host/gb-apu-state.js +321 -0
- package/src/host/gba-video-state.js +215 -0
- package/src/host/gpgx-state.js +320 -0
- package/src/host/index.js +4 -0
- package/src/host/lynx-mikey-state.js +226 -0
- package/src/host/msx-ay-state.js +78 -0
- package/src/host/nes-apu-state.js +194 -0
- package/src/host/pce-psg-state.js +82 -0
- package/src/host/retroConstants.js +72 -0
- package/src/host/snes9x-state.js +35 -0
- package/src/host/types.js +332 -0
- package/src/http/routes.js +182 -0
- package/src/http/skill-doc.js +176 -0
- package/src/http/swagger.js +84 -0
- package/src/http/tool-registry.js +142 -0
- package/src/install/postinstall.mjs +81 -0
- package/src/mcp/disclosure.js +250 -0
- package/src/mcp/log.js +87 -0
- package/src/mcp/server.js +498 -0
- package/src/mcp/state.js +88 -0
- package/src/mcp/tool-manifest.js +92 -0
- package/src/mcp/tools/address-to-symbol.js +145 -0
- package/src/mcp/tools/art-loaders.js +743 -0
- package/src/mcp/tools/assets.js +87 -0
- package/src/mcp/tools/audio.js +562 -0
- package/src/mcp/tools/cart-parts.js +651 -0
- package/src/mcp/tools/cheats.js +343 -0
- package/src/mcp/tools/classify-region.js +107 -0
- package/src/mcp/tools/diff-cluster.js +32 -0
- package/src/mcp/tools/diff-roms.js +394 -0
- package/src/mcp/tools/disasm.js +1410 -0
- package/src/mcp/tools/find-references.js +375 -0
- package/src/mcp/tools/font-map.js +563 -0
- package/src/mcp/tools/frame.js +293 -0
- package/src/mcp/tools/free-space.js +71 -0
- package/src/mcp/tools/index.js +339 -0
- package/src/mcp/tools/input-layout.js +231 -0
- package/src/mcp/tools/input.js +227 -0
- package/src/mcp/tools/lifecycle.js +132 -0
- package/src/mcp/tools/lospec.js +187 -0
- package/src/mcp/tools/memory.js +472 -0
- package/src/mcp/tools/metasprite-tools.js +256 -0
- package/src/mcp/tools/platform-docs.js +113 -0
- package/src/mcp/tools/platform-tools.js +1300 -0
- package/src/mcp/tools/platforms.js +139 -0
- package/src/mcp/tools/playtest.js +360 -0
- package/src/mcp/tools/preview-tile.js +478 -0
- package/src/mcp/tools/project.js +1939 -0
- package/src/mcp/tools/record.js +180 -0
- package/src/mcp/tools/reinject.js +732 -0
- package/src/mcp/tools/rendering-context.js +838 -0
- package/src/mcp/tools/rom-id.js +308 -0
- package/src/mcp/tools/run-until.js +176 -0
- package/src/mcp/tools/snippets.js +209 -0
- package/src/mcp/tools/splice-chr.js +190 -0
- package/src/mcp/tools/sprite-pipeline.js +626 -0
- package/src/mcp/tools/state.js +198 -0
- package/src/mcp/tools/symbols.js +400 -0
- package/src/mcp/tools/tile-inspect.js +293 -0
- package/src/mcp/tools/toolchain.js +720 -0
- package/src/mcp/tools/trace-vram-source.js +81 -0
- package/src/mcp/tools/watch-memory.js +1036 -0
- package/src/mcp/tools/which-tiles.js +180 -0
- package/src/mcp/util.js +355 -0
- package/src/observer/bus.js +127 -0
- package/src/observer/livestream.html +594 -0
- package/src/observer/server.js +78 -0
- package/src/observer/tool-wrap.js +142 -0
- package/src/platforms/_guides/MUSIC_SOURCING.md +104 -0
- package/src/platforms/_guides/ROMHACKING_PLAYBOOK.md +245 -0
- package/src/platforms/atari2600/MENTAL_MODEL.md +194 -0
- package/src/platforms/atari2600/TROUBLESHOOTING.md +155 -0
- package/src/platforms/atari2600/UPSTREAM_SOURCES.md +49 -0
- package/src/platforms/atari2600/lib/README.md +67 -0
- package/src/platforms/atari2600/lib/cc65-src/crt0.s +49 -0
- package/src/platforms/atari2600/lib/cc65-src/ctype.s +5 -0
- package/src/platforms/atari2600/lib/kernel_skeleton.asm +85 -0
- package/src/platforms/atari2600/lib/player_kernel.asm +87 -0
- package/src/platforms/atari2600/lib/playfield_kernel.asm +63 -0
- package/src/platforms/atari2600/lib/read_joystick.asm +76 -0
- package/src/platforms/atari2600/lib/score_kernel.asm +141 -0
- package/src/platforms/atari2600/lib/vcs_constants.h +97 -0
- package/src/platforms/atari2600/lib/vectors.asm +16 -0
- package/src/platforms/atari2600/tia.js +355 -0
- package/src/platforms/atari7800/MENTAL_MODEL.md +324 -0
- package/src/platforms/atari7800/TROUBLESHOOTING.md +195 -0
- package/src/platforms/atari7800/UPSTREAM_SOURCES.md +43 -0
- package/src/platforms/atari7800/lib/README.md +45 -0
- package/src/platforms/atari7800/lib/c/atari7800_music.c +215 -0
- package/src/platforms/atari7800/lib/c/atari7800_music.h +33 -0
- package/src/platforms/atari7800/lib/c/atari7800_sfx.c +74 -0
- package/src/platforms/atari7800/lib/c/atari7800_sfx.h +45 -0
- package/src/platforms/atari7800/lib/cc65-src/clock.s +69 -0
- package/src/platforms/atari7800/lib/cc65-src/clocks_per_sec.s +34 -0
- package/src/platforms/atari7800/lib/cc65-src/clrscr.s +27 -0
- package/src/platforms/atari7800/lib/cc65-src/conio.s +226 -0
- package/src/platforms/atari7800/lib/cc65-src/conio_font.s +278 -0
- package/src/platforms/atari7800/lib/cc65-src/cputc.s +139 -0
- package/src/platforms/atari7800/lib/cc65-src/crt0.s +71 -0
- package/src/platforms/atari7800/lib/cc65-src/ctype.s +5 -0
- package/src/platforms/atari7800/lib/cc65-src/exehdr.s +46 -0
- package/src/platforms/atari7800/lib/cc65-src/extra/mono.s +28 -0
- package/src/platforms/atari7800/lib/cc65-src/extzp.inc +15 -0
- package/src/platforms/atari7800/lib/cc65-src/extzp.s +15 -0
- package/src/platforms/atari7800/lib/cc65-src/get_tv.s +65 -0
- package/src/platforms/atari7800/lib/cc65-src/irq.s +36 -0
- package/src/platforms/atari7800/lib/cc65-src/joy/atari7800-stdjoy.s +197 -0
- package/src/platforms/atari7800/lib/cc65-src/joy_stat_stddrv.s +14 -0
- package/src/platforms/atari7800/lib/cc65-src/libref.s +8 -0
- package/src/platforms/atari7800/lib/cc65-src/mono_clrscr.s +27 -0
- package/src/platforms/atari7800/lib/cc65-src/mono_conio.s +231 -0
- package/src/platforms/atari7800/lib/cc65-src/mono_cputc.s +102 -0
- package/src/platforms/atari7800/lib/cc65-src/mono_font.s +2065 -0
- package/src/platforms/atari7800/lib/cc65-src/mono_setcursor.s +214 -0
- package/src/platforms/atari7800/lib/cc65-src/setcursor.s +214 -0
- package/src/platforms/atari7800/lib/cc65-src/textcolor.s +53 -0
- package/src/platforms/atari7800/lib/cc65-src/wherex.s +19 -0
- package/src/platforms/atari7800/lib/cc65-src/wherey.s +19 -0
- package/src/platforms/atari7800/lib/display_list.asm +53 -0
- package/src/platforms/atari7800/lib/maria_init.asm +48 -0
- package/src/platforms/atari7800/lib/maria_registers.h +61 -0
- package/src/platforms/atari7800/lib/palette_load.asm +53 -0
- package/src/platforms/atari7800/lib/read_pad.asm +57 -0
- package/src/platforms/atari7800/lib/vblank_wait.asm +16 -0
- package/src/platforms/atari7800/maria.js +220 -0
- package/src/platforms/atari7800/song.js +232 -0
- package/src/platforms/c64/MENTAL_MODEL.md +188 -0
- package/src/platforms/c64/TROUBLESHOOTING.md +130 -0
- package/src/platforms/c64/UPSTREAM_SOURCES.md +35 -0
- package/src/platforms/c64/image-to-tilemap.js +190 -0
- package/src/platforms/c64/lib/README.md +52 -0
- package/src/platforms/c64/lib/basic_stub.s +25 -0
- package/src/platforms/c64/lib/c/c64_music.c +248 -0
- package/src/platforms/c64/lib/c/c64_music.h +36 -0
- package/src/platforms/c64/lib/c/c64_sfx.c +94 -0
- package/src/platforms/c64/lib/c/c64_sfx.h +37 -0
- package/src/platforms/c64/lib/c64_registers.h +108 -0
- package/src/platforms/c64/lib/cc65-src/_scrsize.s +12 -0
- package/src/platforms/c64/lib/cc65-src/acc_c128_speed.s +5 -0
- package/src/platforms/c64/lib/cc65-src/acc_c64dtv_speed.s +64 -0
- package/src/platforms/c64/lib/cc65-src/acc_c65_speed.s +69 -0
- package/src/platforms/c64/lib/cc65-src/acc_chameleon_speed.s +100 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_c128.s +33 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_c64dtv.s +44 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_c65.s +55 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_chameleon.s +39 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_scpu.s +34 -0
- package/src/platforms/c64/lib/cc65-src/acc_detect_turbomaster.s +45 -0
- package/src/platforms/c64/lib/cc65-src/acc_scpu_speed.s +59 -0
- package/src/platforms/c64/lib/cc65-src/acc_turbomaster_speed.s +56 -0
- package/src/platforms/c64/lib/cc65-src/bordercolor.s +17 -0
- package/src/platforms/c64/lib/cc65-src/break.s +108 -0
- package/src/platforms/c64/lib/cc65-src/cgetc.s +62 -0
- package/src/platforms/c64/lib/cc65-src/clrscr.s +11 -0
- package/src/platforms/c64/lib/cc65-src/color.s +24 -0
- package/src/platforms/c64/lib/cc65-src/conio.s +10 -0
- package/src/platforms/c64/lib/cc65-src/cputc.s +105 -0
- package/src/platforms/c64/lib/cc65-src/crt0.s +117 -0
- package/src/platforms/c64/lib/cc65-src/devnum.s +7 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-65816.s +377 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-c256k.s +508 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-dqbb.s +447 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-georam.s +355 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-isepic.s +276 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-kerberos.s +281 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-ram.s +270 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-ramcart.s +297 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-reu.s +286 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-rrr.s +363 -0
- package/src/platforms/c64/lib/cc65-src/emd/c64-vdc.s +405 -0
- package/src/platforms/c64/lib/cc65-src/emd/dtv-himem.s +251 -0
- package/src/platforms/c64/lib/cc65-src/extra/soft80.s +71 -0
- package/src/platforms/c64/lib/cc65-src/extra/soft80mono.s +74 -0
- package/src/platforms/c64/lib/cc65-src/extra/tgimousedata.s +21 -0
- package/src/platforms/c64/lib/cc65-src/get_ostype.s +43 -0
- package/src/platforms/c64/lib/cc65-src/get_tv.s +20 -0
- package/src/platforms/c64/lib/cc65-src/gettime.s +83 -0
- package/src/platforms/c64/lib/cc65-src/irq.s +49 -0
- package/src/platforms/c64/lib/cc65-src/joy/c64-hitjoy.s +218 -0
- package/src/platforms/c64/lib/cc65-src/joy/c64-numpad.s +155 -0
- package/src/platforms/c64/lib/cc65-src/joy/c64-ptvjoy.s +146 -0
- package/src/platforms/c64/lib/cc65-src/joy/c64-stdjoy.s +111 -0
- package/src/platforms/c64/lib/cc65-src/joy_stat_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/joy_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/kbhit.s +23 -0
- package/src/platforms/c64/lib/cc65-src/kbrepeat.s +14 -0
- package/src/platforms/c64/lib/cc65-src/kernal.s +53 -0
- package/src/platforms/c64/lib/cc65-src/kplot.s +22 -0
- package/src/platforms/c64/lib/cc65-src/libref.s +16 -0
- package/src/platforms/c64/lib/cc65-src/mainargs.s +137 -0
- package/src/platforms/c64/lib/cc65-src/mcbdefault.s +146 -0
- package/src/platforms/c64/lib/cc65-src/mcbspritedata.s +4 -0
- package/src/platforms/c64/lib/cc65-src/mou/c64-1351.s +467 -0
- package/src/platforms/c64/lib/cc65-src/mou/c64-inkwell.s +446 -0
- package/src/platforms/c64/lib/cc65-src/mou/c64-joy.s +451 -0
- package/src/platforms/c64/lib/cc65-src/mou/c64-pot.s +409 -0
- package/src/platforms/c64/lib/cc65-src/mouse_stat_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/mouse_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/mouseref.s +23 -0
- package/src/platforms/c64/lib/cc65-src/pencalib.c +94 -0
- package/src/platforms/c64/lib/cc65-src/randomize.s +18 -0
- package/src/platforms/c64/lib/cc65-src/revers.s +27 -0
- package/src/platforms/c64/lib/cc65-src/ser/c64-swlink.s +484 -0
- package/src/platforms/c64/lib/cc65-src/ser_stat_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/ser_stddrv.s +13 -0
- package/src/platforms/c64/lib/cc65-src/settime.s +84 -0
- package/src/platforms/c64/lib/cc65-src/soft80.inc +46 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cgetc.s +85 -0
- package/src/platforms/c64/lib/cc65-src/soft80_charset.s +182 -0
- package/src/platforms/c64/lib/cc65-src/soft80_color.s +159 -0
- package/src/platforms/c64/lib/cc65-src/soft80_conio.s +157 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cpeekc.s +148 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cpeekcolor.s +19 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cpeekrevers.s +15 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cpeeks.s +71 -0
- package/src/platforms/c64/lib/cc65-src/soft80_cputc.s +521 -0
- package/src/platforms/c64/lib/cc65-src/soft80_kclrscr.s +76 -0
- package/src/platforms/c64/lib/cc65-src/soft80_kplot.s +63 -0
- package/src/platforms/c64/lib/cc65-src/soft80_scrsize.s +14 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_cgetc.s +67 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_color.s +65 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_conio.s +168 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_cpeekcolor.s +17 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_cputc.s +204 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_kclrscr.s +63 -0
- package/src/platforms/c64/lib/cc65-src/soft80mono_kplot.s +52 -0
- package/src/platforms/c64/lib/cc65-src/status.s +15 -0
- package/src/platforms/c64/lib/cc65-src/sysuname.s +37 -0
- package/src/platforms/c64/lib/cc65-src/tgi/c64-hi.s +881 -0
- package/src/platforms/c64/lib/cc65-src/tgi_stat_stddrv.s +14 -0
- package/src/platforms/c64/lib/cc65-src/tgi_stddrv.s +13 -0
- package/src/platforms/c64/lib/cc65-src/tmcommon.s +67 -0
- package/src/platforms/c64/lib/cc65-src/waitvsync.s +18 -0
- package/src/platforms/c64/lib/read_joystick.s +28 -0
- package/src/platforms/c64/lib/sid_play.s +48 -0
- package/src/platforms/c64/lib/sprite_table.s +73 -0
- package/src/platforms/c64/lib/vic_init.s +47 -0
- package/src/platforms/c64/sid.js +128 -0
- package/src/platforms/c64/song.js +262 -0
- package/src/platforms/c64/vic.js +273 -0
- package/src/platforms/common/default-palette.js +139 -0
- package/src/platforms/common/image-to-tiles.js +418 -0
- package/src/platforms/common/intent.js +111 -0
- package/src/platforms/common/metasprite-adapters.js +279 -0
- package/src/platforms/common/metasprite-codegen.js +192 -0
- package/src/platforms/common/metasprite-core.js +201 -0
- package/src/platforms/common/metasprite.js +89 -0
- package/src/platforms/common/platform-palette.js +137 -0
- package/src/platforms/common/registers.js +329 -0
- package/src/platforms/common/render-tiles.js +86 -0
- package/src/platforms/common/screenshot-sprite.js +153 -0
- package/src/platforms/common/tile-decode.js +149 -0
- package/src/platforms/gb/MENTAL_MODEL.md +262 -0
- package/src/platforms/gb/TROUBLESHOOTING.md +218 -0
- package/src/platforms/gb/UPSTREAM_SOURCES.md +43 -0
- package/src/platforms/gb/image-to-tilemap.js +173 -0
- package/src/platforms/gb/lib/README.md +115 -0
- package/src/platforms/gb/lib/c/LICENSE-HUGEDRIVER +25 -0
- package/src/platforms/gb/lib/c/README.md +122 -0
- package/src/platforms/gb/lib/c/SDCC_GOTCHAS.md +190 -0
- package/src/platforms/gb/lib/c/gb_crt0.s +163 -0
- package/src/platforms/gb/lib/c/gb_hardware.h +113 -0
- package/src/platforms/gb/lib/c/gb_runtime.c +284 -0
- package/src/platforms/gb/lib/c/gb_runtime.h +145 -0
- package/src/platforms/gb/lib/c/hUGEDriver.c +191 -0
- package/src/platforms/gb/lib/c/hUGEDriver.h +95 -0
- package/src/platforms/gb/lib/c/hUGEDriver.upstream.asm +1908 -0
- package/src/platforms/gb/lib/c/lcd_init.c +19 -0
- package/src/platforms/gb/lib/c/patch-header.js +154 -0
- package/src/platforms/gb/lib/c/song_data.c +88 -0
- package/src/platforms/gb/lib/c/unroll.h +52 -0
- package/src/platforms/gb/lib/c/wait_vblank.c +14 -0
- package/src/platforms/gb/lib/dma_oam.asm +51 -0
- package/src/platforms/gb/lib/header.asm +56 -0
- package/src/platforms/gb/lib/joypad_read.asm +47 -0
- package/src/platforms/gb/lib/lcd_init.asm +44 -0
- package/src/platforms/gb/lib/load_palette.asm +25 -0
- package/src/platforms/gb/lib/load_tiles.asm +29 -0
- package/src/platforms/gb/lib/vblank_wait.asm +31 -0
- package/src/platforms/gb/ppu.js +574 -0
- package/src/platforms/gb/song.js +140 -0
- package/src/platforms/gba/MENTAL_MODEL.md +216 -0
- package/src/platforms/gba/TROUBLESHOOTING.md +250 -0
- package/src/platforms/gba/UPSTREAM_SOURCES.md +41 -0
- package/src/platforms/gba/lib/arm-archives/libc.a +0 -0
- package/src/platforms/gba/lib/arm-archives/libgcc.a +0 -0
- package/src/platforms/gba/lib/arm-archives/libnosys.a +0 -0
- package/src/platforms/gba/lib/c/gba_sfx.c +81 -0
- package/src/platforms/gba/lib/c/gba_sfx.h +48 -0
- package/src/platforms/gba/lib/libgba/crtbegin.o +0 -0
- package/src/platforms/gba/lib/libgba/crtend.o +0 -0
- package/src/platforms/gba/lib/libgba/crti.o +0 -0
- package/src/platforms/gba/lib/libgba/crtn.o +0 -0
- package/src/platforms/gba/lib/libgba/gba_cart.ld +319 -0
- package/src/platforms/gba/lib/libgba/gba_crt0.s +258 -0
- package/src/platforms/gba/lib/libgba/include/BoyScout.h +128 -0
- package/src/platforms/gba/lib/libgba/include/disc.h +36 -0
- package/src/platforms/gba/lib/libgba/include/disc_io.h +64 -0
- package/src/platforms/gba/lib/libgba/include/dldi.h +112 -0
- package/src/platforms/gba/lib/libgba/include/erapi.h +195 -0
- package/src/platforms/gba/lib/libgba/include/fade.h +76 -0
- package/src/platforms/gba/lib/libgba/include/gba.h +47 -0
- package/src/platforms/gba/lib/libgba/include/gba_affine.h +83 -0
- package/src/platforms/gba/lib/libgba/include/gba_base.h +122 -0
- package/src/platforms/gba/lib/libgba/include/gba_compression.h +66 -0
- package/src/platforms/gba/lib/libgba/include/gba_console.h +55 -0
- package/src/platforms/gba/lib/libgba/include/gba_dma.h +100 -0
- package/src/platforms/gba/lib/libgba/include/gba_input.h +127 -0
- package/src/platforms/gba/lib/libgba/include/gba_interrupt.h +146 -0
- package/src/platforms/gba/lib/libgba/include/gba_multiboot.h +72 -0
- package/src/platforms/gba/lib/libgba/include/gba_sio.h +124 -0
- package/src/platforms/gba/lib/libgba/include/gba_sound.h +356 -0
- package/src/platforms/gba/lib/libgba/include/gba_sprites.h +195 -0
- package/src/platforms/gba/lib/libgba/include/gba_systemcalls.h +194 -0
- package/src/platforms/gba/lib/libgba/include/gba_timers.h +63 -0
- package/src/platforms/gba/lib/libgba/include/gba_types.h +60 -0
- package/src/platforms/gba/lib/libgba/include/gba_video.h +307 -0
- package/src/platforms/gba/lib/libgba/include/mappy.h +72 -0
- package/src/platforms/gba/lib/libgba/include/mbv2.h +90 -0
- package/src/platforms/gba/lib/libgba/include/xcomms.h +93 -0
- package/src/platforms/gba/lib/libgba/include/xcomms_cmd.h +53 -0
- package/src/platforms/gba/lib/libgba/libgba.seed.a +0 -0
- package/src/platforms/gba/lib/libgba/libgba.seed.hash +1 -0
- package/src/platforms/gba/lib/libgba/src/AffineSet.c +42 -0
- package/src/platforms/gba/lib/libgba/src/ArcTan.s +41 -0
- package/src/platforms/gba/lib/libgba/src/BoyScout/BoyScout.c +1242 -0
- package/src/platforms/gba/lib/libgba/src/BoyScout/GBASoundRegs.h +200 -0
- package/src/platforms/gba/lib/libgba/src/Compression.c +84 -0
- package/src/platforms/gba/lib/libgba/src/CpuSet.c +41 -0
- package/src/platforms/gba/lib/libgba/src/Div.s +58 -0
- package/src/platforms/gba/lib/libgba/src/DivArm.s +50 -0
- package/src/platforms/gba/lib/libgba/src/InterruptDispatcher.s +113 -0
- package/src/platforms/gba/lib/libgba/src/IntrWait.c +35 -0
- package/src/platforms/gba/lib/libgba/src/MultiBoot.s +33 -0
- package/src/platforms/gba/lib/libgba/src/Reset.s +49 -0
- package/src/platforms/gba/lib/libgba/src/Sound.s +48 -0
- package/src/platforms/gba/lib/libgba/src/Sqrt.s +34 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/disc.c +58 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/dldi.c +189 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/dldi_stub.s +78 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.c +260 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.h +72 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.c +60 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.h +48 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.c +83 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.h +45 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.c +508 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.h +45 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.c +87 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.h +42 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.c +47 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.h +43 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.c +83 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.h +45 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.c +385 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.h +48 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd_s.s +139 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.c +203 -0
- package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.h +108 -0
- package/src/platforms/gba/lib/libgba/src/fade.c +185 -0
- package/src/platforms/gba/lib/libgba/src/input.c +127 -0
- package/src/platforms/gba/lib/libgba/src/interrupt.c +116 -0
- package/src/platforms/gba/lib/libgba/src/mappy_print.c +74 -0
- package/src/platforms/gba/lib/libgba/src/mb2print.c +69 -0
- package/src/platforms/gba/lib/libgba/src/mbv2.c +230 -0
- package/src/platforms/gba/lib/libgba/src/mbv2.txt +119 -0
- package/src/platforms/gba/lib/libgba/src/xcomms.c +203 -0
- package/src/platforms/gba/lib/libgba/src/xcomms_print.c +56 -0
- package/src/platforms/gba/lib/libgba/sysinclude/_ansi.h +82 -0
- package/src/platforms/gba/lib/libgba/sysinclude/_newlib_version.h +11 -0
- package/src/platforms/gba/lib/libgba/sysinclude/_syslist.h +41 -0
- package/src/platforms/gba/lib/libgba/sysinclude/alloca.h +21 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ar.h +65 -0
- package/src/platforms/gba/lib/libgba/sysinclude/argz.h +33 -0
- package/src/platforms/gba/lib/libgba/sysinclude/assert.h +50 -0
- package/src/platforms/gba/lib/libgba/sysinclude/complex.h +150 -0
- package/src/platforms/gba/lib/libgba/sysinclude/cpio.h +30 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ctype.h +183 -0
- package/src/platforms/gba/lib/libgba/sysinclude/devctl.h +78 -0
- package/src/platforms/gba/lib/libgba/sysinclude/dirent.h +85 -0
- package/src/platforms/gba/lib/libgba/sysinclude/elf.h +3147 -0
- package/src/platforms/gba/lib/libgba/sysinclude/envlock.h +15 -0
- package/src/platforms/gba/lib/libgba/sysinclude/envz.h +16 -0
- package/src/platforms/gba/lib/libgba/sysinclude/errno.h +11 -0
- package/src/platforms/gba/lib/libgba/sysinclude/fastmath.h +13 -0
- package/src/platforms/gba/lib/libgba/sysinclude/fcntl.h +1 -0
- package/src/platforms/gba/lib/libgba/sysinclude/fenv.h +42 -0
- package/src/platforms/gba/lib/libgba/sysinclude/float.h +631 -0
- package/src/platforms/gba/lib/libgba/sysinclude/fnmatch.h +55 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ftw.h +66 -0
- package/src/platforms/gba/lib/libgba/sysinclude/getopt.h +185 -0
- package/src/platforms/gba/lib/libgba/sysinclude/glob.h +90 -0
- package/src/platforms/gba/lib/libgba/sysinclude/grp.h +86 -0
- package/src/platforms/gba/lib/libgba/sysinclude/iconv.h +63 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ieeefp.h +295 -0
- package/src/platforms/gba/lib/libgba/sysinclude/inttypes.h +345 -0
- package/src/platforms/gba/lib/libgba/sysinclude/iso646.h +45 -0
- package/src/platforms/gba/lib/libgba/sysinclude/langinfo.h +332 -0
- package/src/platforms/gba/lib/libgba/sysinclude/libgen.h +37 -0
- package/src/platforms/gba/lib/libgba/sysinclude/limits.h +168 -0
- package/src/platforms/gba/lib/libgba/sysinclude/locale.h +96 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/_arc4random.h +1 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/_default_types.h +250 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/_endian.h +39 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/_time.h +3 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/_types.h +8 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/ansi.h +1 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/endian.h +69 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/fastmath.h +98 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/ieee.h +127 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/ieeefp.h +533 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/malloc.h +8 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/param.h +8 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp-dj.h +43 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp.h +524 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/stdlib.h +8 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/termios.h +1 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/time.h +15 -0
- package/src/platforms/gba/lib/libgba/sysinclude/machine/types.h +13 -0
- package/src/platforms/gba/lib/libgba/sysinclude/malloc.h +173 -0
- package/src/platforms/gba/lib/libgba/sysinclude/math.h +645 -0
- package/src/platforms/gba/lib/libgba/sysinclude/memory.h +4 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ndbm.h +91 -0
- package/src/platforms/gba/lib/libgba/sysinclude/newlib.h +427 -0
- package/src/platforms/gba/lib/libgba/sysinclude/paths.h +9 -0
- package/src/platforms/gba/lib/libgba/sysinclude/pthread.h +456 -0
- package/src/platforms/gba/lib/libgba/sysinclude/pwd.h +83 -0
- package/src/platforms/gba/lib/libgba/sysinclude/reent.h +190 -0
- package/src/platforms/gba/lib/libgba/sysinclude/regdef.h +7 -0
- package/src/platforms/gba/lib/libgba/sysinclude/regex.h +103 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sched.h +112 -0
- package/src/platforms/gba/lib/libgba/sysinclude/search.h +64 -0
- package/src/platforms/gba/lib/libgba/sysinclude/setjmp.h +25 -0
- package/src/platforms/gba/lib/libgba/sysinclude/signal.h +35 -0
- package/src/platforms/gba/lib/libgba/sysinclude/spawn.h +111 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/ssp.h +76 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdio.h +101 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdlib.h +30 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/string.h +115 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/strings.h +55 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/unistd.h +93 -0
- package/src/platforms/gba/lib/libgba/sysinclude/ssp/wchar.h +97 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdarg.h +135 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdatomic.h +409 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdbool.h +51 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stddef.h +463 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdint.h +466 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdio.h +807 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdio_ext.h +79 -0
- package/src/platforms/gba/lib/libgba/sysinclude/stdlib.h +345 -0
- package/src/platforms/gba/lib/libgba/sysinclude/string.h +183 -0
- package/src/platforms/gba/lib/libgba/sysinclude/strings.h +80 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_default_fcntl.h +241 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_intsup.h +199 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_locale.h +12 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_pthreadtypes.h +233 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_sigset.h +43 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_stdint.h +90 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_timespec.h +52 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_timeval.h +60 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_types.h +228 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/_tz_structs.h +24 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/cdefs.h +754 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/config.h +314 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/custom_file.h +2 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/dir.h +10 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/dirent.h +13 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/endian.h +207 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/errno.h +198 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/fcntl.h +12 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/features.h +551 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/fenv.h +90 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/file.h +2 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/iconvnls.h +77 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/iosupport.h +143 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/lock.h +75 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/param.h +35 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/queue.h +919 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/reent.h +913 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/resource.h +24 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/sched.h +69 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/select.h +94 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/signal.h +388 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/stat.h +179 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/statvfs.h +41 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/stdio.h +27 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/string.h +2 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/syslimits.h +61 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/time.h +448 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/timeb.h +40 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/times.h +32 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/timespec.h +63 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/tree.h +864 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/types.h +228 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/unistd.h +591 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/utime.h +22 -0
- package/src/platforms/gba/lib/libgba/sysinclude/sys/wait.h +44 -0
- package/src/platforms/gba/lib/libgba/sysinclude/tar.h +43 -0
- package/src/platforms/gba/lib/libgba/sysinclude/termios.h +7 -0
- package/src/platforms/gba/lib/libgba/sysinclude/tgmath.h +127 -0
- package/src/platforms/gba/lib/libgba/sysinclude/threads.h +93 -0
- package/src/platforms/gba/lib/libgba/sysinclude/time.h +313 -0
- package/src/platforms/gba/lib/libgba/sysinclude/unctrl.h +42 -0
- package/src/platforms/gba/lib/libgba/sysinclude/unistd.h +6 -0
- package/src/platforms/gba/lib/libgba/sysinclude/utime.h +12 -0
- package/src/platforms/gba/lib/libgba/sysinclude/utmp.h +8 -0
- package/src/platforms/gba/lib/libgba/sysinclude/varargs.h +7 -0
- package/src/platforms/gba/lib/libgba/sysinclude/wchar.h +339 -0
- package/src/platforms/gba/lib/libgba/sysinclude/wctype.h +74 -0
- package/src/platforms/gba/lib/libgba/sysinclude/wordexp.h +53 -0
- package/src/platforms/gba/lib/libtonc/crtbegin.o +0 -0
- package/src/platforms/gba/lib/libtonc/crtend.o +0 -0
- package/src/platforms/gba/lib/libtonc/crti.o +0 -0
- package/src/platforms/gba/lib/libtonc/crtn.o +0 -0
- package/src/platforms/gba/lib/libtonc/gba_cart.ld +319 -0
- package/src/platforms/gba/lib/libtonc/gba_crt0.s +258 -0
- package/src/platforms/gba/lib/libtonc/include/tonc.h +72 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_asminc.h +132 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_bios.h +555 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_core.h +573 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_input.h +184 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_irq.h +121 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_legacy.h +481 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_libgba.h +537 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_math.h +692 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_memdef.h +962 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_memmap.h +583 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_nocash.h +51 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_oam.h +186 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_surface.h +461 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_text.h +270 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_tte.h +748 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_types.h +376 -0
- package/src/platforms/gba/lib/libtonc/include/tonc_video.h +615 -0
- package/src/platforms/gba/lib/libtonc/libtonc.seed.a +0 -0
- package/src/platforms/gba/lib/libtonc/libtonc.seed.hash +1 -0
- package/src/platforms/gba/lib/libtonc/src/asm/clr_blend_fast.s +72 -0
- package/src/platforms/gba/lib/libtonc/src/asm/clr_fade_fast.s +74 -0
- package/src/platforms/gba/lib/libtonc/src/asm/div_lut.s +54 -0
- package/src/platforms/gba/lib/libtonc/src/asm/sin_lut.s +90 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios.s +289 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios_ex.s +97 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_master.s +92 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_nest.s +98 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_memcpy.s +126 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_memset.s +123 -0
- package/src/platforms/gba/lib/libtonc/src/asm/tonc_nocash.s +73 -0
- package/src/platforms/gba/lib/libtonc/src/font/sys8.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/sys8.s +46 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana10.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana10.s +293 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9.s +167 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.s +545 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9b.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9b.s +167 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9i.png +0 -0
- package/src/platforms/gba/lib/libtonc/src/font/verdana9i.s +167 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_bitmap.c +289 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text.c +81 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_bm.c +244 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_map.c +122 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_oam.c +113 -0
- package/src/platforms/gba/lib/libtonc/src/pre1.3/toncfont.s +43 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_bg.c +61 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_bg_affine.c +112 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_bmp16.c +240 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_bmp8.c +314 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_color.c +368 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_core.c +237 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_input.c +118 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_irq.c +271 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_math.c +54 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_oam.c +76 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_obj_affine.c +146 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_sbmp16.c +369 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_sbmp8.c +405 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_schr4c.c +588 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_schr4r.c +462 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_surface.c +105 -0
- package/src/platforms/gba/lib/libtonc/src/tonc_video.c +33 -0
- package/src/platforms/gba/lib/libtonc/src/tte/ase_drawg.c +83 -0
- package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg.c +72 -0
- package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg_b1cs.c +92 -0
- package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg.c +71 -0
- package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cs.c +104 -0
- package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cts_fast.s +115 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts.c +76 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts_fast.s +128 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts.c +67 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts_fast.s +127 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts.c +80 -0
- package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts_fast.s +145 -0
- package/src/platforms/gba/lib/libtonc/src/tte/obj_drawg.c +61 -0
- package/src/platforms/gba/lib/libtonc/src/tte/se_drawg.c +110 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_ase.c +87 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_bmp.c +118 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4c.c +86 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4r.c +87 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_obj.c +84 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_init_se.c +96 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_iohook.c +264 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_main.c +756 -0
- package/src/platforms/gba/lib/libtonc/src/tte/tte_types.s +119 -0
- package/src/platforms/gba/lib/maxmod/LICENSE-MAXMOD +23 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_defs.inc +117 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_format_mas.inc +108 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_macros.inc +195 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_mas.inc +40 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_mas_structs.inc +189 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_ds.inc +46 -0
- package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_gba.inc +42 -0
- package/src/platforms/gba/lib/maxmod/asm_include/swi_gba.inc +23 -0
- package/src/platforms/gba/lib/maxmod/include/maxmod.h +412 -0
- package/src/platforms/gba/lib/maxmod/include/mm_types.h +333 -0
- package/src/platforms/gba/lib/maxmod/maxmod.seed.a +0 -0
- package/src/platforms/gba/lib/maxmod/maxmod.seed.hash +1 -0
- package/src/platforms/gba/lib/maxmod/music/chiptune.xm +0 -0
- package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.bin +0 -0
- package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.h +4 -0
- package/src/platforms/gba/lib/maxmod/music/make_chiptune_xm.js +203 -0
- package/src/platforms/gba/lib/maxmod/source/mm_effect.s +767 -0
- package/src/platforms/gba/lib/maxmod/source/mm_main.s +115 -0
- package/src/platforms/gba/lib/maxmod/source/mm_mas.s +4990 -0
- package/src/platforms/gba/lib/maxmod/source/mm_mas_arm.s +612 -0
- package/src/platforms/gba/lib/maxmod/source_gba/mm_init_default.s +98 -0
- package/src/platforms/gba/lib/maxmod/source_gba/mm_main_gba.s +292 -0
- package/src/platforms/gba/lib/maxmod/source_gba/mm_mixer_gba.s +1367 -0
- package/src/platforms/gba/lib/sysbase/gba_iosupport.c +138 -0
- package/src/platforms/gbc/MENTAL_MODEL.md +178 -0
- package/src/platforms/gbc/TROUBLESHOOTING.md +142 -0
- package/src/platforms/gbc/UPSTREAM_SOURCES.md +60 -0
- package/src/platforms/gbc/lib/c/LICENSE-HUGEDRIVER +25 -0
- package/src/platforms/gbc/lib/c/README.md +122 -0
- package/src/platforms/gbc/lib/c/SDCC_GOTCHAS.md +190 -0
- package/src/platforms/gbc/lib/c/gb_crt0.s +163 -0
- package/src/platforms/gbc/lib/c/gb_hardware.h +113 -0
- package/src/platforms/gbc/lib/c/gb_runtime.c +284 -0
- package/src/platforms/gbc/lib/c/gb_runtime.h +145 -0
- package/src/platforms/gbc/lib/c/hUGEDriver.c +191 -0
- package/src/platforms/gbc/lib/c/hUGEDriver.h +95 -0
- package/src/platforms/gbc/lib/c/hUGEDriver.upstream.asm +1908 -0
- package/src/platforms/gbc/lib/c/lcd_init.c +19 -0
- package/src/platforms/gbc/lib/c/patch-header.js +154 -0
- package/src/platforms/gbc/lib/c/song_data.c +88 -0
- package/src/platforms/gbc/lib/c/unroll.h +52 -0
- package/src/platforms/gbc/lib/c/wait_vblank.c +14 -0
- package/src/platforms/gbc/song.js +3 -0
- package/src/platforms/genesis/MENTAL_MODEL.md +306 -0
- package/src/platforms/genesis/TROUBLESHOOTING.md +226 -0
- package/src/platforms/genesis/UPSTREAM_SOURCES.md +53 -0
- package/src/platforms/genesis/image-to-tilemap.js +351 -0
- package/src/platforms/genesis/lib/README.md +160 -0
- package/src/platforms/genesis/lib/c/crtbegin.o +0 -0
- package/src/platforms/genesis/lib/c/crtend.o +0 -0
- package/src/platforms/genesis/lib/c/genesis.ld +44 -0
- package/src/platforms/genesis/lib/c/genesis_sfx.c +51 -0
- package/src/platforms/genesis/lib/c/genesis_sfx.h +49 -0
- package/src/platforms/genesis/lib/c/libc.a +0 -0
- package/src/platforms/genesis/lib/c/libgcc.a +0 -0
- package/src/platforms/genesis/lib/c/libm.a +0 -0
- package/src/platforms/genesis/lib/c/sega.s +71 -0
- package/src/platforms/genesis/lib/header.s +96 -0
- package/src/platforms/genesis/lib/nmi_safe.s +79 -0
- package/src/platforms/genesis/lib/pad_read.s +104 -0
- package/src/platforms/genesis/lib/sgdk/COPYING.RUNTIME +73 -0
- package/src/platforms/genesis/lib/sgdk/LICENSE +12 -0
- package/src/platforms/genesis/lib/sgdk/include/asm.h +52 -0
- package/src/platforms/genesis/lib/sgdk/include/asm_mac.i +9 -0
- package/src/platforms/genesis/lib/sgdk/include/bmp.h +690 -0
- package/src/platforms/genesis/lib/sgdk/include/config.h +208 -0
- package/src/platforms/genesis/lib/sgdk/include/dma.h +542 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/console.h +387 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/everdrive.h +116 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/fat16.h +84 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/flash.h +164 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/saveman.h +177 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/link_cable.h +316 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/minimusic/minimus.h +29 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/16c550.h +221 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/comm.h +93 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/gamejolt.h +541 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/jsmn.h +471 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/json.h +122 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/lsd.h +172 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/megawifi.h +984 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/mw-msg.h +392 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_pro.h +38 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_x7.h +73 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/serial/buffer.h +8 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/serial/serial.h +133 -0
- package/src/platforms/genesis/lib/sgdk/include/ext/stb/stb_sprintf.h +1864 -0
- package/src/platforms/genesis/lib/sgdk/include/genesis.h +92 -0
- package/src/platforms/genesis/lib/sgdk/include/joy.h +482 -0
- package/src/platforms/genesis/lib/sgdk/include/kdebug.h +21 -0
- package/src/platforms/genesis/lib/sgdk/include/map.h +409 -0
- package/src/platforms/genesis/lib/sgdk/include/mapper.h +186 -0
- package/src/platforms/genesis/lib/sgdk/include/maths.h +1071 -0
- package/src/platforms/genesis/lib/sgdk/include/maths3D.h +480 -0
- package/src/platforms/genesis/lib/sgdk/include/memory.h +346 -0
- package/src/platforms/genesis/lib/sgdk/include/memory_base.h +37 -0
- package/src/platforms/genesis/lib/sgdk/include/object.h +171 -0
- package/src/platforms/genesis/lib/sgdk/include/pal.h +500 -0
- package/src/platforms/genesis/lib/sgdk/include/pool.h +171 -0
- package/src/platforms/genesis/lib/sgdk/include/psg.h +153 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_dpcm2.h +79 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm.h +98 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm4.h +125 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/pcm/tab_vol.h +6 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/smp_null.h +6 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/smp_null_dpcm.h +6 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/sound.h +70 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/xgm.h +399 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/xgm2.h +389 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/z80_def.i80 +41 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/z80_fct.i80 +83 -0
- package/src/platforms/genesis/lib/sgdk/include/snd/z80_mac.i80 +1476 -0
- package/src/platforms/genesis/lib/sgdk/include/sprite_eng.h +1095 -0
- package/src/platforms/genesis/lib/sgdk/include/sprite_eng_legacy.h +1030 -0
- package/src/platforms/genesis/lib/sgdk/include/sram.h +110 -0
- package/src/platforms/genesis/lib/sgdk/include/string.h +349 -0
- package/src/platforms/genesis/lib/sgdk/include/sys.h +511 -0
- package/src/platforms/genesis/lib/sgdk/include/tab_cnv.h +19 -0
- package/src/platforms/genesis/lib/sgdk/include/task.h +77 -0
- package/src/platforms/genesis/lib/sgdk/include/task_cst.h +33 -0
- package/src/platforms/genesis/lib/sgdk/include/timer.h +132 -0
- package/src/platforms/genesis/lib/sgdk/include/tools.h +450 -0
- package/src/platforms/genesis/lib/sgdk/include/types.h +320 -0
- package/src/platforms/genesis/lib/sgdk/include/vdp.h +1150 -0
- package/src/platforms/genesis/lib/sgdk/include/vdp_bg.h +723 -0
- package/src/platforms/genesis/lib/sgdk/include/vdp_pal.h +101 -0
- package/src/platforms/genesis/lib/sgdk/include/vdp_spr.h +448 -0
- package/src/platforms/genesis/lib/sgdk/include/vdp_tile.h +1136 -0
- package/src/platforms/genesis/lib/sgdk/include/vram.h +270 -0
- package/src/platforms/genesis/lib/sgdk/include/ym2612.h +87 -0
- package/src/platforms/genesis/lib/sgdk/include/z80_ctrl.h +420 -0
- package/src/platforms/genesis/lib/sgdk/libmd.seed.a +0 -0
- package/src/platforms/genesis/lib/sgdk/libmd.seed.hash +1 -0
- package/src/platforms/genesis/lib/sgdk/md.ld +120 -0
- package/src/platforms/genesis/lib/sgdk/music/demo.vgm +0 -0
- package/src/platforms/genesis/lib/sgdk/music/demo.xgc +0 -0
- package/src/platforms/genesis/lib/sgdk/music/demo.xgm +0 -0
- package/src/platforms/genesis/lib/sgdk/res/image/font_default.png +0 -0
- package/src/platforms/genesis/lib/sgdk/res/image/sgdk_logo.png +0 -0
- package/src/platforms/genesis/lib/sgdk/res/libres.h +10 -0
- package/src/platforms/genesis/lib/sgdk/res/libres.res +5 -0
- package/src/platforms/genesis/lib/sgdk/res/libres.s +166 -0
- package/src/platforms/genesis/lib/sgdk/res/sound/stop_xgm.bin +0 -0
- package/src/platforms/genesis/lib/sgdk/rom_header.c +33 -0
- package/src/platforms/genesis/lib/sgdk/sega.preprocessed.s +364 -0
- package/src/platforms/genesis/lib/sgdk/sega.s +365 -0
- package/src/platforms/genesis/lib/sgdk/src/bmp.c +1539 -0
- package/src/platforms/genesis/lib/sgdk/src/bmp_a.s +3477 -0
- package/src/platforms/genesis/lib/sgdk/src/boot/rom_header.c +33 -0
- package/src/platforms/genesis/lib/sgdk/src/boot/sega.s +365 -0
- package/src/platforms/genesis/lib/sgdk/src/dma.c +782 -0
- package/src/platforms/genesis/lib/sgdk/src/dma_a.s +23 -0
- package/src/platforms/genesis/lib/sgdk/src/error_a.s +376 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/console.c +490 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/everdrive.c +285 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/fat16.c +610 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/README.md +112 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/flash.c +300 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/saveman.c +641 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/link_cable.c +1758 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/CHANGELOG.md +31 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/LICENSE.txt +17 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/README.md +18 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/data.z80 +148 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/define.z80 +173 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/api-c.md +80 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/format.md +132 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/teradrive.md +33 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/fm.z80 +363 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/main.z80 +433 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus.c +129 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus_drv.s80 +17 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/psg.z80 +231 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/track.z80 +398 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/util.z80 +98 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/16c550.c +84 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/README.md +849 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/comm.c +141 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/gamejolt.c +758 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/json.c +153 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/lsd.c +364 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/megawifi.c +1501 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_pro.c +98 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_x7.c +67 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/serial/buffer.c +69 -0
- package/src/platforms/genesis/lib/sgdk/src/ext/serial/serial.c +158 -0
- package/src/platforms/genesis/lib/sgdk/src/joy.c +1361 -0
- package/src/platforms/genesis/lib/sgdk/src/kdebug.s +109 -0
- package/src/platforms/genesis/lib/sgdk/src/map.c +1915 -0
- package/src/platforms/genesis/lib/sgdk/src/mapper.c +280 -0
- package/src/platforms/genesis/lib/sgdk/src/maths.c +878 -0
- package/src/platforms/genesis/lib/sgdk/src/maths3D.c +480 -0
- package/src/platforms/genesis/lib/sgdk/src/maths3D_a.s +205 -0
- package/src/platforms/genesis/lib/sgdk/src/memory.c +760 -0
- package/src/platforms/genesis/lib/sgdk/src/memory_a.s +306 -0
- package/src/platforms/genesis/lib/sgdk/src/object.c +111 -0
- package/src/platforms/genesis/lib/sgdk/src/pal.c +484 -0
- package/src/platforms/genesis/lib/sgdk/src/pool.c +234 -0
- package/src/platforms/genesis/lib/sgdk/src/psg.c +82 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/drv_null.s80 +27 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/drv_xgm.s80 +3037 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_dpcm2.s80 +984 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm.s80 +592 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm4.s80 +699 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_dpcm2.c +172 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm.c +152 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm4.c +213 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/pcm/tab_vol.c +277 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/smp_null.s +22 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/smp_null_dpcm.s +15 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/sound.c +33 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm.c +683 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2.s80 +993 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_fct.i80 +611 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_mac.i80 +133 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_fct.i80 +114 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_mac.i80 +1444 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_fct.i80 +491 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_mac.i80 +43 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_fct.i80 +1664 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_mac.i80 +295 -0
- package/src/platforms/genesis/lib/sgdk/src/snd/xgm2.c +1083 -0
- package/src/platforms/genesis/lib/sgdk/src/sprite_eng.c +2256 -0
- package/src/platforms/genesis/lib/sgdk/src/sprite_eng_legacy.c +2309 -0
- package/src/platforms/genesis/lib/sgdk/src/sram.c +30 -0
- package/src/platforms/genesis/lib/sgdk/src/sram_a.s +41 -0
- package/src/platforms/genesis/lib/sgdk/src/string.c +720 -0
- package/src/platforms/genesis/lib/sgdk/src/sys.c +1053 -0
- package/src/platforms/genesis/lib/sgdk/src/sys_a.s +74 -0
- package/src/platforms/genesis/lib/sgdk/src/tab_cnv.c +129 -0
- package/src/platforms/genesis/lib/sgdk/src/tab_log10.c +8201 -0
- package/src/platforms/genesis/lib/sgdk/src/tab_log2.c +8201 -0
- package/src/platforms/genesis/lib/sgdk/src/tab_sin.c +2058 -0
- package/src/platforms/genesis/lib/sgdk/src/tab_sqrt.c +8201 -0
- package/src/platforms/genesis/lib/sgdk/src/task.s +148 -0
- package/src/platforms/genesis/lib/sgdk/src/timer.c +201 -0
- package/src/platforms/genesis/lib/sgdk/src/tools.c +1299 -0
- package/src/platforms/genesis/lib/sgdk/src/tools_a.s +979 -0
- package/src/platforms/genesis/lib/sgdk/src/types.c +18 -0
- package/src/platforms/genesis/lib/sgdk/src/vdp.c +1060 -0
- package/src/platforms/genesis/lib/sgdk/src/vdp_bg.c +511 -0
- package/src/platforms/genesis/lib/sgdk/src/vdp_spr.c +322 -0
- package/src/platforms/genesis/lib/sgdk/src/vdp_tile.c +1011 -0
- package/src/platforms/genesis/lib/sgdk/src/vdp_tile_a.s +68 -0
- package/src/platforms/genesis/lib/sgdk/src/vram.c +273 -0
- package/src/platforms/genesis/lib/sgdk/src/ym2612.c +175 -0
- package/src/platforms/genesis/lib/sgdk/src/z80_ctrl.c +334 -0
- package/src/platforms/genesis/lib/sprite_table.s +129 -0
- package/src/platforms/genesis/lib/vblank_wait.s +73 -0
- package/src/platforms/genesis/lib/vdp_init.s +85 -0
- package/src/platforms/genesis/lib/wram.s +88 -0
- package/src/platforms/genesis/lib/z80_bootstrap.s +102 -0
- package/src/platforms/genesis/vdp.js +548 -0
- package/src/platforms/genesis/xgm2-pcm.js +165 -0
- package/src/platforms/gg/MENTAL_MODEL.md +174 -0
- package/src/platforms/gg/TROUBLESHOOTING.md +105 -0
- package/src/platforms/gg/UPSTREAM_SOURCES.md +36 -0
- package/src/platforms/gg/lib/c/gg_crt0.s +112 -0
- package/src/platforms/gg/lib/c/gg_hw.h +62 -0
- package/src/platforms/gg/lib/c/gg_music.c +155 -0
- package/src/platforms/gg/lib/c/gg_music.h +89 -0
- package/src/platforms/gg/lib/c/gg_sfx.c +82 -0
- package/src/platforms/gg/lib/c/gg_sfx.h +40 -0
- package/src/platforms/gg/lib/c/joypad_read.c +22 -0
- package/src/platforms/gg/lib/c/load_palette.c +20 -0
- package/src/platforms/gg/lib/c/load_tiles.c +32 -0
- package/src/platforms/gg/lib/c/sprite_table.c +60 -0
- package/src/platforms/gg/lib/c/vblank_wait.c +10 -0
- package/src/platforms/gg/lib/c/vdp_init.c +58 -0
- package/src/platforms/gg/song.js +189 -0
- package/src/platforms/index.js +7 -0
- package/src/platforms/lynx/MENTAL_MODEL.md +248 -0
- package/src/platforms/lynx/TROUBLESHOOTING.md +105 -0
- package/src/platforms/lynx/UPSTREAM_SOURCES.md +66 -0
- package/src/platforms/lynx/lib/c/lynx_music.c +63 -0
- package/src/platforms/lynx/lib/c/lynx_music.h +16 -0
- package/src/platforms/lynx/lib/c/lynx_sfx.c +147 -0
- package/src/platforms/lynx/lib/c/lynx_sfx.h +59 -0
- package/src/platforms/lynx/lib/cc65-src/bllhdr.s +18 -0
- package/src/platforms/lynx/lib/cc65-src/bootldr.s +195 -0
- package/src/platforms/lynx/lib/cc65-src/cgetc.s +69 -0
- package/src/platforms/lynx/lib/cc65-src/clock.s +87 -0
- package/src/platforms/lynx/lib/cc65-src/crt0.s +135 -0
- package/src/platforms/lynx/lib/cc65-src/defdir.s +29 -0
- package/src/platforms/lynx/lib/cc65-src/eeprom.s +255 -0
- package/src/platforms/lynx/lib/cc65-src/eeprom46.s +204 -0
- package/src/platforms/lynx/lib/cc65-src/eeprom66.s +227 -0
- package/src/platforms/lynx/lib/cc65-src/eeprom86.s +236 -0
- package/src/platforms/lynx/lib/cc65-src/exec.s +34 -0
- package/src/platforms/lynx/lib/cc65-src/exehdr.s +27 -0
- package/src/platforms/lynx/lib/cc65-src/extzp.inc +23 -0
- package/src/platforms/lynx/lib/cc65-src/extzp.s +30 -0
- package/src/platforms/lynx/lib/cc65-src/irq.s +45 -0
- package/src/platforms/lynx/lib/cc65-src/joy/lynx-stdjoy.s +93 -0
- package/src/platforms/lynx/lib/cc65-src/joy_stat_stddrv.s +14 -0
- package/src/platforms/lynx/lib/cc65-src/kbhit.s +56 -0
- package/src/platforms/lynx/lib/cc65-src/libref.s +9 -0
- package/src/platforms/lynx/lib/cc65-src/load.s +41 -0
- package/src/platforms/lynx/lib/cc65-src/lseek.s +58 -0
- package/src/platforms/lynx/lib/cc65-src/lynx-cart.s +98 -0
- package/src/platforms/lynx/lib/cc65-src/lynx-snd.s +1270 -0
- package/src/platforms/lynx/lib/cc65-src/mainargs.s +24 -0
- package/src/platforms/lynx/lib/cc65-src/open.s +136 -0
- package/src/platforms/lynx/lib/cc65-src/oserror.s +14 -0
- package/src/platforms/lynx/lib/cc65-src/read.s +44 -0
- package/src/platforms/lynx/lib/cc65-src/ser/lynx-comlynx.s +404 -0
- package/src/platforms/lynx/lib/cc65-src/ser_stat_stddrv.s +14 -0
- package/src/platforms/lynx/lib/cc65-src/sysuname.s +39 -0
- package/src/platforms/lynx/lib/cc65-src/tgi/lynx-160-102-16.s +1075 -0
- package/src/platforms/lynx/lib/cc65-src/tgi_colors.s +9 -0
- package/src/platforms/lynx/lib/cc65-src/tgi_irq.s +11 -0
- package/src/platforms/lynx/lib/cc65-src/tgi_stat_stddrv.s +14 -0
- package/src/platforms/lynx/lib/cc65-src/tgi_stddrv.s +13 -0
- package/src/platforms/lynx/lib/cc65-src/uploader.s +81 -0
- package/src/platforms/lynx/song.js +291 -0
- package/src/platforms/msx/MENTAL_MODEL.md +115 -0
- package/src/platforms/msx/TROUBLESHOOTING.md +62 -0
- package/src/platforms/msx/UPSTREAM_SOURCES.md +46 -0
- package/src/platforms/msx/image-to-tilemap.js +103 -0
- package/src/platforms/msx/lib/c/hello_msx.c +51 -0
- package/src/platforms/msx/lib/c/msx_crt0.s +74 -0
- package/src/platforms/msx/lib/c/msx_hw.h +92 -0
- package/src/platforms/msx/lib/c/msx_vdp.c +150 -0
- package/src/platforms/msx/tiles.js +99 -0
- package/src/platforms/msx/vdp.js +160 -0
- package/src/platforms/nes/MENTAL_MODEL.md +323 -0
- package/src/platforms/nes/TROUBLESHOOTING.md +319 -0
- package/src/platforms/nes/UPSTREAM_SOURCES.md +31 -0
- package/src/platforms/nes/image-to-chr.js +195 -0
- package/src/platforms/nes/image-to-tilemap.js +415 -0
- package/src/platforms/nes/lib/README.md +40 -0
- package/src/platforms/nes/lib/asm/LICENSE-FAMITONE +40 -0
- package/src/platforms/nes/lib/asm/chr_ram_header.s +32 -0
- package/src/platforms/nes/lib/asm/famitone2.s +1258 -0
- package/src/platforms/nes/lib/asm/famitone_bridge.s +50 -0
- package/src/platforms/nes/lib/asm/music_data.s +238 -0
- package/src/platforms/nes/lib/c/chr_ram_runtime_hello_sprite.c +81 -0
- package/src/platforms/nes/lib/c/chr_ram_runtime_hud_row.c +101 -0
- package/src/platforms/nes/lib/c/nes_runtime.c +347 -0
- package/src/platforms/nes/lib/c/nes_runtime.h +153 -0
- package/src/platforms/nes/lib/c/nmi_handler.c +51 -0
- package/src/platforms/nes/lib/c/nmi_trampoline.s +25 -0
- package/src/platforms/nes/lib/cc65-src/Makefile.inc +9 -0
- package/src/platforms/nes/lib/cc65-src/_scrsize.s +24 -0
- package/src/platforms/nes/lib/cc65-src/cclear.s +29 -0
- package/src/platforms/nes/lib/cc65-src/chline.s +31 -0
- package/src/platforms/nes/lib/cc65-src/clock.s +31 -0
- package/src/platforms/nes/lib/cc65-src/clrscr.s +72 -0
- package/src/platforms/nes/lib/cc65-src/color.s +68 -0
- package/src/platforms/nes/lib/cc65-src/cpeekc.s +37 -0
- package/src/platforms/nes/lib/cc65-src/cpeekcolor.s +8 -0
- package/src/platforms/nes/lib/cc65-src/cpeekrevers.s +37 -0
- package/src/platforms/nes/lib/cc65-src/cputc.s +95 -0
- package/src/platforms/nes/lib/cc65-src/crt0.s +180 -0
- package/src/platforms/nes/lib/cc65-src/cvline.s +31 -0
- package/src/platforms/nes/lib/cc65-src/get_tv.s +37 -0
- package/src/platforms/nes/lib/cc65-src/gotox.s +21 -0
- package/src/platforms/nes/lib/cc65-src/gotoxy.s +22 -0
- package/src/platforms/nes/lib/cc65-src/gotoy.s +22 -0
- package/src/platforms/nes/lib/cc65-src/irq.s +19 -0
- package/src/platforms/nes/lib/cc65-src/joy/nes-stdjoy.s +102 -0
- package/src/platforms/nes/lib/cc65-src/joy_stat_stddrv.s +14 -0
- package/src/platforms/nes/lib/cc65-src/libref.s +9 -0
- package/src/platforms/nes/lib/cc65-src/mainargs.s +24 -0
- package/src/platforms/nes/lib/cc65-src/neschar.s +4616 -0
- package/src/platforms/nes/lib/cc65-src/ppu.s +158 -0
- package/src/platforms/nes/lib/cc65-src/ppubuf.s +117 -0
- package/src/platforms/nes/lib/cc65-src/randomize.s +18 -0
- package/src/platforms/nes/lib/cc65-src/revers.s +27 -0
- package/src/platforms/nes/lib/cc65-src/setcursor.s +37 -0
- package/src/platforms/nes/lib/cc65-src/sysuname.s +39 -0
- package/src/platforms/nes/lib/cc65-src/tgi/nes-64-56-2.s +480 -0
- package/src/platforms/nes/lib/cc65-src/tgi_stat_stddrv.s +14 -0
- package/src/platforms/nes/lib/cc65-src/tgi_stddrv.s +13 -0
- package/src/platforms/nes/lib/cc65-src/waitvsync.s +18 -0
- package/src/platforms/nes/lib/cc65-src/wherex.s +19 -0
- package/src/platforms/nes/lib/cc65-src/wherey.s +19 -0
- package/src/platforms/nes/lib/clear_nametable.s +38 -0
- package/src/platforms/nes/lib/clear_oam.s +18 -0
- package/src/platforms/nes/lib/load_palette.s +31 -0
- package/src/platforms/nes/lib/nmi_safe.s +65 -0
- package/src/platforms/nes/lib/oam_dma.s +16 -0
- package/src/platforms/nes/lib/read_pad.s +46 -0
- package/src/platforms/nes/lib/reset.s +46 -0
- package/src/platforms/nes/lib/sprite_table_populate.s +75 -0
- package/src/platforms/nes/lib/wait_vblank.s +12 -0
- package/src/platforms/nes/palette.js +39 -0
- package/src/platforms/nes/ppu.js +448 -0
- package/src/platforms/pce/MENTAL_MODEL.md +98 -0
- package/src/platforms/pce/TROUBLESHOOTING.md +54 -0
- package/src/platforms/pce/UPSTREAM_SOURCES.md +38 -0
- package/src/platforms/pce/image-to-tilemap.js +123 -0
- package/src/platforms/pce/lib/c/hello_pce.c +37 -0
- package/src/platforms/pce/lib/c/pce_hw.h +130 -0
- package/src/platforms/pce/lib/c/pce_input.c +36 -0
- package/src/platforms/pce/lib/c/pce_sound.c +53 -0
- package/src/platforms/pce/lib/c/pce_video.c +113 -0
- package/src/platforms/pce/tiles.js +92 -0
- package/src/platforms/pce/vce.js +59 -0
- package/src/platforms/pce/vdc.js +52 -0
- package/src/platforms/sms/MENTAL_MODEL.md +286 -0
- package/src/platforms/sms/TROUBLESHOOTING.md +140 -0
- package/src/platforms/sms/UPSTREAM_SOURCES.md +29 -0
- package/src/platforms/sms/image-to-tilemap.js +260 -0
- package/src/platforms/sms/lib/README.md +117 -0
- package/src/platforms/sms/lib/c/joypad_read.c +33 -0
- package/src/platforms/sms/lib/c/load_palette.c +24 -0
- package/src/platforms/sms/lib/c/load_tiles.c +32 -0
- package/src/platforms/sms/lib/c/sms_crt0.s +101 -0
- package/src/platforms/sms/lib/c/sms_hw.h +53 -0
- package/src/platforms/sms/lib/c/sms_music.c +178 -0
- package/src/platforms/sms/lib/c/sms_music.h +50 -0
- package/src/platforms/sms/lib/c/sms_sfx.c +82 -0
- package/src/platforms/sms/lib/c/sms_sfx.h +40 -0
- package/src/platforms/sms/lib/c/sprite_table.c +60 -0
- package/src/platforms/sms/lib/c/vblank_wait.c +10 -0
- package/src/platforms/sms/lib/c/vdp_init.c +58 -0
- package/src/platforms/sms/lib/header.s +33 -0
- package/src/platforms/sms/lib/joypad_read.s +40 -0
- package/src/platforms/sms/lib/load_palette.s +30 -0
- package/src/platforms/sms/lib/load_tiles.s +50 -0
- package/src/platforms/sms/lib/sprite_table.s +44 -0
- package/src/platforms/sms/lib/vblank_wait.s +36 -0
- package/src/platforms/sms/lib/vdp_init.s +47 -0
- package/src/platforms/sms/song.js +217 -0
- package/src/platforms/sms/vdp.js +530 -0
- package/src/platforms/snes/MENTAL_MODEL.md +289 -0
- package/src/platforms/snes/TROUBLESHOOTING.md +208 -0
- package/src/platforms/snes/UPSTREAM_SOURCES.md +50 -0
- package/src/platforms/snes/brr.js +208 -0
- package/src/platforms/snes/image-to-tilemap.js +227 -0
- package/src/platforms/snes/lib/audio/apu_blob.asm +228 -0
- package/src/platforms/snes/lib/audio/apu_blob.bin +0 -0
- package/src/platforms/snes/lib/audio/explosion.brr +0 -0
- package/src/platforms/snes/lib/audio/sample_bank.bin +0 -0
- package/src/platforms/snes/lib/audio/shoot.brr +0 -0
- package/src/platforms/snes/lib/audio/spc_driver.asm +241 -0
- package/src/platforms/snes/lib/audio_pipeline.asm +62 -0
- package/src/platforms/snes/lib/c/crt0.asm +125 -0
- package/src/platforms/snes/lib/c/hdr.asm +50 -0
- package/src/platforms/snes/lib/c/snes_sfx.c +116 -0
- package/src/platforms/snes/lib/c/snes_sfx.h +96 -0
- package/src/platforms/snes/lib/c/snes_sfx_data.asm +25 -0
- package/src/platforms/snes/lib/cgram_upload.asm +43 -0
- package/src/platforms/snes/lib/lorom_header.asm +47 -0
- package/src/platforms/snes/lib/lorom_multibank.asm +66 -0
- package/src/platforms/snes/lib/nmi_safe.asm +77 -0
- package/src/platforms/snes/lib/oam_upload.asm +45 -0
- package/src/platforms/snes/lib/pad_read.asm +64 -0
- package/src/platforms/snes/lib/pvsneslib/LICENSE +21 -0
- package/src/platforms/snes/lib/pvsneslib/include/ctype.h +6 -0
- package/src/platforms/snes/lib/pvsneslib/include/float.h +4 -0
- package/src/platforms/snes/lib/pvsneslib/include/hdr.asm +47 -0
- package/src/platforms/snes/lib/pvsneslib/include/limits.h +13 -0
- package/src/platforms/snes/lib/pvsneslib/include/math.h +10 -0
- package/src/platforms/snes/lib/pvsneslib/include/setjmp.h +4 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/background.h +396 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/console.h +188 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/dma.h +381 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/input.h +289 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/interrupt.h +264 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/libversion.h +10 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/lzss.h +43 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/map.h +113 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/object.h +234 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/pixel.h +53 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/scores.h +66 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/snestypes.h +65 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/sound.h +245 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/sprite.h +456 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes/video.h +465 -0
- package/src/platforms/snes/lib/pvsneslib/include/snes.h +190 -0
- package/src/platforms/snes/lib/pvsneslib/include/stdarg.h +28 -0
- package/src/platforms/snes/lib/pvsneslib/include/stdbool.h +53 -0
- package/src/platforms/snes/lib/pvsneslib/include/stddef.h +27 -0
- package/src/platforms/snes/lib/pvsneslib/include/stdint.h +7 -0
- package/src/platforms/snes/lib/pvsneslib/include/stdio.h +9 -0
- package/src/platforms/snes/lib/pvsneslib/include/stdlib.h +13 -0
- package/src/platforms/snes/lib/pvsneslib/include/string.h +19 -0
- package/src/platforms/snes/lib/pvsneslib/include/strings.h +5 -0
- package/src/platforms/snes/lib/pvsneslib/source/Makefile +87 -0
- package/src/platforms/snes/lib/pvsneslib/source/backgrounds.asm +834 -0
- package/src/platforms/snes/lib/pvsneslib/source/consoles.asm +1028 -0
- package/src/platforms/snes/lib/pvsneslib/source/crt0_snes.asm +329 -0
- package/src/platforms/snes/lib/pvsneslib/source/dmas.asm +1275 -0
- package/src/platforms/snes/lib/pvsneslib/source/hdr.asm +56 -0
- package/src/platforms/snes/lib/pvsneslib/source/input.asm +445 -0
- package/src/platforms/snes/lib/pvsneslib/source/libc.asm +485 -0
- package/src/platforms/snes/lib/pvsneslib/source/libc_c.c +1214 -0
- package/src/platforms/snes/lib/pvsneslib/source/libm.asm +510 -0
- package/src/platforms/snes/lib/pvsneslib/source/libtcc.asm +374 -0
- package/src/platforms/snes/lib/pvsneslib/source/lzsss.asm +256 -0
- package/src/platforms/snes/lib/pvsneslib/source/maps.asm +1078 -0
- package/src/platforms/snes/lib/pvsneslib/source/objects.asm +2881 -0
- package/src/platforms/snes/lib/pvsneslib/source/scores.asm +226 -0
- package/src/platforms/snes/lib/pvsneslib/source/sm_spc.asm +187 -0
- package/src/platforms/snes/lib/pvsneslib/source/snesmodwla.asm +1186 -0
- package/src/platforms/snes/lib/pvsneslib/source/sounds.asm +273 -0
- package/src/platforms/snes/lib/pvsneslib/source/sprites.asm +3946 -0
- package/src/platforms/snes/lib/pvsneslib/source/vblank.asm +917 -0
- package/src/platforms/snes/lib/pvsneslib/source/videos.asm +1137 -0
- package/src/platforms/snes/lib/reset_init.asm +31 -0
- package/src/platforms/snes/lib/sprite_table_populate.asm +122 -0
- package/src/platforms/snes/lib/vram_dma_upload.asm +42 -0
- package/src/platforms/snes/ppu.js +606 -0
- package/src/platforms/snes/song.js +128 -0
- package/src/playtest/playtest.js +841 -0
- package/src/rom-id/identifier.js +421 -0
- package/src/rom-id/patch.js +217 -0
- package/src/toolchains/_worker/pool.js +253 -0
- package/src/toolchains/_worker/run.js +78 -0
- package/src/toolchains/_worker/wasm-worker.js +233 -0
- package/src/toolchains/arm-none-eabi-gcc/gcc.js +216 -0
- package/src/toolchains/asar/asar.js +542 -0
- package/src/toolchains/assemble-snippet.js +256 -0
- package/src/toolchains/cc65/cc65.js +395 -0
- package/src/toolchains/cc65/da65.js +119 -0
- package/src/toolchains/cc65/dbgparse.js +274 -0
- package/src/toolchains/cc65/preset-resolver.js +59 -0
- package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +79 -0
- package/src/toolchains/cc65/presets/nes/chr-ram-runtime.crt0.s +178 -0
- package/src/toolchains/cc65/presets/nes/chr-ram.cfg +76 -0
- package/src/toolchains/cc65/presets/nes/chr-ram.crt0.s +106 -0
- package/src/toolchains/common/ar.js +121 -0
- package/src/toolchains/common/reassemble.js +353 -0
- package/src/toolchains/common/sdk-cache.js +116 -0
- package/src/toolchains/common/symbols.js +139 -0
- package/src/toolchains/dasm/dasm.js +96 -0
- package/src/toolchains/gba-c/gba-c.js +838 -0
- package/src/toolchains/genesis-c/README.md +61 -0
- package/src/toolchains/genesis-c/genesis-c.js +600 -0
- package/src/toolchains/gnu-ld-map.js +86 -0
- package/src/toolchains/index.js +862 -0
- package/src/toolchains/m68k-elf-gcc/gcc.js +230 -0
- package/src/toolchains/objdump.js +199 -0
- package/src/toolchains/parse-errors.js +338 -0
- package/src/toolchains/registry.js +67 -0
- package/src/toolchains/rgbds/rgbds.js +144 -0
- package/src/toolchains/sdcc/preflight-lint.js +295 -0
- package/src/toolchains/sdcc/sdcc.js +540 -0
- package/src/toolchains/sjasm/sjasm.js +85 -0
- package/src/toolchains/snes-c/snes-c.js +409 -0
- package/src/toolchains/tcc816/tcc816.js +79 -0
- package/src/toolchains/vasm68k/vasm68k.js +138 -0
- package/src/toolchains/wladx/wladx.js +120 -0
- package/src/toolchains/z80/binutils.js +82 -0
|
@@ -0,0 +1,1300 @@
|
|
|
1
|
+
// Platform-aware inspection tools. The MCP surface stays generic — every
|
|
2
|
+
// tool takes a `platform` argument (or auto-detects from the loaded host)
|
|
3
|
+
// and dispatches to the right per-platform decoder under src/platforms/.
|
|
4
|
+
|
|
5
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { PNG } from "pngjs";
|
|
8
|
+
import { getHost } from "../state.js";
|
|
9
|
+
import { imageContent, jsonContent, safeTool, textContent } from "../util.js";
|
|
10
|
+
|
|
11
|
+
// Consolidation: several handlers in this big shared file are extracted as
|
|
12
|
+
// *Core functions that the consolidated domain tools (palette/tiles/background/
|
|
13
|
+
// sprites/audioDebug, defined in their own router files) import + call. They're
|
|
14
|
+
// assigned inside registerPlatformTools (they close over the module-scope
|
|
15
|
+
// helpers) and exported as live bindings. registerPlatformTools must run first.
|
|
16
|
+
export let inspectPaletteCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
17
|
+
export let getPlatformMasterPaletteCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
18
|
+
export let getAudioStateCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
19
|
+
export let inspectSpritesCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
20
|
+
export let inspectBackgroundMapCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
21
|
+
export let inspectPatternTilesCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
22
|
+
export let convertImageToTilesCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
23
|
+
export let imageToTilemapCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
24
|
+
export let getCPUStateCore = async () => { throw new Error("platform-tools cores not initialized — registerPlatformTools must run first"); };
|
|
25
|
+
|
|
26
|
+
// Image-output contract: a PNG image goes to disk (path) OR comes back
|
|
27
|
+
// inline (inline:true). No path + not inline → error. The structured
|
|
28
|
+
// JSON (palette/sprite/tile data) is ALWAYS returned regardless.
|
|
29
|
+
function requireImageTarget(outPath, inline, tool) {
|
|
30
|
+
if (!outPath && !inline) {
|
|
31
|
+
throw new Error(`${tool}: pass outputPath (write the image to disk, returns {imagePath}) or inline:true (return the image in the response).`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
import { getCPUState } from "../../host/cpu-state.js";
|
|
35
|
+
import { getDspState } from "../../host/dsp-state.js";
|
|
36
|
+
import { getNesApuState } from "../../host/nes-apu-state.js";
|
|
37
|
+
import { decodeGenesisPSG, decodeGenesisYM2612 } from "../../host/gpgx-state.js";
|
|
38
|
+
import { decodeGbApu, decodeGbaApu } from "../../host/gb-apu-state.js";
|
|
39
|
+
import { decodeC64Sid } from "../../host/c64-sid-state.js";
|
|
40
|
+
import { decodeLynxMikey, decodeLynxPalette, decodeLynxRenderingContext } from "../../host/lynx-mikey-state.js";
|
|
41
|
+
import { getPcePsgState } from "../../host/pce-psg-state.js";
|
|
42
|
+
import { getMsxAyState } from "../../host/msx-ay-state.js";
|
|
43
|
+
import { decodeGbaSprites, decodeGbaPalette, decodeGbaRenderingContext } from "../../host/gba-video-state.js";
|
|
44
|
+
|
|
45
|
+
/** Resolve the platform to inspect: explicit arg → currently loaded host. */
|
|
46
|
+
function resolvePlatform(host, requested) {
|
|
47
|
+
const p = requested ?? host.status.platform;
|
|
48
|
+
if (!p) throw new Error("no platform specified and no host loaded");
|
|
49
|
+
return p;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function registerPlatformTools(server, z, sessionKey) {
|
|
53
|
+
// inspectPatternTiles lives in the `tiles` tool (tiles({op:'png'}), in
|
|
54
|
+
// tile-inspect.js) now — extracted here as a live-binding core. Reads the
|
|
55
|
+
// running emulator's pattern tables / VRAM (or an iNES file via `path`).
|
|
56
|
+
inspectPatternTilesCore = async ({ platform, path: romPath, bpp = 4, tileBaseByte = 0, paletteBase = 0, paletteIndex = 0, tileCount = 0, scale = 1, outputPath, inline }) => {
|
|
57
|
+
requireImageTarget(outputPath, inline, "inspectPatternTiles");
|
|
58
|
+
// Integer nearest-neighbor upscale of a PNG — keeps pixel-art tiles crisp
|
|
59
|
+
// while making a small tile strip actually readable inline.
|
|
60
|
+
const upscalePng = (pngBuf) => {
|
|
61
|
+
if (!scale || scale <= 1) return pngBuf;
|
|
62
|
+
const src = PNG.sync.read(pngBuf);
|
|
63
|
+
const dst = new PNG({ width: src.width * scale, height: src.height * scale });
|
|
64
|
+
for (let y = 0; y < dst.height; y++) {
|
|
65
|
+
const sy = Math.floor(y / scale);
|
|
66
|
+
for (let x = 0; x < dst.width; x++) {
|
|
67
|
+
const sx = Math.floor(x / scale);
|
|
68
|
+
const si = (sy * src.width + sx) * 4, di = (y * dst.width + x) * 4;
|
|
69
|
+
dst.data[di] = src.data[si]; dst.data[di + 1] = src.data[si + 1];
|
|
70
|
+
dst.data[di + 2] = src.data[si + 2]; dst.data[di + 3] = src.data[si + 3];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return PNG.sync.write(dst);
|
|
74
|
+
};
|
|
75
|
+
// Emit the PNG + structured JSON per the contract: inline returns the
|
|
76
|
+
// image in content[]; otherwise write to disk and return {imagePath}.
|
|
77
|
+
const emit = async (pngBufRaw, structured) => {
|
|
78
|
+
const pngBuf = upscalePng(pngBufRaw);
|
|
79
|
+
if (scale > 1) structured = { ...structured, scale };
|
|
80
|
+
if (inline) {
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
imageContent(pngBuf.toString("base64")),
|
|
84
|
+
{ type: "text", text: JSON.stringify(structured) },
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
await writeFile(outputPath, pngBuf);
|
|
89
|
+
const json = jsonContent({ ...structured, imagePath: outputPath });
|
|
90
|
+
json._observerImages = [{ kind: "image", mimeType: "image/png", base64: pngBuf.toString("base64") }];
|
|
91
|
+
return json;
|
|
92
|
+
};
|
|
93
|
+
// File-source path: read iNES directly from disk.
|
|
94
|
+
if (romPath) {
|
|
95
|
+
const p = platform ?? (/\.nes$/i.test(romPath) ? "nes" : null);
|
|
96
|
+
if (!p) throw new Error("inspectPatternTiles: pass platform explicitly when reading from a non-.nes file.");
|
|
97
|
+
if (p !== "nes") throw new Error(`inspectPatternTiles[file mode]: platform '${p}' not yet supported`);
|
|
98
|
+
const { readFile } = await import("node:fs/promises");
|
|
99
|
+
const bytes = new Uint8Array(await readFile(romPath));
|
|
100
|
+
const { chrFromINes } = await import("../../platforms/nes/ppu.js");
|
|
101
|
+
const { width, height, png, hasChr } = chrFromINes(bytes);
|
|
102
|
+
if (!hasChr) throw new Error(`'${romPath}' is a CHR-RAM cart — no graphics in the ROM file. Load it and call inspectPatternTiles without path.`);
|
|
103
|
+
return emit(png, { platform: p, source: "file", sourcePath: romPath, width, height });
|
|
104
|
+
}
|
|
105
|
+
const host = getHost(sessionKey);
|
|
106
|
+
const p = resolvePlatform(host, platform);
|
|
107
|
+
if (p === "nes") {
|
|
108
|
+
const { snapshotPatternTables } = await import("../../platforms/nes/ppu.js");
|
|
109
|
+
const { width, height, png, source, hasChr } = await snapshotPatternTables(host);
|
|
110
|
+
const note = source === "ines"
|
|
111
|
+
? `CHR pattern tables (${width}×${height}, both 4KB banks). Source: iNES file CHR-ROM bank — these tiles are baked into the ROM and never change at runtime.`
|
|
112
|
+
: hasChr === null
|
|
113
|
+
? `CHR pattern tables (${width}×${height}, live from CHR-RAM). Source: emulator's live CHR-RAM — these change as the game writes to PPU $0000-$1FFF. If you see blank tiles, your game hasn't uploaded tiles yet.`
|
|
114
|
+
: `CHR pattern tables (${width}×${height}, both 4KB banks, live from emulator).`;
|
|
115
|
+
const structuredSource = source === "ines" ? "file" : "emulator";
|
|
116
|
+
return emit(png, { platform: p, source: structuredSource, width, height, note });
|
|
117
|
+
}
|
|
118
|
+
if (p === "sms" || p === "gg") {
|
|
119
|
+
// SMS tiles live in VRAM at runtime — the cart has no fixed CHR
|
|
120
|
+
// region. Render all 448 tiles (the entire 16KB VRAM mapped to
|
|
121
|
+
// tiles), using the live first-BG-palette so colors look right.
|
|
122
|
+
const { snapshotPatternTiles, snapshotPalette } = await import("../../platforms/sms/vdp.js");
|
|
123
|
+
const { colors } = snapshotPalette(host, p);
|
|
124
|
+
// Use BG palette (entries 0..15) for rendering.
|
|
125
|
+
const bgPal = colors.slice(0, 16).map((c) => [c.r, c.g, c.b]);
|
|
126
|
+
const vramRegion = p === "gg" ? "gg_vram" : "sms_vram";
|
|
127
|
+
const vram = host.readMemory(vramRegion, 0, 0x4000);
|
|
128
|
+
const { renderSmsTilesheet } = await import("../../platforms/sms/vdp.js");
|
|
129
|
+
const { width, height, png, tileCount } = renderSmsTilesheet(vram, bgPal);
|
|
130
|
+
return emit(png, {
|
|
131
|
+
platform: p, source: "emulator", width, height, tileCount,
|
|
132
|
+
note: `${tileCount} tiles from 16 KB VRAM (covers tiles + name table + SAT — late ` +
|
|
133
|
+
`tiles will be noise from those regions). For the active BG pattern range, check ` +
|
|
134
|
+
`getRenderingContext().sms.bgTileDataBase.`,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (p === "gb" || p === "gbc") {
|
|
138
|
+
const { snapshotPatternTiles } = await import("../../platforms/gb/ppu.js");
|
|
139
|
+
const { width, height, png, tileCount } = snapshotPatternTiles(host, p);
|
|
140
|
+
return emit(png, {
|
|
141
|
+
platform: p, source: "emulator", width, height, tileCount,
|
|
142
|
+
note: `${tileCount} tiles from VRAM $8000-$97FF (the entire tile region). ` +
|
|
143
|
+
`Active BG/Window/sprite tile data area is selected by LCDC bit 4 — check ` +
|
|
144
|
+
`getRenderingContext().gb.bgTileDataBase.`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (p === "snes") {
|
|
148
|
+
const { renderSnesTilesheet, decodeCGRAM } = await import("../../platforms/snes/ppu.js");
|
|
149
|
+
const vram = host.readMemory("video_ram", 0, 0x10000);
|
|
150
|
+
const cgram = host.readMemory("snes_cgram", 0, 512);
|
|
151
|
+
const colors = decodeCGRAM(cgram);
|
|
152
|
+
const r = renderSnesTilesheet(vram, colors, {
|
|
153
|
+
bpp, tileBaseByte, paletteBase, tileCount: tileCount || undefined,
|
|
154
|
+
});
|
|
155
|
+
return emit(r.png, {
|
|
156
|
+
platform: p, source: "emulator", width: r.width, height: r.height,
|
|
157
|
+
tileCount: r.tileCount, bpp: r.bpp, note: r.note,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (p === "genesis") {
|
|
161
|
+
const { snapshotPatternTiles } = await import("../../platforms/genesis/vdp.js");
|
|
162
|
+
const r = snapshotPatternTiles(host, { paletteIndex, tileCount: tileCount || undefined });
|
|
163
|
+
return emit(r.png, {
|
|
164
|
+
platform: p, source: "emulator", width: r.width, height: r.height,
|
|
165
|
+
tileCount: r.tileCount, paletteIndex: r.paletteIndex, note: r.note,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
throw new Error(`inspectPatternTiles not yet implemented for platform '${p}'`);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// inspectPaletteCore: palette({source:'live'}). Module-scope so the `palette`
|
|
172
|
+
// router (in lospec.js) can import it; takes sessionKey for getHost.
|
|
173
|
+
inspectPaletteCore = async ({ platform, area = "all", subPalette, outputPath, inline }, sessionKey) => {
|
|
174
|
+
const host = getHost(sessionKey);
|
|
175
|
+
const p = resolvePlatform(host, platform);
|
|
176
|
+
requireImageTarget(outputPath, inline, "inspectPalette");
|
|
177
|
+
// NES color-list filter: area (bg/sprite/all) + optional sub-palette.
|
|
178
|
+
// Applied to the JSON list only; the swatch PNG still shows the full set
|
|
179
|
+
// so the visual reference stays complete.
|
|
180
|
+
const filterNesColors = (colors) => {
|
|
181
|
+
if (p !== "nes" || (area === "all" && subPalette == null)) return colors;
|
|
182
|
+
const areaStart = area === "sprite" ? 16 : 0;
|
|
183
|
+
const areaLen = area === "all" ? 32 : 16;
|
|
184
|
+
let slice = colors.slice(areaStart, areaStart + areaLen);
|
|
185
|
+
if (subPalette != null) slice = slice.slice(subPalette * 4, subPalette * 4 + 4);
|
|
186
|
+
return slice;
|
|
187
|
+
};
|
|
188
|
+
// The JSON (colors etc.) is ALWAYS returned; only the swatch PNG is gated.
|
|
189
|
+
const emit = async (structured, pngBuf) => {
|
|
190
|
+
if (inline) {
|
|
191
|
+
return {
|
|
192
|
+
content: [
|
|
193
|
+
{ type: "text", text: JSON.stringify(structured) },
|
|
194
|
+
imageContent(pngBuf.toString("base64")),
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
await writeFile(outputPath, pngBuf);
|
|
199
|
+
const json = jsonContent({ ...structured, imagePath: outputPath });
|
|
200
|
+
json._observerImages = [{ kind: "image", mimeType: "image/png", base64: pngBuf.toString("base64") }];
|
|
201
|
+
return json;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
if (p === "nes") {
|
|
205
|
+
const palette = host.readMemory("nes_palette", 0, 32);
|
|
206
|
+
const { renderPalettePng, paletteToGenericColors } = await import("../../platforms/nes/ppu.js");
|
|
207
|
+
const png = renderPalettePng(palette);
|
|
208
|
+
const colors = filterNesColors(paletteToGenericColors(palette));
|
|
209
|
+
const scope = (area === "all" && subPalette == null)
|
|
210
|
+
? undefined
|
|
211
|
+
: { area, ...(subPalette != null ? { subPalette } : {}) };
|
|
212
|
+
return emit({ platform: p, ...(scope ? { scope } : {}), colors }, png);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (p === "snes") {
|
|
216
|
+
const cgram = host.readMemory("snes_cgram", 0, 512);
|
|
217
|
+
const { decodeCGRAM } = await import("../../platforms/snes/ppu.js");
|
|
218
|
+
const colors = decodeCGRAM(cgram);
|
|
219
|
+
const png = renderColorsAsPng(colors, 16); // 16x16 swatch grid
|
|
220
|
+
return emit({ platform: p, colors }, png);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (p === "genesis") {
|
|
224
|
+
const cram = host.readMemory("genesis_cram", 0, 128);
|
|
225
|
+
const { decodeGenesisCRAM } = await import("../../host/gpgx-state.js");
|
|
226
|
+
const colors = decodeGenesisCRAM(cram);
|
|
227
|
+
// 4 palettes × 16 entries = 64 colors; render as 4 rows of 16.
|
|
228
|
+
const png = renderColorsAsPng(colors, 16);
|
|
229
|
+
// CRAM is a flat 64-entry list; the VDP (and SGDK) address it as four
|
|
230
|
+
// 16-color sub-palettes. Group it so the agent doesn't have to guess
|
|
231
|
+
// which flat index its PALn lives at when calling inspectPatternTiles.
|
|
232
|
+
const subPalettes = [0, 1, 2, 3].map((n) => ({
|
|
233
|
+
index: n,
|
|
234
|
+
sgdkName: `PAL${n}`,
|
|
235
|
+
cramRange: [n * 16, n * 16 + 15],
|
|
236
|
+
colors: colors.slice(n * 16, n * 16 + 16),
|
|
237
|
+
}));
|
|
238
|
+
return emit({
|
|
239
|
+
platform: p,
|
|
240
|
+
colors,
|
|
241
|
+
subPalettes,
|
|
242
|
+
note: "Genesis CRAM = 4 sub-palettes × 16 colors. Flat index → sub-palette: 0-15=PAL0, 16-31=PAL1, 32-47=PAL2, 48-63=PAL3. Pass the sub-palette NUMBER (0-3) as inspectPatternTiles({paletteIndex}).",
|
|
243
|
+
}, png);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (p === "sms" || p === "gg") {
|
|
247
|
+
const { snapshotPalette } = await import("../../platforms/sms/vdp.js");
|
|
248
|
+
const { colors, png } = snapshotPalette(host, p);
|
|
249
|
+
return emit({ platform: p, colors }, png);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (p === "gb" || p === "gbc") {
|
|
253
|
+
const { snapshotPalette } = await import("../../platforms/gb/ppu.js");
|
|
254
|
+
const { colors, png, raw } = snapshotPalette(host, p);
|
|
255
|
+
return emit({ platform: p, colors, raw }, png);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (p === "atari2600") {
|
|
259
|
+
const { snapshotPaletteSwatch } = await import("../../platforms/atari2600/tia.js");
|
|
260
|
+
const { colors, png } = snapshotPaletteSwatch(host);
|
|
261
|
+
return emit({ platform: p, colors,
|
|
262
|
+
note: "2600 has only 4 active colors at any moment (P0/P1/PF/BK). The TIA color regs change frequently as the kernel races the beam — this is a snapshot of the current state, NOT the full frame's colors." }, png);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (p === "atari7800") {
|
|
266
|
+
const { snapshotPalette } = await import("../../platforms/atari7800/maria.js");
|
|
267
|
+
const { colors, png, regs } = snapshotPalette(host);
|
|
268
|
+
return emit({ platform: p, colors, mariaRegs: regs }, png);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (p === "c64") {
|
|
272
|
+
const { snapshotPalette } = await import("../../platforms/c64/vic.js");
|
|
273
|
+
const { colors, png, current } = snapshotPalette(host);
|
|
274
|
+
return emit({
|
|
275
|
+
platform: p, colors, current,
|
|
276
|
+
note: "C64 palette is hardware-fixed (16 colors). `current` shows which indices the VIC-II is using right now for border/background/extra-bg. Programs can only choose indices, not RGB.",
|
|
277
|
+
}, png);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (p === "gba") {
|
|
281
|
+
// 256 BG + 256 OBJ entries, 15-bit BGR. Render both as a 16-wide grid.
|
|
282
|
+
const pal = host.readMemory("gba_palette", 0, 0x400);
|
|
283
|
+
const which = (area === "sprite") ? "obj" : (area === "bg") ? "bg" : "all";
|
|
284
|
+
const { entries } = decodeGbaPalette(pal, which);
|
|
285
|
+
const colors = entries.map((e) => ({ r: e.r, g: e.g, b: e.b, hex: e.hex, index: e.index, set: e.set }));
|
|
286
|
+
const png = renderColorsAsPng(colors, 16);
|
|
287
|
+
return emit({
|
|
288
|
+
platform: p,
|
|
289
|
+
colors,
|
|
290
|
+
note: "GBA palette: 256 BG entries (indices 0-255) + 256 OBJ entries (256-511), 15-bit BGR555. " +
|
|
291
|
+
"Each entry's `set` is 'bg' or 'obj'. Use area:'bg' or area:'sprite' to return just one bank.",
|
|
292
|
+
}, png);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (p === "lynx") {
|
|
296
|
+
// Mikey 16-entry 12-bit palette from the $FC00-$FDFF HW window.
|
|
297
|
+
const hw = host.readMemory("lynx_hw_regs", 0, 0x200);
|
|
298
|
+
const { entries } = decodeLynxPalette(hw);
|
|
299
|
+
const colors = entries.map((e) => ({ r: e.r, g: e.g, b: e.b, hex: e.hex, index: e.index }));
|
|
300
|
+
const png = renderColorsAsPng(colors, 16);
|
|
301
|
+
return emit({
|
|
302
|
+
platform: p,
|
|
303
|
+
colors,
|
|
304
|
+
note: "Lynx Mikey palette: 16 entries, 12-bit (4 bits each G/R/B) from $FDA0 (green) + $FDB0 (blue/red).",
|
|
305
|
+
}, png);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (p === "pce") {
|
|
309
|
+
// HuC6260 VCE: 512-entry 9-bit GRB table (256 BG + 256 SPR).
|
|
310
|
+
const pal = host.readMemory("pce_vce_palette", 0, 1024);
|
|
311
|
+
const { decodeVcePalette } = await import("../../platforms/pce/vce.js");
|
|
312
|
+
const which = (area === "sprite") ? "sprite" : (area === "bg") ? "bg" : "all";
|
|
313
|
+
const { entries } = decodeVcePalette(pal, which);
|
|
314
|
+
const colors = entries.map((e) => ({ r: e.r, g: e.g, b: e.b, hex: e.hex, index: e.index, set: e.set, subPalette: e.subPalette, slot: e.slot }));
|
|
315
|
+
const png = renderColorsAsPng(colors, 16);
|
|
316
|
+
return emit({
|
|
317
|
+
platform: p,
|
|
318
|
+
colors,
|
|
319
|
+
note: "PC Engine VCE: 512 colors = 16 BG sub-palettes (indices 0-255) + 16 SPR sub-palettes (256-511), each 16 colors, 9-bit GRB. Slot 0 of each 16 = transparent/backdrop. Pass `area:'bg'|'sprite'` to narrow; `subPalette` (0-15) selects a row.",
|
|
320
|
+
}, png);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (p === "msx") {
|
|
324
|
+
// V9938 paletteReg on MSX2 bitmap modes; fixed TMS9918 on MSX1 modes.
|
|
325
|
+
const palBytes = host.readMemory("msx_palette", 0, 32);
|
|
326
|
+
const regs = host.readMemory("msx_vdp_regs", 0, 64);
|
|
327
|
+
const { decodeMsxPalette, isV9938Mode } = await import("../../platforms/msx/vdp.js");
|
|
328
|
+
const { entries, source } = decodeMsxPalette(palBytes, isV9938Mode(regs));
|
|
329
|
+
const colors = entries.map((e) => ({ r: e.r, g: e.g, b: e.b, hex: e.hex, index: e.index }));
|
|
330
|
+
const png = renderColorsAsPng(colors, 16);
|
|
331
|
+
return emit({
|
|
332
|
+
platform: p,
|
|
333
|
+
colors,
|
|
334
|
+
paletteSource: source,
|
|
335
|
+
note: source === "v9938"
|
|
336
|
+
? "MSX V9938 programmable palette: 16 entries, 9-bit GRB. Active because the VDP is in an MSX2 bitmap mode (screen 4+)."
|
|
337
|
+
: "MSX1 TMS9918 fixed palette: 16 hardware colors (programs choose indices, not RGB). The V9938 paletteReg is only used in MSX2 bitmap modes.",
|
|
338
|
+
}, png);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
throw new Error(`inspectPalette not yet wired for platform '${p}'. Supported: nes, snes, genesis, sms, gg, gb, gbc, atari2600, atari7800, c64, gba, lynx, pce, msx.`);
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// getCPUState → cpu({op:'read'}) (router in watch-memory.js). Live-binding core.
|
|
345
|
+
getCPUStateCore = async ({ platform, cpu = "main" }) => {
|
|
346
|
+
const host = getHost(sessionKey);
|
|
347
|
+
const p = resolvePlatform(host, platform);
|
|
348
|
+
const state = getCPUState(host, p, cpu);
|
|
349
|
+
if (!state) {
|
|
350
|
+
throw new Error(`getCPUState: no decoder for platform '${p}' cpu '${cpu}'. Main CPU is wired for nes, snes, genesis, sms, gg, gb, gbc, atari2600, atari7800, c64, lynx, gba. Secondary CPUs: snes 'spc700' (genesis 'z80' not yet decoded).`);
|
|
351
|
+
}
|
|
352
|
+
return jsonContent({ platform: p, cpu, ...state });
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// ── getAudioState — unified sound-chip introspection ──────────────
|
|
356
|
+
// One tool, `chip` enum discriminator (mirrors getCPUState({cpu})).
|
|
357
|
+
// Subsumes the old getDspState / getPsgState / getYm2612State, which
|
|
358
|
+
// remain as thin deprecated aliases below for back-compat.
|
|
359
|
+
/** Run the chip decoder for one chip; returns the structured JSON object. */
|
|
360
|
+
function readAudioChip(chip) {
|
|
361
|
+
const host = getHost(sessionKey);
|
|
362
|
+
if (chip === "dsp") {
|
|
363
|
+
const p = resolvePlatform(host, "snes");
|
|
364
|
+
const dsp = getDspState(host, p);
|
|
365
|
+
if (!dsp) throw new Error("getAudioState chip:'dsp' is SNES only.");
|
|
366
|
+
const { regs, ...rest } = dsp;
|
|
367
|
+
return { platform: p, chip, ...rest, regsHex: Array.from(regs, (b) => b.toString(16).padStart(2, "0")).join("") };
|
|
368
|
+
}
|
|
369
|
+
if (chip === "ym2612") {
|
|
370
|
+
const blob = host.readMemory("genesis_ym2612", 0, 4096);
|
|
371
|
+
return { platform: "genesis", chip, ...decodeGenesisYM2612(blob) };
|
|
372
|
+
}
|
|
373
|
+
if (chip === "psg") {
|
|
374
|
+
// SN76489 — gpgx runs Genesis AND SMS/GG, and exposes the PSG via the
|
|
375
|
+
// same gpgx-internal region regardless of which is loaded, so chip:'psg'
|
|
376
|
+
// works for all three. Report the actual loaded platform.
|
|
377
|
+
const p = resolvePlatform(host);
|
|
378
|
+
const blob = host.readMemory("genesis_psg", 0, 1024);
|
|
379
|
+
return { platform: (p === "sms" || p === "gg") ? p : "genesis", chip, ...decodeGenesisPSG(blob) };
|
|
380
|
+
}
|
|
381
|
+
if (chip === "nes") {
|
|
382
|
+
const p = resolvePlatform(host, "nes");
|
|
383
|
+
const apu = getNesApuState(host, p);
|
|
384
|
+
if (!apu) throw new Error("getAudioState chip:'nes' is NES only.");
|
|
385
|
+
return { platform: p, chip, ...apu };
|
|
386
|
+
}
|
|
387
|
+
if (chip === "gb") {
|
|
388
|
+
// GB/GBC DMG APU — read the APU register file from gb_io ($FF00-$FF7F).
|
|
389
|
+
const p = resolvePlatform(host);
|
|
390
|
+
if (p !== "gb" && p !== "gbc") throw new Error("getAudioState chip:'gb' is for Game Boy / Game Boy Color only.");
|
|
391
|
+
const io = host.readMemory("gb_io", 0, 0x80);
|
|
392
|
+
return { platform: p, chip, ...decodeGbApu(io) };
|
|
393
|
+
}
|
|
394
|
+
if (chip === "gba") {
|
|
395
|
+
// GBA APU — the IO page carries the 4 DMG PSG channels + 2 DMA FIFO channels.
|
|
396
|
+
const io = host.readMemory("gba_io_regs", 0, 0x400);
|
|
397
|
+
return { platform: "gba", chip, ...decodeGbaApu(io) };
|
|
398
|
+
}
|
|
399
|
+
if (chip === "sid") {
|
|
400
|
+
// C64 SID (6581/8580) — 3 voices + filter, from c64_sid_regs ($D400-$D41C).
|
|
401
|
+
const regs = host.readMemory("c64_sid_regs", 0, 29);
|
|
402
|
+
return { platform: "c64", chip, ...decodeC64Sid(regs) };
|
|
403
|
+
}
|
|
404
|
+
if (chip === "mikey") {
|
|
405
|
+
// Lynx Mikey — 4 audio channels, from the $FC00-$FDFF HW window.
|
|
406
|
+
const hw = host.readMemory("lynx_hw_regs", 0, 0x200);
|
|
407
|
+
return { platform: "lynx", chip, ...decodeLynxMikey(hw) };
|
|
408
|
+
}
|
|
409
|
+
if (chip === "pce") {
|
|
410
|
+
// PC Engine HuC6280 PSG — 6 wavetable channels (ch 4/5 can do noise).
|
|
411
|
+
const psg = getPcePsgState(host);
|
|
412
|
+
if (!psg) throw new Error("getAudioState chip:'pce' — no PSG region (load a PCE ROM into the patched geargrafx core).");
|
|
413
|
+
return { platform: "pce", ...psg };
|
|
414
|
+
}
|
|
415
|
+
if (chip === "ay8910") {
|
|
416
|
+
// MSX AY-3-8910 — 3 square + noise + envelope.
|
|
417
|
+
const ay = getMsxAyState(host);
|
|
418
|
+
if (!ay) throw new Error("getAudioState chip:'ay8910' — no PSG region (load an MSX ROM into the patched blueMSX core).");
|
|
419
|
+
return { platform: "msx", ...ay };
|
|
420
|
+
}
|
|
421
|
+
throw new Error(`getAudioState: unknown chip '${chip}'. Use 'nes' (NES 2A03), 'gb' (Game Boy/GBC), 'gba' (GBA), 'dsp' (SNES), 'psg' (Genesis/SMS/GG SN76489), 'ym2612' (Genesis FM), 'sid' (C64), or 'mikey' (Lynx).`);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
getAudioStateCore = async ({ chip }) => jsonContent(readAudioChip(chip));
|
|
425
|
+
|
|
426
|
+
// inspectSprites lives in the `sprites` tool (metasprite-tools.js) now —
|
|
427
|
+
// extracted here as a live-binding core so the router can call it without
|
|
428
|
+
// disturbing the other handlers registerPlatformTools owns.
|
|
429
|
+
inspectSpritesCore = async ({ platform, maxSlots, slots, outputPath, inline }) => {
|
|
430
|
+
const host = getHost(sessionKey);
|
|
431
|
+
const p = resolvePlatform(host, platform);
|
|
432
|
+
// Generic slot filter, applied by each platform branch before returning.
|
|
433
|
+
// `slots` (explicit index list) wins over `maxSlots` (first N); the
|
|
434
|
+
// returned sprites keep their original .slot field so indices stay honest.
|
|
435
|
+
const slotSet = slots != null ? new Set(slots) : null;
|
|
436
|
+
const clampSlots = (sprites) => {
|
|
437
|
+
const slotsTotal = sprites.length;
|
|
438
|
+
let clipped;
|
|
439
|
+
if (slotSet) clipped = sprites.filter((s, i) => slotSet.has(s.slot ?? i));
|
|
440
|
+
else if (maxSlots != null) clipped = sprites.slice(0, maxSlots);
|
|
441
|
+
else clipped = sprites;
|
|
442
|
+
return { sprites: clipped, slotsTotal, slotsReturned: clipped.length };
|
|
443
|
+
};
|
|
444
|
+
// Gate the PNG for platforms that render one. JSON is always returned.
|
|
445
|
+
const emitImage = async (pngBuf, structured) => {
|
|
446
|
+
requireImageTarget(outputPath, inline, "inspectSprites");
|
|
447
|
+
if (inline) {
|
|
448
|
+
return {
|
|
449
|
+
content: [
|
|
450
|
+
imageContent(pngBuf.toString("base64")),
|
|
451
|
+
{ type: "text", text: JSON.stringify(structured) },
|
|
452
|
+
],
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
await writeFile(outputPath, pngBuf);
|
|
456
|
+
const json = jsonContent({ ...structured, imagePath: outputPath });
|
|
457
|
+
json._observerImages = [{ kind: "image", mimeType: "image/png", base64: pngBuf.toString("base64") }];
|
|
458
|
+
return json;
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
if (p === "nes") {
|
|
462
|
+
const oam = host.readMemory("nes_oam", 0, 256);
|
|
463
|
+
const sprites = [];
|
|
464
|
+
for (let i = 0; i < 64; i++) {
|
|
465
|
+
const o = i * 4;
|
|
466
|
+
const y = oam[o + 0];
|
|
467
|
+
const tile = oam[o + 1];
|
|
468
|
+
const attr = oam[o + 2];
|
|
469
|
+
const x = oam[o + 3];
|
|
470
|
+
sprites.push({
|
|
471
|
+
slot: i,
|
|
472
|
+
x, y, tile,
|
|
473
|
+
palette: attr & 0x3,
|
|
474
|
+
priority: (attr >> 5) & 0x1, // NES is 1-bit priority
|
|
475
|
+
flipH: !!((attr >> 6) & 0x1),
|
|
476
|
+
flipV: !!((attr >> 7) & 0x1),
|
|
477
|
+
size: { w: 8, h: 8 }, // NES sprites are 8x8 or 8x16 (PPUCTRL bit) — default to 8x8
|
|
478
|
+
visible: y < 0xF0,
|
|
479
|
+
raw: { byte0: y, byte1: tile, byte2: attr, byte3: x },
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
return jsonContent({ platform: p, ...clampSlots(sprites) });
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (p === "snes") {
|
|
486
|
+
const oam = host.readMemory("snes_oam", 0, 544);
|
|
487
|
+
const fillram = host.readMemory("snes_fillram", 0, 0x8000);
|
|
488
|
+
const cgram = host.readMemory("snes_cgram", 0, 512);
|
|
489
|
+
const { decodeOAM, decodePpuRegs, ppuRegsPopulated, decodeCGRAM, checkObjPalettes } =
|
|
490
|
+
await import("../../platforms/snes/ppu.js");
|
|
491
|
+
// snes9x mirrors $2100-$213f into FillRAM (by full reg address), so we
|
|
492
|
+
// can read OBSEL and resolve real OBJ size + tile-base addressing.
|
|
493
|
+
const regsLive = ppuRegsPopulated(fillram);
|
|
494
|
+
const ppu = regsLive ? decodePpuRegs(fillram) : null;
|
|
495
|
+
const sprites = decodeOAM(oam, ppu ? {
|
|
496
|
+
smallSize: ppu.objSize.small,
|
|
497
|
+
largeSize: ppu.objSize.large,
|
|
498
|
+
objNameBaseByte: ppu.objNameBaseByte,
|
|
499
|
+
objGapByte: ppu.objGapByte,
|
|
500
|
+
} : {});
|
|
501
|
+
const colors = decodeCGRAM(cgram);
|
|
502
|
+
const { uninitializedPalettes, suspiciousPalettes, paletteReport, warnings } =
|
|
503
|
+
checkObjPalettes(sprites, colors);
|
|
504
|
+
const renderableCount = sprites.filter((s) => s.renderable).length;
|
|
505
|
+
const summary = [
|
|
506
|
+
`${renderableCount} of 128 OBJ slots are renderable on-screen` +
|
|
507
|
+
` (the other ${128 - renderableCount} are parked off-screen/hidden — not drawn).`,
|
|
508
|
+
regsLive
|
|
509
|
+
? `OBSEL=$${ppu.obsel.toString(16)}: OBJ size pair ${JSON.stringify(ppu.objSize.small)}/` +
|
|
510
|
+
`${JSON.stringify(ppu.objSize.large)}, OBJ tile base VRAM 0x${ppu.objNameBaseByte.toString(16)}, ` +
|
|
511
|
+
`OBJ layer ${ppu.mainScreen.obj ? "ENABLED" : "DISABLED"} on main screen (TM=$${ppu.tm.toString(16)}). ` +
|
|
512
|
+
`Each sprite's tileVramAddr + cgramPaletteRange are resolved from this.`
|
|
513
|
+
: `PPU registers not yet populated (step more frames before trusting OBJ size/base — ` +
|
|
514
|
+
`sizes assume the {8×8,16×16} default and tileVramAddr is null).`,
|
|
515
|
+
];
|
|
516
|
+
if (warnings.length) summary.push(...warnings);
|
|
517
|
+
// Clamp only the per-sprite list; renderableCount/warnings stay
|
|
518
|
+
// computed over all 128 slots so the summary remains accurate.
|
|
519
|
+
const { sprites: spritesOut, slotsTotal, slotsReturned } = clampSlots(sprites);
|
|
520
|
+
return jsonContent({
|
|
521
|
+
platform: p,
|
|
522
|
+
sprites: spritesOut,
|
|
523
|
+
slotsTotal,
|
|
524
|
+
slotsReturned,
|
|
525
|
+
renderableCount,
|
|
526
|
+
ppuRegsLive: regsLive,
|
|
527
|
+
ppu: ppu && {
|
|
528
|
+
obsel: ppu.obsel, objSize: ppu.objSize, objNameBaseByte: ppu.objNameBaseByte,
|
|
529
|
+
mainScreenObjEnabled: ppu.mainScreen.obj, tm: ppu.tm, ts: ppu.ts,
|
|
530
|
+
},
|
|
531
|
+
uninitializedObjPalettes: uninitializedPalettes,
|
|
532
|
+
suspiciousObjPalettes: suspiciousPalettes,
|
|
533
|
+
objPaletteReport: paletteReport,
|
|
534
|
+
warnings,
|
|
535
|
+
summary,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (p === "genesis") {
|
|
540
|
+
const vram = host.readMemory("video_ram", 0, 65536);
|
|
541
|
+
const vdpRegs = host.readMemory("genesis_vdp_regs", 0, 32);
|
|
542
|
+
const { decodeGenesisSprites } = await import("../../host/gpgx-state.js");
|
|
543
|
+
const sprites = decodeGenesisSprites(vram, vdpRegs);
|
|
544
|
+
return jsonContent({ platform: p, sprites });
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (p === "sms" || p === "gg") {
|
|
548
|
+
const { snapshotSprites } = await import("../../platforms/sms/vdp.js");
|
|
549
|
+
const snap = snapshotSprites(host, p);
|
|
550
|
+
return emitImage(snap.png, {
|
|
551
|
+
platform: p,
|
|
552
|
+
sprites: snap.sprites,
|
|
553
|
+
vdp: snap.vdp,
|
|
554
|
+
spriteHeight: snap.spriteHeight,
|
|
555
|
+
width: snap.width,
|
|
556
|
+
height: snap.height,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (p === "gb" || p === "gbc") {
|
|
561
|
+
const { snapshotSprites } = await import("../../platforms/gb/ppu.js");
|
|
562
|
+
const snap = snapshotSprites(host, p);
|
|
563
|
+
return emitImage(snap.png, {
|
|
564
|
+
platform: p,
|
|
565
|
+
sprites: snap.sprites,
|
|
566
|
+
lcdc: snap.lcdc,
|
|
567
|
+
spriteHeight: snap.spriteHeight,
|
|
568
|
+
width: snap.width,
|
|
569
|
+
height: snap.height,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (p === "atari2600") {
|
|
574
|
+
// 2600 has no traditional "sprite list" — instead the TIA holds 5
|
|
575
|
+
// graphics objects (P0/P1/M0/M1/Ball) whose state we sample. The
|
|
576
|
+
// kernel re-positions them per-scanline; this is a snapshot.
|
|
577
|
+
const { snapshotTia, snapshotScanline } = await import("../../platforms/atari2600/tia.js");
|
|
578
|
+
const tia = snapshotTia(host);
|
|
579
|
+
const scan = snapshotScanline(host);
|
|
580
|
+
return emitImage(scan.png, {
|
|
581
|
+
platform: p,
|
|
582
|
+
note: scan.note,
|
|
583
|
+
sprites: [
|
|
584
|
+
{ name: "player0", ...tia.sprites.p0, color: tia.colors.p0 },
|
|
585
|
+
{ name: "player1", ...tia.sprites.p1, color: tia.colors.p1 },
|
|
586
|
+
{ name: "missile0", ...tia.sprites.missile0, color: tia.colors.p0 },
|
|
587
|
+
{ name: "missile1", ...tia.sprites.missile1, color: tia.colors.p1 },
|
|
588
|
+
{ name: "ball", ...tia.sprites.ball, color: tia.colors.pf },
|
|
589
|
+
],
|
|
590
|
+
playfield: tia.playfield,
|
|
591
|
+
ctrlpf: tia.ctrlpf,
|
|
592
|
+
nusiz0: tia.nusiz0,
|
|
593
|
+
nusiz1: tia.nusiz1,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (p === "atari7800") {
|
|
598
|
+
// 7800 sprites are driven by MARIA's display list, which lives in
|
|
599
|
+
// RAM at addresses chosen by the game — there's no fixed OAM. We
|
|
600
|
+
// return MARIA regs (background, 8 palettes, control) so the
|
|
601
|
+
// agent can locate the display list via DPP and parse from there.
|
|
602
|
+
const { snapshotPalette } = await import("../../platforms/atari7800/maria.js");
|
|
603
|
+
const { regs, png } = snapshotPalette(host);
|
|
604
|
+
const ram = host.readMemory("system_ram", 0x0080, 0x10);
|
|
605
|
+
const dpp = ram[0x04] | (ram[0x05] << 8); // DPPH/DPPL at $84/$85
|
|
606
|
+
return emitImage(png, {
|
|
607
|
+
platform: p,
|
|
608
|
+
note: "7800 has no fixed OAM. MARIA reads a display list from RAM (pointed at by DPP at $84/$85) each scanline — each entry describes one drawable. To enumerate sprites for the current frame, parse the DL starting at the dpp address. This snapshot shows MARIA's control regs + palette state.",
|
|
609
|
+
dpp: "0x" + dpp.toString(16).toUpperCase().padStart(4, "0"),
|
|
610
|
+
maria: regs,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (p === "c64") {
|
|
615
|
+
const { snapshotSprites } = await import("../../platforms/c64/vic.js");
|
|
616
|
+
const { sprites, vic } = snapshotSprites(host);
|
|
617
|
+
// Sprite pixel-data pointers live at screen[$3F8 + N] × 64. Read
|
|
618
|
+
// them from current screen RAM so the agent can locate sprite art.
|
|
619
|
+
const screenRamBase = parseInt(vic.memPointers.screenRamBaseInVicBank.replace("$", ""), 16);
|
|
620
|
+
const ram = host.readMemory("system_ram", screenRamBase + 0x3F8, 8);
|
|
621
|
+
const spriteDataPointers = Array.from(ram, (b, i) => ({
|
|
622
|
+
slot: i,
|
|
623
|
+
pointerByte: b,
|
|
624
|
+
dataAddr: "$" + (b * 64).toString(16).toUpperCase().padStart(4, "0"),
|
|
625
|
+
dataAddrDec: b * 64,
|
|
626
|
+
}));
|
|
627
|
+
return {
|
|
628
|
+
content: [
|
|
629
|
+
{ type: "text", text: JSON.stringify({
|
|
630
|
+
platform: p, sprites, vic, spriteDataPointers,
|
|
631
|
+
note: "VIC-II has 8 hardware sprites (MOBs). Sprite pixel data lives in main RAM at (screen[$3F8 + N] × 64). spriteDataPointers gives you the address for each.",
|
|
632
|
+
}) },
|
|
633
|
+
],
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (p === "gba") {
|
|
638
|
+
// 128 OAM sprites × 8 bytes, decoded to the normalized shape.
|
|
639
|
+
const oam = host.readMemory("gba_oam", 0, 0x400);
|
|
640
|
+
const { sprites } = decodeGbaSprites(oam, {});
|
|
641
|
+
return jsonContent({ platform: p, ...clampSlots(sprites) });
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (p === "lynx") {
|
|
645
|
+
// Lynx has NO fixed OAM: sprites are SCB (Sprite Control Block) linked
|
|
646
|
+
// lists walked from a RAM address (the engine follows SCBNEXT). There is
|
|
647
|
+
// no hardware sprite table to enumerate at rest, so we cannot return a
|
|
648
|
+
// generic OAM list. Point the agent at the SCB-walk approach instead.
|
|
649
|
+
const hw = host.readMemory("lynx_hw_regs", 0, 0x200);
|
|
650
|
+
const scbnext = hw[0x010] | (hw[0x011] << 8); // SUZY SCBNEXT $FC10/$FC11
|
|
651
|
+
return jsonContent({
|
|
652
|
+
platform: p,
|
|
653
|
+
sprites: [],
|
|
654
|
+
scbListHead: "$" + scbnext.toString(16).toUpperCase().padStart(4, "0"),
|
|
655
|
+
note: "Lynx has no fixed OAM — sprites are SCB (Sprite Control Block) linked lists in main RAM, " +
|
|
656
|
+
"walked by Suzy from the SCBNEXT pointer ($FC10/$FC11, shown as scbListHead). To enumerate sprites, " +
|
|
657
|
+
"read system_ram starting at scbListHead and follow each SCB's next-pointer: each SCB begins with " +
|
|
658
|
+
"SPRCTL0 (type/flip/bpp), SPRCTL1, collision#, then the next-SCB pointer, sprite-data pointer, and " +
|
|
659
|
+
"H/V position + size. The list ends when the next-pointer's high byte is 0. (scbListHead is whatever " +
|
|
660
|
+
"the game last wrote before SPRGO; it may be stale between frames.)",
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (p === "pce") {
|
|
665
|
+
// HuC6270 SATB: 64 sprites × 4 u16. JSON-only.
|
|
666
|
+
const satb = host.readMemory("pce_vdc_satb", 0, 512);
|
|
667
|
+
const { decodeSatb } = await import("../../platforms/pce/vdc.js");
|
|
668
|
+
const sprites = decodeSatb(satb);
|
|
669
|
+
return jsonContent({
|
|
670
|
+
platform: p,
|
|
671
|
+
...clampSlots(sprites),
|
|
672
|
+
note: "PC Engine SATB: 64 sprites, 16/32 wide × 16/32/64 tall. `tile` is the pattern code (16×16 cells in VRAM). `palette` 0-15 indexes the 16 SPR sub-palettes (palette({source:'live'}) area:'sprite'). priority bit = in-front-of-BG.",
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if (p === "msx") {
|
|
677
|
+
// V9938/TMS9918 sprite-attribute table lives in VRAM at the R5/R11 base.
|
|
678
|
+
const vram = host.readMemory("msx_vram", 0, host.regionSize("msx_vram"));
|
|
679
|
+
const regs = host.readMemory("msx_vdp_regs", 0, 64);
|
|
680
|
+
const { decodeMsxSprites, spriteAttrBase } = await import("../../platforms/msx/vdp.js");
|
|
681
|
+
const sprites = decodeMsxSprites(vram, regs);
|
|
682
|
+
return jsonContent({
|
|
683
|
+
platform: p,
|
|
684
|
+
...clampSlots(sprites),
|
|
685
|
+
satBase: "$" + spriteAttrBase(regs).toString(16),
|
|
686
|
+
note: "MSX sprites: up to 32, read from the VRAM sprite-attribute table (base from VDP R5/R11). Y=208 ($D0) terminates the active list. MSX sprites have no flip bits; priority is by slot order (slot 0 = frontmost). `palette` is the color nibble (TMS9918) or palette index (V9938).",
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
throw new Error(`inspectSprites not yet wired for platform '${p}'. Supported: nes, snes, genesis, sms, gg, gb, gbc, atari2600, atari7800, c64, gba, pce, msx. (Lynx returns the SCB list head — it has no fixed OAM.)`);
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// inspectBackgroundMap lives in the `background` tool (rendering-context.js)
|
|
694
|
+
// now — extracted here as a live-binding core so the router can call it
|
|
695
|
+
// without disturbing the other handlers registerPlatformTools owns.
|
|
696
|
+
inspectBackgroundMapCore = async ({ platform, render, region, attributesOnly, tilesOnly, which, window, plane, tilemapBaseByte, tileBaseByte, bpp, mapWidth, mapHeight, outputPath, inline }) => {
|
|
697
|
+
const host = getHost(sessionKey);
|
|
698
|
+
const p = resolvePlatform(host, platform);
|
|
699
|
+
if (attributesOnly && tilesOnly) {
|
|
700
|
+
throw new Error("inspectBackgroundMap: attributesOnly and tilesOnly are mutually exclusive — omit both to get tiles + subPaletteGrid together.");
|
|
701
|
+
}
|
|
702
|
+
// Gate the PNG; the textual note travels alongside it. Used by every
|
|
703
|
+
// image-producing path. NES render:false stays JSON-only (no image).
|
|
704
|
+
const emitImage = async (pngBuf, note) => {
|
|
705
|
+
requireImageTarget(outputPath, inline, "inspectBackgroundMap");
|
|
706
|
+
if (inline) {
|
|
707
|
+
return {
|
|
708
|
+
content: [
|
|
709
|
+
imageContent(pngBuf.toString("base64")),
|
|
710
|
+
{ type: "text", text: note },
|
|
711
|
+
],
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
await writeFile(outputPath, pngBuf);
|
|
715
|
+
const json = jsonContent({ platform: p, imagePath: outputPath, note });
|
|
716
|
+
json._observerImages = [{ kind: "image", mimeType: "image/png", base64: pngBuf.toString("base64") }];
|
|
717
|
+
return json;
|
|
718
|
+
};
|
|
719
|
+
if (p === "nes") {
|
|
720
|
+
if (render) {
|
|
721
|
+
const { snapshotNametable } = await import("../../platforms/nes/ppu.js");
|
|
722
|
+
const png = snapshotNametable(host, { which });
|
|
723
|
+
return emitImage(png, `Background composite (nametable ${which}, 256×240).`);
|
|
724
|
+
}
|
|
725
|
+
// render:false → DECODED structured data (tiles grid + per-tile
|
|
726
|
+
// sub-palette grid decoded from the attribute table + distinct tiles),
|
|
727
|
+
// so the agent never slices CIRAM or hand-decodes the 2-bit attr format.
|
|
728
|
+
const { decodeNametable } = await import("../../platforms/nes/ppu.js");
|
|
729
|
+
const ciram = host.readMemory("nes_nametables", 0, 2048);
|
|
730
|
+
const dec = decodeNametable(ciram, { which, region });
|
|
731
|
+
const base = { platform: p, which, region: dec.region };
|
|
732
|
+
// tilesOnly: just the tile-index grid (+ distinctTiles) — the cheapest
|
|
733
|
+
// "what tiles are here?" read, no attribute annotation.
|
|
734
|
+
if (tilesOnly) {
|
|
735
|
+
return jsonContent({
|
|
736
|
+
...base,
|
|
737
|
+
tiles: dec.tiles,
|
|
738
|
+
distinctTiles: dec.distinctTiles,
|
|
739
|
+
note: "tilesOnly: tile indices for the region. Re-call with attributesOnly:true (or neither flag) to also get the per-tile subPaletteGrid.",
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
// attrTableHex is the FULL 64-byte attribute table for the nametable —
|
|
743
|
+
// one byte covers a 32×32px (4×4-tile) area, so it can't be cleanly
|
|
744
|
+
// sliced to an arbitrary region. subPaletteGrid IS region-clipped (and
|
|
745
|
+
// is what you actually want); attrTableHex is labeled as the raw table.
|
|
746
|
+
const common = {
|
|
747
|
+
...base,
|
|
748
|
+
subPaletteGrid: dec.subPaletteGrid,
|
|
749
|
+
attrTableFullHex: dec.attrTableHex,
|
|
750
|
+
note: "subPaletteGrid[row][col] = BG sub-palette 0-3 per tile in the requested region (decoded from the attribute table). On NES, palette indices for sub-palette N are nes_palette[N*4 .. N*4+3]. attrTableFullHex is the raw 64-byte attribute table for the WHOLE nametable (not region-clipped — one byte spans a 4×4-tile area).",
|
|
751
|
+
};
|
|
752
|
+
if (attributesOnly) {
|
|
753
|
+
return jsonContent(common);
|
|
754
|
+
}
|
|
755
|
+
const full = { ...common, distinctTiles: dec.distinctTiles, tiles: dec.tiles };
|
|
756
|
+
// Big full-screen grid → optionally spill to disk and return a summary,
|
|
757
|
+
// matching the disk-by-default ergonomics of screenshot/inspectPalette.
|
|
758
|
+
if (outputPath) {
|
|
759
|
+
const { mkdir: mkdirp, writeFile: writeFileP } = await import("node:fs/promises");
|
|
760
|
+
const dirname = (await import("node:path")).dirname(outputPath);
|
|
761
|
+
await mkdirp(dirname, { recursive: true });
|
|
762
|
+
await writeFileP(outputPath, JSON.stringify(full, null, 2));
|
|
763
|
+
return jsonContent({
|
|
764
|
+
platform: p, which, region: dec.region,
|
|
765
|
+
path: outputPath,
|
|
766
|
+
distinctTiles: dec.distinctTiles,
|
|
767
|
+
tileCount: dec.width * dec.height,
|
|
768
|
+
note: `Decoded ${dec.width}×${dec.height} tile grid + subPaletteGrid written to ${outputPath}. distinctTiles inline above. Pass a smaller region or attributesOnly to get the grids inline instead.`,
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
return jsonContent(full);
|
|
772
|
+
}
|
|
773
|
+
if (p === "gb" || p === "gbc") {
|
|
774
|
+
const { snapshotBackgroundMap } = await import("../../platforms/gb/ppu.js");
|
|
775
|
+
const snap = snapshotBackgroundMap(host, { which, window, platform: p });
|
|
776
|
+
const label = window ? "Window map" : "BG map";
|
|
777
|
+
return emitImage(snap.png, `${p.toUpperCase()} ${label} composite (${snap.width}×${snap.height}, base=${snap.mapBase}, mode=${snap.mode}, scroll=(${snap.scx},${snap.scy})). ${snap.note}`);
|
|
778
|
+
}
|
|
779
|
+
if (p === "genesis") {
|
|
780
|
+
const { snapshotPlaneMap } = await import("../../platforms/genesis/vdp.js");
|
|
781
|
+
const snap = snapshotPlaneMap(host, { plane });
|
|
782
|
+
return emitImage(snap.png, `Genesis ${snap.plane === "B" ? "Plane B" : "Plane A"} composite (${snap.width}×${snap.height}, base=${snap.baseAddr}, ${snap.wCells}×${snap.hCells} cells). ${snap.note}`);
|
|
783
|
+
}
|
|
784
|
+
if (p === "sms" || p === "gg") {
|
|
785
|
+
const { snapshotBackgroundMap } = await import("../../platforms/sms/vdp.js");
|
|
786
|
+
const snap = snapshotBackgroundMap(host, p);
|
|
787
|
+
return emitImage(snap.png, `${p.toUpperCase()} BG map composite (${snap.width}×${snap.height}, base=${snap.mapBase}, scroll=(${snap.scrollX},${snap.scrollY})). ${snap.note}`);
|
|
788
|
+
}
|
|
789
|
+
if (p === "snes") {
|
|
790
|
+
const { renderSnesTilemap, decodeCGRAM } = await import("../../platforms/snes/ppu.js");
|
|
791
|
+
const vram = host.readMemory("video_ram", 0, 0x10000);
|
|
792
|
+
const cgram = host.readMemory("snes_cgram", 0, 512);
|
|
793
|
+
const colors = decodeCGRAM(cgram);
|
|
794
|
+
const r = renderSnesTilemap(vram, colors, {
|
|
795
|
+
tilemapBaseByte, tileBaseByte, bpp, mapWidth, mapHeight,
|
|
796
|
+
});
|
|
797
|
+
return emitImage(r.png, `SNES BG map composite (${r.width}×${r.height}, ${r.mapWidth}×${r.mapHeight} tiles, ${r.bpp}bpp, tilemap@0x${tilemapBaseByte.toString(16)}, tiles@0x${tileBaseByte.toString(16)}). ${r.note}`);
|
|
798
|
+
}
|
|
799
|
+
throw new Error(`inspectBackgroundMap not yet implemented for platform '${p}'`);
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
// convertImageToTiles → encodeArt({stage:'tiles'}) (router in sprite-pipeline.js).
|
|
803
|
+
convertImageToTilesCore = async ({ platform, pngBase64, pngPath, maxTiles = 512, tileOrder = "row", outputDir, inline }) => {
|
|
804
|
+
if (!inline && !outputDir) {
|
|
805
|
+
throw new Error("convertImageToTiles: pass outputDir (write tiles.bin/palette.bin to disk, returns paths) or inline:true (return base64 in the response).");
|
|
806
|
+
}
|
|
807
|
+
if (!pngBase64 && !pngPath) {
|
|
808
|
+
throw new Error("convertImageToTiles: pass pngPath (a PNG on disk — preferred) or pngBase64.");
|
|
809
|
+
}
|
|
810
|
+
// Resolve the PNG bytes once: from disk (preferred) or from base64.
|
|
811
|
+
const pngBuf = pngPath ? await readFile(pngPath) : Buffer.from(pngBase64, "base64");
|
|
812
|
+
// MSX screen-2 is a special case: a tile is TWO parallel 8-byte tables
|
|
813
|
+
// (pattern bits + per-row fg/bg color), not one tile blob. Emit both
|
|
814
|
+
// streams (pattern.bin + color.bin) instead of the generic tiles.bin.
|
|
815
|
+
if (platform === "msx") {
|
|
816
|
+
const { PNG } = await import("pngjs");
|
|
817
|
+
const { encodeMsxScreen2Tiles } = await import("../../platforms/msx/tiles.js");
|
|
818
|
+
const png = pngBuf;
|
|
819
|
+
const img = PNG.sync.read(png);
|
|
820
|
+
if (img.width % 8 || img.height % 8) {
|
|
821
|
+
throw new Error(`convertImageToTiles(msx): image ${img.width}x${img.height} must be a multiple of 8 in both dimensions.`);
|
|
822
|
+
}
|
|
823
|
+
// Map RGBA → nearest of the 16 fixed TMS9918 colors (MSX1 screen-2).
|
|
824
|
+
const { TMS9918_PALETTE } = await import("../../platforms/msx/vdp.js");
|
|
825
|
+
const indexed = new Uint8Array(img.width * img.height);
|
|
826
|
+
for (let i = 0; i < indexed.length; i++) {
|
|
827
|
+
const r0 = img.data[i * 4], g0 = img.data[i * 4 + 1], b0 = img.data[i * 4 + 2];
|
|
828
|
+
let best = 0, bestD = Infinity;
|
|
829
|
+
for (let c = 0; c < 16; c++) {
|
|
830
|
+
const [pr, pg, pb] = TMS9918_PALETTE[c];
|
|
831
|
+
const d = (pr - r0) ** 2 + (pg - g0) ** 2 + (pb - b0) ** 2;
|
|
832
|
+
if (d < bestD) { bestD = d; best = c; }
|
|
833
|
+
}
|
|
834
|
+
indexed[i] = best;
|
|
835
|
+
}
|
|
836
|
+
const { pattern, color } = encodeMsxScreen2Tiles(indexed, img.width, img.height);
|
|
837
|
+
const tilesAcross = img.width >> 3, tilesDown = img.height >> 3;
|
|
838
|
+
const msxOut = {
|
|
839
|
+
platform: "msx", mode: "screen2",
|
|
840
|
+
tilesAcross, tilesDown, totalTiles: tilesAcross * tilesDown,
|
|
841
|
+
patternBytes: pattern.length, colorBytes: color.length,
|
|
842
|
+
note: "MSX screen-2 tiles = TWO tables: pattern.bin (1bpp, bit7=leftmost) and color.bin (per-row high-nibble=fg, low-nibble=bg color index into the fixed 16-color TMS9918 palette). DMA pattern.bin to the pattern-generator base and color.bin to the color-table base (see background({view:'renderState'}) for those VRAM addresses). Each 8-pixel ROW is limited to 2 colors — that's the classic MSX constraint.",
|
|
843
|
+
};
|
|
844
|
+
if (inline) {
|
|
845
|
+
msxOut.patternBase64 = Buffer.from(pattern).toString("base64");
|
|
846
|
+
msxOut.colorBase64 = Buffer.from(color).toString("base64");
|
|
847
|
+
} else {
|
|
848
|
+
await mkdir(outputDir, { recursive: true });
|
|
849
|
+
msxOut.patternPath = path.join(outputDir, "pattern.bin");
|
|
850
|
+
msxOut.colorPath = path.join(outputDir, "color.bin");
|
|
851
|
+
await writeFile(msxOut.patternPath, Buffer.from(pattern));
|
|
852
|
+
await writeFile(msxOut.colorPath, Buffer.from(color));
|
|
853
|
+
}
|
|
854
|
+
return jsonContent(msxOut);
|
|
855
|
+
}
|
|
856
|
+
const { imageToTiles } = await import("../../platforms/common/image-to-tiles.js");
|
|
857
|
+
const png = pngBuf;
|
|
858
|
+
const r = imageToTiles(platform, png, { maxTiles, tileOrder });
|
|
859
|
+
// Indexed-PNG / palette validation. Catches the most common
|
|
860
|
+
// newbie failure mode: paint in 24-bit RGB → silent color shift.
|
|
861
|
+
const warnings = await validateImagePalette(platform, png);
|
|
862
|
+
const out = {
|
|
863
|
+
platform: r.platform,
|
|
864
|
+
tilesAcross: r.tilesAcross,
|
|
865
|
+
tilesDown: r.tilesDown,
|
|
866
|
+
totalTiles: r.totalTiles,
|
|
867
|
+
tilesBytes: r.tiles.length,
|
|
868
|
+
};
|
|
869
|
+
if (inline) {
|
|
870
|
+
out.tilesBase64 = Buffer.from(r.tiles).toString("base64");
|
|
871
|
+
if (r.palette) {
|
|
872
|
+
out.paletteBase64 = Buffer.from(r.palette).toString("base64");
|
|
873
|
+
out.paletteBytes = r.palette.length;
|
|
874
|
+
out.paletteHex = Array.from(r.palette, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
875
|
+
}
|
|
876
|
+
} else {
|
|
877
|
+
await mkdir(outputDir, { recursive: true });
|
|
878
|
+
out.tilesPath = path.join(outputDir, "tiles.bin");
|
|
879
|
+
await writeFile(out.tilesPath, Buffer.from(r.tiles));
|
|
880
|
+
if (r.palette) {
|
|
881
|
+
out.palettePath = path.join(outputDir, "palette.bin");
|
|
882
|
+
await writeFile(out.palettePath, Buffer.from(r.palette));
|
|
883
|
+
out.paletteBytes = r.palette.length;
|
|
884
|
+
out.paletteHex = Array.from(r.palette, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
if (warnings.length) out.warnings = warnings;
|
|
888
|
+
if (platform === "nes") {
|
|
889
|
+
out.note = "Use patchRom to write the tile bytes (tilesPath / tilesBase64) to the CHR region of an iNES file (offset 16 + prgBanks*16384).";
|
|
890
|
+
} else if (platform === "gb" || platform === "gbc") {
|
|
891
|
+
out.note = "Game Boy uses fixed grayscale (DMG) or runtime palettes (CGB). Tiles are in 'interleaved' bitplane order. Inject into your VRAM via the rgbasm `INCBIN` directive or load via DMA at runtime.";
|
|
892
|
+
} else if (platform === "snes") {
|
|
893
|
+
out.note = "SNES 4bpp 'planar-pairs' layout (32 B/tile). `paletteHex` is a suggested 16-color sub-palette (BGR555 words you'd DMA into CGRAM). DMA the tile bytes to VRAM at your BG/OBJ char base.";
|
|
894
|
+
} else if (platform === "genesis") {
|
|
895
|
+
out.note = "Genesis 4bpp 'packed' layout (32 B/tile, high nibble = left pixel). DMA the tile bytes to VRAM; `paletteHex` is a suggested CRAM sub-palette (write to one of the 4 16-color banks).";
|
|
896
|
+
} else if (platform === "sms" || platform === "gg") {
|
|
897
|
+
out.note = "SMS/GG 4bpp 'interleaved' layout (32 B/tile, per-row [p0,p1,p2,p3]). Write tiles to VRAM tile data base (VDP reg 4); `paletteHex` is a suggested CRAM palette.";
|
|
898
|
+
} else if (platform === "c64") {
|
|
899
|
+
out.note = "C64 hi-res charset: each tile is one 8×8 char (8 B, 1bpp — bit set = foreground in the cell's Color-RAM color, clear = shared background). Load the tile bytes (tilesPath / tilesBase64) into your char base ($0800/$1000/etc.). For a full picture with per-cell colors + screen RAM, use imageToTilemap({platform:'c64'}) instead.";
|
|
900
|
+
} else if (platform === "pce") {
|
|
901
|
+
out.note = "PC Engine HuC6270 4bpp 'planar-pairs' layout (32 B/tile, same as SNES: 16 B plane 0+1, then 16 B plane 2+3). DMA the tile bytes into VRAM at your BG/SPR pattern base. `paletteHex` is a suggested 16-color set — pack each to the VCE's 9-bit GRB at use time. (MSX returns pattern.bin/color.bin instead — see its branch.)";
|
|
902
|
+
}
|
|
903
|
+
return jsonContent(out);
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
// ---- Background image conversion (platform-generic) -------------------
|
|
907
|
+
// Convention: caller already resized + dithered the image into the
|
|
908
|
+
// platform's native palette using the PNG returned by getPlatformPalettePng.
|
|
909
|
+
// The MCP tool then does the platform-specific tile/attribute encoding.
|
|
910
|
+
|
|
911
|
+
// getPlatformMasterPaletteCore: palette({source:'platformMaster'}). Module-scope.
|
|
912
|
+
getPlatformMasterPaletteCore = async ({ platform, format = "png", outputPath }) => {
|
|
913
|
+
const { getPlatformPaletteRgb, rgbHex, rgbHexLospec } = await import("../../platforms/common/platform-palette.js");
|
|
914
|
+
if (format === "lospec") {
|
|
915
|
+
const colors = getPlatformPaletteRgb(platform).map(([r, g, b]) => rgbHexLospec(r, g, b));
|
|
916
|
+
const json = {
|
|
917
|
+
name: `${platform} master palette`,
|
|
918
|
+
author: "romdev",
|
|
919
|
+
colors,
|
|
920
|
+
};
|
|
921
|
+
if (outputPath) {
|
|
922
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
923
|
+
await writeFile(outputPath, JSON.stringify(json, null, 2));
|
|
924
|
+
return jsonContent({ platform, format, path: outputPath, colors: colors.length });
|
|
925
|
+
}
|
|
926
|
+
return jsonContent({ platform, format, json });
|
|
927
|
+
}
|
|
928
|
+
if (format === "hex") {
|
|
929
|
+
const lines = getPlatformPaletteRgb(platform).map(([r, g, b]) => rgbHex(r, g, b));
|
|
930
|
+
const text = lines.join("\n") + "\n";
|
|
931
|
+
if (outputPath) {
|
|
932
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
933
|
+
await writeFile(outputPath, text);
|
|
934
|
+
return jsonContent({ platform, format, path: outputPath, colors: lines.length });
|
|
935
|
+
}
|
|
936
|
+
return jsonContent({ platform, format, text });
|
|
937
|
+
}
|
|
938
|
+
// format === "png"
|
|
939
|
+
const png = await getPlatformPalettePng(platform);
|
|
940
|
+
if (outputPath) {
|
|
941
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
942
|
+
await writeFile(outputPath, png);
|
|
943
|
+
return jsonContent({
|
|
944
|
+
platform,
|
|
945
|
+
format: "png",
|
|
946
|
+
path: outputPath,
|
|
947
|
+
bytes: png.length,
|
|
948
|
+
note: "Use this PNG as the ImageMagick -remap target. The dithered output is what imageToTilemap expects.",
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
return jsonContent({
|
|
952
|
+
platform,
|
|
953
|
+
format: "png",
|
|
954
|
+
pngBase64: Buffer.from(png).toString("base64"),
|
|
955
|
+
note: "Save these bytes to a .png and pass it to ImageMagick as the -remap target. The resulting dithered image is what imageToTilemap expects. (Pass outputPath next time to skip the inline base64.)",
|
|
956
|
+
});
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
// imageToTilemap → encodeArt({stage:'tilemap'}) (router in sprite-pipeline.js).
|
|
960
|
+
imageToTilemapCore = async ({ platform, pngBase64, pngPath, outputDir, maxTiles, backdrop, dedup = true, singlePalette = false }) => {
|
|
961
|
+
let pngBytes;
|
|
962
|
+
if (pngPath) {
|
|
963
|
+
pngBytes = await readFile(pngPath);
|
|
964
|
+
} else if (pngBase64) {
|
|
965
|
+
pngBytes = Buffer.from(pngBase64, "base64");
|
|
966
|
+
} else {
|
|
967
|
+
throw new Error("imageToTilemap: must provide either pngBase64 or pngPath");
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
const r = await imageToTilemap(platform, {
|
|
971
|
+
pngBytes,
|
|
972
|
+
maxTiles,
|
|
973
|
+
backdrop,
|
|
974
|
+
dedup,
|
|
975
|
+
singlePalette,
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
if (outputDir) {
|
|
979
|
+
await mkdir(outputDir, { recursive: true });
|
|
980
|
+
const chrPath = path.join(outputDir, "chr.bin");
|
|
981
|
+
const nametablePath = path.join(outputDir, "nametable.bin");
|
|
982
|
+
const attrPath = path.join(outputDir, "attr.bin");
|
|
983
|
+
const palettePath = path.join(outputDir, "palette.bin");
|
|
984
|
+
const previewPath = path.join(outputDir, "preview.png");
|
|
985
|
+
await writeFile(chrPath, r.chr);
|
|
986
|
+
await writeFile(nametablePath, r.nametable);
|
|
987
|
+
await writeFile(attrPath, r.attr);
|
|
988
|
+
await writeFile(palettePath, r.palette);
|
|
989
|
+
await writeFile(previewPath, r.previewPng);
|
|
990
|
+
return jsonContent({
|
|
991
|
+
platform,
|
|
992
|
+
chrPath,
|
|
993
|
+
chrBytes: r.chr.length,
|
|
994
|
+
nametablePath,
|
|
995
|
+
attrPath,
|
|
996
|
+
palettePath,
|
|
997
|
+
paletteHex: Array.from(r.palette, (b) => b.toString(16).padStart(2, "0")).join(""),
|
|
998
|
+
previewPath,
|
|
999
|
+
uniqueTilesBeforeMerge: r.uniqueTilesBeforeMerge,
|
|
1000
|
+
uniqueTiles: r.uniqueTiles,
|
|
1001
|
+
...(r._c64 ? { c64: r._c64 } : {}),
|
|
1002
|
+
...(r._genesis ? { genesis: r._genesis } : {}),
|
|
1003
|
+
note: platform === "c64"
|
|
1004
|
+
? `C64 hi-res char mode: chr.bin = charset (${r.uniqueTiles} chars × 8B, load into your char base), ` +
|
|
1005
|
+
`nametable.bin = screen RAM (1000 B of char codes → $0400), attr.bin = Color RAM (1000 B, low nibble = ` +
|
|
1006
|
+
`per-cell fg color → $D800), palette.bin = 1 byte shared background color → $D021.` +
|
|
1007
|
+
(r._c64?.warnings?.length ? " WARNINGS: " + r._c64.warnings.join(" ") : "")
|
|
1008
|
+
: platform === "genesis"
|
|
1009
|
+
? `Genesis VDP: chr.bin = ${r.uniqueTiles} deduped 4bpp tiles (32 B each, DMA to VRAM). ` +
|
|
1010
|
+
`nametable.bin = ${40 * 28} 16-bit BE name-table entries (40×28 cells; tile idx + palette line + h/v flip). ` +
|
|
1011
|
+
`palette.bin = 4 lines × 16 colors (128 B BE CRAM words; ${r._genesis?.paletteLines} line(s) used). ` +
|
|
1012
|
+
`Set plane width to 64 cells and write the nametable to your Plane A base.` +
|
|
1013
|
+
(r._genesis?.warnings?.length ? " WARNINGS: " + r._genesis.warnings.slice(0, 3).join(" ") : "")
|
|
1014
|
+
: "Paths written. Pass them as binaryIncludePaths into buildSource.",
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
return jsonContent({
|
|
1019
|
+
platform,
|
|
1020
|
+
chrBase64: Buffer.from(r.chr).toString("base64"),
|
|
1021
|
+
chrBytes: r.chr.length,
|
|
1022
|
+
nametableBase64: Buffer.from(r.nametable).toString("base64"),
|
|
1023
|
+
attrBase64: Buffer.from(r.attr).toString("base64"),
|
|
1024
|
+
paletteBase64: Buffer.from(r.palette).toString("base64"),
|
|
1025
|
+
paletteHex: Array.from(r.palette, (b) => b.toString(16).padStart(2, "0")).join(""),
|
|
1026
|
+
uniqueTilesBeforeMerge: r.uniqueTilesBeforeMerge,
|
|
1027
|
+
uniqueTiles: r.uniqueTiles,
|
|
1028
|
+
previewPngBase64: Buffer.from(r.previewPng).toString("base64"),
|
|
1029
|
+
...(r._c64 ? { c64: r._c64 } : {}),
|
|
1030
|
+
...(r._genesis ? { genesis: r._genesis } : {}),
|
|
1031
|
+
note: platform === "c64"
|
|
1032
|
+
? `C64 hi-res char mode: chrBase64 = charset (${r.uniqueTiles} chars × 8B), nametableBase64 = screen RAM ` +
|
|
1033
|
+
`(char codes → $0400), attrBase64 = Color RAM (low nibble = per-cell fg → $D800), paletteBase64 = ` +
|
|
1034
|
+
`shared background color byte → $D021.` +
|
|
1035
|
+
(r._c64?.warnings?.length ? " WARNINGS: " + r._c64.warnings.join(" ") : "")
|
|
1036
|
+
: platform === "genesis"
|
|
1037
|
+
? `Genesis VDP: chrBase64 = ${r.uniqueTiles} deduped 4bpp tiles (32 B each). nametableBase64 = 40×28 ` +
|
|
1038
|
+
`16-bit BE entries (tile + palette line + flip). paletteBase64 = 4×16 CRAM words (${r._genesis?.paletteLines} used). ` +
|
|
1039
|
+
`Pass outputDir to get .bin files instead of base64.` +
|
|
1040
|
+
(r._genesis?.warnings?.length ? " WARNINGS: " + r._genesis.warnings.slice(0, 3).join(" ") : "")
|
|
1041
|
+
: "Pass outputDir next call to skip inline base64 and get back paths instead.",
|
|
1042
|
+
});
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Render a generic color list as a PNG swatch grid. Each color becomes
|
|
1048
|
+
* a `swatchSize`-pixel square. `cols` controls grid width. Used by the
|
|
1049
|
+
* generic inspectPalette path so SNES/Genesis/GB get the same visual.
|
|
1050
|
+
*
|
|
1051
|
+
* @param {Array<{ r: number, g: number, b: number }>} colors
|
|
1052
|
+
* @param {number} [cols=16]
|
|
1053
|
+
* @param {number} [swatchSize=12]
|
|
1054
|
+
*/
|
|
1055
|
+
function renderColorsAsPng(colors, cols = 16, swatchSize = 12) {
|
|
1056
|
+
const rows = Math.ceil(colors.length / cols);
|
|
1057
|
+
const width = cols * swatchSize;
|
|
1058
|
+
const height = rows * swatchSize;
|
|
1059
|
+
const png = new PNG({ width, height });
|
|
1060
|
+
for (let cy = 0; cy < rows; cy++) {
|
|
1061
|
+
for (let cx = 0; cx < cols; cx++) {
|
|
1062
|
+
const idx = cy * cols + cx;
|
|
1063
|
+
if (idx >= colors.length) break;
|
|
1064
|
+
const { r, g, b } = colors[idx];
|
|
1065
|
+
for (let py = 0; py < swatchSize; py++) {
|
|
1066
|
+
for (let px = 0; px < swatchSize; px++) {
|
|
1067
|
+
const x = cx * swatchSize + px;
|
|
1068
|
+
const y = cy * swatchSize + py;
|
|
1069
|
+
const o = (y * width + x) * 4;
|
|
1070
|
+
png.data[o] = r;
|
|
1071
|
+
png.data[o + 1] = g;
|
|
1072
|
+
png.data[o + 2] = b;
|
|
1073
|
+
png.data[o + 3] = 0xFF;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
return PNG.sync.write(png);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Platform-generic dispatcher for background palette PNG. Adding a new
|
|
1083
|
+
* platform means adding one branch here.
|
|
1084
|
+
* @param {string} platform
|
|
1085
|
+
*/
|
|
1086
|
+
async function getPlatformPalettePng(platform) {
|
|
1087
|
+
if (platform === "nes") {
|
|
1088
|
+
const { nesPalettePng } = await import("../../platforms/nes/image-to-tilemap.js");
|
|
1089
|
+
return nesPalettePng();
|
|
1090
|
+
}
|
|
1091
|
+
if (platform === "snes") {
|
|
1092
|
+
const { snesPalettePng } = await import("../../platforms/snes/image-to-tilemap.js");
|
|
1093
|
+
return snesPalettePng();
|
|
1094
|
+
}
|
|
1095
|
+
if (platform === "genesis") {
|
|
1096
|
+
const { genesisPalettePng } = await import("../../platforms/genesis/image-to-tilemap.js");
|
|
1097
|
+
return genesisPalettePng();
|
|
1098
|
+
}
|
|
1099
|
+
if (platform === "sms" || platform === "gg") {
|
|
1100
|
+
const { smsPalettePng } = await import("../../platforms/sms/image-to-tilemap.js");
|
|
1101
|
+
return smsPalettePng();
|
|
1102
|
+
}
|
|
1103
|
+
if (platform === "gb" || platform === "gbc") {
|
|
1104
|
+
const { gbPalettePng } = await import("../../platforms/gb/image-to-tilemap.js");
|
|
1105
|
+
return gbPalettePng();
|
|
1106
|
+
}
|
|
1107
|
+
if (platform === "atari2600" || platform === "a2600") {
|
|
1108
|
+
const { renderNtscPalettePng } = await import("../../platforms/atari2600/tia.js");
|
|
1109
|
+
return renderNtscPalettePng();
|
|
1110
|
+
}
|
|
1111
|
+
if (platform === "atari7800" || platform === "a7800") {
|
|
1112
|
+
const { renderA78MasterPalettePng } = await import("../../platforms/atari7800/maria.js");
|
|
1113
|
+
return renderA78MasterPalettePng();
|
|
1114
|
+
}
|
|
1115
|
+
if (platform === "c64") {
|
|
1116
|
+
const { renderC64PalettePng } = await import("../../platforms/c64/vic.js");
|
|
1117
|
+
return renderC64PalettePng();
|
|
1118
|
+
}
|
|
1119
|
+
throw new Error(`getPlatformPalettePng not implemented for '${platform}'. Currently supported: nes, snes, genesis, sms, gg, gb, gbc, atari2600, atari7800, c64.`);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* Platform-generic dispatcher for image-to-tilemap conversion.
|
|
1124
|
+
* @param {string} platform
|
|
1125
|
+
* @param {{ pngBytes: Buffer | Uint8Array, maxTiles?: number, backdrop?: number, numPalettes?: number }} args
|
|
1126
|
+
*/
|
|
1127
|
+
async function imageToTilemap(platform, args) {
|
|
1128
|
+
if (platform === "nes") {
|
|
1129
|
+
const { nesImageToTilemap } = await import("../../platforms/nes/image-to-tilemap.js");
|
|
1130
|
+
return nesImageToTilemap(args);
|
|
1131
|
+
}
|
|
1132
|
+
if (platform === "snes") {
|
|
1133
|
+
const { snesImageToTilemap } = await import("../../platforms/snes/image-to-tilemap.js");
|
|
1134
|
+
const r = snesImageToTilemap(args);
|
|
1135
|
+
// Normalize return shape: SNES returns `tilemap` instead of `nametable`/`attr`.
|
|
1136
|
+
return {
|
|
1137
|
+
chr: r.chr,
|
|
1138
|
+
nametable: r.tilemap, // SNES tilemap goes where NES nametable goes
|
|
1139
|
+
attr: new Uint8Array(0), // SNES has no separate attr table (per-tile bits)
|
|
1140
|
+
palette: r.palette,
|
|
1141
|
+
uniqueTilesBeforeMerge: r.uniqueTiles,
|
|
1142
|
+
uniqueTiles: r.uniqueTiles,
|
|
1143
|
+
previewPng: r.previewPng,
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
if (platform === "sms" || platform === "gg") {
|
|
1147
|
+
const { smsImageToTilemap } = await import("../../platforms/sms/image-to-tilemap.js");
|
|
1148
|
+
return smsImageToTilemap(args);
|
|
1149
|
+
}
|
|
1150
|
+
if (platform === "genesis") {
|
|
1151
|
+
const { genesisImageToTilemap } = await import("../../platforms/genesis/image-to-tilemap.js");
|
|
1152
|
+
const r = genesisImageToTilemap(args);
|
|
1153
|
+
return {
|
|
1154
|
+
chr: r.chr,
|
|
1155
|
+
nametable: r.nametable,
|
|
1156
|
+
attr: r.attr,
|
|
1157
|
+
palette: r.palette,
|
|
1158
|
+
uniqueTilesBeforeMerge: r.uniqueTilesBeforeMerge,
|
|
1159
|
+
uniqueTiles: r.uniqueTiles,
|
|
1160
|
+
previewPng: r.previewPng,
|
|
1161
|
+
_genesis: { paletteLines: r.paletteLines, imageColors: r.imageColors, warnings: r.warnings },
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
if (platform === "gb" || platform === "gbc") {
|
|
1165
|
+
const { gbImageToTilemap } = await import("../../platforms/gb/image-to-tilemap.js");
|
|
1166
|
+
return gbImageToTilemap(args);
|
|
1167
|
+
}
|
|
1168
|
+
if (platform === "c64") {
|
|
1169
|
+
const { c64ImageToTilemap } = await import("../../platforms/c64/image-to-tilemap.js");
|
|
1170
|
+
const r = c64ImageToTilemap(args);
|
|
1171
|
+
// Normalize to the dispatcher's expected field names. C64 "chr" is the
|
|
1172
|
+
// charset, "nametable" is screen RAM, "attr" is color RAM.
|
|
1173
|
+
return {
|
|
1174
|
+
chr: r.chr,
|
|
1175
|
+
nametable: r.nametable,
|
|
1176
|
+
attr: r.attr,
|
|
1177
|
+
palette: r.palette,
|
|
1178
|
+
uniqueTilesBeforeMerge: r.uniqueTilesBeforeMerge,
|
|
1179
|
+
uniqueTiles: r.uniqueTiles,
|
|
1180
|
+
previewPng: r.previewPng,
|
|
1181
|
+
_c64: { backgroundColor: r.backgroundColor, imageColors: r.imageColors, warnings: r.warnings },
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
if (platform === "pce") {
|
|
1185
|
+
const { pceImageToTilemap } = await import("../../platforms/pce/image-to-tilemap.js");
|
|
1186
|
+
const r = pceImageToTilemap(args);
|
|
1187
|
+
return {
|
|
1188
|
+
chr: r.tiles, // 4bpp planar-pairs tile bytes (32 B/tile)
|
|
1189
|
+
nametable: r.nametable, // the BAT (16-bit LE entries: tile|palette<<12)
|
|
1190
|
+
attr: new Uint8Array(0), // PCE attributes are packed into the BAT entry
|
|
1191
|
+
palette: r.palette, // 16 × VCE 9-bit GRB words
|
|
1192
|
+
uniqueTiles: r.uniqueTiles,
|
|
1193
|
+
uniqueTilesBeforeMerge: r.uniqueTiles,
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
if (platform === "msx") {
|
|
1197
|
+
const { msxImageToTilemap } = await import("../../platforms/msx/image-to-tilemap.js");
|
|
1198
|
+
const r = msxImageToTilemap(args);
|
|
1199
|
+
return {
|
|
1200
|
+
chr: r.tiles, // screen-2 pattern table (1bpp, 8 B/tile)
|
|
1201
|
+
nametable: r.nametable, // 768 bytes (0..255 × 3 thirds)
|
|
1202
|
+
attr: r.color, // screen-2 color table (per-row fg/bg), 8 B/tile
|
|
1203
|
+
palette: new Uint8Array(0), // MSX1 palette is the fixed TMS9918 set
|
|
1204
|
+
uniqueTiles: r.uniqueTiles,
|
|
1205
|
+
uniqueTilesBeforeMerge: r.uniqueTiles,
|
|
1206
|
+
_msx: { mode: "screen2", note: "chr=pattern table, attr=color table, nametable=name table. Fixed TMS9918 palette." },
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
if (platform === "atari2600" || platform === "a2600") {
|
|
1210
|
+
throw new Error(
|
|
1211
|
+
`imageToTilemap[2600]: the 2600 has no tile/tilemap concept. The playfield ` +
|
|
1212
|
+
`is 20 mirrored bits (PF0/PF1/PF2) that change every scanline, plus 5 ` +
|
|
1213
|
+
`sprite objects. Pictures must be hand-authored as per-scanline byte ` +
|
|
1214
|
+
`streams. There is no automated PNG → 2600 path.`
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
if (platform === "atari7800" || platform === "a7800") {
|
|
1218
|
+
throw new Error(
|
|
1219
|
+
`imageToTilemap[7800]: MARIA reads "display lists" — variable-width sprite/ ` +
|
|
1220
|
+
`character chunks at user-defined RAM addresses — instead of a fixed tilemap. ` +
|
|
1221
|
+
`Converting an arbitrary PNG would require generating a per-zone display list ` +
|
|
1222
|
+
`tuned to the cart, which is game-specific. Not auto-implemented.`
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
throw new Error(`imageToTilemap not implemented for '${platform}'. Currently supported: nes, snes, sms, gg, gb, gbc.`);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Scan a PNG buffer against the platform's master palette and return
|
|
1230
|
+
* an array of human-readable warnings (empty array = OK). Never throws.
|
|
1231
|
+
* Indexed PNGs are validated via their PLTE chunk; truecolor PNGs are
|
|
1232
|
+
* validated by scanning distinct RGB pixels (capped at 256 for cost).
|
|
1233
|
+
*
|
|
1234
|
+
* @param {string} platform
|
|
1235
|
+
* @param {Buffer} pngBuf
|
|
1236
|
+
* @returns {Promise<string[]>}
|
|
1237
|
+
*/
|
|
1238
|
+
async function validateImagePalette(platform, pngBuf) {
|
|
1239
|
+
const warnings = [];
|
|
1240
|
+
let pal;
|
|
1241
|
+
try {
|
|
1242
|
+
const { getPlatformPaletteRgb, paletteContains, rgbHex } =
|
|
1243
|
+
await import("../../platforms/common/platform-palette.js");
|
|
1244
|
+
pal = getPlatformPaletteRgb(platform);
|
|
1245
|
+
// Tolerance: 8 per channel covers LibreSprite sRGB drift. NES/Genesis
|
|
1246
|
+
// strict palettes still match within this.
|
|
1247
|
+
const TOL = 8;
|
|
1248
|
+
const decoded = PNG.sync.read(pngBuf);
|
|
1249
|
+
const plte = decoded.palette; // [[r,g,b,a],...] when PLTE present
|
|
1250
|
+
if (plte && plte.length) {
|
|
1251
|
+
const oob = [];
|
|
1252
|
+
for (let i = 0; i < plte.length; i++) {
|
|
1253
|
+
const [r, g, b] = plte[i];
|
|
1254
|
+
if (!paletteContains(pal, r, g, b, TOL)) {
|
|
1255
|
+
oob.push(rgbHex(r, g, b));
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
if (oob.length) {
|
|
1259
|
+
warnings.push(
|
|
1260
|
+
`PNG PLTE has ${oob.length}/${plte.length} colors outside the ${platform} palette` +
|
|
1261
|
+
` (tolerance ±${TOL}/channel): ` +
|
|
1262
|
+
oob.slice(0, 8).join(", ") + (oob.length > 8 ? `, ... (+${oob.length - 8} more)` : "") +
|
|
1263
|
+
`. Re-export from your editor using getPlatformPalettePng({platform:"${platform}", format:"hex"|"lospec"}) as the source palette.`
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
} else {
|
|
1267
|
+
// Truecolor — scan distinct RGB triples (cap at 256 for cost).
|
|
1268
|
+
const seen = new Map();
|
|
1269
|
+
const buf = decoded.data;
|
|
1270
|
+
const MAX_DISTINCT = 256;
|
|
1271
|
+
for (let i = 0; i < buf.length; i += 4) {
|
|
1272
|
+
const a = buf[i + 3];
|
|
1273
|
+
if (a === 0) continue; // skip fully transparent
|
|
1274
|
+
const key = (buf[i] << 16) | (buf[i + 1] << 8) | buf[i + 2];
|
|
1275
|
+
if (!seen.has(key)) {
|
|
1276
|
+
seen.set(key, [buf[i], buf[i + 1], buf[i + 2]]);
|
|
1277
|
+
if (seen.size > MAX_DISTINCT) break;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
const oob = [];
|
|
1281
|
+
for (const [r, g, b] of seen.values()) {
|
|
1282
|
+
if (!paletteContains(pal, r, g, b, TOL)) {
|
|
1283
|
+
oob.push(rgbHex(r, g, b));
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
if (oob.length) {
|
|
1287
|
+
warnings.push(
|
|
1288
|
+
`PNG has ${oob.length}/${seen.size} distinct colors outside the ${platform} palette` +
|
|
1289
|
+
` (tolerance ±${TOL}/channel): ` +
|
|
1290
|
+
oob.slice(0, 8).join(", ") + (oob.length > 8 ? `, ... (+${oob.length - 8} more)` : "") +
|
|
1291
|
+
`. Quantize to the platform palette first — call getPlatformPalettePng({platform:"${platform}"}) and use the PNG as ImageMagick's -remap target.`
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
} catch (e) {
|
|
1296
|
+
// Never block the build over a validator hiccup.
|
|
1297
|
+
warnings.push(`palette-validation skipped: ${e.message}`);
|
|
1298
|
+
}
|
|
1299
|
+
return warnings;
|
|
1300
|
+
}
|