romdevtools 0.27.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 (199) hide show
  1. package/AGENTS.md +56 -44
  2. package/CHANGELOG.md +355 -0
  3. package/README.md +4 -4
  4. package/examples/README.md +7 -7
  5. package/examples/atari2600/templates/platformer.asm +1227 -325
  6. package/examples/atari2600/templates/puzzle.asm +1056 -0
  7. package/examples/atari2600/templates/racing.asm +909 -257
  8. package/examples/atari2600/templates/shmup.asm +1035 -218
  9. package/examples/atari2600/templates/sports.asm +1143 -229
  10. package/examples/atari7800/templates/hello_sprite.c +8 -4
  11. package/examples/atari7800/templates/platformer.c +991 -152
  12. package/examples/atari7800/templates/puzzle.c +1091 -145
  13. package/examples/atari7800/templates/racing.c +949 -118
  14. package/examples/atari7800/templates/shmup.c +812 -130
  15. package/examples/atari7800/templates/sports.c +820 -181
  16. package/examples/c64/templates/platformer.c +876 -157
  17. package/examples/c64/templates/puzzle.c +881 -143
  18. package/examples/c64/templates/racing.c +873 -88
  19. package/examples/c64/templates/shmup.c +762 -154
  20. package/examples/c64/templates/sports.c +755 -95
  21. package/examples/gb/templates/platformer.c +841 -175
  22. package/examples/gb/templates/puzzle.c +1094 -176
  23. package/examples/gb/templates/racing.c +761 -169
  24. package/examples/gb/templates/shmup.c +679 -169
  25. package/examples/gb/templates/sports.c +790 -153
  26. package/examples/gba/templates/platformer.c +624 -169
  27. package/examples/gba/templates/puzzle.c +535 -207
  28. package/examples/gba/templates/racing.c +513 -196
  29. package/examples/gba/templates/shmup.c +565 -168
  30. package/examples/gba/templates/sports.c +454 -162
  31. package/examples/gbc/templates/platformer.c +944 -176
  32. package/examples/gbc/templates/puzzle.c +1131 -177
  33. package/examples/gbc/templates/racing.c +891 -175
  34. package/examples/gbc/templates/shmup.c +827 -179
  35. package/examples/gbc/templates/sports.c +870 -156
  36. package/examples/genesis/templates/platformer.c +747 -129
  37. package/examples/genesis/templates/puzzle.c +702 -208
  38. package/examples/genesis/templates/racing.c +728 -193
  39. package/examples/genesis/templates/shmup.c +535 -142
  40. package/examples/genesis/templates/shmup_2p.c +13 -1
  41. package/examples/genesis/templates/sports.c +495 -158
  42. package/examples/gg/templates/platformer.c +883 -214
  43. package/examples/gg/templates/puzzle.c +906 -181
  44. package/examples/gg/templates/racing.c +919 -160
  45. package/examples/gg/templates/shmup.c +716 -177
  46. package/examples/gg/templates/sports.c +735 -128
  47. package/examples/lynx/templates/platformer.c +604 -50
  48. package/examples/lynx/templates/puzzle.c +533 -130
  49. package/examples/lynx/templates/racing.c +538 -102
  50. package/examples/lynx/templates/shmup.c +461 -122
  51. package/examples/lynx/templates/sports.c +496 -69
  52. package/examples/msx/platformer/main.c +648 -159
  53. package/examples/msx/puzzle/main.c +750 -185
  54. package/examples/msx/racing/main.c +669 -177
  55. package/examples/msx/shmup/main.c +460 -177
  56. package/examples/msx/sports/main.c +591 -124
  57. package/examples/nes/templates/platformer.c +586 -160
  58. package/examples/nes/templates/puzzle.c +603 -222
  59. package/examples/nes/templates/racing.c +505 -197
  60. package/examples/nes/templates/shmup.c +339 -144
  61. package/examples/nes/templates/sports.c +341 -182
  62. package/examples/pce/platformer/main.c +875 -204
  63. package/examples/pce/puzzle/main.c +797 -216
  64. package/examples/pce/racing/main.c +782 -206
  65. package/examples/pce/shmup/main.c +638 -211
  66. package/examples/pce/sports/main.c +585 -167
  67. package/examples/porting-across-platforms/README.md +1 -1
  68. package/examples/sms/templates/platformer.c +765 -176
  69. package/examples/sms/templates/puzzle.c +783 -177
  70. package/examples/sms/templates/racing.c +812 -133
  71. package/examples/sms/templates/shmup.c +601 -148
  72. package/examples/sms/templates/shmup_2p.c +17 -1
  73. package/examples/sms/templates/sports.c +633 -121
  74. package/examples/snes/templates/music_demo.c +7 -0
  75. package/examples/snes/templates/platformer-data.asm +123 -24
  76. package/examples/snes/templates/platformer-hdr.asm +57 -0
  77. package/examples/snes/templates/platformer.c +587 -149
  78. package/examples/snes/templates/puzzle-data.asm +116 -21
  79. package/examples/snes/templates/puzzle-hdr.asm +57 -0
  80. package/examples/snes/templates/puzzle.c +632 -185
  81. package/examples/snes/templates/racing-data.asm +390 -32
  82. package/examples/snes/templates/racing-hdr.asm +57 -0
  83. package/examples/snes/templates/racing.c +807 -177
  84. package/examples/snes/templates/shmup-data.asm +87 -29
  85. package/examples/snes/templates/shmup-hdr.asm +57 -0
  86. package/examples/snes/templates/shmup.c +459 -180
  87. package/examples/snes/templates/sports-data.asm +48 -2
  88. package/examples/snes/templates/sports-hdr.asm +57 -0
  89. package/examples/snes/templates/sports.c +414 -156
  90. package/package.json +12 -12
  91. package/src/cores/wasm/bluemsx_libretro.js +1 -1
  92. package/src/cores/wasm/bluemsx_libretro.wasm +0 -0
  93. package/src/cores/wasm/fceumm_libretro.js +1 -1
  94. package/src/cores/wasm/fceumm_libretro.wasm +0 -0
  95. package/src/cores/wasm/gambatte_libretro.js +1 -1
  96. package/src/cores/wasm/gambatte_libretro.wasm +0 -0
  97. package/src/cores/wasm/geargrafx_libretro.js +1 -1
  98. package/src/cores/wasm/geargrafx_libretro.wasm +0 -0
  99. package/src/cores/wasm/genesis_plus_gx_libretro.js +1 -1
  100. package/src/cores/wasm/genesis_plus_gx_libretro.wasm +0 -0
  101. package/src/cores/wasm/handy_libretro.js +1 -1
  102. package/src/cores/wasm/handy_libretro.wasm +0 -0
  103. package/src/cores/wasm/mgba_libretro.js +1 -1
  104. package/src/cores/wasm/mgba_libretro.wasm +0 -0
  105. package/src/cores/wasm/prosystem_libretro.js +1 -1
  106. package/src/cores/wasm/prosystem_libretro.wasm +0 -0
  107. package/src/cores/wasm/snes9x_libretro.js +1 -1
  108. package/src/cores/wasm/snes9x_libretro.wasm +0 -0
  109. package/src/cores/wasm/stella2014_libretro.js +1 -1
  110. package/src/cores/wasm/stella2014_libretro.wasm +0 -0
  111. package/src/cores/wasm/vice_x64_libretro.js +1 -1
  112. package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
  113. package/src/host/LibretroHost.js +304 -11
  114. package/src/http/tool-registry.js +11 -11
  115. package/src/mcp/server.js +6 -0
  116. package/src/mcp/tools/cheats.js +2 -1
  117. package/src/mcp/tools/disasm-rebuild.js +315 -65
  118. package/src/mcp/tools/disasm.js +149 -28
  119. package/src/mcp/tools/find-references.js +216 -51
  120. package/src/mcp/tools/frame.js +14 -6
  121. package/src/mcp/tools/index.js +18 -4
  122. package/src/mcp/tools/input.js +31 -7
  123. package/src/mcp/tools/lifecycle.js +6 -4
  124. package/src/mcp/tools/memory.js +208 -39
  125. package/src/mcp/tools/platform-docs.js +1 -1
  126. package/src/mcp/tools/playtest.js +56 -4
  127. package/src/mcp/tools/preview-tile.js +6 -2
  128. package/src/mcp/tools/project.js +1114 -120
  129. package/src/mcp/tools/rom-id.js +5 -1
  130. package/src/mcp/tools/run-until.js +4 -2
  131. package/src/mcp/tools/snippets.js +6 -6
  132. package/src/mcp/tools/sprite-pipeline.js +14 -2
  133. package/src/mcp/tools/state.js +2 -1
  134. package/src/mcp/tools/tile-inspect.js +8 -1
  135. package/src/mcp/tools/toolchain.js +55 -11
  136. package/src/mcp/tools/watch-memory.js +145 -27
  137. package/src/observer/bus.js +73 -0
  138. package/src/observer/livestream.html +4 -2
  139. package/src/observer/tool-wrap.js +17 -14
  140. package/src/platforms/_guides/ROMHACKING_PLAYBOOK.md +64 -17
  141. package/src/platforms/atari2600/MENTAL_MODEL.md +5 -1
  142. package/src/platforms/atari2600/TROUBLESHOOTING.md +40 -0
  143. package/src/platforms/atari7800/MENTAL_MODEL.md +32 -11
  144. package/src/platforms/atari7800/TROUBLESHOOTING.md +5 -5
  145. package/src/platforms/c64/MENTAL_MODEL.md +11 -4
  146. package/src/platforms/c64/TROUBLESHOOTING.md +13 -0
  147. package/src/platforms/gb/MENTAL_MODEL.md +19 -4
  148. package/src/platforms/gb/TROUBLESHOOTING.md +101 -6
  149. package/src/platforms/gb/lib/c/README.md +10 -11
  150. package/src/platforms/gb/lib/c/gb_crt0.s +27 -3
  151. package/src/platforms/gb/lib/c/patch-header.js +19 -6
  152. package/src/platforms/gba/MENTAL_MODEL.md +4 -4
  153. package/src/platforms/gba/TROUBLESHOOTING.md +3 -3
  154. package/src/platforms/gba/lib/c/gba_sfx.c +40 -0
  155. package/src/platforms/gba/lib/c/gba_sfx.h +10 -0
  156. package/src/platforms/gbc/MENTAL_MODEL.md +16 -4
  157. package/src/platforms/gbc/TROUBLESHOOTING.md +24 -3
  158. package/src/platforms/gbc/UPSTREAM_SOURCES.md +1 -1
  159. package/src/platforms/gbc/lib/c/README.md +10 -11
  160. package/src/platforms/gbc/lib/c/font.h +43 -0
  161. package/src/platforms/gbc/lib/c/gb_crt0.s +26 -3
  162. package/src/platforms/gbc/lib/c/patch-header.js +19 -6
  163. package/src/platforms/genesis/MENTAL_MODEL.md +43 -9
  164. package/src/platforms/genesis/TROUBLESHOOTING.md +2 -2
  165. package/src/platforms/genesis/lib/c/genesis_sfx.c +37 -0
  166. package/src/platforms/genesis/lib/c/genesis_sfx.h +1 -0
  167. package/src/platforms/gg/MENTAL_MODEL.md +4 -4
  168. package/src/platforms/gg/TROUBLESHOOTING.md +14 -18
  169. package/src/platforms/gg/UPSTREAM_SOURCES.md +1 -1
  170. package/src/platforms/gg/lib/c/gg_crt0.s +14 -2
  171. package/src/platforms/gg/lib/c/joypad_read.c +29 -0
  172. package/src/platforms/lynx/MENTAL_MODEL.md +1 -1
  173. package/src/platforms/lynx/TROUBLESHOOTING.md +3 -3
  174. package/src/platforms/lynx/lib/c/lynx_sfx.c +38 -2
  175. package/src/platforms/lynx/lib/c/lynx_sfx.h +1 -0
  176. package/src/platforms/msx/MENTAL_MODEL.md +11 -5
  177. package/src/platforms/msx/TROUBLESHOOTING.md +21 -0
  178. package/src/platforms/msx/lib/c/msx_crt0.s +27 -0
  179. package/src/platforms/msx/lib/c/msx_hw.h +3 -0
  180. package/src/platforms/msx/lib/c/msx_vdp.c +70 -0
  181. package/src/platforms/nes/MENTAL_MODEL.md +12 -5
  182. package/src/platforms/nes/lib/c/nes_runtime.c +190 -34
  183. package/src/platforms/nes/lib/c/nes_runtime.h +35 -0
  184. package/src/platforms/pce/MENTAL_MODEL.md +14 -5
  185. package/src/platforms/pce/TROUBLESHOOTING.md +9 -0
  186. package/src/platforms/pce/lib/c/pce_hw.h +13 -1
  187. package/src/platforms/pce/lib/c/pce_sound.c +22 -0
  188. package/src/platforms/pce/lib/c/pce_video.c +32 -0
  189. package/src/platforms/sms/MENTAL_MODEL.md +11 -6
  190. package/src/platforms/sms/TROUBLESHOOTING.md +6 -0
  191. package/src/platforms/sms/lib/c/sms_crt0.s +14 -2
  192. package/src/platforms/snes/MENTAL_MODEL.md +7 -2
  193. package/src/platforms/snes/TROUBLESHOOTING.md +40 -1
  194. package/src/playtest/playtest.js +73 -3
  195. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +13 -8
  196. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.crt0.s +58 -5
  197. package/src/toolchains/cc65/presets/nes/chr-rom.crt0.s +52 -3
  198. package/src/toolchains/cc65/presets/pce/rom32k.cfg +52 -0
  199. package/src/toolchains/index.js +64 -19
