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 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
15 return 1;
16}
17
18void GBASDLDeinitEvents(struct GBASDLEvents* context) {
19 SDL_JoystickClose(context->joystick);
20 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
21}
22
23static void _pauseAfterFrame(struct GBAThread* context) {
24 context->frameCallback = 0;
25 GBAThreadPause(context);
26}
27
28static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_KeyboardEvent* event) {
29 enum GBAKey key = 0;
30 int isPaused = GBAThreadIsPaused(context);
31 switch (event->keysym.sym) {
32 case SDLK_z:
33 key = GBA_KEY_A;
34 break;
35 case SDLK_x:
36 key = GBA_KEY_B;
37 break;
38 case SDLK_a:
39 key = GBA_KEY_L;
40 break;
41 case SDLK_s:
42 key = GBA_KEY_R;
43 break;
44 case SDLK_RETURN:
45 key = GBA_KEY_START;
46 break;
47 case SDLK_BACKSPACE:
48 key = GBA_KEY_SELECT;
49 break;
50 case SDLK_UP:
51 key = GBA_KEY_UP;
52 break;
53 case SDLK_DOWN:
54 key = GBA_KEY_DOWN;
55 break;
56 case SDLK_LEFT:
57 key = GBA_KEY_LEFT;
58 break;
59 case SDLK_RIGHT:
60 key = GBA_KEY_RIGHT;
61 break;
62#ifdef USE_DEBUGGER
63 case SDLK_F11:
64 if (event->type == SDL_KEYDOWN && context->debugger) {
65 ARMDebuggerEnter(context->debugger);
66 }
67 break;
68#endif
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}