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.
This commit is contained in:
kichikuou
2023-06-20 11:07:28 +09:00
parent e9a30f7493
commit 30467371f4
4 changed files with 226 additions and 195 deletions
+2
View File
@@ -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
+26 -12
View File
@@ -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,
+3
View File
@@ -25,6 +25,7 @@
#include "config.h"
#include <sys/types.h>
#include <SDL_events.h>
#include <SDL_surface.h>
#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__ */
+195 -183
View File
@@ -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) {