c64-debug-mcp 1.0.12 → 1.0.14
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/dist/http.cjs +139 -63
- package/dist/http.js +139 -63
- package/dist/stdio.cjs +139 -63
- package/dist/stdio.js +139 -63
- package/package.json +1 -1
package/dist/http.cjs
CHANGED
|
@@ -66,7 +66,7 @@ var stopReasonSchema = import_zod.z.enum([
|
|
|
66
66
|
]);
|
|
67
67
|
var sessionHealthSchema = import_zod.z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
68
68
|
var breakpointKindSchema = import_zod.z.enum(["exec", "read", "write", "read_write"]);
|
|
69
|
-
var resetModeSchema = import_zod.z.enum(["soft", "hard"]);
|
|
69
|
+
var resetModeSchema = import_zod.z.enum(["soft", "hard", "nuclear"]);
|
|
70
70
|
var inputActionSchema = import_zod.z.enum(["press", "release", "tap"]);
|
|
71
71
|
var joystickControlSchema = import_zod.z.enum(["up", "down", "left", "right", "fire"]);
|
|
72
72
|
var joystickPortSchema = import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(2)]);
|
|
@@ -1728,7 +1728,17 @@ var ViceSession = class {
|
|
|
1728
1728
|
}
|
|
1729
1729
|
this.#syncMonitorRuntimeState();
|
|
1730
1730
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1731
|
-
void this.#scheduleRecovery()
|
|
1731
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1732
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
this.#client.on("transport-error", (error) => {
|
|
1737
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1738
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1739
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1740
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1741
|
+
});
|
|
1732
1742
|
}
|
|
1733
1743
|
});
|
|
1734
1744
|
this.#client.on("event", (event) => {
|
|
@@ -2069,6 +2079,10 @@ var ViceSession = class {
|
|
|
2069
2079
|
async resetMachine(mode) {
|
|
2070
2080
|
return this.#withExecutionLock(async () => {
|
|
2071
2081
|
await this.#ensureReady();
|
|
2082
|
+
this.#clearHeldInputState();
|
|
2083
|
+
if (mode === "nuclear") {
|
|
2084
|
+
return await this.#performNuclearReset();
|
|
2085
|
+
}
|
|
2072
2086
|
const wasPaused = this.#explicitPauseActive;
|
|
2073
2087
|
this.#lastExecutionIntent = "reset";
|
|
2074
2088
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2088,6 +2102,67 @@ var ViceSession = class {
|
|
|
2088
2102
|
};
|
|
2089
2103
|
});
|
|
2090
2104
|
}
|
|
2105
|
+
async #performNuclearReset() {
|
|
2106
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2107
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2108
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2109
|
+
await this.#scheduleRecovery();
|
|
2110
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2111
|
+
this.#explicitPauseActive = wasPaused;
|
|
2112
|
+
if (wasPaused) {
|
|
2113
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2114
|
+
await this.pauseExecution();
|
|
2115
|
+
}
|
|
2116
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2117
|
+
const debugState = await this.#readDebugState();
|
|
2118
|
+
return {
|
|
2119
|
+
executionState: debugState.executionState,
|
|
2120
|
+
lastStopReason: debugState.lastStopReason,
|
|
2121
|
+
programCounter: debugState.programCounter,
|
|
2122
|
+
registers: debugState.registers,
|
|
2123
|
+
warnings: []
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
async #captureBreakpointState() {
|
|
2127
|
+
try {
|
|
2128
|
+
const result = await this.listBreakpoints(true);
|
|
2129
|
+
return result.breakpoints.map((bp) => ({
|
|
2130
|
+
kind: bp.kind,
|
|
2131
|
+
start: bp.start,
|
|
2132
|
+
end: bp.end,
|
|
2133
|
+
enabled: bp.enabled,
|
|
2134
|
+
temporary: bp.temporary,
|
|
2135
|
+
hasCondition: bp.hasCondition,
|
|
2136
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2137
|
+
}));
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2140
|
+
return [];
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2144
|
+
if (savedBreakpoints.length === 0) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2148
|
+
for (const bp of savedBreakpoints) {
|
|
2149
|
+
try {
|
|
2150
|
+
await this.breakpointSet({
|
|
2151
|
+
kind: bp.kind,
|
|
2152
|
+
address: bp.start,
|
|
2153
|
+
length: bp.end - bp.start + 1,
|
|
2154
|
+
enabled: bp.enabled,
|
|
2155
|
+
temporary: bp.temporary,
|
|
2156
|
+
label: bp.label ?? void 0
|
|
2157
|
+
});
|
|
2158
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2159
|
+
} catch (error) {
|
|
2160
|
+
this.#writeProcessLogLine(
|
|
2161
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2091
2166
|
async listBreakpoints(includeDisabled = true) {
|
|
2092
2167
|
await this.#ensureReady();
|
|
2093
2168
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2802,7 +2877,9 @@ var ViceSession = class {
|
|
|
2802
2877
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2803
2878
|
];
|
|
2804
2879
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2805
|
-
void this.#scheduleRecovery()
|
|
2880
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2881
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2882
|
+
});
|
|
2806
2883
|
}
|
|
2807
2884
|
});
|
|
2808
2885
|
child.once("error", (error) => {
|
|
@@ -2815,12 +2892,16 @@ var ViceSession = class {
|
|
|
2815
2892
|
this.#transportState = "faulted";
|
|
2816
2893
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2817
2894
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2818
|
-
void this.#scheduleRecovery()
|
|
2895
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2896
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2897
|
+
});
|
|
2819
2898
|
}
|
|
2820
2899
|
});
|
|
2821
2900
|
}
|
|
2822
2901
|
#attachProcessLogging(child, binary, args) {
|
|
2823
2902
|
const logStream = (0, import_node_fs.createWriteStream)(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2903
|
+
logStream.on("error", () => {
|
|
2904
|
+
});
|
|
2824
2905
|
this.#processLogStream = logStream;
|
|
2825
2906
|
this.#stdoutMirrorBuffer = "";
|
|
2826
2907
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2854,7 +2935,10 @@ var ViceSession = class {
|
|
|
2854
2935
|
logStream.write(`
|
|
2855
2936
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2856
2937
|
`);
|
|
2857
|
-
logStream.end()
|
|
2938
|
+
logStream.end(() => {
|
|
2939
|
+
});
|
|
2940
|
+
logStream.on("error", () => {
|
|
2941
|
+
});
|
|
2858
2942
|
this.#processLogStream = null;
|
|
2859
2943
|
}
|
|
2860
2944
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3636,40 +3720,35 @@ var setRegistersTool = createViceTool({
|
|
|
3636
3720
|
});
|
|
3637
3721
|
var readMemoryTool = createViceTool({
|
|
3638
3722
|
id: "memory_read",
|
|
3639
|
-
description: "Reads a memory chunk.
|
|
3640
|
-
inputSchema: import_zod4.z.
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
message: "address + length must stay within the 64K address space",
|
|
3646
|
-
path: ["length"]
|
|
3647
|
-
}),
|
|
3648
|
-
import_zod4.z.object({
|
|
3649
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3650
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)")
|
|
3651
|
-
}).refine((input) => input.start <= input.end, {
|
|
3652
|
-
message: "End address must be greater than or equal to start address",
|
|
3653
|
-
path: ["end"]
|
|
3654
|
-
}).refine((input) => input.end < 65536, {
|
|
3655
|
-
message: "End address must stay within the 64K address space",
|
|
3656
|
-
path: ["end"]
|
|
3657
|
-
})
|
|
3658
|
-
]),
|
|
3723
|
+
description: "Reads a memory chunk. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000). Returns byte values as decimal numbers.",
|
|
3724
|
+
inputSchema: import_zod4.z.object({
|
|
3725
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3726
|
+
data_length: import_zod4.z.number().int().positive().max(65535).optional().describe("Number of bytes to read (use either data_length or end_address)"),
|
|
3727
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address.")
|
|
3728
|
+
}),
|
|
3659
3729
|
dataSchema: import_zod4.z.object({
|
|
3660
|
-
address:
|
|
3730
|
+
address: address16Schema.describe("Start address of the returned memory chunk"),
|
|
3661
3731
|
length: import_zod4.z.number().int().min(0).describe("Number of bytes returned"),
|
|
3662
3732
|
data: byteArraySchema.describe("Raw bytes returned from memory")
|
|
3663
3733
|
}),
|
|
3664
3734
|
execute: async (input) => {
|
|
3665
|
-
|
|
3735
|
+
const address = input.start_address;
|
|
3666
3736
|
let length;
|
|
3667
|
-
if (
|
|
3668
|
-
address
|
|
3669
|
-
|
|
3737
|
+
if (input.end_address !== void 0) {
|
|
3738
|
+
if (address > input.end_address) {
|
|
3739
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3740
|
+
}
|
|
3741
|
+
if (input.end_address >= 65536) {
|
|
3742
|
+
throw new Error("End address must stay within the 64K address space");
|
|
3743
|
+
}
|
|
3744
|
+
length = input.end_address - address + 1;
|
|
3745
|
+
} else if (input.data_length !== void 0) {
|
|
3746
|
+
length = input.data_length;
|
|
3747
|
+
if (address + length > 65536) {
|
|
3748
|
+
throw new Error("address + length must stay within the 64K address space");
|
|
3749
|
+
}
|
|
3670
3750
|
} else {
|
|
3671
|
-
|
|
3672
|
-
length = input.length;
|
|
3751
|
+
throw new Error("Must provide either data_length or end_address");
|
|
3673
3752
|
}
|
|
3674
3753
|
const result = await c64Session.readMemory(address, address + length - 1);
|
|
3675
3754
|
return {
|
|
@@ -3691,7 +3770,7 @@ var writeMemoryTool = createViceTool({
|
|
|
3691
3770
|
}),
|
|
3692
3771
|
dataSchema: import_zod4.z.object({
|
|
3693
3772
|
worked: import_zod4.z.boolean().describe("Whether the write operation completed successfully"),
|
|
3694
|
-
address:
|
|
3773
|
+
address: address16Schema.describe("Start address where the bytes were written"),
|
|
3695
3774
|
length: import_zod4.z.number().int().min(1).describe("Number of bytes written")
|
|
3696
3775
|
}).extend(debugStateSchema.shape),
|
|
3697
3776
|
execute: async (input) => await c64Session.writeMemory(input.address, input.data)
|
|
@@ -3702,7 +3781,7 @@ var executeTool = createViceTool({
|
|
|
3702
3781
|
inputSchema: import_zod4.z.object({
|
|
3703
3782
|
action: import_zod4.z.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3704
3783
|
count: import_zod4.z.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3705
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3784
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3706
3785
|
waitUntilRunningStable: import_zod4.z.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3707
3786
|
}),
|
|
3708
3787
|
dataSchema: debugStateSchema.extend({
|
|
@@ -3740,47 +3819,44 @@ var listBreakpointsTool = createViceTool({
|
|
|
3740
3819
|
});
|
|
3741
3820
|
var breakpointSetTool = createViceTool({
|
|
3742
3821
|
id: "breakpoint_set",
|
|
3743
|
-
description: "Creates an execution breakpoint or read/write watchpoint.
|
|
3744
|
-
inputSchema: import_zod4.z.
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
import_zod4.z.object({
|
|
3755
|
-
kind: breakpointKindSchema,
|
|
3756
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3757
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3758
|
-
condition: import_zod4.z.string().optional(),
|
|
3759
|
-
label: import_zod4.z.string().optional(),
|
|
3760
|
-
temporary: import_zod4.z.boolean().default(false),
|
|
3761
|
-
enabled: import_zod4.z.boolean().default(true)
|
|
3762
|
-
}).refine((input) => input.start <= input.end, {
|
|
3763
|
-
message: "End address must be greater than or equal to start address",
|
|
3764
|
-
path: ["end"]
|
|
3765
|
-
})
|
|
3766
|
-
]),
|
|
3822
|
+
description: "Creates an execution breakpoint or read/write watchpoint. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000).",
|
|
3823
|
+
inputSchema: import_zod4.z.object({
|
|
3824
|
+
kind: breakpointKindSchema,
|
|
3825
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3826
|
+
data_length: import_zod4.z.number().int().positive().default(1).describe("Size of the breakpoint range in bytes (use either data_length or end_address)"),
|
|
3827
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address."),
|
|
3828
|
+
condition: import_zod4.z.string().optional(),
|
|
3829
|
+
label: import_zod4.z.string().optional(),
|
|
3830
|
+
temporary: import_zod4.z.boolean().default(false),
|
|
3831
|
+
enabled: import_zod4.z.boolean().default(true)
|
|
3832
|
+
}),
|
|
3767
3833
|
dataSchema: import_zod4.z.object({
|
|
3768
3834
|
breakpoint: breakpointSchema,
|
|
3769
3835
|
executionState: executionStateSchema,
|
|
3770
3836
|
lastStopReason: stopReasonSchema,
|
|
3771
|
-
programCounter:
|
|
3837
|
+
programCounter: address16Schema.nullable(),
|
|
3772
3838
|
registers: c64PartialRegisterValueSchema.nullable()
|
|
3773
3839
|
}),
|
|
3774
3840
|
execute: async (input) => {
|
|
3775
|
-
const
|
|
3841
|
+
const address = input.start_address;
|
|
3842
|
+
let length;
|
|
3843
|
+
if (input.end_address !== void 0) {
|
|
3844
|
+
if (address > input.end_address) {
|
|
3845
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3846
|
+
}
|
|
3847
|
+
length = input.end_address - address + 1;
|
|
3848
|
+
} else {
|
|
3849
|
+
length = input.data_length;
|
|
3850
|
+
}
|
|
3851
|
+
const normalizedInput = {
|
|
3776
3852
|
kind: input.kind,
|
|
3777
|
-
address
|
|
3778
|
-
length
|
|
3853
|
+
address,
|
|
3854
|
+
length,
|
|
3779
3855
|
condition: input.condition,
|
|
3780
3856
|
label: input.label,
|
|
3781
3857
|
temporary: input.temporary,
|
|
3782
3858
|
enabled: input.enabled
|
|
3783
|
-
}
|
|
3859
|
+
};
|
|
3784
3860
|
const result = await c64Session.breakpointSet(normalizedInput);
|
|
3785
3861
|
return {
|
|
3786
3862
|
breakpoint: normalizeBreakpoint(result.breakpoint),
|
package/dist/http.js
CHANGED
|
@@ -43,7 +43,7 @@ var stopReasonSchema = z.enum([
|
|
|
43
43
|
]);
|
|
44
44
|
var sessionHealthSchema = z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
45
45
|
var breakpointKindSchema = z.enum(["exec", "read", "write", "read_write"]);
|
|
46
|
-
var resetModeSchema = z.enum(["soft", "hard"]);
|
|
46
|
+
var resetModeSchema = z.enum(["soft", "hard", "nuclear"]);
|
|
47
47
|
var inputActionSchema = z.enum(["press", "release", "tap"]);
|
|
48
48
|
var joystickControlSchema = z.enum(["up", "down", "left", "right", "fire"]);
|
|
49
49
|
var joystickPortSchema = z.union([z.literal(1), z.literal(2)]);
|
|
@@ -1705,7 +1705,17 @@ var ViceSession = class {
|
|
|
1705
1705
|
}
|
|
1706
1706
|
this.#syncMonitorRuntimeState();
|
|
1707
1707
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1708
|
-
void this.#scheduleRecovery()
|
|
1708
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1709
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
});
|
|
1713
|
+
this.#client.on("transport-error", (error) => {
|
|
1714
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1715
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1716
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1717
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1718
|
+
});
|
|
1709
1719
|
}
|
|
1710
1720
|
});
|
|
1711
1721
|
this.#client.on("event", (event) => {
|
|
@@ -2046,6 +2056,10 @@ var ViceSession = class {
|
|
|
2046
2056
|
async resetMachine(mode) {
|
|
2047
2057
|
return this.#withExecutionLock(async () => {
|
|
2048
2058
|
await this.#ensureReady();
|
|
2059
|
+
this.#clearHeldInputState();
|
|
2060
|
+
if (mode === "nuclear") {
|
|
2061
|
+
return await this.#performNuclearReset();
|
|
2062
|
+
}
|
|
2049
2063
|
const wasPaused = this.#explicitPauseActive;
|
|
2050
2064
|
this.#lastExecutionIntent = "reset";
|
|
2051
2065
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2065,6 +2079,67 @@ var ViceSession = class {
|
|
|
2065
2079
|
};
|
|
2066
2080
|
});
|
|
2067
2081
|
}
|
|
2082
|
+
async #performNuclearReset() {
|
|
2083
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2084
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2085
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2086
|
+
await this.#scheduleRecovery();
|
|
2087
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2088
|
+
this.#explicitPauseActive = wasPaused;
|
|
2089
|
+
if (wasPaused) {
|
|
2090
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2091
|
+
await this.pauseExecution();
|
|
2092
|
+
}
|
|
2093
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2094
|
+
const debugState = await this.#readDebugState();
|
|
2095
|
+
return {
|
|
2096
|
+
executionState: debugState.executionState,
|
|
2097
|
+
lastStopReason: debugState.lastStopReason,
|
|
2098
|
+
programCounter: debugState.programCounter,
|
|
2099
|
+
registers: debugState.registers,
|
|
2100
|
+
warnings: []
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
async #captureBreakpointState() {
|
|
2104
|
+
try {
|
|
2105
|
+
const result = await this.listBreakpoints(true);
|
|
2106
|
+
return result.breakpoints.map((bp) => ({
|
|
2107
|
+
kind: bp.kind,
|
|
2108
|
+
start: bp.start,
|
|
2109
|
+
end: bp.end,
|
|
2110
|
+
enabled: bp.enabled,
|
|
2111
|
+
temporary: bp.temporary,
|
|
2112
|
+
hasCondition: bp.hasCondition,
|
|
2113
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2114
|
+
}));
|
|
2115
|
+
} catch (error) {
|
|
2116
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2117
|
+
return [];
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2121
|
+
if (savedBreakpoints.length === 0) {
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2125
|
+
for (const bp of savedBreakpoints) {
|
|
2126
|
+
try {
|
|
2127
|
+
await this.breakpointSet({
|
|
2128
|
+
kind: bp.kind,
|
|
2129
|
+
address: bp.start,
|
|
2130
|
+
length: bp.end - bp.start + 1,
|
|
2131
|
+
enabled: bp.enabled,
|
|
2132
|
+
temporary: bp.temporary,
|
|
2133
|
+
label: bp.label ?? void 0
|
|
2134
|
+
});
|
|
2135
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2136
|
+
} catch (error) {
|
|
2137
|
+
this.#writeProcessLogLine(
|
|
2138
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2068
2143
|
async listBreakpoints(includeDisabled = true) {
|
|
2069
2144
|
await this.#ensureReady();
|
|
2070
2145
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2779,7 +2854,9 @@ var ViceSession = class {
|
|
|
2779
2854
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2780
2855
|
];
|
|
2781
2856
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2782
|
-
void this.#scheduleRecovery()
|
|
2857
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2858
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2859
|
+
});
|
|
2783
2860
|
}
|
|
2784
2861
|
});
|
|
2785
2862
|
child.once("error", (error) => {
|
|
@@ -2792,12 +2869,16 @@ var ViceSession = class {
|
|
|
2792
2869
|
this.#transportState = "faulted";
|
|
2793
2870
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2794
2871
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2795
|
-
void this.#scheduleRecovery()
|
|
2872
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2873
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2874
|
+
});
|
|
2796
2875
|
}
|
|
2797
2876
|
});
|
|
2798
2877
|
}
|
|
2799
2878
|
#attachProcessLogging(child, binary, args) {
|
|
2800
2879
|
const logStream = createWriteStream(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2880
|
+
logStream.on("error", () => {
|
|
2881
|
+
});
|
|
2801
2882
|
this.#processLogStream = logStream;
|
|
2802
2883
|
this.#stdoutMirrorBuffer = "";
|
|
2803
2884
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2831,7 +2912,10 @@ var ViceSession = class {
|
|
|
2831
2912
|
logStream.write(`
|
|
2832
2913
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2833
2914
|
`);
|
|
2834
|
-
logStream.end()
|
|
2915
|
+
logStream.end(() => {
|
|
2916
|
+
});
|
|
2917
|
+
logStream.on("error", () => {
|
|
2918
|
+
});
|
|
2835
2919
|
this.#processLogStream = null;
|
|
2836
2920
|
}
|
|
2837
2921
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3613,40 +3697,35 @@ var setRegistersTool = createViceTool({
|
|
|
3613
3697
|
});
|
|
3614
3698
|
var readMemoryTool = createViceTool({
|
|
3615
3699
|
id: "memory_read",
|
|
3616
|
-
description: "Reads a memory chunk.
|
|
3617
|
-
inputSchema: z3.
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
message: "address + length must stay within the 64K address space",
|
|
3623
|
-
path: ["length"]
|
|
3624
|
-
}),
|
|
3625
|
-
z3.object({
|
|
3626
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3627
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)")
|
|
3628
|
-
}).refine((input) => input.start <= input.end, {
|
|
3629
|
-
message: "End address must be greater than or equal to start address",
|
|
3630
|
-
path: ["end"]
|
|
3631
|
-
}).refine((input) => input.end < 65536, {
|
|
3632
|
-
message: "End address must stay within the 64K address space",
|
|
3633
|
-
path: ["end"]
|
|
3634
|
-
})
|
|
3635
|
-
]),
|
|
3700
|
+
description: "Reads a memory chunk. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000). Returns byte values as decimal numbers.",
|
|
3701
|
+
inputSchema: z3.object({
|
|
3702
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3703
|
+
data_length: z3.number().int().positive().max(65535).optional().describe("Number of bytes to read (use either data_length or end_address)"),
|
|
3704
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address.")
|
|
3705
|
+
}),
|
|
3636
3706
|
dataSchema: z3.object({
|
|
3637
|
-
address:
|
|
3707
|
+
address: address16Schema.describe("Start address of the returned memory chunk"),
|
|
3638
3708
|
length: z3.number().int().min(0).describe("Number of bytes returned"),
|
|
3639
3709
|
data: byteArraySchema.describe("Raw bytes returned from memory")
|
|
3640
3710
|
}),
|
|
3641
3711
|
execute: async (input) => {
|
|
3642
|
-
|
|
3712
|
+
const address = input.start_address;
|
|
3643
3713
|
let length;
|
|
3644
|
-
if (
|
|
3645
|
-
address
|
|
3646
|
-
|
|
3714
|
+
if (input.end_address !== void 0) {
|
|
3715
|
+
if (address > input.end_address) {
|
|
3716
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3717
|
+
}
|
|
3718
|
+
if (input.end_address >= 65536) {
|
|
3719
|
+
throw new Error("End address must stay within the 64K address space");
|
|
3720
|
+
}
|
|
3721
|
+
length = input.end_address - address + 1;
|
|
3722
|
+
} else if (input.data_length !== void 0) {
|
|
3723
|
+
length = input.data_length;
|
|
3724
|
+
if (address + length > 65536) {
|
|
3725
|
+
throw new Error("address + length must stay within the 64K address space");
|
|
3726
|
+
}
|
|
3647
3727
|
} else {
|
|
3648
|
-
|
|
3649
|
-
length = input.length;
|
|
3728
|
+
throw new Error("Must provide either data_length or end_address");
|
|
3650
3729
|
}
|
|
3651
3730
|
const result = await c64Session.readMemory(address, address + length - 1);
|
|
3652
3731
|
return {
|
|
@@ -3668,7 +3747,7 @@ var writeMemoryTool = createViceTool({
|
|
|
3668
3747
|
}),
|
|
3669
3748
|
dataSchema: z3.object({
|
|
3670
3749
|
worked: z3.boolean().describe("Whether the write operation completed successfully"),
|
|
3671
|
-
address:
|
|
3750
|
+
address: address16Schema.describe("Start address where the bytes were written"),
|
|
3672
3751
|
length: z3.number().int().min(1).describe("Number of bytes written")
|
|
3673
3752
|
}).extend(debugStateSchema.shape),
|
|
3674
3753
|
execute: async (input) => await c64Session.writeMemory(input.address, input.data)
|
|
@@ -3679,7 +3758,7 @@ var executeTool = createViceTool({
|
|
|
3679
3758
|
inputSchema: z3.object({
|
|
3680
3759
|
action: z3.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3681
3760
|
count: z3.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3682
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3761
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3683
3762
|
waitUntilRunningStable: z3.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3684
3763
|
}),
|
|
3685
3764
|
dataSchema: debugStateSchema.extend({
|
|
@@ -3717,47 +3796,44 @@ var listBreakpointsTool = createViceTool({
|
|
|
3717
3796
|
});
|
|
3718
3797
|
var breakpointSetTool = createViceTool({
|
|
3719
3798
|
id: "breakpoint_set",
|
|
3720
|
-
description: "Creates an execution breakpoint or read/write watchpoint.
|
|
3721
|
-
inputSchema: z3.
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
z3.object({
|
|
3732
|
-
kind: breakpointKindSchema,
|
|
3733
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3734
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3735
|
-
condition: z3.string().optional(),
|
|
3736
|
-
label: z3.string().optional(),
|
|
3737
|
-
temporary: z3.boolean().default(false),
|
|
3738
|
-
enabled: z3.boolean().default(true)
|
|
3739
|
-
}).refine((input) => input.start <= input.end, {
|
|
3740
|
-
message: "End address must be greater than or equal to start address",
|
|
3741
|
-
path: ["end"]
|
|
3742
|
-
})
|
|
3743
|
-
]),
|
|
3799
|
+
description: "Creates an execution breakpoint or read/write watchpoint. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000).",
|
|
3800
|
+
inputSchema: z3.object({
|
|
3801
|
+
kind: breakpointKindSchema,
|
|
3802
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3803
|
+
data_length: z3.number().int().positive().default(1).describe("Size of the breakpoint range in bytes (use either data_length or end_address)"),
|
|
3804
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address."),
|
|
3805
|
+
condition: z3.string().optional(),
|
|
3806
|
+
label: z3.string().optional(),
|
|
3807
|
+
temporary: z3.boolean().default(false),
|
|
3808
|
+
enabled: z3.boolean().default(true)
|
|
3809
|
+
}),
|
|
3744
3810
|
dataSchema: z3.object({
|
|
3745
3811
|
breakpoint: breakpointSchema,
|
|
3746
3812
|
executionState: executionStateSchema,
|
|
3747
3813
|
lastStopReason: stopReasonSchema,
|
|
3748
|
-
programCounter:
|
|
3814
|
+
programCounter: address16Schema.nullable(),
|
|
3749
3815
|
registers: c64PartialRegisterValueSchema.nullable()
|
|
3750
3816
|
}),
|
|
3751
3817
|
execute: async (input) => {
|
|
3752
|
-
const
|
|
3818
|
+
const address = input.start_address;
|
|
3819
|
+
let length;
|
|
3820
|
+
if (input.end_address !== void 0) {
|
|
3821
|
+
if (address > input.end_address) {
|
|
3822
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3823
|
+
}
|
|
3824
|
+
length = input.end_address - address + 1;
|
|
3825
|
+
} else {
|
|
3826
|
+
length = input.data_length;
|
|
3827
|
+
}
|
|
3828
|
+
const normalizedInput = {
|
|
3753
3829
|
kind: input.kind,
|
|
3754
|
-
address
|
|
3755
|
-
length
|
|
3830
|
+
address,
|
|
3831
|
+
length,
|
|
3756
3832
|
condition: input.condition,
|
|
3757
3833
|
label: input.label,
|
|
3758
3834
|
temporary: input.temporary,
|
|
3759
3835
|
enabled: input.enabled
|
|
3760
|
-
}
|
|
3836
|
+
};
|
|
3761
3837
|
const result = await c64Session.breakpointSet(normalizedInput);
|
|
3762
3838
|
return {
|
|
3763
3839
|
breakpoint: normalizeBreakpoint(result.breakpoint),
|
package/dist/stdio.cjs
CHANGED
|
@@ -63,7 +63,7 @@ var stopReasonSchema = import_zod.z.enum([
|
|
|
63
63
|
]);
|
|
64
64
|
var sessionHealthSchema = import_zod.z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
65
65
|
var breakpointKindSchema = import_zod.z.enum(["exec", "read", "write", "read_write"]);
|
|
66
|
-
var resetModeSchema = import_zod.z.enum(["soft", "hard"]);
|
|
66
|
+
var resetModeSchema = import_zod.z.enum(["soft", "hard", "nuclear"]);
|
|
67
67
|
var inputActionSchema = import_zod.z.enum(["press", "release", "tap"]);
|
|
68
68
|
var joystickControlSchema = import_zod.z.enum(["up", "down", "left", "right", "fire"]);
|
|
69
69
|
var joystickPortSchema = import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(2)]);
|
|
@@ -1725,7 +1725,17 @@ var ViceSession = class {
|
|
|
1725
1725
|
}
|
|
1726
1726
|
this.#syncMonitorRuntimeState();
|
|
1727
1727
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1728
|
-
void this.#scheduleRecovery()
|
|
1728
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1729
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
});
|
|
1733
|
+
this.#client.on("transport-error", (error) => {
|
|
1734
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1735
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1736
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1737
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1738
|
+
});
|
|
1729
1739
|
}
|
|
1730
1740
|
});
|
|
1731
1741
|
this.#client.on("event", (event) => {
|
|
@@ -2066,6 +2076,10 @@ var ViceSession = class {
|
|
|
2066
2076
|
async resetMachine(mode) {
|
|
2067
2077
|
return this.#withExecutionLock(async () => {
|
|
2068
2078
|
await this.#ensureReady();
|
|
2079
|
+
this.#clearHeldInputState();
|
|
2080
|
+
if (mode === "nuclear") {
|
|
2081
|
+
return await this.#performNuclearReset();
|
|
2082
|
+
}
|
|
2069
2083
|
const wasPaused = this.#explicitPauseActive;
|
|
2070
2084
|
this.#lastExecutionIntent = "reset";
|
|
2071
2085
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2085,6 +2099,67 @@ var ViceSession = class {
|
|
|
2085
2099
|
};
|
|
2086
2100
|
});
|
|
2087
2101
|
}
|
|
2102
|
+
async #performNuclearReset() {
|
|
2103
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2104
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2105
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2106
|
+
await this.#scheduleRecovery();
|
|
2107
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2108
|
+
this.#explicitPauseActive = wasPaused;
|
|
2109
|
+
if (wasPaused) {
|
|
2110
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2111
|
+
await this.pauseExecution();
|
|
2112
|
+
}
|
|
2113
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2114
|
+
const debugState = await this.#readDebugState();
|
|
2115
|
+
return {
|
|
2116
|
+
executionState: debugState.executionState,
|
|
2117
|
+
lastStopReason: debugState.lastStopReason,
|
|
2118
|
+
programCounter: debugState.programCounter,
|
|
2119
|
+
registers: debugState.registers,
|
|
2120
|
+
warnings: []
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
async #captureBreakpointState() {
|
|
2124
|
+
try {
|
|
2125
|
+
const result = await this.listBreakpoints(true);
|
|
2126
|
+
return result.breakpoints.map((bp) => ({
|
|
2127
|
+
kind: bp.kind,
|
|
2128
|
+
start: bp.start,
|
|
2129
|
+
end: bp.end,
|
|
2130
|
+
enabled: bp.enabled,
|
|
2131
|
+
temporary: bp.temporary,
|
|
2132
|
+
hasCondition: bp.hasCondition,
|
|
2133
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2134
|
+
}));
|
|
2135
|
+
} catch (error) {
|
|
2136
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2137
|
+
return [];
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2141
|
+
if (savedBreakpoints.length === 0) {
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2144
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2145
|
+
for (const bp of savedBreakpoints) {
|
|
2146
|
+
try {
|
|
2147
|
+
await this.breakpointSet({
|
|
2148
|
+
kind: bp.kind,
|
|
2149
|
+
address: bp.start,
|
|
2150
|
+
length: bp.end - bp.start + 1,
|
|
2151
|
+
enabled: bp.enabled,
|
|
2152
|
+
temporary: bp.temporary,
|
|
2153
|
+
label: bp.label ?? void 0
|
|
2154
|
+
});
|
|
2155
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2156
|
+
} catch (error) {
|
|
2157
|
+
this.#writeProcessLogLine(
|
|
2158
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2088
2163
|
async listBreakpoints(includeDisabled = true) {
|
|
2089
2164
|
await this.#ensureReady();
|
|
2090
2165
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2799,7 +2874,9 @@ var ViceSession = class {
|
|
|
2799
2874
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2800
2875
|
];
|
|
2801
2876
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2802
|
-
void this.#scheduleRecovery()
|
|
2877
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2878
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2879
|
+
});
|
|
2803
2880
|
}
|
|
2804
2881
|
});
|
|
2805
2882
|
child.once("error", (error) => {
|
|
@@ -2812,12 +2889,16 @@ var ViceSession = class {
|
|
|
2812
2889
|
this.#transportState = "faulted";
|
|
2813
2890
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2814
2891
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2815
|
-
void this.#scheduleRecovery()
|
|
2892
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2893
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2894
|
+
});
|
|
2816
2895
|
}
|
|
2817
2896
|
});
|
|
2818
2897
|
}
|
|
2819
2898
|
#attachProcessLogging(child, binary, args) {
|
|
2820
2899
|
const logStream = (0, import_node_fs.createWriteStream)(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2900
|
+
logStream.on("error", () => {
|
|
2901
|
+
});
|
|
2821
2902
|
this.#processLogStream = logStream;
|
|
2822
2903
|
this.#stdoutMirrorBuffer = "";
|
|
2823
2904
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2851,7 +2932,10 @@ var ViceSession = class {
|
|
|
2851
2932
|
logStream.write(`
|
|
2852
2933
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2853
2934
|
`);
|
|
2854
|
-
logStream.end()
|
|
2935
|
+
logStream.end(() => {
|
|
2936
|
+
});
|
|
2937
|
+
logStream.on("error", () => {
|
|
2938
|
+
});
|
|
2855
2939
|
this.#processLogStream = null;
|
|
2856
2940
|
}
|
|
2857
2941
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3633,40 +3717,35 @@ var setRegistersTool = createViceTool({
|
|
|
3633
3717
|
});
|
|
3634
3718
|
var readMemoryTool = createViceTool({
|
|
3635
3719
|
id: "memory_read",
|
|
3636
|
-
description: "Reads a memory chunk.
|
|
3637
|
-
inputSchema: import_zod4.z.
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
message: "address + length must stay within the 64K address space",
|
|
3643
|
-
path: ["length"]
|
|
3644
|
-
}),
|
|
3645
|
-
import_zod4.z.object({
|
|
3646
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3647
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)")
|
|
3648
|
-
}).refine((input) => input.start <= input.end, {
|
|
3649
|
-
message: "End address must be greater than or equal to start address",
|
|
3650
|
-
path: ["end"]
|
|
3651
|
-
}).refine((input) => input.end < 65536, {
|
|
3652
|
-
message: "End address must stay within the 64K address space",
|
|
3653
|
-
path: ["end"]
|
|
3654
|
-
})
|
|
3655
|
-
]),
|
|
3720
|
+
description: "Reads a memory chunk. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000). Returns byte values as decimal numbers.",
|
|
3721
|
+
inputSchema: import_zod4.z.object({
|
|
3722
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3723
|
+
data_length: import_zod4.z.number().int().positive().max(65535).optional().describe("Number of bytes to read (use either data_length or end_address)"),
|
|
3724
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address.")
|
|
3725
|
+
}),
|
|
3656
3726
|
dataSchema: import_zod4.z.object({
|
|
3657
|
-
address:
|
|
3727
|
+
address: address16Schema.describe("Start address of the returned memory chunk"),
|
|
3658
3728
|
length: import_zod4.z.number().int().min(0).describe("Number of bytes returned"),
|
|
3659
3729
|
data: byteArraySchema.describe("Raw bytes returned from memory")
|
|
3660
3730
|
}),
|
|
3661
3731
|
execute: async (input) => {
|
|
3662
|
-
|
|
3732
|
+
const address = input.start_address;
|
|
3663
3733
|
let length;
|
|
3664
|
-
if (
|
|
3665
|
-
address
|
|
3666
|
-
|
|
3734
|
+
if (input.end_address !== void 0) {
|
|
3735
|
+
if (address > input.end_address) {
|
|
3736
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3737
|
+
}
|
|
3738
|
+
if (input.end_address >= 65536) {
|
|
3739
|
+
throw new Error("End address must stay within the 64K address space");
|
|
3740
|
+
}
|
|
3741
|
+
length = input.end_address - address + 1;
|
|
3742
|
+
} else if (input.data_length !== void 0) {
|
|
3743
|
+
length = input.data_length;
|
|
3744
|
+
if (address + length > 65536) {
|
|
3745
|
+
throw new Error("address + length must stay within the 64K address space");
|
|
3746
|
+
}
|
|
3667
3747
|
} else {
|
|
3668
|
-
|
|
3669
|
-
length = input.length;
|
|
3748
|
+
throw new Error("Must provide either data_length or end_address");
|
|
3670
3749
|
}
|
|
3671
3750
|
const result = await c64Session.readMemory(address, address + length - 1);
|
|
3672
3751
|
return {
|
|
@@ -3688,7 +3767,7 @@ var writeMemoryTool = createViceTool({
|
|
|
3688
3767
|
}),
|
|
3689
3768
|
dataSchema: import_zod4.z.object({
|
|
3690
3769
|
worked: import_zod4.z.boolean().describe("Whether the write operation completed successfully"),
|
|
3691
|
-
address:
|
|
3770
|
+
address: address16Schema.describe("Start address where the bytes were written"),
|
|
3692
3771
|
length: import_zod4.z.number().int().min(1).describe("Number of bytes written")
|
|
3693
3772
|
}).extend(debugStateSchema.shape),
|
|
3694
3773
|
execute: async (input) => await c64Session.writeMemory(input.address, input.data)
|
|
@@ -3699,7 +3778,7 @@ var executeTool = createViceTool({
|
|
|
3699
3778
|
inputSchema: import_zod4.z.object({
|
|
3700
3779
|
action: import_zod4.z.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3701
3780
|
count: import_zod4.z.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3702
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3781
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3703
3782
|
waitUntilRunningStable: import_zod4.z.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3704
3783
|
}),
|
|
3705
3784
|
dataSchema: debugStateSchema.extend({
|
|
@@ -3737,47 +3816,44 @@ var listBreakpointsTool = createViceTool({
|
|
|
3737
3816
|
});
|
|
3738
3817
|
var breakpointSetTool = createViceTool({
|
|
3739
3818
|
id: "breakpoint_set",
|
|
3740
|
-
description: "Creates an execution breakpoint or read/write watchpoint.
|
|
3741
|
-
inputSchema: import_zod4.z.
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
import_zod4.z.object({
|
|
3752
|
-
kind: breakpointKindSchema,
|
|
3753
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3754
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3755
|
-
condition: import_zod4.z.string().optional(),
|
|
3756
|
-
label: import_zod4.z.string().optional(),
|
|
3757
|
-
temporary: import_zod4.z.boolean().default(false),
|
|
3758
|
-
enabled: import_zod4.z.boolean().default(true)
|
|
3759
|
-
}).refine((input) => input.start <= input.end, {
|
|
3760
|
-
message: "End address must be greater than or equal to start address",
|
|
3761
|
-
path: ["end"]
|
|
3762
|
-
})
|
|
3763
|
-
]),
|
|
3819
|
+
description: "Creates an execution breakpoint or read/write watchpoint. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000).",
|
|
3820
|
+
inputSchema: import_zod4.z.object({
|
|
3821
|
+
kind: breakpointKindSchema,
|
|
3822
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3823
|
+
data_length: import_zod4.z.number().int().positive().default(1).describe("Size of the breakpoint range in bytes (use either data_length or end_address)"),
|
|
3824
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address."),
|
|
3825
|
+
condition: import_zod4.z.string().optional(),
|
|
3826
|
+
label: import_zod4.z.string().optional(),
|
|
3827
|
+
temporary: import_zod4.z.boolean().default(false),
|
|
3828
|
+
enabled: import_zod4.z.boolean().default(true)
|
|
3829
|
+
}),
|
|
3764
3830
|
dataSchema: import_zod4.z.object({
|
|
3765
3831
|
breakpoint: breakpointSchema,
|
|
3766
3832
|
executionState: executionStateSchema,
|
|
3767
3833
|
lastStopReason: stopReasonSchema,
|
|
3768
|
-
programCounter:
|
|
3834
|
+
programCounter: address16Schema.nullable(),
|
|
3769
3835
|
registers: c64PartialRegisterValueSchema.nullable()
|
|
3770
3836
|
}),
|
|
3771
3837
|
execute: async (input) => {
|
|
3772
|
-
const
|
|
3838
|
+
const address = input.start_address;
|
|
3839
|
+
let length;
|
|
3840
|
+
if (input.end_address !== void 0) {
|
|
3841
|
+
if (address > input.end_address) {
|
|
3842
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3843
|
+
}
|
|
3844
|
+
length = input.end_address - address + 1;
|
|
3845
|
+
} else {
|
|
3846
|
+
length = input.data_length;
|
|
3847
|
+
}
|
|
3848
|
+
const normalizedInput = {
|
|
3773
3849
|
kind: input.kind,
|
|
3774
|
-
address
|
|
3775
|
-
length
|
|
3850
|
+
address,
|
|
3851
|
+
length,
|
|
3776
3852
|
condition: input.condition,
|
|
3777
3853
|
label: input.label,
|
|
3778
3854
|
temporary: input.temporary,
|
|
3779
3855
|
enabled: input.enabled
|
|
3780
|
-
}
|
|
3856
|
+
};
|
|
3781
3857
|
const result = await c64Session.breakpointSet(normalizedInput);
|
|
3782
3858
|
return {
|
|
3783
3859
|
breakpoint: normalizeBreakpoint(result.breakpoint),
|
package/dist/stdio.js
CHANGED
|
@@ -40,7 +40,7 @@ var stopReasonSchema = z.enum([
|
|
|
40
40
|
]);
|
|
41
41
|
var sessionHealthSchema = z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
42
42
|
var breakpointKindSchema = z.enum(["exec", "read", "write", "read_write"]);
|
|
43
|
-
var resetModeSchema = z.enum(["soft", "hard"]);
|
|
43
|
+
var resetModeSchema = z.enum(["soft", "hard", "nuclear"]);
|
|
44
44
|
var inputActionSchema = z.enum(["press", "release", "tap"]);
|
|
45
45
|
var joystickControlSchema = z.enum(["up", "down", "left", "right", "fire"]);
|
|
46
46
|
var joystickPortSchema = z.union([z.literal(1), z.literal(2)]);
|
|
@@ -1702,7 +1702,17 @@ var ViceSession = class {
|
|
|
1702
1702
|
}
|
|
1703
1703
|
this.#syncMonitorRuntimeState();
|
|
1704
1704
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1705
|
-
void this.#scheduleRecovery()
|
|
1705
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1706
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
this.#client.on("transport-error", (error) => {
|
|
1711
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1712
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1713
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1714
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1715
|
+
});
|
|
1706
1716
|
}
|
|
1707
1717
|
});
|
|
1708
1718
|
this.#client.on("event", (event) => {
|
|
@@ -2043,6 +2053,10 @@ var ViceSession = class {
|
|
|
2043
2053
|
async resetMachine(mode) {
|
|
2044
2054
|
return this.#withExecutionLock(async () => {
|
|
2045
2055
|
await this.#ensureReady();
|
|
2056
|
+
this.#clearHeldInputState();
|
|
2057
|
+
if (mode === "nuclear") {
|
|
2058
|
+
return await this.#performNuclearReset();
|
|
2059
|
+
}
|
|
2046
2060
|
const wasPaused = this.#explicitPauseActive;
|
|
2047
2061
|
this.#lastExecutionIntent = "reset";
|
|
2048
2062
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2062,6 +2076,67 @@ var ViceSession = class {
|
|
|
2062
2076
|
};
|
|
2063
2077
|
});
|
|
2064
2078
|
}
|
|
2079
|
+
async #performNuclearReset() {
|
|
2080
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2081
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2082
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2083
|
+
await this.#scheduleRecovery();
|
|
2084
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2085
|
+
this.#explicitPauseActive = wasPaused;
|
|
2086
|
+
if (wasPaused) {
|
|
2087
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2088
|
+
await this.pauseExecution();
|
|
2089
|
+
}
|
|
2090
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2091
|
+
const debugState = await this.#readDebugState();
|
|
2092
|
+
return {
|
|
2093
|
+
executionState: debugState.executionState,
|
|
2094
|
+
lastStopReason: debugState.lastStopReason,
|
|
2095
|
+
programCounter: debugState.programCounter,
|
|
2096
|
+
registers: debugState.registers,
|
|
2097
|
+
warnings: []
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
async #captureBreakpointState() {
|
|
2101
|
+
try {
|
|
2102
|
+
const result = await this.listBreakpoints(true);
|
|
2103
|
+
return result.breakpoints.map((bp) => ({
|
|
2104
|
+
kind: bp.kind,
|
|
2105
|
+
start: bp.start,
|
|
2106
|
+
end: bp.end,
|
|
2107
|
+
enabled: bp.enabled,
|
|
2108
|
+
temporary: bp.temporary,
|
|
2109
|
+
hasCondition: bp.hasCondition,
|
|
2110
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2111
|
+
}));
|
|
2112
|
+
} catch (error) {
|
|
2113
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2114
|
+
return [];
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2118
|
+
if (savedBreakpoints.length === 0) {
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2122
|
+
for (const bp of savedBreakpoints) {
|
|
2123
|
+
try {
|
|
2124
|
+
await this.breakpointSet({
|
|
2125
|
+
kind: bp.kind,
|
|
2126
|
+
address: bp.start,
|
|
2127
|
+
length: bp.end - bp.start + 1,
|
|
2128
|
+
enabled: bp.enabled,
|
|
2129
|
+
temporary: bp.temporary,
|
|
2130
|
+
label: bp.label ?? void 0
|
|
2131
|
+
});
|
|
2132
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2133
|
+
} catch (error) {
|
|
2134
|
+
this.#writeProcessLogLine(
|
|
2135
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2065
2140
|
async listBreakpoints(includeDisabled = true) {
|
|
2066
2141
|
await this.#ensureReady();
|
|
2067
2142
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2776,7 +2851,9 @@ var ViceSession = class {
|
|
|
2776
2851
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2777
2852
|
];
|
|
2778
2853
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2779
|
-
void this.#scheduleRecovery()
|
|
2854
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2855
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2856
|
+
});
|
|
2780
2857
|
}
|
|
2781
2858
|
});
|
|
2782
2859
|
child.once("error", (error) => {
|
|
@@ -2789,12 +2866,16 @@ var ViceSession = class {
|
|
|
2789
2866
|
this.#transportState = "faulted";
|
|
2790
2867
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2791
2868
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2792
|
-
void this.#scheduleRecovery()
|
|
2869
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2870
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2871
|
+
});
|
|
2793
2872
|
}
|
|
2794
2873
|
});
|
|
2795
2874
|
}
|
|
2796
2875
|
#attachProcessLogging(child, binary, args) {
|
|
2797
2876
|
const logStream = createWriteStream(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2877
|
+
logStream.on("error", () => {
|
|
2878
|
+
});
|
|
2798
2879
|
this.#processLogStream = logStream;
|
|
2799
2880
|
this.#stdoutMirrorBuffer = "";
|
|
2800
2881
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2828,7 +2909,10 @@ var ViceSession = class {
|
|
|
2828
2909
|
logStream.write(`
|
|
2829
2910
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2830
2911
|
`);
|
|
2831
|
-
logStream.end()
|
|
2912
|
+
logStream.end(() => {
|
|
2913
|
+
});
|
|
2914
|
+
logStream.on("error", () => {
|
|
2915
|
+
});
|
|
2832
2916
|
this.#processLogStream = null;
|
|
2833
2917
|
}
|
|
2834
2918
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3610,40 +3694,35 @@ var setRegistersTool = createViceTool({
|
|
|
3610
3694
|
});
|
|
3611
3695
|
var readMemoryTool = createViceTool({
|
|
3612
3696
|
id: "memory_read",
|
|
3613
|
-
description: "Reads a memory chunk.
|
|
3614
|
-
inputSchema: z3.
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
message: "address + length must stay within the 64K address space",
|
|
3620
|
-
path: ["length"]
|
|
3621
|
-
}),
|
|
3622
|
-
z3.object({
|
|
3623
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3624
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)")
|
|
3625
|
-
}).refine((input) => input.start <= input.end, {
|
|
3626
|
-
message: "End address must be greater than or equal to start address",
|
|
3627
|
-
path: ["end"]
|
|
3628
|
-
}).refine((input) => input.end < 65536, {
|
|
3629
|
-
message: "End address must stay within the 64K address space",
|
|
3630
|
-
path: ["end"]
|
|
3631
|
-
})
|
|
3632
|
-
]),
|
|
3697
|
+
description: "Reads a memory chunk. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000). Returns byte values as decimal numbers.",
|
|
3698
|
+
inputSchema: z3.object({
|
|
3699
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3700
|
+
data_length: z3.number().int().positive().max(65535).optional().describe("Number of bytes to read (use either data_length or end_address)"),
|
|
3701
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address.")
|
|
3702
|
+
}),
|
|
3633
3703
|
dataSchema: z3.object({
|
|
3634
|
-
address:
|
|
3704
|
+
address: address16Schema.describe("Start address of the returned memory chunk"),
|
|
3635
3705
|
length: z3.number().int().min(0).describe("Number of bytes returned"),
|
|
3636
3706
|
data: byteArraySchema.describe("Raw bytes returned from memory")
|
|
3637
3707
|
}),
|
|
3638
3708
|
execute: async (input) => {
|
|
3639
|
-
|
|
3709
|
+
const address = input.start_address;
|
|
3640
3710
|
let length;
|
|
3641
|
-
if (
|
|
3642
|
-
address
|
|
3643
|
-
|
|
3711
|
+
if (input.end_address !== void 0) {
|
|
3712
|
+
if (address > input.end_address) {
|
|
3713
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3714
|
+
}
|
|
3715
|
+
if (input.end_address >= 65536) {
|
|
3716
|
+
throw new Error("End address must stay within the 64K address space");
|
|
3717
|
+
}
|
|
3718
|
+
length = input.end_address - address + 1;
|
|
3719
|
+
} else if (input.data_length !== void 0) {
|
|
3720
|
+
length = input.data_length;
|
|
3721
|
+
if (address + length > 65536) {
|
|
3722
|
+
throw new Error("address + length must stay within the 64K address space");
|
|
3723
|
+
}
|
|
3644
3724
|
} else {
|
|
3645
|
-
|
|
3646
|
-
length = input.length;
|
|
3725
|
+
throw new Error("Must provide either data_length or end_address");
|
|
3647
3726
|
}
|
|
3648
3727
|
const result = await c64Session.readMemory(address, address + length - 1);
|
|
3649
3728
|
return {
|
|
@@ -3665,7 +3744,7 @@ var writeMemoryTool = createViceTool({
|
|
|
3665
3744
|
}),
|
|
3666
3745
|
dataSchema: z3.object({
|
|
3667
3746
|
worked: z3.boolean().describe("Whether the write operation completed successfully"),
|
|
3668
|
-
address:
|
|
3747
|
+
address: address16Schema.describe("Start address where the bytes were written"),
|
|
3669
3748
|
length: z3.number().int().min(1).describe("Number of bytes written")
|
|
3670
3749
|
}).extend(debugStateSchema.shape),
|
|
3671
3750
|
execute: async (input) => await c64Session.writeMemory(input.address, input.data)
|
|
@@ -3676,7 +3755,7 @@ var executeTool = createViceTool({
|
|
|
3676
3755
|
inputSchema: z3.object({
|
|
3677
3756
|
action: z3.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3678
3757
|
count: z3.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3679
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3758
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3680
3759
|
waitUntilRunningStable: z3.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3681
3760
|
}),
|
|
3682
3761
|
dataSchema: debugStateSchema.extend({
|
|
@@ -3714,47 +3793,44 @@ var listBreakpointsTool = createViceTool({
|
|
|
3714
3793
|
});
|
|
3715
3794
|
var breakpointSetTool = createViceTool({
|
|
3716
3795
|
id: "breakpoint_set",
|
|
3717
|
-
description: "Creates an execution breakpoint or read/write watchpoint.
|
|
3718
|
-
inputSchema: z3.
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
z3.object({
|
|
3729
|
-
kind: breakpointKindSchema,
|
|
3730
|
-
start: address16Schema.describe("Start address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3731
|
-
end: address16Schema.describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3732
|
-
condition: z3.string().optional(),
|
|
3733
|
-
label: z3.string().optional(),
|
|
3734
|
-
temporary: z3.boolean().default(false),
|
|
3735
|
-
enabled: z3.boolean().default(true)
|
|
3736
|
-
}).refine((input) => input.start <= input.end, {
|
|
3737
|
-
message: "End address must be greater than or equal to start address",
|
|
3738
|
-
path: ["end"]
|
|
3739
|
-
})
|
|
3740
|
-
]),
|
|
3796
|
+
description: "Creates an execution breakpoint or read/write watchpoint. Specify start_address and either data_length or end_address. Address can be decimal (53248) or hex string with prefix ($D000, 0xD000).",
|
|
3797
|
+
inputSchema: z3.object({
|
|
3798
|
+
kind: breakpointKindSchema,
|
|
3799
|
+
start_address: address16Schema.describe("Start address: decimal (53248) or hex string with prefix ($D000, 0xD000)"),
|
|
3800
|
+
data_length: z3.number().int().positive().default(1).describe("Size of the breakpoint range in bytes (use either data_length or end_address)"),
|
|
3801
|
+
end_address: address16Schema.optional().describe("End address (inclusive): decimal (53248) or hex string with prefix ($D000, 0xD000). Use either data_length or end_address."),
|
|
3802
|
+
condition: z3.string().optional(),
|
|
3803
|
+
label: z3.string().optional(),
|
|
3804
|
+
temporary: z3.boolean().default(false),
|
|
3805
|
+
enabled: z3.boolean().default(true)
|
|
3806
|
+
}),
|
|
3741
3807
|
dataSchema: z3.object({
|
|
3742
3808
|
breakpoint: breakpointSchema,
|
|
3743
3809
|
executionState: executionStateSchema,
|
|
3744
3810
|
lastStopReason: stopReasonSchema,
|
|
3745
|
-
programCounter:
|
|
3811
|
+
programCounter: address16Schema.nullable(),
|
|
3746
3812
|
registers: c64PartialRegisterValueSchema.nullable()
|
|
3747
3813
|
}),
|
|
3748
3814
|
execute: async (input) => {
|
|
3749
|
-
const
|
|
3815
|
+
const address = input.start_address;
|
|
3816
|
+
let length;
|
|
3817
|
+
if (input.end_address !== void 0) {
|
|
3818
|
+
if (address > input.end_address) {
|
|
3819
|
+
throw new Error("End address must be greater than or equal to start address");
|
|
3820
|
+
}
|
|
3821
|
+
length = input.end_address - address + 1;
|
|
3822
|
+
} else {
|
|
3823
|
+
length = input.data_length;
|
|
3824
|
+
}
|
|
3825
|
+
const normalizedInput = {
|
|
3750
3826
|
kind: input.kind,
|
|
3751
|
-
address
|
|
3752
|
-
length
|
|
3827
|
+
address,
|
|
3828
|
+
length,
|
|
3753
3829
|
condition: input.condition,
|
|
3754
3830
|
label: input.label,
|
|
3755
3831
|
temporary: input.temporary,
|
|
3756
3832
|
enabled: input.enabled
|
|
3757
|
-
}
|
|
3833
|
+
};
|
|
3758
3834
|
const result = await c64Session.breakpointSet(normalizedInput);
|
|
3759
3835
|
return {
|
|
3760
3836
|
breakpoint: normalizeBreakpoint(result.breakpoint),
|