romdevtools 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/AGENTS.md +51 -41
  2. package/CHANGELOG.md +46 -0
  3. package/README.md +3 -3
  4. package/examples/README.md +7 -7
  5. package/examples/atari2600/templates/platformer.asm +1225 -332
  6. package/examples/atari2600/templates/puzzle.asm +1056 -0
  7. package/examples/atari2600/templates/racing.asm +906 -275
  8. package/examples/atari2600/templates/shmup.asm +1031 -239
  9. package/examples/atari2600/templates/sports.asm +1135 -253
  10. package/examples/atari7800/templates/platformer.c +991 -156
  11. package/examples/atari7800/templates/puzzle.c +1091 -148
  12. package/examples/atari7800/templates/racing.c +952 -124
  13. package/examples/atari7800/templates/shmup.c +812 -134
  14. package/examples/atari7800/templates/sports.c +820 -184
  15. package/examples/c64/templates/platformer.c +879 -164
  16. package/examples/c64/templates/puzzle.c +855 -178
  17. package/examples/c64/templates/racing.c +873 -97
  18. package/examples/c64/templates/shmup.c +757 -161
  19. package/examples/c64/templates/sports.c +755 -100
  20. package/examples/gb/templates/platformer.c +841 -179
  21. package/examples/gb/templates/puzzle.c +986 -246
  22. package/examples/gb/templates/racing.c +754 -174
  23. package/examples/gb/templates/shmup.c +673 -175
  24. package/examples/gb/templates/sports.c +790 -159
  25. package/examples/gba/templates/platformer.c +626 -165
  26. package/examples/gba/templates/puzzle.c +519 -269
  27. package/examples/gba/templates/racing.c +511 -206
  28. package/examples/gba/templates/shmup.c +564 -179
  29. package/examples/gba/templates/sports.c +454 -174
  30. package/examples/gbc/templates/platformer.c +944 -180
  31. package/examples/gbc/templates/puzzle.c +363 -109
  32. package/examples/gbc/templates/racing.c +884 -180
  33. package/examples/gbc/templates/shmup.c +821 -185
  34. package/examples/gbc/templates/sports.c +870 -162
  35. package/examples/genesis/templates/platformer.c +747 -129
  36. package/examples/genesis/templates/puzzle.c +694 -261
  37. package/examples/genesis/templates/racing.c +726 -203
  38. package/examples/genesis/templates/shmup.c +535 -142
  39. package/examples/genesis/templates/sports.c +495 -158
  40. package/examples/gg/templates/platformer.c +880 -215
  41. package/examples/gg/templates/puzzle.c +875 -216
  42. package/examples/gg/templates/racing.c +915 -172
  43. package/examples/gg/templates/shmup.c +714 -191
  44. package/examples/gg/templates/sports.c +732 -129
  45. package/examples/lynx/templates/platformer.c +604 -69
  46. package/examples/lynx/templates/puzzle.c +498 -158
  47. package/examples/lynx/templates/racing.c +538 -102
  48. package/examples/lynx/templates/shmup.c +458 -131
  49. package/examples/lynx/templates/sports.c +496 -72
  50. package/examples/msx/platformer/main.c +649 -162
  51. package/examples/msx/puzzle/main.c +742 -240
  52. package/examples/msx/racing/main.c +669 -178
  53. package/examples/msx/shmup/main.c +460 -178
  54. package/examples/msx/sports/main.c +592 -126
  55. package/examples/nes/templates/platformer.c +589 -171
  56. package/examples/nes/templates/puzzle.c +563 -242
  57. package/examples/nes/templates/racing.c +502 -208
  58. package/examples/nes/templates/shmup.c +339 -145
  59. package/examples/nes/templates/sports.c +341 -183
  60. package/examples/pce/platformer/main.c +874 -205
  61. package/examples/pce/puzzle/main.c +802 -287
  62. package/examples/pce/racing/main.c +783 -208
  63. package/examples/pce/shmup/main.c +638 -212
  64. package/examples/pce/sports/main.c +586 -169
  65. package/examples/porting-across-platforms/README.md +1 -1
  66. package/examples/sms/templates/platformer.c +762 -177
  67. package/examples/sms/templates/puzzle.c +752 -212
  68. package/examples/sms/templates/racing.c +808 -145
  69. package/examples/sms/templates/shmup.c +599 -162
  70. package/examples/sms/templates/sports.c +630 -122
  71. package/examples/snes/templates/music_demo.c +7 -0
  72. package/examples/snes/templates/platformer-data.asm +123 -24
  73. package/examples/snes/templates/platformer-hdr.asm +57 -0
  74. package/examples/snes/templates/platformer.c +586 -165
  75. package/examples/snes/templates/puzzle-data.asm +116 -21
  76. package/examples/snes/templates/puzzle-hdr.asm +57 -0
  77. package/examples/snes/templates/puzzle.c +614 -235
  78. package/examples/snes/templates/racing-data.asm +390 -32
  79. package/examples/snes/templates/racing-hdr.asm +57 -0
  80. package/examples/snes/templates/racing.c +807 -196
  81. package/examples/snes/templates/shmup-data.asm +87 -29
  82. package/examples/snes/templates/shmup-hdr.asm +57 -0
  83. package/examples/snes/templates/shmup.c +459 -198
  84. package/examples/snes/templates/sports-data.asm +48 -2
  85. package/examples/snes/templates/sports-hdr.asm +57 -0
  86. package/examples/snes/templates/sports.c +414 -163
  87. package/package.json +1 -1
  88. package/src/host/LibretroHost.js +59 -1
  89. package/src/http/tool-registry.js +11 -11
  90. package/src/mcp/tools/cheats.js +2 -1
  91. package/src/mcp/tools/frame.js +3 -2
  92. package/src/mcp/tools/index.js +3 -3
  93. package/src/mcp/tools/input.js +5 -4
  94. package/src/mcp/tools/lifecycle.js +6 -4
  95. package/src/mcp/tools/platform-docs.js +1 -1
  96. package/src/mcp/tools/preview-tile.js +6 -2
  97. package/src/mcp/tools/project.js +1098 -130
  98. package/src/mcp/tools/rom-id.js +5 -1
  99. package/src/mcp/tools/run-until.js +4 -2
  100. package/src/mcp/tools/snippets.js +6 -6
  101. package/src/mcp/tools/sprite-pipeline.js +14 -2
  102. package/src/mcp/tools/state.js +2 -1
  103. package/src/mcp/tools/tile-inspect.js +8 -1
  104. package/src/mcp/tools/toolchain.js +12 -1
  105. package/src/mcp/tools/watch-memory.js +4 -3
  106. package/src/observer/bus.js +73 -0
  107. package/src/observer/livestream.html +4 -2
  108. package/src/observer/tool-wrap.js +17 -14
  109. package/src/platforms/atari7800/MENTAL_MODEL.md +5 -5
  110. package/src/platforms/atari7800/TROUBLESHOOTING.md +5 -5
  111. package/src/platforms/c64/MENTAL_MODEL.md +11 -4
  112. package/src/platforms/c64/TROUBLESHOOTING.md +13 -0
  113. package/src/platforms/gb/MENTAL_MODEL.md +3 -3
  114. package/src/platforms/gb/TROUBLESHOOTING.md +61 -8
  115. package/src/platforms/gb/lib/c/README.md +10 -11
  116. package/src/platforms/gb/lib/c/gb_crt0.s +27 -3
  117. package/src/platforms/gb/lib/c/patch-header.js +13 -3
  118. package/src/platforms/gba/MENTAL_MODEL.md +4 -4
  119. package/src/platforms/gba/TROUBLESHOOTING.md +3 -3
  120. package/src/platforms/gba/lib/c/gba_sfx.c +40 -0
  121. package/src/platforms/gba/lib/c/gba_sfx.h +10 -0
  122. package/src/platforms/gbc/MENTAL_MODEL.md +4 -4
  123. package/src/platforms/gbc/TROUBLESHOOTING.md +4 -4
  124. package/src/platforms/gbc/UPSTREAM_SOURCES.md +1 -1
  125. package/src/platforms/gbc/lib/c/README.md +10 -11
  126. package/src/platforms/gbc/lib/c/gb_crt0.s +26 -3
  127. package/src/platforms/gbc/lib/c/patch-header.js +13 -3
  128. package/src/platforms/genesis/MENTAL_MODEL.md +3 -3
  129. package/src/platforms/genesis/TROUBLESHOOTING.md +2 -2
  130. package/src/platforms/gg/MENTAL_MODEL.md +4 -4
  131. package/src/platforms/gg/TROUBLESHOOTING.md +3 -3
  132. package/src/platforms/gg/UPSTREAM_SOURCES.md +1 -1
  133. package/src/platforms/gg/lib/c/joypad_read.c +29 -0
  134. package/src/platforms/lynx/MENTAL_MODEL.md +1 -1
  135. package/src/platforms/lynx/TROUBLESHOOTING.md +3 -3
  136. package/src/platforms/msx/MENTAL_MODEL.md +5 -5
  137. package/src/platforms/msx/TROUBLESHOOTING.md +2 -2
  138. package/src/platforms/msx/lib/c/msx_hw.h +1 -0
  139. package/src/platforms/msx/lib/c/msx_vdp.c +25 -0
  140. package/src/platforms/nes/MENTAL_MODEL.md +2 -2
  141. package/src/platforms/nes/lib/c/nes_runtime.c +149 -34
  142. package/src/platforms/nes/lib/c/nes_runtime.h +34 -1
  143. package/src/platforms/pce/MENTAL_MODEL.md +5 -5
  144. package/src/platforms/pce/TROUBLESHOOTING.md +1 -1
  145. package/src/platforms/pce/lib/c/pce_hw.h +11 -0
  146. package/src/platforms/pce/lib/c/pce_video.c +32 -0
  147. package/src/platforms/sms/MENTAL_MODEL.md +6 -6
  148. package/src/platforms/snes/MENTAL_MODEL.md +2 -2
  149. package/src/platforms/snes/TROUBLESHOOTING.md +40 -1
  150. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +13 -8
  151. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.crt0.s +58 -5
  152. package/src/toolchains/cc65/presets/nes/chr-rom.crt0.s +52 -3
  153. package/src/toolchains/cc65/presets/pce/rom32k.cfg +52 -0
  154. package/src/toolchains/index.js +27 -11
