romdevtools 0.27.0 → 0.28.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 +5 -3
- package/CHANGELOG.md +309 -0
- package/README.md +1 -1
- package/examples/README.md +1 -1
- package/examples/atari2600/templates/platformer.asm +18 -9
- package/examples/atari2600/templates/racing.asm +25 -4
- package/examples/atari2600/templates/shmup.asm +30 -5
- package/examples/atari2600/templates/sports.asm +41 -9
- package/examples/atari7800/templates/hello_sprite.c +8 -4
- package/examples/atari7800/templates/platformer.c +12 -8
- package/examples/atari7800/templates/puzzle.c +7 -4
- package/examples/atari7800/templates/racing.c +5 -2
- package/examples/atari7800/templates/shmup.c +8 -4
- package/examples/atari7800/templates/sports.c +6 -3
- package/examples/c64/templates/platformer.c +28 -24
- package/examples/c64/templates/puzzle.c +77 -16
- package/examples/c64/templates/racing.c +9 -0
- package/examples/c64/templates/shmup.c +13 -1
- package/examples/c64/templates/sports.c +9 -4
- package/examples/gb/templates/platformer.c +6 -2
- package/examples/gb/templates/puzzle.c +279 -101
- package/examples/gb/templates/racing.c +13 -1
- package/examples/gb/templates/shmup.c +13 -1
- package/examples/gb/templates/sports.c +9 -3
- package/examples/gba/templates/platformer.c +7 -13
- package/examples/gba/templates/puzzle.c +93 -15
- package/examples/gba/templates/racing.c +13 -1
- package/examples/gba/templates/shmup.c +13 -1
- package/examples/gba/templates/sports.c +17 -5
- package/examples/gbc/templates/platformer.c +6 -2
- package/examples/gbc/templates/puzzle.c +878 -178
- package/examples/gbc/templates/racing.c +13 -1
- package/examples/gbc/templates/shmup.c +13 -1
- package/examples/gbc/templates/sports.c +9 -3
- package/examples/genesis/templates/puzzle.c +76 -15
- package/examples/genesis/templates/racing.c +13 -1
- package/examples/genesis/templates/shmup_2p.c +13 -1
- package/examples/gg/templates/platformer.c +4 -0
- package/examples/gg/templates/puzzle.c +80 -14
- package/examples/gg/templates/racing.c +17 -1
- package/examples/gg/templates/shmup.c +17 -1
- package/examples/gg/templates/sports.c +4 -0
- package/examples/lynx/templates/platformer.c +25 -6
- package/examples/lynx/templates/puzzle.c +77 -14
- package/examples/lynx/templates/shmup.c +13 -1
- package/examples/lynx/templates/sports.c +5 -2
- package/examples/msx/platformer/main.c +2 -0
- package/examples/msx/puzzle/main.c +78 -15
- package/examples/msx/racing/main.c +1 -0
- package/examples/msx/shmup/main.c +1 -0
- package/examples/msx/sports/main.c +3 -2
- package/examples/nes/templates/platformer.c +11 -3
- package/examples/nes/templates/puzzle.c +81 -21
- package/examples/nes/templates/racing.c +15 -1
- package/examples/nes/templates/shmup.c +1 -0
- package/examples/nes/templates/sports.c +1 -0
- package/examples/pce/platformer/main.c +3 -1
- package/examples/pce/puzzle/main.c +78 -12
- package/examples/pce/racing/main.c +1 -0
- package/examples/pce/shmup/main.c +5 -4
- package/examples/pce/sports/main.c +4 -3
- package/examples/sms/templates/platformer.c +4 -0
- package/examples/sms/templates/puzzle.c +80 -14
- package/examples/sms/templates/racing.c +17 -1
- package/examples/sms/templates/shmup.c +17 -1
- package/examples/sms/templates/shmup_2p.c +17 -1
- package/examples/sms/templates/sports.c +4 -0
- package/examples/snes/templates/platformer.c +32 -15
- package/examples/snes/templates/puzzle.c +84 -16
- package/examples/snes/templates/racing.c +20 -1
- package/examples/snes/templates/shmup.c +20 -2
- package/examples/snes/templates/sports.c +7 -0
- package/package.json +12 -12
- package/src/cores/wasm/bluemsx_libretro.js +1 -1
- package/src/cores/wasm/bluemsx_libretro.wasm +0 -0
- package/src/cores/wasm/fceumm_libretro.js +1 -1
- package/src/cores/wasm/fceumm_libretro.wasm +0 -0
- package/src/cores/wasm/gambatte_libretro.js +1 -1
- package/src/cores/wasm/gambatte_libretro.wasm +0 -0
- package/src/cores/wasm/geargrafx_libretro.js +1 -1
- package/src/cores/wasm/geargrafx_libretro.wasm +0 -0
- package/src/cores/wasm/genesis_plus_gx_libretro.js +1 -1
- package/src/cores/wasm/genesis_plus_gx_libretro.wasm +0 -0
- package/src/cores/wasm/handy_libretro.js +1 -1
- package/src/cores/wasm/handy_libretro.wasm +0 -0
- package/src/cores/wasm/mgba_libretro.js +1 -1
- package/src/cores/wasm/mgba_libretro.wasm +0 -0
- package/src/cores/wasm/prosystem_libretro.js +1 -1
- package/src/cores/wasm/prosystem_libretro.wasm +0 -0
- package/src/cores/wasm/snes9x_libretro.js +1 -1
- package/src/cores/wasm/snes9x_libretro.wasm +0 -0
- package/src/cores/wasm/stella2014_libretro.js +1 -1
- package/src/cores/wasm/stella2014_libretro.wasm +0 -0
- package/src/cores/wasm/vice_x64_libretro.js +1 -1
- package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
- package/src/host/LibretroHost.js +245 -10
- package/src/mcp/server.js +6 -0
- package/src/mcp/tools/disasm-rebuild.js +315 -65
- package/src/mcp/tools/disasm.js +149 -28
- package/src/mcp/tools/find-references.js +216 -51
- package/src/mcp/tools/frame.js +11 -4
- package/src/mcp/tools/index.js +15 -1
- package/src/mcp/tools/input.js +26 -3
- package/src/mcp/tools/memory.js +208 -39
- package/src/mcp/tools/playtest.js +56 -4
- package/src/mcp/tools/project.js +35 -9
- package/src/mcp/tools/toolchain.js +43 -10
- package/src/mcp/tools/watch-memory.js +141 -24
- package/src/platforms/_guides/ROMHACKING_PLAYBOOK.md +64 -17
- package/src/platforms/atari2600/MENTAL_MODEL.md +5 -1
- package/src/platforms/atari2600/TROUBLESHOOTING.md +40 -0
- package/src/platforms/atari7800/MENTAL_MODEL.md +27 -6
- package/src/platforms/gb/MENTAL_MODEL.md +16 -1
- package/src/platforms/gb/TROUBLESHOOTING.md +42 -0
- package/src/platforms/gb/lib/c/patch-header.js +7 -4
- package/src/platforms/gbc/MENTAL_MODEL.md +12 -0
- package/src/platforms/gbc/TROUBLESHOOTING.md +21 -0
- package/src/platforms/gbc/lib/c/font.h +43 -0
- package/src/platforms/gbc/lib/c/patch-header.js +7 -4
- package/src/platforms/genesis/MENTAL_MODEL.md +40 -6
- package/src/platforms/genesis/lib/c/genesis_sfx.c +37 -0
- package/src/platforms/genesis/lib/c/genesis_sfx.h +1 -0
- package/src/platforms/gg/TROUBLESHOOTING.md +13 -17
- package/src/platforms/gg/lib/c/gg_crt0.s +14 -2
- package/src/platforms/lynx/lib/c/lynx_sfx.c +38 -2
- package/src/platforms/lynx/lib/c/lynx_sfx.h +1 -0
- package/src/platforms/msx/MENTAL_MODEL.md +6 -0
- package/src/platforms/msx/TROUBLESHOOTING.md +21 -0
- package/src/platforms/msx/lib/c/msx_crt0.s +27 -0
- package/src/platforms/msx/lib/c/msx_hw.h +2 -0
- package/src/platforms/msx/lib/c/msx_vdp.c +45 -0
- package/src/platforms/nes/MENTAL_MODEL.md +10 -3
- package/src/platforms/nes/lib/c/nes_runtime.c +41 -0
- package/src/platforms/nes/lib/c/nes_runtime.h +2 -0
- package/src/platforms/pce/MENTAL_MODEL.md +9 -0
- package/src/platforms/pce/TROUBLESHOOTING.md +9 -0
- package/src/platforms/pce/lib/c/pce_hw.h +2 -1
- package/src/platforms/pce/lib/c/pce_sound.c +22 -0
- package/src/platforms/sms/MENTAL_MODEL.md +5 -0
- package/src/platforms/sms/TROUBLESHOOTING.md +6 -0
- package/src/platforms/sms/lib/c/sms_crt0.s +14 -2
- package/src/platforms/snes/MENTAL_MODEL.md +5 -0
- package/src/playtest/playtest.js +73 -3
- package/src/toolchains/index.js +37 -8
package/src/toolchains/index.js
CHANGED
|
@@ -727,7 +727,17 @@ export async function buildForPlatform(args) {
|
|
|
727
727
|
// the cartridge header + reset vectors which the custom crt0 provides.
|
|
728
728
|
// MSX: _CODE goes at $4010 — a cartridge maps at $4000-$BFFF and the first
|
|
729
729
|
// 16 bytes are the ROM header ("AB" + INIT vector) the crt0 emits.
|
|
730
|
-
|
|
730
|
+
// SMS/GG: _CODE goes at $0100 — $0000-$00FF belongs to the crt0's ABS
|
|
731
|
+
// _HEADER area (reset + RST/IRQ/NMI vectors + _boot). The old default of
|
|
732
|
+
// $0000 linked _CODE ON TOP of the vector table: makebin emitted gsinit
|
|
733
|
+
// at $0000 and the di/im 1/SP-init/ISR vectors were GONE — it booted in a
|
|
734
|
+
// BIOS-less emulator by accident (gsinit happened to sit at the reset
|
|
735
|
+
// vector) but had no working IRQ/NMI/pause handling and was one EI away
|
|
736
|
+
// from jumping into garbage on real hardware.
|
|
737
|
+
const codeLoc = args.codeLoc ?? (
|
|
738
|
+
args.platform === "msx" ? MSX_CODE_LOC
|
|
739
|
+
: (args.platform === "sms" || args.platform === "gg") ? 0x0100
|
|
740
|
+
: 0x0000);
|
|
731
741
|
const romSize = SDCC_ROM_SIZE[args.platform] ?? 32 * 1024;
|
|
732
742
|
|
|
733
743
|
// crt0 + headers + sources come straight from the caller. The build
|
|
@@ -809,32 +819,51 @@ export async function buildForPlatform(args) {
|
|
|
809
819
|
// rejected it. Checksum = sum of bytes $0000..$7FEF (everything before
|
|
810
820
|
// the header), stored little-endian. GG BIOS doesn't check, but writing
|
|
811
821
|
// it is harmless. Only touches ROMs that actually have the header.
|
|
812
|
-
if (binary && r.exitCode === 0 && (args.platform === "sms" || args.platform === "gg")
|
|
822
|
+
if (binary && r.exitCode === 0 && (args.platform === "sms" || args.platform === "gg")) {
|
|
823
|
+
// Pad to a full 32KB bank FIRST. sdld emits up to the highest used
|
|
824
|
+
// address, so a small program can come out under $8000 — which (a)
|
|
825
|
+
// skipped this whole header block before (the header guard required
|
|
826
|
+
// 32KB) and (b) odd-size ROMs misbehave on real mappers/flashcarts.
|
|
827
|
+
if (binary.length < 0x8000) {
|
|
828
|
+
const padded = new Uint8Array(0x8000);
|
|
829
|
+
padded.set(binary);
|
|
830
|
+
binary = padded;
|
|
831
|
+
}
|
|
813
832
|
const hdr = 0x7FF0;
|
|
814
833
|
const hasHeader = String.fromCharCode(...binary.slice(hdr, hdr + 8)) === "TMR SEGA";
|
|
834
|
+
// Region nibble is PLATFORM-SPECIFIC and load-bearing: 4 = SMS export,
|
|
835
|
+
// 7 = GG international. A .gg ROM stamped with an SMS region (3/4) makes
|
|
836
|
+
// Genesis Plus GX (RetroArch/RetroDECK's SMS+GG core) boot it in "GG
|
|
837
|
+
// running SMS software" COMPATIBILITY mode — wrong video mode + wrong
|
|
838
|
+
// CRAM format for a native-GG program → black/garbled screen on the
|
|
839
|
+
// user's device while our BIOS-less host looked fine. Size nibble $C =
|
|
840
|
+
// 32KB checksum range ($0000-$7FEF).
|
|
841
|
+
const regionSize = args.platform === "gg" ? 0x7C : 0x4C;
|
|
815
842
|
if (!hasHeader) {
|
|
816
843
|
// No header emitted by the crt0 → write a complete TMR SEGA header
|
|
817
844
|
// into the last 16 bytes of bank 0 ($7FF0-$7FFF). Without this the
|
|
818
845
|
// export (US/EU) SMS BIOS shows "SOFTWARE ERROR" and refuses to run.
|
|
819
846
|
// $7FF0-$7FF7 "TMR SEGA"; $7FF8-$7FF9 reserved ($00); $7FFA-$7FFB
|
|
820
847
|
// checksum (filled below); $7FFC-$7FFE product code/version (zeros
|
|
821
|
-
// ok for homebrew); $7FFF region+size
|
|
822
|
-
// size $C = 32KB, the checksum range that covers $0000-$7FEF).
|
|
848
|
+
// ok for homebrew); $7FFF region+size (see regionSize above).
|
|
823
849
|
const TMR = [0x54,0x4D,0x52,0x20,0x53,0x45,0x47,0x41]; // "TMR SEGA"
|
|
824
850
|
for (let i = 0; i < 8; i++) binary[hdr + i] = TMR[i];
|
|
825
851
|
binary[hdr + 8] = 0x00; binary[hdr + 9] = 0x00; // reserved
|
|
826
852
|
binary[hdr + 12] = 0x00; binary[hdr + 13] = 0x00; // product code lo
|
|
827
853
|
binary[hdr + 14] = 0x00; // product/version
|
|
828
|
-
binary[hdr + 15] = 0x4C; // region 4 (export) + size $C (32KB)
|
|
829
854
|
}
|
|
855
|
+
// Always stamp the platform-correct region/size — a crt0-provided header
|
|
856
|
+
// with an SMS region on a .gg build has the same compat-mode problem.
|
|
857
|
+
binary[hdr + 15] = regionSize;
|
|
830
858
|
// Checksum = sum of bytes $0000..$7FEF (everything before the header),
|
|
831
|
-
// stored little-endian at $7FFA.
|
|
832
|
-
// range, so the BIOS checksums $0000-$7FEF.
|
|
859
|
+
// stored little-endian at $7FFA. Size nibble $C declares the 32KB
|
|
860
|
+
// range, so the BIOS checksums $0000-$7FEF. (The GG BIOS doesn't
|
|
861
|
+
// checksum, but writing it is harmless and correct.)
|
|
833
862
|
let sum = 0;
|
|
834
863
|
for (let i = 0; i < 0x7FF0; i++) sum = (sum + binary[i]) & 0xFFFF;
|
|
835
864
|
binary[0x7FFA] = sum & 0xFF;
|
|
836
865
|
binary[0x7FFB] = (sum >> 8) & 0xFF;
|
|
837
|
-
r.log += `\n---
|
|
866
|
+
r.log += `\n--- ${args.platform.toUpperCase()} header ${hasHeader ? "checksum fixed" : "written + checksummed"} ($7FFA=${sum.toString(16).toUpperCase().padStart(4,"0")}, region/size=$${regionSize.toString(16).toUpperCase()}) ---`;
|
|
838
867
|
}
|
|
839
868
|
// MSX: the binary built with codeLoc=$4010 is a $4000-based page image.
|
|
840
869
|
// SDCC/sdldz80 emit an ihx that, converted to bin, starts at the lowest
|