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