@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.
- package/LICENSE +21 -0
- package/README.md +154 -37
- package/distribution/package.ts +21 -0
- package/distribution/plugin.ts +122 -0
- package/package.json +34 -40
- package/skills/c64-assembler/SKILL.md +76 -0
- package/skills/c64-assembler/scripts/assemble.ts +110 -0
- package/skills/c64-assembler/scripts/compare.ts +84 -0
- package/skills/c64-basic/SKILL.md +66 -0
- package/skills/c64-basic/scripts/basic.ts +46 -0
- package/skills/c64-disk/SKILL.md +93 -0
- package/skills/c64-disk/scripts/containers.ts +124 -0
- package/skills/c64-disk/scripts/disk.ts +120 -0
- package/skills/c64-emulator/SKILL.md +134 -0
- package/skills/c64-knowledge/SKILL.md +192 -0
- package/skills/c64-knowledge/scripts/knowledge.ts +613 -0
- package/skills/c64-memory-map/SKILL.md +79 -0
- package/skills/c64-memory-map/scripts/memmap.ts +92 -0
- package/skills/c64-provenance/SKILL.md +110 -0
- package/skills/c64-provenance/scripts/compare.ts +152 -0
- package/skills/c64-provenance/scripts/provenance.ts +334 -0
- package/skills/c64-provenance/scripts/runtime.ts +191 -0
- package/skills/c64-provenance/scripts/separate.ts +140 -0
- package/skills/c64-reverse-engineering/SKILL.md +144 -0
- package/skills/c64-source/SKILL.md +133 -0
- package/skills/c64-source/scripts/generate.ts +503 -0
- package/skills/c64-source/scripts/loader.ts +589 -0
- package/skills/c64-source/scripts/opcodes.ts +61 -0
- package/skills/c64-source/scripts/source.ts +673 -0
- package/skills/c64-static-analysis/SKILL.md +120 -0
- package/skills/c64-static-analysis/scripts/analyze.ts +293 -0
- package/skills/c64-static-analysis/scripts/coverage.ts +78 -0
- package/skills/c64-static-analysis/scripts/findings.ts +75 -0
- package/skills/c64-static-analysis/scripts/idioms.ts +149 -0
- package/skills/c64-static-analysis/scripts/instructions.ts +105 -0
- package/skills/c64-static-analysis/scripts/pointers.ts +108 -0
- package/skills/c64-testing/SKILL.md +103 -0
- package/skills/c64-testing/references/scenario-format.md +116 -0
- package/skills/c64-testing/scripts/checklist.ts +51 -0
- package/skills/c64-testing/scripts/run.ts +189 -0
- package/skills/c64-testing/scripts/scenario.ts +493 -0
- package/skills/c64-testing/scripts/test.ts +65 -0
- package/skills/c64-unpacker/SKILL.md +135 -0
- package/skills/c64-unpacker/scripts/evidence.ts +207 -0
- package/skills/c64-unpacker/scripts/loads.ts +209 -0
- package/skills/c64-unpacker/scripts/machine.ts +80 -0
- package/skills/c64-unpacker/scripts/stages.ts +130 -0
- package/skills/c64-unpacker/scripts/unpack.ts +683 -0
- package/src/c64.ts +411 -0
- package/src/cli/ap-sdk.ts +44 -0
- package/src/cli/cleanup.ts +194 -0
- package/src/cli/main.ts +125 -0
- package/src/cli/status.ts +61 -0
- package/src/host/main.ts +134 -0
- package/src/host/server.ts +392 -0
- package/src/host/tools/c1541.ts +284 -0
- package/src/host/tools/index.ts +35 -0
- package/src/host/tools/petcat.ts +77 -0
- package/src/host/tools/status.ts +47 -0
- package/src/host/tools/version.ts +41 -0
- package/src/host/vice/adapter.ts +804 -0
- package/src/host/vice/binary-monitor.ts +389 -0
- package/src/host/vice/chips.ts +118 -0
- package/src/host/vice/connect.ts +34 -0
- package/src/host/vice/process.ts +413 -0
- package/src/host/vice/screen.ts +184 -0
- package/src/host/vice/session.ts +1426 -0
- package/src/host/vice/text-monitor.ts +223 -0
- package/src/host-client/autostart.ts +55 -0
- package/src/host-client/connect.ts +241 -0
- package/src/host-client/coverage.ts +63 -0
- package/src/host-client/image.ts +63 -0
- package/src/host-client/steps.ts +170 -0
- package/src/host-client/tools.ts +89 -0
- package/src/host-client/transfer.ts +126 -0
- package/src/host-client/vice-session.ts +316 -0
- package/src/knowledge/database.ts +132 -0
- package/src/knowledge/expression.ts +209 -0
- package/src/knowledge/history.ts +169 -0
- package/src/knowledge/import.ts +392 -0
- package/src/knowledge/read.ts +392 -0
- package/src/knowledge/schema.ts +250 -0
- package/src/knowledge/write.ts +837 -0
- package/src/mcp/main.ts +134 -0
- package/src/mcp/output.ts +32 -0
- package/src/mcp/server.ts +316 -0
- package/src/mcp/tools/debug.ts +327 -0
- package/src/mcp/tools/execution.ts +117 -0
- package/src/mcp/tools/input.ts +72 -0
- package/src/mcp/tools/machine.ts +100 -0
- package/src/mcp/tools/media.ts +129 -0
- package/src/mcp/tools/memory.ts +250 -0
- package/src/mcp/tools/video.ts +271 -0
- package/src/native/acme.ts +116 -0
- package/src/native/discover.ts +179 -0
- package/src/native/dxa.ts +166 -0
- package/src/native/ghidra/analyze.ts +86 -0
- package/src/native/ghidra/index.ts +173 -0
- package/src/native/ghidra/language/c64rt_6510.cspec +34 -0
- package/src/native/ghidra/language/c64rt_6510.ldefs +15 -0
- package/src/native/ghidra/language/c64rt_6510.pspec +15 -0
- package/src/native/ghidra/language/c64rt_6510.slaspec +596 -0
- package/src/native/ghidra/scripts/C64Export.java +274 -0
- package/src/native/ghidra/scripts/C64Prepare.java +60 -0
- package/src/native/local.ts +34 -0
- package/src/native/processes.ts +350 -0
- package/src/native/run.ts +172 -0
- package/src/native/staging.ts +83 -0
- package/src/native/status.ts +113 -0
- package/src/native/types.ts +257 -0
- package/src/native/watchdog.ts +78 -0
- package/src/package.ts +21 -0
- package/src/platform.ts +441 -0
- package/src/project.ts +39 -0
- package/src/protocol/framing.ts +132 -0
- package/src/protocol/messages.ts +259 -0
- package/src/protocol/tools.ts +266 -0
- package/src/protocol/vice.ts +1348 -0
- package/src/script.ts +60 -0
- package/src/time.ts +15 -0
- package/src/trace.ts +194 -0
- package/THIRD-PARTY-NOTICES.md +0 -26
- package/bin/cli.mjs +0 -283
- package/skills/acme-build/SKILL.md +0 -260
- package/skills/acme-build/scripts/acme.mjs +0 -341
- package/skills/acme-build/template.a +0 -53
- package/skills/c64-disk-access/SKILL.md +0 -159
- package/skills/c64-disk-access/scripts/c1541.mjs +0 -569
- package/skills/c64-memory-mapping/SKILL.md +0 -631
- package/skills/c64-memory-mapping/memmap.json +0 -8800
- package/skills/c64-memory-mapping/scripts/driver.mjs +0 -553
- package/skills/c64-petcat/SKILL.md +0 -87
- package/skills/c64-petcat/scripts/petcat.mjs +0 -221
- package/skills/c64-program-recon/SKILL.md +0 -706
- package/skills/c64-program-recon/references/control-flow.md +0 -180
- package/skills/c64-program-recon/references/graphics.md +0 -79
- package/skills/c64-program-recon/references/observation-hazards.md +0 -143
- package/skills/c64-program-recon/references/reconstruction.md +0 -133
- package/skills/c64-program-recon/references/sound-and-input.md +0 -74
- package/skills/c64-program-recon/references/tool-selection.md +0 -78
- package/skills/c64-program-recon/scripts/derive.mjs +0 -364
- package/skills/c64-program-recon/scripts/packer-finding.mjs +0 -709
- package/skills/c64-program-recon/templates/memory-map.template.md +0 -101
- package/skills/c64-provenance-diff/SKILL.md +0 -292
- package/skills/c64-provenance-diff/scripts/diff-images.mjs +0 -984
- package/skills/c64-provenance-diff/scripts/recovery-schema.mjs +0 -395
- package/skills/c64-ram-capture/RELEASES.json.example +0 -17
- package/skills/c64-ram-capture/SKILL.md +0 -474
- package/skills/c64-ram-capture/scripts/compare-cross-binary.mjs +0 -525
- package/skills/c64-ram-capture/scripts/compare.mjs +0 -258
- package/skills/c64-ram-capture/scripts/derive-transients.mjs +0 -575
- package/skills/c64-ram-capture/scripts/dump-artifacts.mjs +0 -317
- package/skills/c64-ram-capture/scripts/mcp-module.mjs +0 -174
- package/skills/c64-ram-capture/scripts/project-paths.mjs +0 -81
- package/skills/c64-ram-capture/scripts/releases.mjs +0 -109
- package/skills/c64-ram-capture/scripts/vsf-slice.mjs +0 -147
- package/skills/c64-ram-capture/scripts/watch-loads.mjs +0 -581
- package/skills/c64-ram-capture/templates/capture-record.template.md +0 -99
- package/skills/c64-ram-capture/transients/README.md +0 -137
- package/skills/routine-queue-walker/SKILL.md +0 -394
- package/skills/routine-queue-walker/scripts/completeness-report.mjs +0 -465
- 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
|
+
}
|