From c879adc43b91a53eb7e76f232a39abb56d8144c1 Mon Sep 17 00:00:00 2001 From: gbc dev Date: Tue, 14 Jul 2026 23:26:49 +0200 Subject: control: socket-based debug channel + gbctl CLI driver Replace the input-only FIFO's limitations with a Unix-domain socket control channel (--sock) that is a superset of the button vocabulary plus emulator introspection: read/write bus memory, get/set CPU context, single-step, PC breakpoints, value-change watchpoints, run/pause. Being a socket it replies to each command and broadcasts async 'event stop ...' lines; a stored last-stop record (stopinfo) lets per-request clients recover a missed event. Add gbctl: a stdlib-python CLI that spawns a tmux pane running the emulator on a ROM, auto-resolves the socket, and drives it with terse verbs (cpu/read/write/ reg/step/break/watch/continue/pause/press/hold/screen/stop). The FIFO stays as legacy input-only. --- src/control.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/control.h (limited to 'src/control.h') diff --git a/src/control.h b/src/control.h new file mode 100644 index 0000000..a625853 --- /dev/null +++ b/src/control.h @@ -0,0 +1,36 @@ +#ifndef GBC_CONTROL_H +#define GBC_CONTROL_H + +#include "gb.h" + +// Socket-based external control + debug channel. +// +// This is a superset of the legacy input FIFO: a Unix-domain stream socket that +// accepts the same button-command vocabulary (see render.h / README) *plus* +// emulator-introspection commands (memory read/write, CPU context, single-step, +// breakpoints, watchpoints, run/pause). Because it is a socket it can reply to +// each command and push asynchronous "event stop ..." lines when execution +// halts at a breakpoint / step boundary / watchpoint. +// +// The protocol is line based (one command per line, '\n' terminated). Replies +// begin with "ok" or "err"; asynchronous notifications begin with "event". + +// Create and start listening on a Unix-domain socket at `path`. Safe to call +// once at startup. On failure prints to stderr and leaves the channel inactive. +void control_open(const char *path); +void control_close(void); +bool control_active(void); + +// Accept new connections and dispatch any pending commands against `gb`. +// Returns false if a client requested the emulator to quit. +bool control_poll(GB *gb); + +// True while the debugger is holding execution (no CPU advancement). +bool control_paused(void); + +// Advance emulation by up to one video frame, honoring the debugger's +// pause / single-step / breakpoint / watchpoint state. When the control channel +// is inactive this simply runs a full frame like the plain emulator loop. +void control_run_frame(GB *gb); + +#endif -- cgit v1.3.1-sl0p