src/gl-main.c (view raw)
1#include "debugger.h"
2#include "gba-thread.h"
3#include "gba.h"
4#include "sdl-events.h"
5#include "renderers/video-software.h"
6
7#include <SDL.h>
8#ifdef __APPLE__
9#include <OpenGL/gl.h>
10#else
11#include <GL/gl.h>
12#endif
13
14#include <fcntl.h>
15#include <errno.h>
16#include <signal.h>
17#include <sys/time.h>
18#include <unistd.h>
19
20struct GLSoftwareRenderer {
21 struct GBAVideoSoftwareRenderer d;
22
23 GLuint tex;
24};
25
26static int _GBASDLInit(struct GLSoftwareRenderer* renderer);
27static void _GBASDLDeinit(struct GLSoftwareRenderer* renderer);
28static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer* renderer);
29
30static const GLint _glVertices[] = {
31 0, 0,
32 256, 0,
33 256, 256,
34 0, 256
35};
36
37static const GLint _glTexCoords[] = {
38 0, 0,
39 1, 0,
40 1, 1,
41 0, 1
42};
43
44int main(int argc, char** argv) {
45 const char* fname = "test.rom";
46 if (argc > 1) {
47 fname = argv[1];
48 }
49 int fd = open(fname, O_RDONLY);
50 if (fd < 0) {
51 return 1;
52 }
53
54 sigset_t signals;
55 sigaddset(&signals, SIGINT);
56 sigaddset(&signals, SIGTRAP);
57 pthread_sigmask(SIG_BLOCK, &signals, 0);
58
59 struct GBAThread context;
60 struct GLSoftwareRenderer renderer;
61 GBAVideoSoftwareRendererCreate(&renderer.d);
62
63 if (!_GBASDLInit(&renderer)) {
64 return 1;
65 }
66
67 context.fd = fd;
68 context.fname = fname;
69 context.useDebugger = 1;
70 context.renderer = &renderer.d.d;
71 GBAThreadStart(&context);
72
73 _GBASDLRunloop(&context, &renderer);
74
75 GBAThreadJoin(&context);
76 close(fd);
77
78 _GBASDLDeinit(&renderer);
79
80 return 0;
81}
82
83static int _GBASDLInit(struct GLSoftwareRenderer* renderer) {
84 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
85 return 0;
86 }
87
88 GBASDLInitEvents();
89
90 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
91 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
92 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
93 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
94 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
95#ifdef COLOR_16_BIT
96 SDL_SetVideoMode(240, 160, 16, SDL_OPENGL);
97#else
98 SDL_SetVideoMode(240, 160, 32, SDL_OPENGL);
99#endif
100
101 renderer->d.outputBuffer = malloc(256 * 256 * 4);
102 renderer->d.outputBufferStride = 256;
103 glGenTextures(1, &renderer->tex);
104 glBindTexture(GL_TEXTURE_2D, renderer->tex);
105 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
106 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
107 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
108 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
109 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
110
111 glViewport(0, 0, 240, 160);
112
113 return 1;
114}
115
116static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer* renderer) {
117 SDL_Event event;
118
119 glEnable(GL_TEXTURE_2D);
120 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
121 glEnableClientState(GL_VERTEX_ARRAY);
122 glVertexPointer(2, GL_INT, 0, _glVertices);
123 glTexCoordPointer(2, GL_INT, 0, _glTexCoords);
124 glMatrixMode (GL_PROJECTION);
125 glLoadIdentity();
126 glOrtho(0, 240, 160, 0, 0, 1);
127 while (context->started && (!context->debugger || context->debugger->state != DEBUGGER_EXITING)) {
128 pthread_mutex_lock(&renderer->d.mutex);
129 if (renderer->d.d.framesPending) {
130 renderer->d.d.framesPending = 0;
131 pthread_mutex_unlock(&renderer->d.mutex);
132 glBindTexture(GL_TEXTURE_2D, renderer->tex);
133#ifdef COLOR_16_BIT
134 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, renderer->d.outputBuffer);
135#else
136 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer);
137#endif
138 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
139
140 SDL_GL_SwapBuffers();
141
142 while (SDL_PollEvent(&event)) {
143 GBASDLHandleEvent(context, &event);
144 }
145 pthread_mutex_lock(&renderer->d.mutex);
146 pthread_cond_broadcast(&renderer->d.downCond);
147 } else {
148 pthread_cond_broadcast(&renderer->d.downCond);
149 pthread_cond_wait(&renderer->d.upCond, &renderer->d.mutex);
150 }
151 pthread_mutex_unlock(&renderer->d.mutex);
152 }
153}
154
155static void _GBASDLDeinit(struct GLSoftwareRenderer* renderer) {
156 free(renderer->d.outputBuffer);
157
158 GBASDLDeinitEvents();
159 SDL_Quit();
160}