mirror of
https://github.com/libretro/FBNeo.git
synced 2024-11-23 08:59:39 +00:00
Add switchres to linux/sdl2
This allows perfect display on CRT The work is based on https://github.com/antonioginer/switchres which is the switchres code extracted from GroovyMAME and made available to other emulators that wish to add CRT display. This first commit simply concerns linux using the SDL2 video backend. Add INCLUDE_SWITCHRES=1 to enable switchres functionnality at make. To test under Linux you need: * a valid switchres.ini in /etc * libswitchres.so in your LD_LIBRARY_PATH
This commit is contained in:
parent
f2973312dc
commit
a19bac6bc0
2
makefile
2
makefile
@ -68,6 +68,8 @@ LSB_FIRST = 1
|
||||
# Include png.h from burner.h
|
||||
INCLUDE_LIB_PNGH = 1
|
||||
|
||||
# Enable CRT resolution switching
|
||||
# INCLUDE_SWITCHRES = 1
|
||||
|
||||
#
|
||||
# execute an appropriate system-specific makefile
|
||||
|
@ -86,6 +86,12 @@ depobj += un7z.o \
|
||||
Delta.o LzmaDec.o Lzma2Dec.o Ppmd7.o Ppmd7Dec.o Sha256.o Xz.o XzCrc64.o XzCrc64Opt.o XzDec.o
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_SWITCHRES
|
||||
$(info Switchres will be enabled)
|
||||
alldir += dep/libs/switchres intf/video/switchres
|
||||
depobj += vid_switchres.o
|
||||
endif
|
||||
|
||||
autobj += $(depobj)
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
@ -112,6 +118,10 @@ ifdef DARWIN
|
||||
lib += -L/System/Library/Frameworks/OpenGL.framework/Libraries/
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_SWITCHRES
|
||||
lib += -ldl
|
||||
endif
|
||||
|
||||
autdep = $(depobj:.o=.d)
|
||||
drvdep = $(drvsrc:.o=.d)
|
||||
|
||||
@ -256,6 +266,10 @@ ifdef BUILD_X64_EXE
|
||||
DEF := $(DEF) -DBUILD_X64_EXE -DXBYAK_NO_OP_NAMES -DMIPS3_X64_DRC
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_SWITCHRES
|
||||
DEF := $(DEF) -DINCLUDE_SWITCHRES
|
||||
endif
|
||||
|
||||
ifdef SYMBOL
|
||||
|
||||
CFLAGS += -ggdb3 -fno-omit-frame-pointer
|
||||
|
94
src/dep/libs/switchres/switchres_wrapper.h
Normal file
94
src/dep/libs/switchres/switchres_wrapper.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**************************************************************
|
||||
|
||||
log.h - Simple logging for Switchres
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
Switchres Modeline generation engine for emulation
|
||||
|
||||
License GPL-2.0+
|
||||
Copyright 2010-2020 Chris Kennedy, Antonio Giner,
|
||||
Alexandre Wodarczyk, Gil Delescluse
|
||||
|
||||
**************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <dlfcn.h>
|
||||
#define LIBTYPE void*
|
||||
#define OPENLIB(libname) dlopen((libname), RTLD_LAZY)
|
||||
#define LIBFUNC(libh, fn) dlsym((libh), (fn))
|
||||
#define LIBERROR dlerror
|
||||
#define CLOSELIB(libh) dlclose((libh))
|
||||
|
||||
#elif defined _WIN32
|
||||
#include <windows.h>
|
||||
//#include <string>
|
||||
#define LIBTYPE HINSTANCE
|
||||
#define OPENLIB(libname) LoadLibrary(TEXT((libname)))
|
||||
#define LIBFUNC(lib, fn) GetProcAddress((lib), (fn))
|
||||
char* LIBERROR()
|
||||
{
|
||||
//Get the error message, if any.
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if(errorMessageID == 0)
|
||||
return NULL; //No error message has been recorded
|
||||
|
||||
LPSTR messageBuffer;
|
||||
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
static char error_msg[256] = {0};
|
||||
strncpy(error_msg, messageBuffer, sizeof(error_msg)-1);
|
||||
LocalFree(messageBuffer);
|
||||
return error_msg;
|
||||
}
|
||||
#define CLOSELIB(libp) FreeLibrary((libp))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef MODULE_API_EXPORTS
|
||||
#define MODULE_API __declspec(dllexport)
|
||||
#else
|
||||
#define MODULE_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define MODULE_API
|
||||
#endif
|
||||
|
||||
// That's all the exposed data from Switchres calculation
|
||||
typedef struct MODULE_API {
|
||||
int width;
|
||||
int height;
|
||||
double refresh;
|
||||
unsigned char is_refresh_off;
|
||||
unsigned char is_stretched;
|
||||
int x_scale;
|
||||
int y_scale;
|
||||
unsigned char interlace;
|
||||
} sr_mode;
|
||||
|
||||
MODULE_API void sr_init();
|
||||
MODULE_API void sr_deinit();
|
||||
MODULE_API unsigned char sr_add_mode(int, int, double, unsigned char, sr_mode*);
|
||||
MODULE_API unsigned char sr_switch_to_mode(int, int, double, unsigned char, sr_mode*);
|
||||
MODULE_API void sr_set_monitor(const char*);
|
||||
|
||||
|
||||
// Inspired by https://stackoverflow.com/a/1067684
|
||||
typedef struct MODULE_API {
|
||||
void (*init)(void);
|
||||
void (*deinit)(void);
|
||||
unsigned char (*sr_add_mode)(int, int, double, unsigned char, sr_mode*);
|
||||
unsigned char (*sr_switch_to_mode)(int, int, double, unsigned char, sr_mode*);
|
||||
} srAPI;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -3,6 +3,10 @@
|
||||
#include "vid_support.h"
|
||||
#include "vid_softfx.h"
|
||||
|
||||
#ifdef INCLUDE_SWITCHRES
|
||||
#include "vid_switchres.h"
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
|
||||
@ -42,6 +46,7 @@ void RenderMessage()
|
||||
|
||||
static int Exit()
|
||||
{
|
||||
switchres_exit();
|
||||
kill_inline_font(); //TODO: This is not supposed to be here
|
||||
SDL_DestroyTexture(sdlTexture);
|
||||
SDL_DestroyRenderer(sdlRenderer);
|
||||
@ -74,16 +79,21 @@ static int Init()
|
||||
BurnDrvGetAspect(&GameAspectX, &GameAspectY);
|
||||
|
||||
display_w = nVidImageWidth;
|
||||
#ifdef INCLUDE_SWITCHRES
|
||||
// Don't force 4:3 aspect-ratio, until there is a command-line switch
|
||||
display_h = nVidImageHeight;
|
||||
#else
|
||||
display_h = nVidImageWidth * GameAspectY / GameAspectX;
|
||||
#endif
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
|
||||
{
|
||||
BurnDrvGetVisibleSize(&nVidImageHeight, &nVidImageWidth);
|
||||
BurnDrvGetAspect(&GameAspectY, &GameAspectX);
|
||||
//BurnDrvGetAspect(&GameAspectX, &GameAspectY);
|
||||
printf("Vertical\n");
|
||||
nRotateGame = 1;
|
||||
display_w = nVidImageHeight * GameAspectX / GameAspectY;
|
||||
display_w = nVidImageWidth;
|
||||
display_h = nVidImageHeight;
|
||||
}
|
||||
|
||||
@ -110,6 +120,16 @@ static int Init()
|
||||
dstrect.h = display_h;
|
||||
dstrect.w = display_w;
|
||||
|
||||
//Test refresh rate availability
|
||||
printf("Game resolution: %dx%d@%f\n", nVidImageWidth, nVidImageHeight, nBurnFPS/100.0);
|
||||
|
||||
#ifdef INCLUDE_SWITCHRES
|
||||
unsigned char interlace = 0; // FBN doesn't handle interlace yet, force it to disabled
|
||||
double rr = nBurnFPS / 100.0;
|
||||
switchres_init();
|
||||
switchres_switch_resolution(display_w, display_h, rr, interlace);
|
||||
#endif
|
||||
|
||||
if (nRotateGame)
|
||||
{
|
||||
sdlWindow = SDL_CreateWindow(
|
||||
@ -132,14 +152,15 @@ static int Init()
|
||||
title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
display_w,
|
||||
display_h,
|
||||
display_w,
|
||||
screenFlags
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Check that the window was successfully created
|
||||
if (sdlWindow == NULL)
|
||||
{
|
||||
|
77
src/intf/video/switchres/vid_switchres.cpp
Normal file
77
src/intf/video/switchres/vid_switchres.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "switchres_wrapper.h"
|
||||
#include "burner.h"
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#define LIBSWR "libswitchres.so"
|
||||
#elif _WIN32
|
||||
#define LIBSWR "libswitchres.dll"
|
||||
#endif
|
||||
|
||||
srAPI* SRobj;
|
||||
|
||||
unsigned char switchres_init() {
|
||||
const char* err_msg;
|
||||
|
||||
printf("About to open %s.\n", LIBSWR);
|
||||
|
||||
// Load the lib
|
||||
LIBTYPE dlp = OPENLIB(LIBSWR);
|
||||
|
||||
// Loading failed, inform and exit
|
||||
if (!dlp) {
|
||||
printf("Loading %s failed.\n", LIBSWR);
|
||||
printf("Error: %s\n", LIBERROR());
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Loading %s succeded.\n", LIBSWR);
|
||||
|
||||
// Load the init()
|
||||
LIBERROR();
|
||||
SRobj = (srAPI*)LIBFUNC(dlp, "srlib");
|
||||
if ((err_msg = LIBERROR()) != NULL) {
|
||||
printf("Failed to load srAPI: %s\n", err_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Testing the function
|
||||
printf("Init a new switchres_manager object:\n");
|
||||
SRobj->init();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char switchres_switch_resolution(int& w, int& h, double& rr, unsigned char& interlace) {
|
||||
// Call mode + get result values
|
||||
unsigned char ret;
|
||||
sr_mode srm;
|
||||
|
||||
printf("Orignial resolution expected: %dx%d@%f-%d\n", w, h, rr, interlace);
|
||||
ret = SRobj->sr_add_mode(w, h, rr, interlace, &srm);
|
||||
if(!ret)
|
||||
{
|
||||
printf("ERROR: couldn't add the required mode. Exiting!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Got resolution: %dx%d%c@%f\n", srm.width, srm.height, srm.interlace, srm.refresh);
|
||||
ret = SRobj->sr_switch_to_mode(srm.width, srm.height, srm.refresh, srm.interlace, &srm);
|
||||
if(!ret)
|
||||
{
|
||||
printf("ERROR: couldn't switch to the required mode. Exiting!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set the values
|
||||
w = srm.width;
|
||||
h = srm.height;
|
||||
rr = srm.refresh;
|
||||
interlace = srm.interlace;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void switchres_exit() {
|
||||
SRobj->deinit();
|
||||
}
|
||||
|
5
src/intf/video/switchres/vid_switchres.h
Normal file
5
src/intf/video/switchres/vid_switchres.h
Normal file
@ -0,0 +1,5 @@
|
||||
unsigned char switchres_init();
|
||||
|
||||
unsigned char switchres_switch_resolution(int& w, int& h, double& rr, unsigned char& interlace);
|
||||
|
||||
void switchres_exit();
|
Loading…
Reference in New Issue
Block a user