romdevtools 0.22.0 → 0.22.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 +8 -0
- package/package.json +1 -1
- package/src/mcp/tools/watch-memory.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ 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.22.1
|
|
8
|
+
|
|
9
|
+
Doc-only follow-up to 0.22.0's movement-analysis feedback: the `pressDuring`
|
|
10
|
+
schema on `watch` and `breakpoint` now states that entries with OVERLAPPING
|
|
11
|
+
windows on the same port are OR'd into a chord (e.g. `b`+`right` held while `a`
|
|
12
|
+
fires mid-window), not overwritten. The driver already behaved this way; this
|
|
13
|
+
documents the guarantee so it doesn't have to be confirmed empirically.
|
|
14
|
+
|
|
7
15
|
## 0.22.0
|
|
8
16
|
|
|
9
17
|
**Transparency + correctness pass: every tool failure is actionable, dangerous
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "romdevtools",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "Tool server giving coding agents full control of homebrew ROM development AND reverse-engineering/romhacking across 14 retro platforms (NES, SNES, GB, Genesis, Atari, C64, PC Engine, MSX, ...) 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",
|
|
@@ -761,7 +761,7 @@ export function registerWatchMemoryTools(server, z, sessionKey) {
|
|
|
761
761
|
button: z.string(),
|
|
762
762
|
port: z.number().int().min(0).max(3).default(0),
|
|
763
763
|
holdFrames: z.number().int().min(1).default(2),
|
|
764
|
-
})).optional().describe("Schedule input while waiting (drive the game to the state that triggers the condition). If OMITTED, this run inherits whatever input({op:'set'}) last held — same as frame({op:'step'}). If GIVEN, the schedule OWNS the pad for the whole run (a prior input({op:'set'}) is ignored); use it to drive the watched window itself."),
|
|
764
|
+
})).optional().describe("Schedule input while waiting (drive the game to the state that triggers the condition). If OMITTED, this run inherits whatever input({op:'set'}) last held — same as frame({op:'step'}). If GIVEN, the schedule OWNS the pad for the whole run (a prior input({op:'set'}) is ignored); use it to drive the watched window itself. Entries with OVERLAPPING windows on the same port are OR'd into a chord (e.g. b+right held while a fires mid-window), not overwritten."),
|
|
765
765
|
abortIf: z.array(z.object({
|
|
766
766
|
region: z.enum(MEMORY_REGIONS).optional().describe("memory region (default system_ram)"),
|
|
767
767
|
offset: z.number().int().min(0).describe("byte offset within the region"),
|
|
@@ -1040,7 +1040,7 @@ export function registerWatchMemoryTools(server, z, sessionKey) {
|
|
|
1040
1040
|
button: z.string(),
|
|
1041
1041
|
port: z.number().int().min(0).max(3).default(0),
|
|
1042
1042
|
holdFrames: z.number().int().min(1).default(2),
|
|
1043
|
-
})).optional().describe("Schedule input while watching (drive the game to the state that touches the watched bytes/range, or uploads the graphic for on:'dma'). If OMITTED, this run inherits whatever input({op:'set'}) last held — same as frame({op:'step'}). If GIVEN, the schedule OWNS the pad for the whole run (a prior input({op:'set'}) is ignored)."),
|
|
1043
|
+
})).optional().describe("Schedule input while watching (drive the game to the state that touches the watched bytes/range, or uploads the graphic for on:'dma'). If OMITTED, this run inherits whatever input({op:'set'}) last held — same as frame({op:'step'}). If GIVEN, the schedule OWNS the pad for the whole run (a prior input({op:'set'}) is ignored). Entries with OVERLAPPING windows on the same port are OR'd into a chord (e.g. b+right held while a fires mid-window), not overwritten."),
|
|
1044
1044
|
fromState: z.string().optional().describe("on:'range'/'pc' — restore an in-memory savestate SLOT (from state({op:'save', name})) BEFORE tracing, so the log runs from a known moment (jump to the boss fight, then see what writes HP). Deterministic + repeatable."),
|
|
1045
1045
|
fromStatePath: z.string().optional().describe("on:'range'/'pc' — like fromState but restore from a savestate FILE on disk (state({op:'save', path})). Relative path resolves against the loaded ROM's dir."),
|
|
1046
1046
|
},
|