all repos — mgba @ 705b6e9b139b7c0c6fe1c10ffe21a0a44241f9a9

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	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}