c64bridge 0.9.1 → 0.9.3
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/AGENTS.md +5 -0
- package/README.md +115 -15
- package/data/assembly/assembly-spec.md +1 -1
- package/data/basic/rom-routines.md +269 -0
- package/data/context/bootstrap.md +4 -4
- package/data/context/fast-paths.md +3 -1
- package/data/graphics/petscii-style-guide.md +1 -1
- package/data/graphics/sprite-charset-best-practices.md +14 -13
- package/data/io/cia-spec.md +2 -2
- package/data/{memory/kernal-memory-map.md → kernal/rom-routines.md} +3 -2
- package/data/memory/low-memory-map.md +1 -0
- package/data/memory/memory-map.md +13 -0
- package/data/sound/sid-file-structure.md +5 -5
- package/data/sound/sid-programming-best-practices.md +5 -5
- package/data/vice/vice-binary-monitor-spec.md +5 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/c64Client.js +33 -15
- package/dist/config.js +22 -0
- package/dist/mcp-server.js +17 -5
- package/dist/rag/knowledgeIndex.js +54 -9
- package/dist/rag/resourceUris.js +2 -0
- package/dist/sidwaveCompiler.js +1 -1
- package/dist/tools/input.js +5 -7
- package/dist/tools/memory.js +11 -2
- package/dist/tools/programRunners.js +3 -3
- package/dist/tools/responses.js +14 -1
- package/dist/tools/{assember.js → translation/assembler.js} +56 -162
- package/dist/tools/{basicTokenizer.js → translation/basicTokenizer.js} +1 -1
- package/dist/tools/translation/disassembler.js +150 -0
- package/dist/tools/translation/opcodeInventory.js +126 -0
- package/doc/developer.md +3 -2
- package/doc/reviews/audit.md +143 -0
- package/mcp/resources.json +60 -7
- package/mcp/schemas/c64_input.schema.json +231 -113
- package/mcp/server.json +1 -1
- package/mcp/tools.json +234 -115
- package/mcp.json +8 -4
- package/package.json +12 -8
- package/scripts/c64-cli.mjs +2 -2
- package/scripts/run-coverage.mjs +54 -3
- package/scripts/run-tests.mjs +1 -0
- package/scripts/run-tests.ts +1 -0
- package/scripts/update-readme.ts +1 -0
- package/server.json +3 -3
- package/dist/tools/disassembler.js +0 -478
- /package/dist/tools/{symbolRegistry.js → translation/symbolRegistry.js} +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# C64 Bridge MCP Server Audit
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This audit reviews the C64 Bridge repository as an MCP server for C64 Ultimate/C64U REST devices and VICE emulator control. It covers server initialization, tool/resource/prompt registration, tool schemas and results, device-control safety, VICE integration, C64 Ultimate integration, documentation consistency, and test/coverage architecture.
|
|
6
|
+
|
|
7
|
+
## Assumptions
|
|
8
|
+
|
|
9
|
+
- The local repository is the source of truth for supported behavior.
|
|
10
|
+
- The current branch is `fix/readme`.
|
|
11
|
+
- Pre-existing modified `data/**` files are user-owned unless a finding specifically requires editing them.
|
|
12
|
+
- Real hardware is not required for fixes where mock or emulator tests cover the behavior.
|
|
13
|
+
- Compatibility aliases for removed legacy resource URIs are not required; tests already assert legacy URI rejection.
|
|
14
|
+
|
|
15
|
+
## Methodology
|
|
16
|
+
|
|
17
|
+
1. Inspected repository layout, package scripts, README, AGENTS instructions, skill routing, and MCP generated artifacts.
|
|
18
|
+
2. Inspected `src/mcp-server.ts`, tool registries, schema utilities, knowledge resource registry, VICE backend, C64U backend, and client device-control helpers.
|
|
19
|
+
3. Ran baseline install/build/test/coverage commands.
|
|
20
|
+
4. Scanned for top-level tool schema combinators, stale resource URIs, broad validation gaps, and hidden-result patterns.
|
|
21
|
+
5. Classified findings with the requested severity model and mapped fixes to tests.
|
|
22
|
+
|
|
23
|
+
## Repository Areas Inspected
|
|
24
|
+
|
|
25
|
+
- `src/mcp-server.ts`
|
|
26
|
+
- `src/tools/**`
|
|
27
|
+
- `src/rag/resourceUris.ts`
|
|
28
|
+
- `src/rag/knowledgeIndex.ts`
|
|
29
|
+
- `src/c64Client.ts`
|
|
30
|
+
- `src/device.ts`
|
|
31
|
+
- `src/vice/**`
|
|
32
|
+
- `src/prompts/registry.ts`
|
|
33
|
+
- `scripts/run-coverage.mjs`
|
|
34
|
+
- `scripts/run-tests.ts`
|
|
35
|
+
- `README.md`
|
|
36
|
+
- `AGENTS.md`
|
|
37
|
+
- `.github/skills/**`
|
|
38
|
+
- `mcp/**`
|
|
39
|
+
- `test/**`
|
|
40
|
+
|
|
41
|
+
## MCP Server Design Review
|
|
42
|
+
|
|
43
|
+
The server uses the official TypeScript MCP SDK and registers `resources/list`, `resources/read`, `tools/list`, `tools/call`, `prompts/list`, and `prompts/get` handlers over stdio. Diagnostics are written to stderr/files, leaving stdout for the MCP protocol. Tool errors are returned as tool results with `isError`, which matches MCP expectations for model-visible tool failures.
|
|
44
|
+
|
|
45
|
+
Confirmed non-issue: optional HTTP CLI parsing exists but current `main()` always connects stdio; the README describes stdio as canonical. No fix is required for this audit because no HTTP server path is advertised as the normal agent transport.
|
|
46
|
+
|
|
47
|
+
## Tool Design Review
|
|
48
|
+
|
|
49
|
+
Most public tools are grouped under names such as `c64_program`, `c64_memory`, `c64_config`, and `c64_sound` with an `op` discriminator. The shared `discriminatedUnionSchema` intentionally flattens operations to avoid top-level `oneOf`, which is correct for common MCP/LLM client compatibility.
|
|
50
|
+
|
|
51
|
+
Confirmed issue: `c64_input` is an outlier and still exposes top-level `oneOf` plus `discriminator`. Its metadata also references `c64://specs/assembly` and `c64://specs/memory-map`, which are not registered resources.
|
|
52
|
+
|
|
53
|
+
## Resource URI Design Review
|
|
54
|
+
|
|
55
|
+
Canonical resources use the `c64://` scheme with concise namespaces such as `guide`, `basic`, `assembly`, `graphics`, `sound`, `memory`, `io`, `printer`, `vice`, and `platform`. The registered resource list is stable, discoverable, and documented in README-generated sections. Tests assert old legacy URI forms are rejected.
|
|
56
|
+
|
|
57
|
+
Confirmed non-issue: legacy resource aliases do not need to be preserved because repository tests already reject legacy direct reads.
|
|
58
|
+
|
|
59
|
+
Confirmed issue: tool metadata in `c64_input` points to stale `c64://specs/*` URIs outside the canonical resource set.
|
|
60
|
+
|
|
61
|
+
## Device-Control Safety Review
|
|
62
|
+
|
|
63
|
+
The tool layer generally bounds address lengths, file image parameters, stream names, joystick values, and grouped operations. Memory mutation paths support verification and C64U pause/resume where applicable.
|
|
64
|
+
|
|
65
|
+
Confirmed issue: lower-level client parsing accepts partial numeric literals through `parseInt`, so values such as `$04ZZ` can resolve to `$0004`. Hex byte parsing can also silently truncate through `Buffer.from(value, "hex")`, so malformed data such as `$AAZZ` can become `$AA`. Raw memory helpers do not consistently reject address ranges that cross `$FFFF` before calling a backend.
|
|
66
|
+
|
|
67
|
+
## VICE Integration Review
|
|
68
|
+
|
|
69
|
+
VICE support is separated through `ViceBackend`, `ViceClient`, readiness helpers, and Binary Monitor guidance resources. Tests cover monitor framing, single-client behavior, process launch, readiness, resource get/set, mock and device smoke paths. Joystick simulation is correctly marked VICE-only at operation-platform level.
|
|
70
|
+
|
|
71
|
+
Confirmed issue: `c64_input` schema compatibility affects VICE joystick discoverability in some clients.
|
|
72
|
+
|
|
73
|
+
## C64 Ultimate REST Integration Review
|
|
74
|
+
|
|
75
|
+
C64U REST base URLs are normalized through config and environment handling. Network passwords are sent as `X-Password`. HTTP clients use timeouts. Tests cover mock REST endpoints, password behavior, memory, runners, drives, config, streams, and files.
|
|
76
|
+
|
|
77
|
+
Possible issue requiring external confirmation: local option-list validation for arbitrary C64U configuration values is limited because firmware-provided option inventories are not fully represented in repository data. The current safe approach is to list/read config first and rely on firmware rejection for unknown values. This was not fixed without a reliable local option source.
|
|
78
|
+
|
|
79
|
+
## Error Handling Review
|
|
80
|
+
|
|
81
|
+
Tool errors are normalized through `ToolValidationError`, `ToolExecutionError`, `toolErrorResult`, and `unknownErrorResult`. Tool-level failures are model-visible rather than protocol-level except for unknown tool lookup through registry invocation.
|
|
82
|
+
|
|
83
|
+
Confirmed issue: memory parse failures for partial literals are not reliably raised today, reducing the value of this error-handling layer for device safety.
|
|
84
|
+
|
|
85
|
+
## Schema/Input Validation Review
|
|
86
|
+
|
|
87
|
+
Most grouped tools use flattened schemas with enum-constrained `op`. String, number, boolean, array, object, and optional schema helpers enforce runtime validation.
|
|
88
|
+
|
|
89
|
+
Confirmed issue: `c64_input` still has a top-level `oneOf`.
|
|
90
|
+
|
|
91
|
+
Confirmed issue: C64Client numeric and hex parsing needs stricter validation below the tool layer so public methods and internal raw paths fail safely.
|
|
92
|
+
|
|
93
|
+
## Documentation Review
|
|
94
|
+
|
|
95
|
+
README, AGENTS, skills, and generated `mcp/**` files are broadly consistent with current grouped tool names and canonical resource URIs. README resource lists are generated.
|
|
96
|
+
|
|
97
|
+
Confirmed issue: generated `mcp/tools.json` and schema output inherit the stale `c64_input` resources and top-level `oneOf` until source is fixed and generation reruns.
|
|
98
|
+
|
|
99
|
+
## Test Architecture and Coverage Review
|
|
100
|
+
|
|
101
|
+
The repository has broad unit, integration, MCP harness, VICE mock, and VICE device tests. `npm test` passes. Coverage is intended to be enforced by `scripts/run-coverage.mjs` and `.c8rc.json` with 90% thresholds.
|
|
102
|
+
|
|
103
|
+
Confirmed issue: baseline `npm run coverage` failed after passing shards because the wrapper attempted to copy a missing `coverage/lcov.info` for the VICE device shard.
|
|
104
|
+
|
|
105
|
+
## Findings
|
|
106
|
+
|
|
107
|
+
| ID | Severity | Area | Finding | Evidence | Impact | Recommended fix | Status |
|
|
108
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
109
|
+
| MCP-AUDIT-001 | High | Device-control safety | Numeric and hex parsing can accept partial malformed input, and raw memory access lacks consistent 64 KB range guards. | `src/c64Client.ts` uses `parseInt`; `hexStringToBuffer` and `src/tools/memory.ts` parse hex through `Buffer.from(..., "hex")`; raw reads/writes do not consistently validate range overflow. | Malformed addresses or bytes can target the wrong memory location or write truncated data before a device call fails. | Enforce full-literal parsing, strict hex validation, and range checks before memory reads/writes. Add regression tests. | Planned |
|
|
110
|
+
| MCP-AUDIT-002 | High | MCP schema/resource metadata | `c64_input` exposes top-level `oneOf`/`discriminator` and stale `c64://specs/*` resources. | `src/tools/input.ts`; generated `mcp/tools.json` and `mcp/schemas/c64_input.schema.json`. | Some MCP/LLM clients may fail to call the tool, and metadata points agents to resources that cannot be read. | Use flattened `discriminatedUnionSchema` and canonical resources. Regenerate MCP artifacts and tests. | Planned |
|
|
111
|
+
| MCP-AUDIT-003 | Medium | Coverage architecture | Coverage command fails with `ENOENT` copying `coverage/lcov.info` after VICE device shard. | Baseline `npm run coverage` failed in `scripts/run-coverage.mjs:181`. | Required coverage verification cannot complete reliably even when tests pass. | Make the wrapper robust to Bun temporary LCOV output and add script regression tests. | Planned |
|
|
112
|
+
| MCP-AUDIT-004 | Low | Dependency hygiene | `npm install` reports 1 moderate and 1 high vulnerability. | Baseline install output. | Potential dependency risk, but not enough local evidence to safely upgrade during this audit. | Defer to a dependency/security review with package upgrade testing. | Deferred |
|
|
113
|
+
| MCP-AUDIT-005 | Trivial | Formatting | Some inspected source has indentation inconsistencies. | `src/rag/knowledgeIndex.ts`, `src/tools/memory.ts`. | Cosmetic only. | Defer unless adjacent to required edits. | Deferred |
|
|
114
|
+
|
|
115
|
+
## Fix Plan Mapped To Findings
|
|
116
|
+
|
|
117
|
+
- MCP-AUDIT-001: update strict parsers and range guards in `src/c64Client.ts` and `src/tools/memory.ts`; update `test/c64ClientInvalidInputs.test.mjs` and `test/memory.test.mjs`.
|
|
118
|
+
- MCP-AUDIT-002: update `src/tools/input.ts`; update input/schema tests; regenerate `README.md` and `mcp/**` via `npm run build`.
|
|
119
|
+
- MCP-AUDIT-003: update `scripts/run-coverage.mjs`; update `test/scripts/run-coverage.test.mjs`.
|
|
120
|
+
|
|
121
|
+
## Confirmed Issues
|
|
122
|
+
|
|
123
|
+
- MCP-AUDIT-001
|
|
124
|
+
- MCP-AUDIT-002
|
|
125
|
+
- MCP-AUDIT-003
|
|
126
|
+
|
|
127
|
+
## Possible Issues Requiring External Confirmation
|
|
128
|
+
|
|
129
|
+
- Full local option-list validation for C64U firmware configuration values depends on firmware-provided category/item/value metadata not present in repository evidence.
|
|
130
|
+
|
|
131
|
+
## Non-Issues
|
|
132
|
+
|
|
133
|
+
- Legacy resource URI aliases are intentionally absent.
|
|
134
|
+
- Stdio-first transport is consistent with repository instructions.
|
|
135
|
+
- VICE Binary Monitor reference is present and routed through canonical resource and skills.
|
|
136
|
+
|
|
137
|
+
## Trivialities Intentionally Deferred
|
|
138
|
+
|
|
139
|
+
- Formatting-only indentation cleanup not adjacent to required edits.
|
|
140
|
+
|
|
141
|
+
## Final Status After Implementation
|
|
142
|
+
|
|
143
|
+
Implementation has not yet started. This section will be updated after fixes and final verification.
|
package/mcp/resources.json
CHANGED
|
@@ -522,6 +522,11 @@
|
|
|
522
522
|
},
|
|
523
523
|
"order": 0,
|
|
524
524
|
"relatedResources": [
|
|
525
|
+
"c64://memory/zero-page-and-workspace",
|
|
526
|
+
"c64://basic/rom-routines",
|
|
527
|
+
"c64://kernal/rom-routines",
|
|
528
|
+
"c64://io/spec",
|
|
529
|
+
"c64://io/cia/spec",
|
|
525
530
|
"c64://assembly/6510-spec"
|
|
526
531
|
]
|
|
527
532
|
}
|
|
@@ -557,19 +562,60 @@
|
|
|
557
562
|
"order": 1,
|
|
558
563
|
"relatedResources": [
|
|
559
564
|
"c64://memory/map",
|
|
565
|
+
"c64://basic/rom-routines",
|
|
566
|
+
"c64://kernal/rom-routines",
|
|
560
567
|
"c64://assembly/6510-spec"
|
|
561
568
|
]
|
|
562
569
|
}
|
|
563
570
|
},
|
|
564
571
|
{
|
|
565
|
-
"name": "
|
|
572
|
+
"name": "BASIC ROM Routines Memory Map",
|
|
573
|
+
"uri": "c64://basic/rom-routines",
|
|
574
|
+
"description": "Memory-map-style breakdown of BASIC ROM routines, tables, parser helpers, and entry points.",
|
|
575
|
+
"mimeType": "text/markdown",
|
|
576
|
+
"_meta": {
|
|
577
|
+
"domain": "memory",
|
|
578
|
+
"priority": "reference",
|
|
579
|
+
"summary": "Maps BASIC ROM landmarks, reusable interpreter routines, numeric helpers, string helpers, and C64-specific BASIC continuation entries.",
|
|
580
|
+
"prompts": [
|
|
581
|
+
"memory-debug",
|
|
582
|
+
"assembly-program",
|
|
583
|
+
"basic-program"
|
|
584
|
+
],
|
|
585
|
+
"tools": [
|
|
586
|
+
"read",
|
|
587
|
+
"verify_and_write_memory"
|
|
588
|
+
],
|
|
589
|
+
"tags": [
|
|
590
|
+
"memory",
|
|
591
|
+
"basic",
|
|
592
|
+
"rom"
|
|
593
|
+
],
|
|
594
|
+
"bundle": {
|
|
595
|
+
"id": "memory",
|
|
596
|
+
"title": "Memory & I/O Reference",
|
|
597
|
+
"summary": "Critical tables for RAM layout, zero-page vectors, and peripheral I/O registers.",
|
|
598
|
+
"order": 5
|
|
599
|
+
},
|
|
600
|
+
"order": 2,
|
|
601
|
+
"relatedResources": [
|
|
602
|
+
"c64://memory/map",
|
|
603
|
+
"c64://memory/zero-page-and-workspace",
|
|
604
|
+
"c64://kernal/rom-routines",
|
|
605
|
+
"c64://basic/spec",
|
|
606
|
+
"c64://assembly/6510-spec"
|
|
607
|
+
]
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"name": "KERNAL ROM Routines Memory Map",
|
|
566
612
|
"uri": "c64://kernal/rom-routines",
|
|
567
|
-
"description": "
|
|
613
|
+
"description": "Memory-map-style breakdown of KERNAL ROM routines, vectors, tables, and entry points.",
|
|
568
614
|
"mimeType": "text/markdown",
|
|
569
615
|
"_meta": {
|
|
570
616
|
"domain": "memory",
|
|
571
617
|
"priority": "reference",
|
|
572
|
-
"summary": "
|
|
618
|
+
"summary": "Maps KERNAL ROM vectors, jump table entries, internal routines, serial/tape/screen services, and reset handlers.",
|
|
573
619
|
"prompts": [
|
|
574
620
|
"memory-debug",
|
|
575
621
|
"assembly-program"
|
|
@@ -588,9 +634,12 @@
|
|
|
588
634
|
"summary": "Critical tables for RAM layout, zero-page vectors, and peripheral I/O registers.",
|
|
589
635
|
"order": 5
|
|
590
636
|
},
|
|
591
|
-
"order":
|
|
637
|
+
"order": 3,
|
|
592
638
|
"relatedResources": [
|
|
593
639
|
"c64://memory/map",
|
|
640
|
+
"c64://memory/zero-page-and-workspace",
|
|
641
|
+
"c64://basic/rom-routines",
|
|
642
|
+
"c64://io/spec",
|
|
594
643
|
"c64://assembly/6510-spec"
|
|
595
644
|
]
|
|
596
645
|
}
|
|
@@ -625,9 +674,11 @@
|
|
|
625
674
|
"summary": "Critical tables for RAM layout, zero-page vectors, and peripheral I/O registers.",
|
|
626
675
|
"order": 5
|
|
627
676
|
},
|
|
628
|
-
"order":
|
|
677
|
+
"order": 4,
|
|
629
678
|
"relatedResources": [
|
|
630
679
|
"c64://memory/map",
|
|
680
|
+
"c64://memory/zero-page-and-workspace",
|
|
681
|
+
"c64://io/cia/spec",
|
|
631
682
|
"c64://assembly/6510-spec"
|
|
632
683
|
]
|
|
633
684
|
}
|
|
@@ -661,10 +712,11 @@
|
|
|
661
712
|
"summary": "Critical tables for RAM layout, zero-page vectors, and peripheral I/O registers.",
|
|
662
713
|
"order": 5
|
|
663
714
|
},
|
|
664
|
-
"order":
|
|
715
|
+
"order": 5,
|
|
665
716
|
"relatedResources": [
|
|
666
717
|
"c64://io/spec",
|
|
667
|
-
"c64://memory/map"
|
|
718
|
+
"c64://memory/map",
|
|
719
|
+
"c64://memory/zero-page-and-workspace"
|
|
668
720
|
]
|
|
669
721
|
}
|
|
670
722
|
},
|
|
@@ -919,6 +971,7 @@
|
|
|
919
971
|
"c64://graphics/sprite-charset/best-practices",
|
|
920
972
|
"c64://memory/map",
|
|
921
973
|
"c64://memory/zero-page-and-workspace",
|
|
974
|
+
"c64://basic/rom-routines",
|
|
922
975
|
"c64://kernal/rom-routines",
|
|
923
976
|
"c64://io/spec",
|
|
924
977
|
"c64://io/cia/spec",
|
|
@@ -1,136 +1,254 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "object",
|
|
3
|
-
"
|
|
4
|
-
|
|
3
|
+
"properties": {
|
|
4
|
+
"op": {
|
|
5
|
+
"type": "string",
|
|
6
|
+
"enum": [
|
|
7
|
+
"write_text",
|
|
8
|
+
"key",
|
|
9
|
+
"joystick"
|
|
10
|
+
],
|
|
11
|
+
"description": "Selects the operation."
|
|
12
|
+
},
|
|
13
|
+
"text": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
16
|
+
"minLength": 1,
|
|
17
|
+
"maxLength": 512
|
|
18
|
+
},
|
|
19
|
+
"delayMs": {
|
|
20
|
+
"type": [
|
|
21
|
+
"integer",
|
|
22
|
+
"null"
|
|
23
|
+
],
|
|
24
|
+
"description": "Delay in ms after sending (default 0).",
|
|
25
|
+
"minimum": 0,
|
|
26
|
+
"maximum": 10000,
|
|
27
|
+
"default": 0
|
|
28
|
+
},
|
|
29
|
+
"key": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
32
|
+
"minLength": 1,
|
|
33
|
+
"maxLength": 32
|
|
34
|
+
},
|
|
35
|
+
"durationMs": {
|
|
36
|
+
"type": [
|
|
37
|
+
"integer",
|
|
38
|
+
"null"
|
|
39
|
+
],
|
|
40
|
+
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
41
|
+
"minimum": 0,
|
|
42
|
+
"maximum": 5000,
|
|
43
|
+
"default": 0
|
|
44
|
+
},
|
|
45
|
+
"count": {
|
|
46
|
+
"type": [
|
|
47
|
+
"integer",
|
|
48
|
+
"null"
|
|
49
|
+
],
|
|
50
|
+
"description": "Number of times to press the key (default 1).",
|
|
51
|
+
"minimum": 1,
|
|
52
|
+
"maximum": 100,
|
|
53
|
+
"default": 1
|
|
54
|
+
},
|
|
55
|
+
"port": {
|
|
56
|
+
"type": "integer",
|
|
57
|
+
"description": "Joystick port (1 = $DC01, 2 = $DC00).",
|
|
58
|
+
"minimum": 1,
|
|
59
|
+
"maximum": 2
|
|
60
|
+
},
|
|
61
|
+
"controls": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"description": "List of controls to activate simultaneously.",
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"description": "Control to activate.",
|
|
67
|
+
"enum": [
|
|
68
|
+
"up",
|
|
69
|
+
"down",
|
|
70
|
+
"left",
|
|
71
|
+
"right",
|
|
72
|
+
"fire"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"minItems": 0
|
|
76
|
+
},
|
|
77
|
+
"action": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "press = hold until a release call; release = restore all bits; tap = press then release after durationMs.",
|
|
80
|
+
"enum": [
|
|
81
|
+
"press",
|
|
82
|
+
"release",
|
|
83
|
+
"tap"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"required": [
|
|
88
|
+
"op"
|
|
89
|
+
],
|
|
90
|
+
"description": "Input operations: write_text, key, joystick.\n\nOperations:\n- write_text: Send a text string to the keyboard buffer, with PETSCII token expansion. Required inputs: text. Optional inputs: delayMs.\n- key: Tap a single key or hold it for a duration. Required inputs: key. Optional inputs: durationMs, count.\n- joystick: Simulate joystick input by writing directly to CIA1 Port A/B registers. Required inputs: port, controls, action. Optional inputs: durationMs.",
|
|
91
|
+
"additionalProperties": false,
|
|
92
|
+
"x-c64bridge-operations": [
|
|
5
93
|
{
|
|
6
|
-
"
|
|
94
|
+
"op": "write_text",
|
|
7
95
|
"description": "Send a text string to the keyboard buffer, with PETSCII token expansion.",
|
|
8
|
-
"properties": {
|
|
9
|
-
"op": {
|
|
10
|
-
"const": "write_text"
|
|
11
|
-
},
|
|
12
|
-
"text": {
|
|
13
|
-
"type": "string",
|
|
14
|
-
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
15
|
-
"minLength": 1,
|
|
16
|
-
"maxLength": 512
|
|
17
|
-
},
|
|
18
|
-
"delayMs": {
|
|
19
|
-
"type": [
|
|
20
|
-
"integer",
|
|
21
|
-
"null"
|
|
22
|
-
],
|
|
23
|
-
"description": "Delay in ms after sending (default 0).",
|
|
24
|
-
"minimum": 0,
|
|
25
|
-
"maximum": 10000,
|
|
26
|
-
"default": 0
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
96
|
"required": [
|
|
30
|
-
"op",
|
|
31
97
|
"text"
|
|
32
98
|
],
|
|
33
|
-
"
|
|
99
|
+
"optional": [
|
|
100
|
+
"delayMs"
|
|
101
|
+
],
|
|
102
|
+
"inputSchema": {
|
|
103
|
+
"type": "object",
|
|
104
|
+
"description": "Send a text string to the keyboard buffer, with PETSCII token expansion.",
|
|
105
|
+
"properties": {
|
|
106
|
+
"op": {
|
|
107
|
+
"const": "write_text"
|
|
108
|
+
},
|
|
109
|
+
"text": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
112
|
+
"minLength": 1,
|
|
113
|
+
"maxLength": 512
|
|
114
|
+
},
|
|
115
|
+
"delayMs": {
|
|
116
|
+
"type": [
|
|
117
|
+
"integer",
|
|
118
|
+
"null"
|
|
119
|
+
],
|
|
120
|
+
"description": "Delay in ms after sending (default 0).",
|
|
121
|
+
"minimum": 0,
|
|
122
|
+
"maximum": 10000,
|
|
123
|
+
"default": 0
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"required": [
|
|
127
|
+
"op",
|
|
128
|
+
"text"
|
|
129
|
+
],
|
|
130
|
+
"additionalProperties": false
|
|
131
|
+
}
|
|
34
132
|
},
|
|
35
133
|
{
|
|
36
|
-
"
|
|
134
|
+
"op": "key",
|
|
37
135
|
"description": "Tap a single key or hold it for a duration.",
|
|
38
|
-
"properties": {
|
|
39
|
-
"op": {
|
|
40
|
-
"const": "key"
|
|
41
|
-
},
|
|
42
|
-
"key": {
|
|
43
|
-
"type": "string",
|
|
44
|
-
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
45
|
-
"minLength": 1,
|
|
46
|
-
"maxLength": 32
|
|
47
|
-
},
|
|
48
|
-
"durationMs": {
|
|
49
|
-
"type": [
|
|
50
|
-
"integer",
|
|
51
|
-
"null"
|
|
52
|
-
],
|
|
53
|
-
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
54
|
-
"minimum": 0,
|
|
55
|
-
"maximum": 5000,
|
|
56
|
-
"default": 0
|
|
57
|
-
},
|
|
58
|
-
"count": {
|
|
59
|
-
"type": [
|
|
60
|
-
"integer",
|
|
61
|
-
"null"
|
|
62
|
-
],
|
|
63
|
-
"description": "Number of times to press the key (default 1).",
|
|
64
|
-
"minimum": 1,
|
|
65
|
-
"maximum": 100,
|
|
66
|
-
"default": 1
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
136
|
"required": [
|
|
70
|
-
"op",
|
|
71
137
|
"key"
|
|
72
138
|
],
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
"minimum": 1,
|
|
86
|
-
"maximum": 2
|
|
87
|
-
},
|
|
88
|
-
"controls": {
|
|
89
|
-
"type": "array",
|
|
90
|
-
"description": "List of controls to activate simultaneously.",
|
|
91
|
-
"items": {
|
|
139
|
+
"optional": [
|
|
140
|
+
"durationMs",
|
|
141
|
+
"count"
|
|
142
|
+
],
|
|
143
|
+
"inputSchema": {
|
|
144
|
+
"type": "object",
|
|
145
|
+
"description": "Tap a single key or hold it for a duration.",
|
|
146
|
+
"properties": {
|
|
147
|
+
"op": {
|
|
148
|
+
"const": "key"
|
|
149
|
+
},
|
|
150
|
+
"key": {
|
|
92
151
|
"type": "string",
|
|
93
|
-
"description": "
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
"down",
|
|
97
|
-
"left",
|
|
98
|
-
"right",
|
|
99
|
-
"fire"
|
|
100
|
-
]
|
|
152
|
+
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
153
|
+
"minLength": 1,
|
|
154
|
+
"maxLength": 32
|
|
101
155
|
},
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
|
|
156
|
+
"durationMs": {
|
|
157
|
+
"type": [
|
|
158
|
+
"integer",
|
|
159
|
+
"null"
|
|
160
|
+
],
|
|
161
|
+
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
162
|
+
"minimum": 0,
|
|
163
|
+
"maximum": 5000,
|
|
164
|
+
"default": 0
|
|
165
|
+
},
|
|
166
|
+
"count": {
|
|
167
|
+
"type": [
|
|
168
|
+
"integer",
|
|
169
|
+
"null"
|
|
170
|
+
],
|
|
171
|
+
"description": "Number of times to press the key (default 1).",
|
|
172
|
+
"minimum": 1,
|
|
173
|
+
"maximum": 100,
|
|
174
|
+
"default": 1
|
|
175
|
+
}
|
|
112
176
|
},
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
177
|
+
"required": [
|
|
178
|
+
"op",
|
|
179
|
+
"key"
|
|
180
|
+
],
|
|
181
|
+
"additionalProperties": false
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"op": "joystick",
|
|
186
|
+
"description": "Simulate joystick input by writing directly to CIA1 Port A/B registers.",
|
|
124
187
|
"required": [
|
|
125
|
-
"op",
|
|
126
188
|
"port",
|
|
127
189
|
"controls",
|
|
128
190
|
"action"
|
|
129
191
|
],
|
|
130
|
-
"
|
|
192
|
+
"optional": [
|
|
193
|
+
"durationMs"
|
|
194
|
+
],
|
|
195
|
+
"inputSchema": {
|
|
196
|
+
"type": "object",
|
|
197
|
+
"description": "Simulate joystick input by writing directly to CIA1 Port A/B registers.",
|
|
198
|
+
"properties": {
|
|
199
|
+
"op": {
|
|
200
|
+
"const": "joystick"
|
|
201
|
+
},
|
|
202
|
+
"port": {
|
|
203
|
+
"type": "integer",
|
|
204
|
+
"description": "Joystick port (1 = $DC01, 2 = $DC00).",
|
|
205
|
+
"minimum": 1,
|
|
206
|
+
"maximum": 2
|
|
207
|
+
},
|
|
208
|
+
"controls": {
|
|
209
|
+
"type": "array",
|
|
210
|
+
"description": "List of controls to activate simultaneously.",
|
|
211
|
+
"items": {
|
|
212
|
+
"type": "string",
|
|
213
|
+
"description": "Control to activate.",
|
|
214
|
+
"enum": [
|
|
215
|
+
"up",
|
|
216
|
+
"down",
|
|
217
|
+
"left",
|
|
218
|
+
"right",
|
|
219
|
+
"fire"
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
"minItems": 0
|
|
223
|
+
},
|
|
224
|
+
"action": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"description": "press = hold until a release call; release = restore all bits; tap = press then release after durationMs.",
|
|
227
|
+
"enum": [
|
|
228
|
+
"press",
|
|
229
|
+
"release",
|
|
230
|
+
"tap"
|
|
231
|
+
]
|
|
232
|
+
},
|
|
233
|
+
"durationMs": {
|
|
234
|
+
"type": [
|
|
235
|
+
"integer",
|
|
236
|
+
"null"
|
|
237
|
+
],
|
|
238
|
+
"description": "Duration to hold for tap action in ms (default 80).",
|
|
239
|
+
"minimum": 10,
|
|
240
|
+
"maximum": 5000,
|
|
241
|
+
"default": 80
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"required": [
|
|
245
|
+
"op",
|
|
246
|
+
"port",
|
|
247
|
+
"controls",
|
|
248
|
+
"action"
|
|
249
|
+
],
|
|
250
|
+
"additionalProperties": false
|
|
251
|
+
}
|
|
131
252
|
}
|
|
132
|
-
]
|
|
133
|
-
"discriminator": {
|
|
134
|
-
"propertyName": "op"
|
|
135
|
-
}
|
|
253
|
+
]
|
|
136
254
|
}
|