Skip to main content

GDB Remote Serial Protocol (RSP)

Spectranext cartridges support the GDB Remote Serial Protocol (RSP), enabling external tools to automate file operations, device control, and debugging tasks. This protocol allows you to build custom tools that interact with the cartridge's onboard XFS filesystem without requiring a web browser or manual file transfers.

Overview

The GDB RSP implementation in Spectranext provides:

  • File operations via vFile protocol extension
  • Device-specific operations via vSpectranext protocol extension
  • Standard GDB debugging capabilities (register access, memory read/write, breakpoints)
  • Connection via USB CDC or TCP socket (port 1337, for emulators)

Protocol Basics

Packet Format

GDB RSP uses a simple packet-based protocol:

$<data>#<checksum>

Where:

  • $ - Packet start delimiter
  • <data> - Packet payload (can contain any bytes, including null bytes)
  • # - Checksum delimiter
  • <checksum> - Two hex digits representing the 8-bit checksum of all bytes in <data>

Checksum Calculation

The checksum is the sum of all bytes in the data payload, modulo 256:

checksum = sum(ord(byte) for byte in data) & 0xFF

Acknowledgments

  • ACK (+): Sent when a packet is received correctly
  • NAK (-): Sent when a packet checksum is invalid or packet is malformed

Interrupt Character

The interrupt character (\x03, Ctrl+C) can be sent at any time to halt execution. It is only processed when the deframer is in idle state (not receiving a packet).

Connection Methods

USB CDC (Serial)

The device appears as a USB CDC serial port (e.g., /dev/ttyACM0 on Linux, COM28 on Windows).

TCP Socket (Emulators)

Connect via TCP socket:

  • Host: localhost (or remote host if GDB server is running remotely)
  • Port: 1337 (default)

The TCP connection is useful when using the Fuse emulator's GDB server.

Protocol Detection

To detect if a device supports Spectranext extensions, send a qSupported query:

$qSupported#<checksum>

The response will include vSpectranext+ if supported:

$PacketSize=4000;qXfer:features:read+;qXfer:auxv:read+;vSpectranext+#<checksum>

vFile Protocol

The vFile protocol extension provides file operations on the cartridge's RAM filesystem. All paths and data are encoded as ASCII-hex (two hex characters per byte).

Packet Format

$vFile:<subcommand>:<args>#<checksum>

Commands

vFile:open

Open a file for reading or writing.

Request:

$vFile:open:<fd>,<flags>,<mode>,<path>#<checksum>
  • <fd>: File descriptor (hex, ignored, use 1)
  • <flags>: Open flags (hex):
    • 0x0000 = O_RDONLY (read-only)
    • 0x0001 = O_WRONLY (write-only)
    • 0x0002 = O_RDWR (read-write)
    • 0x0008 = O_APPEND (append mode)
    • 0x0100 = O_CREAT (create if not exists)
    • 0x0200 = O_CREAT | O_TRUNC (create and truncate)
  • <mode>: File mode (hex, ignored)
  • <path>: File path (ASCII-hex encoded)

Response:

  • Success: F<fd> where <fd> is the file descriptor (hex, typically 1)
  • Error: F-1,<errno> where <errno> is the error number (hex)

Example:

Request:  $vFile:open:1,2,0,2f746573742e747874#<checksum>
(opens "/test.txt" for read-write)

Response: F1

vFile:close

Close an open file.

Request:

$vFile:close:<fd>#<checksum>
  • <fd>: File descriptor (hex)

Response:

  • Success: F0
  • Error: F-1,<errno>

Example:

Request:  $vFile:close:1#<checksum>

Response: F0

vFile:pread

Read data from an open file (sequential read from current position).

Request:

$vFile:pread:<fd>,<count>#<checksum>
  • <fd>: File descriptor (hex)
  • <count>: Number of bytes to read (hex)

Response:

  • Success: <hex-data> (hex-encoded binary data, no prefix)
  • Error: F-1,<errno>

Example:

Request:  $vFile:pread:1,100#<checksum>
(read 256 bytes)

Response: 48656c6c6f20576f726c64...
(hex-encoded "Hello World...")

vFile:pwrite

Write data to an open file (sequential write at current position).

Request:

$vFile:pwrite:<fd>,<hex-data>#<checksum>
  • <fd>: File descriptor (hex)
  • <hex-data>: Binary data encoded as ASCII-hex (two hex chars per byte)

Response:

  • Success: F<bytes-written> where <bytes-written> is the number of bytes written (hex)
  • Error: F-1,<errno>

Example:

Request:  $vFile:pwrite:1,48656c6c6f#<checksum>
(write "Hello" = 0x48 0x65 0x6c 0x6c 0x6f)

Response: F5
(5 bytes written)

vFile:size

Get the size of a file.

Request:

$vFile:size:<path>#<checksum>
  • <path>: File path (ASCII-hex encoded)

Response:

  • Success: F<size> where <size> is the file size in bytes (hex)
  • Error: F-1,<errno>

Example:

Request:  $vFile:size:2f746573742e747874#<checksum>
(get size of "/test.txt")

Response: F1000
(file is 4096 bytes)

vFile:exists

Check if a file exists.

Request:

$vFile:exists:<path>#<checksum>
  • <path>: File path (ASCII-hex encoded)

