From e8c1777a1761ebf55029589912198c83fb06aaec Mon Sep 17 00:00:00 2001 From: gbc dev Date: Fri, 17 Jul 2026 20:22:13 +0200 Subject: main: allow --sock (control/debug socket) in headless mode The control socket was only opened on the windowed path, so a --headless GB couldn't be inspected. A scriptable, invisible GB is exactly the one you most want to peek into - reading kernel WRAM over the debug socket is how the TCP field-offset corruption got pinned down. Open it in the headless loop too and poll it each frame; close it on exit. --- src/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main.c b/src/main.c index e95ab95..0dec4df 100644 --- a/src/main.c +++ b/src/main.c @@ -251,6 +251,14 @@ int main(int argc, char **argv) { gb->serial_in_fd = STDIN_FILENO; gb->serial_no_eof = (keys != NULL); // OSK provides input; don't EOF-exit } + // --sock works headless too: a scriptable GB you can also debug + // (read/write memory, breakpoints, button injection) is far more + // useful than one you can't see into. + if (sock_path) { + control_open(sock_path); + if (control_active()) + fprintf(stderr, "control socket: %s\n", sock_path); + } int keys_frame = 0; int fl = fcntl(STDIN_FILENO, F_GETFL, 0); if (fl != -1) fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK); @@ -280,6 +288,7 @@ int main(int argc, char **argv) { gb->buttons = keys_mask(keys, keys_frame); if (keys_frame++ > (int)strlen(keys) * 20 + 40) break; } + if (sock_path && !control_poll(gb)) break; // debug socket quit run_frame(gb); // advance ~a frame's worth of cycles if (!uncapped) { double target = start_t + (gb->cycles - start_cyc) / HZ; @@ -294,6 +303,7 @@ int main(int argc, char **argv) { } } if (raw_tty) tcsetattr(STDIN_FILENO, TCSANOW, &saved_tio); + control_close(); fprintf(stderr, "[sl0pboy] headless loop exit: %s\n", gb->poweroff ? "guest poweroff" : "signal"); if (shot_frames >= 0) { // --headless --shot FILE: dump final LCD -- cgit v1.3.1-sl0p