src/platform/sdl/sdl-events.c (view raw)
1#include "sdl-events.h"
2
3#include "debugger.h"
4#include "gba-io.h"
5#include "gba-serialize.h"
6#include "gba-video.h"
7
8int GBASDLInitEvents(struct GBASDLEvents* context) {
9 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
10 return 0;
11 }
12 SDL_JoystickEventState(SDL_ENABLE);
13 context->joystick = SDL_JoystickOpen(0);
14#if !SDL_VERSION_ATLEAST(2, 0, 0)
15 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
16#endif
17 return 1;
18}
19
20void GBASDLDeinitEvents(struct GBASDLEvents* context) {
21 SDL_JoystickClose(context->joystick);
22 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
23}
24
25static void _pauseAfterFrame(struct GBAThread* context) {
26 context->frameCallback = 0;
27 GBAThreadPause(context);
28}
29
30static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_KeyboardEvent* event) {
31 enum GBAKey key = 0;
32 int isPaused = GBAThreadIsPaused(context);
33 switch (event->keysym.sym) {
34 case SDLK_z:
35 key = GBA_KEY_A;
36 break;
37 case SDLK_x:
38 key = GBA_KEY_B;
39 break;
40 case SDLK_a:
41 key = GBA_KEY_L;
42 break;
43 case SDLK_s:
44 key = GBA_KEY_R;
45 break;
46 case SDLK_RETURN:
47 key = GBA_KEY_START;
48 break;
49 case SDLK_BACKSPACE:
50 key = GBA_KEY_SELECT;
51 break;
52 case SDLK_UP:
53 key = GBA_KEY_UP;
54 break;
55 case SDLK_DOWN:
56 key = GBA_KEY_DOWN;
57 break;
58 case SDLK_LEFT:
59 key = GBA_KEY_LEFT;
60 break;
61 case SDLK_RIGHT:
62 key = GBA_KEY_RIGHT;
63 break;
64 case SDLK_F11:
65 if (event->type == SDL_KEYDOWN && context->debugger) {
66 ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
67 }
68 break;
69 case SDLK_TAB:
70 context->sync.audioWait = event->type != SDL_KEYDOWN;
71 return;
72 case SDLK_LEFTBRACKET:
73 if (!isPaused) {
74 GBAThreadPause(context);
75 }
76 GBARewind(context, 10);
77 if (!isPaused) {
78 GBAThreadUnpause(context);
79 }
80 default:
81 if (event->type == SDL_KEYDOWN) {
82 if (event->keysym.mod & KMOD_CTRL) {
83 switch (event->keysym.sym) {
84 case SDLK_p:
85 GBAThreadTogglePause(context);
86 break;
87 case SDLK_n:
88 GBAThreadPause(context);
89 context->frameCallback = _pauseAfterFrame;
90 GBAThreadUnpause(context);
91 break;
92 default:
93 break;
94 }
95 }
96 if (event->keysym.mod & KMOD_SHIFT) {
97 switch (event->keysym.sym) {
98 case SDLK_F1:
99 case SDLK_F2:
100 case SDLK_F3:
101 case SDLK_F4:
102 case SDLK_F5:
103 case SDLK_F6:
104 case SDLK_F7:
105 case SDLK_F8:
106 case SDLK_F9:
107 case SDLK_F10:
108 if (!isPaused) {
109 GBAThreadPause(context);
110 }
111 GBASaveState(context->gba, event->keysym.sym - SDLK_F1);
112 if (!isPaused) {
113 GBAThreadUnpause(context);
114 }
115 break;
116 default:
117 break;
118 }
119 } else {
120 switch (event->keysym.sym) {
121 case SDLK_F1:
122 case SDLK_F2:
123 case SDLK_F3:
124 case SDLK_F4:
125 case SDLK_F5:
126 case SDLK_F6:
127 case SDLK_F7:
128 case SDLK_F8:
129 case SDLK_F9:
130 case SDLK_F10:
131 if (!isPaused) {
132 GBAThreadPause(context);
133 }
134 GBALoadState(context->gba, event->keysym.sym - SDLK_F1);
135 if (!isPaused) {
136 GBAThreadUnpause(context);
137 }
138 break;
139 default:
140 break;
141 }
142 }
143 }
144 return;
145 }
146
147 if (event->type == SDL_KEYDOWN) {
148 context->activeKeys |= 1 << key;
149 } else {
150 context->activeKeys &= ~(1 << key);
151 }
152}
153
154static void _GBASDLHandleJoyButton(struct GBAThread* context, const struct SDL_JoyButtonEvent* event) {
155 enum GBAKey key = 0;
156 // Sorry, hardcoded to my gamepad for now
157 switch (event->button) {
158 case 2:
159 key = GBA_KEY_A;
160 break;
161 case 1:
162 key = GBA_KEY_B;
163 break;
164 case 6:
165 key = GBA_KEY_L;
166 break;
167 case 7:
168 key = GBA_KEY_R;
169 break;
170 case 8:
171 key = GBA_KEY_START;
172 break;
173 case 9:
174 key = GBA_KEY_SELECT;
175 break;
176 default:
177 return;
178 }
179
180 if (event->type == SDL_JOYBUTTONDOWN) {
181 context->activeKeys |= 1 << key;
182 } else {
183 context->activeKeys &= ~(1 << key);
184 }
185}
186
187static void _GBASDLHandleJoyHat(struct GBAThread* context, const struct SDL_JoyHatEvent* event) {
188 enum GBAKey key = 0;
189
190 if (event->value & SDL_HAT_UP) {
191 key |= 1 << GBA_KEY_UP;
192 }
193 if (event->value & SDL_HAT_LEFT) {
194 key |= 1 << GBA_KEY_LEFT;
195 }
196 if (event->value & SDL_HAT_DOWN) {
197 key |= 1 << GBA_KEY_DOWN;
198 }
199 if (event->value & SDL_HAT_RIGHT) {
200 key |= 1 << GBA_KEY_RIGHT;
201 }
202
203 context->activeKeys &= ~((1 << GBA_KEY_UP) | (1 << GBA_KEY_LEFT) | (1 << GBA_KEY_DOWN) | (1 << GBA_KEY_RIGHT));
204 context->activeKeys |= key;
205}
206
207void GBASDLHandleEvent(struct GBAThread* context, const union SDL_Event* event) {
208 switch (event->type) {
209 case SDL_QUIT:
210 // FIXME: this isn't thread-safe
211 if (context->debugger) {
212 context->debugger->state = DEBUGGER_EXITING;
213 }
214 MutexLock(&context->stateMutex);
215 context->state = THREAD_EXITING;
216 ConditionWake(&context->stateCond);
217 MutexUnlock(&context->stateMutex);
218 break;
219 case SDL_KEYDOWN:
220 case SDL_KEYUP:
221 _GBASDLHandleKeypress(context, &event->key);
222 break;
223 case SDL_JOYBUTTONDOWN:
224 case SDL_JOYBUTTONUP:
225 _GBASDLHandleJoyButton(context, &event->jbutton);
226 break;
227 case SDL_JOYHATMOTION:
228 _GBASDLHandleJoyHat(context, &event->jhat);
229 }
230}