@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
@@ -1,258 +0,0 @@
1
- #!/usr/bin/env node
2
- // Compare 65536-byte C64 RAM captures and classify every difference.
3
- //
4
- // Pure logic. This module reads files the agent already captured and does
5
- // arithmetic over them. It contacts nothing: the mcp__plugin_c64-re-tools_vice__* tools are the
6
- // only route to the emulator (.claude/CLAUDE.md § Emulator Access), and
7
- // nothing here opens a connection, reads broker state, or shells out.
8
- //
9
- // The classification rules are the ones c64-ram-capture/SKILL.md states, and
10
- // they live here so they are applied identically every time instead of being
11
- // re-derived by hand per session:
12
- //
13
- // volatile $0000-$0001, $0100-$01FF, $0200-$03FF, $D000-$DFFF -- counted,
14
- // reported, excluded from the verdict
15
- // drift exactly one bit differs -- listed as a candidate, does not fail
16
- // divergence two or more bits differ -- listed, and fails the comparison
17
- //
18
- // $D000-$DFFF is this module's one departure from what SKILL.md said when it was
19
- // written: that range is I/O, not RAM, so it can never be stable. See the VOLATILE
20
- // table below for the evidence (observed 2026-08-04).
21
-
22
- import { readFileSync } from "node:fs";
23
- import { createHash } from "node:crypto";
24
- import { basename } from "node:path";
25
-
26
- const IMAGE_BYTES = 65536;
27
-
28
- // Volatile spans, inclusive. A difference inside these is expected on any two
29
- // captures of the same checkpoint and never fails a comparison.
30
- const VOLATILE = [
31
- [0x0000, 0x0001], // CPU port
32
- [0x0100, 0x01ff], // stack page
33
- [0x0200, 0x03ff], // KERNAL work area / BASIC input buffer
34
- // $D000-$DFFF is I/O, not RAM: the VIC's registers repeat every $40 across
35
- // $D000-$D3FF and the SID's across $D400-$D7FF, so reading this range samples
36
- // live hardware and two captures can never agree here. Added 2026-08-04 after
37
- // every divergence across all six committed gameentry pairings landed either
38
- // here ($D344, $D625, $D628) or in RAM under KERNAL ROM -- see
39
- // Observed 2026-08-04. Confidence HIGH: structural.
40
- [0xd000, 0xdfff],
41
- ];
42
-
43
- // Deliberately NOT volatile: $E000-$FFFF (RAM under KERNAL ROM when HIRAM=0).
44
- // $FAD8 and $FC51 do differ across captures, but only 2 addresses out of 8192 --
45
- // far too few for power-on garbage, and unexplained. Blanket-excluding 8 KB on
46
- // two data points would hide real divergence, so these still fail and the
47
- // capture record carries the explanation. Confidence MEDIUM, see the same entry.
48
-
49
- const isVolatile = (a) => VOLATILE.some(([lo, hi]) => a >= lo && a <= hi);
50
-
51
- const hex4 = (n) => "$" + n.toString(16).toUpperCase().padStart(4, "0");
52
- const hex2 = (n) => "$" + n.toString(16).toUpperCase().padStart(2, "0");
53
- const bin8 = (n) => "%" + n.toString(2).padStart(8, "0");
54
-
55
- const popcount = (n) => {
56
- let c = 0;
57
- while (n) {
58
- n &= n - 1;
59
- c++;
60
- }
61
- return c;
62
- };
63
-
64
- function loadImage(path) {
65
- const buf = readFileSync(path);
66
- if (buf.length !== IMAGE_BYTES) {
67
- throw new Error(
68
- `${path}: ${buf.length} bytes, expected ${IMAGE_BYTES} — not a full 64K image`,
69
- );
70
- }
71
- return buf;
72
- }
73
-
74
- const sha256 = (buf) => createHash("sha256").update(buf).digest("hex");
75
-
76
- /**
77
- * Classify every differing address between two images.
78
- * Returns { volatile[], drift[], divergence[], pass } — the three lists
79
- * SKILL.md requires, plus the verdict.
80
- */
81
- function compare(a, b) {
82
- const volatile_ = [];
83
- const drift = [];
84
- const divergence = [];
85
-
86
- for (let addr = 0; addr < IMAGE_BYTES; addr++) {
87
- const x = a[addr];
88
- const y = b[addr];
89
- if (x === y) continue;
90
-
91
- const bits = popcount(x ^ y);
92
- const rec = { addr, a: x, b: y, bits };
93
-
94
- // Volatile wins over bit-count: an address in a volatile span is excluded
95
- // from the verdict regardless of how many bits moved.
96
- if (isVolatile(addr)) volatile_.push(rec);
97
- else if (bits === 1) drift.push(rec);
98
- else divergence.push(rec);
99
- }
100
-
101
- return { volatile: volatile_, drift, divergence, pass: divergence.length === 0 };
102
- }
103
-
104
- const fmtRow = (r) =>
105
- ` ${hex4(r.addr)} ${hex2(r.a)} ${bin8(r.a)} -> ${hex2(r.b)} ${bin8(r.b)} ${r.bits} bit${r.bits === 1 ? "" : "s"}`;
106
-
107
- function printList(title, rows, limit) {
108
- console.log(`\n${title}: ${rows.length}`);
109
- if (!rows.length) return;
110
- // --limit 0 means unlimited, matching the usage text. Anything else caps.
111
- const shown = limit ? rows.slice(0, limit) : rows;
112
- for (const r of shown) console.log(fmtRow(r));
113
- if (shown.length < rows.length) {
114
- console.log(` … ${rows.length - shown.length} more (--limit 0 for all)`);
115
- }
116
- }
117
-
118
- function cmdCompare(argv) {
119
- const limit = limitFrom(argv);
120
- const paths = argv.filter((s) => !s.startsWith("--") && !/^\d+$/.test(s));
121
- if (paths.length !== 2) throw new Error("compare needs exactly two image paths");
122
-
123
- const [pa, pb] = paths;
124
- const a = loadImage(pa);
125
- const b = loadImage(pb);
126
-
127
- const ha = sha256(a);
128
- const hb = sha256(b);
129
-
130
- console.log(`A ${basename(pa)} sha256 ${ha}`);
131
- console.log(`B ${basename(pb)} sha256 ${hb}`);
132
-
133
- if (ha === hb) {
134
- console.log("\nIDENTICAL — the two images are byte-for-byte equal.");
135
- console.log("\nVERDICT: PASS");
136
- return 0;
137
- }
138
-
139
- const r = compare(a, b);
140
-
141
- printList("volatile (excluded from the verdict)", r.volatile, limit);
142
- printList("drift — exactly one bit, reported as candidates", r.drift, limit);
143
- printList("DIVERGENCE — two or more bits, fails the comparison", r.divergence, limit);
144
-
145
- const total = r.volatile.length + r.drift.length + r.divergence.length;
146
- console.log(`\ntotal differing addresses: ${total} of ${IMAGE_BYTES}`);
147
- console.log(`\nVERDICT: ${r.pass ? "PASS" : "FAIL"}`);
148
- if (r.pass && r.drift.length) {
149
- console.log("Drift candidates present — pass, but record them with the capture.");
150
- }
151
- return r.pass ? 0 : 1;
152
- }
153
-
154
- /**
155
- * Drift floor across N captures of the same checkpoint: every address that
156
- * differed in ANY pairing. Reported as a floor, never as a complete set —
157
- * more captures can only widen it.
158
- */
159
- function cmdFloor(argv) {
160
- const limit = limitFrom(argv);
161
- const paths = argv.filter((s) => !s.startsWith("--") && !/^\d+$/.test(s));
162
- if (paths.length < 2) throw new Error("floor needs at least two image paths");
163
-
164
- const imgs = paths.map((p) => ({ path: p, buf: loadImage(p) }));
165
- for (const i of imgs) console.log(`${basename(i.path)} sha256 ${sha256(i.buf)}`);
166
-
167
- const floor = new Map(); // addr -> Set of distinct values seen
168
- let worstPair = null;
169
-
170
- for (let i = 0; i < imgs.length; i++) {
171
- for (let j = i + 1; j < imgs.length; j++) {
172
- const r = compare(imgs[i].buf, imgs[j].buf);
173
- for (const rec of [...r.volatile, ...r.drift, ...r.divergence]) {
174
- if (!floor.has(rec.addr)) floor.set(rec.addr, new Set());
175
- floor.get(rec.addr).add(rec.a);
176
- floor.get(rec.addr).add(rec.b);
177
- }
178
- const label = `${basename(imgs[i].path)} vs ${basename(imgs[j].path)}`;
179
- console.log(
180
- `\n${label}: ${r.volatile.length} volatile, ${r.drift.length} drift, ${r.divergence.length} divergence -> ${r.pass ? "PASS" : "FAIL"}`,
181
- );
182
- if (!r.pass && (!worstPair || r.divergence.length > worstPair.n)) {
183
- worstPair = { label, n: r.divergence.length };
184
- }
185
- }
186
- }
187
-
188
- const addrs = [...floor.keys()].sort((x, y) => x - y);
189
- const vol = addrs.filter(isVolatile).length;
190
-
191
- console.log(`\nDRIFT FLOOR: ${addrs.length} addresses (${vol} inside volatile spans)`);
192
- const shown = limit === 0 ? addrs : addrs.slice(0, limit || 40);
193
- for (const a of shown) {
194
- const vals = [...floor.get(a)].sort((p, q) => p - q).map(hex2).join(" / ");
195
- console.log(` ${hex4(a)}${isVolatile(a) ? " [volatile]" : " "} ${vals}`);
196
- }
197
- if (shown.length < addrs.length) {
198
- console.log(` … ${addrs.length - shown.length} more (--limit 0 for all)`);
199
- }
200
-
201
- console.log(
202
- "\nThis is a FLOOR, not a complete set — more captures of the same checkpoint can only widen it.",
203
- );
204
- if (worstPair) {
205
- const n = worstPair.n;
206
- console.log(`Worst pairing: ${worstPair.label} (${n} divergence${n === 1 ? "" : "s"}).`);
207
- }
208
- return 0;
209
- }
210
-
211
- /** SHA-256 and size of each image, for recording alongside a capture. */
212
- function cmdDigest(argv) {
213
- const paths = argv.filter((s) => !s.startsWith("--"));
214
- if (!paths.length) throw new Error("digest needs at least one image path");
215
- for (const p of paths) {
216
- const buf = readFileSync(p);
217
- const ok = buf.length === IMAGE_BYTES;
218
- console.log(
219
- `${sha256(buf)} ${buf.length} bytes${ok ? "" : " *** NOT 65536 — not a full image ***"} ${basename(p)}`,
220
- );
221
- }
222
- return 0;
223
- }
224
-
225
- function limitFrom(argv) {
226
- const i = argv.indexOf("--limit");
227
- if (i < 0) return undefined;
228
- const n = Number(argv[i + 1]);
229
- if (!Number.isInteger(n) || n < 0) throw new Error("--limit needs a non-negative integer");
230
- return n;
231
- }
232
-
233
- const commands = { compare: cmdCompare, floor: cmdFloor, digest: cmdDigest };
234
-
235
- const [cmd, ...rest] = process.argv.slice(2);
236
- if (!cmd || !commands[cmd]) {
237
- console.error(`usage: node compare.mjs <command>
238
-
239
- compare <a.bin> <b.bin> [--limit N] classify every difference, print a verdict
240
- floor <a.bin> <b.bin> [...] [--limit N] drift floor across N captures of one checkpoint
241
- digest <image.bin>... sha256 + size, for the capture record
242
-
243
- Volatile (counted, excluded from the verdict): $0000-$0001, $0100-$01FF, $0200-$03FF, $D000-$DFFF.
244
- $D000-$DFFF is I/O, not RAM — reading it samples live hardware, so it can never be stable.
245
- One differing bit is drift and passes; two or more is divergence and fails.
246
- --limit 0 prints every row. Exit status is 1 on a FAIL verdict.
247
-
248
- Images come from the capture procedure in this skill's SKILL.md, via mcp__plugin_c64-re-tools_vice__*.
249
- This script contacts nothing.`);
250
- process.exit(cmd ? 1 : 0);
251
- }
252
-
253
- try {
254
- process.exit(commands[cmd](rest));
255
- } catch (e) {
256
- console.error(`error: ${e.message}`);
257
- process.exit(1);
258
- }