Added basic SDL2 GameController API support. SDL2 rendering added. For some reason windowed mode totally sucks, at least on my Ubuntu 12.04 machine. But fullscreen runs just fine. Updated main SConstruct to allow overriding LIBRARY_PATH and INCLUDE_PATH for non-standard SDL2 installation paths
This commit is contained in:
parent
108cf8494c
commit
bb27c041ea
|
@ -66,7 +66,10 @@ if os.environ.has_key('PKG_CONFIG_PATH'):
|
|||
env['ENV']['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH']
|
||||
if os.environ.has_key('PKG_CONFIG_LIBDIR'):
|
||||
env['ENV']['PKG_CONFIG_LIBDIR'] = os.environ['PKG_CONFIG_LIBDIR']
|
||||
|
||||
if os.environ.has_key('LIBRARY_PATH'):
|
||||
env['ENV']['LIBRARY_PATH'] = os.environ['LIBRARY_PATH']
|
||||
if os.environ.has_key('INCLUDE_PATH'):
|
||||
env['ENV']['INCLUDE_PATH'] = os.environ['INCLUDE_PATH']
|
||||
|
||||
print "platform: ", env['PLATFORM']
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ source_list = Split(
|
|||
config.cpp
|
||||
sdl.cpp
|
||||
sdl-joystick.cpp
|
||||
sdl-gamectrl.cpp
|
||||
sdl-sound.cpp
|
||||
sdl-throttle.cpp
|
||||
sdl-video.cpp
|
||||
|
|
|
@ -62,7 +62,7 @@ LoadCPalette(const std::string &file)
|
|||
static void
|
||||
CreateDirs(const std::string &dir)
|
||||
{
|
||||
char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
|
||||
char *subs[8]= {"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"};
|
||||
std::string subdir;
|
||||
int x;
|
||||
|
||||
|
@ -225,15 +225,15 @@ InitConfig()
|
|||
|
||||
config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1);
|
||||
|
||||
#ifdef _S9XLUA_H
|
||||
#ifdef _S9XLUA_H
|
||||
// load lua script
|
||||
config->addOption("loadlua", "SDL.LuaScript", "");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
#ifdef CREATE_AVI
|
||||
config->addOption("videolog", "SDL.VideoLog", "");
|
||||
config->addOption("mute", "SDL.MuteCapture", 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// auto load/save on gameload/close
|
||||
config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE);
|
||||
|
@ -243,7 +243,7 @@ InitConfig()
|
|||
config->addOption("periodicsaves", "SDL.PeriodicSaves", 0);
|
||||
|
||||
|
||||
#ifdef _GTK
|
||||
#ifdef _GTK
|
||||
char* home_dir = getenv("HOME");
|
||||
// prefixed with _ because they are internal (not cli options)
|
||||
config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir);
|
||||
|
@ -251,7 +251,7 @@ InitConfig()
|
|||
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
|
||||
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
|
||||
config->addOption("_lastloadlua", "SDL.LastLoadLua", home_dir);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// fcm -> fm2 conversion
|
||||
config->addOption("fcmconvert", "SDL.FCMConvert", "");
|
||||
|
@ -377,7 +377,8 @@ InitConfig()
|
|||
SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
|
||||
SDLK_6, SDLK_7, SDLK_8, SDLK_9,
|
||||
SDLK_PAGEUP, // select state next
|
||||
SDLK_PAGEDOWN}; // select state prev
|
||||
SDLK_PAGEDOWN
|
||||
}; // select state prev
|
||||
|
||||
prefix = "SDL.Hotkeys.";
|
||||
for(int i=0; i < HK_MAX; i++)
|
||||
|
|
|
@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */
|
|||
|
||||
int InitJoysticks(void);
|
||||
int KillJoysticks(void);
|
||||
int InitGameControllers(void);
|
||||
int KillGameControllers(void);
|
||||
uint32 *GetJSOr(void);
|
||||
|
||||
int InitVideo(FCEUGI *gi);
|
||||
|
|
|
@ -320,11 +320,11 @@ std::string GetFilename (const char *title, bool save, const char *filter)
|
|||
std::string GetUserText (const char *title)
|
||||
{
|
||||
#ifdef _GTK
|
||||
/* prg318 - 10/13/11 - this is broken in recent build and causes
|
||||
/* prg318 - 10/13/11 - this is broken in recent build and causes
|
||||
* segfaults/very weird behavior i'd rather remove it for now than it cause
|
||||
* accidental segfaults
|
||||
* TODO fix it
|
||||
*/
|
||||
*/
|
||||
#if 0
|
||||
|
||||
GtkWidget* d;
|
||||
|
@ -801,7 +801,7 @@ static void KeyboardCommands ()
|
|||
goto DIPSless;
|
||||
|
||||
// toggle the various dipswitches
|
||||
for(int i=1; i<=8;i++)
|
||||
for(int i=1; i<=8; i++)
|
||||
{
|
||||
if(keyonly(i))
|
||||
FCEUI_VSUniToggleDIP(i-1);
|
||||
|
@ -864,8 +864,8 @@ do { \
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
DIPSless:
|
||||
for(int i=0; i<10;i++)
|
||||
DIPSless:
|
||||
for(int i=0; i<10; i++)
|
||||
{
|
||||
if (keyonly (i))
|
||||
SSM (i);
|
||||
|
@ -1089,6 +1089,15 @@ DTestButton (ButtConfig * bc)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
else if( bc->ButtType[x] == BUTTC_GAMECONTROLLER )
|
||||
{
|
||||
if( DTestButtonGC(bc) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1099,15 +1108,32 @@ DTestButton (ButtConfig * bc)
|
|||
#define MKZ() {{0},{0},{0},0}
|
||||
#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
|
||||
|
||||
#define MGC(x) {{BUTTC_GAMECONTROLLER}, {0}, {x},1}
|
||||
#define MGZ() {{0},{0},{0},SDL_CONTROLLER_BUTTON_INVALID}
|
||||
|
||||
ButtConfig GamePadConfig[4][10] = {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/* Gamepad 1 */
|
||||
{MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER),
|
||||
MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()},
|
||||
/* Gamepad 1 */
|
||||
{
|
||||
// 'B' button -- using 'x' as 'B' works out well for XBox controller for
|
||||
// which SDL2 buttons seem to be named. This is 'square' on PS3.
|
||||
MGC (SDL_CONTROLLER_BUTTON_A),
|
||||
// 'A' button 360 'A' button, PS3 'X' button.
|
||||
MGC (SDL_CONTROLLER_BUTTON_X),
|
||||
MGC (SDL_CONTROLLER_BUTTON_BACK), // Select = SDL "BACK" at least for PS3.
|
||||
MGC (SDL_CONTROLLER_BUTTON_START), // START seem to be fairly universal.
|
||||
MGC (SDL_CONTROLLER_BUTTON_DPAD_UP),
|
||||
MGC (SDL_CONTROLLER_BUTTON_DPAD_DOWN),
|
||||
MGC (SDL_CONTROLLER_BUTTON_DPAD_LEFT),
|
||||
MGC (SDL_CONTROLLER_BUTTON_DPAD_RIGHT),
|
||||
MGZ (),
|
||||
MGZ ()
|
||||
},
|
||||
#else
|
||||
/* Gamepad 1 */
|
||||
{MK (KP3), MK (KP2), MK (SLASH), MK (ENTER),
|
||||
MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()},
|
||||
{ MK (KP3), MK (KP2), MK (SLASH), MK (ENTER),
|
||||
MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()
|
||||
},
|
||||
#endif
|
||||
|
||||
/* Gamepad 2 */
|
||||
|
@ -1155,16 +1181,16 @@ UpdateGamepad(void)
|
|||
if(opposite_dirs == 0)
|
||||
{
|
||||
// test for left+right and up+down
|
||||
if(x == 4){
|
||||
if(x == 4) {
|
||||
up = true;
|
||||
}
|
||||
if((x == 5) && (up == true)){
|
||||
if((x == 5) && (up == true)) {
|
||||
continue;
|
||||
}
|
||||
if(x == 6){
|
||||
if(x == 6) {
|
||||
left = true;
|
||||
}
|
||||
if((x == 7) && (left == true)){
|
||||
if((x == 7) && (left == true)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1210,12 +1236,14 @@ static ButtConfig powerpadsc[2][12] = {
|
|||
MK (O), MK (P), MK (BRACKET_LEFT),
|
||||
MK (BRACKET_RIGHT), MK (K), MK (L), MK (SEMICOLON),
|
||||
MK (APOSTROPHE),
|
||||
MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)},
|
||||
MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)
|
||||
},
|
||||
{
|
||||
MK (O), MK (P), MK (BRACKET_LEFT),
|
||||
MK (BRACKET_RIGHT), MK (K), MK (L), MK (SEMICOLON),
|
||||
MK (APOSTROPHE),
|
||||
MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)}
|
||||
MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)
|
||||
}
|
||||
};
|
||||
|
||||
static uint32 powerpadbuf[2] = { 0, 0 };
|
||||
|
@ -1482,7 +1510,7 @@ static ButtConfig HyperShotButtons[4] = {
|
|||
/**
|
||||
* Update the status of the HyperShot input device.
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
UpdateHyperShot ()
|
||||
{
|
||||
int x;
|
||||
|
@ -1506,7 +1534,7 @@ static ButtConfig MahjongButtons[21] = {
|
|||
/**
|
||||
* Update the status of for the Mahjong input device.
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
UpdateMahjong ()
|
||||
{
|
||||
int x;
|
||||
|
@ -1528,7 +1556,7 @@ static ButtConfig QuizKingButtons[6] = {
|
|||
/**
|
||||
* Update the status of the QuizKing input device.
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
UpdateQuizKing ()
|
||||
{
|
||||
int x;
|
||||
|
@ -1551,7 +1579,7 @@ static ButtConfig TopRiderButtons[8] = {
|
|||
/**
|
||||
* Update the status of the TopRider input device.
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
UpdateTopRider ()
|
||||
{
|
||||
int x;
|
||||
|
@ -1575,7 +1603,7 @@ static ButtConfig FTrainerButtons[12] = {
|
|||
/**
|
||||
* Update the status of the FTrainer input device.
|
||||
*/
|
||||
static void
|
||||
static void
|
||||
UpdateFTrainer ()
|
||||
{
|
||||
int x;
|
||||
|
@ -1764,7 +1792,7 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb)
|
|||
* used as input for the specified button, thus allowing up to four
|
||||
* possible settings for each input button.
|
||||
*/
|
||||
void
|
||||
void
|
||||
ConfigButton (char *text, ButtConfig * bc)
|
||||
{
|
||||
uint8 buf[256];
|
||||
|
@ -1978,7 +2006,7 @@ void InputCfg (const std::string & text)
|
|||
* configuration management. Will probably want to change this in the
|
||||
* future - soules.
|
||||
*/
|
||||
void
|
||||
void
|
||||
UpdateInput (Config * config)
|
||||
{
|
||||
char buf[64];
|
||||
|
@ -2084,6 +2112,10 @@ UpdateInput (Config * config)
|
|||
{
|
||||
type = BUTTC_JOYSTICK;
|
||||
}
|
||||
else if (device.find ("GameController") != std::string::npos)
|
||||
{
|
||||
type = BUTTC_GAMECONTROLLER;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = 0;
|
||||
|
@ -2295,16 +2327,38 @@ UpdateInput (Config * config)
|
|||
// GamePad defaults
|
||||
const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = { "A", "B", "Select", "Start",
|
||||
"Up", "Down", "Left", "Right", "TurboA", "TurboB"
|
||||
};
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] =
|
||||
{ "GameController", "None", "None", "None" };
|
||||
const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] =
|
||||
{ { SDL_CONTROLLER_BUTTON_A,
|
||||
SDL_CONTROLLER_BUTTON_X,
|
||||
SDL_CONTROLLER_BUTTON_BACK,
|
||||
SDL_CONTROLLER_BUTTON_START,
|
||||
SDL_CONTROLLER_BUTTON_DPAD_UP,
|
||||
SDL_CONTROLLER_BUTTON_DPAD_DOWN,
|
||||
SDL_CONTROLLER_BUTTON_DPAD_LEFT,
|
||||
SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
|
||||
SDL_CONTROLLER_BUTTON_INVALID,
|
||||
SDL_CONTROLLER_BUTTON_INVALID
|
||||
},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#else
|
||||
const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] =
|
||||
{ "Keyboard", "None", "None", "None" };
|
||||
const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] =
|
||||
{ {SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN,
|
||||
SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
{ { SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN,
|
||||
SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0
|
||||
},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
// PowerPad defaults
|
||||
const char *PowerPadNames[POWERPAD_NUM_BUTTONS] =
|
||||
|
@ -2312,10 +2366,11 @@ const char *PowerPadNames[POWERPAD_NUM_BUTTONS] =
|
|||
const char *DefaultPowerPadDevice[POWERPAD_NUM_DEVICES] =
|
||||
{ "Keyboard", "None" };
|
||||
const int DefaultPowerPad[POWERPAD_NUM_DEVICES][POWERPAD_NUM_BUTTONS] =
|
||||
{ {SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET,
|
||||
{ { SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET,
|
||||
SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE,
|
||||
SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH
|
||||
},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
// QuizKing defaults
|
||||
|
|
|
@ -27,6 +27,7 @@ int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
|
|||
#define BUTTC_KEYBOARD 0x00
|
||||
#define BUTTC_JOYSTICK 0x01
|
||||
#define BUTTC_MOUSE 0x02
|
||||
#define BUTTC_GAMECONTROLLER 0x03
|
||||
|
||||
#define FCFGD_GAMEPAD 1
|
||||
#define FCFGD_POWERPAD 2
|
||||
|
@ -48,6 +49,7 @@ void IncreaseEmulationSpeed(void);
|
|||
void DecreaseEmulationSpeed(void);
|
||||
|
||||
int DTestButtonJoy(ButtConfig *bc);
|
||||
int DTestButtonGC(ButtConfig *bc);
|
||||
|
||||
void FCEUD_UpdateInput(void);
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2002 Paul Kuliniewicz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief Handles GameController input using the SDL. This is an SDL2-only feature
|
||||
|
||||
#include "sdl.h"
|
||||
|
||||
/* This entire file is SDL2 only. GameController API is new as of SDL2 */
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#define MAX_GAMECONTROLLERS 32
|
||||
static SDL_GameController *s_GameCtrls[MAX_GAMECONTROLLERS] = {NULL};
|
||||
|
||||
static int s_gcinited = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Tests if the given button is active on the joystick.
|
||||
*/
|
||||
int
|
||||
DTestButtonGC(ButtConfig *bc)
|
||||
{
|
||||
int x;
|
||||
//printf("DTestButtonGC\n");
|
||||
SDL_GameController *gc;
|
||||
|
||||
for(x = 0; x < bc->NumC; x++)
|
||||
{
|
||||
gc = s_GameCtrls[bc->DeviceNum[x]];
|
||||
if( SDL_GameControllerGetButton(gc, (SDL_GameControllerButton) bc->ButtonNum[x]) )
|
||||
{
|
||||
//printf("GC %d btn '%s'=down\n", bc->DeviceNum[x],
|
||||
// SDL_GameControllerGetStringForButton( (SDL_GameControllerButton) bc->ButtonNum[x]));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the SDL joystick subsystem.
|
||||
*/
|
||||
int
|
||||
KillGameControllers()
|
||||
{
|
||||
int n; /* joystick index */
|
||||
|
||||
if(!s_gcinited) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(n = 0; n < MAX_GAMECONTROLLERS; n++) {
|
||||
if (s_GameCtrls[n]) {
|
||||
SDL_GameControllerClose(s_GameCtrls[n]);
|
||||
}
|
||||
s_GameCtrls[n]=0;
|
||||
}
|
||||
SDL_QuitSubSystem(MAX_GAMECONTROLLERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the SDL Game-Controller subsystem.
|
||||
*/
|
||||
int
|
||||
InitGameControllers()
|
||||
{
|
||||
int n; /* joystick index */
|
||||
int total;
|
||||
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
|
||||
// Game Controller API wraps joystick API, so the number of joysticks is also
|
||||
// the number of game controllers. For some reason SDL2 decided to leave
|
||||
// this as one API
|
||||
total = SDL_NumJoysticks();
|
||||
if(total>MAX_GAMECONTROLLERS) {
|
||||
total = MAX_GAMECONTROLLERS;
|
||||
}
|
||||
|
||||
for(n = 0; n < total; n++) {
|
||||
// Detect if a JoyStick is a game-controller, and if so, open it.
|
||||
if( SDL_IsGameController(n) ) {
|
||||
s_GameCtrls[n] = SDL_GameControllerOpen(n);
|
||||
if( ! s_GameCtrls[n] ) {
|
||||
printf("Could not open gamecontroller %d: %s.\n",
|
||||
n - 1, SDL_GetError());
|
||||
}
|
||||
else {
|
||||
printf("Opening Game Controller %d, name=%s\n", n, SDL_GameControllerName(s_GameCtrls[n]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_gcinited = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif //#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
|
@ -49,6 +49,9 @@ fillaudio(void *udata,
|
|||
uint8 *stream,
|
||||
int len)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_memset(stream, 0, len);
|
||||
#endif
|
||||
int16 *tmps = (int16*)stream;
|
||||
len >>= 1;
|
||||
while(len) {
|
||||
|
|
|
@ -52,11 +52,19 @@
|
|||
// GLOBALS
|
||||
extern Config *g_config;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
static SDL_Window * s_window;
|
||||
static SDL_Renderer * s_renderer;
|
||||
extern SDL_Surface * s_screen; // TODO - where else is this accessed?
|
||||
static SDL_Texture * s_texture;
|
||||
static SDL_Surface * s_IconSurface = NULL;
|
||||
#else
|
||||
// STATIC GLOBALS
|
||||
extern SDL_Surface *s_screen;
|
||||
|
||||
static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits.
|
||||
static SDL_Surface *s_IconSurface = NULL;
|
||||
#endif
|
||||
|
||||
static int s_curbpp;
|
||||
static int s_srendline, s_erendline;
|
||||
|
@ -71,8 +79,11 @@ static int s_eefx;
|
|||
static int s_clipSides;
|
||||
static int s_fullscreen;
|
||||
static int noframe;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#else
|
||||
static int s_nativeWidth = -1;
|
||||
static int s_nativeHeight = -1;
|
||||
#endif
|
||||
|
||||
#define NWIDTH (256 - (s_clipSides ? 16 : 0))
|
||||
#define NOFFSET (s_clipSides ? 8 : 0)
|
||||
|
@ -92,6 +103,51 @@ bool FCEUD_ShouldDrawInputAids()
|
|||
return s_fullscreen!=0;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
int
|
||||
KillVideo()
|
||||
{
|
||||
// if the IconSurface has been initialized, destroy it
|
||||
if(s_IconSurface) {
|
||||
SDL_FreeSurface(s_IconSurface);
|
||||
s_IconSurface=0;
|
||||
}
|
||||
|
||||
// return failure if the video system was not initialized
|
||||
if(s_inited == 0)
|
||||
return -1;
|
||||
|
||||
// shut down the system that converts from 8 to 16/32 bpp
|
||||
if(s_curbpp > 8)
|
||||
KillBlitToHigh();
|
||||
|
||||
// Tear down SDL2 resources in reverse order from init
|
||||
if(s_texture) {
|
||||
SDL_DestroyTexture(s_texture);
|
||||
s_texture = 0;
|
||||
}
|
||||
|
||||
if(s_screen) {
|
||||
SDL_FreeSurface(s_screen);
|
||||
s_screen=0;
|
||||
}
|
||||
|
||||
if(s_renderer) {
|
||||
SDL_DestroyRenderer(s_renderer);
|
||||
}
|
||||
|
||||
if( s_window ) {
|
||||
SDL_DestroyWindow(s_window);
|
||||
s_window=0;
|
||||
}
|
||||
|
||||
// shut down the SDL video sub-system
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
s_inited = 0;
|
||||
return 0;
|
||||
}
|
||||
#else // SDL < 2.0
|
||||
int
|
||||
KillVideo()
|
||||
{
|
||||
|
@ -122,6 +178,7 @@ KillVideo()
|
|||
s_inited = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif // SDL2 check
|
||||
|
||||
|
||||
// this variable contains information about the special scaling filters
|
||||
|
@ -154,6 +211,142 @@ int InitVideo(FCEUGI *gi)
|
|||
// This is a big TODO. Stubbing this off into its own function,
|
||||
// as the SDL surface routines have changed drastically in SDL2
|
||||
// TODO - SDL2
|
||||
const char * window_name;
|
||||
int error, flags = 0;
|
||||
int doublebuf, xstretch, ystretch, xres, yres, show_fps;
|
||||
uint32_t Amask, Rmask, Gmask, Bmask;
|
||||
int bpp;
|
||||
|
||||
FCEUI_printf("Initializing video (SDL2.x) ...");
|
||||
|
||||
// load the relevant configuration variables
|
||||
g_config->getOption("SDL.Fullscreen", &s_fullscreen);
|
||||
g_config->getOption("SDL.DoubleBuffering", &doublebuf);
|
||||
#ifdef OPENGL
|
||||
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
|
||||
#endif
|
||||
g_config->getOption("SDL.SpecialFilter", &s_sponge);
|
||||
g_config->getOption("SDL.XStretch", &xstretch);
|
||||
g_config->getOption("SDL.YStretch", &ystretch);
|
||||
g_config->getOption("SDL.LastXRes", &xres);
|
||||
g_config->getOption("SDL.LastYRes", &yres);
|
||||
g_config->getOption("SDL.ClipSides", &s_clipSides);
|
||||
g_config->getOption("SDL.NoFrame", &noframe);
|
||||
g_config->getOption("SDL.ShowFPS", &show_fps);
|
||||
|
||||
// check the starting, ending, and total scan lines
|
||||
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
|
||||
s_tlines = s_erendline - s_srendline + 1;
|
||||
|
||||
#if OPENGL
|
||||
if( !s_useOpenGL || s_sponge )
|
||||
{
|
||||
FCEUD_PrintError("SDL2 Does not support non-OpenGL rendering or special filters\n");
|
||||
KillVideo();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize the SDL video subsystem if it is not already active
|
||||
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
|
||||
error = SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||
if(error) {
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
s_inited = 1;
|
||||
|
||||
// For simplicity, hard-code this to 32bpp for now...
|
||||
s_curbpp = 32;
|
||||
|
||||
// If game is running, set window name accordingly
|
||||
if( gi )
|
||||
{
|
||||
window_name = (const char *) gi->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
window_name = "FCE Ultra";
|
||||
}
|
||||
|
||||
s_exs = 1.0;
|
||||
s_eys = 1.0;
|
||||
if(s_fullscreen) {
|
||||
s_window = SDL_CreateWindow( window_name,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
0, 0, // Res not specified in full-screen mode
|
||||
SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
} else {
|
||||
s_window = SDL_CreateWindow( window_name,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
xres, yres,
|
||||
0);
|
||||
}
|
||||
|
||||
// This stuff all applies regardless of full-screen vs windowed mode.
|
||||
s_renderer = SDL_CreateRenderer(s_window, -1, 0);
|
||||
|
||||
// Set logical rendering size & specify scaling mode. All rendering is
|
||||
// now done to the renderer rather than directly to the screen surface.
|
||||
// The renderer takes care of any scaling necessary.
|
||||
//
|
||||
// NOTE: setting scale quality to "nearest" will result in a blown-up but
|
||||
// pixelated while "linear" will tend to blur everything.
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
|
||||
SDL_RenderSetLogicalSize(s_renderer, xres, yres);
|
||||
|
||||
|
||||
//
|
||||
// Create the texture that will ultimately be rendered.
|
||||
// s_screen is used to build up an image, then the texture will be updated
|
||||
// all at once when it's ready
|
||||
s_texture = SDL_CreateTexture(s_renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
xres, yres);
|
||||
//
|
||||
// Create a surface to draw pixels onto
|
||||
//
|
||||
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
|
||||
s_screen = SDL_CreateRGBSurface(0, xres, yres, bpp,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
|
||||
if( !s_screen )
|
||||
{
|
||||
FCEUD_PrintError(SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Setup Icon surface
|
||||
//
|
||||
#ifdef LSB_FIRST
|
||||
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
|
||||
32, 32, 24, 32 * 3,
|
||||
0xFF, 0xFF00, 0xFF0000, 0x00);
|
||||
#else
|
||||
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
|
||||
32, 32, 24, 32 * 3,
|
||||
0xFF0000, 0xFF00, 0xFF, 0x00);
|
||||
#endif
|
||||
|
||||
SDL_SetWindowIcon(s_window, s_IconSurface);
|
||||
|
||||
s_paletterefresh = 1; // Force palette refresh
|
||||
|
||||
// always init blit to high since bpp forced to 32 for now.
|
||||
InitBlitToHigh(s_curbpp >> 3,
|
||||
s_screen->format->Rmask,
|
||||
s_screen->format->Gmask,
|
||||
s_screen->format->Bmask,
|
||||
0, //s_eefx, Hard-code SFX off
|
||||
0, //s_sponge, Hard-code special filters off.
|
||||
0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
|
@ -505,6 +698,31 @@ InitVideo(FCEUGI *gi)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void ToggleFS()
|
||||
{
|
||||
// pause while we we are making the switch
|
||||
bool paused = FCEUI_EmulationPaused();
|
||||
|
||||
if(!paused)
|
||||
FCEUI_ToggleEmulationPause();
|
||||
|
||||
g_config->getOption("SDL.Fullscreen", &s_fullscreen);
|
||||
s_fullscreen = !s_fullscreen;
|
||||
g_config->setOption("SDL.Fullscreen", s_fullscreen);
|
||||
|
||||
// shut down the current video system
|
||||
// KillVideo(); - No longer needed for SDL2, I think?
|
||||
|
||||
// flip the fullscreen flag
|
||||
SDL_SetWindowFullscreen(s_window,
|
||||
s_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 );
|
||||
|
||||
// if we paused to make the switch; unpause
|
||||
if(!paused)
|
||||
FCEUI_ToggleEmulationPause();
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* Toggles the full-screen display.
|
||||
*/
|
||||
|
@ -542,6 +760,7 @@ void ToggleFS()
|
|||
if(!paused)
|
||||
FCEUI_ToggleEmulationPause();
|
||||
}
|
||||
#endif
|
||||
|
||||
static SDL_Color s_psdl[256];
|
||||
|
||||
|
@ -580,6 +799,9 @@ FCEUD_GetPalette(uint8 index,
|
|||
*/
|
||||
static void RedoPalette()
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SetPaletteBlitToHigh((uint8*)s_psdl);
|
||||
#else
|
||||
#ifdef OPENGL
|
||||
if(s_useOpenGL)
|
||||
SetOpenGLPalette((uint8*)s_psdl);
|
||||
|
@ -590,22 +812,75 @@ static void RedoPalette()
|
|||
SetPaletteBlitToHigh((uint8*)s_psdl);
|
||||
} else
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
//TODO - SDL2
|
||||
#else
|
||||
|
||||
SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
// XXX soules - console lock/unlock unimplemented?
|
||||
|
||||
///Currently unimplemented.
|
||||
void LockConsole(){}
|
||||
void LockConsole() {}
|
||||
|
||||
///Currently unimplemented.
|
||||
void UnlockConsole(){}
|
||||
void UnlockConsole() {}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
void
|
||||
BlitScreen(uint8 *XBuf)
|
||||
{
|
||||
SDL_Surface * TmpScreen = s_screen;
|
||||
uint8 *dest;
|
||||
int xo = 0, yo = 0;
|
||||
|
||||
if(!s_screen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh the palette if required
|
||||
if(s_paletterefresh) {
|
||||
RedoPalette();
|
||||
s_paletterefresh = 0;
|
||||
}
|
||||
|
||||
// XXX soules - not entirely sure why this is being done yet
|
||||
XBuf += s_srendline * 256;
|
||||
|
||||
// lock the display, if necessary
|
||||
if(SDL_MUSTLOCK(TmpScreen)) {
|
||||
if(SDL_LockSurface(TmpScreen) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dest = (uint8*)TmpScreen->pixels;
|
||||
|
||||
#if 0
|
||||
if(s_fullscreen) {
|
||||
xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2);
|
||||
dest += xo * (s_curbpp >> 3);
|
||||
if(TmpScreen->h > (s_tlines * s_eys)) {
|
||||
yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2);
|
||||
dest += yo * TmpScreen->pitch;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
|
||||
TmpScreen->pitch, (int)s_exs, (int)s_eys);
|
||||
|
||||
if(SDL_MUSTLOCK(TmpScreen)) {
|
||||
SDL_UnlockSurface(TmpScreen);
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(s_texture, NULL, s_screen->pixels, s_screen->pitch);
|
||||
SDL_RenderClear(s_renderer);
|
||||
SDL_RenderCopy(s_renderer, s_texture, NULL, NULL);
|
||||
SDL_RenderPresent(s_renderer);
|
||||
}
|
||||
|
||||
#else // SDL1.x
|
||||
/**
|
||||
* Pushes the given buffer of bits to the screen.
|
||||
*/
|
||||
|
@ -706,12 +981,8 @@ BlitScreen(uint8 *XBuf)
|
|||
}
|
||||
|
||||
// ensure that the display is updated
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
//TODO - SDL2
|
||||
#else
|
||||
SDL_UpdateRect(s_screen, xo, yo,
|
||||
(Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys));
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
#if 0 /* PAL INTO NTSC HACK */
|
||||
|
@ -721,9 +992,12 @@ BlitScreen(uint8 *XBuf)
|
|||
if(FCEUI_GetDesiredFPS() == 838977920)
|
||||
{
|
||||
static unsigned dup=0;
|
||||
if(++dup==5) { dup=0;
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); }
|
||||
} }
|
||||
if(++dup==5) {
|
||||
dup=0;
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{ int fps = FCEUI_GetDesiredFPS();
|
||||
static unsigned char* result = NULL;
|
||||
|
@ -736,8 +1010,11 @@ BlitScreen(uint8 *XBuf)
|
|||
}
|
||||
switch(s_curbpp)
|
||||
{
|
||||
#if 0
|
||||
case 24: case 32: case 15: case 16:
|
||||
#if 0
|
||||
case 24:
|
||||
case 32:
|
||||
case 15:
|
||||
case 16:
|
||||
/* Convert to I420 if possible, because our I420 conversion is optimized
|
||||
* and it'll produce less network traffic, hence faster throughput than
|
||||
* anything else. And H.264 eats only I420, so it'd be converted sooner
|
||||
|
@ -745,14 +1022,22 @@ BlitScreen(uint8 *XBuf)
|
|||
*/
|
||||
switch(s_curbpp)
|
||||
{
|
||||
case 32: Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 24: Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 15: Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 16: Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width); break;
|
||||
case 32:
|
||||
Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width);
|
||||
break;
|
||||
case 24:
|
||||
Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width);
|
||||
break;
|
||||
case 15:
|
||||
Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width);
|
||||
break;
|
||||
case 16:
|
||||
Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width);
|
||||
break;
|
||||
}
|
||||
NESVideoLoggingVideo(&result[0], width,height, fps, 12);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
|
||||
}
|
||||
|
@ -796,6 +1081,7 @@ BlitScreen(uint8 *XBuf)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#endif // SDL_VERSION_ATLEAST(2, 0, 0) for BlitScreen
|
||||
|
||||
/**
|
||||
* Converts an x-y coordinate in the window manager into an x-y
|
||||
|
|
|
@ -310,6 +310,9 @@ DriverInitialize(FCEUGI *gi)
|
|||
if(InitJoysticks())
|
||||
inited|=2;
|
||||
|
||||
if(InitGameControllers())
|
||||
inited|=8;
|
||||
|
||||
int fourscore=0;
|
||||
g_config->getOption("SDL.FourScore", &fourscore);
|
||||
eoptions &= ~EO_FOURSCORE;
|
||||
|
@ -329,6 +332,8 @@ DriverKill()
|
|||
if (!noconfig)
|
||||
g_config->save();
|
||||
|
||||
if(inited&8)
|
||||
KillGameControllers();
|
||||
if(inited&2)
|
||||
KillJoysticks();
|
||||
if(inited&4)
|
||||
|
|
Loading…
Reference in New Issue