c64bridge 0.9.2 → 1.0.0

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 (58) hide show
  1. package/AGENTS.md +24 -3
  2. package/README.md +271 -161
  3. package/data/basic/rom-routines.md +269 -0
  4. package/data/context/bootstrap.md +1 -1
  5. package/data/io/cia-spec.md +2 -2
  6. package/data/{memory/kernal-memory-map.md → kernal/rom-routines.md} +3 -2
  7. package/data/memory/low-memory-map.md +1 -0
  8. package/data/memory/memory-map.md +13 -0
  9. package/dist/.tsbuildinfo +1 -1
  10. package/dist/c64Client.js +127 -12
  11. package/dist/config.js +34 -8
  12. package/dist/device.js +75 -45
  13. package/dist/mcp-server.js +28 -8
  14. package/dist/platform.js +13 -2
  15. package/dist/rag/knowledgeIndex.js +54 -9
  16. package/dist/rag/resourceUris.js +2 -0
  17. package/dist/tools/audio.js +1 -1
  18. package/dist/tools/developer.js +6 -6
  19. package/dist/tools/graphics.js +4 -4
  20. package/dist/tools/input.js +129 -12
  21. package/dist/tools/machineControl.js +85 -6
  22. package/dist/tools/memory.js +1 -1
  23. package/dist/tools/meta/index.js +1 -1
  24. package/dist/tools/programRunners.js +5 -5
  25. package/dist/tools/rag.js +1 -1
  26. package/dist/tools/registry/batch.js +1 -1
  27. package/dist/tools/registry/config.js +5 -5
  28. package/dist/tools/registry/disk.js +2 -2
  29. package/dist/tools/registry/drive.js +2 -2
  30. package/dist/tools/registry/graphics.js +2 -2
  31. package/dist/tools/registry/memory.js +2 -2
  32. package/dist/tools/registry/platform.js +7 -5
  33. package/dist/tools/registry/program.js +5 -5
  34. package/dist/tools/registry/rag.js +1 -1
  35. package/dist/tools/registry/sound.js +4 -4
  36. package/dist/tools/registry/system.js +13 -3
  37. package/dist/tools/storage.js +1 -1
  38. package/doc/c64u/c64-openapi.yaml +1130 -774
  39. package/doc/developer.md +3 -2
  40. package/doc/u2/u2-openapi.yaml +1192 -0
  41. package/generated/c64/index.js +142 -9
  42. package/generated/openapi/c64u/index.js +1117 -0
  43. package/generated/openapi/u2/index.js +929 -0
  44. package/mcp/resources.json +60 -7
  45. package/mcp/schemas/c64_graphics.schema.json +3 -3
  46. package/mcp/schemas/c64_input.schema.json +247 -6
  47. package/mcp/schemas/c64_memory.schema.json +3 -3
  48. package/mcp/schemas/c64_program.schema.json +3 -3
  49. package/mcp/schemas/c64_select_backend.schema.json +2 -0
  50. package/mcp/schemas/c64_system.schema.json +41 -1
  51. package/mcp/server.json +1 -1
  52. package/mcp/tools.json +382 -41
  53. package/mcp.json +21 -5
  54. package/package.json +14 -8
  55. package/scripts/mockC64Server.mjs +40 -0
  56. package/scripts/prepare-release.mjs +13 -2
  57. package/scripts/update-readme.ts +19 -30
  58. package/server.json +2 -2
@@ -1,30 +1,143 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
- title: Ultimate 64 REST API
4
- version: "1.0.0"
5
- summary: REST interface exposed by Ultimate 64 / 1541 Ultimate firmware ≥ 3.11.
3
+ title: Ultimate 64 Elite REST API
4
+ version: 3.15-alpha
5
+ summary: REST API exposed by the Ultimate 64 Elite 3.15 alpha firmware.
6
6
  description: |
7
- This OpenAPI document captures the public HTTP interface described in the
8
- official Ultimate 64 REST API documentation at
9
- https://1541u-documentation.readthedocs.io/en/latest/api/api_calls.html.
10
- Responses always include an `errors` array unless noted. When a network
11
- password is configured, clients must supply the `X-Password` header on every
12
- request. Example payloads were captured against a local Ultimate 64 Elite
13
- reachable as `http://c64u` running firmware 3.12a.
7
+ Source-derived OpenAPI description for the HTTP API implemented in
8
+ `/software/api` of the 1541ultimate firmware tree.
9
+
10
+ The firmware exposes a single `v1` API version. JSON responses include an
11
+ `errors` array. Binary endpoints return `application/octet-stream` on
12
+ success and JSON with `errors` when the request cannot be completed.
13
+
14
+ If a network password is configured on the device, every API request must
15
+ include the `X-Password` header. If no network password is configured, the
16
+ same endpoints are available without the header.
14
17
  servers:
15
- - url: http://c64u
16
- description: Ultimate 64 on the local network (example fixture)
18
+ - url: http://u64
19
+ description: Ultimate 64 Elite on the local network
20
+ - url: http://{host}
21
+ description: Custom Ultimate host or IP address
22
+ variables:
23
+ host:
24
+ default: u64
25
+ tags:
26
+ - name: System
27
+ - name: Runners
28
+ - name: Configuration
29
+ - name: Machine
30
+ - name: Drives
31
+ - name: Streams
32
+ - name: Files
33
+ - name: Input
34
+ security:
35
+ - NetworkPassword: []
36
+ - {}
17
37
  components:
18
38
  securitySchemes:
19
39
  NetworkPassword:
20
40
  type: apiKey
21
41
  in: header
22
42
  name: X-Password
43
+ description: Required only when the device network password is configured.
44
+ parameters:
45
+ Category:
46
+ name: category
47
+ in: path
48
+ required: true
49
+ schema:
50
+ type: string
51
+ description: Configuration category name or firmware wildcard pattern.
52
+ Item:
53
+ name: item
54
+ in: path
55
+ required: true
56
+ schema:
57
+ type: string
58
+ description: Configuration item name or firmware wildcard pattern.
59
+ Setting:
60
+ name: setting
61
+ in: path
62
+ required: true
63
+ schema:
64
+ type: string
65
+ description: Configuration value carried as the third path segment.
66
+ Drive:
67
+ name: drive
68
+ in: path
69
+ required: true
70
+ schema:
71
+ type: string
72
+ enum: [a, b]
73
+ description: Internal drive slot.
74
+ FilePath:
75
+ name: path
76
+ in: path
77
+ required: true
78
+ allowReserved: true
79
+ schema:
80
+ type: string
81
+ description: Device filesystem path below `/v1/files/`; URL-encode reserved characters.
82
+ Address:
83
+ name: address
84
+ in: query
85
+ required: true
86
+ schema:
87
+ type: string
88
+ pattern: "^(0x)?[0-9A-Fa-f]{1,4}$"
89
+ description: C64 address in hexadecimal.
90
+ Length:
91
+ name: length
92
+ in: query
93
+ required: false
94
+ schema:
95
+ type: integer
96
+ minimum: 0
97
+ maximum: 65536
98
+ default: 256
99
+ FileQuery:
100
+ name: file
101
+ in: query
102
+ required: true
103
+ schema:
104
+ type: string
105
+ description: Absolute or device-relative file path.
106
+ SongNumber:
107
+ name: songnr
108
+ in: query
109
+ required: false
110
+ schema:
111
+ type: integer
112
+ minimum: 0
113
+ default: 0
114
+ DiskName:
115
+ name: diskname
116
+ in: query
117
+ required: false
118
+ schema:
119
+ type: string
120
+ D64Tracks:
121
+ name: tracks
122
+ in: query
123
+ required: false
124
+ schema:
125
+ type: integer
126
+ minimum: 35
127
+ maximum: 41
128
+ default: 35
129
+ DnpTracks:
130
+ name: tracks
131
+ in: query
132
+ required: true
133
+ schema:
134
+ type: integer
135
+ minimum: 1
136
+ maximum: 255
23
137
  schemas:
24
- ErrorResponse:
138
+ ErrorList:
25
139
  type: object
26
- required:
27
- - errors
140
+ required: [errors]
28
141
  properties:
29
142
  errors:
30
143
  type: array
@@ -32,116 +145,159 @@ components:
32
145
  type: string
33
146
  VersionResponse:
34
147
  allOf:
35
- - $ref: '#/components/schemas/ErrorResponse'
148
+ - $ref: "#/components/schemas/ErrorList"
36
149
  - type: object
37
- required:
38
- - version
150
+ required: [version]
39
151
  properties:
40
152
  version:
41
153
  type: string
154
+ example: "0.1"
42
155
  InfoResponse:
43
156
  allOf:
44
- - $ref: '#/components/schemas/ErrorResponse'
157
+ - $ref: "#/components/schemas/ErrorList"
45
158
  - type: object
159
+ required: [product, firmware_version, fpga_version, hostname]
46
160
  properties:
47
161
  product:
48
162
  type: string
163
+ example: Ultimate 64 Elite
49
164
  firmware_version:
50
165
  type: string
166
+ example: 3.15 alpha
51
167
  fpga_version:
52
168
  type: string
169
+ example: "122"
53
170
  core_version:
54
171
  type: string
