Remote debugging over ZRCP¶
ZRCP is the text protocol the ZEsarUX emulator offers for remote control. DeZog
can debug through it (its zrcp remote type), and because every command is a
line of text you can also drive it by hand with telnet. JNEXT speaks ZRCP as
ZEsarUX 12.0 does.
Start JNEXT with a ZRCP port¶
$ jnext --zrcp-port 10000
The log confirms it:
[13:10:21.837] [debugger] [info] zrcp: listening on 127.0.0.1:10000
10000 is ZEsarUX's own default, and the one DeZog expects. --zrcp-port 0
lets the system pick a free port and prints it. The server is off unless you
give the option, and it works in every frontend: the Qt window, the SDL build
and --headless. It can run together with the DeZog (--dzrp-port) and
z88dk-gdb (--gdb-port) servers; each has its own port and one client.
DeZog¶
In your project's .vscode/launch.json, use DeZog's zrcp remote — the one
it uses for ZEsarUX — with JNEXT's port:
{
"type": "dezog",
"request": "launch",
"name": "JNEXT (ZRCP)",
"remoteType": "zrcp",
"zrcp": {
"hostname": "localhost",
"port": 10000,
"resetOnLaunch": true,
"skipInterrupt": false
},
"load": "mygame.nex",
"sjasmplus": [ { "path": "mygame.sld" } ],
"topOfStack": "stack_top"
}
The assembler, label and topOfStack settings are DeZog's, not JNEXT's; see
DeZog's own documentation for them. Two of the zrcp settings matter here:
resetOnLaunch(DeZog's default,true): DeZog starts every session withhard-reset-cpu. In JNEXT that is a cold boot of the whole machine, the same as Machine > Power Reset (F1), finished before JNEXT answers, so the program is then loaded into a fresh machine. Withfalsethe program is loaded into the machine as it is.skipInterrupt: leave itfalse(DeZog's default). Withtrue, DeZog asks the emulator to step over interrupt routines, which JNEXT does not do: DeZog shows one warning at launch (Unsupported in jnext: step-over-interrupt (bit 5)), the session carries on, and stepping enters an interrupt routine when one is taken.
DeZog then holds the machine stopped and loads load with smartload, which
takes a .nex, .sna, .szx, .z80, .jns, .tap, .tzx, .wav or
.rzx file. From there you have breakpoints (with conditions) and
watchpoints, stepping, step over and step out, the call stack, reverse
debugging over the CPU history, code coverage, and -state save /
-state restore.
Run JNEXT as the machine your program needs: --machine next, the default,
for a .nex.
By hand¶
$ telnet localhost 10000
Welcome to ZEsarUX remote command protocol (ZRCP)
Write help for available commands
command> enter-cpu-step
command@cpu-step> smartload "mygame.nex"
command@cpu-step> disassemble 8000H 3
8000 DI
8001 PUSH IY
8003 EXX
command@cpu-step> enable-breakpoints
command@cpu-step> set-breakpoint 1 PC=8005H
command@cpu-step> run
Running until a breakpoint, key press or data sent, menu opening or other event
Breakpoint fired: PC=8005H
PC=8005 SP=fdf9 AF=0044 BC=0b00 HL=339b DE=369b IX=8000 IY=5c3a ...
8005 LD (8379),SP
command@cpu-step>
Every reply ends with the prompt: command>, or command@cpu-step> while
the machine is held stopped. help lists every command JNEXT serves; help
command describes one, and says where JNEXT behaves differently from
ZEsarUX. Numbers are decimal, or hexadecimal with an H suffix (8000H). A
command JNEXT does not serve answers Error. Unsupported command in jnext:
and its name.
While run runs, anything you send stops it, and what you sent is
discarded, not executed: pressing Enter on an empty line is the way to stop
the machine by hand.
What to expect¶
get-memory-pagesnames what each slot reads now, in ZEsarUX's spelling:O<n>for a ROM page (O0andO1are ROM 0's two halves),A<n>for a RAM page,SR<n>in config mode,ROfor the boot ROM, andDIVwhile the DivMMC is paged in over the slot. The Multiface, Layer 2 and the alternate ROM have no ZEsarUX spelling, so their slot shows the page or ROM it covers. TheMMU=field ofget-registersis unchanged.- Connecting does not stop the machine;
enter-cpu-stepdoes. Leaving (orquit) resumes it if the stop was the client's own and nothing else is attached; with JNEXT's debugger window open, or another remote debugger connected, it stays paused and the pause becomes theirs. - Breakpoints are the session's. They start disabled, as in ZEsarUX:
until
enable-breakpoints,set-breakpointanswersError. You must enable breakpoints first. They are removed when the client leaves. Conditions are ZEsarUX's (PC=8000H,SP>=65280,PC=PEEKW(SP-2) AND SP>=65280,A<>0 AND (HL&FFH)=5, ...);help set-breakpointlists the terms JNEXT honours. JNEXT addsCVAR(path), a C variable of the stopped program (PC=8D3EH AND CVAR(a)=2,evaluate CVAR(p->x)): see C variables.set-register CVAR(path)=valuewrites one (set-register CVAR(g_int)=10), in the same extension: see Changing a C variable. With JNEXT's debugger window open they appear in its Breakpoints panel asExecute (client N), read-only, but are not drawn as a dot in the Disassembly or Source breakpoint columns, and a click there does not remove them (see Whose breakpoints the gutters show and change). - The history, the coverage and the call tracking are the machine's. A
client that turns one on turns it off again when it leaves; one that was
already on — the trace you enabled in the debugger window — stays on. A
client's
cpu-history clearandset-max-sizechange only what that client sees: JNEXT's own Step Back keeps its whole history. Because the history is JNEXT's trace,cpu-history enabled yesshows what the trace already holds (up to 10000 entries) andclearstarts the view afresh, where ZEsarUX's history starts empty and records only afterstarted yes. DeZog sendsclearitself, so it sees only its own steps. snapshot-save/snapshot-loadkeep the snapshot in memory, for that session only; nothing is written to disk. Save it with the machine paused while it runs, not stopped at a breakpoint (a breakpoint stops it mid-frame). To keep a snapshot on disk, save a.jnsfile from JNEXT's File menu.smartload,load-binaryandsave-binaryread and write files on the computer running JNEXT, like ZEsarUX.- One client at a time. A second connection is answered
Error. Another ZRCP client is connectedand closed. hard-reset-cpuandreset-cpukeep the session: its breakpoints and settings survive the reset, and a machine held in cpu-step mode stays stopped, at the reset address.
Headless runs¶
With --headless, a client that holds the machine stopped holds its frames
too, exactly as described for DeZog in
Remote debugging with DeZog: nothing is
emulated while it waits, and --delayed-automatic-exit still ends the run on
time.
Security¶
The server listens on 127.0.0.1 only. --debug-listen-address changes that
for every debug server, and is refused unless a server port is given too.
ZRCP has no authentication: anyone who can reach the port controls the
machine and can read and write files on your computer through smartload,
load-binary and save-binary, so widen it only on a network you trust.
For the full list of command-line options mentioned here, see jnext(1) or USAGE.md.