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:
mcfarlandjb 2014-02-16 04:49:53 +00:00
parent 108cf8494c
commit bb27c041ea
10 changed files with 1099 additions and 616 deletions

View File

@ -66,7 +66,10 @@ if os.environ.has_key('PKG_CONFIG_PATH'):
env['ENV']['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH'] env['ENV']['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH']
if os.environ.has_key('PKG_CONFIG_LIBDIR'): if os.environ.has_key('PKG_CONFIG_LIBDIR'):
env['ENV']['PKG_CONFIG_LIBDIR'] = os.environ['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'] print "platform: ", env['PLATFORM']

View File

@ -11,6 +11,7 @@ source_list = Split(
config.cpp config.cpp
sdl.cpp sdl.cpp
sdl-joystick.cpp sdl-joystick.cpp
sdl-gamectrl.cpp
sdl-sound.cpp sdl-sound.cpp
sdl-throttle.cpp sdl-throttle.cpp
sdl-video.cpp sdl-video.cpp

View File

@ -62,7 +62,7 @@ LoadCPalette(const std::string &file)
static void static void
CreateDirs(const std::string &dir) 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; std::string subdir;
int x; int x;
@ -139,7 +139,7 @@ InitConfig()
config->addOption("soundrecord", "SDL.Sound.RecordFile", ""); config->addOption("soundrecord", "SDL.Sound.RecordFile", "");
config->addOption("soundbufsize", "SDL.Sound.BufSize", 128); config->addOption("soundbufsize", "SDL.Sound.BufSize", 128);
config->addOption("lowpass", "SDL.Sound.LowPass", 0); config->addOption("lowpass", "SDL.Sound.LowPass", 0);
config->addOption('g', "gamegenie", "SDL.GameGenie", 0); config->addOption('g', "gamegenie", "SDL.GameGenie", 0);
config->addOption("pal", "SDL.PAL", 0); config->addOption("pal", "SDL.PAL", 0);
config->addOption("frameskip", "SDL.Frameskip", 0); config->addOption("frameskip", "SDL.Frameskip", 0);
@ -191,7 +191,7 @@ InitConfig()
config->addOption('k', "netkey", "SDL.NetworkGameKey", ""); config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
config->addOption("port", "SDL.NetworkPort", 4046); config->addOption("port", "SDL.NetworkPort", 4046);
config->addOption("players", "SDL.NetworkPlayers", 1); config->addOption("players", "SDL.NetworkPlayers", 1);
// input configuration options // input configuration options
config->addOption("input1", "SDL.Input.0", "GamePad.0"); config->addOption("input1", "SDL.Input.0", "GamePad.0");
config->addOption("input2", "SDL.Input.1", "GamePad.1"); config->addOption("input2", "SDL.Input.1", "GamePad.1");
@ -200,50 +200,50 @@ InitConfig()
// allow for input configuration // allow for input configuration
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
// display input // display input
config->addOption("inputdisplay", "SDL.InputDisplay", 0); config->addOption("inputdisplay", "SDL.InputDisplay", 0);
// enable / disable opposite directionals (left + right or up + down simultaneously) // enable / disable opposite directionals (left + right or up + down simultaneously)
config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1); config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1);
// pause movie playback at frame x // pause movie playback at frame x
config->addOption("pauseframe", "SDL.PauseFrame", 0); config->addOption("pauseframe", "SDL.PauseFrame", 0);
config->addOption("recordhud", "SDL.RecordHUD", 1); config->addOption("recordhud", "SDL.RecordHUD", 1);
config->addOption("moviemsg", "SDL.MovieMsg", 1); config->addOption("moviemsg", "SDL.MovieMsg", 1);
// overwrite the config file? // overwrite the config file?
config->addOption("no-config", "SDL.NoConfig", 0); config->addOption("no-config", "SDL.NoConfig", 0);
config->addOption("autoresume", "SDL.AutoResume", 0); config->addOption("autoresume", "SDL.AutoResume", 0);
// video playback // video playback
config->addOption("playmov", "SDL.Movie", ""); config->addOption("playmov", "SDL.Movie", "");
config->addOption("subtitles", "SDL.SubtitleDisplay", 1); config->addOption("subtitles", "SDL.SubtitleDisplay", 1);
config->addOption("fourscore", "SDL.FourScore", 0); config->addOption("fourscore", "SDL.FourScore", 0);
config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1); config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1);
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
// load lua script // load lua script
config->addOption("loadlua", "SDL.LuaScript", ""); config->addOption("loadlua", "SDL.LuaScript", "");
#endif #endif
#ifdef CREATE_AVI #ifdef CREATE_AVI
config->addOption("videolog", "SDL.VideoLog", ""); config->addOption("videolog", "SDL.VideoLog", "");
config->addOption("mute", "SDL.MuteCapture", 0); config->addOption("mute", "SDL.MuteCapture", 0);
#endif #endif
// auto load/save on gameload/close // auto load/save on gameload/close
config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE); config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE);
config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE); config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE);
//TODO implement this //TODO implement this
config->addOption("periodicsaves", "SDL.PeriodicSaves", 0); config->addOption("periodicsaves", "SDL.PeriodicSaves", 0);
#ifdef _GTK #ifdef _GTK
char* home_dir = getenv("HOME"); char* home_dir = getenv("HOME");
// prefixed with _ because they are internal (not cli options) // prefixed with _ because they are internal (not cli options)
config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir); config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir);
@ -251,19 +251,19 @@ InitConfig()
config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir); config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir);
config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir); config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir);
config->addOption("_lastloadlua", "SDL.LastLoadLua", home_dir); config->addOption("_lastloadlua", "SDL.LastLoadLua", home_dir);
#endif #endif
// fcm -> fm2 conversion // fcm -> fm2 conversion
config->addOption("fcmconvert", "SDL.FCMConvert", ""); config->addOption("fcmconvert", "SDL.FCMConvert", "");
// fm2 -> srt conversion // fm2 -> srt conversion
config->addOption("ripsubs", "SDL.RipSubs", ""); config->addOption("ripsubs", "SDL.RipSubs", "");
// enable new PPU core // enable new PPU core
config->addOption("newppu", "SDL.NewPPU", 0); config->addOption("newppu", "SDL.NewPPU", 0);
// quit when a+b+select+start is pressed // quit when a+b+select+start is pressed
config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0); config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0);
// GamePad 0 - 3 // GamePad 0 - 3
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) {
@ -277,7 +277,7 @@ InitConfig()
config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]); config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]);
} }
} }
// PowerPad 0 - 1 // PowerPad 0 - 1
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
char buf[64]; char buf[64];
@ -337,7 +337,7 @@ InitConfig()
config->addOption(prefix + "DeviceNum", 0); config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) { for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
config->addOption(prefix + FamilyKeyBoardNames[j], config->addOption(prefix + FamilyKeyBoardNames[j],
DefaultFamilyKeyBoard[j]); DefaultFamilyKeyBoard[j]);
} }
// for FAMICOM microphone in pad 2 pad 1 didn't have it // for FAMICOM microphone in pad 2 pad 1 didn't have it
@ -377,7 +377,8 @@ InitConfig()
SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_6, SDLK_7, SDLK_8, SDLK_9,
SDLK_PAGEUP, // select state next SDLK_PAGEUP, // select state next
SDLK_PAGEDOWN}; // select state prev SDLK_PAGEDOWN
}; // select state prev
prefix = "SDL.Hotkeys."; prefix = "SDL.Hotkeys.";
for(int i=0; i < HK_MAX; i++) for(int i=0; i < HK_MAX; i++)

