all repos — mgba @ cc2262149ec6b8ed18a6677a19c109b7eb384661

mGBA Game Boy Advance Emulator

src/main.c (view raw)

  1#include "debugger.h"
  2#include "gba-thread.h"
  3#include "gba.h"
  4#include "renderers/video-glsl.h"
  5
  6#include <SDL.h>
  7#ifdef __APPLE__
  8#include <OpenGL/gl.h>
  9#else
 10#include <GL/gl.h>
 11#endif
 12
 13#include <fcntl.h>
 14#include <errno.h>
 15#include <signal.h>
 16#include <sys/time.h>
 17#include <unistd.h>
 18
 19static int _GBASDLInit(void);
 20static void _GBASDLDeinit(void);
 21static void _GBASDLRunloop(struct GBAThread* context, struct GBAVideoGLSLRenderer* renderer);
 22static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_KeyboardEvent* event);
 23
 24
 25int main(int argc, char** argv) {
 26	const char* fname = "test.rom";
 27	if (argc > 1) {
 28		fname = argv[1];
 29	}
 30	int fd = open(fname, O_RDONLY);
 31	if (fd < 0) {
 32		return 1;
 33	}
 34
 35	struct GBAThread context;
 36	struct GBAVideoGLSLRenderer renderer;
 37
 38	if (!_GBASDLInit()) {
 39		return 1;
 40	}
 41	GBAVideoGLSLRendererCreate(&renderer);
 42
 43	context.fd = fd;
 44	context.renderer = &renderer.d;
 45	GBAThreadStart(&context);
 46
 47	_GBASDLRunloop(&context, &renderer);
 48
 49	GBAThreadJoin(&context);
 50	close(fd);
 51
 52	_GBASDLDeinit();
 53
 54	return 0;
 55}
 56
 57static int _GBASDLInit() {
 58	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 59		return 0;
 60	}
 61
 62	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
 63	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
 64	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
 65	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
 66	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
 67	SDL_SetVideoMode(240, 160, 32, SDL_OPENGL);
 68
 69	glViewport(0, 0, 240, 160);
 70
 71	return 1;
 72}
 73
 74static void _GBASDLRunloop(struct GBAThread* context, struct GBAVideoGLSLRenderer* renderer) {
 75	SDL_Event event;
 76
 77	glEnable(GL_TEXTURE_2D);
 78	while (context->started && context->debugger->state != DEBUGGER_EXITING) {
 79		GBAVideoGLSLRendererProcessEvents(renderer);
 80		pthread_mutex_lock(&renderer->mutex);
 81		if (renderer->d.framesPending) {
 82			renderer->d.framesPending = 0;
 83			pthread_mutex_unlock(&renderer->mutex);
 84
 85			SDL_GL_SwapBuffers();
 86
 87			while (SDL_PollEvent(&event)) {
 88				switch (event.type) {
 89				case SDL_QUIT:
 90					// FIXME: this isn't thread-safe
 91					context->debugger->state = DEBUGGER_EXITING;
 92					break;
 93				case SDL_KEYDOWN:
 94				case SDL_KEYUP:
 95					_GBASDLHandleKeypress(context, &event.key);
 96					break;
 97				}
 98			}
 99			pthread_mutex_lock(&renderer->mutex);
100			pthread_cond_broadcast(&renderer->downCond);
101		} else {
102			pthread_cond_broadcast(&renderer->downCond);
103			pthread_cond_wait(&renderer->upCond, &renderer->mutex);
104		}
105		pthread_mutex_unlock(&renderer->mutex);
106	}
107}
108
109static void _GBASDLDeinit() {
110	SDL_Quit();
111}
112
113static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_KeyboardEvent* event) {
114	enum GBAKey key = 0;
115	switch (event->keysym.sym) {
116	case SDLK_z:
117		key = GBA_KEY_A;
118		break;
119	case SDLK_x:
120		key = GBA_KEY_B;
121		break;
122	case SDLK_a:
123		key = GBA_KEY_L;
124		break;
125	case SDLK_s:
126		key = GBA_KEY_R;
127		break;
128	case SDLK_RETURN:
129		key = GBA_KEY_START;
130		break;
131	case SDLK_BACKSPACE:
132		key = GBA_KEY_SELECT;
133		break;
134	case SDLK_UP:
135		key = GBA_KEY_UP;
136		break;
137	case SDLK_DOWN:
138		key = GBA_KEY_DOWN;
139		break;
140	case SDLK_LEFT:
141		key = GBA_KEY_LEFT;
142		break;
143	case SDLK_RIGHT:
144		key = GBA_KEY_RIGHT;
145		break;
146	case SDLK_TAB:
147		context->renderer->turbo = !context->renderer->turbo;
148		return;
149	default:
150		return;
151	}
152
153	if (event->type == SDL_KEYDOWN) {
154		context->activeKeys |= 1 << key;
155	} else {
156		context->activeKeys &= ~(1 << key);
157	}
158}