c64bridge 0.8.1 → 0.9.1

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 (92) hide show
  1. package/.github/prompts/steer.prompt.md +55 -0
  2. package/AGENTS.md +9 -7
  3. package/README.md +192 -154
  4. package/data/embeddings_asm.json +1 -1
  5. package/data/embeddings_basic.json +1 -1
  6. package/data/embeddings_hardware.json +1 -1
  7. package/data/embeddings_mixed.json +1 -1
  8. package/data/embeddings_other.json +1 -1
  9. package/data/graphics/petscii-style-guide.md +4 -4
  10. package/data/graphics/sprite-charset-best-practices.md +9 -9
  11. package/data/vice/vice-binary-monitor-spec.md +938 -0
  12. package/dist/.tsbuildinfo +1 -1
  13. package/dist/c64Client.js +76 -2
  14. package/dist/device.js +129 -13
  15. package/dist/mcp-server.js +1 -1
  16. package/dist/prompts/registry.js +27 -25
  17. package/dist/rag/indexer.js +18 -8
  18. package/dist/rag/knowledgeIndex.js +112 -79
  19. package/dist/rag/resourceUris.js +93 -0
  20. package/dist/sidwaveCompiler.js +1 -1
  21. package/dist/{assemblyConverter.js → tools/assember.js} +10 -1
  22. package/dist/tools/audio.js +11 -11
  23. package/dist/{basicConverter.js → tools/basicTokenizer.js} +1 -1
  24. package/dist/tools/debug.js +159 -6
  25. package/dist/tools/developer.js +13 -13
  26. package/dist/tools/disassembler.js +478 -0
  27. package/dist/tools/graphics.js +10 -10
  28. package/dist/tools/input.js +338 -0
  29. package/dist/tools/machineControl.js +5 -5
  30. package/dist/tools/memory.js +336 -12
  31. package/dist/tools/meta/index.js +1 -1
  32. package/dist/tools/printer.js +11 -12
  33. package/dist/tools/programRunners.js +61 -22
  34. package/dist/tools/rag.js +9 -9
  35. package/dist/tools/registry/batch.js +167 -0
  36. package/dist/tools/registry/config.js +1 -1
  37. package/dist/tools/registry/disk.js +1 -1
  38. package/dist/tools/registry/drive.js +1 -1
  39. package/dist/tools/registry/extract.js +1 -1
  40. package/dist/tools/registry/graphics.js +102 -2
  41. package/dist/tools/registry/index.js +4 -0
  42. package/dist/tools/registry/input.js +2 -0
  43. package/dist/tools/registry/memory.js +62 -2
  44. package/dist/tools/registry/platform.js +1 -1
  45. package/dist/tools/registry/printer.js +1 -1
  46. package/dist/tools/registry/program.js +1 -1
  47. package/dist/tools/registry/rag.js +1 -1
  48. package/dist/tools/registry/sound.js +1 -1
  49. package/dist/tools/registry/stream.js +1 -1
  50. package/dist/tools/registry/system.js +1 -1
  51. package/dist/tools/schema.js +4 -5
  52. package/dist/tools/storage.js +15 -15
  53. package/dist/tools/streaming.js +3 -3
  54. package/dist/tools/symbolRegistry.js +49 -0
  55. package/dist/tools/types.js +56 -4
  56. package/dist/tools/vice.js +2 -5
  57. package/dist/vice/process.js +120 -2
  58. package/dist/vice/readiness.js +35 -0
  59. package/dist/vice/smokeOptions.js +44 -0
  60. package/dist/vice/viceClient.js +5 -1
  61. package/dist/viceRunner.js +2 -0
  62. package/doc/plans/prompts/README.md +7 -7
  63. package/mcp/prompts.json +42 -59
  64. package/mcp/protocol-examples.json +2 -2
  65. package/mcp/resources.json +179 -166
  66. package/mcp/schemas/c64_batch.schema.json +53 -0
  67. package/mcp/schemas/c64_config.schema.json +525 -283
  68. package/mcp/schemas/c64_debug.schema.json +763 -304
  69. package/mcp/schemas/c64_disk.schema.json +499 -243
  70. package/mcp/schemas/c64_drive.schema.json +165 -90
  71. package/mcp/schemas/c64_extract.schema.json +533 -274
  72. package/mcp/schemas/c64_graphics.schema.json +607 -295
  73. package/mcp/schemas/c64_input.schema.json +136 -0
  74. package/mcp/schemas/c64_memory.schema.json +637 -128
  75. package/mcp/schemas/c64_printer.schema.json +393 -196
  76. package/mcp/schemas/c64_program.schema.json +699 -340
  77. package/mcp/schemas/c64_rag.schema.json +100 -54
  78. package/mcp/schemas/c64_select_backend.schema.json +49 -23
  79. package/mcp/schemas/c64_sound.schema.json +1092 -577
  80. package/mcp/schemas/c64_stream.schema.json +89 -47
  81. package/mcp/schemas/c64_system.schema.json +351 -185
  82. package/mcp/schemas/c64_vice.schema.json +85 -47
  83. package/mcp/server.json +1 -1
  84. package/mcp/tools.json +7299 -3346
  85. package/mcp.json +3 -3
  86. package/package.json +17 -14
  87. package/scripts/fetch-external-sources.mjs +1 -2
  88. package/scripts/run-coverage.mjs +33 -1
  89. package/scripts/run-tests.mjs +2 -2
  90. package/scripts/run-tests.ts +275 -52
  91. package/scripts/update-readme.ts +132 -3
  92. package/server.json +2 -2