55
- description: Present on Ultimate 64 devices.
172
+ description: Present on Ultimate 64-class firmware builds.
173
+ example: 1.4B
56
174
  hostname:
57
175
  type: string
58
176
  unique_id:
59
177
  type: string
60
- ConfigListResponse:
178
+ ConfigCategoriesResponse:
61
179
  allOf:
62
- - $ref: '#/components/schemas/ErrorResponse'
180
+ - $ref: "#/components/schemas/ErrorList"
63
181
  - type: object
182
+ required: [categories]
64
183
  properties:
65
184
  categories:
66
185
  type: array
67
186
  items:
68
187
  type: string
188
+ ConfigValue:
189
+ oneOf:
190
+ - type: string
191
+ - type: integer
192
+ ConfigItemDetail:
193
+ type: object
194
+ required: [current]
195
+ properties:
196
+ current:
197
+ $ref: "#/components/schemas/ConfigValue"
198
+ values:
199
+ type: array
200
+ items:
201
+ type: string
202
+ presets:
203
+ type: array
204
+ items:
205
+ type: string
206
+ min:
207
+ type: integer
208
+ max:
209
+ type: integer
210
+ format:
211
+ type: string
212
+ default:
213
+ $ref: "#/components/schemas/ConfigValue"
214
+ additionalProperties: true
69
215
  ConfigCategoryResponse:
70
216
  allOf:
71
- - $ref: '#/components/schemas/ErrorResponse'
72
- - type: object
73
- additionalProperties:
74
- type: object
75
- ConfigItemResponse:
76
- allOf:
77
- - $ref: '#/components/schemas/ErrorResponse'
217
+ - $ref: "#/components/schemas/ErrorList"
78
218
  - type: object
79
219
  additionalProperties:
80
220
  type: object
81
- MemoryReadJson:
221
+ additionalProperties:
222
+ oneOf:
223
+ - $ref: "#/components/schemas/ConfigValue"
224
+ - $ref: "#/components/schemas/ConfigItemDetail"
225
+ ConfigBatchUpdate:
226
+ type: object
227
+ additionalProperties:
228
+ type: object
229
+ additionalProperties:
230
+ $ref: "#/components/schemas/ConfigValue"
231
+ example:
232
+ Drive A Settings:
233
+ Drive: Enabled
234
+ Drive Bus ID: 8
235
+ ConfigStoreListResponse:
82
236
  allOf:
83
- - $ref: '#/components/schemas/ErrorResponse'
237
+ - $ref: "#/components/schemas/ErrorList"
84
238
  - type: object
85
239
  properties:
86
- data:
87
- oneOf:
88
- - type: string
89
- description: Base64 encoded bytes.
90
- - type: array
91
- items:
92
- type: integer
93
- format: int32
94
- minimum: 0
95
- maximum: 255
96
- MemoryDebugResponse:
240
+ loaded:
241
+ type: array
242
+ items:
243
+ type: string
244
+ written:
245
+ type: array
246
+ items:
247
+ type: string
248
+ reset:
249
+ type: array
250
+ items:
251
+ type: string
252
+ ActionResponse:
97
253
  allOf:
98
- - $ref: '#/components/schemas/ErrorResponse'
254
+ - $ref: "#/components/schemas/ErrorList"
99
255
  - type: object
100
- required:
101
- - value
102
- properties:
103
- value:
104
- type: string
105
- description: Hex string read from $D7FF.
256
+ additionalProperties: true
257
+ DriveInfo:
258
+ type: object
259
+ properties:
260
+ enabled:
261
+ type: boolean
262
+ bus_id:
263
+ type: integer
264
+ type:
265
+ type: string
266
+ rom:
267
+ type: string
268
+ image_file:
269
+ type: string
270
+ image_path:
271
+ type: string
272
+ last_error:
273
+ type: string
274
+ partitions:
275
+ type: array
276
+ items:
277
+ type: object
278
+ properties:
279
+ id:
280
+ type: integer
281
+ path:
282
+ type: string
283
+ additionalProperties: true
106
284
  DriveListResponse:
107
285
  allOf:
108
- - $ref: '#/components/schemas/ErrorResponse'
286
+ - $ref: "#/components/schemas/ErrorList"
109
287
  - type: object
288
+ required: [drives]
110
289
  properties:
111
290
  drives:
112
291
  type: array
113
292
  items:
114
293
  type: object
115
294
  additionalProperties:
116
- type: object
117
- properties:
118
- enabled:
119
- type: boolean
120
- bus_id:
121
- type: integer
122
- type:
123
- type: string
124
- rom:
125
- type: string
126
- image_file:
127
- type: string
128
- image_path:
129
- type: string
130
- last_error:
131
- type: string
132
- partitions:
133
- type: array
134
- items:
135
- type: object
136
- properties:
137
- id:
138
- type: integer
139
- path:
140
- type: string
295
+ $ref: "#/components/schemas/DriveInfo"
141
296
  FileInfoResponse:
142
297
  allOf:
143
- - $ref: '#/components/schemas/ErrorResponse'
298
+ - $ref: "#/components/schemas/ErrorList"
144
299
  - type: object
300
+ required: [files]
145
301
  properties:
146
302
  files:
147
303
  type: object
@@ -155,956 +311,1156 @@ components:
155
311
  extension:
156
312
  type: string
157
313
  additionalProperties: true
158
- MachineActionResponse:
314
+ InputStateResponse:
159
315
  allOf:
160
- - $ref: '#/components/schemas/ErrorResponse'
161
- RunnerActionResponse:
162
- allOf:
163
- - $ref: '#/components/schemas/ErrorResponse'
164
- security:
165
- - NetworkPassword: []
316
+ - $ref: "#/components/schemas/ErrorList"
317
+ - type: object
318
+ required: [keyboard, joysticks]
319
+ properties:
320
+ keyboard:
321
+ type: object
322
+ required: [inputs]
323
+ properties:
324
+ inputs:
325
+ type: array
326
+ items:
327
+ $ref: "#/components/schemas/KeyboardInput"
328
+ joysticks:
329
+ type: array
330
+ items:
331
+ type: object
332
+ required: [port, inputs]
333
+ properties:
334
+ port:
335
+ type: integer
336
+ enum: [1, 2]
337
+ inputs:
338
+ type: array
339
+ items:
340
+ $ref: "#/components/schemas/JoystickInput"
341
+ InputBatch:
342
+ type: object
343
+ required: [events]
344
+ properties:
345
+ events:
346
+ type: array
347
+ minItems: 1
348
+ maxItems: 64
349
+ items:
350
+ oneOf:
351
+ - $ref: "#/components/schemas/KeyboardEvent"
352
+ - $ref: "#/components/schemas/JoystickEvent"
353
+ - $ref: "#/components/schemas/ReleaseAllEvent"
354
+ KeyboardEvent:
355
+ type: object
356
+ required: [kind, inputs, transition]
357
+ properties:
358
+ kind:
359
+ const: keyboard
360
+ inputs:
361
+ type: array
362
+ minItems: 1
363
+ maxItems: 8
364
+ items:
365
+ $ref: "#/components/schemas/KeyboardInput"
366
+ transition:
367
+ $ref: "#/components/schemas/InputTransition"
368
+ additionalProperties: false
369
+ JoystickEvent:
370
+ type: object
371
+ required: [kind, port, inputs, transition]
372
+ properties:
373
+ kind:
374
+ const: joystick
375
+ port:
376
+ type: integer
377
+ enum: [1, 2]
378
+ inputs:
379
+ type: array
380
+ minItems: 1
381
+ maxItems: 7
382
+ items:
383
+ $ref: "#/components/schemas/JoystickInput"
384
+ transition:
385
+ $ref: "#/components/schemas/InputTransition"
386
+ additionalProperties: false
387
+ ReleaseAllEvent:
388
+ type: object
389
+ required: [kind]
390
+ properties:
391
+ kind:
392
+ const: release_all
393
+ additionalProperties: false
394
+ InputTransition:
395
+ type: string
396
+ enum: [press, release, tap]
397
+ KeyboardInput:
398
+ type: string
399
+ enum:
400
+ - inst_del
401
+ - return
402
+ - cursor_left_right
403
+ - f7
404
+ - f1
405
+ - f3
406
+ - f5
407
+ - cursor_up_down
408
+ - "0"
409
+ - "1"
410
+ - "2"
411
+ - "3"
412
+ - "4"
413
+ - "5"
414
+ - "6"
415
+ - "7"
416
+ - "8"
417
+ - "9"
418
+ - a
419
+ - b
420
+ - c
421
+ - d
422
+ - e
423
+ - f
424
+ - g
425
+ - h
426
+ - i
427
+ - j
428
+ - k
429
+ - l
430
+ - m
431
+ - n
432
+ - o
433
+ - p
434
+ - q
435
+ - r
436
+ - s
437
+ - t
438
+ - u
439
+ - v
440
+ - w
441
+ - x
442
+ - y
443
+ - z
444
+ - left_shift
445
+ - right_shift
446
+ - plus
447
+ - minus
448
+ - period
449
+ - colon
450
+ - at
451
+ - comma
452
+ - pound
453
+ - star
454
+ - semicolon
455
+ - clr_home
456
+ - equals
457
+ - arrow_up
458
+ - slash
459
+ - arrow_left
460
+ - ctrl
461
+ - space
462
+ - commodore
463
+ - run_stop
464
+ - restore
465
+ JoystickInput:
466
+ type: string
467
+ enum: [up, down, left, right, fire, fire2, fire3]
468
+ requestBodies:
469
+ BinaryUpload:
470
+ required: true
471
+ content:
472
+ multipart/form-data:
473
+ schema:
474
+ type: object
475
+ required: [file]
476
+ properties:
477
+ file:
478
+ type: string
479
+ format: binary
480
+ application/octet-stream:
481
+ schema:
482
+ type: string
483
+ format: binary
484
+ SidUpload:
485
+ required: true
486
+ content:
487
+ multipart/form-data:
488
+ schema:
489
+ type: object
490
+ required: [file]
491
+ properties:
492
+ file:
493
+ type: array
494
+ minItems: 1
495
+ maxItems: 2
496
+ items:
497
+ type: string
498
+ format: binary
499
+ description: First file is the SID; optional second file is SID song-length data.
500
+ responses:
501
+ JsonOk:
502
+ description: Successful JSON response.
503
+ content:
504
+ application/json:
505
+ schema:
506
+ $ref: "#/components/schemas/ActionResponse"
507
+ BadRequest:
508
+ description: Request could not be parsed or failed validation.
509
+ content:
510
+ application/json:
511
+ schema:
512
+ $ref: "#/components/schemas/ErrorList"
513
+ Forbidden:
514
+ description: Network password is configured and `X-Password` is missing or wrong.
515
+ content:
516
+ application/json:
517
+ schema:
518
+ $ref: "#/components/schemas/ErrorList"
519
+ NotFound:
520
+ description: Route, file, category, item, or active menu screen was not found.
521
+ content:
522
+ application/json:
523
+ schema:
524
+ $ref: "#/components/schemas/ErrorList"
525
+ PreconditionFailed:
526
+ description: Required request body was missing.
527
+ content:
528
+ application/json:
529
+ schema:
530
+ $ref: "#/components/schemas/ErrorList"
531
+ NotImplemented:
532
+ description: Firmware route exists, but the current FPGA or hardware capability is unavailable.
533
+ content:
534
+ application/json:
535
+ schema:
536
+ $ref: "#/components/schemas/ErrorList"
537
+ ServerError:
538
+ description: Device-side operation failed.
539
+ content:
540
+ application/json:
541
+ schema:
542
+ $ref: "#/components/schemas/ErrorList"
166
543
  paths:
544
+ /v1/help:
545
+ get:
546
+ tags: [System]
547
+ operationId: getHelp
548
+ summary: Return minimal HTML help for a command.
549
+ parameters:
550
+ - name: command
551
+ in: query
552
+ required: true
553
+ schema:
554
+ type: string
555
+ responses:
556
+ "200":
557
+ description: HTML help.
558
+ content:
559
+ text/html:
560
+ schema:
561
+ type: string
562
+ "400":
563
+ $ref: "#/components/responses/BadRequest"
564
+ "403":
565
+ $ref: "#/components/responses/Forbidden"
167
566
  /v1/version:
168
567
  get:
169
- summary: Get API version
170
- description: Returns the firmware-defined REST API semantic version.
568
+ tags: [System]
569
+ operationId: getApiVersion
570
+ summary: Get REST API version.
171
571
  responses:
172
- '200':
173
- description: Successful response
572
+ "200":
573
+ description: API version.
174
574
  content:
175
575
  application/json:
176
576
  schema:
177
- $ref: '#/components/schemas/VersionResponse'
178
- examples:
179
- live:
180
- value:
181
- version: "0.1"
182
- errors: []
577
+ $ref: "#/components/schemas/VersionResponse"
578
+ "403":
579
+ $ref: "#/components/responses/Forbidden"
183
580
  /v1/info:
184
581
  get:
185
- summary: Get device information
186
- description: >-
187
- Returns hardware metadata (product, firmware version, FPGA/core
188
- versions, hostname). Available on Ultimate firmware 3.12 and newer. On
189
- earlier releases the endpoint responds with HTTP 404.
582
+ tags: [System]
583
+ operationId: getDeviceInfo
584
+ summary: Get device identity and firmware versions.
190
585
  responses:
191
- '200':
192
- description: Successful response
586
+ "200":
587
+ description: Device information.
193
588
  content:
194
589
  application/json:
195
590
  schema:
196
- $ref: '#/components/schemas/InfoResponse'
197
- examples:
198
- live:
199
- value:
200
- product: Ultimate 64 Elite
201
- firmware_version: "3.12a"
202
- fpga_version: "121"
203
- core_version: "1.45"
204
- hostname: c64u
205
- unique_id: 38C1BA
206
- errors: []
591
+ $ref: "#/components/schemas/InfoResponse"
592
+ "403":
593
+ $ref: "#/components/responses/Forbidden"
207
594
  /v1/runners:sidplay:
208
595
  put:
209
- summary: Play SID from filesystem
596
+ tags: [Runners]
597
+ operationId: playSidFromFile
598
+ summary: Play a SID file already present on the device filesystem.
210
599
  parameters:
211
- - in: query
212
- name: file
213
- required: true
214
- schema:
215
- type: string
216
- - in: query
217
- name: songnr
218
- schema:
219
- type: integer
220
- minimum: 0
600
+ - $ref: "#/components/parameters/FileQuery"
601
+ - $ref: "#/components/parameters/SongNumber"
221
602
  responses:
222
- '200':
223
- description: Request accepted
224
- content:
225
- application/json:
226
- schema:
227
- $ref: '#/components/schemas/RunnerActionResponse'
603
+ "200":
604
+ $ref: "#/components/responses/JsonOk"
605
+ "400":
606
+ $ref: "#/components/responses/BadRequest"
607
+ "403":
608
+ $ref: "#/components/responses/Forbidden"
609
+ "404":
610
+ $ref: "#/components/responses/NotFound"
228
611
  post:
229
- summary: Play uploaded SID
612
+ tags: [Runners]
613
+ operationId: playUploadedSid
614
+ summary: Upload and play a SID file.
230
615
  parameters:
231
- - in: query
232
- name: songnr
233
- schema:
234
- type: integer
235
- minimum: 0
616
+ - $ref: "#/components/parameters/SongNumber"
236
617
  requestBody:
237
- required: true
238
- content:
239
- multipart/form-data:
240
- schema:
241
- type: object
242
- properties:
243
- sid:
244
- type: string
245
- format: binary
246
- songlengths:
247
- type: string
248
- format: binary
249
- required:
250
- - sid
618
+ $ref: "#/components/requestBodies/SidUpload"
251
619
  responses:
252
- '200':
253
- description: Request accepted
254
- content:
255
- application/json:
256
- schema:
257
- $ref: '#/components/schemas/RunnerActionResponse'
620
+ "200":
621
+ $ref: "#/components/responses/JsonOk"
622
+ "400":
623
+ $ref: "#/components/responses/BadRequest"
624
+ "403":
625
+ $ref: "#/components/responses/Forbidden"
626
+ "412":
627
+ $ref: "#/components/responses/PreconditionFailed"
258
628
  /v1/runners:modplay:
259
629
  put:
260
- summary: Play MOD from filesystem
630
+ tags: [Runners]
631
+ operationId: playModFromFile
632
+ summary: Play a MOD file from the device filesystem.
633
+ description: Requires the FPGA sampler capability.
261
634
  parameters:
262
- - in: query
263
- name: file
264
- required: true
265
- schema:
266
- type: string
635
+ - $ref: "#/components/parameters/FileQuery"
267
636
  responses:
268
- '200':
269
- description: Request accepted
270
- content:
271
- application/json:
272
- schema:
273
- $ref: '#/components/schemas/RunnerActionResponse'
637
+ "200":
638
+ $ref: "#/components/responses/JsonOk"
639
+ "403":
640
+ $ref: "#/components/responses/Forbidden"
641
+ "404":
642
+ $ref: "#/components/responses/NotFound"
643
+ "501":
644
+ $ref: "#/components/responses/NotImplemented"
274
645
  post:
275
- summary: Play uploaded MOD
646
+ tags: [Runners]
647
+ operationId: playUploadedMod
648
+ summary: Upload and play a MOD file.
649
+ description: Requires the FPGA sampler capability.
276
650
  requestBody:
277
- required: true
278
- content:
279
- application/octet-stream:
280
- schema:
281
- type: string
282
- format: binary
651
+ $ref: "#/components/requestBodies/BinaryUpload"
283
652
  responses:
284
- '200':
285
- description: Request accepted
286
- content:
287
- application/json:
288
- schema:
289
- $ref: '#/components/schemas/RunnerActionResponse'
653
+ "200":
654
+ $ref: "#/components/responses/JsonOk"
655
+ "403":
656
+ $ref: "#/components/responses/Forbidden"
657
+ "412":
658
+ $ref: "#/components/responses/PreconditionFailed"
659
+ "501":
660
+ $ref: "#/components/responses/NotImplemented"
290
661
  /v1/runners:load_prg:
291
662
  put:
292
- summary: Load PRG from filesystem
663
+ tags: [Runners]
664
+ operationId: loadPrgFromFile
665
+ summary: Load a PRG from the device filesystem without starting it.
293
666
  parameters:
294
- - in: query
295
- name: file
296
- required: true
297
- schema:
298
- type: string
667
+ - $ref: "#/components/parameters/FileQuery"
299
668
  responses:
300
- '200':
301
- description: Request accepted
302
- content:
303
- application/json:
304
- schema:
305
- $ref: '#/components/schemas/RunnerActionResponse'
669
+ "200":
670
+ $ref: "#/components/responses/JsonOk"
671
+ "403":
672
+ $ref: "#/components/responses/Forbidden"
673
+ "404":
674
+ $ref: "#/components/responses/NotFound"
306
675
  post:
307
- summary: Load uploaded PRG
676
+ tags: [Runners]
677
+ operationId: loadUploadedPrg
678
+ summary: Upload a PRG and load it without starting it.
308
679
  requestBody:
309
- required: true
310
- content:
311
- application/octet-stream:
312
- schema:
313
- type: string
314
- format: binary
680
+ $ref: "#/components/requestBodies/BinaryUpload"
315
681
  responses:
316
- '200':
317
- description: Request accepted
318
- content:
319
- application/json:
320
- schema:
321
- $ref: '#/components/schemas/RunnerActionResponse'
682
+ "200":
683
+ $ref: "#/components/responses/JsonOk"
684
+ "403":
685
+ $ref: "#/components/responses/Forbidden"
686
+ "412":
687
+ $ref: "#/components/responses/PreconditionFailed"
322
688
  /v1/runners:run_prg:
323
689
  put:
324
- summary: Run PRG from filesystem
690
+ tags: [Runners]
691
+ operationId: runPrgFromFile
692
+ summary: Load and run a PRG from the device filesystem.
325
693
  parameters:
326
- - in: query
327
- name: file
328
- required: true
329
- schema:
330
- type: string
694
+ - $ref: "#/components/parameters/FileQuery"
331
695
  responses:
332
- '200':
333
- description: Request accepted
334
- content:
335
- application/json:
336
- schema:
337
- $ref: '#/components/schemas/RunnerActionResponse'
696
+ "200":
697
+ $ref: "#/components/responses/JsonOk"
698
+ "403":
699
+ $ref: "#/components/responses/Forbidden"
700
+ "404":
701
+ $ref: "#/components/responses/NotFound"
338
702
  post:
339
- summary: Run uploaded PRG
703
+ tags: [Runners]
704
+ operationId: runUploadedPrg
705
+ summary: Upload, load, and run a PRG.
340
706
  requestBody:
341
- required: true
342
- content:
343
- application/octet-stream:
344
- schema:
345
- type: string
346
- format: binary
707
+ $ref: "#/components/requestBodies/BinaryUpload"
347
708
  responses:
348
- '200':
349
- description: Request accepted
350
- content:
351
- application/json:
352
- schema:
353
- $ref: '#/components/schemas/RunnerActionResponse'
709
+ "200":
710
+ $ref: "#/components/responses/JsonOk"
711
+ "403":
712
+ $ref: "#/components/responses/Forbidden"
713
+ "412":
714
+ $ref: "#/components/responses/PreconditionFailed"
354
715
  /v1/runners:run_crt:
355
716
  put:
356
- summary: Run cartridge from filesystem
717
+ tags: [Runners]
718
+ operationId: runCrtFromFile
719
+ summary: Load and start a CRT cartridge image from the device filesystem.
357
720
  parameters:
358
- - in: query
359
- name: file
360
- required: true
361
- schema:
362
- type: string
721
+ - $ref: "#/components/parameters/FileQuery"
363
722
  responses:
364
- '200':
365
- description: Request accepted
366
- content:
367
- application/json:
368
- schema:
369
- $ref: '#/components/schemas/RunnerActionResponse'
723
+ "200":
724
+ $ref: "#/components/responses/JsonOk"
725
+ "403":
726
+ $ref: "#/components/responses/Forbidden"
727
+ "404":
728
+ $ref: "#/components/responses/NotFound"
370
729
  post:
371
- summary: Run uploaded cartridge
730
+ tags: [Runners]
731
+ operationId: runUploadedCrt
732
+ summary: Upload, load, and start a CRT cartridge image.
372
733
  requestBody:
373
- required: true
374
- content:
375
- application/octet-stream:
376
- schema:
377
- type: string
378
- format: binary
734
+ $ref: "#/components/requestBodies/BinaryUpload"
379
735
  responses:
380
- '200':
381
- description: Request accepted
382
- content:
383
- application/json:
384
- schema:
385
- $ref: '#/components/schemas/RunnerActionResponse'
736
+ "200":
737
+ $ref: "#/components/responses/JsonOk"
738
+ "403":
739
+ $ref: "#/components/responses/Forbidden"
740
+ "412":
741
+ $ref: "#/components/responses/PreconditionFailed"
386
742
  /v1/configs:
387
743
  get:
388
- summary: List configuration categories
389
- description: Enumerates top-level configuration pages as displayed in the
390
- Ultimate menu. Supports wildcard queries via URL encoding.
744
+ tags: [Configuration]
745
+ operationId: listConfigCategories
746
+ summary: List configuration categories.
391
747
  responses:
392
- '200':
393
- description: Categories returned
748
+ "200":
749
+ description: Configuration categories.
394
750
  content:
395
751
  application/json:
396
752
  schema:
397
- $ref: '#/components/schemas/ConfigListResponse'
398
- examples:
399
- live:
400
- value:
401
- categories:
402
- - Audio Mixer
403
- - SID Sockets Configuration
404
- - UltiSID Configuration
405
- - SID Addressing
406
- - U64 Specific Settings
407
- - C64 and Cartridge Settings
408
- - Clock Settings
409
- - Network Settings
410
- - Ethernet Settings
411
- - WiFi settings
412
- - LED Strip Settings
413
- - Data Streams
414
- - SoftIEC Drive Settings
415
- - Printer Settings
416
- - Modem Settings
417
- - User Interface Settings
418
- - Tape Settings
419
- - Drive A Settings
420
- - Drive B Settings
421
- errors: []
753
+ $ref: "#/components/schemas/ConfigCategoriesResponse"
754
+ "403":
755
+ $ref: "#/components/responses/Forbidden"
422
756
  post:
423
- summary: Batch update configuration
757
+ tags: [Configuration]
758
+ operationId: batchUpdateConfig
759
+ summary: Apply a JSON batch of configuration values.
760
+ description: Use single-item `PUT` for interactive writes; batch POST buffers the body on-device.
424
761
  requestBody:
425
762
  required: true
426
763
  content:
427
764
  application/json:
428
765
  schema:
429
- type: object
430
- additionalProperties:
431
- type: object
766
+ $ref: "#/components/schemas/ConfigBatchUpdate"
432
767
  responses:
433
- '200':
434
- description: Update applied
435
- content:
436
- application/json:
437
- schema:
438
- $ref: '#/components/schemas/ErrorResponse'
768
+ "200":
769
+ $ref: "#/components/responses/JsonOk"
770
+ "400":
771
+ $ref: "#/components/responses/BadRequest"
772
+ "403":
773
+ $ref: "#/components/responses/Forbidden"
774
+ "412":
775
+ $ref: "#/components/responses/PreconditionFailed"
439
776
  /v1/configs/{category}:
440
777
  get:
441
- summary: Inspect category
442
- description: Returns all items inside the specified category. Wildcards
443
- may match multiple categories; each appears as an object property in the
444
- response.
778
+ tags: [Configuration]
779
+ operationId: getConfigCategory
780
+ summary: Get matching configuration categories and their current values.
445
781
  parameters:
446
- - in: path
447
- name: category
448
- required: true
449
- schema:
450
- type: string
782
+ - $ref: "#/components/parameters/Category"
451
783
  responses:
452
- '200':
453
- description: Category returned
784
+ "200":
785
+ description: Matching category values.
454
786
  content:
455
787
  application/json:
456
788
  schema:
457
- $ref: '#/components/schemas/ConfigCategoryResponse'
458
- examples:
459
- drive_a:
460
- summary: Drive A Settings (firmware 3.12a)
461
- value:
462
- Drive A Settings:
463
- Drive: Enabled
464
- Drive Type: "1541"
465
- Drive Bus ID: 8
466
- ROM for 1541 mode: 1541.rom
467
- ROM for 1571 mode: 1571.rom
468
- ROM for 1581 mode: 1581.rom
469
- Extra RAM: Disabled
470
- Disk swap delay: 1
471
- Resets when C64 resets: "Yes"
472
- Freezes in menu: "Yes"
473
- GCR Save Align Tracks: "Yes"
474
- Leave Menu on Mount: "Yes"
475
- D64 Geos Copy Protection: none
476
- errors: []
789
+ $ref: "#/components/schemas/ConfigCategoryResponse"
790
+ "403":
791
+ $ref: "#/components/responses/Forbidden"
477
792
  /v1/configs/{category}/{item}:
478
793
  get:
