diff --git a/.gitignore b/.gitignore index 137ad8a..c77e7dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ # local utils and files local/* -build/* +build/ _build # temp files *.tmp - diff --git a/api/api_calls.rst b/api/api_calls.rst index e61c956..fc888dd 100644 --- a/api/api_calls.rst +++ b/api/api_calls.rst @@ -4,6 +4,8 @@ REST API Calls Starting from Ultimate firmware 3.11, the application supports API calls by means of the HTTP protocol. This simplifies the integration of remote control functionality in external applications, as it follows a well defined standard. +For generated clients and tooling, see the machine-readable :doc:`OpenAPI specification `. + The format of the URL is as follows: ``/v1//:?`` @@ -300,7 +302,10 @@ Machine - This U64-only command causes the machine to power off. Note that it is likely that you won't receive a valid response. * - ``PUT /v1/machine:menu_button`` - - - This command does the same thing as pressing the Menu button on an 1541 Ultimate cartridge, or briefly pressing the Multi Button on the Ultimate 64. The system will either enter or exit the Ultimate menu system depending on it's current state. + - This command does the same thing as pressing the Menu button on a 1541 Ultimate cartridge, or briefly pressing the Multi Button on the Ultimate 64. The system toggles the Ultimate menu: if the menu is closed, it opens; if the menu is open, it closes. + * - ``GET /v1/machine:menu_screen`` + - + - Returns the currently active firmware menu screen as a binary 40x25 character matrix followed by a 40x25 colour-attribute matrix. Use this together with ``/v1/machine:input`` to drive and inspect the menu over REST without using the video stream. If no readable menu screen is active, the endpoint returns ``404 Not Found`` with the normal JSON ``errors`` array. * - ``PUT /v1/machine:writemem`` - | *address* | *data* @@ -332,6 +337,190 @@ Machine - This command writes the value specified by the *value* argument (in hexadecimal) into the debug register ($D7FF), and then reads the debug register ($D7FF) and returns it in the "value" field of the JSON response. *This is currently an U64-only call.* +Menu Screen Response +^^^^^^^^^^^^^^^^^^^^ + +``GET /v1/machine:menu_screen`` returns ``Content-Type: application/octet-stream`` and +``Content-Disposition: attachment`` on success, with a ``Content-Length`` of ``2000``. The body is always exactly +2000 bytes: + +.. list-table:: + :widths: 20 20 60 + :header-rows: 1 + + * - Byte range + - Size + - Content + * - ``0..999`` + - 1000 bytes + - 40x25 character matrix + * - ``1000..1999`` + - 1000 bytes + - 40x25 colour-attribute matrix + +Both matrices are row-major. For a cell at *row* 0..24 and *column* 0..39, the offset within each matrix is:: + + offset = row * 40 + column + +Each colour-attribute byte stores both colours: + +.. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Bits + - Meaning + * - ``0..3`` + - Foreground colour + * - ``4..7`` + - Background colour + +The character matrix contains the firmware UI character bytes. Printable text is stored as normal printable character +values. Firmware box-drawing and UI glyphs use low character values, and reverse-video cells are marked by bit 7 of the +character byte. + +Input (U64 only) +^^^^^^^^^^^^^^^^ + +The input endpoint injects keyboard and joystick input on Ultimate 64-class hardware. + +.. list-table:: + :widths: 25 10 65 + :header-rows: 1 + + * - URL + - Parameters + - Action + * - ``GET /v1/machine:input`` + - + - Returns the currently active REST-injected keyboard and joystick inputs. + * - ``POST /v1/machine:input`` + - + - Applies a JSON batch of keyboard, joystick, and release-all events, then returns the resulting input state. The request body must use ``Content-Type: application/json``. + +On products that do not provide the required Ultimate 64 input hardware, these calls return HTTP status code ``501`` with +an error message. Password handling is the same as other REST API calls. + +The request body may be up to 4096 bytes. The successful response format is:: + + { + "keyboard": { + "inputs": ["left_shift", "a"] + }, + "joysticks": [ + { + "port": 1, + "inputs": [] + }, + { + "port": 2, + "inputs": ["up", "fire"] + } + ], + "errors": [] + } + +``POST /v1/machine:input`` expects a top-level object with an ``events`` array. The array must contain 1 to 64 events. +The complete batch is validated before any event is applied; if validation fails, the endpoint returns ``400 Bad +Request`` and leaves the current input state unchanged. + +Keyboard events +""""""""""""""" + +Keyboard events have this format:: + + { + "kind": "keyboard", + "inputs": ["left_shift", "a"], + "transition": "tap" + } + +``transition`` must be one of: + +.. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Transition + - Meaning + * - ``press`` + - Hold the listed inputs until they are released or all REST inputs are cleared. + * - ``release`` + - Release the listed inputs. + * - ``tap`` + - Press and release the listed inputs automatically. + +Valid keyboard input names are: + +``inst_del``, ``return``, ``cursor_left_right``, ``f7``, ``f1``, ``f3``, ``f5``, ``cursor_up_down``, +digits ``0`` through ``9``, letters ``a`` through ``z``, ``left_shift``, ``right_shift``, ``plus``, ``minus``, ``period``, ``colon``, ``at``, +``comma``, ``pound``, ``star``, ``semicolon``, ``clr_home``, ``equals``, ``arrow_up``, ``slash``, ``arrow_left``, +``ctrl``, ``space``, ``commodore``, ``run_stop``, and ``restore``. + +In the ranges above, each digit and each letter is a separate input name. + +The ``inputs`` array must contain 1 to 8 unique keyboard input names. ``restore`` is special: it must appear alone and +can only be used with ``"transition": "tap"``. + +When the firmware menu is active, keyboard events are translated to menu keystrokes. This allows a client to open the +menu with ``PUT /v1/machine:menu_button``, navigate or type with ``POST /v1/machine:input``, and read the result with +``GET /v1/machine:menu_screen``. + +Joystick events +""""""""""""""" + +Joystick events have this format:: + + { + "kind": "joystick", + "port": 2, + "inputs": ["up", "fire"], + "transition": "press" + } + +``port`` must be ``1`` or ``2``. Valid joystick input names are ``up``, ``down``, ``left``, ``right``, ``fire``, +``fire2``, and ``fire3``. The ``inputs`` array must contain 1 to 7 unique joystick input names. The same ``press``, +``release``, and ``tap`` transitions are supported. + +Release-all events +"""""""""""""""""" + +A release-all event clears every REST-injected keyboard and joystick input:: + + { + "kind": "release_all" + } + +It may not contain ``inputs``, ``port``, or ``transition``. A successful machine reset or reboot also clears the +REST-injected keyboard and joystick state. + +Example input batch +""""""""""""""""""" + +This example holds joystick port 2 up and fire, types ``A`` on the keyboard, and then releases all REST input state:: + + POST /v1/machine:input + Content-Type: application/json + + { + "events": [ + { + "kind": "joystick", + "port": 2, + "inputs": ["up", "fire"], + "transition": "press" + }, + { + "kind": "keyboard", + "inputs": ["left_shift", "a"], + "transition": "tap" + }, + { + "kind": "release_all" + } + ] + } + Floppy Drives ~~~~~~~~~~~~~ @@ -502,4 +691,3 @@ This section lists the API commands for file manipulation. This is the current s to be created. The number of tracks is a required argument to this function. Each track will have 256 sectors. The maximum number of tracks is 255, which makes the maximum DNP size almost 16 Megabytes. The optional *diskname* argument overrides the name to be used in the header of the disk. When not given, it is taken from the name of the file that is being created. - diff --git a/api/openapi.rst b/api/openapi.rst new file mode 100644 index 0000000..2dac63c --- /dev/null +++ b/api/openapi.rst @@ -0,0 +1,20 @@ +OpenAPI Specification +===================== + +The REST API is also available as an OpenAPI 3.1 document: + +:download:`Download rest_api_openapi.yaml ` + +The specification covers the Ultimate REST API for U64 and U2-family devices. It is based on the firmware REST API reference. + +Why this is useful +------------------ + +YAML-based OpenAPI documentation is useful because it is both documentation and a machine-readable contract: + +- Client libraries can be generated from it, reducing hand-written HTTP wrapper code. +- Test suites can validate that request and response shapes still match the documented firmware contract. +- Mock servers can use it to emulate the REST API during application development when no Ultimate device is available. +- API explorers and documentation tools can render it as an interactive reference. +- The exact path, method, parameter, request body, response body, header, and error shapes are kept in one structured file. +- Changes to the REST API can be reviewed as precise schema diffs, which makes omissions and incompatible changes easier to spot than in prose alone. diff --git a/api/rest_api_openapi.yaml b/api/rest_api_openapi.yaml new file mode 100644 index 0000000..628eea8 --- /dev/null +++ b/api/rest_api_openapi.yaml @@ -0,0 +1,1461 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.1/schema.yaml +openapi: 3.1.0 +info: + title: Ultimate REST API + version: "1.0.0" + summary: REST interface exposed by Ultimate 64 and 1541 Ultimate firmware >= 3.11. + description: | + This OpenAPI document captures the public HTTP interface described in the + official Ultimate REST API documentation at + https://1541u-documentation.readthedocs.io/en/latest/api/api_calls.html. + Responses always include an `errors` array unless noted. When a network + password is configured, clients must supply the `X-Password` header on every + request. Example payloads were captured against a local Ultimate 64 Elite + reachable as `http://u64` running firmware 3.12a. +servers: + - url: http://u64 + description: Ultimate device on the local network (example fixture) +components: + securitySchemes: + NetworkPassword: + type: apiKey + in: header + name: X-Password + description: Required only when a network password is configured on the Ultimate device. + schemas: + ErrorResponse: + type: object + required: + - errors + properties: + errors: + type: array + items: + type: string + VersionResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + required: + - version + properties: + version: + type: string + InfoResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + properties: + product: + type: string + firmware_version: + type: string + fpga_version: + type: string + core_version: + type: string + description: Present on Ultimate 64 devices. + hostname: + type: string + unique_id: + type: string + ConfigListResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + properties: + categories: + type: array + items: + type: string + ConfigCategoryResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + additionalProperties: + type: object + ConfigItemResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + additionalProperties: + type: object + MemoryReadJson: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + properties: + data: + oneOf: + - type: string + description: Base64 encoded bytes. + - type: array + items: + type: integer + format: int32 + minimum: 0 + maximum: 255 + MemoryDebugResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + required: + - value + properties: + value: + type: string + description: Hex string read from $D7FF. + DriveListResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + properties: + drives: + type: array + items: + type: object + additionalProperties: + type: object + properties: + enabled: + type: boolean + bus_id: + type: integer + type: + type: string + rom: + type: string + image_file: + type: string + image_path: + type: string + last_error: + type: string + partitions: + type: array + items: + type: object + properties: + id: + type: integer + path: + type: string + FileInfoResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + properties: + files: + type: object + properties: + path: + type: string + filename: + type: string + size: + type: integer + extension: + type: string + additionalProperties: true + MachineActionResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + MenuScreenUnavailableResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + example: + errors: + - Menu screen unavailable. + MenuScreenBytes: + type: string + format: binary + description: | + Exactly 2000 bytes. Bytes 0..999 are the 40x25 firmware UI character + matrix. Bytes 1000..1999 are the matching 40x25 colour-attribute + matrix. Both matrices are row-major: offset = row * 40 + column. + In each colour-attribute byte, bits 0..3 are the foreground colour + and bits 4..7 are the background colour. + minLength: 2000 + maxLength: 2000 + InputTransition: + type: string + enum: + - press + - release + - tap + KeyboardInputName: + type: string + enum: + - inst_del + - return + - cursor_left_right + - f7 + - f1 + - f3 + - f5 + - cursor_up_down + - "0" + - "1" + - "2" + - "3" + - "4" + - "5" + - "6" + - "7" + - "8" + - "9" + - a + - b + - c + - d + - e + - f + - g + - h + - i + - j + - k + - l + - m + - "n" + - o + - p + - q + - r + - s + - t + - u + - v + - w + - x + - "y" + - z + - left_shift + - right_shift + - plus + - minus + - period + - colon + - at + - comma + - pound + - star + - semicolon + - clr_home + - equals + - arrow_up + - slash + - arrow_left + - ctrl + - space + - commodore + - run_stop + - restore + description: | + REST input name from the C64 keyboard matrix. `restore` is special: + firmware accepts it only as the sole input in a keyboard event with + transition `tap`. + JoystickInputName: + type: string + enum: + - up + - down + - left + - right + - fire + - fire2 + - fire3 + KeyboardInputEvent: + type: object + additionalProperties: false + required: + - kind + - inputs + - transition + properties: + kind: + type: string + const: keyboard + inputs: + type: array + minItems: 1 + maxItems: 8 + uniqueItems: true + items: + $ref: "#/components/schemas/KeyboardInputName" + transition: + $ref: "#/components/schemas/InputTransition" + JoystickInputEvent: + type: object + additionalProperties: false + required: + - kind + - port + - inputs + - transition + properties: + kind: + type: string + const: joystick + port: + type: integer + enum: + - 1 + - 2 + inputs: + type: array + minItems: 1 + maxItems: 7 + uniqueItems: true + items: + $ref: "#/components/schemas/JoystickInputName" + transition: + $ref: "#/components/schemas/InputTransition" + ReleaseAllInputEvent: + type: object + additionalProperties: false + required: + - kind + properties: + kind: + type: string + const: release_all + InputEvent: + oneOf: + - $ref: "#/components/schemas/KeyboardInputEvent" + - $ref: "#/components/schemas/JoystickInputEvent" + - $ref: "#/components/schemas/ReleaseAllInputEvent" + InputRequest: + type: object + additionalProperties: false + required: + - events + properties: + events: + type: array + minItems: 1 + maxItems: 64 + items: + $ref: "#/components/schemas/InputEvent" + KeyboardInputState: + type: object + required: + - inputs + properties: + inputs: + type: array + items: + $ref: "#/components/schemas/KeyboardInputName" + JoystickInputState: + type: object + required: + - port + - inputs + properties: + port: + type: integer + enum: + - 1 + - 2 + inputs: + type: array + items: + $ref: "#/components/schemas/JoystickInputName" + InputStateResponse: + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + required: + - keyboard + - joysticks + properties: + keyboard: + $ref: "#/components/schemas/KeyboardInputState" + joysticks: + type: array + minItems: 2 + maxItems: 2 + items: + $ref: "#/components/schemas/JoystickInputState" + RunnerActionResponse: + description: Standard response for runner control actions. + allOf: + - $ref: "#/components/schemas/ErrorResponse" + - type: object + +security: + - {} + - NetworkPassword: [] + +paths: + /v1/version: + get: + summary: Get API version + description: Returns the firmware-defined REST API semantic version. + responses: + "200": + description: Successful response + content: + application/json: + schema: + $ref: "#/components/schemas/VersionResponse" + examples: + live: + value: + version: "0.1" + errors: [] + /v1/info: + get: + summary: Get device information + description: >- + Returns hardware metadata (product, firmware version, FPGA/core + versions, hostname). Available on Ultimate firmware 3.12 and newer. On + earlier releases the endpoint responds with HTTP 404. + responses: + "200": + description: Successful response + content: + application/json: + schema: + $ref: "#/components/schemas/InfoResponse" + examples: + live: + value: + product: Ultimate 64 Elite + firmware_version: "3.12a" + fpga_version: "121" + core_version: "1.45" + hostname: c64u + unique_id: 38C1BA + errors: [] + /v1/runners:sidplay: + put: + summary: Play SID from filesystem + parameters: + - in: query + name: file + required: true + schema: + type: string + - in: query + name: songnr + schema: + type: integer + minimum: 0 + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + post: + summary: Play uploaded SID + description: > + Upload a SID file for playback. Optionally attach a song-lengths (.ssl) file + as the second multipart file to specify per-subsong durations. + parameters: + - in: query + name: songnr + schema: + type: integer + minimum: 0 + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: array + minItems: 1 + maxItems: 2 + items: + type: string + format: binary + description: > + Multipart field name used for uploads. The first entry is the SID file + to play. The optional second entry is a .ssl song-lengths file: a binary + array of 2-byte entries, one per subsong in order: [minutes, seconds], + both packed BCD. Minutes range 00-99, seconds range 00-59. Max 512 bytes + (256 entries). Missing or invalid entries are replaced with firmware defaults. + required: + - file + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + + /v1/runners:modplay: + put: + summary: Play MOD from filesystem + parameters: + - in: query + name: file + required: true + schema: + type: string + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + post: + summary: Play uploaded MOD + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + /v1/runners:load_prg: + put: + summary: Load PRG from filesystem + parameters: + - in: query + name: file + required: true + schema: + type: string + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + post: + summary: Load uploaded PRG + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + /v1/runners:run_prg: + put: + summary: Run PRG from filesystem + parameters: + - in: query + name: file + required: true + schema: + type: string + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + post: + summary: Run uploaded PRG + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + /v1/runners:run_crt: + put: + summary: Run cartridge from filesystem + parameters: + - in: query + name: file + required: true + schema: + type: string + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + post: + summary: Run uploaded cartridge + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Request accepted + content: + application/json: + schema: + $ref: "#/components/schemas/RunnerActionResponse" + /v1/configs: + get: + summary: List configuration categories + description: Enumerates top-level configuration pages as displayed in the + Ultimate menu. Supports wildcard queries via URL encoding. + responses: + "200": + description: Categories returned + content: + application/json: + schema: + $ref: "#/components/schemas/ConfigListResponse" + examples: + live: + value: + categories: + - Audio Mixer + - SID Sockets Configuration + - UltiSID Configuration + - SID Addressing + - U64 Specific Settings + - C64 and Cartridge Settings + - Clock Settings + - Network Settings + - Ethernet Settings + - WiFi settings + - LED Strip Settings + - Data Streams + - SoftIEC Drive Settings + - Printer Settings + - Modem Settings + - User Interface Settings + - Tape Settings + - Drive A Settings + - Drive B Settings + errors: [] + post: + summary: Batch update configuration + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: + type: object + responses: + "200": + description: Update applied + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/configs/{category}: + get: + summary: Inspect category + description: Returns all items inside the specified category. Wildcards + may match multiple categories; each appears as an object property in the + response. + parameters: + - in: path + name: category + required: true + schema: + type: string + responses: + "200": + description: Category returned + content: + application/json: + schema: + $ref: "#/components/schemas/ConfigCategoryResponse" + examples: + drive_a: + summary: Drive A Settings (firmware 3.12a) + value: + Drive A Settings: + Drive: Enabled + Drive Type: "1541" + Drive Bus ID: 8 + ROM for 1541 mode: 1541.rom + ROM for 1571 mode: 1571.rom + ROM for 1581 mode: 1581.rom + Extra RAM: Disabled + Disk swap delay: 1 + Resets when C64 resets: "Yes" + Freezes in menu: "Yes" + GCR Save Align Tracks: "Yes" + Leave Menu on Mount: "Yes" + D64 Geos Copy Protection: none + errors: [] + /v1/configs/{category}/{item}: + get: + summary: Inspect configuration item + parameters: + - in: path + name: category + required: true + schema: + type: string + - in: path + name: item + required: true + schema: + type: string + responses: + "200": + description: Item returned + content: + application/json: + schema: + $ref: "#/components/schemas/ConfigItemResponse" + put: + summary: Update configuration item + parameters: + - in: path + name: category + required: true + schema: + type: string + - in: path + name: item + required: true + schema: + type: string + - in: query + name: value + required: true + schema: + type: string + responses: + "200": + description: Update applied + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/configs:load_from_flash: + put: + summary: Load configuration from flash + responses: + "200": + description: Loaded + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/configs:save_to_flash: + put: + summary: Save configuration to flash + responses: + "200": + description: Saved + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/configs:reset_to_default: + put: + summary: Reset configuration to defaults + responses: + "200": + description: Reset complete + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/machine:reset: + put: + summary: Soft reset machine + responses: + "200": + description: Reset triggered + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:reboot: + put: + summary: Reboot machine + responses: + "200": + description: Reboot triggered + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:pause: + put: + summary: Pause machine via DMA + responses: + "200": + description: Pause applied + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:resume: + put: + summary: Resume machine from pause + responses: + "200": + description: Resume applied + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:poweroff: + put: + summary: Power off machine + responses: + "200": + description: Power off requested + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:menu_button: + put: + summary: Toggle Ultimate menu button + description: Toggles the Ultimate firmware menu, equivalent to pressing + the physical menu button. If the menu is closed it opens; if the menu is + open it closes. + responses: + "200": + description: Button event queued + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:menu_screen: + get: + summary: Read active firmware menu screen + description: | + Returns the active 40x25 firmware menu text-mode screen as two raw + matrices. The first 1000 bytes are character bytes; the second 1000 + bytes are colour-attribute bytes. This endpoint is intended to be used + with `/v1/machine:menu_button` and `/v1/machine:input` to drive and + inspect the firmware menu over REST. + responses: + "200": + description: Readable 40x25 menu screen returned + headers: + Content-Disposition: + schema: + type: string + const: attachment + Content-Length: + schema: + type: integer + const: 2000 + content: + application/octet-stream: + schema: + $ref: "#/components/schemas/MenuScreenBytes" + "404": + description: No readable menu screen is currently available + content: + application/json: + schema: + $ref: "#/components/schemas/MenuScreenUnavailableResponse" + examples: + unavailable: + value: + errors: + - Menu screen unavailable. + /v1/machine:input: + get: + summary: Get REST-injected input state + description: Returns the currently active keyboard and joystick inputs + injected through the REST input endpoint. Ultimate 64-class input + hardware is required. + responses: + "200": + description: Input state returned + content: + application/json: + schema: + $ref: "#/components/schemas/InputStateResponse" + examples: + empty: + value: + keyboard: + inputs: [] + joysticks: + - port: 1 + inputs: [] + - port: 2 + inputs: [] + errors: [] + "501": + description: Keyboard and joystick injection are not available on this hardware + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + post: + summary: Inject keyboard and joystick input + description: | + Applies a validated batch of keyboard, joystick, and release-all events, + then returns the resulting input state. The firmware validates the + complete batch before applying any event; invalid batches return HTTP + 400 and leave the current input state unchanged. When the firmware menu + is active, keyboard events are translated to menu keystrokes. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/InputRequest" + examples: + shifted_key_and_joystick: + value: + events: + - kind: joystick + port: 2 + inputs: + - up + - fire + transition: press + - kind: keyboard + inputs: + - left_shift + - a + transition: tap + responses: + "200": + description: Events applied + content: + application/json: + schema: + $ref: "#/components/schemas/InputStateResponse" + "400": + description: Invalid body, content type, or event batch + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "501": + description: Keyboard and joystick injection are not available on this hardware + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/machine:writemem: + put: + summary: Write memory via query data + parameters: + - in: query + name: address + required: true + schema: + type: string + description: Hexadecimal start address. + - in: query + name: data + required: true + schema: + type: string + description: Hex string representing bytes (up to 128 bytes). + responses: + "200": + description: Write applied + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + post: + summary: Write memory via binary payload + parameters: + - in: query + name: address + required: true + schema: + type: string + description: Hexadecimal start address. + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Write applied + content: + application/json: + schema: + $ref: "#/components/schemas/MachineActionResponse" + /v1/machine:readmem: + get: + summary: Read memory + description: Performs a DMA read at the requested address. Firmware + returns either a JSON wrapper or raw bytes. Use `length` to limit the + transfer (default 256 bytes). + parameters: + - in: query + name: address + required: true + schema: + type: string + description: Hexadecimal start address. + - in: query + name: length + schema: + type: integer + minimum: 1 + maximum: 4096 + responses: + "200": + description: Memory data + content: + application/json: + schema: + $ref: "#/components/schemas/MemoryReadJson" + application/octet-stream: + schema: + type: string + format: binary + examples: + vic_border: + summary: Base64 rendering of two raw bytes for $D020-$D021 + value: "/vY=" + /v1/machine:debugreg: + get: + summary: Read debug register + responses: + "200": + description: Register value + content: + application/json: + schema: + $ref: "#/components/schemas/MemoryDebugResponse" + put: + summary: Write debug register + parameters: + - in: query + name: value + required: true + schema: + type: string + description: Hexadecimal value to write. + responses: + "200": + description: Updated register value + content: + application/json: + schema: + $ref: "#/components/schemas/MemoryDebugResponse" + /v1/drives: + get: + summary: List internal drives + description: Returns current Ultimate-managed drives, images, and service + devices (SoftIEC, printer emulation). + responses: + "200": + description: Drive information + content: + application/json: + schema: + $ref: "#/components/schemas/DriveListResponse" + examples: + live: + value: + drives: + - a: + enabled: true + bus_id: 8 + type: "1541" + rom: "1541.rom" + image_file: "" + image_path: "" + - b: + enabled: false + bus_id: 9 + type: "1541" + rom: "1541.rom" + image_file: "" + image_path: "" + - IEC Drive: + bus_id: 11 + enabled: false + type: "DOS emulation" + last_error: "73,U64IEC ULTIMATE DOS V1.1,00,00" + partitions: + - id: 0 + path: "/Usb0/" + - Printer Emulation: + bus_id: 4 + enabled: false + errors: [] + /v1/drives/{drive}:mount: + put: + summary: Mount disk image from filesystem + parameters: + - in: path + name: drive + required: true + schema: + type: string + - in: query + name: image + required: true + schema: + type: string + - in: query + name: type + schema: + type: string + enum: [d64, g64, d71, g71, d81] + - in: query + name: mode + schema: + type: string + enum: [readwrite, readonly, unlinked] + responses: + "200": + description: Mount complete + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + post: + summary: Mount uploaded disk image + parameters: + - in: path + name: drive + required: true + schema: + type: string + - in: query + name: type + schema: + type: string + enum: [d64, g64, d71, g71, d81] + - in: query + name: mode + schema: + type: string + enum: [readwrite, readonly, unlinked] + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: Mount complete + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:reset: + put: + summary: Reset drive + parameters: + - in: path + name: drive + required: true + schema: + type: string + responses: + "200": + description: Reset complete + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:remove: + put: + summary: Remove mounted image + parameters: + - in: path + name: drive + required: true + schema: + type: string + responses: + "200": + description: Removal complete + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:on: + put: + summary: Power on drive + parameters: + - in: path + name: drive + required: true + schema: + type: string + responses: + "200": + description: Drive powered on + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:off: + put: + summary: Power off drive + parameters: + - in: path + name: drive + required: true + schema: + type: string + responses: + "200": + description: Drive powered off + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:load_rom: + put: + summary: Load ROM from filesystem + parameters: + - in: path + name: drive + required: true + schema: + type: string + - in: query + name: file + required: true + schema: + type: string + responses: + "200": + description: ROM loaded + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + post: + summary: Load ROM from upload + parameters: + - in: path + name: drive + required: true + schema: + type: string + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: ROM loaded + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/drives/{drive}:set_mode: + put: + summary: Set drive mode + parameters: + - in: path + name: drive + required: true + schema: + type: string + - in: query + name: mode + required: true + schema: + type: string + enum: [1541, 1571, 1581] + responses: + "200": + description: Mode updated + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/streams/{stream}:start: + put: + summary: Start data stream + parameters: + - in: path + name: stream + required: true + schema: + type: string + enum: [video, audio, debug] + - in: query + name: ip + required: true + schema: + type: string + description: Target IP address with optional port (ip[:port]). + responses: + "200": + description: Stream started + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/streams/{stream}:stop: + put: + summary: Stop data stream + parameters: + - in: path + name: stream + required: true + schema: + type: string + enum: [video, audio, debug] + responses: + "200": + description: Stream stopped + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/files/{path}:info: + get: + summary: Inspect file metadata + parameters: + - in: path + name: path + required: true + schema: + type: string + responses: + "200": + description: Metadata returned + content: + application/json: + schema: + $ref: "#/components/schemas/FileInfoResponse" + examples: + live: + value: + files: + path: /Flash/roms/1541.rom + filename: 1541.rom + size: 16384 + extension: ROM + errors: [] + /v1/files/{path}:create_d64: + put: + summary: Create D64 image + parameters: + - in: path + name: path + required: true + schema: + type: string + - in: query + name: tracks + schema: + type: integer + enum: [35, 40] + - in: query + name: diskname + schema: + type: string + responses: + "200": + description: Image created + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/files/{path}:create_d71: + put: + summary: Create D71 image + parameters: + - in: path + name: path + required: true + schema: + type: string + - in: query + name: diskname + schema: + type: string + responses: + "200": + description: Image created + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/files/{path}:create_d81: + put: + summary: Create D81 image + parameters: + - in: path + name: path + required: true + schema: + type: string + - in: query + name: diskname + schema: + type: string + responses: + "200": + description: Image created + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + /v1/files/{path}:create_dnp: + put: + summary: Create DNP image + parameters: + - in: path + name: path + required: true + schema: + type: string + - in: query + name: tracks + required: true + schema: + type: integer + minimum: 1 + maximum: 255 + - in: query + name: diskname + schema: + type: string + responses: + "200": + description: Image created + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" diff --git a/howto/machine_code_monitor.rst b/howto/machine_code_monitor.rst new file mode 100644 index 0000000..d11a6d9 --- /dev/null +++ b/howto/machine_code_monitor.rst @@ -0,0 +1,577 @@ +Machine Code Monitor +==================== + +The Machine Code Monitor is a keyboard-driven tool for inspecting and editing live or frozen C64 memory. + +It supports hexadecimal, ASCII, screen-code, binary, and assembly views, plus inline editing, bulk memory operations, file load/save, and execution from a selected address. + +Almost every command is a single keypress, and the monitor stays open until you exit it, so you can move freely between views and operations. If you forget a key, press ``F3`` for the on-screen help. + +*Applies to: Ultimate 1541-II, Ultimate-II+, Ultimate 64* + +Entry and Exit +-------------- + +``C=`` denotes the Commodore key. For example, ``C=+O`` means: hold the Commodore key, then press ``O``. + +To open the monitor, use one of the following: + +- Press ``C=+O``. +- Press ``F5``, open ``Developer``, then select ``Machine Code Monitor``. + +Open the built-in help with ``F3`` or ``?``. It lists every key binding: + +.. image:: ../media/monitor/help_view.png + :alt: Monitor built-in help screen listing key bindings + +To close the monitor: + +- Press ``C=+O`` again. +- Press ``RUN/STOP`` when no edit operation or popup is active. + +Screen Layout +------------- + +The monitor screen has three fixed regions: + +Header +~~~~~~ + +- Shows the current view, cursor address, and active modes. +- Mode indicators may include ``Undoc``, ``Frz``, ``Poll``, or ``EDIT``. + +Body +~~~~ + +- Shows the memory region around the current cursor address. +- The active cursor position is highlighted in reverse. +- May show popups, such as search results, load/save prompts, completion pickers, or bookmarks. + +Footer +~~~~~~ + +- Shows the active CPU port mapping and VIC bank. For more details, see :ref:`machine-monitor-cpu-vic-bank-display`. +- ``CPU0``..\ ``CPU7`` identify the selected CPU memory configuration. +- ``VIC0``..\ ``VIC3`` identify the selected VIC bank and its base address. +- When jumping to a bookmark, the footer briefly shows bookmark information. + +Example layout, with the ``Undoc``, ``Poll``, and ``EDIT`` mode indicators active in the header: + +.. image:: ../media/monitor/layout_example.png + :alt: Monitor screen layout showing the header, body, and footer regions + +Views +----- + +The monitor provides five primary views: + +===== ======== === =============================== +Key View ID Purpose +===== ======== === =============================== +``M`` Memory HEX Hexadecimal byte view +``A`` Assembly ASM Disassembly and inline assembly +``B`` Binary BIN Bit-level byte view +``I`` ASCII ASC ASCII byte view +``V`` Screen SCR Screen code view +===== ======== === =============================== + +.. _memory--hex-view: + +Memory / Hex View +~~~~~~~~~~~~~~~~~ + +Memory view shows raw bytes in hexadecimal together with a compact printable-character preview. + +Example: + +.. image:: ../media/monitor/hex_view.png + :alt: Monitor Memory / Hex view at $0168 + +Assembly View +~~~~~~~~~~~~~ + +Assembly view shows decoded 6510 instructions, their instruction bytes, and the memory source used for each row. + +Example: + +.. image:: ../media/monitor/assembly_view.png + :alt: Monitor Assembly view at $E011 + +Assembly view is also a full inline assembler: in edit mode it offers opcode completion as you type. See :ref:`machine-monitor-inline-assembler`. + +Binary View +~~~~~~~~~~~ + +Binary view shows each byte as eight bits, using ``.`` for a cleared bit and ``*`` for a set bit. It is useful for inspecting registers, character glyphs, sprite data, and other bit-oriented memory. + +Because C64 sprite data uses 3 bytes per row, binary view supports multiple ``W``\ idth modes for viewing bytes in different groupings. + +The top status line shows the current byte address followed by the selected bit number, for example ``$DC00/7``. Bit 7 is the most significant bit on the left, and bit 0 is the least significant bit on the right. + +Example: + +.. image:: ../media/monitor/binary_view.png + :alt: Monitor Binary view at $DC00 + +Cycling the ``W`` width mode to ``3S`` makes each row span the full 24 bits of a sprite line, so 21 consecutive rows display a whole C64 sprite as a bitmap. Here a sprite stored at ``$2000``: + +.. image:: ../media/monitor/binary_sprite.png + :alt: Binary view in 3S sprite mode showing a 24 by 21 sprite bitmap + +ASCII View +~~~~~~~~~~ + +Use ASCII view when the bytes are intended to be printable ASCII rather than C64 screen codes. + +Behavior: + +- Bytes ``$20-$7E`` are shown as their normal ASCII characters. +- All other bytes are shown as ``.``. +- Typing a printable ASCII character writes that character's byte value. +- Lowercase ASCII is preserved. + +Example: + +.. image:: ../media/monitor/ascii_view.png + :alt: Monitor ASCII view at $A000 + +Screen View +~~~~~~~~~~~ + +Use Screen view when the bytes represent C64 screen codes, for example when viewing screen RAM, which by default starts at ``$0400``. + +Screen view is for screen-code bytes, not PETSCII text. + +The header shows the active screen charset mode: + +- ``MONITOR SCR U/G $xxxx`` for **Uppercase/Graphics** +- ``MONITOR SCR L/U $xxxx`` for **Lowercase/Uppercase** + +The active mode is changed with ``U``; see :ref:`machine-monitor-view-modifiers`. + +Screen ``U/G`` +^^^^^^^^^^^^^^ + +- Displays ``$00`` as ``@``. +- Displays ``$01-$1A`` as ``A-Z``. +- Typing ``A-Z`` or ``a-z`` writes ``$01-$1A``. + +Screen ``L/U`` +^^^^^^^^^^^^^^ + +- Displays ``$01-$1A`` as ``a-z``. +- Displays ``$41-$5A`` as ``A-Z``. +- Typing ``a-z`` writes ``$01-$1A``. +- Typing ``A-Z`` writes ``$41-$5A``. + +Example: + +.. image:: ../media/monitor/screen_view.png + :alt: Monitor Screen view at $0400 + +Because the monitor is rendered with the firmware UI font rather than the live C64 character set, graphics bytes are shown with readable fallback glyphs instead of exact C64 glyph shapes. + +.. _machine-monitor-view-modifiers: + +View Modifiers +-------------- + +Some keys modify the current view instead of switching to another view. + +``U``: View-Specific Toggle +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``U`` is context-sensitive: + ++-------------+----------------------------------------------------------------------+ +| View | ``U`` behavior | ++=============+======================================================================+ +| Assembly | Toggles undocumented opcodes | ++-------------+----------------------------------------------------------------------+ +| Screen | Toggles the monitor-local screen charset between ``U/G`` and ``L/U`` | ++-------------+----------------------------------------------------------------------+ +| Other views | Ignored | ++-------------+----------------------------------------------------------------------+ + +In Assembly view, enabling undocumented opcodes affects how bytes are decoded and how assembly completion behaves. + +In Screen view, ``U`` changes only the monitor-local interpretation of screen codes. It does not change the live C64 character set. + +``W``: Width Mode +~~~~~~~~~~~~~~~~~ + +``W`` is view-dependent: + +======== ====================================== +View ``W`` behavior +======== ====================================== +Memory Cycles ``8 <-> 16`` bytes per row +Binary Cycles ``1 -> 2 -> 3 -> 3S -> 4 -> 1`` +ASCII Fixed-width, 32 bytes per row +Screen Fixed-width, 32 bytes per row +Assembly Variable-width, 1 to 3 bytes +======== ====================================== + +Binary width details: + +- ``1``, ``2``, and ``3`` show one, two, or three bytes as bit fields with a trailing hex preview. +- ``3S`` shows three bytes as one continuous 24-bit sprite-style row, with a hex preview. +- ``4`` shows four bytes as one continuous 32-bit row without a trailing hex preview. + +Navigation and Context +---------------------- + +- ``J``: jump to an address. +- ``G``: exit the monitor and execute from an address. +- ``F1`` or ``Shift+Space``: page up. +- ``F7`` or ``Space``: page down. +- ``Enter``: in Assembly view, follow the target of a jumpable instruction, or return to the most recent saved source location when the current instruction is not jumpable and the follow stack is non-empty. +- ``O``: cycle CPU port banking, ``CPU0``..\ ``CPU7``. +- ``Shift+O``: cycle the VIC bank override. +- ``Z``: toggle freeze when the backend supports it. +- ``P``: toggle poll mode in the local monitor. Poll mode is unavailable over telnet. + +Addresses in command prompts are hexadecimal. + +Follow/Return +~~~~~~~~~~~~~ + +Follow code flow in the Assembly view: + +- ``Enter`` follows the resolved target when the cursor is on a jumpable instruction such as ``JMP``, ``JSR``, ``BEQ``, ``BNE``, ``BCC``, ``BCS``, ``BMI``, ``BPL``, ``BVC``, or ``BVS``. +- ``Enter`` returns to the most recent saved source location when the current Assembly instruction is not jumpable and the follow stack is non-empty. +- The follow stack holds up to 10 return locations. When it is full, the oldest entry is discarded and the newest 10 are kept. +- After each successful follow or return, the bottom row shows a compact zero-based follow-stack status for about 2 seconds, for example ``F1 JMP $E000`` and ``F0 RET $A000``. + +.. _machine-monitor-cpu-vic-bank-display: + +CPU and VIC Bank Display +~~~~~~~~~~~~~~~~~~~~~~~~ + +The footer summarizes the selected CPU-visible memory configuration and VIC bank, for example ``CPU7 $A:BAS $D:I/O $E:KRN VIC0 $0000``. + +``CPU0``..\ ``CPU7`` are shorthand for the three 6510 port memory-configuration bits at ``$0001``: ``LORAM``, ``HIRAM``, and ``CHAREN``. + +In the normal no-cartridge configuration, the footer fields have these possible values: + +====== =============== ========================= +Field Address range Values +====== =============== ========================= +``$A`` ``$A000-$BFFF`` ``BAS``, ``RAM`` +``$D`` ``$D000-$DFFF`` ``I/O``, ``CHR``, ``RAM`` +``$E`` ``$E000-$FFFF`` ``KRN``, ``RAM`` +====== =============== ========================= + +======= =========================== +Value Meaning +======= =========================== +``BAS`` BASIC ROM +``I/O`` I/O registers and Color RAM +``CHR`` Character generator ROM +``KRN`` KERNAL ROM +``RAM`` RAM +======= =========================== + +``VIC0``..\ ``VIC3`` show the selected VIC bank controlled through CIA 2 port A at ``$DD00``, with base address ``$0000``, ``$4000``, ``$8000``, or ``$C000``. + +Cartridges can further affect the CPU-visible memory map through the expansion-port ``GAME`` and ``EXROM`` lines. + +Editing +------- + +All views support editing: + +- ``E``: enter edit mode. +- ``C=+E`` or ``RUN/STOP``: leave edit mode. + +Edit behavior is view-specific: + ++----------+----------------------------------------------------------------------------------+ +| View | Edit behavior | ++==========+==================================================================================+ +| Memory | Type two hex nibbles to write one byte | ++----------+----------------------------------------------------------------------------------+ +| ASCII | Type printable ASCII characters directly | ++----------+----------------------------------------------------------------------------------+ +| Screen | Type screen characters using the active Screen charset mode | ++----------+----------------------------------------------------------------------------------+ +| Binary | Type ``0`` or ``Space`` to clear the selected bit; type ``1`` or ``*`` to set it | ++----------+----------------------------------------------------------------------------------+ +| Assembly | Edit instructions inline with mnemonic completion and direct operand typing | ++----------+----------------------------------------------------------------------------------+ + +In edit mode, ``Space`` remains view-specific data entry and does not page. + +``DEL`` is logical delete, not raw backspace: + +============ =================================================== +View ``DEL`` behavior +============ =================================================== +Memory Writes ``$00`` and advances +ASCII/Screen Writes a space +Binary Clears the selected bit +Assembly Replaces the current instruction with ``NOP`` bytes +============ =================================================== + +In Assembly view, if an inline edit is already active, ``DEL`` first cancels the current line edit state. + +.. _machine-monitor-inline-assembler: + +Inline Assembler +~~~~~~~~~~~~~~~~~ + +Assembly view is a full inline assembler, not just a disassembler. In edit mode, typing the first letter of a mnemonic opens an opcode completion drop-down beside the current instruction. The drop-down lists every matching opcode together with its addressing mode, and narrows as you type: + +.. image:: ../media/monitor/asm_opcode_completion.png + :alt: Opcode completion drop-down in the inline assembler + +- Each further mnemonic letter narrows the list. The drop-down header shows the typed prefix and the number of remaining matches. +- ``Up`` and ``Down`` move through the candidates. +- Once the three-letter mnemonic is complete, type the operand directly, for example ``#$00`` or ``$D020``. +- ``Return`` accepts the highlighted opcode, or the operand you typed, and writes the instruction in place. +- ``RUN/STOP`` closes the drop-down and leaves the instruction unchanged. + +Undocumented opcodes appear in the drop-down only when they are enabled with ``U``; see :ref:`machine-monitor-view-modifiers`. + +Selection and Clipboard +----------------------- + +- Copy the current byte with ``C=+C``. +- Paste the clipboard at the cursor with ``C=+V``. +- Toggle range mode with ``R``. + +Range mode anchors the current address. The selected span runs from the anchor address to the current cursor address, inclusive. + +While range mode is active: + +- ``C=+C`` copies the selected span. +- Pressing ``R`` again also copies the selected span and exits range mode. + +Number Tool +----------- + +- Open the number tool with ``N``. + +The number tool is a compact base-conversion and overwrite popup for the current target. It shows the same value in these forms: + +- Hex +- Decimal +- Binary +- ASCII +- Screen code + +.. image:: ../media/monitor/number_tool.png + :alt: Monitor Number tool showing one byte in five forms + +In Assembly view, the number tool targets the operand bytes of the current instruction when possible. + +The ASCII and Screen rows in the number tool use the same mappings as the ASCII and Screen views. + +Calculator +~~~~~~~~~~ + +In the Number popup, press ``+``, ``-``, ``*``, or ``/`` to open the calculator. The expression is initialized with the current value and the selected operator. + +.. image:: ../media/monitor/calculator.png + :alt: Monitor Number tool calculator evaluating an expression + +Press ``Return`` or ``=`` to evaluate the expression. Press ``RUN/STOP`` to cancel. On success, the popup returns to the compact conversion layout and refreshes all rows with the result. + +Expressions may contain one or more values separated by ``+``, ``-``, ``*``, or ``/``. \* and / are evaluated before + and -. Division is unsigned integer division and truncates toward zero. + +Examples: + +.. code:: text + + 42 + $1000+4 + $2000/16 + %1010*3 + 1+2/3 + 2+3*4 + +Formal EBNF grammar: + +.. code:: ebnf + + expr = term, { ("+" | "-"), term } ; + term = value, { ("*" | "/"), value } ; + value = hex | decimal | binary ; + + hex = "$", hex_digits ; + decimal = decimal_digits ; + binary = "%", binary_digits ; + +Memory Operations +----------------- + +The monitor includes direct bulk memory commands: + ++-------+----------+---------------------------------------------+-----------------------------------------------------------------------+ +| Key | Command | Syntax | Result | ++=======+==========+=============================================+=======================================================================+ +| ``F`` | Fill | ``start-end,value`` | Fill an inclusive range with one byte | ++-------+----------+---------------------------------------------+-----------------------------------------------------------------------+ +| ``T`` | Transfer | ``start-end,dest`` | Copy a range to a destination | ++-------+----------+---------------------------------------------+-----------------------------------------------------------------------+ +| ``C`` | Compare | ``start-end,dest`` | Compare a range against another location and list differing addresses | ++-------+----------+---------------------------------------------+-----------------------------------------------------------------------+ +| ``H`` | Hunt | ``start-end,bytes`` or ``start-end,"text"`` | Search for a byte sequence or quoted ASCII string | ++-------+----------+---------------------------------------------+-----------------------------------------------------------------------+ + +``Hunt`` prompts for a range followed by a byte sequence or quoted text: + +.. image:: ../media/monitor/hunt_search.png + :alt: Monitor Hunt search prompt + +Matches are listed in a result picker: + +.. image:: ../media/monitor/hunt_results.png + :alt: Monitor Hunt result picker + +- ``Return``: jump to the selected match. +- ``RUN/STOP``: close the picker. + +File I/O +-------- + +- ``L``: load a file into memory. +- ``S``: save memory to a file. + +Files may exist directly in the Ultimate filesystem or inside a disk image such as ``.D64``. + +Load +~~~~ + +Load is a two-step flow: + +1. Pick a file. +2. Enter load parameters. + +In the file picker, select an existing file by pressing ``ENTER`` on it, then choosing ``Select`` from the context-sensitive menu. + +.. image:: ../media/monitor/load_picker.png + :alt: Monitor Load file picker + +.. image:: ../media/monitor/load_select.png + :alt: Choosing Select from the Load context menu + +Load syntax: + +.. code:: text + + [PRG|AAAA],[Offset],[Len|AUTO] + +Default: + +.. code:: text + + PRG,0000,AUTO + +This loads the whole file to the start address stored in its first two bytes. + +.. image:: ../media/monitor/load_params.png + :alt: Monitor Load parameters prompt + +Fields: + ++---------------------+---------------------------------------------------------------------------------+ +| Field | Meaning | ++=====================+=================================================================================+ +| ``PRG`` or ``AAAA`` | Use the two-byte load address from the PRG file, or load to an explicit address | ++---------------------+---------------------------------------------------------------------------------+ +| ``Offset`` | Number of bytes to skip after the PRG header | ++---------------------+---------------------------------------------------------------------------------+ +| ``Len`` or ``AUTO`` | Load the automatically determined length, or load an explicit byte count | ++---------------------+---------------------------------------------------------------------------------+ + +Examples: + ++--------------------+---------------------------------------------------------+ +| Input | Meaning | ++====================+=========================================================+ +| ``PRG`` | Load a PRG to its embedded load address | ++--------------------+---------------------------------------------------------+ +| ``0801`` | Load to ``$0801`` | ++--------------------+---------------------------------------------------------+ +| ``PRG,1000`` | Skip ``$1000`` bytes after the PRG header | ++--------------------+---------------------------------------------------------+ +| ``0801,0002,0010`` | Load ``$0010`` bytes from offset ``$0002`` to ``$0801`` | ++--------------------+---------------------------------------------------------+ + +Save +~~~~ + +Save is a two-step flow: + +1. Enter the byte range to save. +2. Pick or create the destination file. + +Save syntax: + +.. code:: text + + 0800-9FFF + +The range is inclusive. Save writes a normal PRG file with a two-byte load address header. + +.. image:: ../media/monitor/save_range.png + :alt: Monitor Save range prompt + +In the file picker, pick an existing file to overwrite it, or choose ``<< Create new file >>`` to write a new file: + +.. image:: ../media/monitor/save_picker.png + :alt: Monitor Save destination picker + +Selecting ``<< Create new file >>`` prompts for the new file name: + +.. image:: ../media/monitor/save_filename.png + :alt: Monitor Save new file name prompt + +Bookmarks +--------- + +The monitor has 10 persistent bookmark slots. + +- List bookmarks with ``C=+B``. +- Jump directly to a slot with ``C=+0`` .. ``C=+9``. + +Each bookmark stores: + +- Label +- Address +- View ID +- View width or width mode where applicable +- CPU bank +- VIC bank + +Bookmark popup controls: + +=============== ================================================= +Key Action +=============== ================================================= +``Up``/``Down`` Select a slot +``Return`` Restore the selected slot +``S`` Store the current location into the selected slot +``L`` Edit the label +``DEL`` Reset the slot to its default +``0``..\ ``9`` Jump directly to that slot +=============== ================================================= + +Default slots are aimed at common C64 locations: + +.. image:: ../media/monitor/bookmarks.png + :alt: Monitor bookmarks popup with default slots + +Additional Notes +---------------- + +Use **UI Freeze** mode when the monitor output must be captured in the video stream. + +Use **UI Overlay on HDMI** mode when polling is needed to observe live changes. + +To switch between UI Freeze and UI Overlay modes: + +1. Exit the monitor. +2. Press ``C=+I``. +3. Reopen the monitor. diff --git a/index.rst b/index.rst index 3f56ab6..dd90209 100644 --- a/index.rst +++ b/index.rst @@ -14,10 +14,11 @@ Cartridge Emulation Tape Emulation Modem Emulation Layer + Machine Code Monitor Command Interface Virtual Printer ReST API Reference + OpenAPI Specification Assembly64 Integration Interview By Retro Magazine FAQ by Grrrolf - diff --git a/media/monitor/ascii_view.png b/media/monitor/ascii_view.png new file mode 100644 index 0000000..ac126cb Binary files /dev/null and b/media/monitor/ascii_view.png differ diff --git a/media/monitor/asm_opcode_completion.png b/media/monitor/asm_opcode_completion.png new file mode 100644 index 0000000..96da234 Binary files /dev/null and b/media/monitor/asm_opcode_completion.png differ diff --git a/media/monitor/assembly_view.png b/media/monitor/assembly_view.png new file mode 100644 index 0000000..afaf9fc Binary files /dev/null and b/media/monitor/assembly_view.png differ diff --git a/media/monitor/binary_sprite.png b/media/monitor/binary_sprite.png new file mode 100644 index 0000000..4bc8091 Binary files /dev/null and b/media/monitor/binary_sprite.png differ diff --git a/media/monitor/binary_view.png b/media/monitor/binary_view.png new file mode 100644 index 0000000..8ff7313 Binary files /dev/null and b/media/monitor/binary_view.png differ diff --git a/media/monitor/bookmarks.png b/media/monitor/bookmarks.png new file mode 100644 index 0000000..142518c Binary files /dev/null and b/media/monitor/bookmarks.png differ diff --git a/media/monitor/calculator.png b/media/monitor/calculator.png new file mode 100644 index 0000000..e818ee8 Binary files /dev/null and b/media/monitor/calculator.png differ diff --git a/media/monitor/help_view.png b/media/monitor/help_view.png new file mode 100644 index 0000000..1a7e5ca Binary files /dev/null and b/media/monitor/help_view.png differ diff --git a/media/monitor/hex_view.png b/media/monitor/hex_view.png new file mode 100644 index 0000000..8639b0e Binary files /dev/null and b/media/monitor/hex_view.png differ diff --git a/media/monitor/hunt_results.png b/media/monitor/hunt_results.png new file mode 100644 index 0000000..9a87ab8 Binary files /dev/null and b/media/monitor/hunt_results.png differ diff --git a/media/monitor/hunt_search.png b/media/monitor/hunt_search.png new file mode 100644 index 0000000..cf844ef Binary files /dev/null and b/media/monitor/hunt_search.png differ diff --git a/media/monitor/layout_example.png b/media/monitor/layout_example.png new file mode 100644 index 0000000..6d1906f Binary files /dev/null and b/media/monitor/layout_example.png differ diff --git a/media/monitor/load_params.png b/media/monitor/load_params.png new file mode 100644 index 0000000..01eb274 Binary files /dev/null and b/media/monitor/load_params.png differ diff --git a/media/monitor/load_picker.png b/media/monitor/load_picker.png new file mode 100644 index 0000000..6c035ad Binary files /dev/null and b/media/monitor/load_picker.png differ diff --git a/media/monitor/load_select.png b/media/monitor/load_select.png new file mode 100644 index 0000000..745d306 Binary files /dev/null and b/media/monitor/load_select.png differ diff --git a/media/monitor/number_tool.png b/media/monitor/number_tool.png new file mode 100644 index 0000000..7e0d9b8 Binary files /dev/null and b/media/monitor/number_tool.png differ diff --git a/media/monitor/save_filename.png b/media/monitor/save_filename.png new file mode 100644 index 0000000..87acbd1 Binary files /dev/null and b/media/monitor/save_filename.png differ diff --git a/media/monitor/save_picker.png b/media/monitor/save_picker.png new file mode 100644 index 0000000..c6d5e2b Binary files /dev/null and b/media/monitor/save_picker.png differ diff --git a/media/monitor/save_range.png b/media/monitor/save_range.png new file mode 100644 index 0000000..0faf150 Binary files /dev/null and b/media/monitor/save_range.png differ diff --git a/media/monitor/screen_view.png b/media/monitor/screen_view.png new file mode 100644 index 0000000..f93cdd7 Binary files /dev/null and b/media/monitor/screen_view.png differ