@@ -1,26 +1,64 @@
1
- ; ── shmup-data.asm — font + 3-sprite blob for shmup.c ─────────────
1
+ ; ── shmup-data.asm — SOLAR BULWARK's assembly half ───────────────────────────
2
+ ;
3
+ ; What lives here (and why it can't live in shmup.c):
4
+ ; 1. sram_read16/sram_write16 — battery SRAM accessors. SRAM sits at
5
+ ; $70:0000 (declared in hdr.asm — see shmup-hdr.asm), reachable only
6
+ ; with long (24-bit) addressing, which tcc C pointers don't emit.
7
+ ; 2. Font + sprite tiles + starfield tiles (rodata).
2
8
  ;
3
9
  ; tilsprite contains three 8×8 4bpp tiles back-to-back:
4
- ; tile 0 (offset 0) — ship (palette colour 1, mid-blue)
10
+ ; tile 0 (offset 0) — ship (palette colour 1; P2 reuses the SAME tile
11
+ ; through OBJ palette 1 — see shmup.c)
5
12
  ; tile 1 (offset 32) — bullet (palette colour 2, yellow)
6
- ; tile 2 (offset 64) — enemy (palette colour 3, red)
13
+ ; tile 2 (offset 64) — enemy (palette colour 3)
14
+ ;
15
+ ; Each 8×8 4bpp tile = 32 bytes: 8 rows of plane0/plane1 byte pairs, then
16
+ ; 8 rows of plane2/plane3 pairs. Colour index bits: p0=1, p1=2, p2=4, p3=8.
7
17
  ;
8
- ; Each 8×8 4bpp tile = 32 bytes (4 bitplanes × 8 rows × 1 byte).
9
- ; SNES interleaves planes 0+1 first (16 bytes), then 2+3 (16 bytes).
18
+ ; Section names must stay unique vs snes_sfx_data.asm (also linked in).
10
19
 
11
20
  .include "hdr.asm"
12
21
 
22
+ .SECTION ".shmup_asm" SUPERFREE
23
+
24
+ ; ── HARDWARE IDIOM (load-bearing) — battery SRAM accessors ──────────────────
25
+ ; SRAM is mapped at $70:0000 (LoROM, SRAMSIZE $01 in shmup-hdr.asm = 2 KB).
26
+ ; Long addressing only — there is no SRAM mirror in the program banks, which
27
+ ; is why these are asm and not C. tcc calling convention: u16 arg at 5,s
28
+ ; (after the 4-byte rtl frame), second arg at 7,s; u16 return in tcc__r0.
29
+
30
+ ; u16 sram_read16(u16 offset)
31
+ sram_read16:
32
+ php
33
+ rep #$30
34
+ lda 5,s ; offset
35
+ tax
36
+ sep #$20
37
+ lda.l $700000,x
38
+ sta.w tcc__r0
39
+ lda.l $700001,x
40
+ sta.w tcc__r0 + 1
41
+ plp
42
+ rtl
43
+
44
+ ; void sram_write16(u16 offset, u16 value)
45
+ sram_write16:
46
+ php
47
+ rep #$30
48
+ lda 5,s ; offset
49
+ tax
50
+ lda 7,s ; value
51
+ sep #$20
52
+ sta.l $700000,x ; low byte
53
+ xba
54
+ sta.l $700001,x ; high byte
55
+ plp
56
+ rtl
57
+
58
+ .ENDS
59
+
13
60
  .section ".rodata1" superfree
14
61
 
15
- ; ⚠ KNOWN ISSUE (text-BG HUD): this is a STUB font. consoleInitText DMAs
16
- ; 3072 bytes from here into VRAM; with only a stub, it reads past into
17
- ; adjacent data → a garbage font → the text BG shows a junk checkerboard
18
- ; AND the HUD text is unreadable. The real fix is to ship PVSnesLib's
19
- ; open-source bitmap font: convert pvsneslibfont.png with gfx2snes and
20
- ; `.incbin "pvsneslibfont.pic"` / `.pal` here (see the official PVSnesLib
21
- ; hello_world example). Tracked as R7(c) follow-up. The GAME itself
22
- ; (sprites, motion, input, collision, sound) renders + plays correctly;
23
- ; only the on-BG HUD text is affected.
24
62
  tilfont:
25
63
  ; 8x8 4bpp console font, 96 glyphs (ASCII 0x20-0x7F). consoleInitText
26
64
  ; DMAs exactly 3072 bytes (96 tiles x 32 bytes, 4bpp) from here into
@@ -351,26 +389,46 @@ palsprite:
351
389
  .db $00, $00, $00, $00, $00, $00, $00, $00
352
390
  .db $00, $00, $00, $00, $00, $00, $00, $00
353
391
 
354
- ; ── Background wallpaper (one 8×8 4bpp tile, 4 solid colour quadrants) ──
355
- ; Tiled across BG1 it paints the whole screen in four muted colours so the
356
- ; playfield never reads as a flat/blank backdrop. Quadrant→colour: TL=1,
357
- ; TR=2, BL=3, BR=4. 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1
358
- ; pairs, bytes 16-31 = rows 0-7 plane2/plane3 pairs.
392
+ ; ── Starfield tiles (four 8×8 4bpp tiles) ───────────────────────────────────
393
+ ; shmup.c checkers tiles 0/1 across BG1 (two near-black space tones no
394
+ ; single colour ever dominates the frame, which keeps render-health checks
395
+ ; honest) and scatters tiles 2/3 (stars) with its LFSR. The whole field then
396
+ ; scrolls in hardware (BG1VOFS) while the BG0 text HUD stays put.
397
+ ; 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1 pairs, bytes 16-31 =
398
+ ; rows 0-7 plane2/plane3 pairs. Colour bits: p0=1, p1=2, p2=4, p3=8.
359
399
  tilbg:
360
- .db $F0, $0F, $F0, $0F, $F0, $0F, $F0, $0F ; rows 0-3: p0=left p1=right
361
- .db $F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0 ; rows 4-7: p0+p1 = left
362
- .db $00, $00, $00, $00, $00, $00, $00, $00 ; rows 0-3: p2/p3 = 0
363
- .db $0F, $00, $0F, $00, $0F, $00, $0F, $00 ; rows 4-7: p2 = right
400
+ ; tile 0 space tone A (solid colour 1, one dim speckle = colour 3)
401
+ .db $FF, $00, $FF, $00, $FF, $00, $FF, $00 ; rows 0-3: p0 set = colour 1
402
+ .db $FF, $00, $FF, $08, $FF, $00, $FF, $00 ; row 5: p1 bit → colour 3 dot
403
+ .db $00, $00, $00, $00, $00, $00, $00, $00
404
+ .db $00, $00, $00, $00, $00, $00, $00, $00
405
+ ; tile 1 — space tone B (solid colour 2, one dim speckle = colour 3)
406
+ .db $00, $FF, $00, $FF, $10, $FF, $00, $FF ; row 2: p0 bit → colour 3 dot
407
+ .db $00, $FF, $00, $FF, $00, $FF, $00, $FF
408
+ .db $00, $00, $00, $00, $00, $00, $00, $00
409
+ .db $00, $00, $00, $00, $00, $00, $00, $00
410
+ ; tile 2 — bright star on tone A (cross of colour 5 = p0+p2, white)
411
+ .db $FF, $00, $FF, $00, $FF, $00, $FF, $00
412
+ .db $FF, $00, $FF, $00, $FF, $00, $FF, $00
413
+ .db $00, $00, $00, $00, $10, $00, $38, $00 ; rows 2-4: p2 star cross
414
+ .db $10, $00, $00, $00, $00, $00, $00, $00
415
+ ; tile 3 — gold star on tone B (cross of colour 6 = p1+p2, pale gold)
416
+ .db $00, $FF, $00, $FF, $00, $FF, $00, $FF
417
+ .db $00, $FF, $00, $FF, $00, $FF, $00, $FF
418
+ .db $00, $00, $00, $00, $00, $00, $00, $00
419
+ .db $08, $00, $1C, $00, $08, $00, $00, $00 ; rows 4-6: p2 star cross
364
420
 
365
421
  palbg:
366
- ; 16-colour BG palette; only 1-4 used (the four wallpaper quadrant tones).
422
+ ; 16-colour BG palette (BGR555); 1-2 = space tones, 3 = speckle, 5-6 = stars.
367
423
  .db $00, $00 ; 0 unused (BG fully opaque)
368
- .db $C4, $30 ; 1 dark blue
369
- .db $42, $29 ; 2 dark teal
370
- .db $88, $30 ; 3 dark purple
371
- .db $C6, $24 ; 4 dark slate
424
+ .db $62, $24 ; 1 space tone A (deep blue)
425
+ .db $45, $20 ; 2 space tone B (deep indigo)
426
+ .db $6A, $41 ; 3 dim speckle (grey-blue)
427
+ .db $00, $00 ; 4 unused
428
+ .db $FF, $7F ; 5 bright star (white)
429
+ .db $9E, $43 ; 6 gold star (pale gold)
372
430
  .db $00, $00, $00, $00, $00, $00, $00, $00
373
431
  .db $00, $00, $00, $00, $00, $00, $00, $00
374
- .db $00, $00, $00, $00, $00, $00
432
+ .db $00, $00
375
433
 
376
434
  .ends
@@ -0,0 +1,57 @@
1
+ ;==LoRom== shmup hdr.asm — PROJECT OVERRIDE of PVSnesLib's stock header
2
+ ;
3
+ ; Why this file exists: the stock include/hdr.asm declares CARTRIDGETYPE $00
4
+ ; (ROM only) and SRAMSIZE $00. The SNES cart header is the ONLY place battery
5
+ ; SRAM gets declared — snes9x (and real flash carts) size the save RAM from
6
+ ; these two bytes. Delete this file and the build still succeeds, the game
7
+ ; still runs, and saves silently stop existing: sram_read16/sram_write16 hit
8
+ ; open bus at $70:0000 and the hi-score never survives a power cycle.
9
+ ;
10
+ ; Everything except CARTRIDGETYPE/SRAMSIZE/NAME is byte-identical to the
11
+ ; stock header — the memory map and vectors MUST match what PVSnesLib's
12
+ ; crt0/libs were assembled against, or wlalink places sections inconsistently.
13
+
14
+ .MEMORYMAP ; Begin describing the system architecture.
15
+ SLOTSIZE $8000 ; ROM slot is $8000 bytes (LoROM 32K banks).
16
+ DEFAULTSLOT 0
17
+ SLOT 0 $8000 ; ROM
18
+ SLOT 1 $0 $2000 ; low WRAM mirror (tcc registers live at $0000)
19
+ SLOT 2 $2000 $E000 ; WRAM $2000-$FFFF
20
+ SLOT 3 $0 $10000 ; bank $7F WRAM (tcc C globals)
21
+ .ENDME
22
+
23
+ .ROMBANKSIZE $8000 ; 32 KByte ROM banks
24
+ .ROMBANKS 8 ; 2 Mbits (256 KB) — matches PVSnesLib stock
25
+
26
+ .SNESHEADER
27
+ ID "SNES"
28
+
29
+ NAME "SOLAR BULWARK " ; Program Title - 21 bytes, space-padded.
30
+ ; "123456789012345678901"
31
+
32
+ SLOWROM
33
+ LOROM
34
+
35
+ CARTRIDGETYPE $02 ; $02 = ROM + SRAM + battery ← THE SAVE SWITCH
36
+ ROMSIZE $08 ; $08 = 2 Mbits
37
+ SRAMSIZE $01 ; $01 = 2 KB SRAM, mapped at $70:0000-$07FF
38
+ COUNTRY $01 ; $01 = U.S.
39
+ LICENSEECODE $00
40
+ VERSION $00
41
+ .ENDSNES
42
+
43
+ .SNESNATIVEVECTOR ; Native Mode interrupt vector table
44
+ COP EmptyHandler
45
+ BRK EmptyHandler
46
+ ABORT EmptyHandler
47
+ NMI VBlank ; PVSnesLib's vblank.asm handler
48
+ IRQ EmptyHandler
49
+ .ENDNATIVEVECTOR
50
+
51
+ .SNESEMUVECTOR ; Emulation Mode interrupt vector table
52
+ COP EmptyHandler
53
+ ABORT EmptyHandler
54
+ NMI EmptyHandler
55
+ RESET tcc__start ; PVSnesLib crt0 entry
56
+ IRQBRK EmptyHandler
57
+ .ENDEMUVECTOR