479
- summary: Inspect configuration item
794
+ tags: [Configuration]
795
+ operationId: getConfigItem
796
+ summary: Get detailed metadata for matching configuration items.
480
797
  parameters:
481
- - in: path
482
- name: category
483
- required: true
484
- schema:
485
- type: string
486
- - in: path
487
- name: item
488
- required: true
489
- schema:
490
- type: string
798
+ - $ref: "#/components/parameters/Category"
799
+ - $ref: "#/components/parameters/Item"
491
800
  responses:
492
- '200':
493
- description: Item returned
801
+ "200":
802
+ description: Matching item metadata.
494
803
  content:
495
804
  application/json:
496
805
  schema:
497
- $ref: '#/components/schemas/ConfigItemResponse'
806
+ $ref: "#/components/schemas/ConfigCategoryResponse"
807
+ "403":
808
+ $ref: "#/components/responses/Forbidden"
498
809
  put:
499
- summary: Update configuration item
810
+ tags: [Configuration]
811
+ operationId: updateConfigItem
812
+ summary: Update one configuration item using the `value` query parameter.
500
813
  parameters:
501
- - in: path
502
- name: category
503
- required: true
504
- schema:
505
- type: string
506
- - in: path
507
- name: item
508
- required: true
509
- schema:
510
- type: string
511
- - in: query
512
- name: value
814
+ - $ref: "#/components/parameters/Category"
815
+ - $ref: "#/components/parameters/Item"
816
+ - name: value
817
+ in: query
513
818
  required: true
514
819
  schema:
515
820
  type: string
516
821
  responses:
517
- '200':
518
- description: Update applied
519
- content:
520
- application/json:
521
- schema:
522
- $ref: '#/components/schemas/ErrorResponse'
822
+ "200":
823
+ $ref: "#/components/responses/JsonOk"
824
+ "400":
825
+ $ref: "#/components/responses/BadRequest"
826
+ "403":
827
+ $ref: "#/components/responses/Forbidden"
828
+ "404":
829
+ $ref: "#/components/responses/NotFound"
830
+ /v1/configs/{category}/{item}/{setting}:
831
+ put:
832
+ tags: [Configuration]
833
+ operationId: updateConfigItemByPath
834
+ summary: Update one configuration item using the third path segment as the value.
835
+ parameters:
836
+ - $ref: "#/components/parameters/Category"
837
+ - $ref: "#/components/parameters/Item"
838
+ - $ref: "#/components/parameters/Setting"
839
+ responses:
840
+ "200":
841
+ $ref: "#/components/responses/JsonOk"
842
+ "400":
843
+ $ref: "#/components/responses/BadRequest"
844
+ "403":
845
+ $ref: "#/components/responses/Forbidden"
846
+ "404":
847
+ $ref: "#/components/responses/NotFound"
523
848
  /v1/configs:load_from_flash:
524
849
  put:
525
- summary: Load configuration from flash
850
+ tags: [Configuration]
851
+ operationId: loadAllConfigsFromFlash
852
+ summary: Reload all configuration stores from flash.
526
853
  responses:
527
- '200':
528
- description: Loaded
854
+ "200":
855
+ $ref: "#/components/responses/JsonOk"
856
+ "403":
857
+ $ref: "#/components/responses/Forbidden"
858
+ /v1/configs/{category}:load_from_flash:
859
+ put:
860
+ tags: [Configuration]
861
+ operationId: loadConfigCategoryFromFlash
862
+ summary: Reload matching configuration stores from flash.
863
+ parameters:
864
+ - $ref: "#/components/parameters/Category"
865
+ responses:
866
+ "200":
867
+ description: Matching stores loaded.
529
868
  content:
530
869
  application/json:
531
870
  schema:
532
- $ref: '#/components/schemas/ErrorResponse'
871
+ $ref: "#/components/schemas/ConfigStoreListResponse"
872
+ "403":
873
+ $ref: "#/components/responses/Forbidden"
533
874
  /v1/configs:save_to_flash:
534
875
  put:
535
- summary: Save configuration to flash
876
+ tags: [Configuration]
877
+ operationId: saveAllConfigsToFlash
878
+ summary: Save stale configuration stores to flash.
536
879
  responses:
537
- '200':
538
- description: Saved
880
+ "200":
881
+ description: Stores written.
539
882
  content:
540
883
  application/json:
541
884
  schema:
542
- $ref: '#/components/schemas/ErrorResponse'
543
- /v1/configs:reset_to_default:
885
+ $ref: "#/components/schemas/ConfigStoreListResponse"
886
+ "403":
887
+ $ref: "#/components/responses/Forbidden"
888
+ /v1/configs/{category}:save_to_flash:
544
889
  put:
545
- summary: Reset configuration to defaults
890
+ tags: [Configuration]
891
+ operationId: saveConfigCategoryToFlash
892
+ summary: Save matching stale configuration stores to flash.
893
+ parameters:
894
+ - $ref: "#/components/parameters/Category"
546
895
  responses:
547
- '200':
548
- description: Reset complete
896
+ "200":
897
+ description: Matching stores written.
549
898
  content:
550
899
  application/json:
551
900
  schema:
552
- $ref: '#/components/schemas/ErrorResponse'
553
- /v1/machine:reset:
901
+ $ref: "#/components/schemas/ConfigStoreListResponse"
902
+ "403":
903
+ $ref: "#/components/responses/Forbidden"
904
+ /v1/configs:reset_to_default:
905
+ put:
906
+ tags: [Configuration]
907
+ operationId: resetAllConfigsToDefault
908
+ summary: Reset all configuration stores to firmware defaults.
909
+ responses:
910
+ "200":
911
+ $ref: "#/components/responses/JsonOk"
912
+ "403":
913
+ $ref: "#/components/responses/Forbidden"
914
+ /v1/configs/{category}:reset_to_default:
554
915
  put:
555
- summary: Soft reset machine
916
+ tags: [Configuration]
917
+ operationId: resetConfigCategoryToDefault
918
+ summary: Reset matching configuration stores to firmware defaults.
919
+ parameters:
920
+ - $ref: "#/components/parameters/Category"
556
921
  responses:
557
- '200':
558
- description: Reset triggered
922
+ "200":
923
+ description: Matching stores reset.
559
924
  content:
560
925
  application/json:
561
926
  schema:
562
- $ref: '#/components/schemas/MachineActionResponse'
927
+ $ref: "#/components/schemas/ConfigStoreListResponse"
928
+ "403":
929
+ $ref: "#/components/responses/Forbidden"
930
+ /v1/machine:reset:
931
+ put:
932
+ tags: [Machine]
933
+ operationId: resetMachine
934
+ summary: Reset the C64.
935
+ responses:
936
+ "200":
937
+ $ref: "#/components/responses/JsonOk"
938
+ "403":
939
+ $ref: "#/components/responses/Forbidden"
563
940
  /v1/machine:reboot:
564
941
  put:
565
- summary: Reboot machine
942
+ tags: [Machine]
943
+ operationId: rebootMachine
944
+ summary: Reboot the C64.
566
945
  responses:
567
- '200':
568
- description: Reboot triggered
569
- content:
570
- application/json:
571
- schema:
572
- $ref: '#/components/schemas/MachineActionResponse'
946
+ "200":
947
+ $ref: "#/components/responses/JsonOk"
948
+ "403":
949
+ $ref: "#/components/responses/Forbidden"
573
950
  /v1/machine:pause:
574
951
  put:
575
- summary: Pause machine via DMA
952
+ tags: [Machine]
953
+ operationId: pauseMachine
954
+ summary: Pause the machine using DMA.
576
955
  responses:
577
- '200':
578
- description: Pause applied
579
- content:
580
- application/json:
581
- schema:
582
- $ref: '#/components/schemas/MachineActionResponse'
956
+ "200":
957
+ $ref: "#/components/responses/JsonOk"
958
+ "403":
959
+ $ref: "#/components/responses/Forbidden"
583
960
  /v1/machine:resume:
584
961
  put:
585
- summary: Resume machine from pause
962
+ tags: [Machine]
963
+ operationId: resumeMachine
964
+ summary: Resume a paused machine.
586
965
  responses:
587
- '200':
588
- description: Resume applied
589
- content:
590
- application/json:
591
- schema:
592
- $ref: '#/components/schemas/MachineActionResponse'
966
+ "200":
967
+ $ref: "#/components/responses/JsonOk"
968
+ "403":
969
+ $ref: "#/components/responses/Forbidden"
593
970
  /v1/machine:poweroff:
594
971
  put:
595
- summary: Power off machine
972
+ tags: [Machine]
973
+ operationId: powerOffMachine
974
+ summary: Request machine power off.
596
975
  responses:
597
- '200':
598
- description: Power off requested
599
- content:
600
- application/json:
601
- schema:
602
- $ref: '#/components/schemas/MachineActionResponse'
976
+ "200":
977
+ $ref: "#/components/responses/JsonOk"
978
+ "403":
979
+ $ref: "#/components/responses/Forbidden"
603
980
  /v1/machine:menu_button:
604
981
  put:
605
- summary: Toggle Ultimate menu button
982
+ tags: [Machine]
983
+ operationId: pressMenuButton
984
+ summary: Press the Ultimate menu button.
606
985
  responses:
607
- '200':
608
- description: Button event queued
609
- content:
610
- application/json:
611
- schema:
612
- $ref: '#/components/schemas/MachineActionResponse'
986
+ "200":
987
+ $ref: "#/components/responses/JsonOk"
988
+ "403":
989
+ $ref: "#/components/responses/Forbidden"
613
990
  /v1/machine:writemem:
614
991
  put:
615
- summary: Write memory via query data
992
+ tags: [Machine]
993
+ operationId: writeMemoryHex
994
+ summary: Write up to 128 bytes of C64 memory from a hex string.
616
995
  parameters:
617
- - in: query
618
- name: address
619
- required: true
620
- schema:
621
- type: string
622
- description: Hexadecimal start address.
623
- - in: query
624
- name: data
996
+ - $ref: "#/components/parameters/Address"
997
+ - name: data
998
+ in: query
625
999
  required: true
626
1000
  schema:
627
1001
  type: string
628
- description: Hex string representing bytes (≤ 128 bytes).
1002
+ pattern: "^([0-9A-Fa-f]{2}){1,128}$"
629
1003
  responses:
630
- '200':
631
- description: Write applied
632
- content:
633
- application/json:
634
- schema:
635
- $ref: '#/components/schemas/MachineActionResponse'
1004
+ "200":
1005
+ $ref: "#/components/responses/JsonOk"
1006
+ "400":
1007
+ $ref: "#/components/responses/BadRequest"
1008
+ "403":
1009
+ $ref: "#/components/responses/Forbidden"
636
1010
  post:
637
- summary: Write memory via binary payload
1011
+ tags: [Machine]
1012
+ operationId: writeMemoryUpload
1013
+ summary: Write C64 memory from an uploaded binary payload.
638
1014
  parameters:
639
- - in: query
640
- name: address
641
- required: true
642
- schema:
643
- type: string
644
- description: Hexadecimal start address.
1015
+ - $ref: "#/components/parameters/Address"
645
1016
  requestBody:
646
- required: true
647
- content:
648
- application/octet-stream:
649
- schema:
650
- type: string
651
- format: binary
1017
+ $ref: "#/components/requestBodies/BinaryUpload"
652
1018
  responses:
653
- '200':
654
- description: Write applied
655
- content:
656
- application/json:
657
- schema:
658
- $ref: '#/components/schemas/MachineActionResponse'
1019
+ "200":
1020
+ $ref: "#/components/responses/JsonOk"
1021
+ "400":
1022
+ $ref: "#/components/responses/BadRequest"
1023
+ "403":
1024
+ $ref: "#/components/responses/Forbidden"
1025
+ "404":
1026
+ $ref: "#/components/responses/NotFound"
1027
+ "412":
1028
+ $ref: "#/components/responses/PreconditionFailed"
1029
+ "500":
1030
+ $ref: "#/components/responses/ServerError"
659
1031
  /v1/machine:readmem:
660
1032
  get:
661
- summary: Read memory
662
- description: Performs a DMA read at the requested address. Firmware
663
- returns either a JSON wrapper or raw bytes. Use `length` to limit the
664
- transfer (default 256 bytes).
1033
+ tags: [Machine]
1034
+ operationId: readMemory
1035
+ summary: Read C64 memory as raw bytes.
665
1036
  parameters:
666
- - in: query
667
- name: address
668
- required: true
669
- schema:
670
- type: string
671
- description: Hexadecimal start address.
672
- - in: query
673
- name: length
674
- schema:
675
- type: integer
676
- minimum: 1
677
- maximum: 4096
1037
+ - $ref: "#/components/parameters/Address"
1038
+ - $ref: "#/components/parameters/Length"
678
1039
  responses:
679
- '200':
680
- description: Memory data
1040
+ "200":
1041
+ description: Raw memory bytes.
681
1042
  content:
682
- application/json:
683
- schema:
684
- $ref: '#/components/schemas/MemoryReadJson'
685
1043
  application/octet-stream:
686
1044
  schema:
687
1045
  type: string
688
1046
  format: binary
689
- examples:
690
- vic_border:
691
- summary: Raw bytes for $D020-$D021
692
- value: !!binary |
693
- /vY=
694
- /v1/machine:debugreg:
1047
+ "400":
1048
+ $ref: "#/components/responses/BadRequest"
1049
+ "403":
1050
+ $ref: "#/components/responses/Forbidden"
1051
+ /v1/machine:menu_screen:
695
1052
  get:
696
- summary: Read debug register
1053
+ tags: [Machine]
1054
+ operationId: readMenuScreen
1055
+ summary: Read the active Ultimate menu screen matrix as raw bytes.
1056
+ description: Returns 404 JSON when no active menu screen matrix is available.
697
1057
  responses:
698
- '200':
699
- description: Register value
1058
+ "200":
1059
+ description: Active screen matrix bytes.
700
1060
  content:
701
- application/json:
1061
+ application/octet-stream:
702
1062
  schema:
703
- $ref: '#/components/schemas/MemoryDebugResponse'
1063
+ type: string
1064
+ format: binary
1065
+ "403":
1066
+ $ref: "#/components/responses/Forbidden"
1067
+ "404":
1068
+ $ref: "#/components/responses/NotFound"
1069
+ /v1/machine:debugreg:
1070
+ get:
1071
+ tags: [Machine]
1072
+ operationId: readDebugRegister
1073
+ summary: Read the Ultimate 64 debug register.
1074
+ responses:
1075
+ "200":
1076
+ $ref: "#/components/responses/JsonOk"
1077
+ "403":
1078
+ $ref: "#/components/responses/Forbidden"
704
1079
  put:
705
- summary: Write debug register
1080
+ tags: [Machine]
1081
+ operationId: writeDebugRegister
1082
+ summary: Write the Ultimate 64 debug register.
706
1083
  parameters:
707
- - in: query
708
- name: value
1084
+ - name: value
1085
+ in: query
709
1086
  required: true
710
1087
  schema:
711
1088
  type: string
712
- description: Hexadecimal value to write.
1089
+ pattern: "^(0x)?[0-9A-Fa-f]{1,2}$"
1090
+ responses:
1091
+ "200":
1092
+ $ref: "#/components/responses/JsonOk"
1093
+ "400":
1094
+ $ref: "#/components/responses/BadRequest"
1095
+ "403":
1096
+ $ref: "#/components/responses/Forbidden"
1097
+ /v1/machine:measure:
1098
+ get:
1099
+ tags: [Machine]
1100
+ operationId: measureCartridgeBus
1101
+ summary: Capture cartridge-bus timing as a VCD file.
1102
+ responses:
1103
+ "200":
1104
+ description: VCD timing capture.
1105
+ content:
1106
+ application/octet-stream:
1107
+ schema:
1108
+ type: string
1109
+ format: binary
1110
+ "403":
1111
+ $ref: "#/components/responses/Forbidden"
1112
+ "501":
1113
+ $ref: "#/components/responses/NotImplemented"
1114
+ /v1/machine:input:
1115
+ get:
1116
+ tags: [Input]
1117
+ operationId: getInputState
1118
+ summary: Read REST-injected keyboard and joystick state.
713
1119
  responses:
714
- '200':
715
- description: Updated register value
1120
+ "200":
1121
+ description: Current input state.
716
1122
  content:
717
1123
  application/json:
718
1124
  schema:
719
- $ref: '#/components/schemas/MemoryDebugResponse'
1125
+ $ref: "#/components/schemas/InputStateResponse"
1126
+ "403":
1127
+ $ref: "#/components/responses/Forbidden"
1128
+ "501":
1129
+ $ref: "#/components/responses/NotImplemented"
1130
+ post:
1131
+ tags: [Input]
1132
+ operationId: sendInputEvents
1133
+ summary: Apply keyboard and joystick input events.
1134
+ requestBody:
1135
+ required: true
1136
+ content:
1137
+ application/json:
1138
+ schema:
1139
+ $ref: "#/components/schemas/InputBatch"
1140
+ responses:
1141
+ "200":
1142
+ description: Updated input state.
1143
+ content:
1144
+ application/json:
1145
+ schema:
1146
+ $ref: "#/components/schemas/InputStateResponse"
1147
+ "400":
1148
+ $ref: "#/components/responses/BadRequest"
1149
+ "403":
1150
+ $ref: "#/components/responses/Forbidden"
1151
+ "412":
1152
+ $ref: "#/components/responses/PreconditionFailed"
1153
+ "500":
1154
+ $ref: "#/components/responses/ServerError"
1155
+ "501":
1156
+ $ref: "#/components/responses/NotImplemented"
720
1157
  /v1/drives:
721
1158
  get:
722
- summary: List internal drives
723
- description: Returns current Ultimate-managed drives, images, and service
724
- devices (SoftIEC, printer emulation).
1159
+ tags: [Drives]
1160
+ operationId: listDrives
1161
+ summary: List internal drives and IEC service devices.
725
1162
  responses:
726
- '200':
727
- description: Drive information
1163
+ "200":
1164
+ description: Drive list.
728
1165
  content:
729
1166
  application/json:
730
1167
  schema:
