Skip to main content

spectranext.h

spectranext.h (included in the SDK) exposes the Z80 interface to Spectranext services: controller status, Wi-Fi scan/connect/disconnect, DNS, engine calls (e.g. JSONPath), and direct XFS-to-Spectranext-RAM reads. Everything routes through the single SPECTRANEXT ($3EF0) jump-table entry, selected by register A on entry.

spectranext.h is linked by libspectranet

Functions declared here are not linked separately as are provided as part of libspectranet library.

Error convention (assembly): carry set = error; carry clear = success.


Functions​

C calling convention: __z88dk_callee (callee cleans stack), except spectranext_detect and spectranext_get_version, which use __FASTCALL__.

spectranext_get_version​

int8_t spectranext_get_version(char *version_out)

Returns the firmware build identity as a NUL-terminated ASCII string. The caller supplies SPECTRANEXT_VERSION_SIZE (32) writable bytes outside controller page B ($2000–$2FFF). Ignore the buffer if the call fails.

ReturnMeaning
0Version string written to version_out.
-1The ROM does not support operation 15, or the call failed.
#include <spectranext.h>

char version[SPECTRANEXT_VERSION_SIZE];
if (spectranext_get_version(version) == 0) {
// Example: "1.0-12fb395e"
} else {
// Older ROM: the version is unavailable.
}

The string contains the contents of rp2350/version.txt, a hyphen, and the build's eight-character Git hash. It has at most 31 visible bytes and no newline. The shared controller ROM supplies the value on both cartridge hardware and Fuse; Fuse reports the version bundled with the emulator.

Compare the major.minor prefix when your application needs a release level. Compare the complete string when it needs one exact build. The hash identifies a build but does not order builds with the same prefix. A release-level check depends on version.txt being advanced for that release. This is firmware identity, not a list of supported API features; the existence of this call alone does not establish that any later operation is available.


spectranext_detect​

Returns whether the cartridge is Spectranext (see Detection):

ReturnMeaning
1Spectranext
0Classic Spectranet
-1No compatible interface
int result = spectranext_detect();
if (result == 1) {
// Spectranext present
}

spectranext_get_controller_status​

int8_t spectranext_get_controller_status(int8_t *wifi_connection_out, uint32_t *ipv4_out)

Fills Wi-Fi connection state and IPv4 (host byte order).

ReturnMeaning
< 0ROM/port failure.
≥ 0Controller status (compare with WIFI_CONTROLLER_STATUS_*).

On success, *wifi_connection_out uses WIFI_CONNECT_*; *ipv4_out is the IPv4 address in host order.

uint32_t ipv4;
int8_t wifi_state;
int8_t status = spectranext_get_controller_status(&wifi_state, &ipv4);
if (status >= 0) {
// wifi_state: WIFI_CONNECT_*
// ipv4: address in host order
}

spectranext_wifi_scan_access_points​

int8_t spectranext_wifi_scan_access_points(void)
ReturnMeaning
< 0Failure.
≥ 0Number of networks found.
int8_t count = spectranext_wifi_scan_access_points();
if (count < 0) {
// error
} else {
// count networks available via spectranext_wifi_get_access_point()
}

spectranext_wifi_get_access_point​

int8_t spectranext_wifi_get_access_point(uint8_t ap, spectranext_wifi_scan_result_t *result)

Copies the extended scan result for index ap (0-based). The result contains a 64-byte NUL-terminated SSID, a 6-byte BSSID, and signed RSSI in dBm. An RSSI of 0 and all-zero BSSID mean that extended metadata was unavailable.

ReturnMeaning
0Success.
-1Failure.
spectranext_wifi_scan_result_t result;
int8_t r = spectranext_wifi_get_access_point(0, &result);
if (r == 0) {
// result.ssid, result.bssid, and result.rssi are available
}

spectranext_wifi_connect_access_point​

int8_t spectranext_wifi_connect_access_point(const char *ssid, const char *password,
const uint8_t *bssid)
ReturnMeaning
0Success.
-1Failure.
int8_t r = spectranext_wifi_connect_access_point(result.ssid, "s3cr3t", result.bssid);
if (r < 0) {
// connection failed
}

spectranext_wifi_disconnect​

int8_t spectranext_wifi_disconnect(void)
ReturnMeaning
0Success.
-1Failure.
int8_t r = spectranext_wifi_disconnect();

spectranext_gethostbyname​

int8_t spectranext_gethostbyname(const char *hostname, uint32_t *result_ipv4)

Resolves hostname to an IPv4 address; *result_ipv4 is host byte order.

ReturnMeaning
0Success.
-1Failure (ROM/port or lookup error).
uint32_t ipv4;
int8_t r = spectranext_gethostbyname("example.com", &ipv4);
if (r == 0) {
// ipv4 contains resolved address in host byte order
}

spectranext_enginecall​

int8_t spectranext_enginecall(const char *input, const char *output, const char *operation)

Runs a named engine call with argv-style arguments in operation (space-separated; see below). Used to copy mounted files into XFS RAM or run JSONPath and XPath queries.

Input file (input) — a path on the current default XFS mount, or N:path to select mount slot 0…3 explicitly (e.g. 1:data/app.json).

Output file (output) — path on the RAM XFS volume only (no N: prefix); the result is written there.

Operation (operation) — first token is the engine name, such as cp, jsonpath or xpath (json is also accepted for jsonpath). Further tokens are engine-specific. See Engine calls for usage and supported input formats.

spectranext_enginecall("1:example.json", "example.bin", "jsonpath $[*].id $[*].name");

The call waits for completion on controller channel 0. To continue running while an operation executes, submit it through direct memory access on controller channel 1. Channel 0 SDK calls remain available.