@@ -0,0 +1,478 @@
1
+ /**
2
+ * 6502/6510 disassembler covering the full 256-opcode space, including
3
+ * undocumented (illegal) opcodes. Mnemonic naming follows the canonical
4
+ * convention used by the 1541U monitor (HLT->JAM, ASO->SLO, LSE->SRE,
5
+ * DCM->DCP, INS->ISC).
6
+ */
7
+ function entry(mnemonic, mode, illegal = false) {
8
+ return { mnemonic, mode, illegal };
9
+ }
10
+ // Canonicalization rules from disassembler_6502.cc:
11
+ // HLT -> JAM, ASO -> SLO, LSE -> SRE, DCM -> DCP, INS -> ISC
12
+ function canonical(mnemonic) {
13
+ switch (mnemonic) {
14
+ case "HLT": return "JAM";
15
+ case "ASO": return "SLO";
16
+ case "LSE": return "SRE";
17
+ case "DCM": return "DCP";
18
+ case "INS": return "ISC";
19
+ default: return mnemonic;
20
+ }
21
+ }
22
+ // 256-entry opcode table mirroring `opcode_templates` in disassembler_6502.cc.
23
+ // `illegal` is taken from the bitmap `illegal_map` in the same reference.
24
+ const OPCODES = (() => {
25
+ // Build the illegal-opcode bitmap from the reference file.
26
+ const ILLEGAL_MAP = [
27
+ 0x989C, 0x9C9C, 0x888C, 0x9C9C,
28
+ 0x889C, 0x9C9C, 0x889C, 0x9C9C,
29
+ 0x8A8D, 0xD88C, 0x8888, 0x888C,
30
+ 0x888C, 0x9C9C, 0x888C, 0x9C9C,
31
+ ];
32
+ const isIllegal = (op) => {
33
+ const row = ILLEGAL_MAP[op >> 4];
34
+ return ((row >> (op & 0x0F)) & 1) !== 0;
35
+ };
36
+ const t = new Array(256);
37
+ // Helper: fill one row of 16 entries by mnemonic/mode pairs.
38
+ const set = (op, mnemonic, mode) => {
39
+ t[op] = { mnemonic: canonical(mnemonic), mode, illegal: isIllegal(op) };
40
+ };
41
+ // 0x00-0x0F
42
+ set(0x00, "BRK", 0 /* Mode.Imp */);
43
+ set(0x01, "ORA", 12 /* Mode.IndX */);
44
+ set(0x02, "HLT", 0 /* Mode.Imp */);
45
+ set(0x03, "ASO", 12 /* Mode.IndX */);
46
+ set(0x04, "NOP", 3 /* Mode.Zp */);
47
+ set(0x05, "ORA", 3 /* Mode.Zp */);
48
+ set(0x06, "ASL", 3 /* Mode.Zp */);
49
+ set(0x07, "ASO", 3 /* Mode.Zp */);
50
+ set(0x08, "PHP", 0 /* Mode.Imp */);
51
+ set(0x09, "ORA", 2 /* Mode.Imm */);
52
+ set(0x0A, "ASL", 1 /* Mode.Acc */);
53
+ set(0x0B, "ANC", 2 /* Mode.Imm */);
54
+ set(0x0C, "NOP", 8 /* Mode.Abs */);
55
+ set(0x0D, "ORA", 8 /* Mode.Abs */);
56
+ set(0x0E, "ASL", 8 /* Mode.Abs */);
57
+ set(0x0F, "ASO", 8 /* Mode.Abs */);
58
+ // 0x10-0x1F
59
+ set(0x10, "BPL", 7 /* Mode.Rel */);
60
+ set(0x11, "ORA", 13 /* Mode.IndY */);
61
+ set(0x12, "HLT", 0 /* Mode.Imp */);
62
+ set(0x13, "ASO", 13 /* Mode.IndY */);
63
+ set(0x14, "NOP", 4 /* Mode.ZpX */);
64
+ set(0x15, "ORA", 4 /* Mode.ZpX */);
65
+ set(0x16, "ASL", 4 /* Mode.ZpX */);
66
+ set(0x17, "ASO", 4 /* Mode.ZpX */);
67
+ set(0x18, "CLC", 0 /* Mode.Imp */);
68
+ set(0x19, "ORA", 10 /* Mode.AbsY */);
69
+ set(0x1A, "NOP", 0 /* Mode.Imp */);
70
+ set(0x1B, "ASO", 10 /* Mode.AbsY */);
71
+ set(0x1C, "NOP", 9 /* Mode.AbsX */);
72
+ set(0x1D, "ORA", 9 /* Mode.AbsX */);
73
+ set(0x1E, "ASL", 9 /* Mode.AbsX */);
74
+ set(0x1F, "ASO", 9 /* Mode.AbsX */);
75
+ // 0x20-0x2F
76
+ set(0x20, "JSR", 8 /* Mode.Abs */);
77
+ set(0x21, "AND", 12 /* Mode.IndX */);
78
+ set(0x22, "HLT", 0 /* Mode.Imp */);
79
+ set(0x23, "RLA", 12 /* Mode.IndX */);
80
+ set(0x24, "BIT", 3 /* Mode.Zp */);
81
+ set(0x25, "AND", 3 /* Mode.Zp */);
82
+ set(0x26, "ROL", 3 /* Mode.Zp */);
83
+ set(0x27, "RLA", 3 /* Mode.Zp */);
84
+ set(0x28, "PLP", 0 /* Mode.Imp */);
85
+ set(0x29, "AND", 2 /* Mode.Imm */);
86
+ set(0x2A, "ROL", 1 /* Mode.Acc */);
87
+ set(0x2B, "ANC", 2 /* Mode.Imm */);
88
+ set(0x2C, "BIT", 8 /* Mode.Abs */);
89
+ set(0x2D, "AND", 8 /* Mode.Abs */);
90
+ set(0x2E, "ROL", 8 /* Mode.Abs */);
91
+ set(0x2F, "RLA", 8 /* Mode.Abs */);
92
+ // 0x30-0x3F
93
+ set(0x30, "BMI", 7 /* Mode.Rel */);
94
+ set(0x31, "AND", 13 /* Mode.IndY */);
95
+ set(0x32, "HLT", 0 /* Mode.Imp */);
96
+ set(0x33, "RLA", 13 /* Mode.IndY */);
97
+ set(0x34, "NOP", 4 /* Mode.ZpX */);
98
+ set(0x35, "AND", 4 /* Mode.ZpX */);
99
+ set(0x36, "ROL", 4 /* Mode.ZpX */);
100
+ set(0x37, "RLA", 4 /* Mode.ZpX */);
101
+ set(0x38, "SEC", 0 /* Mode.Imp */);
102
+ set(0x39, "AND", 10 /* Mode.AbsY */);
103
+ set(0x3A, "NOP", 0 /* Mode.Imp */);
104
+ set(0x3B, "RLA", 10 /* Mode.AbsY */);
105
+ set(0x3C, "NOP", 9 /* Mode.AbsX */);
106
+ set(0x3D, "AND", 9 /* Mode.AbsX */);
107
+ set(0x3E, "ROL", 9 /* Mode.AbsX */);
108
+ set(0x3F, "RLA", 9 /* Mode.AbsX */);
109
+ // 0x40-0x4F
110
+ set(0x40, "RTI", 0 /* Mode.Imp */);
111
+ set(0x41, "EOR", 12 /* Mode.IndX */);
112
+ set(0x42, "HLT", 0 /* Mode.Imp */);
113
+ set(0x43, "LSE", 12 /* Mode.IndX */);
114
+ set(0x44, "NOP", 3 /* Mode.Zp */);
115
+ set(0x45, "EOR", 3 /* Mode.Zp */);
116
+ set(0x46, "LSR", 3 /* Mode.Zp */);
117
+ set(0x47, "LSE", 3 /* Mode.Zp */);
118
+ set(0x48, "PHA", 0 /* Mode.Imp */);
119
+ set(0x49, "EOR", 2 /* Mode.Imm */);
120
+ set(0x4A, "LSR", 1 /* Mode.Acc */);
121
+ set(0x4B, "ALR", 2 /* Mode.Imm */);
122
+ set(0x4C, "JMP", 8 /* Mode.Abs */);
123
+ set(0x4D, "EOR", 8 /* Mode.Abs */);
124
+ set(0x4E, "LSR", 8 /* Mode.Abs */);
125
+ set(0x4F, "LSE", 8 /* Mode.Abs */);
126
+ // 0x50-0x5F
127
+ set(0x50, "BVC", 7 /* Mode.Rel */);
128
+ set(0x51, "EOR", 13 /* Mode.IndY */);
129
+ set(0x52, "HLT", 0 /* Mode.Imp */);
130
+ set(0x53, "LSE", 13 /* Mode.IndY */);
131
+ set(0x54, "NOP", 4 /* Mode.ZpX */);
132
+ set(0x55, "EOR", 4 /* Mode.ZpX */);
133
+ set(0x56, "LSR", 4 /* Mode.ZpX */);
134
+ set(0x57, "LSE", 4 /* Mode.ZpX */);
135
+ set(0x58, "CLI", 0 /* Mode.Imp */);
136
+ set(0x59, "EOR", 10 /* Mode.AbsY */);
137
+ set(0x5A, "NOP", 0 /* Mode.Imp */);
138
+ set(0x5B, "LSE", 10 /* Mode.AbsY */);
139
+ set(0x5C, "NOP", 9 /* Mode.AbsX */);
140
+ set(0x5D, "EOR", 9 /* Mode.AbsX */);
141
+ set(0x5E, "LSR", 9 /* Mode.AbsX */);
142
+ set(0x5F, "LSE", 9 /* Mode.AbsX */);
143
+ // 0x60-0x6F
144
+ set(0x60, "RTS", 0 /* Mode.Imp */);
145
+ set(0x61, "ADC", 12 /* Mode.IndX */);
146
+ set(0x62, "HLT", 0 /* Mode.Imp */);
147
+ set(0x63, "RRA", 12 /* Mode.IndX */);
148
+ set(0x64, "NOP", 3 /* Mode.Zp */);
149
+ set(0x65, "ADC", 3 /* Mode.Zp */);
150
+ set(0x66, "ROR", 3 /* Mode.Zp */);
151
+ set(0x67, "RRA", 3 /* Mode.Zp */);
152
+ set(0x68, "PLA", 0 /* Mode.Imp */);
153
+ set(0x69, "ADC", 2 /* Mode.Imm */);
154
+ set(0x6A, "ROR", 1 /* Mode.Acc */);
155
+ set(0x6B, "ARR", 2 /* Mode.Imm */);
156
+ set(0x6C, "JMP", 11 /* Mode.Ind */);
157
+ set(0x6D, "ADC", 8 /* Mode.Abs */);
158
+ set(0x6E, "ROR", 8 /* Mode.Abs */);
159
+ set(0x6F, "RRA", 8 /* Mode.Abs */);
160
+ // 0x70-0x7F
161
+ set(0x70, "BVS", 7 /* Mode.Rel */);
162
+ set(0x71, "ADC", 13 /* Mode.IndY */);
163
+ set(0x72, "HLT", 0 /* Mode.Imp */);
164
+ set(0x73, "RRA", 13 /* Mode.IndY */);
165
+ set(0x74, "NOP", 4 /* Mode.ZpX */);
166
+ set(0x75, "ADC", 4 /* Mode.ZpX */);
167
+ set(0x76, "ROR", 4 /* Mode.ZpX */);
168
+ set(0x77, "RRA", 4 /* Mode.ZpX */);
169
+ set(0x78, "SEI", 0 /* Mode.Imp */);
170
+ set(0x79, "ADC", 10 /* Mode.AbsY */);
171
+ set(0x7A, "NOP", 0 /* Mode.Imp */);
172
+ set(0x7B, "RRA", 10 /* Mode.AbsY */);
173
+ set(0x7C, "NOP", 9 /* Mode.AbsX */);
174
+ set(0x7D, "ADC", 9 /* Mode.AbsX */);
175
+ set(0x7E, "ROR", 9 /* Mode.AbsX */);
176
+ set(0x7F, "RRA", 9 /* Mode.AbsX */);
177
+ // 0x80-0x8F
178
+ set(0x80, "NOP", 2 /* Mode.Imm */);
179
+ set(0x81, "STA", 12 /* Mode.IndX */);
180
+ set(0x82, "NOP", 2 /* Mode.Imm */);
181
+ set(0x83, "SAX", 12 /* Mode.IndX */);
182
+ set(0x84, "STY", 3 /* Mode.Zp */);
183
+ set(0x85, "STA", 3 /* Mode.Zp */);
184
+ set(0x86, "STX", 3 /* Mode.Zp */);
185
+ set(0x87, "SAX", 3 /* Mode.Zp */);
186
+ set(0x88, "DEY", 0 /* Mode.Imp */);
187
+ set(0x89, "NOP", 2 /* Mode.Imm */);
188
+ set(0x8A, "TXA", 0 /* Mode.Imp */);
189
+ set(0x8B, "XAA", 2 /* Mode.Imm */);
190
+ set(0x8C, "STY", 8 /* Mode.Abs */);
191
+ set(0x8D, "STA", 8 /* Mode.Abs */);
192
+ set(0x8E, "STX", 8 /* Mode.Abs */);
193
+ set(0x8F, "SAX", 8 /* Mode.Abs */);
194
+ // 0x90-0x9F
195
+ set(0x90, "BCC", 7 /* Mode.Rel */);
196
+ set(0x91, "STA", 13 /* Mode.IndY */);
197
+ set(0x92, "HLT", 0 /* Mode.Imp */);
198
+ set(0x93, "AHX", 13 /* Mode.IndY */);
199
+ set(0x94, "STY", 4 /* Mode.ZpX */);
200
+ set(0x95, "STA", 4 /* Mode.ZpX */);
201
+ set(0x96, "STX", 5 /* Mode.ZpY */);
202
+ set(0x97, "SAX", 5 /* Mode.ZpY */);
203
+ set(0x98, "TYA", 0 /* Mode.Imp */);
204
+ set(0x99, "STA", 10 /* Mode.AbsY */);
205
+ set(0x9A, "TXS", 0 /* Mode.Imp */);
206
+ set(0x9B, "TAS", 10 /* Mode.AbsY */);
207
+ set(0x9C, "SHY", 9 /* Mode.AbsX */);
208
+ set(0x9D, "STA", 9 /* Mode.AbsX */);
209
+ set(0x9E, "SHX", 10 /* Mode.AbsY */);
210
+ set(0x9F, "AHX", 10 /* Mode.AbsY */);
211
+ // 0xA0-0xAF
212
+ set(0xA0, "LDY", 2 /* Mode.Imm */);
213
+ set(0xA1, "LDA", 12 /* Mode.IndX */);
214
+ set(0xA2, "LDX", 2 /* Mode.Imm */);
215
+ set(0xA3, "LAX", 12 /* Mode.IndX */);
216
+ set(0xA4, "LDY", 3 /* Mode.Zp */);
217
+ set(0xA5, "LDA", 3 /* Mode.Zp */);
218
+ set(0xA6, "LDX", 3 /* Mode.Zp */);
219
+ set(0xA7, "LAX", 3 /* Mode.Zp */);
220
+ set(0xA8, "TAY", 0 /* Mode.Imp */);
221
+ set(0xA9, "LDA", 2 /* Mode.Imm */);
222
+ set(0xAA, "TAX", 0 /* Mode.Imp */);
223
+ set(0xAB, "LAX", 2 /* Mode.Imm */);
224
+ set(0xAC, "LDY", 8 /* Mode.Abs */);
225
+ set(0xAD, "LDA", 8 /* Mode.Abs */);
226
+ set(0xAE, "LDX", 8 /* Mode.Abs */);
227
+ set(0xAF, "LAX", 8 /* Mode.Abs */);
228
+ // 0xB0-0xBF
229
+ set(0xB0, "BCS", 7 /* Mode.Rel */);
230
+ set(0xB1, "LDA", 13 /* Mode.IndY */);
231
+ set(0xB2, "HLT", 0 /* Mode.Imp */);
232
+ set(0xB3, "LAX", 13 /* Mode.IndY */);
233
+ set(0xB4, "LDY", 4 /* Mode.ZpX */);
234
+ set(0xB5, "LDA", 4 /* Mode.ZpX */);
235
+ set(0xB6, "LDX", 5 /* Mode.ZpY */);
236
+ set(0xB7, "LAX", 5 /* Mode.ZpY */);
237
+ set(0xB8, "CLV", 0 /* Mode.Imp */);
238
+ set(0xB9, "LDA", 10 /* Mode.AbsY */);
239
+ set(0xBA, "TSX", 0 /* Mode.Imp */);
240
+ set(0xBB, "LAS", 10 /* Mode.AbsY */);
241
+ set(0xBC, "LDY", 9 /* Mode.AbsX */);
242
+ set(0xBD, "LDA", 9 /* Mode.AbsX */);
243
+ set(0xBE, "LDX", 10 /* Mode.AbsY */);
244
+ set(0xBF, "LAX", 10 /* Mode.AbsY */);
245
+ // 0xC0-0xCF
246
+ set(0xC0, "CPY", 2 /* Mode.Imm */);
247
+ set(0xC1, "CMP", 12 /* Mode.IndX */);
248
+ set(0xC2, "NOP", 2 /* Mode.Imm */);
249
+ set(0xC3, "DCM", 12 /* Mode.IndX */);
250
+ set(0xC4, "CPY", 3 /* Mode.Zp */);
251
+ set(0xC5, "CMP", 3 /* Mode.Zp */);
252
+ set(0xC6, "DEC", 3 /* Mode.Zp */);
253
+ set(0xC7, "DCM", 3 /* Mode.Zp */);
254
+ set(0xC8, "INY", 0 /* Mode.Imp */);
255
+ set(0xC9, "CMP", 2 /* Mode.Imm */);
256
+ set(0xCA, "DEX", 0 /* Mode.Imp */);
257
+ set(0xCB, "AXS", 2 /* Mode.Imm */);
258
+ set(0xCC, "CPY", 8 /* Mode.Abs */);
259
+ set(0xCD, "CMP", 8 /* Mode.Abs */);
260
+ set(0xCE, "DEC", 8 /* Mode.Abs */);
261
+ set(0xCF, "DCM", 8 /* Mode.Abs */);
262
+ // 0xD0-0xDF
263
+ set(0xD0, "BNE", 7 /* Mode.Rel */);
264
+ set(0xD1, "CMP", 13 /* Mode.IndY */);
265
+ set(0xD2, "HLT", 0 /* Mode.Imp */);
266
+ set(0xD3, "DCM", 13 /* Mode.IndY */);
267
+ set(0xD4, "NOP", 4 /* Mode.ZpX */);
268
+ set(0xD5, "CMP", 4 /* Mode.ZpX */);
269
+ set(0xD6, "DEC", 4 /* Mode.ZpX */);
270
+ set(0xD7, "DCM", 4 /* Mode.ZpX */);
271
+ set(0xD8, "CLD", 0 /* Mode.Imp */);
272
+ set(0xD9, "CMP", 10 /* Mode.AbsY */);
273
+ set(0xDA, "NOP", 0 /* Mode.Imp */);
274
+ set(0xDB, "DCM", 10 /* Mode.AbsY */);
275
+ set(0xDC, "NOP", 9 /* Mode.AbsX */);
276
+ set(0xDD, "CMP", 9 /* Mode.AbsX */);
277
+ set(0xDE, "DEC", 9 /* Mode.AbsX */);
278
+ set(0xDF, "DCM", 9 /* Mode.AbsX */);
279
+ // 0xE0-0xEF
280
+ set(0xE0, "CPX", 2 /* Mode.Imm */);
281
+ set(0xE1, "SBC", 12 /* Mode.IndX */);
282
+ set(0xE2, "NOP", 2 /* Mode.Imm */);
283
+ set(0xE3, "INS", 12 /* Mode.IndX */);
284
+ set(0xE4, "CPX", 3 /* Mode.Zp */);
285
+ set(0xE5, "SBC", 3 /* Mode.Zp */);
286
+ set(0xE6, "INC", 3 /* Mode.Zp */);
287
+ set(0xE7, "INS", 3 /* Mode.Zp */);
288
+ set(0xE8, "INX", 0 /* Mode.Imp */);
289
+ set(0xE9, "SBC", 2 /* Mode.Imm */);
290
+ set(0xEA, "NOP", 0 /* Mode.Imp */);
291
+ set(0xEB, "SBC", 2 /* Mode.Imm */);
292
+ set(0xEC, "CPX", 8 /* Mode.Abs */);
293
+ set(0xED, "SBC", 8 /* Mode.Abs */);
294
+ set(0xEE, "INC", 8 /* Mode.Abs */);
295
+ set(0xEF, "INS", 8 /* Mode.Abs */);
296
+ // 0xF0-0xFF
297
+ set(0xF0, "BEQ", 7 /* Mode.Rel */);
298
+ set(0xF1, "SBC", 13 /* Mode.IndY */);
299
+ set(0xF2, "HLT", 0 /* Mode.Imp */);
300
+ set(0xF3, "INS", 13 /* Mode.IndY */);
301
+ set(0xF4, "NOP", 6 /* Mode.ZpS */);
302
+ set(0xF5, "SBC", 4 /* Mode.ZpX */);
303
+ set(0xF6, "INC", 4 /* Mode.ZpX */);
304
+ set(0xF7, "INS", 4 /* Mode.ZpX */);
305
+ set(0xF8, "SED", 0 /* Mode.Imp */);
306
+ set(0xF9, "SBC", 10 /* Mode.AbsY */);
307
+ set(0xFA, "NOP", 0 /* Mode.Imp */);
308
+ set(0xFB, "INS", 10 /* Mode.AbsY */);
309
+ set(0xFC, "NOP", 9 /* Mode.AbsX */);
310
+ set(0xFD, "SBC", 9 /* Mode.AbsX */);
311
+ set(0xFE, "INC", 9 /* Mode.AbsX */);
312
+ set(0xFF, "INS", 9 /* Mode.AbsX */);
313
+ return t;
314
+ })();
315
+ function modeSize(mode) {
316
+ switch (mode) {
317
+ case 0 /* Mode.Imp */:
318
+ case 1 /* Mode.Acc */:
319
+ return 1;
320
+ case 2 /* Mode.Imm */:
321
+ case 3 /* Mode.Zp */:
322
+ case 4 /* Mode.ZpX */:
323
+ case 5 /* Mode.ZpY */:
324
+ case 6 /* Mode.ZpS */:
325
+ case 7 /* Mode.Rel */:
326
+ case 12 /* Mode.IndX */:
327
+ case 13 /* Mode.IndY */:
328
+ return 2;
329
+ case 8 /* Mode.Abs */:
330
+ case 9 /* Mode.AbsX */:
331
+ case 10 /* Mode.AbsY */:
332
+ case 11 /* Mode.Ind */:
333
+ return 3;
334
+ }
335
+ }
336
+ function hex2(v) {
337
+ return v.toString(16).toUpperCase().padStart(2, "0");
338
+ }
339
+ function hex4(v) {
340
+ return v.toString(16).toUpperCase().padStart(4, "0");
341
+ }
342
+ function labelOrHex4(addr, symbols) {
343
+ const label = symbols?.get(addr);
344
+ return label ? `${label} ($${hex4(addr)})` : `$${hex4(addr)}`;
345
+ }
346
+ function formatOperand(mode, bytes, offset, instrAddr, symbols) {
347
+ switch (mode) {
348
+ case 0 /* Mode.Imp */:
349
+ return "";
350
+ case 1 /* Mode.Acc */:
351
+ return "A";
352
+ case 2 /* Mode.Imm */:
353
+ return `#$${hex2(bytes[offset + 1] ?? 0)}`;
354
+ case 3 /* Mode.Zp */:
355
+ return `$${hex2(bytes[offset + 1] ?? 0)}`;
356
+ case 4 /* Mode.ZpX */:
357
+ return `$${hex2(bytes[offset + 1] ?? 0)},X`;
358
+ case 5 /* Mode.ZpY */:
359
+ return `$${hex2(bytes[offset + 1] ?? 0)},Y`;
360
+ case 6 /* Mode.ZpS */:
361
+ return `$${hex2(bytes[offset + 1] ?? 0)},S`;
362
+ case 7 /* Mode.Rel */: {
363
+ const rel = bytes[offset + 1] ?? 0;
364
+ const signed = rel >= 0x80 ? rel - 0x100 : rel;
365
+ const target = (instrAddr + 2 + signed) & 0xffff;
366
+ return labelOrHex4(target, symbols);
367
+ }
368
+ case 8 /* Mode.Abs */: {
369
+ const lo = bytes[offset + 1] ?? 0;
370
+ const hi = bytes[offset + 2] ?? 0;
371
+ const addr = lo | (hi << 8);
372
+ return labelOrHex4(addr, symbols);
373
+ }
374
+ case 9 /* Mode.AbsX */: {
375
+ const lo = bytes[offset + 1] ?? 0;
376
+ const hi = bytes[offset + 2] ?? 0;
377
+ const addr = lo | (hi << 8);
378
+ return `${labelOrHex4(addr, symbols)},X`;
379
+ }
380
+ case 10 /* Mode.AbsY */: {
381
+ const lo = bytes[offset + 1] ?? 0;
382
+ const hi = bytes[offset + 2] ?? 0;
383
+ const addr = lo | (hi << 8);
384
+ return `${labelOrHex4(addr, symbols)},Y`;
385
+ }
386
+ case 11 /* Mode.Ind */: {
387
+ const lo = bytes[offset + 1] ?? 0;
388
+ const hi = bytes[offset + 2] ?? 0;
389
+ const addr = lo | (hi << 8);
390
+ return `($${hex4(addr)})`;
391
+ }
392
+ case 12 /* Mode.IndX */:
393
+ return `($${hex2(bytes[offset + 1] ?? 0)},X)`;
394
+ case 13 /* Mode.IndY */:
395
+ return `($${hex2(bytes[offset + 1] ?? 0)}),Y`;
396
+ }
397
+ }
398
+ /**
399
+ * Disassemble a block of 6502/6510 bytes.
400
+ *
401
+ * @param bytes Raw memory bytes (may be longer than needed)
402
+ * @param baseAddress The C64 memory address of `bytes[0]`
403
+ * @param countOrOptions Either a max-instruction count (legacy form) or an options object
404
+ * @param symbols Optional address->label map (legacy positional form)
405
+ */
406
+ export function disassemble(bytes, baseAddress, countOrOptions, symbols) {
407
+ const options = typeof countOrOptions === "object" && countOrOptions !== null
408
+ ? countOrOptions
409
+ : { count: countOrOptions, symbols };
410
+ const limit = options.count ?? Infinity;
411
+ const symMap = options.symbols ?? symbols;
412
+ const allowUndocumented = options.allowUndocumented !== false;
413
+ const lines = [];
414
+ let offset = 0;
415
+ while (offset < bytes.length && lines.length < limit) {
416
+ const instrAddr = (baseAddress + offset) & 0xffff;
417
+ const opcode = bytes[offset] ?? 0;
418
+ const op = OPCODES[opcode];
419
+ const label = symMap?.get(instrAddr);
420
+ if (op.illegal && !allowUndocumented) {
421
+ lines.push({
422
+ address: instrAddr,
423
+ bytes: [opcode],
424
+ label,
425
+ mnemonic: "???",
426
+ operand: `$${hex2(opcode)}`,
427
+ undocumented: true,
428
+ });
429
+ offset += 1;
430
+ continue;
431
+ }
432
+ const size = modeSize(op.mode);
433
+ const instrBytes = [];
434
+ for (let i = 0; i < size && offset + i < bytes.length; i++) {
435
+ instrBytes.push(bytes[offset + i] ?? 0);
436
+ }
437
+ const operand = formatOperand(op.mode, bytes, offset, instrAddr, symMap);
438
+ lines.push({
439
+ address: instrAddr,
440
+ bytes: instrBytes,
441
+ label,
442
+ mnemonic: op.mnemonic,
443
+ operand,
444
+ undocumented: op.illegal,
445
+ });
446
+ offset += size;
447
+ }
448
+ return lines;
449
+ }
450
+ /**
451
+ * Render disassembly lines as a human-readable string.
452
+ * Format: [label:\n] $ADDR XX XX XX MNEM operand ; *undocumented*
453
+ */
454
+ export function formatDisassembly(lines) {
455
+ const parts = [];
456
+ for (const line of lines) {
457
+ if (line.label) {
458
+ parts.push(`${line.label}:`);
459
+ }
460
+ const addrStr = `$${hex4(line.address)}`;
461
+ const byteStr = line.bytes.map((b) => hex2(b)).join(" ").padEnd(8);
462
+ const mnemonic = line.undocumented ? `${line.mnemonic}*` : line.mnemonic;
463
+ const instrStr = line.operand
464
+ ? `${mnemonic} ${line.operand}`
465
+ : mnemonic;
466
+ parts.push(` ${addrStr} ${byteStr} ${instrStr}`);
467
+ }
468
+ return parts.join("\n");
469
+ }
470
+ /** Returns true when the opcode is undocumented per the 1541U reference. */
471
+ export function isUndocumentedOpcode(opcode) {
472
+ return OPCODES[opcode & 0xff].illegal;
473
+ }
474
+ /** Lookup helper used by tests to verify table coverage. */
475
+ export function opcodeMetadata(opcode) {
476
+ const entry = OPCODES[opcode & 0xff];
477
+ return { mnemonic: entry.mnemonic, undocumented: entry.illegal, size: modeSize(entry.mode) };
478
+ }
@@ -546,9 +546,9 @@ export const graphicsModule = defineToolModule({
546
546
  domain: "graphics",
547
547
  summary: "PETSCII art, sprite workflows, and VIC-II graphics helpers.",
548
548
  resources: [
549
- "c64://specs/vic",
550
- "c64://specs/assembly",
551
- "c64://specs/basic",
549
+ "c64://graphics/vic/spec",
550
+ "c64://assembly/6510-spec",
551
+ "c64://basic/spec",
552
552
  ],
553
553
  prompts: ["graphics-demo", "basic-program", "assembly-program"],
554
554
  defaultTags: ["graphics", "vic"],
@@ -559,10 +559,10 @@ export const graphicsModule = defineToolModule({
559
559
  tools: [
560
560
  {
561
561
  name: "render_sprite",
562
- description: "Display supplied 63-byte sprite data at the requested position and colour by writing memory and patching VIC-II registers directly. See c64://specs/vic for registers.",
562
+ description: "Display supplied 63-byte sprite data at the requested position and colour by writing memory and patching VIC-II registers directly. See c64://graphics/vic/spec for registers.",
563
563
  summary: "Writes sprite data into RAM, updates the sprite pointer table, and patches VIC-II registers to render a sprite preview.",
564
564
  inputSchema: spriteArgsSchema.jsonSchema,
565
- relatedResources: ["c64://specs/vic"],
565
+ relatedResources: ["c64://graphics/vic/spec"],
566
566
  relatedPrompts: ["graphics-demo", "assembly-program"],
567
567
  tags: ["sprite", "assembly", "pal-ntsc"],
568
568
  prerequisites: ["upload_run_asm"],
@@ -587,7 +587,7 @@ export const graphicsModule = defineToolModule({
587
587
  description: "Import an image file, convert it to a VIC-II bitmap, write it into RAM, and display it.",
588
588
  summary: "Decodes a source image, quantizes it into C64 colours, writes bitmap/screen/color RAM, and displays it in hires or multicolor bitmap mode.",
589
589
  inputSchema: generateBitmapArgsSchema.jsonSchema,
590
- relatedResources: ["c64://specs/vic", "c64://context/bootstrap"],
590
+ relatedResources: ["c64://graphics/vic/spec", "c64://guide/bootstrap"],
591
591
  relatedPrompts: ["graphics-demo"],
592
592
  tags: ["bitmap", "vic", "image"],
593
593
  workflowHints: [
@@ -601,10 +601,10 @@ export const graphicsModule = defineToolModule({
601
601
  },
602
602
  {
603
603
  name: "render_petscii_text",
604
- description: "Display PETSCII text with optional border and background colours. See c64://specs/basic.",
604
+ description: "Display PETSCII text with optional border and background colours. See c64://basic/spec.",
605
605
  summary: "Generates a BASIC program that clears the screen, sets colours, and prints text.",
606
606
  inputSchema: renderPetsciiScreenArgsSchema.jsonSchema,
607
- relatedResources: ["c64://specs/basic", "c64://context/bootstrap"],
607
+ relatedResources: ["c64://basic/spec", "c64://guide/bootstrap"],
608
608
  relatedPrompts: ["basic-program", "graphics-demo"],
609
609
  tags: ["basic", "screen"],
610
610
  prerequisites: ["upload_run_basic"],
@@ -626,10 +626,10 @@ export const graphicsModule = defineToolModule({
626
626
  },
627
627
  {
628
628
  name: "render_petscii_art",
629
- description: "Create PETSCII art from prompts, text, or bitmap input, and optionally display it on the C64. Returns metadata including PETSCII codes and glyphs. See c64://specs/basic, c64://specs/vic, and c64://specs/charset.",
629
+ description: "Create PETSCII art from prompts, text, or bitmap input, and optionally display it on the C64. Returns metadata including PETSCII codes and glyphs. See c64://basic/spec, c64://graphics/vic/spec, and c64://graphics/character-set.",
630
630
  summary: "Synthesises PETSCII art, generates a BASIC program with preview metadata (petsciiCodes, glyphs, dimensions), and uploads it unless dry-run is requested.",
631
631
  inputSchema: petsciiImageArgsSchema.jsonSchema,
632
- relatedResources: ["c64://specs/basic", "c64://specs/vic", "c64://specs/charset"],
632
+ relatedResources: ["c64://basic/spec", "c64://graphics/vic/spec", "c64://graphics/character-set"],
633
633
  relatedPrompts: ["graphics-demo", "basic-program"],
634
634
  tags: ["petscii", "basic", "pal-ntsc"],
635
635
  prerequisites: ["upload_run_basic"],