all repos — mgba @ 49de0fb52e8da117efe0cd076d1bd097844b1f54

mGBA Game Boy Advance Emulator

Different mains for SDL and EGL, supporting Raspberry Pi and BeagleBone Black
Jeffrey Pfau jeffrey@endrift.com
Wed, 29 May 2013 21:18:25 -0700
commit

49de0fb52e8da117efe0cd076d1bd097844b1f54

parent

f8b0acd86aa052a14f41d36527dcaa67bc2062b6

5 files changed, 286 insertions(+), 156 deletions(-)

jump to
M CMakeLists.txtCMakeLists.txt

@@ -1,10 +1,10 @@

cmake_minimum_required(VERSION 2.6) project(GBAc) -set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Wextra -Werror --std=gnu99") -set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -Wextra -Werror --std=gnu99") +set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Wextra -Wno-error=type-limits --std=gnu99") +set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -Wextra --std=gnu99") file(GLOB ARM_SRC ${CMAKE_SOURCE_DIR}/src/arm/*.c) file(GLOB GBA_SRC ${CMAKE_SOURCE_DIR}/src/gba/*.c) -file(GLOB RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/*.c) +file(GLOB RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/video-software.c) file(GLOB DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/*.c) file(GLOB THIRD_PARTY ${CMAKE_SOURCE_DIR}/third-party/linenoise/linenoise.c) include_directories(${CMAKE_SOURCE_DIR}/src/arm)

@@ -16,9 +16,19 @@ find_package(SDL 1.2 REQUIRED)

file(GLOB SDL_SRC ${CMAKE_SOURCE_DIR}/src/sdl/sdl-*.c) include_directories(${CMAKE_SOURCE_DIR}/src/sdl) -find_package(OpenGL REQUIRED) - +if(BUILD_RASPI AND BUILD_EGL) + set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/egl-main.c) + set(OPENGL_LIBRARY "-lEGL -lGLESv2 -lvcos -lvchiq_arm -lvchostif -lbcm_host") + set(OPENGL_INCLUDE_DIR "") + add_definitions(-DBUILD_RASPI) +elseif(BUILD_BBB OR BUILD_RASPI) + set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/sdl-main.c) +else() + set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/gl-main.c) + find_package(OpenGL REQUIRED) + include_directories(${SDL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) +endif() include_directories(${SDL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) -add_executable(gbac ${ARM_SRC} ${GBA_SRC} ${DEBUGGER_SRC} ${RENDERER_SRC} ${THIRD_PARTY} ${SDL_SRC} ${CMAKE_SOURCE_DIR}/src/main.c) +add_executable(gbac ${ARM_SRC} ${GBA_SRC} ${DEBUGGER_SRC} ${RENDERER_SRC} ${THIRD_PARTY} ${SDL_SRC} ${MAIN_SRC}) target_link_libraries(gbac m pthread ${SDL_LIBRARY} ${OPENGL_LIBRARY})
A src/egl-main.c

@@ -0,0 +1,172 @@

+#include "debugger.h" +#include "gba-thread.h" +#include "gba.h" +#include "renderers/video-glsl.h" +#include "sdl-events.h" + +#include <SDL.h> +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +#include <bcm_host.h> + +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <sys/time.h> +#include <unistd.h> + +struct GBAVideoEGLRenderer { + struct GBAVideoGLSLRenderer d; + + EGLDisplay display; + EGLSurface surface; + EGLContext context; +}; + +static int _GBAEGLInit(struct GBAVideoEGLRenderer* renderer); +static void _GBAEGLDeinit(struct GBAVideoEGLRenderer* renderer); +static void _GBAEGLRunloop(struct GBAThread* context, struct GBAVideoEGLRenderer* renderer); + +int main(int argc, char** argv) { + const char* fname = "test.rom"; + if (argc > 1) { + fname = argv[1]; + } + int fd = open(fname, O_RDONLY); + if (fd < 0) { + return 1; + } + + struct GBAThread context; + struct GBAVideoEGLRenderer renderer; + + if (!_GBAEGLInit(&renderer)) { + return 1; + } + GBAVideoGLSLRendererCreate(&renderer.d); + + context.fd = fd; + context.renderer = &renderer.d.d; + GBAThreadStart(&context); + + _GBAEGLRunloop(&context, &renderer); + + GBAThreadJoin(&context); + close(fd); + + _GBAEGLDeinit(&renderer); + + return 0; +} + +static int _GBAEGLInit(struct GBAVideoEGLRenderer* renderer) { + if (SDL_Init(SDL_INIT_JOYSTICK) < 0) { + return 0; + } + + GBASDLInitEvents(); + bcm_host_init(); + renderer->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + int major, minor; + if (EGL_FALSE == eglInitialize(renderer->display, &major, &minor)) { + printf("Failed to initialize EGL"); + return 0; + } + + if (EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) { + printf("Failed to get GLES API"); + return 0; + } + + const EGLint requestConfig[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLConfig config; + EGLint numConfigs; + + if (EGL_FALSE == eglChooseConfig(renderer->display, requestConfig, &config, 1, &numConfigs)) { + printf("Failed to choose EGL config\n"); + return 0; + } + + const EGLint contextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + renderer->context = eglCreateContext(renderer->display, config, EGL_NO_CONTEXT, contextAttributes); + + DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0); + DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); + + VC_RECT_T destRect = { + .x = 0, + .y = 0, + .width = 240, + .height = 160 + }; + + VC_RECT_T srcRect = { + .x = 0, + .y = 0, + .width = 240, + .height = 160 + }; + + DISPMANX_ELEMENT_HANDLE_T element = vc_dispmanx_element_add(update, display, 0, &destRect, 0, &srcRect, DISPMANX_PROTECTION_NONE, 0, 0, DISPMANX_NO_ROTATE); + vc_dispmanx_update_submit_sync(update); + + EGL_DISPMANX_WINDOW_T window = { + .element = element, + .width = 240, + .height = 160 + }; + + renderer->surface = eglCreateWindowSurface(renderer->display, config, &window, 0); + return EGL_TRUE == eglMakeCurrent(renderer->display, renderer->surface, renderer->surface, renderer->context); +} + +static void _GBAEGLRunloop(struct GBAThread* context, struct GBAVideoEGLRenderer* renderer) { + SDL_Event event; + + while (context->started && context->debugger->state != DEBUGGER_EXITING) { + GBAVideoGLSLRendererProcessEvents(&renderer->d); + pthread_mutex_lock(&renderer->d.mutex); + if (renderer->d.d.framesPending) { + renderer->d.d.framesPending = 0; + pthread_mutex_unlock(&renderer->d.mutex); + + eglSwapBuffers(renderer->display, renderer->surface); + + while (SDL_PollEvent(&event)) { + GBASDLHandleEvent(context, &event); + } + pthread_mutex_lock(&renderer->d.mutex); + pthread_cond_broadcast(&renderer->d.downCond); + } else { + pthread_cond_broadcast(&renderer->d.downCond); + pthread_cond_wait(&renderer->d.upCond, &renderer->d.mutex); + } + pthread_mutex_unlock(&renderer->d.mutex); + } +} + +static void _GBAEGLDeinit(struct GBAVideoEGLRenderer* renderer) { + eglMakeCurrent(renderer->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(renderer->display, renderer->surface); + eglDestroyContext(renderer->display, renderer->context); + eglTerminate(renderer->display); + + GBASDLDeinitEvents(); + SDL_Quit(); + + bcm_host_deinit(); +}
A src/sdl-main.c

@@ -0,0 +1,98 @@

+#include "debugger.h" +#include "gba-thread.h" +#include "gba.h" +#include "renderers/video-software.h" +#include "sdl-events.h" + +#include <SDL.h> + +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <sys/time.h> +#include <unistd.h> + +static int _GBASDLInit(void); +static void _GBASDLDeinit(void); +static void _GBASDLRunloop(struct GBAThread* context, struct GBAVideoSoftwareRenderer* renderer); + +int main(int argc, char** argv) { + const char* fname = "test.rom"; + if (argc > 1) { + fname = argv[1]; + } + int fd = open(fname, O_RDONLY); + if (fd < 0) { + return 1; + } + + struct GBAThread context; + struct GBAVideoSoftwareRenderer renderer; + + if (!_GBASDLInit()) { + return 1; + } + GBAVideoSoftwareRendererCreate(&renderer); + SDL_Surface* surface = SDL_GetVideoSurface(); + SDL_LockSurface(surface); + renderer.outputBuffer = surface->pixels; + renderer.outputBufferStride = surface->pitch / 4; + + context.fd = fd; + context.renderer = &renderer.d; + GBAThreadStart(&context); + + _GBASDLRunloop(&context, &renderer); + + SDL_UnlockSurface(surface); + GBAThreadJoin(&context); + close(fd); + + _GBASDLDeinit(); + + return 0; +} + +static int _GBASDLInit() { + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + return 0; + } + + GBASDLInitEvents(); + + SDL_SetVideoMode(240, 160, 32, SDL_DOUBLEBUF | SDL_HWSURFACE); + + return 1; +} + +static void _GBASDLRunloop(struct GBAThread* context, struct GBAVideoSoftwareRenderer* renderer) { + SDL_Event event; + SDL_Surface* surface = SDL_GetVideoSurface(); + + while (context->started && context->debugger->state != DEBUGGER_EXITING) { + pthread_mutex_lock(&renderer->mutex); + if (renderer->d.framesPending) { + renderer->d.framesPending = 0; + pthread_mutex_unlock(&renderer->mutex); + + SDL_UnlockSurface(surface); + SDL_Flip(surface); + SDL_LockSurface(surface); + + while (SDL_PollEvent(&event)) { + GBASDLHandleEvent(context, &event); + } + pthread_mutex_lock(&renderer->mutex); + pthread_cond_broadcast(&renderer->downCond); + } else { + pthread_cond_broadcast(&renderer->downCond); + pthread_cond_wait(&renderer->upCond, &renderer->mutex); + } + pthread_mutex_unlock(&renderer->mutex); + } +} + +static void _GBASDLDeinit() { + GBASDLDeinitEvents(); + SDL_Quit(); +}
D src/sdl/main.c

@@ -1,150 +0,0 @@

-#include "debugger.h" -#include "gba-thread.h" -#include "gba.h" -#include "sdl-events.h" -#include "renderers/video-software.h" - -#include <SDL.h> -#ifdef __APPLE__ -#include <OpenGL/gl.h> -#else -#include <GL/gl.h> -#endif - -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <sys/time.h> -#include <unistd.h> - -struct GLSoftwareRenderer { - struct GBAVideoSoftwareRenderer d; - - GLuint tex; -}; - -static int _GBASDLInit(struct GLSoftwareRenderer* renderer); -static void _GBASDLDeinit(struct GLSoftwareRenderer* renderer); -static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer* renderer); - -static const GLint _glVertices[] = { - 0, 0, - 256, 0, - 256, 256, - 0, 256 -}; - -static const GLint _glTexCoords[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 -}; - -int main(int argc, char** argv) { - const char* fname = "test.rom"; - if (argc > 1) { - fname = argv[1]; - } - int fd = open(fname, O_RDONLY); - if (fd < 0) { - return 1; - } - - sigset_t signals; - sigaddset(&signals, SIGINT); - sigaddset(&signals, SIGTRAP); - pthread_sigmask(SIG_BLOCK, &signals, 0); - - struct GBAThread context; - struct GLSoftwareRenderer renderer; - GBAVideoSoftwareRendererCreate(&renderer.d); - - if (!_GBASDLInit(&renderer)) { - return 1; - } - - context.fd = fd; - context.renderer = &renderer.d.d; - GBAThreadStart(&context); - - _GBASDLRunloop(&context, &renderer); - - GBAThreadJoin(&context); - close(fd); - - _GBASDLDeinit(&renderer); - - return 0; -} - -static int _GBASDLInit(struct GLSoftwareRenderer* renderer) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - return 0; - } - - GBASDLInitEvents(); - - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_SetVideoMode(240, 160, 32, SDL_OPENGL); - - renderer->d.outputBuffer = malloc(256 * 256 * 4); - renderer->d.outputBufferStride = 256; - glGenTextures(1, &renderer->tex); - glBindTexture(GL_TEXTURE_2D, renderer->tex); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glViewport(0, 0, 240, 160); - - return 1; -} - -static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer* renderer) { - SDL_Event event; - - glEnable(GL_TEXTURE_2D); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_INT, 0, _glVertices); - glTexCoordPointer(2, GL_INT, 0, _glTexCoords); - glMatrixMode (GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 240, 160, 0, 0, 1); - while (context->started && context->debugger->state != DEBUGGER_EXITING) { - pthread_mutex_lock(&renderer->d.mutex); - if (renderer->d.d.framesPending) { - renderer->d.d.framesPending = 0; - pthread_mutex_unlock(&renderer->d.mutex); - glBindTexture(GL_TEXTURE_2D, renderer->tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, renderer->d.outputBuffer); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - SDL_GL_SwapBuffers(); - - while (SDL_PollEvent(&event)) { - GBASDLHandleEvent(context, &event); - } - pthread_mutex_lock(&renderer->d.mutex); - pthread_cond_broadcast(&renderer->d.downCond); - } else { - pthread_cond_broadcast(&renderer->d.downCond); - pthread_cond_wait(&renderer->d.upCond, &renderer->d.mutex); - } - pthread_mutex_unlock(&renderer->d.mutex); - } -} - -static void _GBASDLDeinit(struct GLSoftwareRenderer* renderer) { - free(renderer->d.outputBuffer); - - GBASDLDeinitEvents(); - SDL_Quit(); -}