About engines
Engines let Spectranext prepare data for a ZX Spectrum program, such as copying a mounted file into XFS RAM or extracting values from JSON and HTML.
Calling engines
Invoking an engine (paths, mounts, return codes) is documented on spectranext.h — spectranext_enginecall. This page describes the documented engines and the structured output used by jsonpath and xpath.
From C:
int8_t r = spectranext_enginecall("0:example.json", "out.bin", "jsonpath '$[*][\"id\",\"title\",\"url\"]'");
The operation string is parsed like argv: the first token is the engine name; remaining tokens are engine-specific (for jsonpath, each token is one JSONPath expression).
The legacy name json is still accepted and behaves the same as jsonpath.
Engines available
| Engine | Role |
|---|---|
cp | Copy an entire file, or a byte range, from a mounted filesystem into XFS RAM. |
jsonpath | Load JSON from the input file, evaluate one or more JSONPath expressions, write scalar results to the output file using the format below. |
xpath | Load HTML from the input file (libxml2 HTML parser with recovery), evaluate one or more XPath 1.0 expressions, write string results in the same column format as jsonpath. |
img2spec (planned) | Image Spectrumizer — convert a raster image from the input file into Spectrum-friendly art (attributes, possibly screen$, etc.) and write a digestible binary/text bundle. To do — not implemented yet. |
Unknown engine names fail with a negative error code (see spectranext_enginecall).
cp engine
Use cp to make a local RAM copy of a file from the current mount or an
explicit mount slot. For example, with an HTTPS filesystem mounted on slot 3:
int8_t result = spectranext_enginecall("3:assets.bin", "assets-cache.bin", "cp");
if (result < 0) {
/* Copy failed; do not use the output. */
}
The output path belongs to XFS RAM and has no mount prefix. An existing output file is truncated. Use a different name when copying from XFS RAM so that source and destination are separate files.
Copy a byte range
Supply both an offset and a size to copy part of a file:
/* Copy 16 KiB starting at byte 32 KiB. */
spectranext_enginecall("3:assets.bin", "part.bin", "cp 32768 16384");
| Operation | Meaning |
|---|---|
cp | Copy until the input reaches EOF. |
cp OFFSET SIZE | Skip OFFSET bytes, then copy exactly SIZE bytes. |
Offset and size are nonnegative byte counts, in decimal or 0x hexadecimal.
If the input ends before that range has been copied, the operation fails.
A failed copy can leave a
partial output file; use it only after a successful result.
The SDK call returns 0 on success and a negative value on failure. It waits for the copy to finish. To keep your program running during the copy, submit the same engine call on controller channel 1. Channel 0 can then read an already-copied file while channel 1 prepares the next one.
Structured output format (JSONPath and XPath)
Engine output is a binary stream on the RAM XFS volume. It is a sequence of length-prefixed strings, written back-to-back:
- Length header — 2 bytes, little-endian
uint16: byte length of the payload including the terminating NUL (strlen(text) + 1). - Payload — that many bytes: the C string (including the terminating NUL).
Think of the file as a stack of samples: each logical value is one header + string record. There is no extra padding between records.
The jsonpath and xpath engines use this for:
- A decimal count string (e.g.
"9") for how many scalars follow in that column. - Then one record per scalar (IDs, titles, URLs, …), in match order.
If you pass several path arguments (jsonpath path1 path2 … or xpath expr1 expr2 …), the engine writes one column per path: for each path it emits count, then all matched values for that path, then moves to the next path.
jsonpath engine
Inputs
| Piece | Meaning |
|---|---|
Input file (spectranext_enginecall first argument) | Path on the current default mount, or N:path to select mount index N (0…3). The file must contain UTF-8 JSON (object, array, etc.). For HTTP(s)/TNFS app data, mount point 3 is preferred (filesystem mount points). |
| Output file (second argument) | Plain path on the RAM XFS volume only (no N: prefix). Created/truncated by the engine. |
| Operation (third argument) | After parsing: argv[0] = jsonpath (or json); argv[1]… = one or more JSONPath strings (space-separated in the shell; in C use a single string with spaces). |
Each JSONPath must match only scalar values (strings, numbers, booleans, null). If a path matches an object or array, the call fails (non-scalar error).
Scalars are converted to text for output (e.g. numbers formatted as integers when exact; strings copied; null → null, booleans → true / false).
One path, multiple fields per array element
A single path can select several fields per array element, e.g. $[*]["id","title","url"]. Matches are emitted in order: for each item, id, then title, then url, then the next item’s triple, and so on. The leading count string is the total number of scalar values in that column (for three fields per story, count = 3 × number_of_stories).
xpath engine
Inputs
| Piece | Meaning |
|---|---|
| Input file | Path on the current default mount, or N:path to select a mount explicitly. The file contains HTML (UTF-8), parsed with libxml2’s HTML parser (recover from markup errors). See mount points. |
| Output file | Plain path on the RAM XFS volume only (same as jsonpath). |
| Operation | argv[0] = xpath; argv[1]… = one or more XPath 1.0 expressions (quote tokens that contain spaces). |
For each expression:
- A node set result emits
count= number of nodes, then the string value of each node (same idea as multiple scalar matches injsonpath). Attribute nodes yield their value text. - String, number, or boolean results emit
count=1and one text value.
The HTML http://www.w3.org/1999/xhtml namespace is registered with prefix html if you need explicit prefixed names in expressions.
img2spec engine (planned)
Status: to do — not implemented.
Image Spectrumizer — intended to read a bitmap image (format TBD: PNG, JPEG, etc.), quantize and map to Spectrum display constraints (attributes, possibly Timex/chunky modes later), and write a small binary or text bundle on the RAM volume suitable for loading or further processing on the Spectrum.
Examples
JSONPath
Command
engine-call 0:example.json out.bin jsonpath '$[*]["id","title","url"]'
Sample input JSON (0:example.json)
[
{
"id": 47687273,
"title": "Git commands I run before reading any code",
"points": 412,
"user": "grepsedawk",
"time": 1775638422,
"time_ago": "4 hours ago",
"comments_count": 92,
"type": "link",
"url": "https://example.com",
"domain": "example.com"
}
]
With more objects in the array, the same pattern repeats: each object contributes id, title, url in order.
Logical layout of out.bin
The file is not human-readable text; conceptually the jsonpath engine writes:
[ count as decimal string ]
[ id text ]
[ title text ]
[ url text ]
[ id text ]
[ title text ]
[ url text ]
…
Each bracket is one LE length + NUL-terminated string record as in Structured output format. For example, with one array element above, count is "3" (three scalars), then the string forms of id, title, and url.
C example
spectranext_enginecall(
"0:example.json",
"out.bin",
"jsonpath '$[*][\"id\",\"title\",\"url\"]'");
XPath
HTML on an HTTP(s) mount works like any other input path. With news.ycombinator.com mounted at site root on mount point 3 (see HTTP(s) filesystem and mount point conventions), path 3:show fetches https://news.ycombinator.com/show.
Three XPath expressions give three columns (rank text, story title, link href), each with its own count then scalars — same binary layout as multiple jsonpath arguments.
Command
engine-call 3:show out.bin xpath '//span[@class="rank"]/text()' '//span[@class="titleline"]/a/text()' '//span[@class="titleline"]/a/@href'
Logical layout of out.bin
Conceptually (each line is one LE length-prefixed string record):
[ count column 0 ]
[ rank text ]
[ rank text ]
…
[ count column 1 ]
[ title text ]
…
[ count column 2 ]
[ href text ]
…
C example
spectranext_enginecall(
"3:show",
"out.bin",
"xpath "
"'//span[@class=\"rank\"]/text()' "
"'//span[@class=\"titleline\"]/a/text()' "
"'//span[@class=\"titleline\"]/a/@href'");
To inspect a captured file on a host machine, use tools/enginefile-decode.py.
See also
- spectranext.h —
spectranext_enginecall, mount rules, error codes - HTTP(s) filesystem — hosting JSON or HTML on an HTTP(s) mount (e.g.
3:news/1.json,3:showwhen HTTP(s) is mounted at index 3)