@henols/c64-re-tools 1.1.0 → 2.0.0-rc.11

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 (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -37
  3. package/distribution/package.ts +21 -0
  4. package/distribution/plugin.ts +122 -0
  5. package/package.json +34 -40
  6. package/skills/c64-assembler/SKILL.md +76 -0
  7. package/skills/c64-assembler/scripts/assemble.ts +110 -0
  8. package/skills/c64-assembler/scripts/compare.ts +84 -0
  9. package/skills/c64-basic/SKILL.md +66 -0
  10. package/skills/c64-basic/scripts/basic.ts +46 -0
  11. package/skills/c64-disk/SKILL.md +93 -0
  12. package/skills/c64-disk/scripts/containers.ts +124 -0
  13. package/skills/c64-disk/scripts/disk.ts +120 -0
  14. package/skills/c64-emulator/SKILL.md +134 -0
  15. package/skills/c64-knowledge/SKILL.md +192 -0
  16. package/skills/c64-knowledge/scripts/knowledge.ts +613 -0
  17. package/skills/c64-memory-map/SKILL.md +79 -0
  18. package/skills/c64-memory-map/scripts/memmap.ts +92 -0
  19. package/skills/c64-provenance/SKILL.md +110 -0
  20. package/skills/c64-provenance/scripts/compare.ts +152 -0
  21. package/skills/c64-provenance/scripts/provenance.ts +334 -0
  22. package/skills/c64-provenance/scripts/runtime.ts +191 -0
  23. package/skills/c64-provenance/scripts/separate.ts +140 -0
  24. package/skills/c64-reverse-engineering/SKILL.md +144 -0
  25. package/skills/c64-source/SKILL.md +133 -0
  26. package/skills/c64-source/scripts/generate.ts +503 -0
  27. package/skills/c64-source/scripts/loader.ts +589 -0
  28. package/skills/c64-source/scripts/opcodes.ts +61 -0
  29. package/skills/c64-source/scripts/source.ts +673 -0
  30. package/skills/c64-static-analysis/SKILL.md +120 -0
  31. package/skills/c64-static-analysis/scripts/analyze.ts +293 -0
  32. package/skills/c64-static-analysis/scripts/coverage.ts +78 -0
  33. package/skills/c64-static-analysis/scripts/findings.ts +75 -0
  34. package/skills/c64-static-analysis/scripts/idioms.ts +149 -0
  35. package/skills/c64-static-analysis/scripts/instructions.ts +105 -0
  36. package/skills/c64-static-analysis/scripts/pointers.ts +108 -0
  37. package/skills/c64-testing/SKILL.md +103 -0
  38. package/skills/c64-testing/references/scenario-format.md +116 -0
  39. package/skills/c64-testing/scripts/checklist.ts +51 -0
  40. package/skills/c64-testing/scripts/run.ts +189 -0
  41. package/skills/c64-testing/scripts/scenario.ts +493 -0
  42. package/skills/c64-testing/scripts/test.ts +65 -0
  43. package/skills/c64-unpacker/SKILL.md +135 -0
  44. package/skills/c64-unpacker/scripts/evidence.ts +207 -0
  45. package/skills/c64-unpacker/scripts/loads.ts +209 -0
  46. package/skills/c64-unpacker/scripts/machine.ts +80 -0
  47. package/skills/c64-unpacker/scripts/stages.ts +130 -0
  48. package/skills/c64-unpacker/scripts/unpack.ts +683 -0
  49. package/src/c64.ts +411 -0
  50. package/src/cli/ap-sdk.ts +44 -0
  51. package/src/cli/cleanup.ts +194 -0
  52. package/src/cli/main.ts +125 -0
  53. package/src/cli/status.ts +61 -0
  54. package/src/host/main.ts +134 -0
  55. package/src/host/server.ts +392 -0
  56. package/src/host/tools/c1541.ts +284 -0
  57. package/src/host/tools/index.ts +35 -0
  58. package/src/host/tools/petcat.ts +77 -0
  59. package/src/host/tools/status.ts +47 -0
  60. package/src/host/tools/version.ts +41 -0
  61. package/src/host/vice/adapter.ts +804 -0
  62. package/src/host/vice/binary-monitor.ts +389 -0
  63. package/src/host/vice/chips.ts +118 -0
  64. package/src/host/vice/connect.ts +34 -0
  65. package/src/host/vice/process.ts +413 -0
  66. package/src/host/vice/screen.ts +184 -0
  67. package/src/host/vice/session.ts +1426 -0
  68. package/src/host/vice/text-monitor.ts +223 -0
  69. package/src/host-client/autostart.ts +55 -0
  70. package/src/host-client/connect.ts +241 -0
  71. package/src/host-client/coverage.ts +63 -0
  72. package/src/host-client/image.ts +63 -0
  73. package/src/host-client/steps.ts +170 -0
  74. package/src/host-client/tools.ts +89 -0
  75. package/src/host-client/transfer.ts +126 -0
  76. package/src/host-client/vice-session.ts +316 -0
  77. package/src/knowledge/database.ts +132 -0
  78. package/src/knowledge/expression.ts +209 -0
  79. package/src/knowledge/history.ts +169 -0
  80. package/src/knowledge/import.ts +392 -0
  81. package/src/knowledge/read.ts +392 -0
  82. package/src/knowledge/schema.ts +250 -0
  83. package/src/knowledge/write.ts +837 -0
  84. package/src/mcp/main.ts +134 -0
  85. package/src/mcp/output.ts +32 -0
  86. package/src/mcp/server.ts +316 -0
  87. package/src/mcp/tools/debug.ts +327 -0
  88. package/src/mcp/tools/execution.ts +117 -0
  89. package/src/mcp/tools/input.ts +72 -0
  90. package/src/mcp/tools/machine.ts +100 -0
  91. package/src/mcp/tools/media.ts +129 -0
  92. package/src/mcp/tools/memory.ts +250 -0
  93. package/src/mcp/tools/video.ts +271 -0
  94. package/src/native/acme.ts +116 -0
  95. package/src/native/discover.ts +179 -0
  96. package/src/native/dxa.ts +166 -0
  97. package/src/native/ghidra/analyze.ts +86 -0
  98. package/src/native/ghidra/index.ts +173 -0
  99. package/src/native/ghidra/language/c64rt_6510.cspec +34 -0
  100. package/src/native/ghidra/language/c64rt_6510.ldefs +15 -0
  101. package/src/native/ghidra/language/c64rt_6510.pspec +15 -0
  102. package/src/native/ghidra/language/c64rt_6510.slaspec +596 -0
  103. package/src/native/ghidra/scripts/C64Export.java +274 -0
  104. package/src/native/ghidra/scripts/C64Prepare.java +60 -0
  105. package/src/native/local.ts +34 -0
  106. package/src/native/processes.ts +350 -0
  107. package/src/native/run.ts +172 -0
  108. package/src/native/staging.ts +83 -0
  109. package/src/native/status.ts +113 -0
  110. package/src/native/types.ts +257 -0
  111. package/src/native/watchdog.ts +78 -0
  112. package/src/package.ts +21 -0
  113. package/src/platform.ts +441 -0
  114. package/src/project.ts +39 -0
  115. package/src/protocol/framing.ts +132 -0
  116. package/src/protocol/messages.ts +259 -0
  117. package/src/protocol/tools.ts +266 -0
  118. package/src/protocol/vice.ts +1348 -0
  119. package/src/script.ts +60 -0
  120. package/src/time.ts +15 -0
  121. package/src/trace.ts +194 -0
  122. package/THIRD-PARTY-NOTICES.md +0 -26
  123. package/bin/cli.mjs +0 -283
  124. package/skills/acme-build/SKILL.md +0 -260
  125. package/skills/acme-build/scripts/acme.mjs +0 -341
  126. package/skills/acme-build/template.a +0 -53
  127. package/skills/c64-disk-access/SKILL.md +0 -159
  128. package/skills/c64-disk-access/scripts/c1541.mjs +0 -569
  129. package/skills/c64-memory-mapping/SKILL.md +0 -631
  130. package/skills/c64-memory-mapping/memmap.json +0 -8800
  131. package/skills/c64-memory-mapping/scripts/driver.mjs +0 -553
  132. package/skills/c64-petcat/SKILL.md +0 -87
  133. package/skills/c64-petcat/scripts/petcat.mjs +0 -221
  134. package/skills/c64-program-recon/SKILL.md +0 -706
  135. package/skills/c64-program-recon/references/control-flow.md +0 -180
  136. package/skills/c64-program-recon/references/graphics.md +0 -79
  137. package/skills/c64-program-recon/references/observation-hazards.md +0 -143
  138. package/skills/c64-program-recon/references/reconstruction.md +0 -133
  139. package/skills/c64-program-recon/references/sound-and-input.md +0 -74
  140. package/skills/c64-program-recon/references/tool-selection.md +0 -78
  141. package/skills/c64-program-recon/scripts/derive.mjs +0 -364
  142. package/skills/c64-program-recon/scripts/packer-finding.mjs +0 -709
  143. package/skills/c64-program-recon/templates/memory-map.template.md +0 -101
  144. package/skills/c64-provenance-diff/SKILL.md +0 -292
  145. package/skills/c64-provenance-diff/scripts/diff-images.mjs +0 -984
  146. package/skills/c64-provenance-diff/scripts/recovery-schema.mjs +0 -395
  147. package/skills/c64-ram-capture/RELEASES.json.example +0 -17
  148. package/skills/c64-ram-capture/SKILL.md +0 -474
  149. package/skills/c64-ram-capture/scripts/compare-cross-binary.mjs +0 -525
  150. package/skills/c64-ram-capture/scripts/compare.mjs +0 -258
  151. package/skills/c64-ram-capture/scripts/derive-transients.mjs +0 -575
  152. package/skills/c64-ram-capture/scripts/dump-artifacts.mjs +0 -317
  153. package/skills/c64-ram-capture/scripts/mcp-module.mjs +0 -174
  154. package/skills/c64-ram-capture/scripts/project-paths.mjs +0 -81
  155. package/skills/c64-ram-capture/scripts/releases.mjs +0 -109
  156. package/skills/c64-ram-capture/scripts/vsf-slice.mjs +0 -147
  157. package/skills/c64-ram-capture/scripts/watch-loads.mjs +0 -581
  158. package/skills/c64-ram-capture/templates/capture-record.template.md +0 -99
  159. package/skills/c64-ram-capture/transients/README.md +0 -137
  160. package/skills/routine-queue-walker/SKILL.md +0 -394
  161. package/skills/routine-queue-walker/scripts/completeness-report.mjs +0 -465
  162. package/skills/vice-wedge-triage/SKILL.md +0 -269
@@ -0,0 +1,35 @@
1
+ // The typed tool dispatcher of the Host Runtime. The host runs only
2
+ // VICE and the tools that come with it (c1541, petcat); skill scripts run
3
+ // ACME, DXA and Ghidra themselves. One entry per operation, never a
4
+ // generic executable route.
5
+
6
+ import type { ViceVersion } from "../../native/discover.ts";
7
+ import type { ProcessSupervisor } from "../../native/processes.ts";
8
+ import type { ToolContext } from "../../native/run.ts";
9
+ import type { ToolOperation, ToolOperations } from "../../protocol/tools.ts";
10
+ import type { ToolDispatcher } from "../server.ts";
11
+ import { inspect } from "./c1541.ts";
12
+ import { decode } from "./petcat.ts";
13
+ import { hostStatus } from "./status.ts";
14
+
15
+ /** Runs one operation with its validated parameters and attachments. */
16
+ type Adapter<O extends ToolOperation> = (
17
+ params: ToolOperations[O]["params"],
18
+ attachments: Buffer[],
19
+ context: ToolContext,
20
+ ) => Promise<{ result: ToolOperations[O]["result"]; attachments?: Buffer[] }>;
21
+
22
+ const ADAPTERS: { [O in ToolOperation]: Adapter<O> } = {
23
+ "host.status": (_params, _attachments, context) => hostStatus(context),
24
+ "c1541.inspect": (params, attachments, context) => inspect(params, attachments[0]!, context),
25
+ "petcat.decode": (_params, attachments, context) => decode(attachments[0]!, context),
26
+ };
27
+
28
+ /** `vice`: the version that the host read from the emulator at start, for host.status. */
29
+ export function createToolDispatcher(options: { supervisor: ProcessSupervisor; env?: NodeJS.ProcessEnv; log?: (line: string) => void; vice?: ViceVersion }): ToolDispatcher {
30
+ return (op, params, attachments, signal) => {
31
+ const context = { supervisor: options.supervisor, signal, env: options.env, log: options.log };
32
+ if (op === "host.status") return hostStatus(context, options.vice) as ReturnType<ToolDispatcher>;
33
+ return ADAPTERS[op](params, attachments, context);
34
+ };
35
+ }
@@ -0,0 +1,77 @@
1
+ // The petcat adapter. petcat makes the C64 BASIC V2 listing; the
2
+ // adapter parses the tokenized program itself to check that listing and to
3
+ // find the machine-code handoffs, because petcat's exit status proves nothing
4
+ // (it prints any bytes as text).
5
+
6
+ import { existsSync, readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ import { findHandoffs, parseTokenized } from "../../c64.ts";
10
+ import { WireFailure } from "../../protocol/messages.ts";
11
+ import { type PetcatResult } from "../../protocol/tools.ts";
12
+ import { Workspace } from "../../native/staging.ts";
13
+ import { findTool, PETCAT } from "../../native/discover.ts";
14
+ import { requireMinimumVersion } from "./version.ts";
15
+ import { runToolOrFail, type ToolContext } from "../../native/run.ts";
16
+
17
+ const TIMEOUT_MS = 30_000;
18
+ const LISTING = "listing.txt";
19
+ /**
20
+ * petcat's listing lines (" 10 sys2061"), as number and text. petcat
21
+ * prints π ($ff) as `~`, which is no PETSCII character: the text has π (F-13).
22
+ */
23
+ export function parseListing(listing: string): Array<{ number: number; text: string }> {
24
+ const lines: Array<{ number: number; text: string }> = [];
25
+ for (const line of listing.split(/\r?\n/)) {
26
+ if (line.trim() === "") continue;
27
+ const match = /^\s*(\d+) ?(.*)$/.exec(line);
28
+ if (match === null) throw new WireFailure("operation-failed", "petcat printed a listing line without a line number.");
29
+ lines.push({ number: Number(match[1]), text: match[2]!.replaceAll("~", "π") });
30
+ }
31
+ return lines;
32
+ }
33
+
34
+ export async function decode(
35
+ program: Buffer,
36
+ context: ToolContext,
37
+ ): Promise<{ result: PetcatResult }> {
38
+ const tokenized = parseTokenized(program);
39
+ if ("reason" in tokenized) return { result: { decoded: false, reason: tokenized.reason } };
40
+ const executable = findTool(PETCAT, context.env);
41
+ await requireMinimumVersion(PETCAT, executable, context);
42
+ // petcat gets the BASIC text only, closed with a real end marker: after a
43
+ // link that only ends BASIC (machine code right after the last line), petcat
44
+ // prints a comment line where a listing line belongs.
45
+ const text = Buffer.concat([program.subarray(0, tokenized.textBytes), Buffer.of(0, 0)]);
46
+ const workspace = Workspace.create(context.supervisor);
47
+ try {
48
+ workspace.materialize("input", [{ path: "program.prg", size: text.length }], [text]);
49
+ const listingPath = join(workspace.directory("out"), LISTING);
50
+ const run = await runToolOrFail(
51
+ "petcat",
52
+ "The BASIC decode",
53
+ // -2: C64 BASIC V2 keywords. -nh: no header. The input is never read as an option.
54
+ { argv: [executable, "-2", "-nh", "-o", listingPath, "--", "input/program.prg"], cwd: workspace.root, timeoutMs: TIMEOUT_MS },
55
+ context,
56
+ );
57
+ if (run.code !== 0 || !existsSync(listingPath)) {
58
+ context.log?.(`petcat exited ${run.code}:\n${run.stdout}\n${run.stderr}`);
59
+ throw new WireFailure("operation-failed", "petcat could not decode the program.");
60
+ }
61
+ const lines = parseListing(readFileSync(listingPath, "latin1"));
62
+ const agrees = lines.length === tokenized.lines.length && lines.every((line, index) => line.number === tokenized.lines[index]!.number);
63
+ if (!agrees) throw new WireFailure("operation-failed", "petcat's listing does not match the lines of the program.");
64
+ return {
65
+ result: {
66
+ decoded: true,
67
+ loadAddress: tokenized.loadAddress,
68
+ basicEnd: tokenized.basicEnd,
69
+ listing: lines.map((line) => `${line.number} ${line.text}`).join("\n"),
70
+ lines,
71
+ handoffs: findHandoffs(tokenized.lines),
72
+ },
73
+ };
74
+ } finally {
75
+ workspace.remove();
76
+ }
77
+ }
@@ -0,0 +1,47 @@
1
+ // host.status: VICE and the tools that come with it, each found the way its
2
+ // operations find it and run once with a version option. A tool from a
3
+ // VICE older than MIN_VICE is reported as not working, as its operations refuse it.
4
+ // VICE itself is reported with the version that the host read from the
5
+ // running emulator at start: the Homebrew x64sc of VICE 3.10 on macOS stops
6
+ // on -version ("argv[0] is NULL") although the emulator runs.
7
+
8
+ import { arch, platform, release } from "node:os";
9
+
10
+ import { PACKAGE } from "../../package.ts";
11
+ import type { HostInfo, ToolStatus } from "../../protocol/tools.ts";
12
+ import { C1541, findTool, isOlderThanMinimum, MIN_VICE, PETCAT, VICE, viceFlaws, viceVersionOf, type ToolSpec, type ViceVersion } from "../../native/discover.ts";
13
+ import type { ToolContext } from "../../native/run.ts";
14
+ import { probeTools } from "../../native/status.ts";
15
+ import { findVice } from "../vice/process.ts";
16
+
17
+ function requireMinimum(status: ToolStatus, tool: ToolSpec): ToolStatus {
18
+ if (!status.runs) return status;
19
+ const version = viceVersionOf(status.version ?? "");
20
+ if (version !== undefined && !isOlderThanMinimum(version)) return status;
21
+ const found = version === undefined ? "It does not tell its VICE version" : `It comes from VICE ${version.major}.${version.minor}`;
22
+ return { ...status, runs: false, problem: `${found}, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}` };
23
+ }
24
+
25
+ /** The version text of a VICE version, as x64sc -version prints it. */
26
+ const versionText = (version: ViceVersion) => `x64sc (VICE ${version.major}.${version.minor}${version.revision === undefined ? "" : ` SVN r${version.revision}`})`;
27
+
28
+ /** `started`: the version that the host read from the emulator at start; without it, VICE is probed with -version too. */
29
+ export async function hostStatus(context: ToolContext, started?: ViceVersion): Promise<{ result: { host: HostInfo; tools: ToolStatus[] } }> {
30
+ const specs = [VICE, C1541, PETCAT];
31
+ const probed = await probeTools(
32
+ [
33
+ ...(started === undefined ? [{ name: VICE.name, find: findVice, args: ["-version"], pattern: /^x64sc \(VICE \d/ }] : []),
34
+ { name: C1541.name, find: (env) => findTool(C1541, env), args: ["-version"], pattern: /^c1541 \(VICE \d/ },
35
+ { name: PETCAT.name, find: (env) => findTool(PETCAT, env), args: ["-version"], pattern: /^petcat \(VICE \d/ },
36
+ ],
37
+ context,
38
+ );
39
+ const tools = started === undefined ? probed : [{ name: VICE.name, found: true, path: findVice(context.env ?? process.env), version: versionText(started), runs: true }, ...probed];
40
+ const checked = tools.map((status, index) => requireMinimum(status, specs[index]!));
41
+ // VICE runs with its known flaws; status names them (D56).
42
+ const vice = checked[0]!;
43
+ const version = vice.runs ? viceVersionOf(vice.version ?? "") : undefined;
44
+ const flaws = version === undefined ? [] : viceFlaws(version);
45
+ if (flaws.length > 0) checked[0] = { ...vice, flaws };
46
+ return { result: { host: { version: PACKAGE.version, platform: platform(), release: release(), arch: arch() }, tools: checked } };
47
+ }
@@ -0,0 +1,41 @@
1
+ // The VICE tools on the host must come from a VICE that c64-re-tools works
2
+ // with. Each executable is asked once for its version; a version that
3
+ // cannot be read is refused, as is one that is too old.
4
+
5
+ import { tmpdir } from "node:os";
6
+
7
+ import { WireFailure } from "../../protocol/messages.ts";
8
+ import { isOlderThanMinimum, MIN_VICE, viceVersionOf, type ToolSpec } from "../../native/discover.ts";
9
+ import { runToolOrFail, type ToolContext } from "../../native/run.ts";
10
+
11
+ const VERSION_TIMEOUT_MS = 30_000;
12
+ const checked = new Map<string, Promise<void>>();
13
+
14
+ /** Refuses a tool from a VICE older than MIN_VICE, or one whose VICE version cannot be read, by name and with the remedy. */
15
+ export function requireMinimumVersion(tool: ToolSpec, executable: string, context: ToolContext): Promise<void> {
16
+ let check = checked.get(executable);
17
+ if (check === undefined) {
18
+ // Every caller waits for the same check, so no caller's cancel may stop it; its own time limit bounds it.
19
+ const shared: ToolContext = { ...context, signal: new AbortController().signal };
20
+ check = (async () => {
21
+ const run = await runToolOrFail(tool.name, `The ${tool.name} version check`, { argv: [executable, "-version"], cwd: tmpdir(), timeoutMs: VERSION_TIMEOUT_MS }, shared);
22
+ const version = viceVersionOf(`${run.stdout}\n${run.stderr}`);
23
+ if (version === undefined) {
24
+ throw new WireFailure(
25
+ "installation-incomplete",
26
+ `${tool.name} does not tell its VICE version, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}`,
27
+ );
28
+ }
29
+ if (isOlderThanMinimum(version)) {
30
+ throw new WireFailure(
31
+ "installation-incomplete",
32
+ `${tool.name} comes from VICE ${version.major}.${version.minor}, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}`,
33
+ );
34
+ }
35
+ })();
36
+ // A refusal or a failed check is asked again next time: the user can install a newer VICE meanwhile.
37
+ check.catch(() => checked.delete(executable));
38
+ checked.set(executable, check);
39
+ }
40
+ return check;
41
+ }