731
- $ref: '#/components/schemas/DriveListResponse'
732
- examples:
733
- live:
734
- value:
735
- drives:
736
- - a:
737
- enabled: true
738
- bus_id: 8
739
- type: "1541"
740
- rom: "1541.rom"
741
- image_file: ""
742
- image_path: ""
743
- - b:
744
- enabled: false
745
- bus_id: 9
746
- type: "1541"
747
- rom: "1541.rom"
748
- image_file: ""
749
- image_path: ""
750
- - IEC Drive:
751
- bus_id: 11
752
- enabled: false
753
- type: "DOS emulation"
754
- last_error: "73,U64IEC ULTIMATE DOS V1.1,00,00"
755
- partitions:
756
- - id: 0
757
- path: "/Usb0/"
758
- - Printer Emulation:
759
- bus_id: 4
760
- enabled: false
761
- errors: []
1168
+ $ref: "#/components/schemas/DriveListResponse"
1169
+ "403":
1170
+ $ref: "#/components/responses/Forbidden"
762
1171
  /v1/drives/{drive}:mount:
763
1172
  put:
764
- summary: Mount disk image from filesystem
1173
+ tags: [Drives]
1174
+ operationId: mountDiskImage
1175
+ summary: Mount a disk image from the device filesystem.
765
1176
  parameters:
766
- - in: path
767
- name: drive
768
- required: true
769
- schema:
770
- type: string
771
- - in: query
772
- name: image
1177
+ - $ref: "#/components/parameters/Drive"
1178
+ - name: image
1179
+ in: query
773
1180
  required: true
774
1181
  schema:
775
1182
  type: string
776
- - in: query
777
- name: type
1183
+ - name: type
1184
+ in: query
1185
+ required: false
778
1186
  schema:
779
1187
  type: string
780
1188
  enum: [d64, g64, d71, g71, d81]
781
- - in: query
782
- name: mode
1189
+ - name: mode
1190
+ in: query
1191
+ required: false
783
1192
  schema:
784
1193
  type: string
785
1194
  enum: [readwrite, readonly, unlinked]
786
1195
  responses:
787
- '200':
788
- description: Mount complete
789
- content:
790
- application/json:
791
- schema:
792
- $ref: '#/components/schemas/ErrorResponse'
1196
+ "200":
1197
+ $ref: "#/components/responses/JsonOk"
1198
+ "400":
1199
+ $ref: "#/components/responses/BadRequest"
1200
+ "403":
1201
+ $ref: "#/components/responses/Forbidden"
793
1202
  post:
794
- summary: Mount uploaded disk image
1203
+ tags: [Drives]
1204
+ operationId: mountUploadedDiskImage
1205
+ summary: Upload and mount a disk image.
795
1206
  parameters:
796
- - in: path
797
- name: drive
798
- required: true
799
- schema:
800
- type: string
801
- - in: query
802
- name: type
1207
+ - $ref: "#/components/parameters/Drive"
1208
+ - name: type
1209
+ in: query
1210
+ required: false
803
1211
  schema:
804
1212
  type: string
805
1213
  enum: [d64, g64, d71, g71, d81]
806
- - in: query
807
- name: mode
1214
+ - name: mode
1215
+ in: query
1216
+ required: false
808
1217
  schema:
809
1218
  type: string
810
1219
  enum: [readwrite, readonly, unlinked]
811
1220
  requestBody:
812
- required: true
813
- content:
814
- application/octet-stream:
815
- schema:
816
- type: string
817
- format: binary
1221
+ $ref: "#/components/requestBodies/BinaryUpload"
818
1222
  responses:
819
- '200':
820
- description: Mount complete
821
- content:
822
- application/json:
823
- schema:
824
- $ref: '#/components/schemas/ErrorResponse'
1223
+ "200":
1224
+ $ref: "#/components/responses/JsonOk"
1225
+ "400":
1226
+ $ref: "#/components/responses/BadRequest"
1227
+ "403":
1228
+ $ref: "#/components/responses/Forbidden"
1229
+ "412":
1230
+ $ref: "#/components/responses/PreconditionFailed"
825
1231
  /v1/drives/{drive}:reset:
826
1232
  put:
827
- summary: Reset drive
1233
+ tags: [Drives]
1234
+ operationId: resetDrive
1235
+ summary: Reset a drive.
828
1236
  parameters:
829
- - in: path
830
- name: drive
831
- required: true
832
- schema:
833
- type: string
1237
+ - $ref: "#/components/parameters/Drive"
834
1238
  responses:
835
- '200':
836
- description: Reset complete
837
- content:
838
- application/json:
839
- schema:
840
- $ref: '#/components/schemas/ErrorResponse'
1239
+ "200":
1240
+ $ref: "#/components/responses/JsonOk"
1241
+ "403":
1242
+ $ref: "#/components/responses/Forbidden"
841
1243
  /v1/drives/{drive}:remove:
842
1244
  put:
843
- summary: Remove mounted image
1245
+ tags: [Drives]
1246
+ operationId: removeMountedImage
1247
+ summary: Remove the mounted image from a drive.
844
1248
  parameters:
845
- - in: path
846
- name: drive
847
- required: true
848
- schema:
849
- type: string
1249
+ - $ref: "#/components/parameters/Drive"
850
1250
  responses:
851
- '200':
852
- description: Removal complete
853
- content:
854
- application/json:
855
- schema:
856
- $ref: '#/components/schemas/ErrorResponse'
1251
+ "200":
1252
+ $ref: "#/components/responses/JsonOk"
1253
+ "403":
1254
+ $ref: "#/components/responses/Forbidden"
857
1255
  /v1/drives/{drive}:on:
858
1256
  put:
859
- summary: Power on drive
1257
+ tags: [Drives]
1258
+ operationId: powerOnDrive
1259
+ summary: Power on a drive.
860
1260
  parameters:
861
- - in: path
862
- name: drive
863
- required: true
864
- schema:
865
- type: string
1261
+ - $ref: "#/components/parameters/Drive"
866
1262
  responses:
867
- '200':
868
- description: Drive powered on
869
- content:
870
- application/json:
871
- schema:
872
- $ref: '#/components/schemas/ErrorResponse'
1263
+ "200":
1264
+ $ref: "#/components/responses/JsonOk"
1265
+ "403":
1266
+ $ref: "#/components/responses/Forbidden"
873
1267
  /v1/drives/{drive}:off:
874
1268
  put:
875
- summary: Power off drive
1269
+ tags: [Drives]
1270
+ operationId: powerOffDrive
1271
+ summary: Power off a drive.
876
1272
  parameters:
877
- - in: path
878
- name: drive
879
- required: true
880
- schema:
881
- type: string
1273
+ - $ref: "#/components/parameters/Drive"
882
1274
  responses:
883
- '200':
884
- description: Drive powered off
885
- content:
886
- application/json:
887
- schema:
888
- $ref: '#/components/schemas/ErrorResponse'
1275
+ "200":
1276
+ $ref: "#/components/responses/JsonOk"
1277
+ "403":
1278
+ $ref: "#/components/responses/Forbidden"
1279
+ /v1/drives/{drive}:unlink:
1280
+ put:
1281
+ tags: [Drives]
1282
+ operationId: unlinkMountedImage
1283
+ summary: Unlink the mounted image from host storage.
1284
+ parameters:
1285
+ - $ref: "#/components/parameters/Drive"
1286
+ responses:
1287
+ "200":
1288
+ $ref: "#/components/responses/JsonOk"
1289
+ "403":
1290
+ $ref: "#/components/responses/Forbidden"
889
1291
  /v1/drives/{drive}:load_rom:
890
1292
  put:
891
- summary: Load ROM from filesystem
1293
+ tags: [Drives]
1294
+ operationId: loadDriveRomFromFile
1295
+ summary: Load a drive ROM from the device filesystem.
892
1296
  parameters:
893
- - in: path
894
- name: drive
895
- required: true
896
- schema:
897
- type: string
898
- - in: query
899
- name: file
900
- required: true
901
- schema:
902
- type: string
1297
+ - $ref: "#/components/parameters/Drive"
1298
+ - $ref: "#/components/parameters/FileQuery"
903
1299
  responses:
904
- '200':
905
- description: ROM loaded
906
- content:
907
- application/json:
908
- schema:
909
- $ref: '#/components/schemas/ErrorResponse'
1300
+ "200":
1301
+ $ref: "#/components/responses/JsonOk"
1302
+ "403":
1303
+ $ref: "#/components/responses/Forbidden"
910
1304
  post:
911
- summary: Load ROM from upload
1305
+ tags: [Drives]
1306
+ operationId: loadUploadedDriveRom
1307
+ summary: Upload and load a drive ROM.
912
1308
  parameters:
913
- - in: path
914
- name: drive
915
- required: true
916
- schema:
917
- type: string
1309
+ - $ref: "#/components/parameters/Drive"
918
1310
  requestBody:
919
- required: true
920
- content:
921
- application/octet-stream:
922
- schema:
923
- type: string
924
- format: binary
1311
+ $ref: "#/components/requestBodies/BinaryUpload"
925
1312
  responses:
