romdevtools 0.15.0 → 0.21.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 (117) hide show
  1. package/AGENTS.md +61 -13
  2. package/CHANGELOG.md +289 -0
  3. package/README.md +1 -1
  4. package/examples/README.md +2 -0
  5. package/examples/atari2600/templates/platformer.asm +460 -0
  6. package/examples/atari2600/templates/racing.asm +463 -0
  7. package/examples/atari2600/templates/shmup.asm +386 -0
  8. package/examples/atari2600/templates/sports.asm +362 -0
  9. package/examples/atari7800/templates/default.c +49 -5
  10. package/examples/atari7800/templates/platformer.c +43 -4
  11. package/examples/atari7800/templates/puzzle.c +39 -4
  12. package/examples/atari7800/templates/racing.c +39 -4
  13. package/examples/atari7800/templates/shmup.c +40 -2
  14. package/examples/atari7800/templates/sports.c +36 -5
  15. package/examples/c64/templates/platformer.c +19 -5
  16. package/examples/c64/templates/puzzle.c +32 -2
  17. package/examples/c64/templates/shmup.c +28 -2
  18. package/examples/c64/templates/sports.c +30 -2
  19. package/examples/gb/templates/default.c +110 -16
  20. package/examples/gb/templates/platformer.c +25 -4
  21. package/examples/gb/templates/puzzle.c +32 -2
  22. package/examples/gb/templates/racing.c +72 -8
  23. package/examples/gb/templates/shmup.c +38 -1
  24. package/examples/gb/templates/sports.c +48 -1
  25. package/examples/gba/templates/gba_hello.c +29 -11
  26. package/examples/gba/templates/puzzle.c +15 -3
  27. package/examples/gba/templates/racing.c +65 -3
  28. package/examples/gba/templates/shmup.c +41 -4
  29. package/examples/gba/templates/sports.c +36 -2
  30. package/examples/gba/templates/tonc_hello.c +41 -5
  31. package/examples/gbc/templates/default.c +103 -26
  32. package/examples/gbc/templates/platformer.c +25 -4
  33. package/examples/gbc/templates/puzzle.c +32 -2
  34. package/examples/gbc/templates/racing.c +85 -19
  35. package/examples/gbc/templates/shmup.c +34 -1
  36. package/examples/gbc/templates/sports.c +45 -1
  37. package/examples/genesis/templates/puzzle.c +37 -3
  38. package/examples/genesis/templates/racing.c +44 -11
  39. package/examples/genesis/templates/sgdk_hello.c +34 -1
  40. package/examples/genesis/templates/shmup.c +31 -1
  41. package/examples/gg/templates/default.c +56 -18
  42. package/examples/gg/templates/platformer.c +18 -12
  43. package/examples/gg/templates/puzzle.c +38 -7
  44. package/examples/gg/templates/racing.c +51 -5
  45. package/examples/gg/templates/shmup.c +47 -3
  46. package/examples/gg/templates/sports.c +46 -3
  47. package/examples/lynx/templates/default.c +39 -8
  48. package/examples/lynx/templates/puzzle.c +28 -1
  49. package/examples/lynx/templates/racing.c +34 -7
  50. package/examples/lynx/templates/shmup.c +42 -3
  51. package/examples/lynx/templates/sports.c +29 -2
  52. package/examples/msx/platformer/main.c +213 -0
  53. package/examples/msx/puzzle/main.c +250 -0
  54. package/examples/msx/racing/main.c +249 -0
  55. package/examples/msx/shmup/main.c +288 -0
  56. package/examples/msx/sports/main.c +182 -0
  57. package/examples/nes/templates/default.c +67 -19
  58. package/examples/nes/templates/platformer.c +65 -6
  59. package/examples/nes/templates/puzzle.c +67 -6
  60. package/examples/nes/templates/racing.c +45 -13
  61. package/examples/nes/templates/shmup.c +51 -2
  62. package/examples/nes/templates/sports.c +51 -6
  63. package/examples/pce/platformer/main.c +283 -0
  64. package/examples/pce/puzzle/main.c +304 -0
  65. package/examples/pce/racing/main.c +304 -0
  66. package/examples/pce/shmup/main.c +346 -0
  67. package/examples/pce/sports/main.c +254 -0
  68. package/examples/sms/main.c +35 -6
  69. package/examples/sms/templates/puzzle.c +34 -5
  70. package/examples/sms/templates/racing.c +39 -2
  71. package/examples/sms/templates/shmup.c +41 -2
  72. package/examples/sms/templates/sports.c +43 -2
  73. package/examples/snes/templates/default.c +50 -28
  74. package/examples/snes/templates/platformer-data.asm +22 -0
  75. package/examples/snes/templates/platformer.c +16 -1
  76. package/examples/snes/templates/puzzle-data.asm +22 -0
  77. package/examples/snes/templates/puzzle.c +17 -1
  78. package/examples/snes/templates/racing-data.asm +22 -0
  79. package/examples/snes/templates/racing.c +17 -1
  80. package/examples/snes/templates/shmup-data.asm +22 -0
  81. package/examples/snes/templates/shmup.c +20 -1
  82. package/examples/snes/templates/sports-data.asm +22 -0
  83. package/examples/snes/templates/sports.c +16 -1
  84. package/package.json +1 -1
  85. package/src/cores/wasm/vice_x64_libretro.js +1 -1
  86. package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
  87. package/src/host/LibretroHost.js +122 -1
  88. package/src/host/callbacks.js +9 -1
  89. package/src/host/types.js +15 -8
  90. package/src/http/skill-doc.js +1 -1
  91. package/src/http/tool-registry.js +27 -2
  92. package/src/mcp/tools/cart-parts.js +75 -3
  93. package/src/mcp/tools/disasm-rebuild.js +507 -0
  94. package/src/mcp/tools/disasm.js +95 -6
  95. package/src/mcp/tools/frame.js +168 -3
  96. package/src/mcp/tools/index.js +4 -4
  97. package/src/mcp/tools/lifecycle.js +4 -2
  98. package/src/mcp/tools/project.js +54 -9
  99. package/src/mcp/tools/state.js +201 -14
  100. package/src/mcp/tools/toolchain.js +89 -4
  101. package/src/mcp/tools/watch-memory.js +125 -14
  102. package/src/platforms/c64/MENTAL_MODEL.md +45 -1
  103. package/src/platforms/c64/d64.js +281 -0
  104. package/src/platforms/gb/MENTAL_MODEL.md +10 -0
  105. package/src/platforms/msx/MENTAL_MODEL.md +10 -6
  106. package/src/platforms/nes/MENTAL_MODEL.md +63 -2
  107. package/src/platforms/pce/MENTAL_MODEL.md +9 -4
  108. package/src/platforms/pce/lib/c/pce_video.c +1 -1
  109. package/src/rom-id/identifier.js +15 -0
  110. package/src/toolchains/cc65/cc65.js +8 -1
  111. package/src/toolchains/cc65/ines.js +145 -0
  112. package/src/toolchains/cc65/presets/nes/chr-rom.cfg +83 -0
  113. package/src/toolchains/cc65/presets/nes/chr-rom.crt0.s +153 -0
  114. package/src/toolchains/common/reassemble.js +10 -2
  115. package/src/toolchains/gba-c/gba-c.js +6 -1
  116. package/src/toolchains/genesis-c/genesis-c.js +10 -2
  117. package/src/toolchains/parse-errors.js +67 -5
