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