View File

@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */
int InitJoysticks(void); int InitJoysticks(void);
int KillJoysticks(void); int KillJoysticks(void);
int InitGameControllers(void);
int KillGameControllers(void);
uint32 *GetJSOr(void); uint32 *GetJSOr(void);
int InitVideo(FCEUGI *gi); int InitVideo(FCEUGI *gi);

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
#define BUTTC_KEYBOARD 0x00 #define BUTTC_KEYBOARD 0x00
#define BUTTC_JOYSTICK 0x01 #define BUTTC_JOYSTICK 0x01
#define BUTTC_MOUSE 0x02 #define BUTTC_MOUSE 0x02
#define BUTTC_GAMECONTROLLER 0x03
#define FCFGD_GAMEPAD 1 #define FCFGD_GAMEPAD 1
#define FCFGD_POWERPAD 2 #define FCFGD_POWERPAD 2
@ -48,6 +49,7 @@ void IncreaseEmulationSpeed(void);
void DecreaseEmulationSpeed(void); void DecreaseEmulationSpeed(void);
int DTestButtonJoy(ButtConfig *bc); int DTestButtonJoy(ButtConfig *bc);
int DTestButtonGC(ButtConfig *bc);
void FCEUD_UpdateInput(void); void FCEUD_UpdateInput(void);

