Mercurial > repos > blastem
changeset 2703:829205a9647a default tip
Pump events and allow debug window interaction while paused in CPU debugger on Windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 04 Jul 2025 21:24:15 -0700 |
parents | 0a6d644c47aa |
children | |
files | debug.c util.c util.h |
diffstat | 3 files changed, 100 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/debug.c Fri Jul 04 21:23:48 2025 -0700 +++ b/debug.c Fri Jul 04 21:24:15 2025 -0700 @@ -2296,6 +2296,18 @@ END }; +static void read_wait_progress(void) +{ + process_events(); +#ifndef IS_LIB + render_update_display(); + vdp_context *vdp = current_system->get_vdp(current_system); + if (vdp) { + vdp_update_per_frame_debug(vdp); + } +#endif +} + static uint8_t read_parse_command(debug_root *root, parsed_command *out, int indent_level) { ++indent_level; @@ -2305,35 +2317,9 @@ } putchar(' '); fflush(stdout); -#ifdef _WIN32 -#define wait 0 -#else - int wait = 1; - fd_set read_fds; - FD_ZERO(&read_fds); - struct timeval timeout; -#endif - do { - process_events(); -#ifndef IS_LIB - render_update_display(); - vdp_context *vdp = current_system->get_vdp(current_system); - if (vdp) { - vdp_update_per_frame_debug(vdp); - } -#endif -#ifndef _WIN32 - timeout.tv_sec = 0; - timeout.tv_usec = 16667; - FD_SET(fileno(stdin), &read_fds); - if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) >= 1) { - wait = 0; - } -#endif - } while (wait); - + read_wait_progress(); char input_buf[1024]; - if (!fgets(input_buf, sizeof(input_buf), stdin)) { + if (!fgets_timeout(input_buf, sizeof(input_buf), stdin, 16667, read_wait_progress)) { fputs("fgets failed", stderr); return READ_FAILED; }
--- a/util.c Fri Jul 04 21:23:48 2025 -0700 +++ b/util.c Fri Jul 04 21:24:15 2025 -0700 @@ -757,6 +757,70 @@ return WSAGetLastError() == WSAEWOULDBLOCK; } +typedef struct { + HANDLE request_event; + HANDLE reply_event; + CRITICAL_SECTION lock; + FILE *f; + char *dst; + size_t size; +} stdio_timeout_state; + +static DWORD WINAPI stdio_timeout_thread(LPVOID param) +{ + stdio_timeout_state *state = param; + EnterCriticalSection(&state->lock); + for(;;) + { + while (!state->f) + { + LeaveCriticalSection(&state->lock); + WaitForSingleObject(state->request_event, INFINITE); + EnterCriticalSection(&state->lock); + } + char *dst = state->dst; + size_t size = state->size; + FILE *f = state->f; + LeaveCriticalSection(&state->lock); + dst = fgets(dst, size, f); + EnterCriticalSection(&state->lock); + state->dst = dst; + state->f = NULL; + SetEvent(&state->reply_event); + } + LeaveCriticalSection(&state->lock); + + return 0; +} + +char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) +{ + static HANDLE workerThread; + static stdio_timeout_state state; + if (!workerThread) { + InitializeCriticalSection(&state.lock); + state.request_event = CreateEventA(NULL, FALSE, FALSE, NULL); + state.reply_event = CreateEventA(NULL, FALSE, FALSE, NULL); + workerThread = CreateThread(NULL, 64 * 1024, stdio_timeout_thread, &state, 0, NULL); + } + EnterCriticalSection(&state.lock); + state.f = f; + state.dst = dst; + state.size = size; + SetEvent(state.request_event); + while (state.f) + { + LeaveCriticalSection(&state.lock); + WaitForSingleObject(state.reply_event, timeout_usec / 1000); + EnterCriticalSection(&state.lock); + if (state.f) { + timeout_cb(); + } + } + LeaveCriticalSection(&state.lock); + return state.dst; +} + #else #include <fcntl.h> #include <signal.h> @@ -864,6 +928,26 @@ } return exe_dir; } + +char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) +{ + int wait = 1; + fd_set read_fds; + FD_ZERO(&read_fds); + struct timeval timeout; + do { + timeout.tv_sec = timeout_usec / 1000000; + timeout.tv_usec = timeout_usec % 1000000; + FD_SET(fileno(stdin), &read_fds); + if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) >= 1) { + wait = 0; + } else { + timeout_cb(); + } + } while (wait); + return fgets(dst, size, f); +} + #include <dirent.h> #ifdef __ANDROID__
--- a/util.h Fri Jul 04 21:23:48 2025 -0700 +++ b/util.h Fri Jul 04 21:24:15 2025 -0700 @@ -108,6 +108,8 @@ int socket_last_error(void); //Returns if the last socket error was EAGAIN/EWOULDBLOCK int socket_error_is_wouldblock(void); +//works like fgets, but calls timeout_cb every timeout_usec microseconds while waiting for input +char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)); #if defined(__ANDROID__) && !defined(IS_LIB) FILE* fopen_wrapper(const char *path, const char *mode); #ifndef DISABLE_ZLIB