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}