all repos — mgba @ 9c2c93220b22887991cc7141a8c8669f2150d6fa

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