@henols/c64-re-tools 1.0.0 → 2.0.0-rc.10

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 (159) 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 +166 -0
  16. package/skills/c64-knowledge/scripts/knowledge.ts +492 -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 +126 -0
  26. package/skills/c64-source/scripts/generate.ts +490 -0
  27. package/skills/c64-source/scripts/loader.ts +571 -0
  28. package/skills/c64-source/scripts/opcodes.ts +61 -0
  29. package/skills/c64-source/scripts/source.ts +595 -0
  30. package/skills/c64-static-analysis/SKILL.md +119 -0
  31. package/skills/c64-static-analysis/scripts/analyze.ts +275 -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-testing/SKILL.md +103 -0
  37. package/skills/c64-testing/references/scenario-format.md +116 -0
  38. package/skills/c64-testing/scripts/checklist.ts +51 -0
  39. package/skills/c64-testing/scripts/run.ts +189 -0
  40. package/skills/c64-testing/scripts/scenario.ts +493 -0
  41. package/skills/c64-testing/scripts/test.ts +65 -0
  42. package/skills/c64-unpacker/SKILL.md +135 -0
  43. package/skills/c64-unpacker/scripts/evidence.ts +207 -0
  44. package/skills/c64-unpacker/scripts/loads.ts +209 -0
  45. package/skills/c64-unpacker/scripts/machine.ts +80 -0
  46. package/skills/c64-unpacker/scripts/stages.ts +130 -0
  47. package/skills/c64-unpacker/scripts/unpack.ts +683 -0
  48. package/src/c64.ts +411 -0
  49. package/src/cli/ap-sdk.ts +44 -0
  50. package/src/cli/cleanup.ts +194 -0
  51. package/src/cli/main.ts +125 -0
  52. package/src/cli/status.ts +61 -0
  53. package/src/host/main.ts +134 -0
  54. package/src/host/server.ts +392 -0
  55. package/src/host/tools/c1541.ts +284 -0
  56. package/src/host/tools/index.ts +35 -0
  57. package/src/host/tools/petcat.ts +77 -0
  58. package/src/host/tools/status.ts +47 -0
  59. package/src/host/tools/version.ts +41 -0
  60. package/src/host/vice/adapter.ts +804 -0
  61. package/src/host/vice/binary-monitor.ts +389 -0
  62. package/src/host/vice/chips.ts +118 -0
  63. package/src/host/vice/connect.ts +34 -0
  64. package/src/host/vice/process.ts +413 -0
  65. package/src/host/vice/screen.ts +184 -0
  66. package/src/host/vice/session.ts +1426 -0
  67. package/src/host/vice/text-monitor.ts +223 -0
  68. package/src/host-client/autostart.ts +55 -0
  69. package/src/host-client/connect.ts +241 -0
  70. package/src/host-client/coverage.ts +63 -0
  71. package/src/host-client/steps.ts +170 -0
  72. package/src/host-client/tools.ts +89 -0
  73. package/src/host-client/transfer.ts +126 -0
  74. package/src/host-client/vice-session.ts +316 -0
  75. package/src/knowledge/database.ts +132 -0
  76. package/src/knowledge/history.ts +163 -0
  77. package/src/knowledge/import.ts +391 -0
  78. package/src/knowledge/read.ts +342 -0
  79. package/src/knowledge/schema.ts +229 -0
  80. package/src/knowledge/write.ts +663 -0
  81. package/src/mcp/main.ts +134 -0
  82. package/src/mcp/output.ts +32 -0
  83. package/src/mcp/server.ts +316 -0
  84. package/src/mcp/tools/debug.ts +327 -0
  85. package/src/mcp/tools/execution.ts +117 -0
  86. package/src/mcp/tools/input.ts +72 -0
  87. package/src/mcp/tools/machine.ts +100 -0
  88. package/src/mcp/tools/media.ts +129 -0
  89. package/src/mcp/tools/memory.ts +250 -0
  90. package/src/mcp/tools/video.ts +271 -0
  91. package/src/native/acme.ts +116 -0
  92. package/src/native/discover.ts +179 -0
  93. package/src/native/dxa.ts +166 -0
  94. package/src/native/ghidra/analyze.ts +86 -0
  95. package/src/native/ghidra/index.ts +173 -0
  96. package/src/native/ghidra/language/c64rt_6510.cspec +34 -0
  97. package/src/native/ghidra/language/c64rt_6510.ldefs +15 -0
  98. package/src/native/ghidra/language/c64rt_6510.pspec +15 -0
  99. package/src/native/ghidra/language/c64rt_6510.slaspec +596 -0
  100. package/src/native/ghidra/scripts/C64Export.java +274 -0
  101. package/src/native/ghidra/scripts/C64Prepare.java +60 -0
  102. package/src/native/local.ts +34 -0
  103. package/src/native/processes.ts +350 -0
  104. package/src/native/run.ts +172 -0
  105. package/src/native/staging.ts +83 -0
  106. package/src/native/status.ts +113 -0
  107. package/src/native/types.ts +257 -0
  108. package/src/native/watchdog.ts +78 -0
  109. package/src/package.ts +21 -0
  110. package/src/platform.ts +441 -0
  111. package/src/project.ts +39 -0
  112. package/src/protocol/framing.ts +132 -0
  113. package/src/protocol/messages.ts +259 -0
  114. package/src/protocol/tools.ts +266 -0
  115. package/src/protocol/vice.ts +1348 -0
  116. package/src/script.ts +60 -0
  117. package/src/time.ts +15 -0
  118. package/src/trace.ts +194 -0
  119. package/THIRD-PARTY-NOTICES.md +0 -26
  120. package/bin/cli.mjs +0 -283
  121. package/skills/acme-build/SKILL.md +0 -260
  122. package/skills/acme-build/scripts/acme.mjs +0 -341
  123. package/skills/acme-build/template.a +0 -53
  124. package/skills/c64-disk-access/SKILL.md +0 -159
  125. package/skills/c64-disk-access/scripts/c1541.mjs +0 -569
  126. package/skills/c64-memory-mapping/SKILL.md +0 -631
  127. package/skills/c64-memory-mapping/memmap.json +0 -8800
  128. package/skills/c64-memory-mapping/scripts/driver.mjs +0 -553
  129. package/skills/c64-petcat/SKILL.md +0 -87
  130. package/skills/c64-petcat/scripts/petcat.mjs +0 -221
  131. package/skills/c64-program-recon/SKILL.md +0 -706
  132. package/skills/c64-program-recon/references/control-flow.md +0 -180
  133. package/skills/c64-program-recon/references/graphics.md +0 -79
  134. package/skills/c64-program-recon/references/observation-hazards.md +0 -143
  135. package/skills/c64-program-recon/references/reconstruction.md +0 -133
  136. package/skills/c64-program-recon/references/sound-and-input.md +0 -74
  137. package/skills/c64-program-recon/references/tool-selection.md +0 -78
  138. package/skills/c64-program-recon/scripts/derive.mjs +0 -364
  139. package/skills/c64-program-recon/scripts/packer-finding.mjs +0 -709
  140. package/skills/c64-program-recon/templates/memory-map.template.md +0 -101
  141. package/skills/c64-provenance-diff/SKILL.md +0 -292
  142. package/skills/c64-provenance-diff/scripts/diff-images.mjs +0 -984
  143. package/skills/c64-provenance-diff/scripts/recovery-schema.mjs +0 -395
  144. package/skills/c64-ram-capture/RELEASES.json.example +0 -17
  145. package/skills/c64-ram-capture/SKILL.md +0 -474
  146. package/skills/c64-ram-capture/scripts/compare-cross-binary.mjs +0 -525
  147. package/skills/c64-ram-capture/scripts/compare.mjs +0 -258
  148. package/skills/c64-ram-capture/scripts/derive-transients.mjs +0 -575
  149. package/skills/c64-ram-capture/scripts/dump-artifacts.mjs +0 -317
  150. package/skills/c64-ram-capture/scripts/mcp-module.mjs +0 -174
  151. package/skills/c64-ram-capture/scripts/project-paths.mjs +0 -81
  152. package/skills/c64-ram-capture/scripts/releases.mjs +0 -109
  153. package/skills/c64-ram-capture/scripts/vsf-slice.mjs +0 -147
  154. package/skills/c64-ram-capture/scripts/watch-loads.mjs +0 -581
  155. package/skills/c64-ram-capture/templates/capture-record.template.md +0 -99
  156. package/skills/c64-ram-capture/transients/README.md +0 -137
  157. package/skills/routine-queue-walker/SKILL.md +0 -394
  158. package/skills/routine-queue-walker/scripts/completeness-report.mjs +0 -465
  159. package/skills/vice-wedge-triage/SKILL.md +0 -269