ReturnMeaning
0Success.
< 0Failure: negative int8_t error code from the engine (e.g. -1 unknown engine, -2 I/O, -3 JSON parse, -4 JSONPath, -5 non-scalar match, -6 bad argv).
int8_t r = spectranext_enginecall("0:config.json", "out.bin", "jsonpath $.name");

spectranext_xfs_read​

int32_t spectranext_xfs_read(const spectranext_xfs_read_request_t *request)

Reads a range from an absolute path in the local XFS overlay directly into Spectranext RAM pages. This avoids an intermediate Z80 buffer and is intended for loading a contiguous binary image or data block into page-addressable Spectranext RAM.

The lookup is controller-owned: the path is resolved through the normal local overlay order—RAM, then flash, then ROMFS—not through the caller's currently selected VFS mount. The path must therefore be absolute, for example "/assets/data.bin".

ReturnMeaning
>= 0Actual number of bytes read. A shorter value than maximum_data is end of file.
-1Invalid request, controller failure, or XFS read failure.

Request structure​

typedef struct spectranext_xfs_read_request_s {
char source_filename[128];
uint32_t source_offset;
uint8_t target_first_page;
uint16_t target_first_page_offset;
uint32_t maximum_data;
} spectranext_xfs_read_request_t;
FieldMeaning
source_filenameAbsolute, NUL-terminated path in the local XFS overlay. Maximum 127 visible characters plus the terminator.
source_offsetZero-based byte offset in the source file.
target_first_pageFirst destination Spectranext RAM page, in the inclusive range $C0–$DF.
target_first_page_offsetOffset within that first 4 KiB page, from 0 to $0FFF.
maximum_dataMaximum number of bytes to copy. The complete destination range must fit from the chosen page/offset through the end of page $DF; requests do not wrap.

The copy continues across consecutive 4 KiB RAM pages as required. It never modifies the source file. The routine does not change which pages are presently mapped at page A or page B; map the destination page yourself when you want to inspect or execute the loaded data.

#include <spectranext.h>

spectranext_xfs_read_request_t request = {
"/assets/intro.bin", // source_filename
0, // source_offset
0xD8, // target_first_page
0, // target_first_page_offset
4096 // maximum_data
};

int32_t bytes = spectranext_xfs_read(&request);
if (bytes < 0) {
// Controller or XFS failure
} else if (bytes != 4096) {
// Source file ended early
}

// Expose the result at $1000–$1FFF:
setpagea(0xD8);

Linking (libspectranet vs libspectranet_np)​

  • libspectranet — Paged build: use when your program already follows the usual Spectranet paging model (see memory).
  • libspectranet_np — No-page stubs: often paired with an explicit pagein() at startup when your code expects Spectranet ROM to be mapped before calling these helpers.

Exact link lines and pragma redirects match your other Spectranet projects (e.g. libterm, ndos). The SDK copies spectranext.h into sdk/include/.


See also​

Protected user settings​

CMD_SYS_SETTINGS_READ (9) and CMD_SYS_SETTINGS_WRITE (10) use HL as the payload buffer and BC as capacity or exact length. READ returns BC=16. The payload contains DivMMC compatibility (0 or 1) at byte 0, with 15 opaque reserved bytes. Read the complete payload and preserve its other bytes when editing. Buffers must not overlap page B ($2000–$2fff). Carry/A report errors: 1 unsupported command, 2 insufficient buffer, 3 invalid payload, 4 unsupported format, 5 old/unrecognized bootloader, 6 busy, 7 storage/staging failure, 8 lockout. An unsupported READ does not imply native mode.

C callers use spectranext_settings_read(buffer, capacity) and spectranext_settings_write(buffer, length). READ returns 16, WRITE returns 0, and failures return negative error codes. spectranext_get_diagnostics(buffer) returns ten read-only bytes: bootloader version (LE u32), active policy (u8), lockout reason (LE u32), and supported safety capabilities (u8).

Enabling requires bootloader version 3, safety ABI 1 and its settings/update capabilities. Enabling and disabling both enter limp mode until a complete power cycle. A paged SDK call exits from host RAM through its normal page-out. A no-page caller must explicitly page out from code and stack above 16 KiB after WRITE returns, and must not return into expansion ROM afterwards. Reset cannot clear a lockout; remove Spectrum power and USB, then remove or disable DivMMC before using native mode. These features remain subject to the hardware release checks described in the design document.

.spx upgrade / spectranext_upgrade() requests bootloader mode for the OTA image staged by the controller's autonomous OTA process. It performs no network check or download. The bootloader owns file validation and reports missing or invalid content. Entry requires bootloader revision 7, safety ABI 1 and explicit-update capability (bit 2), alongside its protected-settings capabilities.

The controller prepares a one-shot PSRAM request and acknowledges it. Completed physical page-out authorizes the request, then it resets the Spectrum and reboots the controller. The application ROM returns through the dot command's normal setup stage; the dot frontend only supplies arguments.

In DivMMC mode the bootloader starts paged out. Run .spx after reset, manually or from esxDOS startup, to probe $033B, explicitly page in, and call $0004. That entry runs the full bootloader CRT and launches its checking, confirmation/progress or error UI. While mapped, it serves the full low 16K. Native bootloader entry remains automatic. Explicit requests cannot bypass confirmation through /OTA/SILENT.

SDK calls acknowledge preparation only. Callers use their ordinary high-RAM page-out path and must tolerate a full reset afterward; no fingerprint polling or custom RAM continuation is required. Cancellation/completion releases bus service, resets the Spectrum and restarts the controller with protected settings preserved. Ordinary DivMMC startup without a request stays passive.