all repos — mgba @ 07d3fbaceb5afa160d73acf99488e650666ad1a4

mGBA Game Boy Advance Emulator

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}