@@ -0,0 +1,386 @@
1
+ ; ── shmup.asm — Atari 2600 SHMUP genre scaffold ─────────────────────
2
+ ;
3
+ ; The 2600's flagship genre — Space Invaders, Galaxian, Demon Attack
4
+ ; were all fixed/gallery shooters, because that is exactly what the TIA
5
+ ; is good at. This is the canonical 2600 shmup, identical in spirit to
6
+ ; the verified `mini_invaders` template.
7
+ ;
8
+ ; A fixed-shooter / gallery-shooter 2600 game that uses the RIGHT TIA
9
+ ; objects instead of playfield "barcode" bars (see the note at the bottom).
10
+ ;
11
+ ; TIA object roles (the canonical layout for this genre):
12
+ ; P0 = player cannon (double-width via NUSIZ0 = %00000111)
13
+ ; P1 + NUSIZ1 = %011 (3 medium-spaced copies) = a ROW OF INVADERS
14
+ ; → one GRP1 write draws three aliens, hardware-replicated.
15
+ ; M0 = the player's shot
16
+ ; PF = a thin ground line only (NOT the aliens — playfield bits look
17
+ ; like a barcode; real sprites read as actual invaders).
18
+ ;
19
+ ; The aliens march left/right as a block (move P1's X), drop a step at
20
+ ; the edges, and you shoot upward with the joystick button. This is the
21
+ ; deliberately-small but visually-honest version of the genre on the
22
+ ; 2600 — extend it by reusing P1 again lower down for shields, or
23
+ ; adding M1 as an alien bomb.
24
+ ;
25
+ ; NTSC kernel: 3 VSYNC + 37 VBLANK + 192 visible + 30 overscan.
26
+
27
+ processor 6502
28
+ org $F000
29
+
30
+ VSYNC = $00
31
+ VBLANK = $01
32
+ WSYNC = $02
33
+ NUSIZ0 = $04
34
+ NUSIZ1 = $05
35
+ COLUP0 = $06
36
+ COLUP1 = $07
37
+ COLUPF = $08
38
+ COLUBK = $09
39
+ CTRLPF = $0A
40
+ RESP0 = $10
41
+ RESP1 = $11
42
+ RESM0 = $12
43
+ GRP0 = $1B
44
+ GRP1 = $1C
45
+ ENAM0 = $1D
46
+ PF0 = $0D
47
+ HMP0 = $20
48
+ HMP1 = $21
49
+ HMM0 = $22
50
+ HMOVE = $2A
51
+ HMCLR = $2B
52
+ SWCHA = $280
53
+ INPT4 = $0C ; P0 fire (active-low, bit 7)
54
+ AUDC0 = $15
55
+ AUDF0 = $17
56
+ AUDV0 = $19
57
+
58
+ ; Zero page
59
+ P_X = $80 ; player cannon X (visible column)
60
+ ALIEN_X = $81 ; left edge of the alien block (P1 X)
61
+ ALIEN_Y = $82 ; top scanline of the alien row
62
+ ALIEN_DIR = $83 ; 1 = right, $FF = left
63
+ SHOT_X = $84
64
+ SHOT_Y = $85 ; $FF = no shot active
65
+ FRAME = $86
66
+ MARCH = $87 ; march timer
67
+ SFX_LEFT = $88
68
+
69
+ START:
70
+ SEI
71
+ CLD
72
+ LDX #$FF
73
+ TXS
74
+ LDA #0
75
+ .clr:
76
+ STA $00,X
77
+ DEX
78
+ BNE .clr
79
+
80
+ LDA #76
81
+ STA P_X
82
+ LDA #40
83
+ STA ALIEN_X
84
+ LDA #60
85
+ STA ALIEN_Y
86
+ LDA #1
87
+ STA ALIEN_DIR
88
+ LDA #$FF
89
+ STA SHOT_Y ; no shot yet
90
+
91
+ ; Colours
92
+ LDA #$06 ; dark blue-grey bg
93
+ STA COLUBK
94
+ LDA #$1E ; yellow cannon
95
+ STA COLUP0
96
+ LDA #$46 ; red-ish aliens
97
+ STA COLUP1
98
+ LDA #$0A ; grey ground line
99
+ STA COLUPF
100
+
101
+ ; Object sizes: P0 double-width; P1 = 3 medium-spaced copies.
102
+ LDA #%00000101 ; NUSIZ0: P0 double size (2x width)
103
+ STA NUSIZ0
104
+ LDA #%00000011 ; NUSIZ1: three copies, medium spacing
105
+ STA NUSIZ1
106
+ LDA #1
107
+ STA CTRLPF ; PF reflected (symmetric ground)
108
+
109
+ MAIN:
110
+ INC FRAME
111
+
112
+ ; ── VSYNC (3 lines) ──
113
+ LDA #2
114
+ STA VSYNC
115
+ STA WSYNC
116
+ STA WSYNC
117
+ STA WSYNC
118
+ LDA #0
119
+ STA VSYNC
120
+
121
+ ; ── VBLANK (37 lines) — do all game logic here ──
122
+ LDA #2
123
+ STA VBLANK
124
+ LDX #37
125
+ .vb:
126
+ STA WSYNC
127
+ DEX
128
+ BNE .vb
129
+
130
+ ; Player move (every 2nd frame), joystick port A high nibble.
131
+ LDA FRAME
132
+ AND #$01
133
+ BNE .skipmove
134
+ LDA SWCHA
135
+ ASL ; bit7 = P0 Right
136
+ BCS .nr
137
+ LDA P_X
138
+ CMP #140
139
+ BCS .nr
140
+ INC P_X
141
+ INC P_X
142
+ .nr:
143
+ ASL ; bit6 = P0 Left
144
+ BCS .nl
145
+ LDA P_X
146
+ CMP #10
147
+ BCC .nl
148
+ DEC P_X
149
+ DEC P_X
150
+ .nl:
151
+ .skipmove:
152
+
153
+ ; Fire on button (INPT4 bit7 active-low) if no shot active.
154
+ LDA SHOT_Y
155
+ CMP #$FF
156
+ BNE .noFire
157
+ BIT INPT4
158
+ BMI .noFire ; bit7 set = not pressed
159
+ LDA P_X
160
+ CLC
161
+ ADC #4
162
+ STA SHOT_X
163
+ LDA #180
164
+ STA SHOT_Y
165
+ ; pew sfx
166
+ LDA #$04
167
+ STA AUDC0
168
+ LDA #$08
169
+ STA AUDF0
170
+ LDA #$0C
171
+ STA AUDV0
172
+ LDA #6
173
+ STA SFX_LEFT
174
+ .noFire:
175
+
176
+ ; Move shot up 4px/frame; despawn past the aliens.
177
+ LDA SHOT_Y
178
+ CMP #$FF
179
+ BEQ .noShotMove
180
+ SEC
181
+ SBC #4
182
+ STA SHOT_Y
183
+ CMP #50
184
+ BCS .noShotMove
185
+ LDA #$FF
186
+ STA SHOT_Y
187
+ .noShotMove:
188
+
189
+ ; March the alien block every 24 frames.
190
+ INC MARCH
191
+ LDA MARCH
192
+ CMP #24
193
+ BCC .noMarch
194
+ LDA #0
195
+ STA MARCH
196
+ LDA ALIEN_DIR
197
+ BMI .marchLeft
198
+ LDA ALIEN_X
199
+ CMP #96
200
+ BCS .flip ; hit right edge → reverse + drop
201
+ CLC
202
+ ADC #6
203
+ STA ALIEN_X
204
+ JMP .noMarch
205
+ .marchLeft:
206
+ LDA ALIEN_X
207
+ CMP #14
208
+ BCC .flip ; hit left edge → reverse + drop
209
+ SEC
210
+ SBC #6
211
+ STA ALIEN_X
212
+ JMP .noMarch
213
+ .flip:
214
+ ; Reverse direction and step the whole row DOWN one notch. ALIEN_Y is
215
+ ; the row's top scanline; SMALLER Y = lower on screen (Y counts 192→1),
216
+ ; so "drop" means decrement ALIEN_Y. Stop dropping once they reach the
217
+ ; player's row (game-over territory — kept simple here: clamp).
218
+ LDA ALIEN_DIR
219
+ EOR #$FE ; 1 <-> $FF
220
+ STA ALIEN_DIR
221
+ LDA ALIEN_Y
222
+ CMP #30
223
+ BCC .noMarch ; already near the bottom — don't go further
224
+ SEC
225
+ SBC #6
226
+ STA ALIEN_Y
227
+ .noMarch:
228
+
229
+ ; sfx countdown
230
+ LDA SFX_LEFT
231
+ BEQ .sfxDone
232
+ DEC SFX_LEFT
233
+ BNE .sfxDone
234
+ LDA #0
235
+ STA AUDV0
236
+ .sfxDone:
237
+
238
+ ; ── Position objects (race-the-beam) ──
239
+ ; P0 (player) at column P_X.
240
+ STA WSYNC
241
+ STA HMCLR
242
+ LDX P_X
243
+ LDA #0
244
+ .p0pos:
245
+ CPX #15
246
+ BCC .p0done
247
+ SEC
248
+ SBC #15
249
+ TAX
250
+ JMP .p0pos
251
+ .p0done:
252
+ STA RESP0
253
+ ; P1 (alien block) at column ALIEN_X.
254
+ STA WSYNC
255
+ LDX ALIEN_X
256
+ LDA #0
257
+ .p1pos:
258
+ CPX #15
259
+ BCC .p1done
260
+ SEC
261
+ SBC #15
262
+ TAX
263
+ JMP .p1pos
264
+ .p1done:
265
+ STA RESP1
266
+ ; M0 (shot) at column SHOT_X.
267
+ STA WSYNC
268
+ LDX SHOT_X
269
+ LDA #0
270
+ .m0pos:
271
+ CPX #15
272
+ BCC .m0done
273
+ SEC
274
+ SBC #15
275
+ TAX
276
+ JMP .m0pos
277
+ .m0done:
278
+ STA RESM0
279
+ STA HMOVE
280
+
281
+ LDA #0
282
+ STA VBLANK
283
+
284
+ ; ── Visible (192 lines) ──
285
+ LDY #192
286
+ .draw:
287
+ STA WSYNC
288
+
289
+ ; Player cannon: 8 rows around scanline 176 (near the bottom).
290
+ TYA
291
+ SEC
292
+ SBC #16 ; 192-176 region → small Y window near bottom
293
+ CMP #8
294
+ BCS .pBlank
295
+ TAX
296
+ LDA SHIP,X
297
+ STA GRP0
298
+ JMP .pDone
299
+ .pBlank:
300
+ LDA #0
301
+ STA GRP0
302
+ .pDone:
303
+
304
+ ; Alien row: 8 rows starting at ALIEN_Y, drawn via P1 (NUSIZ1 gives
305
+ ; 3 hardware copies, so one GRP1 write paints all three invaders).
306
+ ; Window: (Y - ALIEN_Y) in [0..7] → index into the ALIEN bitmap.
307
+ TYA
308
+ SEC
309
+ SBC ALIEN_Y
310
+ CMP #8
311
+ BCS .aBlank
312
+ TAX
313
+ LDA ALIEN,X
314
+ STA GRP1
315
+ JMP .aDone
316
+ .aBlank:
317
+ LDA #0
318
+ STA GRP1
319
+ .aDone:
320
+
321
+ ; Shot: enable M0 for 4 lines around SHOT_Y.
322
+ TYA
323
+ SEC
324
+ SBC SHOT_Y
325
+ CMP #4
326
+ BCS .sBlank
327
+ LDA #2
328
+ STA ENAM0
329
+ JMP .sDone
330
+ .sBlank:
331
+ LDA #0
332
+ STA ENAM0
333
+ .sDone:
334
+
335
+ ; Ground line near the very bottom via PF0.
336
+ CPY #6
337
+ BCS .noGround
338
+ LDA #$F0
339
+ STA PF0
340
+ JMP .gDone
341
+ .noGround:
342
+ LDA #0
343
+ STA PF0
344
+ .gDone:
345
+
346
+ DEY
347
+ BNE .draw
348
+
349
+ ; ── Overscan (30 lines) ──
350
+ LDA #2
351
+ STA VBLANK
352
+ LDX #30
353
+ .os:
354
+ STA WSYNC
355
+ DEX
356
+ BNE .os
357
+
358
+ JMP MAIN
359
+
360
+ ; 8-row cannon silhouette (double-width via NUSIZ0).
361
+ SHIP:
362
+ .byte %00011000
363
+ .byte %00011000
364
+ .byte %00111100
365
+ .byte %01111110
366
+ .byte %11111111
367
+ .byte %11111111
368
+ .byte %11111111
369
+ .byte %11100111
370
+
371
+ ; 8-row invader silhouette — drawn via P1 with NUSIZ1=%011 so it
372
+ ; hardware-replicates into 3 medium-spaced aliens from one GRP1 write.
373
+ ALIEN:
374
+ .byte %00100100
375
+ .byte %00111100
376
+ .byte %01111110
377
+ .byte %11011011
378
+ .byte %11111111
379
+ .byte %01011010
380
+ .byte %00100100
381
+ .byte %01000010
382
+
383
+ org $FFFA
384
+ .word START
385
+ .word START
386
+ .word START