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