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 case SDLK_F11:
63 if (event->type == SDL_KEYDOWN && context->debugger) {
64 ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
65 }
66 break;
67 case SDLK_TAB:
68 context->sync.audioWait = event->type != SDL_KEYDOWN;
69 return;
70 case SDLK_LEFTBRACKET:
71 if (!isPaused) {
72 GBAThreadPause(context);
73 }
74 GBARewind(context, 10);
75 if (!isPaused) {
76 GBAThreadUnpause(context);
77 }
78 default:
79 if (event->type == SDL_KEYDOWN) {
80 if (event->keysym.mod & KMOD_CTRL) {
81 switch (event->keysym.sym) {
82 case SDLK_p:
83 GBAThreadTogglePause(context);
84 break;
85 case SDLK_n:
86 GBAThreadPause(context);
87 context->frameCallback = _pauseAfterFrame;
88 GBAThreadUnpause(context);
89 break;
90 default:
91 break;
92 }
93 }
94 if (event->keysym.mod & KMOD_SHIFT) {
95 switch (event->keysym.sym) {
96 case SDLK_F1:
97 case SDLK_F2:
98 case SDLK_F3:
99 case SDLK_F4:
100 case SDLK_F5:
101 case SDLK_F6:
102 case SDLK_F7:
103 case SDLK_F8:
104 case SDLK_F9:
105 case SDLK_F10:
106 if (!isPaused) {
107 GBAThreadPause(context);
108 }
109 GBASaveState(context->gba, event->keysym.sym - SDLK_F1);
110 if (!isPaused) {
111 GBAThreadUnpause(context);
112 }
113 break;
114 default:
115 break;
116 }
117 } else {
118 switch (event->keysym.sym) {
119 case SDLK_F1:
120 case SDLK_F2:
121 case SDLK_F3:
122 case SDLK_F4:
123 case SDLK_F5:
124 case SDLK_F6:
125 case SDLK_F7:
126 case SDLK_F8:
127 case SDLK_F9:
128 case SDLK_F10:
129 if (!isPaused) {
130 GBAThreadPause(context);
131 }
132 GBALoadState(context->gba, event->keysym.sym - SDLK_F1);
133 if (!isPaused) {
134 GBAThreadUnpause(context);
135 }
136 break;
137 default:
138 break;
139 }
140 }
141 }
142 return;
143 }
144
145 if (event->type == SDL_KEYDOWN) {
146 context->activeKeys |= 1 << key;
147 } else {
148 context->activeKeys &= ~(1 << key);
149 }
150}
151
152static void _GBASDLHandleJoyButton(struct GBAThread* context, const struct SDL_JoyButtonEvent* event) {
153 enum GBAKey key = 0;
154 // Sorry, hardcoded to my gamepad for now
155 switch (event->button) {
156 case 2:
157 key = GBA_KEY_A;
158 break;
159 case 1:
160 key = GBA_KEY_B;
161 break;
162 case 6:
163 key = GBA_KEY_L;
164 break;
165 case 7:
166 key = GBA_KEY_R;
167 break;
168 case 8:
169 key = GBA_KEY_START;
170 break;
171 case 9:
172 key = GBA_KEY_SELECT;
173 break;
174 default:
175 return;
176 }
177
178 if (event->type == SDL_JOYBUTTONDOWN) {
179 context->activeKeys |= 1 << key;
180 } else {
181 context->activeKeys &= ~(1 << key);
182 }
183}
184
185static void _GBASDLHandleJoyHat(struct GBAThread* context, const struct SDL_JoyHatEvent* event) {
186 enum GBAKey key = 0;
187
188 if (event->value & SDL_HAT_UP) {
189 key |= 1 << GBA_KEY_UP;
190 }
191 if (event->value & SDL_HAT_LEFT) {
192 key |= 1 << GBA_KEY_LEFT;
193 }
194 if (event->value & SDL_HAT_DOWN) {
195 key |= 1 << GBA_KEY_DOWN;
196 }
197 if (event->value & SDL_HAT_RIGHT) {
198 key |= 1 << GBA_KEY_RIGHT;
199 }
200
201 context->activeKeys &= ~((1 << GBA_KEY_UP) | (1 << GBA_KEY_LEFT) | (1 << GBA_KEY_DOWN) | (1 << GBA_KEY_RIGHT));
202 context->activeKeys |= key;
203}
204
205void GBASDLHandleEvent(struct GBAThread* context, const union SDL_Event* event) {
206 switch (event->type) {
207 case SDL_QUIT:
208 // FIXME: this isn't thread-safe
209 if (context->debugger) {
210 context->debugger->state = DEBUGGER_EXITING;
211 }
212 MutexLock(&context->stateMutex);
213 context->state = THREAD_EXITING;
214 ConditionWake(&context->stateCond);
215 MutexUnlock(&context->stateMutex);
216 break;
217 case SDL_KEYDOWN:
218 case SDL_KEYUP:
219 _GBASDLHandleKeypress(context, &event->key);
220 break;
221 case SDL_JOYBUTTONDOWN:
222 case SDL_JOYBUTTONUP:
223 _GBASDLHandleJoyButton(context, &event->jbutton);
224 break;
225 case SDL_JOYHATMOTION:
226 _GBASDLHandleJoyHat(context, &event->jhat);
227 }
228}