926
- '200':
927
- description: ROM loaded
928
- content:
929
- application/json:
930
- schema:
931
- $ref: '#/components/schemas/ErrorResponse'
1313
+ "200":
1314
+ $ref: "#/components/responses/JsonOk"
1315
+ "403":
1316
+ $ref: "#/components/responses/Forbidden"
1317
+ "412":
1318
+ $ref: "#/components/responses/PreconditionFailed"
932
1319
  /v1/drives/{drive}:set_mode:
933
1320
  put:
934
- summary: Set drive mode
1321
+ tags: [Drives]
1322
+ operationId: setDriveMode
1323
+ summary: Set drive emulation mode.
935
1324
  parameters:
936
- - in: path
937
- name: drive
1325
+ - $ref: "#/components/parameters/Drive"
1326
+ - name: mode
1327
+ in: query
938
1328
  required: true
939
1329
  schema:
940
1330
  type: string
941
- - in: query
942
- name: mode
943
- required: true
944
- schema:
945
- type: string
946
- enum: [1541, 1571, 1581]
1331
+ enum: ["1541", "1571", "1581"]
947
1332
  responses:
948
- '200':
949
- description: Mode updated
950
- content:
951
- application/json:
952
- schema:
953
- $ref: '#/components/schemas/ErrorResponse'
1333
+ "200":
1334
+ $ref: "#/components/responses/JsonOk"
1335
+ "400":
1336
+ $ref: "#/components/responses/BadRequest"
1337
+ "403":
1338
+ $ref: "#/components/responses/Forbidden"
954
1339
  /v1/streams/{stream}:start:
955
1340
  put:
956
- summary: Start data stream
1341
+ tags: [Streams]
1342
+ operationId: startDataStream
1343
+ summary: Start a data stream.
957
1344
  parameters:
958
- - in: path
959
- name: stream
1345
+ - name: stream
1346
+ in: path
960
1347
  required: true
961
1348
  schema:
962
1349
  type: string
963
1350
  enum: [video, audio, debug]
964
- - in: query
965
- name: ip
1351
+ - name: ip
1352
+ in: query
966
1353
  required: true
967
1354
  schema:
968
1355
  type: string
969
- description: Target IP address with optional port (ip[:port]).
1356
+ description: Destination IPv4 address, optionally with port.
970
1357
  responses:
971
- '200':
972
- description: Stream started
973
- content:
974
- application/json:
975
- schema:
976
- $ref: '#/components/schemas/ErrorResponse'
1358
+ "200":
1359
+ $ref: "#/components/responses/JsonOk"
1360
+ "403":
1361
+ $ref: "#/components/responses/Forbidden"
1362
+ "404":
1363
+ $ref: "#/components/responses/NotFound"
977
1364
  /v1/streams/{stream}:stop:
978
1365
  put:
979
- summary: Stop data stream
1366
+ tags: [Streams]
1367
+ operationId: stopDataStream
1368
+ summary: Stop a data stream.
980
1369
  parameters:
981
- - in: path
982
- name: stream
1370
+ - name: stream
1371
+ in: path
983
1372
  required: true
984
1373
  schema:
985
1374
  type: string
986
1375
  enum: [video, audio, debug]
987
1376
  responses:
988
- '200':
989
- description: Stream stopped
990
- content:
991
- application/json:
992
- schema:
993
- $ref: '#/components/schemas/ErrorResponse'
1377
+ "200":
1378
+ $ref: "#/components/responses/JsonOk"
1379
+ "403":
1380
+ $ref: "#/components/responses/Forbidden"
1381
+ "404":
1382
+ $ref: "#/components/responses/NotFound"
994
1383
  /v1/files/{path}:info:
995
1384
  get:
996
- summary: Inspect file metadata
1385
+ tags: [Files]
1386
+ operationId: getFileInfo
1387
+ summary: Get metadata for a device filesystem path.
997
1388
  parameters:
998
- - in: path
999
- name: path
1000
- required: true
1001
- schema:
1002
- type: string
1389
+ - $ref: "#/components/parameters/FilePath"
1003
1390
  responses:
1004
- '200':
1005
- description: Metadata returned
1391
+ "200":
1392
+ description: File metadata.
1006
1393
  content:
1007
1394
  application/json:
1008
1395
  schema:
1009
- $ref: '#/components/schemas/FileInfoResponse'
1010
- examples:
1011
- live:
1012
- value:
1013
- files:
1014
- path: /Flash/roms/1541.rom
1015
- filename: 1541.rom
1016
- size: 16384
1017
- extension: ROM
1018
- errors: []
1396
+ $ref: "#/components/schemas/FileInfoResponse"
1397
+ "403":
1398
+ $ref: "#/components/responses/Forbidden"
1399
+ "404":
1400
+ $ref: "#/components/responses/NotFound"
1019
1401
  /v1/files/{path}:create_d64:
1020
1402
  put:
1021
- summary: Create D64 image
1403
+ tags: [Files]
1404
+ operationId: createD64
1405
+ summary: Create and format a D64 image.
1022
1406
  parameters:
1023
- - in: path
1024
- name: path
1025
- required: true
1026
- schema:
1027
- type: string
1028
- - in: query
1029
- name: tracks
1030
- schema:
1031
- type: integer
1032
- enum: [35, 40]
1033
- - in: query
1034
- name: diskname
1035
- schema:
1036
- type: string
1407
+ - $ref: "#/components/parameters/FilePath"
1408
+ - $ref: "#/components/parameters/D64Tracks"
1409
+ - $ref: "#/components/parameters/DiskName"
1037
1410
  responses:
1038
- '200':
1039
- description: Image created
1040
- content:
1041
- application/json:
1042
- schema:
1043
- $ref: '#/components/schemas/ErrorResponse'
1411
+ "200":
1412
+ $ref: "#/components/responses/JsonOk"
1413
+ "400":
1414
+ $ref: "#/components/responses/BadRequest"
1415
+ "403":
1416
+ $ref: "#/components/responses/Forbidden"
1417
+ "500":
1418
+ $ref: "#/components/responses/ServerError"
1044
1419
  /v1/files/{path}:create_d71:
1045
1420
  put:
1046
- summary: Create D71 image
1421
+ tags: [Files]
1422
+ operationId: createD71
1423
+ summary: Create and format a D71 image.
1047
1424
  parameters:
1048
- - in: path
1049
- name: path
1050
- required: true
1051
- schema:
1052
- type: string
1053
- - in: query
1054
- name: diskname
1055
- schema:
1056
- type: string
1425
+ - $ref: "#/components/parameters/FilePath"
1426
+ - $ref: "#/components/parameters/DiskName"
1057
1427
  responses:
1058
- '200':
1059
- description: Image created
1060
- content:
1061
- application/json:
1062
- schema:
1063
- $ref: '#/components/schemas/ErrorResponse'
1428
+ "200":
1429
+ $ref: "#/components/responses/JsonOk"
1430
+ "403":
1431
+ $ref: "#/components/responses/Forbidden"
1432
+ "500":
1433
+ $ref: "#/components/responses/ServerError"
1064
1434
  /v1/files/{path}:create_d81:
1065
1435
  put:
1066
- summary: Create D81 image
1436
+ tags: [Files]
1437
+ operationId: createD81
1438
+ summary: Create and format a D81 image.
1067
1439
  parameters:
1068
- - in: path
1069
- name: path
1070
- required: true
1071
- schema:
1072
- type: string
1073
- - in: query
1074
- name: diskname
1075
- schema:
1076
- type: string
1440
+ - $ref: "#/components/parameters/FilePath"
1441
+ - $ref: "#/components/parameters/DiskName"
1077
1442
  responses:
1078
- '200':
1079
- description: Image created
1080
- content:
1081
- application/json:
1082
- schema:
1083
- $ref: '#/components/schemas/ErrorResponse'
1443
+ "200":
1444
+ $ref: "#/components/responses/JsonOk"
1445
+ "403":
1446
+ $ref: "#/components/responses/Forbidden"
1447
+ "500":
1448
+ $ref: "#/components/responses/ServerError"
1084
1449
  /v1/files/{path}:create_dnp:
1085
1450
  put:
1086
- summary: Create DNP image
1451
+ tags: [Files]
1452
+ operationId: createDnp
1453
+ summary: Create and format a DNP image.
1087
1454
  parameters:
1088
- - in: path
1089
- name: path
1090
- required: true
1091
- schema:
1092
- type: string
1093
- - in: query
1094
- name: tracks
1095
- required: true
1096
- schema:
1097
- type: integer
1098
- minimum: 1
1099
- maximum: 255
1100
- - in: query
1101
- name: diskname
1102
- schema:
1103
- type: string
1455
+ - $ref: "#/components/parameters/FilePath"
1456
+ - $ref: "#/components/parameters/DnpTracks"
1457
+ - $ref: "#/components/parameters/DiskName"
1104
1458
  responses:
1105
- '200':
1106
- description: Image created
1107
- content:
1108
- application/json:
1109
- schema:
1110
- $ref: '#/components/schemas/ErrorResponse'
1459
+ "200":
1460
+ $ref: "#/components/responses/JsonOk"
1461
+ "400":
1462
+ $ref: "#/components/responses/BadRequest"
1463
+ "403":
1464
+ $ref: "#/components/responses/Forbidden"
1465
+ "500":
1466
+ $ref: "#/components/responses/ServerError"