From 30467371f4cce2d6db1132daae8c5cb930f8540d Mon Sep 17 00:00:00 2001 From: kichikuou Date: Tue, 20 Jun 2023 09:14:32 +0900 Subject: [PATCH] debugger_dap: Handle SDL messages while paused in the debugger So that you can move around the window while the game is paused. Now DAP messages read from stdin are once posted to the SDL message queue, and then inserted into the debugger command queue in the main thread. --- src/debugger.h | 2 + src/debugger_dap.c | 38 +++-- src/sdl_core.h | 3 + src/sdl_event.c | 378 +++++++++++++++++++++++---------------------- 4 files changed, 226 insertions(+), 195 deletions(-) diff --git a/src/debugger.h b/src/debugger.h index 4e2e61e..aa39308 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -47,6 +47,7 @@ void dbg_main(int bp_no); void dbg_onsleep(void); uint8_t dbg_handle_breakpoint(int page, int addr); boolean dbg_console_vprintf(int lv, const char *format, va_list ap); +void dbg_post_command(void *data); #else // ENABLE_DEBUGGER @@ -57,6 +58,7 @@ boolean dbg_console_vprintf(int lv, const char *format, va_list ap); #define dbg_onsleep() #define dbg_handle_breakpoint(page, addr) BREAKPOINT #define dbg_console_vprintf(lv, format, ap) false +#define dbg_post_command(data) #endif // ENABLE_DEBUGGER diff --git a/src/debugger_dap.c b/src/debugger_dap.c index ebc917e..5683bff 100644 --- a/src/debugger_dap.c +++ b/src/debugger_dap.c @@ -567,13 +567,13 @@ static int read_command_thread(void *data) { } char *buf = malloc(content_length); fread(buf, content_length, 1, stdin); - msgq_enqueue(queue, buf); + sdl_post_debugger_command(buf); content_length = -1; } else { fprintf(stderr, "Unknown Debug Adapter Protocol header: %s", header); } } - msgq_enqueue(queue, NULL); // EOF + sdl_post_debugger_command(NULL); // end of messages return 0; } @@ -588,11 +588,16 @@ static void dbg_dap_init(const char *path) { SDL_CreateThread(read_command_thread, "Debugger", NULL); - while (!initialized) { - char *msg = msgq_dequeue(queue); - if (!msg) - break; - handle_message(msg); + while (!initialized && !nact->is_quit) { + SDL_Event e; + SDL_WaitEvent(&e); + sdl_handle_event(&e); + while (!msgq_isempty(queue)) { + char *msg = msgq_dequeue(queue); + if (!msg) + return; + handle_message(msg); + } } } @@ -605,11 +610,16 @@ static void dbg_dap_repl(int bp_no) { dbg_state = DBG_RUNNING; boolean continue_repl = true; - while (continue_repl) { - char *msg = msgq_dequeue(queue); - if (!msg) - break; - continue_repl = handle_message(msg); + while (continue_repl && !nact->is_quit) { + SDL_Event e; + SDL_WaitEvent(&e); + sdl_handle_event(&e); + while (!msgq_isempty(queue)) { + char *msg = msgq_dequeue(queue); + if (!msg) + return; + continue_repl = handle_message(msg); + } } } @@ -624,6 +634,10 @@ static void dbg_dap_onsleep(void) { dbg_main(0); } +void dbg_post_command(void *data) { + msgq_enqueue(queue, data); +} + DebuggerImpl dbg_dap_impl = { .init = dbg_dap_init, .quit = dbg_dap_quit, diff --git a/src/sdl_core.h b/src/sdl_core.h index 98e29e5..d6f93bd 100644 --- a/src/sdl_core.h +++ b/src/sdl_core.h @@ -25,6 +25,7 @@ #include "config.h" #include +#include #include #include "portab.h" #include "ags.h" @@ -110,5 +111,7 @@ extern uint32_t sdl_getTicks(void); extern void sdl_sleep(int msec); extern void sdl_wait_vsync(); extern boolean sdl_inputString(struct inputstring_param *); +extern void sdl_post_debugger_command(void *data); +extern void sdl_handle_event(SDL_Event *e); #endif /* !__SDL_CORE__ */ diff --git a/src/sdl_event.c b/src/sdl_event.c index eae1075..279020e 100644 --- a/src/sdl_event.c +++ b/src/sdl_event.c @@ -33,6 +33,7 @@ #include "portab.h" #include "system.h" +#include "debugger.h" #include "nact.h" #include "sdl_core.h" #include "sdl_private.h" @@ -47,6 +48,7 @@ static uint32_t custom_event_type = (uint32_t)-1; enum CustomEventCode { SIMULATE_RIGHT_BUTTON, + DEBUGGER_COMMAND, }; /* pointer の状態 */ @@ -233,190 +235,195 @@ static void rance4v2_hack(void) { nact->wait_vsync = FALSE; } +void sdl_handle_event(SDL_Event *e) { + if (sdl_custom_event_handler && sdl_custom_event_handler(e)) + return; + + switch (e->type) { + case SDL_QUIT: + menu_quitmenu_open(); + break; + + case SDL_WINDOWEVENT: + switch (e->window.event) { + case SDL_WINDOWEVENT_EXPOSED: + sdl_dirty = TRUE; + break; + } + break; +#ifdef _WIN32 + case SDL_SYSWMEVENT: + win_menu_onsyswmevent(e->syswm.msg); + break; +#endif + case SDL_APP_DIDENTERFOREGROUND: + sdl_dirty = TRUE; + break; + case SDL_KEYDOWN: + keyEventProsess(&e->key, TRUE); + break; + case SDL_KEYUP: + keyEventProsess(&e->key, FALSE); + switch (e->key.keysym.sym) { + case SDLK_F1: + msgskip_activate(!msgskip_isActivated()); + break; + case SDLK_F4: + sdl_setFullscreen(!sdl_fs_on); + break; + } + break; + case SDL_MOUSEMOTION: + mousex = e->motion.x; + mousey = e->motion.y; + send_agsevent(AGSEVENT_MOUSE_MOTION, 0); + break; + + case SDL_MOUSEWHEEL: + { + int y = e->wheel.y * (e->wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? -1 : 1); + if (y > 0) + mouse_wheel_up += y; + else if (y < 0) + mouse_wheel_down -= y; + send_agsevent(AGSEVENT_MOUSE_WHEEL, y); + break; + } + + case SDL_MOUSEBUTTONDOWN: + mouseb |= (1 << e->button.button); + RawKeyInfo[mouse_to_rawkey(e->button.button)] = TRUE; + send_agsevent(AGSEVENT_BUTTON_PRESS, mouse_to_agsevent(e->button.button)); + break; + + case SDL_MOUSEBUTTONUP: + mouseb &= (0xffffffff ^ (1 << e->button.button)); + RawKeyInfo[mouse_to_rawkey(e->button.button)] = FALSE; + send_agsevent(AGSEVENT_BUTTON_RELEASE, mouse_to_agsevent(e->button.button)); + if (e->button.button == 2) { + menu_open(); + } + break; + + case SDL_FINGERDOWN: + if (SDL_GetNumTouchFingers(e->tfinger.touchId) >= 2) { + mouseb &= ~(1 << SDL_BUTTON_LEFT); + mouseb |= 1 << SDL_BUTTON_RIGHT; + RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_LEFT)] = FALSE; + RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_RIGHT)] = TRUE; + send_agsevent(AGSEVENT_BUTTON_PRESS, AGSEVENT_BUTTON_RIGHT); + } else { + // SDL_RendererEventWatch clamps touch locations outside of the + // viewport to 0.0-1.0. Treat such events as right-clicks. + int button; + if (e->tfinger.x == 0.0f || e->tfinger.x == 1.0f || e->tfinger.y == 0.0f || e->tfinger.y == 1.0f) { + button = SDL_BUTTON_RIGHT; + } else { + button = SDL_BUTTON_LEFT; + mousex = e->tfinger.x * view_w; + mousey = e->tfinger.y * view_h; + send_agsevent(AGSEVENT_MOUSE_MOTION, 0); + } + mouseb |= 1 << button; + RawKeyInfo[mouse_to_rawkey(button)] = TRUE; + send_agsevent(AGSEVENT_BUTTON_PRESS, mouse_to_agsevent(button)); + } + break; + + case SDL_FINGERUP: + if (SDL_GetNumTouchFingers(e->tfinger.touchId) == 0) { + int ags_button = (mouseb & 1 << SDL_BUTTON_LEFT) ? AGSEVENT_BUTTON_LEFT : AGSEVENT_BUTTON_RIGHT; + mouseb &= ~(1 << SDL_BUTTON_LEFT | 1 << SDL_BUTTON_RIGHT); + RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_LEFT)] = FALSE; + RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_RIGHT)] = FALSE; + mousex = e->tfinger.x * view_w; + mousey = e->tfinger.y * view_h; + send_agsevent(AGSEVENT_BUTTON_RELEASE, ags_button); + } + break; + + case SDL_FINGERMOTION: + mousex = e->tfinger.x * view_w; + mousey = e->tfinger.y * view_h; + send_agsevent(AGSEVENT_MOUSE_MOTION, 0); + break; + + case SDL_JOYDEVICEADDED: + sdl_joy_open(e->jdevice.which); + break; + + case SDL_JOYAXISMOTION: + if (abs(e->jaxis.value) < 0x4000) { + joyinfo &= e->jaxis.axis == 0 ? ~0xc : ~3; + } else { + int i = (e->jaxis.axis == 0 ? 2 : 0) + + (e->jaxis.value > 0 ? 1 : 0); + joyinfo |= 1 << i; + } + break; + + case SDL_JOYBALLMOTION: + break; + + case SDL_JOYHATMOTION: + joyinfo &= ~(SYS35KEY_UP | SYS35KEY_DOWN | SYS35KEY_LEFT | SYS35KEY_RIGHT); + switch (e->jhat.value) { + case SDL_HAT_UP: joyinfo |= SYS35KEY_UP; break; + case SDL_HAT_DOWN: joyinfo |= SYS35KEY_DOWN; break; + case SDL_HAT_LEFT: joyinfo |= SYS35KEY_LEFT; break; + case SDL_HAT_RIGHT: joyinfo |= SYS35KEY_RIGHT; break; + case SDL_HAT_LEFTUP: joyinfo |= SYS35KEY_LEFT | SYS35KEY_UP; break; + case SDL_HAT_RIGHTUP: joyinfo |= SYS35KEY_RIGHT | SYS35KEY_UP; break; + case SDL_HAT_LEFTDOWN: joyinfo |= SYS35KEY_LEFT | SYS35KEY_DOWN; break; + case SDL_HAT_RIGHTDOWN: joyinfo |= SYS35KEY_RIGHT | SYS35KEY_DOWN; break; + } + break; + + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + if (e->jbutton.button < 4) { + int i = 1 << (e->jbutton.button+4); + if (e->jbutton.state == SDL_PRESSED) + joyinfo |= i; + else + joyinfo &= ~i; + } else { + if (e->jbutton.state == SDL_RELEASED) { + } + } + break; + default: + if (e->type == custom_event_type) { + switch (e->user.code) { + case SIMULATE_RIGHT_BUTTON: + if ((intptr_t)e->user.data1) { + mouseb |= 1 << SDL_BUTTON_RIGHT; + RawKeyInfo[KEY_MOUSE_RIGHT] = TRUE; + send_agsevent(AGSEVENT_BUTTON_PRESS, AGSEVENT_BUTTON_RIGHT); + } else { + mouseb &= ~(1 << SDL_BUTTON_RIGHT); + RawKeyInfo[KEY_MOUSE_RIGHT] = FALSE; + send_agsevent(AGSEVENT_BUTTON_RELEASE, AGSEVENT_BUTTON_RIGHT); + } + break; + case DEBUGGER_COMMAND: + dbg_post_command(e->user.data1); + break; + } + } + break; + } +} + /* Event処理 */ static void sdl_getEvent(void) { static int cmd_count_of_prev_input = -1; - SDL_Event e; - boolean m2b = FALSE, msg_skip = FALSE; boolean had_input = false; + SDL_Event e; while (SDL_PollEvent(&e)) { had_input = true; - - if (sdl_custom_event_handler && sdl_custom_event_handler(&e)) - continue; - - switch (e.type) { - case SDL_QUIT: - menu_quitmenu_open(); - break; - - case SDL_WINDOWEVENT: - switch (e.window.event) { - case SDL_WINDOWEVENT_EXPOSED: - sdl_dirty = TRUE; - break; - } - break; -#ifdef _WIN32 - case SDL_SYSWMEVENT: - win_menu_onsyswmevent(e.syswm.msg); - break; -#endif - case SDL_APP_DIDENTERFOREGROUND: - sdl_dirty = TRUE; - break; - case SDL_KEYDOWN: - keyEventProsess(&e.key, TRUE); - break; - case SDL_KEYUP: - keyEventProsess(&e.key, FALSE); - switch (e.key.keysym.sym) { - case SDLK_F1: - msg_skip = TRUE; - break; - case SDLK_F4: - sdl_setFullscreen(!sdl_fs_on); - break; - } - break; - case SDL_MOUSEMOTION: - mousex = e.motion.x; - mousey = e.motion.y; - send_agsevent(AGSEVENT_MOUSE_MOTION, 0); - break; - - case SDL_MOUSEWHEEL: - { - int y = e.wheel.y * (e.wheel.direction == SDL_MOUSEWHEEL_FLIPPED ? -1 : 1); - if (y > 0) - mouse_wheel_up += y; - else if (y < 0) - mouse_wheel_down -= y; - send_agsevent(AGSEVENT_MOUSE_WHEEL, y); - break; - } - - case SDL_MOUSEBUTTONDOWN: - mouseb |= (1 << e.button.button); - RawKeyInfo[mouse_to_rawkey(e.button.button)] = TRUE; - send_agsevent(AGSEVENT_BUTTON_PRESS, mouse_to_agsevent(e.button.button)); - break; - - case SDL_MOUSEBUTTONUP: - mouseb &= (0xffffffff ^ (1 << e.button.button)); - RawKeyInfo[mouse_to_rawkey(e.button.button)] = FALSE; - send_agsevent(AGSEVENT_BUTTON_RELEASE, mouse_to_agsevent(e.button.button)); - if (e.button.button == 2) { - m2b = TRUE; - } - break; - - case SDL_FINGERDOWN: - if (SDL_GetNumTouchFingers(e.tfinger.touchId) >= 2) { - mouseb &= ~(1 << SDL_BUTTON_LEFT); - mouseb |= 1 << SDL_BUTTON_RIGHT; - RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_LEFT)] = FALSE; - RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_RIGHT)] = TRUE; - send_agsevent(AGSEVENT_BUTTON_PRESS, AGSEVENT_BUTTON_RIGHT); - } else { - // SDL_RendererEventWatch clamps touch locations outside of the - // viewport to 0.0-1.0. Treat such events as right-clicks. - int button; - if (e.tfinger.x == 0.0f || e.tfinger.x == 1.0f || e.tfinger.y == 0.0f || e.tfinger.y == 1.0f) { - button = SDL_BUTTON_RIGHT; - } else { - button = SDL_BUTTON_LEFT; - mousex = e.tfinger.x * view_w; - mousey = e.tfinger.y * view_h; - send_agsevent(AGSEVENT_MOUSE_MOTION, 0); - } - mouseb |= 1 << button; - RawKeyInfo[mouse_to_rawkey(button)] = TRUE; - send_agsevent(AGSEVENT_BUTTON_PRESS, mouse_to_agsevent(button)); - } - break; - - case SDL_FINGERUP: - if (SDL_GetNumTouchFingers(e.tfinger.touchId) == 0) { - int ags_button = (mouseb & 1 << SDL_BUTTON_LEFT) ? AGSEVENT_BUTTON_LEFT : AGSEVENT_BUTTON_RIGHT; - mouseb &= ~(1 << SDL_BUTTON_LEFT | 1 << SDL_BUTTON_RIGHT); - RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_LEFT)] = FALSE; - RawKeyInfo[mouse_to_rawkey(SDL_BUTTON_RIGHT)] = FALSE; - mousex = e.tfinger.x * view_w; - mousey = e.tfinger.y * view_h; - send_agsevent(AGSEVENT_BUTTON_RELEASE, ags_button); - } - break; - - case SDL_FINGERMOTION: - mousex = e.tfinger.x * view_w; - mousey = e.tfinger.y * view_h; - send_agsevent(AGSEVENT_MOUSE_MOTION, 0); - break; - - case SDL_JOYDEVICEADDED: - sdl_joy_open(e.jdevice.which); - break; - - case SDL_JOYAXISMOTION: - if (abs(e.jaxis.value) < 0x4000) { - joyinfo &= e.jaxis.axis == 0 ? ~0xc : ~3; - } else { - int i = (e.jaxis.axis == 0 ? 2 : 0) + - (e.jaxis.value > 0 ? 1 : 0); - joyinfo |= 1 << i; - } - break; - - case SDL_JOYBALLMOTION: - break; - - case SDL_JOYHATMOTION: - joyinfo &= ~(SYS35KEY_UP | SYS35KEY_DOWN | SYS35KEY_LEFT | SYS35KEY_RIGHT); - switch (e.jhat.value) { - case SDL_HAT_UP: joyinfo |= SYS35KEY_UP; break; - case SDL_HAT_DOWN: joyinfo |= SYS35KEY_DOWN; break; - case SDL_HAT_LEFT: joyinfo |= SYS35KEY_LEFT; break; - case SDL_HAT_RIGHT: joyinfo |= SYS35KEY_RIGHT; break; - case SDL_HAT_LEFTUP: joyinfo |= SYS35KEY_LEFT | SYS35KEY_UP; break; - case SDL_HAT_RIGHTUP: joyinfo |= SYS35KEY_RIGHT | SYS35KEY_UP; break; - case SDL_HAT_LEFTDOWN: joyinfo |= SYS35KEY_LEFT | SYS35KEY_DOWN; break; - case SDL_HAT_RIGHTDOWN: joyinfo |= SYS35KEY_RIGHT | SYS35KEY_DOWN; break; - } - break; - - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: - if (e.jbutton.button < 4) { - int i = 1 << (e.jbutton.button+4); - if (e.jbutton.state == SDL_PRESSED) - joyinfo |= i; - else - joyinfo &= ~i; - } else { - if (e.jbutton.state == SDL_RELEASED) { - } - } - break; - default: - if (e.type == custom_event_type) { - switch (e.user.code) { - case SIMULATE_RIGHT_BUTTON: - if ((intptr_t)e.user.data1) { - mouseb |= 1 << SDL_BUTTON_RIGHT; - RawKeyInfo[KEY_MOUSE_RIGHT] = TRUE; - send_agsevent(AGSEVENT_BUTTON_PRESS, AGSEVENT_BUTTON_RIGHT); - } else { - mouseb &= ~(1 << SDL_BUTTON_RIGHT); - RawKeyInfo[KEY_MOUSE_RIGHT] = FALSE; - send_agsevent(AGSEVENT_BUTTON_RELEASE, AGSEVENT_BUTTON_RIGHT); - } - break; - } - } - break; - } + sdl_handle_event(&e); } if (had_input) { cmd_count_of_prev_input = nact->cmd_count; @@ -425,12 +432,6 @@ static void sdl_getEvent(void) { if (nact->game == GAME_RANCE4_V2) rance4v2_hack(); } - - if (m2b) { - menu_open(); - } - - if (msg_skip) msgskip_activate(!msgskip_isActivated()); } /* キー情報の取得 */ @@ -488,6 +489,17 @@ int sdl_getJoyInfo(void) { return joyinfo; } +void sdl_post_debugger_command(void *data) { + SDL_Event event = { + .user = { + .type = custom_event_type, + .code = DEBUGGER_COMMAND, + .data1 = data + } + }; + SDL_PushEvent(&event); +} + #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE void simulate_right_button(int pressed) {