@@ -78,6 +78,13 @@ int main(void) {
78
78
  * screen is on you get a black/forced-blank screen forever. */
79
79
  sfx_init();
80
80
 
81
+ /* One frame between init and the FIRST command: sfx_init returns the
82
+ * instant the SPC echoes the jump command, but the driver then spends
83
+ * ~50 port writes initialising the DSP BEFORE it seeds its command
84
+ * edge-detector from $2140. A command sent inside that window gets
85
+ * swallowed by the seed — the music silently never starts. */
86
+ WaitForVBlank();
87
+
81
88
  /* Auto-start music. */
82
89
  sfx_music_play();
83
90
  music_running = 1;
@@ -1,6 +1,61 @@
1
- ; ── platformer-data.asm — one sprite (player) + font stubs ─────────
1
+ ; ── platformer-data.asm — CRAG CAPER's assembly half ─────────────────────────
2
+ ;
3
+ ; What lives here (and why it can't live in platformer.c):
4
+ ; 1. The telem block, in a RAMSECTION pinned to WRAM BANK $7E. tcc-65816
5
+ ; puts C globals in bank $7F at addresses the linker picks; a headless
6
+ ; test harness wants a block it can FIND by scanning, at an address WE
7
+ ; control. platformer.c reaches it as a plain extern.
8
+ ; 2. sram_read16/sram_write16 — battery SRAM accessors. SRAM sits at
9
+ ; $70:0000 (declared in hdr.asm — see platformer-hdr.asm), reachable
10
+ ; only with long (24-bit) addressing, which tcc C pointers don't emit.
11
+ ; 3. Font + sprite tiles + level BG tiles (rodata).
12
+ ;
13
+ ; Section names must stay unique vs snes_sfx_data.asm (also linked in).
14
+
2
15
  .include "hdr.asm"
3
16
 
17
+ .RAMSECTION "platformer_wram" BANK $7E SLOT 2
18
+ telem dsb 24 ; headless-test telemetry block (see platformer.c)
19
+ .ENDS
20
+
21
+ .SECTION ".platformer_asm" SUPERFREE
22
+
23
+ ; ── HARDWARE IDIOM (load-bearing) — battery SRAM accessors ──────────────────
24
+ ; SRAM is mapped at $70:0000 (LoROM, SRAMSIZE $01 in platformer-hdr.asm =
25
+ ; 2 KB). Long addressing only — there is no SRAM mirror in the program banks,
26
+ ; which is why these are asm and not C. tcc calling convention: u16 arg at
27
+ ; 5,s (after the 4-byte rtl frame), second arg at 7,s; u16 return in tcc__r0.
28
+
29
+ ; u16 sram_read16(u16 offset)
30
+ sram_read16:
31
+ php
32
+ rep #$30
33
+ lda 5,s ; offset
34
+ tax
35
+ sep #$20
36
+ lda.l $700000,x
37
+ sta.w tcc__r0
38
+ lda.l $700001,x
39
+ sta.w tcc__r0 + 1
40
+ plp
41
+ rtl
42
+
43
+ ; void sram_write16(u16 offset, u16 value)
44
+ sram_write16:
45
+ php
46
+ rep #$30
47
+ lda 5,s ; offset
48
+ tax
49
+ lda 7,s ; value
50
+ sep #$20
51
+ sta.l $700000,x ; low byte
52
+ xba
53
+ sta.l $700001,x ; high byte
54
+ plp
55
+ rtl
56
+
57
+ .ENDS
58
+
4
59
  .section ".rodata1" superfree
5
60
 
6
61
  tilfont:
@@ -308,40 +363,84 @@ palfont:
308
363
  .db $00, $00
309
364
 
310
365
  tilsprite:
311
- ; Tile 0 player (filled diamond, colour 1)
312
- .db $18, $00, $3C, $00, $7E, $00, $FF, $00
313
- .db $FF, $00, $7E, $00, $3C, $00, $18, $00
366
+ ; OBJ tiles, 8x8 4bpp (32 bytes each: rows 0-7 plane0/plane1 byte pairs,
367
+ ; then rows 0-7 plane2/plane3 pairs). Pixel colour = the 4 plane bits, and
368
+ ; the colour indexes palsprite below so plane choice IS colour choice:
369
+ ; player body = plane0 only → colour 1 (red)
370
+ ; player eyes = plane0+plane1 → colour 3 (white)
371
+ ; coin disc = plane2 only → colour 4 (gold)
372
+ ; coin ring = plane0+plane2 → colour 5 (dark gold)
373
+ ; spike = plane1+plane2 → colour 6 (danger red)
374
+ ; tile 0 — player, idle (round body + legs, two eyes)
375
+ .db $3C, $00, $7E, $24, $FF, $24, $FF, $00
376
+ .db $FF, $00, $7E, $00, $66, $00, $66, $00
314
377
  .db $00, $00, $00, $00, $00, $00, $00, $00
315
378
  .db $00, $00, $00, $00, $00, $00, $00, $00
316
-
317
- palsprite:
318
- .db $00, $00 ; 0 transparent
319
- .db $00, $7C ; 1 red
379
+ ; tile 1 — player, jumping (arms up)
380
+ .db $18, $00, $7E, $24, $FF, $24, $FF, $00
381
+ .db $E7, $00, $C3, $00, $81, $00, $00, $00
320
382
  .db $00, $00, $00, $00, $00, $00, $00, $00
321
383
  .db $00, $00, $00, $00, $00, $00, $00, $00
384
+ ; tile 2 — coin (gold disc, embossed ring)
385
+ .db $00, $00, $3C, $00, $66, $00, $5A, $00
386
+ .db $5A, $00, $66, $00, $3C, $00, $00, $00
387
+ .db $3C, $00, $7E, $00, $FF, $00, $FF, $00
388
+ .db $FF, $00, $FF, $00, $7E, $00, $3C, $00
389
+ ; tile 3 — ground spike
390
+ .db $00, $00, $00, $18, $00, $18, $00, $3C
391
+ .db $00, $3C, $00, $7E, $00, $7E, $00, $FF
392
+ .db $00, $00, $18, $00, $18, $00, $3C, $00
393
+ .db $3C, $00, $7E, $00, $7E, $00, $FF, $00
394
+
395
+ palsprite:
396
+ ; OBJ palette block 0 (CGRAM 128-143), BGR555 little-endian.
397
+ .db $00, $00 ; 0 transparent
398
+ .db $1F, $00 ; 1 red (player body)
399
+ .db $10, $00 ; 2 dark red (unused, free)
400
+ .db $FF, $7F ; 3 white (player eyes)
401
+ .db $3F, $13 ; 4 gold (coin disc)
402
+ .db $3C, $0A ; 5 dark gold (coin ring)
403
+ .db $DE, $18 ; 6 danger red (spike)
404
+ .db $00, $00 ; 7 unused
322
405
  .db $00, $00, $00, $00, $00, $00, $00, $00
323
406
  .db $00, $00, $00, $00, $00, $00, $00, $00
324
407
 
325
- ; ── Background wallpaper (one 8x8 4bpp tile, 4 solid colour quadrants) ──
326
- ; Tiled across BG1 it paints the whole screen in four muted colours so the
327
- ; playfield never reads as a flat/blank backdrop. Quadrant->colour: TL=1,
328
- ; TR=2, BL=3, BR=4. 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1
329
- ; pairs, bytes 16-31 = rows 0-7 plane2/plane3 pairs.
408
+ ; ── Level BG tiles (8x8 4bpp, same plane layout as the sprites above).
409
+ ; Colour 0 is TRANSPARENT the backdrop (CGRAM colour 0 = sky blue) shows
410
+ ; through, which is also why the dirt speckle holes read as sky-blue grit.
330
411
  tilbg:
331
- .db $F0, $0F, $F0, $0F, $F0, $0F, $F0, $0F ; rows 0-3: p0=left p1=right
332
- .db $F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0 ; rows 4-7: p0+p1 = left
333
- .db $00, $00, $00, $00, $00, $00, $00, $00 ; rows 0-3: p2/p3 = 0
334
- .db $0F, $00, $0F, $00, $0F, $00, $0F, $00 ; rows 4-7: p2 = right
412
+ ; tile 0 blank (all transparent = pure sky)
413
+ .db $00, $00, $00, $00, $00, $00, $00, $00
414
+ .db $00, $00, $00, $00, $00, $00, $00, $00
415
+ .db $00, $00, $00, $00, $00, $00, $00, $00
416
+ .db $00, $00, $00, $00, $00, $00, $00, $00
417
+ ; tile 1 — puffy cloud (colour 1 = white, shared with the text ink)
418
+ .db $00, $00, $18, $00, $3C, $00, $7E, $00
419
+ .db $7E, $00, $00, $00, $00, $00, $00, $00
420
+ .db $00, $00, $00, $00, $00, $00, $00, $00
421
+ .db $00, $00, $00, $00, $00, $00, $00, $00
422
+ ; tile 2 — dirt fill (colour 2 brown, speckled with transparent holes)
423
+ .db $00, $FF, $00, $FF, $00, $EF, $00, $FF
424
+ .db $00, $FF, $00, $FE, $00, $FF, $00, $FF
425
+ .db $00, $00, $00, $00, $00, $00, $00, $00
426
+ .db $00, $00, $00, $00, $00, $00, $00, $00
427
+ ; tile 3 — grass top (2 rows colour 3 green over colour 2 dirt) — used for
428
+ ; both the ground surface and the floating one-way platforms
429
+ .db $FF, $FF, $FF, $FF, $00, $FF, $00, $FF
430
+ .db $00, $FF, $00, $FF, $00, $FF, $00, $FF
431
+ .db $00, $00, $00, $00, $00, $00, $00, $00
432
+ .db $00, $00, $00, $00, $00, $00, $00, $00
335
433
 
336
434
  palbg:
337
- ; 16-colour BG palette; only 1-4 used (the four wallpaper quadrant tones).
338
- .db $00, $00 ; 0 unused (BG fully opaque)
339
- .db $C4, $30 ; 1 dark blue
340
- .db $42, $29 ; 2 dark teal
341
- .db $88, $30 ; 3 dark purple
342
- .db $C6, $24 ; 4 dark slate
435
+ ; BG palette block 0 (CGRAM 0-15), BGR555 little-endian. Loaded AFTER the
436
+ ; console font palette and deliberately a SUPERSET of it: colour 1 stays
437
+ ; white so the HUD/title text keeps its ink, colour 0 is the backdrop sky.
438
+ .db $4B, $72 ; 0 sky blue (the backdrop colour — colour 0 IS the sky)
439
+ .db $FF, $7F ; 1 white (text ink + clouds)
440
+ .db $2E, $11 ; 2 dirt brown
441
+ .db $86, $1A ; 3 grass green
442
+ .db $00, $00, $00, $00, $00, $00, $00, $00
343
443
  .db $00, $00, $00, $00, $00, $00, $00, $00
344
444
  .db $00, $00, $00, $00, $00, $00, $00, $00
345
- .db $00, $00, $00, $00, $00, $00
346
445
 
347
446
  .ends
@@ -0,0 +1,57 @@
1
+ ;==LoRom== platformer 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 (our telem block lands here)
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 "CRAG CAPER " ; 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