Response:

  • Exists: F,1
  • Not exists: F,0
  • Error: F-1,<errno>

Example:

Request:  $vFile:exists:2f746573742e747874#<checksum>

Response: F,1

vFile:unlink

Delete a file.

Request:

$vFile:unlink:<path>#<checksum>
  • <path>: File path (ASCII-hex encoded)

Response:

  • Success: F0
  • Error: F-1,<errno>

Example:

Request:  $vFile:unlink:2f746573742e747874#<checksum>

Response: F0

vSpectranext Protocol

The vSpectranext protocol extension provides Spectranext-specific operations for device control and directory operations.

Packet Format

$vSpectranext:<subcommand>:<args>#<checksum>

Commands

vSpectranext:reboot

Trigger a ZX Spectrum reboot.

Request:

$vSpectranext:reboot#<checksum>

Response:

  • Success: OK (sent before reboot)

Example:

Request:  $vSpectranext:reboot#<checksum>

Response: OK
(device reboots immediately after)

vSpectranext:autoboot

Configure autoboot from xfs://ram/ and reboot the device.

Request:

$vSpectranext:autoboot#<checksum>

Response:

  • Success: OK (sent before reboot)
  • Error: E<errno>

Example:

Request:  $vSpectranext:autoboot#<checksum>

Response: OK
(device configures autoboot and reboots)

vSpectranext:opendir

Open a directory for reading.

Request:

$vSpectranext:opendir:<path>#<checksum>
  • <path>: Directory path (ASCII-hex encoded)

Response:

  • Success: OK
  • Error: E<errno>

Example:

Request:  $vSpectranext:opendir:2f#<checksum>
(open root directory "/")

Response: OK

vSpectranext:readdir

Read the next directory entry.

Request:

$vSpectranext:readdir#<checksum>

Response:

  • Success: FOK,<name>,<type>,<size> where:
    • <name>: File/directory name (ASCII-hex encoded)
    • <type>: F for file, D for directory
    • <size>: File size in bytes (hex, ignored for directories)
  • End of directory: `` (empty string)
  • Error: E<errno>

Example:

Request:  $vSpectranext:readdir#<checksum>

Response: FOK,746573742e747874,46,1000
(file "test.txt", type file, size 4096 bytes)

Request: $vSpectranext:readdir#<checksum>

Response:
(end of directory)

vSpectranext:closedir

Close an open directory.

Request:

$vSpectranext:closedir#<checksum>

Response:

  • Success: OK
  • Error: E<errno>

Example:

Request:  $vSpectranext:closedir#<checksum>

Response: OK

vSpectranext:mv

Move/rename a file or directory.

Request:

$vSpectranext:mv:<old-path>,<new-path>#<checksum>
  • <old-path>: Current path (ASCII-hex encoded)
  • <new-path>: New path (ASCII-hex encoded)

Response:

  • Success: OK
  • Error: E<errno>

Example:

Request:  $vSpectranext:mv:2f6f6c64,2f6e6577#<checksum>
(rename "/old" to "/new")

Response: OK

vSpectranext:mkdir

Create a directory.

Request:

$vSpectranext:mkdir:<path>#<checksum>
  • <path>: Directory path (ASCII-hex encoded)

Response:

  • Success: OK
  • Error: E<errno>

Example:

Request:  $vSpectranext:mkdir:2f6d79646972#<checksum>
(create "/mydir")

Response: OK

vSpectranext:rmdir

Remove an empty directory.

Request:

$vSpectranext:rmdir:<path>#<checksum>
  • <path>: Directory path (ASCII-hex encoded)

Response:

  • Success: OK
  • Error: E<errno>

Example:

Request:  $vSpectranext:rmdir:2f6d79646972#<checksum>

Response: OK

Error Codes

Error responses use standard errno values:

  • 0 = Success (no error)
  • 2 = ENOENT (No such file or directory)
  • 5 = EIO (Input/output error)
  • 9 = EBADF (Bad file descriptor)
  • 12 = ENOMEM (Out of memory)
  • 17 = EEXIST (File exists)
  • 20 = ENOTDIR (Not a directory)
  • 21 = EISDIR (Is a directory)
  • 22 = EINVAL (Invalid argument)
  • 27 = EFBIG (File too large)
  • 28 = ENOSPC (No space left on device)
  • 39 = ENOTEMPTY (Directory not empty)

Implementation Notes

Sequential I/O

vFile:pread and vFile:pwrite perform sequential I/O from the current file position. The position advances automatically after each read or write operation.

Path Encoding

All paths must be encoded as ASCII-hex (two hex characters per byte). For example:

  • /2f
  • /test.txt2f746573742e747874
  • /my dir/file.bin2f6d79206469722f66696c652e62696e

Binary Data Encoding

Binary data in vFile:pwrite requests must be hex-encoded. Binary data in vFile:pread responses is returned as hex-encoded.

Packet Size Limits

The maximum packet size is as advertised in qSupported. For large file transfers, split data into multiple vFile:pwrite operations.

Reference Implementation

The spx command-line tool (sdk/bin/spx.py) provides a complete reference implementation of the GDB RSP protocol for Spectranext. You can use it as a reference for building your own tools.

See Also