all repos — mgba @ 6616ca9111785abada65142442c51a84dc0c804d

mGBA Game Boy Advance Emulator

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}