romdevtools 0.70.0 → 0.71.1
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/CHANGELOG.md +80 -0
- package/examples/dreamcast/platformer/main.c +31 -0
- package/examples/dreamcast/puzzle/main.c +44 -0
- package/examples/dreamcast/racing/main.c +39 -0
- package/examples/dreamcast/shmup/main.c +50 -0
- package/examples/dreamcast/sports/main.c +39 -0
- package/package.json +3 -3
- package/src/cores/capabilities.js +13 -9
- package/src/host/LibretroHost.js +242 -23
- package/src/host/callbacks.js +68 -1
- package/src/host/cpu-state.js +32 -0
- package/src/host/dc-aica-state.js +67 -0
- package/src/mcp/tools/audio.js +1 -1
- package/src/mcp/tools/disasm.js +1 -1
- package/src/mcp/tools/index.js +1 -1
- package/src/mcp/tools/platform-docs.js +1 -1
- package/src/mcp/tools/platform-tools.js +9 -1
- package/src/mcp/tools/platforms.js +46 -10
- package/src/mcp/tools/toolchain.js +140 -10
- package/src/platforms/dreamcast/MENTAL_MODEL.md +87 -0
- package/src/platforms/dreamcast/TROUBLESHOOTING.md +55 -0
- package/src/platforms/dreamcast/UPSTREAM_SOURCES.md +57 -0
- package/src/platforms/gba/MENTAL_MODEL.md +22 -1
- package/src/platforms/n64/MENTAL_MODEL.md +84 -0
- package/src/platforms/n64/TROUBLESHOOTING.md +60 -0
- package/src/platforms/n64/UPSTREAM_SOURCES.md +52 -0
- package/src/platforms/n64/lib/c/n64.c +181 -80
- package/src/platforms/ps1/MENTAL_MODEL.md +85 -0
- package/src/platforms/ps1/TROUBLESHOOTING.md +55 -0
- package/src/platforms/ps1/UPSTREAM_SOURCES.md +54 -0
- package/src/platforms/snes/TROUBLESHOOTING.md +10 -0
- package/src/toolchains/asar/asar.js +84 -14
- package/src/toolchains/mips-c/mips-c.js +35 -1
- package/src/toolchains/sh-c/lib/dc.h +65 -15
- package/src/toolchains/sh-c/sh-c.js +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,86 @@ All notable changes to `romdevtools`. Dates are release dates.
|
|
|
4
4
|
(Published as `romdev-mcp` through 0.11.0; renamed to `romdevtools` in 0.13.0 —
|
|
5
5
|
the `romdev-mcp` bin is kept as an alias.)
|
|
6
6
|
|
|
7
|
+
## 0.71.1 — 2026-06-29
|
|
8
|
+
|
|
9
|
+
Feedback from the first run against the `pret/pokeruby` GBA decompilation.
|
|
10
|
+
|
|
11
|
+
- **Project-mode `entry` now resolves a NESTED path** (e.g. `entry:'src/main.c'`). The
|
|
12
|
+
recursive asset staging already walked subdirs, but entry resolution stayed top-level
|
|
13
|
+
only — so any decomp/SDK-layout project whose entry isn't at the repo root failed with
|
|
14
|
+
"entry not found." Now it resolves against the recursive file set, reads the nested file
|
|
15
|
+
as the entry **source**, accepts a bare filename when it uniquely matches one nested
|
|
16
|
+
file, and errors with a "did you mean `src/…`?" hint.
|
|
17
|
+
- **`platform({op:'list'})` honors the `platform` filter** — returns just that one
|
|
18
|
+
platform's row instead of the whole 17-platform matrix (the biggest token sink reported:
|
|
19
|
+
~17 KB → ~0.8 KB for one platform). New **`slim:true`** drops the verbose per-language
|
|
20
|
+
`note` + `quirks` prose (~60× smaller); detail stays behind `op:'doc'`/`op:'capabilities'`.
|
|
21
|
+
- **`platform({op:'resolve'})` surfaces the toolchain(s)** + a note that the build
|
|
22
|
+
toolchain is WASM/harness-only (was core-paths-only, forcing `node_modules` spelunking).
|
|
23
|
+
- **GBA `mental_model` "What's NOT bundled"** now calls out **agbcc's absence** (the real
|
|
24
|
+
blocker for byte-exact Gen-III decomps like pokeruby/pokeemerald) and adds a "romdev's
|
|
25
|
+
build model" section: `build` is single-shot compile→ROM, the toolchain can't back an
|
|
26
|
+
external Makefile, with the confirmed host agbcc recipe for matching builds.
|
|
27
|
+
|
|
28
|
+
## 0.71.0 — 2026-06-28
|
|
29
|
+
|
|
30
|
+
### N64 / PS1 / Dreamcast reach full parity: cpuState + audioDebug + GPU-rendering helper libs + 5 examples each
|
|
31
|
+
|
|
32
|
+
The three next-gen 3D platforms are now first-class alongside the original 14.
|
|
33
|
+
|
|
34
|
+
**Live debugging (cpuState + audioDebug).** PS1 (beetle_psx_hw) and Dreamcast (flycast)
|
|
35
|
+
gained the romdev debug-reader exports, so `cpu({op:'read'})` and
|
|
36
|
+
`audioDebug({op:'inspect'})` light up (N64 already had them):
|
|
37
|
+
- **PS1** — `cpu({op:'read'})` returns the live R3000A register file; `audioDebug({chip:'spu'})`
|
|
38
|
+
decodes the SPU's 24 voices + main volume (read from the raw register mirror, not the
|
|
39
|
+
sweep-quantized `SPU_Read`).
|
|
40
|
+
- **Dreamcast** — `cpu({op:'read'})` returns the SH-4 registers (r0–r15, pc, pr, gbr, vbr,
|
|
41
|
+
sr + decoded flags, mac, fpul); `audioDebug({chip:'aica'})` decodes the AICA's 64
|
|
42
|
+
PCM/ADPCM channels + master volume. Full host plumbing + decoders added.
|
|
43
|
+
- The capability manifest now reports cpuState/audioDebug `true` for all three (verified by
|
|
44
|
+
probing real core exports; `breakpoint`/`watch` remain pending on PS1/DC).
|
|
45
|
+
|
|
46
|
+
**GPU-rendering helper libs (no software framebuffers).** Every 3D platform's helper now
|
|
47
|
+
draws through the GPU — a software rasterizer would be black on the GL cores and <1fps:
|
|
48
|
+
- **N64** — the `n64.h` helper was rewritten to emit a **GBI (F3DEX2) display list** that
|
|
49
|
+
glide64 HLEs onto the GPU (clear/rect as fill-rectangles, triangles scan-converted into
|
|
50
|
+
GPU fill-rect spans), instead of poking pixels into RDRAM (which rendered black on
|
|
51
|
+
glide64). No Nintendo microcode shipped — the OSTask CRC-bait trick selects F3DEX2.
|
|
52
|
+
- **PS1** — already correct (GP0 GPU primitives on beetle_psx_hw).
|
|
53
|
+
- **Dreamcast** — `dc.h` now sets **480i interlace** in `dc_video_init` (240p only showed
|
|
54
|
+
the top 240 of 480 lines), and added a Maple-DMA `dc_pad()` / `dc_pressed()`.
|
|
55
|
+
- `#include "n64.h"` / `#include "psx.h"` now auto-bundle (parity with `dc.h`).
|
|
56
|
+
|
|
57
|
+
**5 genre examples per platform.** N64, PS1, and Dreamcast each ship
|
|
58
|
+
shmup / platformer / puzzle / racing / sports examples — all verified building + rendering
|
|
59
|
+
on the GPU.
|
|
60
|
+
|
|
61
|
+
**Docs.** MENTAL_MODEL + TROUBLESHOOTING for N64, PS1, and Dreamcast (the render model,
|
|
62
|
+
boot story, debug surface, and what's N/A and why).
|
|
63
|
+
|
|
64
|
+
### asar (SNES) build-tool fixes
|
|
65
|
+
|
|
66
|
+
From real commercial-disassembly feedback:
|
|
67
|
+
- **`build({output:'project'|'run'})` honors `options` + a new `defines` map** (e.g. asar
|
|
68
|
+
`--define`) — they were silently dropped.
|
|
69
|
+
- **New `entry` param** so a project whose top file isn't `main.*` (e.g. an existing
|
|
70
|
+
`smw.asm` disassembly) builds without injecting glue.
|
|
71
|
+
- **Subdirectory assets are staged recursively** (a flat `readdir` missed nested
|
|
72
|
+
`incbin`/`incsrc` targets).
|
|
73
|
+
- **A clean asar error is no longer mislabeled** `[worker] Abort in WASM` (it exits errors
|
|
74
|
+
via a C++-exception path; the misleading heap-pointer line is stripped when real
|
|
75
|
+
diagnostics are present).
|
|
76
|
+
- **The LoROM-header bankcross preflight no longer false-positives** on banks $01+ (the
|
|
77
|
+
header is only in bank $00) and honors `check bankcross off`.
|
|
78
|
+
- **A readfile/filesize advisory** warns when a source reads many distinct files that way
|
|
79
|
+
(the asar-WASM resource limit), pointing at the pre-convert-to-`.bin` + `incbin`
|
|
80
|
+
workaround.
|
|
81
|
+
|
|
82
|
+
### Toolchain
|
|
83
|
+
|
|
84
|
+
- **sh-c (Dreamcast) defaults to `-O1`** — the sh-elf `cc1.wasm` has an `-O2`-only pass
|
|
85
|
+
that aborts on common control flow; `-O1` dodges it. A user-supplied `-O<level>` wins.
|
|
86
|
+
|
|
7
87
|
## 0.70.0 — 2026-06-26
|
|
8
88
|
|
|
9
89
|
### Dreamcast is ship-ready: verified build → run → screenshot, with a renderable example
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Dreamcast PLATFORMER demo — a side-scrolling scene: a hero hops across platforms
|
|
2
|
+
* while the camera scrolls. Self-animating (no input). Renders on the PowerVR2 via
|
|
3
|
+
* the framebuffer path. */
|
|
4
|
+
#include "dc.h"
|
|
5
|
+
|
|
6
|
+
void main(void){
|
|
7
|
+
int frame = 0;
|
|
8
|
+
dc_video_init();
|
|
9
|
+
for (;;){
|
|
10
|
+
int scroll = (frame * 2) % (DC_W);
|
|
11
|
+
int t = frame % 90;
|
|
12
|
+
int jump = t < 45 ? t : (90 - t); /* 0..45..0 hop */
|
|
13
|
+
int hy = DC_H - 140 - jump * 2;
|
|
14
|
+
int hx = DC_W/2 - 16;
|
|
15
|
+
|
|
16
|
+
dc_clear(dc_rgb(80, 150, 230)); /* sky */
|
|
17
|
+
/* parallax hills */
|
|
18
|
+
{ int i; for (i = -1; i < 6; i++){ int x = i*140 - (scroll/2); dc_rect(x, DC_H-200, 120, 200, dc_rgb(60, 170, 90)); } }
|
|
19
|
+
/* ground */
|
|
20
|
+
dc_rect(0, DC_H-60, DC_W, 60, dc_rgb(120, 80, 40));
|
|
21
|
+
/* floating platforms (scrolling) */
|
|
22
|
+
{ int i; for (i = -1; i < 6; i++){ int x = i*180 - (scroll % 180); dc_rect(x, DC_H-160, 90, 18, dc_rgb(150, 110, 60)); } }
|
|
23
|
+
/* hero (head + body) */
|
|
24
|
+
dc_rect(hx, hy, 32, 32, dc_rgb(240, 90, 70));
|
|
25
|
+
dc_rect(hx+6, hy+6, 6, 6, dc_rgb(255,255,255)); /* eye */
|
|
26
|
+
dc_rect(hx, hy+32, 32, 20, dc_rgb(40, 60, 200)); /* legs */
|
|
27
|
+
/* a coin that bobs */
|
|
28
|
+
dc_rect(DC_W/2 + 120 - (scroll%240), DC_H-220 + (jump), 18, 18, dc_rgb(255, 220, 60));
|
|
29
|
+
frame++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* Dreamcast PUZZLE demo — a falling-block (Tetris-like) board that fills + clears
|
|
2
|
+
* rows on a loop. Self-animating (no input). Renders on the PowerVR2 framebuffer. */
|
|
3
|
+
#include "dc.h"
|
|
4
|
+
|
|
5
|
+
#define COLS 10
|
|
6
|
+
#define ROWS 16
|
|
7
|
+
#define CELL 24
|
|
8
|
+
|
|
9
|
+
static unsigned char board[ROWS][COLS];
|
|
10
|
+
static unsigned int rng = 0xACE1u;
|
|
11
|
+
static unsigned int rnd(void){ rng ^= rng << 7; rng ^= rng >> 9; rng ^= rng << 8; return rng; }
|
|
12
|
+
|
|
13
|
+
static const u16 PAL[7] = { 0, 0xF800, 0x07E0, 0x001F, 0xFFE0, 0xF81F, 0x07FF };
|
|
14
|
+
|
|
15
|
+
void main(void){
|
|
16
|
+
int frame = 0, px = COLS/2, py = 0, col = 1, i, r, c;
|
|
17
|
+
dc_video_init();
|
|
18
|
+
for (;;){
|
|
19
|
+
int ox = (DC_W - COLS*CELL)/2, oy = (DC_H - ROWS*CELL)/2;
|
|
20
|
+
|
|
21
|
+
if ((frame % 8) == 0){
|
|
22
|
+
/* drop the active block one row; lock + respawn at the bottom */
|
|
23
|
+
if (py+1 >= ROWS || board[py+1][px]){
|
|
24
|
+
board[py][px] = col;
|
|
25
|
+
/* clear full-ish rows occasionally to keep it moving */
|
|
26
|
+
for (r = 0; r < ROWS; r++){ int full=1; for (c=0;c<COLS;c++) if(!board[r][c]) full=0;
|
|
27
|
+
if (full){ for(c=0;c<COLS;c++) board[r][c]=0; } }
|
|
28
|
+
py = 0; px = rnd()%COLS; col = 1 + rnd()%6;
|
|
29
|
+
if (board[0][px]){ for(r=0;r<ROWS;r++)for(c=0;c<COLS;c++) board[r][c]=0; } /* reset if buried */
|
|
30
|
+
} else py++;
|
|
31
|
+
}
|
|
32
|
+
dc_clear(dc_rgb(18, 18, 30));
|
|
33
|
+
/* board frame */
|
|
34
|
+
dc_rect(ox-4, oy-4, COLS*CELL+8, ROWS*CELL+8, dc_rgb(90,90,120));
|
|
35
|
+
dc_rect(ox, oy, COLS*CELL, ROWS*CELL, dc_rgb(10,10,18));
|
|
36
|
+
/* settled cells */
|
|
37
|
+
for (r = 0; r < ROWS; r++) for (c = 0; c < COLS; c++) if (board[r][c])
|
|
38
|
+
dc_rect(ox + c*CELL+1, oy + r*CELL+1, CELL-2, CELL-2, PAL[board[r][c]]);
|
|
39
|
+
/* active block */
|
|
40
|
+
dc_rect(ox + px*CELL+1, oy + py*CELL+1, CELL-2, CELL-2, PAL[col]);
|
|
41
|
+
frame++;
|
|
42
|
+
(void)i;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* Dreamcast RACING demo — a pseudo-3D road that curves + scrolls toward a horizon,
|
|
2
|
+
* with a car at the bottom that drifts side to side. Self-animating (no input).
|
|
3
|
+
* Renders on the PowerVR2 framebuffer. */
|
|
4
|
+
#include "dc.h"
|
|
5
|
+
|
|
6
|
+
/* tiny fixed sine via a 16-entry quarter table */
|
|
7
|
+
static const int SIN16[17] = {0,49,97,142,181,213,236,251,256,251,236,213,181,142,97,49,0};
|
|
8
|
+
static int isin(int a){ a &= 63; if(a<16) return SIN16[a]; if(a<32) return SIN16[32-a]; if(a<48) return -SIN16[a-32]; return -SIN16[64-a]; }
|
|
9
|
+
|
|
10
|
+
void main(void){
|
|
11
|
+
int frame = 0, y;
|
|
12
|
+
dc_video_init();
|
|
13
|
+
for (;;){
|
|
14
|
+
int horizon = DC_H/3;
|
|
15
|
+
dc_clear(dc_rgb(60, 140, 230)); /* sky */
|
|
16
|
+
dc_rect(0, horizon, DC_W, DC_H-horizon, dc_rgb(40, 120, 50)); /* grass */
|
|
17
|
+
|
|
18
|
+
/* road: for each scanline below the horizon, a trapezoid widening to the
|
|
19
|
+
bottom, shifted by a curve that scrolls. */
|
|
20
|
+
for (y = horizon; y < DC_H; y++){
|
|
21
|
+
int depth = y - horizon;
|
|
22
|
+
int half = depth * (DC_W/2 - 20) / (DC_H - horizon) + 12;
|
|
23
|
+
int curve = isin((frame/2 + depth/4)) * depth / 256;
|
|
24
|
+
int cx = DC_W/2 + curve;
|
|
25
|
+
/* road stripe alternation for motion */
|
|
26
|
+
u16 rc = (((depth + frame) / 12) & 1) ? dc_rgb(70,70,75) : dc_rgb(90,90,95);
|
|
27
|
+
dc_rect(cx - half, y, half*2, 1, rc);
|
|
28
|
+
/* center dashes */
|
|
29
|
+
if ((((depth + frame*2)/16) & 1)) dc_rect(cx-2, y, 4, 1, dc_rgb(240,240,120));
|
|
30
|
+
}
|
|
31
|
+
/* the car (drifts L/R) */
|
|
32
|
+
{ int carx = DC_W/2 + isin(frame/3) * 60 / 256 - 24;
|
|
33
|
+
dc_rect(carx, DC_H-70, 48, 40, dc_rgb(220, 40, 40));
|
|
34
|
+
dc_rect(carx+6, DC_H-64, 36, 14, dc_rgb(40,40,60)); /* windshield */
|
|
35
|
+
dc_rect(carx-4, DC_H-44, 10, 18, dc_rgb(20,20,20)); /* wheels */
|
|
36
|
+
dc_rect(carx+42, DC_H-44, 10, 18, dc_rgb(20,20,20)); }
|
|
37
|
+
frame++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* Dreamcast SHMUP demo — a vertical shooter scene rendered on the PowerVR2 via the
|
|
2
|
+
* framebuffer path. The ship weaves, bullets stream up, enemies descend + recycle.
|
|
3
|
+
* Self-animating (no input) — proves program-controlled graphics render on the GPU.
|
|
4
|
+
* (DC input via dc_pad() reads the resting controller state; full press wiring is a
|
|
5
|
+
* follow-up — see dc.h.) */
|
|
6
|
+
#include "dc.h"
|
|
7
|
+
|
|
8
|
+
#define NB 12
|
|
9
|
+
#define NE 6
|
|
10
|
+
|
|
11
|
+
static int frame;
|
|
12
|
+
static unsigned int rng = 0x1234567u;
|
|
13
|
+
static unsigned int rnd(void){ rng ^= rng << 13; rng ^= rng >> 17; rng ^= rng << 5; return rng; }
|
|
14
|
+
|
|
15
|
+
static int bx[NB], by[NB], ba[NB];
|
|
16
|
+
static int ex[NE], ey[NE];
|
|
17
|
+
|
|
18
|
+
void main(void){
|
|
19
|
+
int i;
|
|
20
|
+
dc_video_init();
|
|
21
|
+
for (i = 0; i < NE; i++){ ex[i] = 60 + i*90; ey[i] = -(int)(rnd()%300); }
|
|
22
|
+
for (;;){
|
|
23
|
+
int shipx = DC_W/2 + (int)(80.0 * ((frame % 120) < 60 ? (frame%60) : (60-(frame%60))) / 60.0 - 40);
|
|
24
|
+
int shipy = DC_H - 80;
|
|
25
|
+
|
|
26
|
+
/* spawn a bullet every 8 frames */
|
|
27
|
+
if ((frame & 7) == 0){
|
|
28
|
+
for (i = 0; i < NB; i++) if (!ba[i]){ ba[i]=1; bx[i]=shipx; by[i]=shipy; break; }
|
|
29
|
+
}
|
|
30
|
+
dc_clear(dc_rgb(8, 10, 28));
|
|
31
|
+
/* starfield */
|
|
32
|
+
for (i = 0; i < 24; i++){
|
|
33
|
+
int sx = (int)((rnd()%DC_W));
|
|
34
|
+
int sy = (int)((frame*2 + i*53) % DC_H);
|
|
35
|
+
dc_rect(sx, sy, 2, 2, dc_rgb(120,120,160));
|
|
36
|
+
}
|
|
37
|
+
/* enemies */
|
|
38
|
+
for (i = 0; i < NE; i++){
|
|
39
|
+
ey[i] += 2;
|
|
40
|
+
if (ey[i] > DC_H){ ey[i] = -(int)(rnd()%200); ex[i] = (int)(rnd()%(DC_W-40)); }
|
|
41
|
+
if (ey[i] >= 0) dc_rect(ex[i], ey[i], 36, 28, dc_rgb(220, 60, 60));
|
|
42
|
+
}
|
|
43
|
+
/* bullets */
|
|
44
|
+
for (i = 0; i < NB; i++) if (ba[i]){ by[i] -= 8; if (by[i] < 0) ba[i]=0; else dc_rect(bx[i]-2, by[i], 4, 12, dc_rgb(255,240,80)); }
|
|
45
|
+
/* player ship (a little arrow of rects) */
|
|
46
|
+
dc_rect(shipx-4, shipy, 8, 24, dc_rgb(80, 200, 255));
|
|
47
|
+
dc_rect(shipx-16, shipy+14, 32, 8, dc_rgb(60, 160, 230));
|
|
48
|
+
frame++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* Dreamcast SPORTS demo — a top-down pong/air-hockey rally: two paddles track a
|
|
2
|
+
* bouncing ball with a scoreboard. Self-animating (the CPU "AI" plays both sides).
|
|
3
|
+
* Renders on the PowerVR2 framebuffer. */
|
|
4
|
+
#include "dc.h"
|
|
5
|
+
|
|
6
|
+
void main(void){
|
|
7
|
+
int frame = 0;
|
|
8
|
+
int bx = DC_W/2, by = DC_H/2, vx = 5, vy = 3;
|
|
9
|
+
int p0 = DC_H/2, p1 = DC_H/2; /* paddle centers (y) */
|
|
10
|
+
int s0 = 0, s1 = 0, i;
|
|
11
|
+
dc_video_init();
|
|
12
|
+
for (;;){
|
|
13
|
+
/* ball physics */
|
|
14
|
+
bx += vx; by += vy;
|
|
15
|
+
if (by < 12 || by > DC_H-12) vy = -vy;
|
|
16
|
+
/* paddles track the ball (simple AI) */
|
|
17
|
+
if (p0 < by) p0 += 4; else p0 -= 4;
|
|
18
|
+
if (p1 < by) p1 += 4; else p1 -= 4;
|
|
19
|
+
/* bounce off paddles / score */
|
|
20
|
+
if (bx < 40){ if (by > p0-50 && by < p0+50) vx = -vx; else { s1++; bx=DC_W/2; by=DC_H/2; vx=5; } }
|
|
21
|
+
if (bx > DC_W-40){ if (by > p1-50 && by < p1+50) vx = -vx; else { s0++; bx=DC_W/2; by=DC_H/2; vx=-5; } }
|
|
22
|
+
|
|
23
|
+
dc_clear(dc_rgb(15, 60, 30)); /* court green */
|
|
24
|
+
/* center line (dashed) */
|
|
25
|
+
for (i = 0; i < DC_H; i += 32) dc_rect(DC_W/2-2, i+8, 4, 16, dc_rgb(200,200,200));
|
|
26
|
+
/* top/bottom rails */
|
|
27
|
+
dc_rect(0, 0, DC_W, 8, dc_rgb(220,220,220));
|
|
28
|
+
dc_rect(0, DC_H-8, DC_W, 8, dc_rgb(220,220,220));
|
|
29
|
+
/* paddles */
|
|
30
|
+
dc_rect(24, p0-50, 14, 100, dc_rgb(80, 160, 255));
|
|
31
|
+
dc_rect(DC_W-38, p1-50, 14, 100, dc_rgb(255, 160, 80));
|
|
32
|
+
/* ball */
|
|
33
|
+
dc_rect(bx-8, by-8, 16, 16, dc_rgb(255, 240, 80));
|
|
34
|
+
/* scoreboard (score as stacked pips) */
|
|
35
|
+
for (i = 0; i < s0 && i < 9; i++) dc_rect(DC_W/2 - 60 - i*10, 16, 8, 8, dc_rgb(80,160,255));
|
|
36
|
+
for (i = 0; i < s1 && i < 9; i++) dc_rect(DC_W/2 + 56 + i*10, 16, 8, 8, dc_rgb(255,160,80));
|
|
37
|
+
frame++; (void)frame;
|
|
38
|
+
}
|
|
39
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "romdevtools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.1",
|
|
4
4
|
"description": "Tool server giving coding agents full control of homebrew ROM development AND reverse-engineering/romhacking across 17 retro platforms (NES, SNES, GB, Genesis, Atari, C64, PC Engine, MSX, PlayStation, N64, Dreamcast, ...) via WASM toolchains + emulator cores. Use over plain HTTP, as an Agent Skill, or as an MCP server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp/server.js",
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"romdev-core-geargrafx": "0.7.0",
|
|
59
59
|
"romdev-core-gpgx": "0.12.0",
|
|
60
60
|
"romdev-core-handy": "0.7.0",
|
|
61
|
-
"romdev-core-flycast": "0.1.
|
|
61
|
+
"romdev-core-flycast": "0.1.1",
|
|
62
62
|
"romdev-core-parallel-n64": "0.1.0",
|
|
63
|
-
"romdev-core-beetle-psx-hw": "0.1.
|
|
63
|
+
"romdev-core-beetle-psx-hw": "0.1.1",
|
|
64
64
|
"romdev-core-prosystem": "0.8.0",
|
|
65
65
|
"romdev-core-vice": "0.9.0",
|
|
66
66
|
"romdev-famitone": "0.1.0",
|
|
@@ -224,14 +224,15 @@ export const CAPABILITIES = {
|
|
|
224
224
|
// beetle_psx_hw: the GPU renders on the REAL GPU via the GLES3/WebGL2 hardware
|
|
225
225
|
// renderer through native-gles (like glide64-N64 + Flycast-DC), with OpenBIOS
|
|
226
226
|
// EMBEDDED (PCSX-Redux, MIT, region-free) — no Sony firmware to ship, no BIOS file.
|
|
227
|
-
// run/screenshot + cheats live; disasm + decompile work
|
|
228
|
-
// MIPS:LE:32 SLEIGH spec). cpuState
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
227
|
+
// run/screenshot + cheats + cpuState + audioDebug live; disasm + decompile work
|
|
228
|
+
// (MIPS Capstone + the MIPS:LE:32 SLEIGH spec). cpuState (R3000A GPR_full/BACKED_PC)
|
|
229
|
+
// + audioDebug (SPU $1F801C00 register block) come from beetle-side
|
|
230
|
+
// romdev_mips_regs_get/romdev_spu_get exports patched into cpu.c (see
|
|
231
|
+
// scripts/patches/romdev-snippets/beetle-psx-regsnap.c). build needs a PS1
|
|
232
|
+
// toolchain (PSn00bSDK, not yet).
|
|
232
233
|
build: true, run: true, screenshot: true,
|
|
233
234
|
inspectSprites: false, inspectPalette: false, inspectBackground: false,
|
|
234
|
-
renderingContext: false, cpuState:
|
|
235
|
+
renderingContext: false, cpuState: true, audioDebug: true,
|
|
235
236
|
cart: false, disasm: true, decompile: true,
|
|
236
237
|
},
|
|
237
238
|
},
|
|
@@ -264,11 +265,14 @@ export const CAPABILITIES = {
|
|
|
264
265
|
// code (run + memory introspection), and the PowerVR2 present-path works — flycast
|
|
265
266
|
// renders to the GL FBO and the host reads it back (verified: a framebuffer-writing
|
|
266
267
|
// program shows ~727k captured pixels). `build` lands with the sh-elf-gcc WASM
|
|
267
|
-
// toolchain.
|
|
268
|
-
//
|
|
268
|
+
// toolchain. cpuState (SH-4 Sh4cntx regs) + audioDebug (AICA 64-channel register
|
|
269
|
+
// window) come from romdev_sh4_regs_get/romdev_aica_get patched into the flycast
|
|
270
|
+
// libretro entry (see scripts/patches/romdev-snippets/flycast-debug.c). The 3D
|
|
271
|
+
// renderer has no tile/sprite inspectors (N/A by hw). disasm/decompile = SH-4
|
|
272
|
+
// analysis slice (rizin `sh` + Ghidra SuperH4 SLEIGH).
|
|
269
273
|
build: true, run: true, screenshot: true,
|
|
270
274
|
inspectSprites: false, inspectPalette: false, inspectBackground: false,
|
|
271
|
-
renderingContext: false, cpuState:
|
|
275
|
+
renderingContext: false, cpuState: true, audioDebug: true,
|
|
272
276
|
cart: false, disasm: true, decompile: true,
|
|
273
277
|
},
|
|
274
278
|
},
|