all repos — mgba @ 26c1fbd48f574c700ae993eda7de8f37e08c1174

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