From 283040a1a5356e774276ba8f6c7404483b81bc11 Mon Sep 17 00:00:00 2001 From: gbc dev Date: Thu, 16 Jul 2026 11:25:43 +0200 Subject: headless: interactive TTY mode (raw stdin) for driving a guest OS live When stdin is a terminal, --headless now disables canonical mode + local echo so keystrokes reach the guest immediately and only the guest echoes (no doubled chars). Piped/redirected stdin is untouched (scripted input still works). Keep ISIG so Ctrl-C quits; restore termios on exit. VMIN=1 so a no-data non-blocking read is EAGAIN, not a 0-byte read the serial layer would misread as EOF. --- src/main.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/main.c b/src/main.c index f0709c2..648ded2 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include static volatile sig_atomic_t running = 1; static void on_sig(int s) { (void)s; running = 0; } @@ -100,6 +101,21 @@ int main(int argc, char **argv) { if (fl != -1) fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK); signal(SIGINT, on_sig); signal(SIGTERM, on_sig); + // Interactive: if stdin is a terminal, drop line-buffering + local echo + // so keystrokes reach the guest immediately and only the guest echoes. + // (Piped/redirected stdin is left alone, for scripted input.) + struct termios saved_tio; + bool raw_tty = isatty(STDIN_FILENO) && tcgetattr(STDIN_FILENO, &saved_tio) == 0; + if (raw_tty) { + struct termios t = saved_tio; + t.c_lflag &= ~(ICANON | ECHO); // char-at-a-time, no echo (keep ISIG) + // VMIN=1 (not 0): with O_NONBLOCK, "no data" is EAGAIN, not a 0-byte + // read that we'd otherwise misread as EOF. + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr(STDIN_FILENO, TCSANOW, &t); + fprintf(stderr, "[gbc: interactive serial console - Ctrl-C to quit]\n"); + } bool uncapped = (target_fps <= 0); double start_t = now_sec(); u64 start_cyc = gb->cycles; @@ -118,6 +134,7 @@ int main(int argc, char **argv) { } } } + if (raw_tty) tcsetattr(STDIN_FILENO, TCSANOW, &saved_tio); cart_free(&gb->cart); free(gb); return 0; } -- cgit v1.3.1-sl0p