Skip to content

Commit 719a566

Browse files
committed
Add input event specific system calls
This commit integrates a new system call, syscall_poll_event, with SDL's event system, three types of input-specific events are supported: keyboard event, mouse motion event and mouse button event, this input system will improve the interactivity of the demos.
1 parent a99d779 commit 719a566

File tree

2 files changed

+146
-3
lines changed

2 files changed

+146
-3
lines changed

syscall.c

+4
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ static void syscall_open(struct riscv_t *rv)
301301
#ifdef ENABLE_SDL
302302
extern void syscall_draw_frame(struct riscv_t *rv);
303303
extern void syscall_draw_frame_pal(struct riscv_t *rv);
304+
extern void syscall_poll_event(struct riscv_t *rv);
304305
#endif
305306

306307
void syscall_handler(struct riscv_t *rv)
@@ -343,6 +344,9 @@ void syscall_handler(struct riscv_t *rv)
343344
case 0xbabe:
344345
syscall_draw_frame_pal(rv);
345346
break;
347+
case 0xc0de:
348+
syscall_poll_event(rv);
349+
break;
346350
#endif
347351
default:
348352
fprintf(stderr, "unknown syscall %d\n", (int) syscall);

syscall_sdl.c

+142-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,71 @@
99

1010
#include "state.h"
1111

12+
#define MAX_EVENT_QUEUE_SIZE 128
13+
14+
enum {
15+
KEY_EVENT = 0,
16+
MOUSE_MOTION_EVENT = 1,
17+
MOUSE_BUTTON_EVENT = 2,
18+
};
19+
20+
typedef struct {
21+
uint32_t keycode;
22+
uint8_t state;
23+
} key_event_t;
24+
25+
typedef struct {
26+
int32_t xrel, yrel;
27+
} mouse_motion_t;
28+
29+
typedef struct {
30+
uint8_t button;
31+
uint8_t state;
32+
} mouse_button_t;
33+
34+
typedef struct {
35+
uint32_t type;
36+
union {
37+
key_event_t key_event;
38+
mouse_motion_t mouse_motion;
39+
mouse_button_t mouse_button;
40+
};
41+
} event_t;
42+
43+
typedef struct {
44+
event_t events[MAX_EVENT_QUEUE_SIZE];
45+
size_t start, end;
46+
bool full;
47+
} event_queue_t;
48+
1249
static SDL_Window *window = NULL;
1350
static SDL_Renderer *renderer;
1451
static SDL_Texture *texture;
52+
static event_queue_t event_queue = {
53+
.events = {},
54+
.start = 0,
55+
.end = 0,
56+
.full = false,
57+
};
58+
59+
static bool event_pop(event_t *event)
60+
{
61+
if (event_queue.start == event_queue.end)
62+
return false;
63+
*event = event_queue.events[event_queue.start++];
64+
event_queue.start &= MAX_EVENT_QUEUE_SIZE - 1;
65+
event_queue.full = false;
66+
return true;
67+
}
68+
69+
static void event_push(event_t event)
70+
{
71+
if (event_queue.full)
72+
return;
73+
event_queue.events[event_queue.end++] = event;
74+
event_queue.end &= MAX_EVENT_QUEUE_SIZE - 1;
75+
event_queue.full = (event_queue.start == event_queue.end);
76+
}
1577

1678
/* check if we need to setup SDL and run event loop */
1779
static bool check_sdl(struct riscv_t *rv, uint32_t width, uint32_t height)
@@ -43,10 +105,55 @@ static bool check_sdl(struct riscv_t *rv, uint32_t width, uint32_t height)
43105
rv_halt(rv);
44106
return false;
45107
case SDL_KEYDOWN:
46-
if (event.key.keysym.sym == SDLK_ESCAPE) {
47-
rv_halt(rv);
48-
return false;
108+
if (event.key.keysym.sym == SDLK_ESCAPE &&
109+
SDL_GetRelativeMouseMode() == SDL_TRUE) {
110+
SDL_SetRelativeMouseMode(SDL_FALSE);
111+
break;
49112
}
113+
/* fall through */
114+
case SDL_KEYUP: {
115+
if (event.key.repeat)
116+
break;
117+
event_t new_event = {
118+
.type = KEY_EVENT,
119+
.key_event =
120+
{
121+
.keycode = event.key.keysym.sym,
122+
.state = (bool) (event.key.state == SDL_PRESSED),
123+
},
124+
};
125+
event_push(new_event);
126+
break;
127+
}
128+
case SDL_MOUSEMOTION: {
129+
event_t new_event = {
130+
.type = MOUSE_MOTION_EVENT,
131+
.mouse_motion =
132+
{
133+
.xrel = event.motion.xrel,
134+
.yrel = event.motion.yrel,
135+
},
136+
};
137+
event_push(new_event);
138+
break;
139+
}
140+
case SDL_MOUSEBUTTONDOWN:
141+
if (event.button.button == SDL_BUTTON_LEFT &&
142+
SDL_GetRelativeMouseMode() == SDL_FALSE) {
143+
SDL_SetRelativeMouseMode(SDL_TRUE);
144+
break;
145+
}
146+
/* fall through */
147+
case SDL_MOUSEBUTTONUP: {
148+
event_t new_event = {
149+
.type = MOUSE_BUTTON_EVENT,
150+
.mouse_button = {
151+
.button = event.button.button,
152+
.state = (bool) (event.button.state == SDL_PRESSED),
153+
}};
154+
event_push(new_event);
155+
break;
156+
}
50157
}
51158
}
52159
return true;
@@ -118,3 +225,35 @@ void syscall_draw_frame_pal(struct riscv_t *rv)
118225
free(i);
119226
free(j);
120227
}
228+
229+
void syscall_poll_event(struct riscv_t *rv)
230+
{
231+
state_t *s = rv_userdata(rv); /* access userdata */
232+
233+
/* poll_event(base) */
234+
const uint32_t base = rv_get_reg(rv, rv_reg_a0);
235+
236+
event_t event;
237+
if (!event_pop(&event)) {
238+
rv_set_reg(rv, rv_reg_a0, 0);
239+
return;
240+
}
241+
242+
memory_write(s->mem, base + 0, (const uint8_t *) &event.type, 4);
243+
switch (event.type) {
244+
case KEY_EVENT:
245+
memory_write(s->mem, base + 4, (const uint8_t *) &event.key_event,
246+
sizeof(key_event_t));
247+
break;
248+
case MOUSE_MOTION_EVENT:
249+
memory_write(s->mem, base + 4, (const uint8_t *) &event.mouse_motion,
250+
sizeof(mouse_motion_t));
251+
break;
252+
case MOUSE_BUTTON_EVENT:
253+
memory_write(s->mem, base + 4, (const uint8_t *) &event.mouse_button,
254+
sizeof(mouse_button_t));
255+
break;
256+
}
257+
258+
rv_set_reg(rv, rv_reg_a0, 1);
259+
}

0 commit comments

Comments
 (0)