@@ -0,0 +1,130 @@
1
+ // The stage rule of the c64-unpacker script (D43, F-17). The memory map keeps
2
+ // no order: a written and executed byte can be code that ran first and was
3
+ // written over later, as a decruncher does to its own start code. So a stage
4
+ // starts only where the CPU executes an opcode byte that the current stage
5
+ // wrote before the CPU got there. Code that the stage executed before it wrote
6
+ // it is the stage's own code: it stops the run once, and then a write watch
7
+ // over it arms it again. Written code that the stage calls, and that returns
8
+ // to the stage, is the stage's own code too (D59): a packer hands off by JMP,
9
+ // RTS or RTI and never runs its own code again.
10
+
11
+ import { COVERAGE } from "#src/c64.ts";
12
+ import { writtenBlocks } from "#src/host-client/coverage.ts";
13
+
14
+ export interface Range {
15
+ start: number;
16
+ end: number;
17
+ }
18
+
19
+ const contains = (range: Range, address: number) => address >= range.start && address <= range.end;
20
+
21
+ /** The flags of two maps from $0000 in one. */
22
+ export function mergeMaps(into: Uint8Array, from: Uint8Array): void {
23
+ for (let address = 0; address < into.length; address++) into[address]! |= from[address]!;
24
+ }
25
+
26
+ /**
27
+ * The written blocks of at least `minimum` bytes in which a chunk executed
28
+ * code that can start a stage: every executed address except own code that
29
+ * the stage has not written.
30
+ */
31
+ export function stageCandidates(stage: Uint8Array, chunk: Uint8Array, own: ReadonlySet<number>, minimum: number, called: readonly Range[] = []): Range[] {
32
+ const combined = Uint8Array.from(stage);
33
+ mergeMaps(combined, chunk);
34
+ return writtenBlocks(combined, minimum).filter((block) => {
35
+ for (let address = block.start; address <= block.end; address++) {
36
+ if ((chunk[address]! & COVERAGE.ramExecute) === 0) continue;
37
+ if (inRanges(called, address)) continue;
38
+ if (own.has(address) && (combined[address]! & COVERAGE.ramWrite) === 0) continue;
39
+ return true;
40
+ }
41
+ return false;
42
+ });
43
+ }
44
+
45
+ /**
46
+ * The points of a run over the candidate blocks: exec breakpoints over all of
47
+ * them except own code that is not written yet, and write watches over that
48
+ * own code.
49
+ */
50
+ export function stagePoints(blocks: readonly Range[], own: ReadonlySet<number>, written: (address: number) => boolean, called: readonly Range[] = []): { exec: Range[]; watch: Range[] } {
51
+ const exec: Range[] = [];
52
+ const watch: Range[] = [];
53
+ const add = (list: Range[], address: number) => {
54
+ const last = list[list.length - 1];
55
+ if (last !== undefined && last.end === address - 1) last.end = address;
56
+ else list.push({ start: address, end: address });
57
+ };
58
+ for (const block of blocks) {
59
+ for (let address = block.start; address <= block.end; address++) {
60
+ if (inRanges(called, address)) continue;
61
+ if (own.has(address) && !written(address)) add(watch, address);
62
+ else add(exec, address);
63
+ }
64
+ }
65
+ return { exec, watch };
66
+ }
67
+
68
+ /** True when the address lies in one of the ranges. */
69
+ export function inRanges(ranges: readonly Range[], address: number): boolean {
70
+ return ranges.some((range) => contains(range, address));
71
+ }
72
+
73
+ /**
74
+ * Where a call returns to the stage (D59): the return address on top of the
75
+ * stack, when a JSR that the stage executed pushed it. `stack` is page 1.
76
+ * Returns the address of the instruction after that JSR.
77
+ */
78
+ export function callReturn(stack: Uint8Array, sp: number, byteAt: (address: number) => number, executed: (address: number) => boolean): number | undefined {
79
+ const pushed = stack[(sp + 1) & 0xff]! | (stack[(sp + 2) & 0xff]! << 8);
80
+ const jsr = (pushed - 2) & 0xffff;
81
+ if (byteAt(jsr) !== 0x20 || !executed(jsr)) return undefined;
82
+ return (pushed + 1) & 0xffff;
83
+ }
84
+
85
+ /**
86
+ * The code that ran in a block: its executed opcode bytes with the two bytes
87
+ * after each, which can be operands, joined and cut at the block's end.
88
+ */
89
+ export function executedIn(map: Uint8Array, block: Range): Range[] {
90
+ const ranges: Range[] = [];
91
+ for (let address = block.start; address <= block.end; address++) {
92
+ if ((map[address]! & COVERAGE.ramExecute) === 0) continue;
93
+ const end = Math.min(block.end, address + 2);
94
+ const last = ranges[ranges.length - 1];
95
+ if (last !== undefined && address <= last.end + 1) last.end = Math.max(last.end, end);
96
+ else ranges.push({ start: address, end });
97
+ }
98
+ return ranges;
99
+ }
100
+
101
+ /**
102
+ * The segments of a capture: the blocks that the stages wrote, without loader
103
+ * leftovers, joined into ranges that do not overlap or touch (F-26). A block
104
+ * is a leftover when it holds the entry of an intermediate stage that started
105
+ * after the block's writer, and no write from that stage on replaced the code
106
+ * at that entry (R2-01). Code that a stage ran before a later stage wrote over
107
+ * it never drops a block, and the block that holds the capture entry is always
108
+ * a segment. The filter comes before the join: a join first would drop the
109
+ * program with a leftover. `writtenBy` is the last stage that wrote into the
110
+ * range.
111
+ */
112
+ export function captureSegments(stages: ReadonlyArray<{ entry: number; wrote: readonly Range[] }>, entry: number): Array<Range & { writtenBy: number }> {
113
+ const last = stages.length - 1;
114
+ const replaced = (from: number, address: number) => stages.slice(from).some((stage) => inRanges(stage.wrote, address));
115
+ const leftover = (block: Range, writer: number) =>
116
+ !contains(block, entry) && stages.some((stage, index) => index > writer && index < last && contains(block, stage.entry) && !replaced(index, stage.entry));
117
+ const blocks = stages
118
+ .flatMap((stage, index) => stage.wrote.map((range) => ({ start: range.start, end: range.end, writtenBy: index })))
119
+ .filter((block) => !leftover(block, block.writtenBy))
120
+ .sort((a, b) => a.start - b.start);
121
+ const segments: Array<Range & { writtenBy: number }> = [];
122
+ for (const block of blocks) {
123
+ const previous = segments[segments.length - 1];
124
+ if (previous !== undefined && block.start <= previous.end + 1) {
125
+ previous.end = Math.max(previous.end, block.end);
126
+ previous.writtenBy = Math.max(previous.writtenBy, block.writtenBy);
127
+ } else segments.push({ ...block });
128
+ }
129
+ return segments;
130
+ }