View File

@ -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)

View File

@ -46,9 +46,12 @@ static int s_mute = 0;
*/ */
static void static void
fillaudio(void *udata, fillaudio(void *udata,
uint8 *stream, uint8 *stream,
int len) int len)
{ {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_memset(stream, 0, len);
#endif
int16 *tmps = (int16*)stream; int16 *tmps = (int16*)stream;
len >>= 1; len >>= 1;
while(len) { while(len) {
@ -117,7 +120,7 @@ InitSound()
// For safety, set a bare minimum: // For safety, set a bare minimum:
if (s_BufferSize < spec.samples * 2) if (s_BufferSize < spec.samples * 2)
s_BufferSize = spec.samples * 2; s_BufferSize = spec.samples * 2;
s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize); s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize);
if (!s_Buffer) if (!s_Buffer)
@ -129,7 +132,7 @@ InitSound()
puts(SDL_GetError()); puts(SDL_GetError());
KillSound(); KillSound();
return 0; return 0;
} }
SDL_PauseAudio(0); SDL_PauseAudio(0);
FCEUI_SetSoundVolume(soundvolume); FCEUI_SetSoundVolume(soundvolume);
@ -173,7 +176,7 @@ WriteSound(int32 *buf,
if (EmulationPaused == 0) if (EmulationPaused == 0)
while(Count) while(Count)
{ {
while(s_BufferIn == s_BufferSize) while(s_BufferIn == s_BufferSize)
{ {
SDL_Delay(1); SDL_Delay(1);
} }
@ -181,11 +184,11 @@ WriteSound(int32 *buf,
s_Buffer[s_BufferWrite] = *buf; s_Buffer[s_BufferWrite] = *buf;
Count--; Count--;
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize; s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
SDL_LockAudio(); SDL_LockAudio();
s_BufferIn++; s_BufferIn++;
SDL_UnlockAudio(); SDL_UnlockAudio();
buf++; buf++;
} }
} }
@ -195,8 +198,8 @@ WriteSound(int32 *buf,
*/ */
void void
SilenceSound(int n) SilenceSound(int n)
{ {
SDL_PauseAudio(n); SDL_PauseAudio(n);
} }
/** /**

View File

@ -52,11 +52,19 @@
// GLOBALS // GLOBALS
extern Config *g_config; 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 // STATIC GLOBALS
extern SDL_Surface *s_screen; extern SDL_Surface *s_screen;
static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits. static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits.
static SDL_Surface *s_IconSurface = NULL; static SDL_Surface *s_IconSurface = NULL;
#endif
static int s_curbpp; static int s_curbpp;
static int s_srendline, s_erendline; static int s_srendline, s_erendline;
@ -71,8 +79,11 @@ static int s_eefx;
static int s_clipSides; static int s_clipSides;
static int s_fullscreen; static int s_fullscreen;
static int noframe; static int noframe;
#if SDL_VERSION_ATLEAST(2, 0, 0)
#else
static int s_nativeWidth = -1; static int s_nativeWidth = -1;
static int s_nativeHeight = -1; static int s_nativeHeight = -1;
#endif
#define NWIDTH (256 - (s_clipSides ? 16 : 0)) #define NWIDTH (256 - (s_clipSides ? 16 : 0))
#define NOFFSET (s_clipSides ? 8 : 0) #define NOFFSET (s_clipSides ? 8 : 0)
@ -91,7 +102,8 @@ bool FCEUD_ShouldDrawInputAids()
{ {
return s_fullscreen!=0; return s_fullscreen!=0;
} }
#if SDL_VERSION_ATLEAST(2, 0, 0)
int int
KillVideo() KillVideo()
{ {
@ -104,7 +116,51 @@ KillVideo()
// return failure if the video system was not initialized // return failure if the video system was not initialized
if(s_inited == 0) if(s_inited == 0)
return -1; 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()
{
// 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;
// if the rest of the system has been initialized, shut it down // if the rest of the system has been initialized, shut it down
#ifdef OPENGL #ifdef OPENGL
// check for OpenGL and shut it down // check for OpenGL and shut it down
@ -122,6 +178,7 @@ KillVideo()
s_inited = 0; s_inited = 0;
return 0; return 0;
} }
#endif // SDL2 check
// this variable contains information about the special scaling filters // 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, // This is a big TODO. Stubbing this off into its own function,
// as the SDL surface routines have changed drastically in SDL2 // as the SDL surface routines have changed drastically in SDL2
// TODO - 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 #else
/** /**
@ -191,7 +384,7 @@ InitVideo(FCEUGI *gi)
// check if we should auto-set x/y resolution // check if we should auto-set x/y resolution
// check for OpenGL and set the global flags // check for OpenGL and set the global flags
#if OPENGL #if OPENGL
if(s_useOpenGL && !s_sponge) { if(s_useOpenGL && !s_sponge) {
flags = SDL_OPENGL; flags = SDL_OPENGL;
@ -216,7 +409,7 @@ InitVideo(FCEUGI *gi)
if(vinf->hw_available) { if(vinf->hw_available) {
flags |= SDL_HWSURFACE; flags |= SDL_HWSURFACE;
} }
// get the monitor's current resolution if we do not already have it // get the monitor's current resolution if we do not already have it
if(s_nativeWidth < 0) { if(s_nativeWidth < 0) {
s_nativeWidth = vinf->current_w; s_nativeWidth = vinf->current_w;
@ -227,7 +420,7 @@ InitVideo(FCEUGI *gi)
// check to see if we are showing FPS // check to see if we are showing FPS
FCEUI_SetShowFPS(show_fps); FCEUI_SetShowFPS(show_fps);
// check if we are rendering fullscreen // check if we are rendering fullscreen
if(s_fullscreen) { if(s_fullscreen) {
int no_cursor; int no_cursor;
@ -238,7 +431,7 @@ InitVideo(FCEUGI *gi)
else { else {
SDL_ShowCursor(1); SDL_ShowCursor(1);
} }
if(noframe) { if(noframe) {
flags |= SDL_NOFRAME; flags |= SDL_NOFRAME;
} }
@ -251,7 +444,7 @@ InitVideo(FCEUGI *gi)
if(s_useOpenGL) { if(s_useOpenGL) {
FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n"); FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n");
if(doublebuf) { if(doublebuf) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
} }
} else } else
#endif #endif
@ -270,21 +463,21 @@ InitVideo(FCEUGI *gi)
double native_ratio = ((double)NWIDTH) / s_tlines; double native_ratio = ((double)NWIDTH) / s_tlines;
double screen_ratio = ((double)xres) / yres; double screen_ratio = ((double)xres) / yres;
int keep_ratio; int keep_ratio;
g_config->getOption("SDL.KeepRatio", &keep_ratio); g_config->getOption("SDL.KeepRatio", &keep_ratio);
// Try to choose resolution // Try to choose resolution
if (screen_ratio < native_ratio) if (screen_ratio < native_ratio)
{ {
// The screen is narrower than the original. Maximizing width will not clip // The screen is narrower than the original. Maximizing width will not clip
auto_xscale = auto_yscale = GetXScale(xres); auto_xscale = auto_yscale = GetXScale(xres);
if (keep_ratio) if (keep_ratio)
auto_yscale = GetYScale(yres); auto_yscale = GetYScale(yres);
} }
else else
{ {
auto_yscale = auto_xscale = GetYScale(yres); auto_yscale = auto_xscale = GetYScale(yres);
if (keep_ratio) if (keep_ratio)
auto_xscale = GetXScale(xres); auto_xscale = GetXScale(xres);
} }
s_exs = auto_xscale; s_exs = auto_xscale;
@ -304,7 +497,7 @@ InitVideo(FCEUGI *gi)
} else { } else {
desbpp = 0; desbpp = 0;
} }
// -Video Modes Tag- // -Video Modes Tag-
if(s_sponge) { if(s_sponge) {
if(s_sponge == 4 || s_sponge == 5) { if(s_sponge == 4 || s_sponge == 5) {
@ -337,8 +530,8 @@ InitVideo(FCEUGI *gi)
#ifdef OPENGL #ifdef OPENGL
s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres, s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres,
s_useOpenGL ? s_nativeHeight : yres, s_useOpenGL ? s_nativeHeight : yres,
desbpp, flags); desbpp, flags);
#else #else
s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags); s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags);
#endif #endif
@ -354,7 +547,7 @@ InitVideo(FCEUGI *gi)
g_config->getOption("SDL.XScale", &s_exs); g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys); g_config->getOption("SDL.YScale", &s_eys);
g_config->getOption("SDL.SpecialFX", &s_eefx); g_config->getOption("SDL.SpecialFX", &s_eefx);
// -Video Modes Tag- // -Video Modes Tag-
if(s_sponge) { if(s_sponge) {
if(s_sponge >= 4) { if(s_sponge >= 4) {
@ -392,11 +585,11 @@ InitVideo(FCEUGI *gi)
{ {
while (gtk_events_pending()) while (gtk_events_pending())
gtk_main_iteration_do(FALSE); gtk_main_iteration_do(FALSE);
char SDL_windowhack[128]; char SDL_windowhack[128];
sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox))); sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox)));
SDL_putenv(SDL_windowhack); SDL_putenv(SDL_windowhack);
// init SDL video // init SDL video
if (SDL_WasInit(SDL_INIT_VIDEO)) if (SDL_WasInit(SDL_INIT_VIDEO))
SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_QuitSubSystem(SDL_INIT_VIDEO);
@ -407,10 +600,10 @@ InitVideo(FCEUGI *gi)
} }
} }
#endif #endif
s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs), s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs),
(int)(s_tlines * s_eys), (int)(s_tlines * s_eys),
desbpp, flags); desbpp, flags);
if(!s_screen) { if(!s_screen) {
FCEUD_PrintError(SDL_GetError()); FCEUD_PrintError(SDL_GetError());
return -1; return -1;
@ -422,9 +615,9 @@ InitVideo(FCEUGI *gi)
GtkRequisition req; GtkRequisition req;
gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
} }
#endif #endif
} }
s_curbpp = s_screen->format->BitsPerPixel; s_curbpp = s_screen->format->BitsPerPixel;
if(!s_screen) { if(!s_screen) {
FCEUD_PrintError(SDL_GetError()); FCEUD_PrintError(SDL_GetError());
@ -434,17 +627,17 @@ InitVideo(FCEUGI *gi)
#if 0 #if 0
// XXX soules - this would be creating a surface on the video // XXX soules - this would be creating a surface on the video
// card, but was commented out for some reason... // card, but was commented out for some reason...
s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240,
s_screen->format->BitsPerPixel, s_screen->format->BitsPerPixel,
s_screen->format->Rmask, s_screen->format->Rmask,
s_screen->format->Gmask, s_screen->format->Gmask,
s_screen->format->Bmask, 0); s_screen->format->Bmask, 0);
#endif #endif
FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n", FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",
s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, s_screen->w, s_screen->h, s_screen->format->BitsPerPixel,
s_fullscreen ? "full screen" : ""); s_fullscreen ? "full screen" : "");
if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) { if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) {
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp); FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp);
@ -465,34 +658,34 @@ InitVideo(FCEUGI *gi)
// create the surface for displaying graphical messages // create the surface for displaying graphical messages
#ifdef LSB_FIRST #ifdef LSB_FIRST
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3, 32, 32, 24, 32 * 3,
0xFF, 0xFF00, 0xFF0000, 0x00); 0xFF, 0xFF00, 0xFF0000, 0x00);
#else #else
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3, 32, 32, 24, 32 * 3,
0xFF0000, 0xFF00, 0xFF, 0x00); 0xFF0000, 0xFF00, 0xFF, 0x00);
#endif #endif
SDL_WM_SetIcon(s_IconSurface,0); SDL_WM_SetIcon(s_IconSurface,0);
s_paletterefresh = 1; s_paletterefresh = 1;
// XXX soules - can't SDL do this for us? // XXX soules - can't SDL do this for us?
// if using more than 8bpp, initialize the conversion routines // if using more than 8bpp, initialize the conversion routines
if(s_curbpp > 8) { if(s_curbpp > 8) {
InitBlitToHigh(s_curbpp >> 3, InitBlitToHigh(s_curbpp >> 3,
s_screen->format->Rmask, s_screen->format->Rmask,
s_screen->format->Gmask, s_screen->format->Gmask,
s_screen->format->Bmask, s_screen->format->Bmask,
s_eefx, s_sponge, 0); s_eefx, s_sponge, 0);
#ifdef OPENGL #ifdef OPENGL
if(s_useOpenGL) if(s_useOpenGL)
{ {
int openGLip; int openGLip;
g_config->getOption("SDL.OpenGLip", &openGLip); g_config->getOption("SDL.OpenGLip", &openGLip);
if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0), if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0),
s_srendline, s_erendline + 1, s_srendline, s_erendline + 1,
s_exs, s_eys, s_eefx, s_exs, s_eys, s_eefx,
openGLip, xstretch, ystretch, s_screen)) openGLip, xstretch, ystretch, s_screen))
{ {
FCEUD_PrintError("Error initializing OpenGL."); FCEUD_PrintError("Error initializing OpenGL.");
KillVideo(); KillVideo();
@ -505,12 +698,37 @@ InitVideo(FCEUGI *gi)
} }
#endif #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. * Toggles the full-screen display.
*/ */
void ToggleFS() void ToggleFS()
{ {
// pause while we we are making the switch // pause while we we are making the switch
bool paused = FCEUI_EmulationPaused(); bool paused = FCEUI_EmulationPaused();
if(!paused) if(!paused)
FCEUI_ToggleEmulationPause(); FCEUI_ToggleEmulationPause();
@ -526,7 +744,7 @@ void ToggleFS()
if(noGui == 0) if(noGui == 0)
{ {
if(!fullscreen) if(!fullscreen)
showGui(0); showGui(0);
else else
showGui(1); showGui(1);
} }
@ -542,6 +760,7 @@ void ToggleFS()
if(!paused) if(!paused)
FCEUI_ToggleEmulationPause(); FCEUI_ToggleEmulationPause();
} }
#endif
static SDL_Color s_psdl[256]; static SDL_Color s_psdl[256];
@ -566,46 +785,102 @@ FCEUD_SetPalette(uint8 index,
*/ */
void void
FCEUD_GetPalette(uint8 index, FCEUD_GetPalette(uint8 index,
uint8 *r, uint8 *r,
uint8 *g, uint8 *g,
uint8 *b) uint8 *b)
{ {
*r = s_psdl[index].r; *r = s_psdl[index].r;
*g = s_psdl[index].g; *g = s_psdl[index].g;
*b = s_psdl[index].b; *b = s_psdl[index].b;
} }
/** /**
* Pushes the palette structure into the underlying video subsystem. * Pushes the palette structure into the underlying video subsystem.
*/ */
static void RedoPalette() static void RedoPalette()
{ {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SetPaletteBlitToHigh((uint8*)s_psdl);
#else
#ifdef OPENGL #ifdef OPENGL
if(s_useOpenGL) if(s_useOpenGL)
SetOpenGLPalette((uint8*)s_psdl); SetOpenGLPalette((uint8*)s_psdl);
else else
#endif #endif
{ {
if(s_curbpp > 8) { if(s_curbpp > 8) {
SetPaletteBlitToHigh((uint8*)s_psdl); SetPaletteBlitToHigh((uint8*)s_psdl);
} else } else
{ {
#if SDL_VERSION_ATLEAST(2, 0, 0)
//TODO - SDL2
#else
SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256); SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256);
#endif
} }
} }
#endif
} }
// XXX soules - console lock/unlock unimplemented? // XXX soules - console lock/unlock unimplemented?
///Currently unimplemented. ///Currently unimplemented.
void LockConsole(){} void LockConsole() {}
///Currently unimplemented. ///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. * Pushes the given buffer of bits to the screen.
*/ */
@ -666,19 +941,19 @@ BlitScreen(uint8 *XBuf)
if(s_curbpp > 8) { if(s_curbpp > 8) {
if(s_BlitBuf) { if(s_BlitBuf) {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1); TmpScreen->pitch, 1, 1);
} else { } else {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys); TmpScreen->pitch, (int)s_exs, (int)s_eys);
} }
} else { } else {
if(s_BlitBuf) { if(s_BlitBuf) {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1, 0, s_sponge); TmpScreen->pitch, 1, 1, 0, s_sponge);
} else { } else {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys, TmpScreen->pitch, (int)s_exs, (int)s_eys,
s_eefx, s_sponge); s_eefx, s_sponge);
} }
} }
@ -687,7 +962,7 @@ BlitScreen(uint8 *XBuf)
SDL_UnlockSurface(TmpScreen); SDL_UnlockSurface(TmpScreen);
} }
// if we have a hardware video buffer, do a fast video->video copy // if we have a hardware video buffer, do a fast video->video copy
if(s_BlitBuf) { if(s_BlitBuf) {
SDL_Rect srect; SDL_Rect srect;
SDL_Rect drect; SDL_Rect drect;
@ -705,97 +980,108 @@ BlitScreen(uint8 *XBuf)
SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect); SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect);
} }
// ensure that the display is updated // ensure that the display is updated
#if SDL_VERSION_ATLEAST(2, 0, 0)
//TODO - SDL2
#else
SDL_UpdateRect(s_screen, xo, yo, SDL_UpdateRect(s_screen, xo, yo,
(Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys)); (Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys));
#endif
#ifdef CREATE_AVI #ifdef CREATE_AVI
#if 0 /* PAL INTO NTSC HACK */ #if 0 /* PAL INTO NTSC HACK */
{ int fps = FCEUI_GetDesiredFPS(); { int fps = FCEUI_GetDesiredFPS();
if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711; if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711;
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
if(FCEUI_GetDesiredFPS() == 838977920) if(FCEUI_GetDesiredFPS() == 838977920)
{ {
static unsigned dup=0; static unsigned dup=0;
if(++dup==5) { dup=0; if(++dup==5) {
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); } dup=0;
} } NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
}
}
}
#else #else
{ int fps = FCEUI_GetDesiredFPS(); { int fps = FCEUI_GetDesiredFPS();
static unsigned char* result = NULL; static unsigned char* result = NULL;
static unsigned resultsize = 0; static unsigned resultsize = 0;
int width = NWIDTH, height = s_tlines; int width = NWIDTH, height = s_tlines;
if(!result || resultsize != width*height*3*2) if(!result || resultsize != width*height*3*2)
{ {
if(result) free(result); if(result) free(result);
result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2); result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2);
} }
switch(s_curbpp) switch(s_curbpp)
{ {
#if 0 #if 0
case 24: case 32: case 15: case 16: case 24:
/* Convert to I420 if possible, because our I420 conversion is optimized case 32:
* and it'll produce less network traffic, hence faster throughput than case 15:
* anything else. And H.264 eats only I420, so it'd be converted sooner case 16:
* or later anyway if we didn't do it. Win-win situation. /* Convert to I420 if possible, because our I420 conversion is optimized
*/ * and it'll produce less network traffic, hence faster throughput than
switch(s_curbpp) * anything else. And H.264 eats only I420, so it'd be converted sooner
{ * or later anyway if we didn't do it. Win-win situation.
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; switch(s_curbpp)
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);
NESVideoLoggingVideo(&result[0], width,height, fps, 12); break;
break; case 24:
#endif Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width);
default: break;
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); 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
default:
NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp);
}
}
#endif #endif
#if REALTIME_LOGGING #if REALTIME_LOGGING
{ {
static struct timeval last_time; static struct timeval last_time;
static int first_time=1; static int first_time=1;
extern long soundrate; extern long soundrate;
struct timeval cur_time; struct timeval cur_time;
gettimeofday(&cur_time, NULL); gettimeofday(&cur_time, NULL);
double timediff = double timediff =
(cur_time.tv_sec *1e6 + cur_time.tv_usec (cur_time.tv_sec *1e6 + cur_time.tv_usec
- (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6; - (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6;
int nframes = timediff * 60 - 1; int nframes = timediff * 60 - 1;
if(first_time) if(first_time)
first_time = 0; first_time = 0;
else while(nframes > 0) else while(nframes > 0)
{ {
static const unsigned char Buf[800*4] = {0}; static const unsigned char Buf[800*4] = {0};
NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp); NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp);
NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0); NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0);
--nframes; --nframes;
} }
memcpy(&last_time, &cur_time, sizeof(last_time)); memcpy(&last_time, &cur_time, sizeof(last_time));
} }
#endif #endif
#endif #endif
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
// TODO // TODO
#else #else
// have to flip the displayed buffer in the case of double buffering // have to flip the displayed buffer in the case of double buffering
if(s_screen->flags & SDL_DOUBLEBUF) { if(s_screen->flags & SDL_DOUBLEBUF) {
SDL_Flip(s_screen); SDL_Flip(s_screen);
} }
#endif #endif
} }
#endif // SDL_VERSION_ATLEAST(2, 0, 0) for BlitScreen
/** /**
* Converts an x-y coordinate in the window manager into an x-y * Converts an x-y coordinate in the window manager into an x-y
@ -803,7 +1089,7 @@ BlitScreen(uint8 *XBuf)
*/ */
uint32 uint32
PtoV(uint16 x, PtoV(uint16 x,
uint16 y) uint16 y)
{ {
y = (uint16)((double)y / s_eys); y = (uint16)((double)y / s_eys);
x = (uint16)((double)x / s_exs); x = (uint16)((double)x / s_exs);

View File

@ -310,6 +310,9 @@ DriverInitialize(FCEUGI *gi)
if(InitJoysticks()) if(InitJoysticks())
inited|=2; inited|=2;
if(InitGameControllers())
inited|=8;
int fourscore=0; int fourscore=0;
g_config->getOption("SDL.FourScore", &fourscore); g_config->getOption("SDL.FourScore", &fourscore);
eoptions &= ~EO_FOURSCORE; eoptions &= ~EO_FOURSCORE;
@ -329,6 +332,8 @@ DriverKill()
if (!noconfig) if (!noconfig)
g_config->save(); g_config->save();
if(inited&8)
KillGameControllers();
if(inited&2) if(inited&2)
KillJoysticks(); KillJoysticks();
if(inited&4) if(inited&4)