From 8ed30d6aec87c8fb8c4fa27e07a3699e3d5b8e42 Mon Sep 17 00:00:00 2001 From: Bobby Dilley Date: Sat, 4 Jan 2025 22:43:08 +0000 Subject: [PATCH] Rework settings, add border controls --- docs/lindbergh.conf | 143 ++++++++++++++++---------------------- src/lindbergh/border.c | 57 +++++++++++++++ src/lindbergh/border.h | 6 ++ src/lindbergh/config.c | 68 +++++++++++++++--- src/lindbergh/config.h | 9 ++- src/lindbergh/gluthooks.c | 33 +++++---- src/lindbergh/glxhooks.c | 59 ++++++++-------- 7 files changed, 231 insertions(+), 144 deletions(-) create mode 100644 src/lindbergh/border.c create mode 100644 src/lindbergh/border.h diff --git a/docs/lindbergh.conf b/docs/lindbergh.conf index 9cefc48..b39fdae 100644 --- a/docs/lindbergh.conf +++ b/docs/lindbergh.conf @@ -1,135 +1,98 @@ # SEGA Lindbergh Emulator Configuration File # By the Lindbergh Development Team 2024-2025 -# All config options here are commented out by default. -# Uncomment them to enable that configuration override option. - # Set the requested dip switch width here -# Default: 640 -# WIDTH 1360 +WIDTH AUTO # Set the requested dip switch height here -# Default: 480 -# HEIGHT 768 +HEIGHT AUTO # Set if the emulator should go full screen -# Default: 0 -# FULLSCREEN 0 +FULLSCREEN 0 # Sets the Input Mode # Mode 0: will use both SDL/X11 and EVDEV inputs (default) # Mode 1: will use SDL/X11 inputs only # Mode 2: will use EVDEV raw inputs only, which should be configured at the bottom of the settings file -# Default: 0 -# INPUT_MODE 0 +INPUT_MODE 0 # Set to 1 if you want to disable SDL (Fixes SRTV boost bar) -# Default: 0 -# NO_SDL 1 +NO_SDL 0 # Set the Region ( JP/US/EX ) -# Default: JP -# REGION EX +REGION EX # Set if you want the game to be Free Play -# Default: 0 -# FREEPLAY 1 - -# Set the different keys used to control the games. -# You can find out the key numbers by running `xev` on linux. -# 28=t, 10=1, 39=s, 14=5, 111=Up, 116=Down, 113=Left, 114=Right, 24=q, 25=w, 26=e, 27=r -# TEST_KEY 28 -# PLAYER_1_START_KEY 10 -# PLAYER_1_SERVICE_KEY 39 -# PLAYER_1_COIN_KEY 14 -# PLAYER_1_UP_KEY 111 -# PLAYER_1_DOWN_KEY 116 -# PLAYER_1_LEFT_KEY 113 -# PLAYER_1_RIGHT_KEY 114 -# PLAYER_1_BUTTON_1_KEY 24 -# PLAYER_1_BUTTON_2_KEY 25 -# PLAYER_1_BUTTON_3_KEY 26 -# PLAYER_1_BUTTON_4_KEY 27 +FREEPLAY 1 # Set if the emulator should emulate JVS and use the keyboard/mouse for controls. # If this is set to 0, then the emulator will route the traffic to the serial device # defined in JVS_PATH if it has been defined. -# Default: 1 -# EMULATE_JVS 0 +EMULATE_JVS 1 # Set if the emulator should emulate the rideboard used in the special games here -# If this is set to 0, then the emulator will route the traffic to the serial device -# defined in RIDEBOARD_PATH if it has been defined. -# Default: 0 (unless set by game) -# EMULATE_RIDEBOARD 1 +# If this is set to 0, then the emulator will route the traffic to one of the serial ports +EMULATE_RIDEBOARD AUTO # Set if the emulator should emulate the driveboard used in driving games here -# If this is set to 0, then the emulator will route the traffic to the serial device -# defined in DRIVEBOARD_PATH if it has been defined. -# Default: 0 (unless set by game) -# EMULATE_DRIVEBOARD 1 +# If this is set to 0, then the emulator will route the traffic to one of the serial ports +EMULATE_DRIVEBOARD AUTO # Set if the emulator should emulate the motion board from Outrun 2 SP SDX here -# If this is set to 0, then the emulator will route the traffic to the serial device -# defined in MOTIONBOARD_PATH if it has been defined. -# Default: 0 (unless set by game) -# EMULATE_MOTIONBOARD 1 +# If this is set to 0, then the emulator will route the traffic to one of the serial ports +EMULATE_MOTIONBOARD AUTO # Define the path to pass the JVS packets to if JVS is not being emulated. -# Default: /dev/ttyUSB0 -# JVS_PATH /dev/ttyUSB0 +JVS_PATH /dev/ttyUSB0 # Define the path to pass the first serial port to if it's not being emulated. -# Default: /dev/ttyS0 -# SERIAL_1_PATH /dev/ttyUSB0 +SERIAL_1_PATH /dev/ttyUSB0 # Define the path to pass the second serial port to if it's not being emulated. -# Default: /dev/ttyS1 -# SERIAL_2_PATH /dev/ttyUSB0 +SERIAL_2_PATH /dev/ttyUSB0 # Define the path to the sram.bin file -# Default: sram.bin -# SRAM_PATH sram.bin +SRAM_PATH sram.bin # Define the path to the eeprom.bin file -# Default: eeprom.bin -# EEPROM_PATH eeprom.bin +EEPROM_PATH eeprom.bin # Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown) -# Default: 0 -# GPU_VENDOR 0 +GPU_VENDOR 0 # Set if you want to see debug messages in the console -# Default: 0 -# DEBUG_MSGS 1 +DEBUG_MSGS 0 + +# Set if you'd like to add a border for optical light gun tracking +BORDER_ENABLED 0 + +# Set the thickness of the white border as a percentage of the width of the screen +WHITE_BORDER_PERCENTAGE 2 + +# Set the thickness of the black border which sits around the +# white border as a percentage of the width of the screen +BLACK_BORDER_PERCENTAGE 0 # Set to true if you experience flickering in hummer -# Default: 0 -# HUMMER_FLICKER_FIX 1 +HUMMER_FLICKER_FIX 0 # Set to keep the aspect ratio (4:3) in games like Sega Race TV and Primeval Hunt -# Default: 0 -# KEEP_ASPECT_RATIO 1 +KEEP_ASPECT_RATIO 0 # Set to 0 if you want to disable the Glare effect in OutRun -# Default: 0 -# OUTRUN_LENS_GLARE_ENABLED 0 - -# Set to 1 if you want to limit the FPS in games that are not limited like OutRun2 -# Default: 0 -# FPS_LIMITER_ENABLED 1 - -# Set the target FPS (will only work if FPS_LIMITER_ENABLED = 1) -# Default: 60 -# FPS_TARGET 60 +OUTRUN_LENS_GLARE_ENABLED 1 # Set to 1 to bypass cabinet checks including drive board and tower in Outrun 2 SP SDX -# Default: 0 -# SKIP_OUTRUN_CABINET_CHECK 0 +SKIP_OUTRUN_CABINET_CHECK 0 + +# Set to 1 if you want to limit the FPS in games that are not limited like OutRun2 +FPS_LIMITER_ENABLED 0 + +# Set the target FPS (will only work if FPS_LIMITER_ENABLED = 1) +FPS_TARGET 60 # Set to 1 if you want to render LGJ using the mesa patches instead of nVidia (fixes some glitches) -# Default: 1 -# LGJ_RENDER_WITH_MESA 1 +LGJ_RENDER_WITH_MESA 1 # Set the Primeval Hunt mode # Mode 0: Leaves everything as default @@ -137,16 +100,30 @@ # Mode 2: Side by Side # Mode 3: 3ds mode 1 (Touch screen to the right) # Mode 4: 3ds mode 2 (Touch screen to the bottom) -# Default: 1 -# PRIMEVAL_HUNT_MODE 1 +PRIMEVAL_HUNT_MODE 1 # Hacky way to make MJ4 work at prohibited times? # MJ4_ENABLED_ALL_THE_TIME 1 # Set the colour of the lindbergh to change the Segaboot logo # Possible colours are: YELLOW, RED, BLUE, SILVER, REDEX -# Default: YELLOW -# LINDBERGH_COLOUR YELLOW +LINDBERGH_COLOUR YELLOW + +# X11 MODE (Input Mode 1) +# To find the value pairs for these run `xev` on linux + +TEST_KEY 28 # t +PLAYER_1_START_KEY 10 # 1 +PLAYER_1_SERVICE_KEY 39 # s +PLAYER_1_COIN_KEY 14 # 5 +PLAYER_1_UP_KEY 111 # Up +PLAYER_1_DOWN_KEY 116 # Down +PLAYER_1_LEFT_KEY 113 # Left +PLAYER_1_RIGHT_KEY 114 # Right +PLAYER_1_BUTTON_1_KEY 24 # q +PLAYER_1_BUTTON_2_KEY 25 # w +PLAYER_1_BUTTON_3_KEY 26 # e +PLAYER_1_BUTTON_4_KEY 27 # r # EVDEV MODE (Input Mode 2) # To find the value pairs for these run ./lindbergh --list-controllers diff --git a/src/lindbergh/border.c b/src/lindbergh/border.c new file mode 100644 index 0000000..6c13274 --- /dev/null +++ b/src/lindbergh/border.c @@ -0,0 +1,57 @@ +#include + +#include "border.h" + +void drawBorderWithOffset(int width, int height, float borderPercentage, float offsetPercentage, GLfloat *color) +{ + // Border thickness based on the percentage of the width/height + int borderWidth = (int)(width * borderPercentage); // Border width as a percentage of the screen width + int borderHeight = borderWidth; + + // Offset based on the percentage of the width/height + int offsetX = (int)(width * offsetPercentage); // Horizontal offset from the screen edge + int offsetY = offsetX; + + // Set the clear color based on the color parameter + glClearColor(color[0], color[1], color[2], color[3]); + + // Left side (borderWidth wide from top to bottom, starting from the left edge with offset) + glScissor(offsetX, offsetY, borderWidth, + height - 2 * offsetY); // X = offsetX, Y = offsetY, Width = borderWidth, Height = (height - 2 * offsetY) + glClear(GL_COLOR_BUFFER_BIT); + + // Right side (borderWidth wide from top to bottom, starting from the right edge with offset) + glScissor(width - borderWidth - offsetX, offsetY, borderWidth, + height - + 2 * offsetY); // X = (width - borderWidth - offsetX), Y = offsetY, Width = borderWidth, Height = (height - 2 * offsetY) + glClear(GL_COLOR_BUFFER_BIT); + + // Top side (borderHeight wide from left to right, starting from the top edge with offset) + glScissor(offsetX, offsetY, width - 2 * offsetX, + borderHeight); // X = offsetX, Y = offsetY, Width = (width - 2 * offsetX), Height = borderHeight + glClear(GL_COLOR_BUFFER_BIT); + + // Bottom side (borderHeight wide from left to right, starting from the bottom edge with offset) + glScissor(offsetX, height - borderHeight - offsetY, width - 2 * offsetX, + borderHeight); // X = offsetX, Y = (height - borderHeight - offsetY), Width = (width - 2 * offsetX), Height = borderHeight + glClear(GL_COLOR_BUFFER_BIT); +} + +void drawGameBorder(int width, int height, float whiteBorderPercentage, float blackBorderPercentage) +{ + // Store the old clear colour + GLfloat originalClearColour[4]; + glGetFloatv(GL_COLOR_CLEAR_VALUE, originalClearColour); + + GLfloat blackColour[4] = {0.0, 0.0, 0.0, 0.0}; + GLfloat whiteColour[4] = {1.0, 1.0, 1.0, 0.0}; + + glEnable(GL_SCISSOR_TEST); + + drawBorderWithOffset(width, height, whiteBorderPercentage, blackBorderPercentage, whiteColour); + drawBorderWithOffset(width, height, blackBorderPercentage, 0, blackColour); + + glDisable(GL_SCISSOR_TEST); + + glClearColor(originalClearColour[0], originalClearColour[1], originalClearColour[2], originalClearColour[3]); +} \ No newline at end of file diff --git a/src/lindbergh/border.h b/src/lindbergh/border.h new file mode 100644 index 0000000..e4de1b5 --- /dev/null +++ b/src/lindbergh/border.h @@ -0,0 +1,6 @@ +#ifndef BORDER_H +#define BORDER_H + +void drawGameBorder(int width, int height, float whiteBorderPercentage, float blackBorderPercentage); + +#endif // BORDER_H \ No newline at end of file diff --git a/src/lindbergh/config.c b/src/lindbergh/config.c index e80f25d..c3f071f 100644 --- a/src/lindbergh/config.c +++ b/src/lindbergh/config.c @@ -367,6 +367,8 @@ static int detectGame(uint32_t elf_crc) config.gameNativeResolutions = ""; config.gameType = SHOOTING; config.gameStatus = WORKING; + config.width = 1360; + config.height = 768; return 0; } break; @@ -381,6 +383,8 @@ static int detectGame(uint32_t elf_crc) config.gameNativeResolutions = ""; config.gameType = SHOOTING; config.gameStatus = WORKING; + config.width = 1024; + config.height = 768; return 0; } break; @@ -843,6 +847,8 @@ static int detectGame(uint32_t elf_crc) config.gameNativeResolutions = ""; config.gameType = SHOOTING; config.gameStatus = WORKING; + config.width = 1360; + config.height = 768; return 0; } break; @@ -939,6 +945,24 @@ const char *getGpuTypeString(GpuType gpuType) return GpuTypeStrings[gpuType]; } +void toLowerCase(char *str) { + while (*str) { // Iterate through the string until the null terminator + *str = tolower((unsigned char)*str); // Convert each character to lowercase + str++; // Move to the next character + } +} + +int getNextIntOrAuto(char *saveptr, int defaultValue) { + char nextToken[256]; + strcpy(nextToken, getNextToken(NULL, " ", &saveptr)); + toLowerCase(nextToken); + + if(strcmp(nextToken, "auto") == 0) + return defaultValue; + + return atoi(nextToken); +} + int readConfig(FILE *configFile, EmulatorConfig *config) { char buffer[MAX_LINE_LENGTH]; @@ -953,11 +977,15 @@ int readConfig(FILE *configFile, EmulatorConfig *config) char *command = getNextToken(buffer, " ", &saveptr); - if (strcmp(command, "WIDTH") == 0) - config->width = atoi(getNextToken(NULL, " ", &saveptr)); + if (strcmp(command, "WIDTH") == 0) { + int defaultValue = config->width; + config->width = getNextIntOrAuto(saveptr, defaultValue); + } - else if (strcmp(command, "HEIGHT") == 0) - config->height = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "HEIGHT") == 0) { + int defaultValue = config->height; + config->height = getNextIntOrAuto(saveptr, defaultValue); + } else if (strcmp(command, "EEPROM_PATH") == 0) strcpy(config->eepromPath, getNextToken(NULL, " ", &saveptr)); @@ -965,14 +993,20 @@ int readConfig(FILE *configFile, EmulatorConfig *config) else if (strcmp(command, "SRAM_PATH") == 0) strcpy(config->sramPath, getNextToken(NULL, " ", &saveptr)); - else if (strcmp(command, "EMULATE_RIDEBOARD") == 0) - config->emulateRideboard = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "EMULATE_RIDEBOARD") == 0) { + int defaultValue = config->emulateRideboard; + config->emulateRideboard = getNextIntOrAuto(saveptr, defaultValue); + } - else if (strcmp(command, "EMULATE_DRIVEBOARD") == 0) - config->emulateDriveboard = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "EMULATE_DRIVEBOARD") == 0) { + int defaultValue = config->emulateDriveboard; + config->emulateDriveboard = getNextIntOrAuto(saveptr, defaultValue); + } - else if (strcmp(command, "EMULATE_MOTIONBOARD") == 0) - config->emulateMotionboard = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "EMULATE_MOTIONBOARD") == 0) { + int defaultValue = config->emulateMotionboard; + config->emulateMotionboard = getNextIntOrAuto(saveptr, defaultValue); + } else if (strcmp(command, "FULLSCREEN") == 0) config->fullscreen = atoi(getNextToken(NULL, " ", &saveptr)); @@ -1254,6 +1288,15 @@ int readConfig(FILE *configFile, EmulatorConfig *config) else if (strcmp(command, "SKIP_OUTRUN_CABINET_CHECK") == 0) config->skipOutrunCabinetCheck = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "BORDER_ENABLED") == 0) + config->borderEnabled = atoi(getNextToken(NULL, " ", &saveptr)); + + else if (strcmp(command, "WHITE_BORDER_PERCENTAGE") == 0) + config->whiteBorderPercentage = (float) atoi(getNextToken(NULL, " ", &saveptr)) / 100.0; + + else if (strcmp(command, "BLACK_BORDER_PERCENTAGE") == 0) + config->blackBorderPercentage = (float) atoi(getNextToken(NULL, " ", &saveptr)) / 100.0; + else if (strcmp(command, "INPUT_MODE") == 0) config->inputMode = atoi(getNextToken(NULL, " ", &saveptr)); @@ -1313,7 +1356,7 @@ int initConfig() strcpy(config.serial2Path, "/dev/ttyS1"); config.width = 640; config.height = 480; - config.region = 0; + config.region = EX; config.freeplay = -1; config.showDebugMessages = 0; config.hummerFlickerFix = 0; @@ -1340,6 +1383,9 @@ int initConfig() memset(&config.arcadeInputs.analogue_deadzone_end, 0, sizeof(config.arcadeInputs.analogue_deadzone_end)); config.crc32 = elf_crc; config.skipOutrunCabinetCheck = 0; + config.borderEnabled = 0; + config.whiteBorderPercentage = 0.02; + config.blackBorderPercentage = 0.0; if (detectGame(config.crc32) != 0) { log_warn("Unsure what game with CRC 0x%X is. Please submit this new game to the GitHub repository: " diff --git a/src/lindbergh/config.h b/src/lindbergh/config.h index 8c42a2a..e1e9824 100644 --- a/src/lindbergh/config.h +++ b/src/lindbergh/config.h @@ -103,9 +103,9 @@ typedef enum typedef enum { - JP, - US, - EX + JP = 0, + US = 1, + EX = 2 } GameRegion; typedef enum @@ -261,6 +261,9 @@ typedef struct ArcadeInputs arcadeInputs; int inputMode; // 0 = both, 1 = SDL/X11 only, 2 = EVDEV only int skipOutrunCabinetCheck; + float whiteBorderPercentage; + float blackBorderPercentage; + int borderEnabled; } EmulatorConfig; KeyMapping getDefaultKeymap(); diff --git a/src/lindbergh/gluthooks.c b/src/lindbergh/gluthooks.c index 67a710c..aba6bc3 100644 --- a/src/lindbergh/gluthooks.c +++ b/src/lindbergh/gluthooks.c @@ -21,6 +21,7 @@ #include "config.h" #include "fps_limiter.h" #include "sdlcalls.h" +#include "border.h" extern SDL_Window *SDLwindow; extern char SDLgameTitle[]; @@ -88,14 +89,19 @@ void FGAPIENTRY glutMainLoopEvent(void) void FGAPIENTRY glutSwapBuffers(void) { - if (getConfig()->noSDL) + EmulatorConfig *config = getConfig(); + + if (config->borderEnabled) + drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage); + + if (config->noSDL) { void FGAPIENTRY (*_glutSwapBuffers)(void) = dlsym(RTLD_NEXT, "glutSwapBuffers"); _glutSwapBuffers(); return; } - int gId = getConfig()->crc32; + int gId = config->crc32; if (gId == OUTRUN_2_SP_SDX || gId == OUTRUN_2_SP_SDX_REVA || gId == OUTRUN_2_SP_SDX_REVA_TEST || gId == OUTRUN_2_SP_SDX_REVA_TEST2 || gId == OUTRUN_2_SP_SDX_TEST) { @@ -104,7 +110,7 @@ void FGAPIENTRY glutSwapBuffers(void) SDL_GL_SwapWindow(SDLwindow); - if (getConfig()->fpsLimiter) + if (config->fpsLimiter) { fpsLimit.frameStart = Clock_now(); FpsLimiter(&fpsLimit); @@ -290,8 +296,7 @@ void FGAPIENTRY glutKeyboardFunc(void (*callback)(unsigned char, int, int)) { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutKeyboardFunc)(void (*callback)(unsigned char, int, int)) = - dlsym(RTLD_NEXT, "glutKeyboardFunc"); + void FGAPIENTRY (*_glutKeyboardFunc)(void (*callback)(unsigned char, int, int)) = dlsym(RTLD_NEXT, "glutKeyboardFunc"); _glutKeyboardFunc(callback); return; } @@ -302,8 +307,7 @@ void FGAPIENTRY glutKeyboardUpFunc(void (*callback)(unsigned char, int, int)) { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutKeyboardUpFunc)(void (*callback)(unsigned char, int, int)) = - dlsym(RTLD_NEXT, "glutKeyboardUpFunc"); + void FGAPIENTRY (*_glutKeyboardUpFunc)(void (*callback)(unsigned char, int, int)) = dlsym(RTLD_NEXT, "glutKeyboardUpFunc"); _glutKeyboardUpFunc(callback); return; } @@ -358,8 +362,7 @@ void FGAPIENTRY glutPassiveMotionFunc(void (*callback)(int, int)) { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutPassiveMotionFunc)(void (*callback)(int, int)) = - dlsym(RTLD_NEXT, "glutPassiveMotionFunc"); + void FGAPIENTRY (*_glutPassiveMotionFunc)(void (*callback)(int, int)) = dlsym(RTLD_NEXT, "glutPassiveMotionFunc"); _glutPassiveMotionFunc(callback); return; } @@ -414,8 +417,7 @@ void FGAPIENTRY glutSolidSphere(double radius, GLint slices, GLint stacks) { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutSolidSphere)(double radius, GLint slices, GLint stacks) = - dlsym(RTLD_NEXT, "glutSolidSphere"); + void FGAPIENTRY (*_glutSolidSphere)(double radius, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutSolidSphere"); _glutSolidSphere(radius, slices, stacks); return; } @@ -426,8 +428,7 @@ void FGAPIENTRY glutWireSphere(double radius, GLint slices, GLint stacks) { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutWireSphere)(double radius, GLint slices, GLint stacks) = - dlsym(RTLD_NEXT, "glutWireSphere"); + void FGAPIENTRY (*_glutWireSphere)(double radius, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutWireSphere"); _glutWireSphere(radius, slices, stacks); return; } @@ -438,8 +439,7 @@ void FGAPIENTRY glutWireCone(double base, double height, GLint slices, GLint sta { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutWireCone)(double base, double height, GLint slices, GLint stacks) = - dlsym(RTLD_NEXT, "glutWireCone"); + void FGAPIENTRY (*_glutWireCone)(double base, double height, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutWireCone"); _glutWireCone(base, height, slices, stacks); return; } @@ -450,8 +450,7 @@ void FGAPIENTRY glutSolidCone(double base, double height, GLint slices, GLint st { if (getConfig()->noSDL) { - void FGAPIENTRY (*_glutSolidCone)(double base, double height, GLint slices, GLint stacks) = - dlsym(RTLD_NEXT, "glutSolidCone"); + void FGAPIENTRY (*_glutSolidCone)(double base, double height, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutSolidCone"); _glutSolidCone(base, height, slices, stacks); return; } diff --git a/src/lindbergh/glxhooks.c b/src/lindbergh/glxhooks.c index 77c78ad..3ad3783 100644 --- a/src/lindbergh/glxhooks.c +++ b/src/lindbergh/glxhooks.c @@ -24,6 +24,7 @@ #include "sdlcalls.h" #include "patch.h" #include "config.h" +#include "border.h" bool sdlGame = false; extern SDL_Window *SDLwindow; @@ -35,6 +36,11 @@ extern Window win; void glXToSDLSwapBuffers(Display *dpy, GLXDrawable drawable) { pollEvents(); + + EmulatorConfig *config = getConfig(); + if (config->borderEnabled) + drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage); + SDL_GL_SwapWindow(SDLwindow); if (getConfig()->fpsLimiter) { @@ -65,8 +71,8 @@ XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList) return _glXChooseVisual(dpy, screen, attribList); } -void GLAPIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, - const GLchar *message, const void *userParam) +void GLAPIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, + const void *userParam) { if (id == 1099) return; @@ -89,9 +95,14 @@ void glXSwapBuffers(Display *dpy, GLXDrawable drawable) { void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable) = dlsym(RTLD_NEXT, "glXSwapBuffers"); - int gId = getConfig()->crc32; - if (getConfig()->noSDL && (gId == OUTRUN_2_SP_SDX || gId == OUTRUN_2_SP_SDX_REVA || - gId == OUTRUN_2_SP_SDX_REVA_TEST || gId == OUTRUN_2_SP_SDX_REVA_TEST2 || gId == OUTRUN_2_SP_SDX_TEST)) + EmulatorConfig *config = getConfig(); + + if (config->borderEnabled) + drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage); + + int gId = config->crc32; + if (getConfig()->noSDL && (gId == OUTRUN_2_SP_SDX || gId == OUTRUN_2_SP_SDX_REVA || gId == OUTRUN_2_SP_SDX_REVA_TEST || + gId == OUTRUN_2_SP_SDX_REVA_TEST2 || gId == OUTRUN_2_SP_SDX_TEST)) { XEvent event; while (XPending(dpy)) @@ -100,7 +111,7 @@ void glXSwapBuffers(Display *dpy, GLXDrawable drawable) } } _glXSwapBuffers(dpy, drawable); - if (getConfig()->fpsLimiter) + if (config->fpsLimiter) { fpsLimit.frameStart = Clock_now(); FpsLimiter(&fpsLimit); @@ -139,8 +150,7 @@ GLXContext glXGetCurrentContext() GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list) { - GLXPbuffer (*_glXCreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attrib_list) = - dlsym(RTLD_NEXT, "glXCreatePbuffer"); + GLXPbuffer (*_glXCreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attrib_list) = dlsym(RTLD_NEXT, "glXCreatePbuffer"); if (sdlGame) return 0; return _glXCreatePbuffer(dpy, config, attrib_list); @@ -164,8 +174,7 @@ void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf) XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) { - XVisualInfo *(*_glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) = - dlsym(RTLD_NEXT, "glXGetVisualFromFBConfig"); + XVisualInfo *(*_glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) = dlsym(RTLD_NEXT, "glXGetVisualFromFBConfig"); if (sdlGame) return 0; return _glXGetVisualFromFBConfig(dpy, config); @@ -203,9 +212,9 @@ GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, if (__NV_PRIME_RENDER_OFFLOAD == NULL) __NV_PRIME_RENDER_OFFLOAD = " "; if ((strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0) && (strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0) && - ((gId == THE_HOUSE_OF_THE_DEAD_4_REVA) || (gId == THE_HOUSE_OF_THE_DEAD_4_REVB) || - (gId == THE_HOUSE_OF_THE_DEAD_4_REVC) || (gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL) || - (gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB) || (gId == THE_HOUSE_OF_THE_DEAD_EX) || (gId == TOO_SPICY))) + ((gId == THE_HOUSE_OF_THE_DEAD_4_REVA) || (gId == THE_HOUSE_OF_THE_DEAD_4_REVB) || (gId == THE_HOUSE_OF_THE_DEAD_4_REVC) || + (gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL) || (gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB) || (gId == THE_HOUSE_OF_THE_DEAD_EX) || + (gId == TOO_SPICY))) { for (int i = 0; attrib_list[i] != None; i += 2) { @@ -222,8 +231,8 @@ GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) { - GLXContext (*_glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, - Bool direct) = dlsym(RTLD_NEXT, "glXCreateNewContext"); + GLXContext (*_glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) = + dlsym(RTLD_NEXT, "glXCreateNewContext"); GLXContext ctx = _glXCreateNewContext(dpy, config, render_type, share_list, direct); @@ -237,20 +246,12 @@ GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type return ctx; } -GLXPbuffer glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, - int *attrib_list) +GLXPbuffer glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) { if (sdlGame) return 0; - int pbufferAttribs[] = {GLX_PBUFFER_WIDTH, - width, - GLX_PBUFFER_HEIGHT, - height, - GLX_PRESERVED_CONTENTS, - true, - GLX_LARGEST_PBUFFER, - true, - None}; + int pbufferAttribs[] = { + GLX_PBUFFER_WIDTH, width, GLX_PBUFFER_HEIGHT, height, GLX_PRESERVED_CONTENTS, true, GLX_LARGEST_PBUFFER, true, None}; return glXCreatePbuffer(dpy, config, pbufferAttribs); } @@ -274,8 +275,7 @@ GLXFBConfigSGIX *glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_lis __NV_PRIME_RENDER_OFFLOAD = " "; if ((strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0) && (strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0) && ((gId == INITIALD_4_REVA) || (gId == INITIALD_4_REVB) || (gId == INITIALD_4_REVC) || (gId == INITIALD_4_REVD) || - (gId == INITIALD_4_REVG) || (gId == INITIALD_4_EXP_REVB) || (gId == INITIALD_4_EXP_REVC) || - gId == INITIALD_4_EXP_REVD)) + (gId == INITIALD_4_REVG) || (gId == INITIALD_4_EXP_REVB) || (gId == INITIALD_4_EXP_REVC) || gId == INITIALD_4_EXP_REVD)) { for (int i = 0; attrib_list[i] != None; i += 2) { @@ -296,8 +296,7 @@ int glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute return glXGetFBConfigAttrib(dpy, config, attribute, value); } -GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, - Bool direct) +GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) { if (sdlGame) return 0;