Updated code to allow proper emulator launching on RetroPie.

Note that this is WIP, and more changes will be added, especially in the
scripting area.
This commit is contained in:
Pieter Hulshoff 2017-06-21 11:05:09 +02:00
parent 126f88b4ce
commit f6ba968925
30 changed files with 732 additions and 711 deletions

View File

@ -1,72 +1,24 @@
up = Up
down = Down
left = Left
right = Right
up = Keypad 8,Up
down = Keypad 2,Down
left = Keypad 4,Left,joy0Button7
right = Keypad 6,Right,joy0Button5
pageUp = A
pageDown = B
letterUp = N
letterDown = M
nextPlaylist = P
favPlaylist = F
nextPlaylist = F2
prevPlaylist = F1
addPlaylist = I
removePlaylist = O
random = R
select = Space
back = Escape
select = 1,Return,joy0Button3
back = 2,Escape,joy0Button0
quit = Q
# Define controller analogue dead zone. Default (when not configured) is 3%.
# deadZone = 3
##############################################################################
# MOUSE CODES
###################### ######################################################
# Code # Description
###################### ######################################################
# mouseButtonLeft Left mouse click
# mouseButtonMiddle Middle mouse click
# mouseButtonRight Right mouse click
# mouseButtonX1 ?
# mouseButtonX2 ?
# See below for a list of key codes that can be used for configuring the controls:
##############################################################################
# JOYSTICK/GAMEPAD CODES
###################### ######################################################
# Code # Description
###################### ######################################################
# X is joypad number (0 is first joystick/gamepad)
# joyXHatYLeftUp Y=hat number (0 is the first dpad) (example joy0Hat0Up)
# joyXHatYLeft
# joyXHatYLeftDown
# joyXHatYUp
# joyXHatYDown
# joyXHatYRightUp
# joyXHatYRight
# joyXHatYRightDown
# joyXButtonY Y is button number (0 is first button)
# Example: joy1button7 -> second joystick, 8th button
# Open up the gamepad control panel in windows or use
# "jstest" in linux
#
# joyXAxis0+ First POV stick, first axis positive direction
# (axis 0 is usually x)
# joyXAxis0- First POV stick, first axis positive direction
# (axis 0 is usually x)
# joyXAxis1+ First POV stick, second axis positive direction
# (axis 0 is usually y)
#joyXAxis1- First POV stick, second axis positive direction
# (axis 0 is usually y)
#
# joyXAxis2+ Second POV stick, first axis positive direction
# (axis 2 is usually x)
# joyXAxis2- Second POV stick, first axis positive direction
# (axis 2 is usually x)
# joyXAxis3+ Second POV stick, second axis positive direction
# (axis 3 is usually y)
# joyXAxis3- Second POV stick, second axis positive direction
# (axis 3 is usually y)
##############################################################################
# KEYBOARD CODES
###################### ######################################################
# Code # Description
###################### ######################################################

View File

@ -15,9 +15,13 @@ fullscreen = no
horizontal = stretch # or enter in the screen pixel width (i.e 1024)
vertical = stretch # or enter in the screen pixel width (i.e 768)
layout = Aeon Nox
hideMouse = yes
showParenthesis = yes
showSquareBrackets = yes
# Hide the mouse
hideMouse = yes
# Hide () and [] from game titles
showParenthesis = no
showSquareBrackets = no
# specify the name of the first collection to load on start
firstCollection = Main
@ -25,12 +29,15 @@ firstCollection = Main
# specify whether RetroFE should switch to Favorites list if it exists.
autoFavorites = true
# specify whether RetroFE should remember the last selected game
rememberMenu = true
#######################################
# Video playback settings
#######################################
# set to "no" for very old/slow systems
videoEnable = yes
videoEnable = yes
# Number of times to loop video playback (enter 0 to continuously loop)
videoLoop = 0
@ -38,17 +45,27 @@ videoLoop = 0
#######################################
# General
#######################################
# exit the frontend when the back button is pressed on the first page
exitOnFirstPageBack = yes
# specify whether RetroFE should close when pressing back on the main menu
exitOnFirstPageBack = no
# enter 0 attract mode, otherwise enter the number of seconds to wait before enabling attract mode
attractModeTime = 45
attractModeTime = 45
# remember the last highlighted menu when re-entering a menu
# specify whether RetroFE should remember the last highlighted menu when re-entering a menu
rememberMenu = yes
# Clear the input on entering/exiting a collection
collectionInputClear = false
# specify whether RetroFE should clear the input queue on entering/exiting a collection
collectionInputClear = true
# specify whether RetroFE should minimize when running in full-screen mode
minimize_on_focus_loss = no
# specify whether RetroFE should unload SDL when running a program/game
# This is needed to prevent emulators from launching behind the front-end, e.g. on RetroPie.
# Set to false or comment out to prevent briefly seeing your Windows environment if you don't
# need this feature.
unloadSDL = true
#######################################
# Base folders of media and ROM files

View File

@ -30,9 +30,8 @@
#include <cstring>
#endif
Launcher::Launcher(RetroFE &p, Configuration &c)
Launcher::Launcher(Configuration &c)
: config_(c)
, retrofe_(p)
{
}
@ -153,9 +152,6 @@ bool Launcher::execute(std::string executable, std::string args, std::string cur
Logger::write(Logger::ZONE_INFO, "Launcher", "Attempting to launch: " + executionString);
Logger::write(Logger::ZONE_INFO, "Launcher", " from within folder: " + currentDirectory);
//todo: use delegation instead of depending on knowing the RetroFE class (tie to an interface)
retrofe_.launchEnter();
#ifdef WIN32
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
@ -205,7 +201,6 @@ bool Launcher::execute(std::string executable, std::string args, std::string cur
}
Logger::write(Logger::ZONE_INFO, "Launcher", "Completed");
retrofe_.launchExit();
return retVal;
}

View File

@ -24,7 +24,7 @@ class RetroFE;
class Launcher
{
public:
Launcher(RetroFE &p, Configuration &c);
Launcher(Configuration &c);
bool run(std::string collection, Item *collectionItem);
private:
@ -48,5 +48,4 @@ private:
std::string itemCollectionName);
Configuration &config_;
RetroFE &retrofe_;
};

View File

@ -31,8 +31,6 @@ public:
virtual ~Component();
virtual void freeGraphicsMemory();
virtual void allocateGraphicsMemory();
virtual void launchEnter() {}
virtual void launchExit() {}
void triggerEvent(std::string event, int menuIndex = -1);
void setPlaylist(std::string name );
void setNewItemSelected();

View File

@ -53,8 +53,6 @@ void Image::allocateGraphicsMemory()
int width;
int height;
Component::allocateGraphicsMemory();
if(!texture_)
{
SDL_LockMutex(SDL::getMutex());
@ -74,8 +72,12 @@ void Image::allocateGraphicsMemory()
SDL_UnlockMutex(SDL::getMutex());
}
Component::allocateGraphicsMemory();
}
void Image::draw()
{
Component::draw();

View File

@ -99,21 +99,6 @@ void ReloadableMedia::allocateGraphicsMemory()
Component::allocateGraphicsMemory();
}
void ReloadableMedia::launchEnter()
{
if(loadedComponent_)
{
loadedComponent_->launchEnter();
}
}
void ReloadableMedia::launchExit()
{
if(loadedComponent_)
{
loadedComponent_->launchExit();
}
}
void ReloadableMedia::freeGraphicsMemory()
{

View File

@ -33,8 +33,6 @@ public:
void draw();
void freeGraphicsMemory();
void allocateGraphicsMemory();
void launchEnter();
void launchExit();
Component *findComponent(std::string collection, std::string type, std::string basename, bool systemMode);
void enableTextFallback_(bool value);

View File

@ -98,8 +98,10 @@ void ReloadableScrollingText::update(float dt)
}
void ReloadableScrollingText::launchExit( )
void ReloadableScrollingText::allocateGraphicsMemory( )
{
Component::allocateGraphicsMemory( );
fontInst_->initialize( );
reloadTexture( );
}
@ -107,6 +109,7 @@ void ReloadableScrollingText::launchExit( )
void ReloadableScrollingText::freeGraphicsMemory( )
{
Component::freeGraphicsMemory( );
fontInst_->deInitialize( );
text_.clear( );
}

View File

@ -28,8 +28,8 @@ public:
virtual ~ReloadableScrollingText( );
void update(float dt);
void draw( );
void allocateGraphicsMemory( );
void freeGraphicsMemory( );
void launchExit();
private:
void reloadTexture( );

View File

@ -71,17 +71,12 @@ void ReloadableText::allocateGraphicsMemory()
{
ReloadTexture();
fontInst_->initialize();
// NOTICE! needs to be done last to prevent flags from being missed
Component::allocateGraphicsMemory();
}
void ReloadableText::launchEnter()
{
}
void ReloadableText::launchExit()
{
}
void ReloadableText::freeGraphicsMemory()
{
@ -92,7 +87,11 @@ void ReloadableText::freeGraphicsMemory()
delete imageInst_;
imageInst_ = NULL;
}
fontInst_->deInitialize();
}
void ReloadableText::ReloadTexture()
{
if (imageInst_ != NULL)

View File

@ -31,8 +31,6 @@ public:
void draw();
void freeGraphicsMemory();
void allocateGraphicsMemory();
void launchEnter();
void launchExit();
private:
void ReloadTexture();

View File

@ -140,8 +140,6 @@ void ScrollingList::deallocateSpritePoints()
{
deallocateTexture(i);
}
componentIndex_ = 0;
}
void ScrollingList::allocateSpritePoints()
@ -152,26 +150,41 @@ void ScrollingList::allocateSpritePoints()
for(unsigned int i = 0; i < scrollPoints_->size(); ++i)
{
componentIndex_ = 0;
unsigned int index = loopIncrement(itemIndex_, i, items_->size());
unsigned int index = loopIncrement(itemIndex_, i, items_->size());
unsigned int oindex = loopIncrement(componentIndex_, i, components_.size());
Item *item = items_->at(index);
allocateTexture(i, item);
Component *c = components_.at(i);
Component *o = components_.at(oindex);
ViewInfo *current = scrollPoints_->at(i);
allocateTexture(oindex, item);
unsigned int nextI = loopIncrement(i, 1, scrollPoints_->size());
Component *c = components_.at(oindex);
ViewInfo *current = scrollPoints_->at(oindex);
unsigned int nextI = loopIncrement(oindex, 1, scrollPoints_->size());
ViewInfo *next = scrollPoints_->at(nextI);
resetTweens(c, tweenPoints_->at(i), current, next, 0);
if(o)
{
c->baseViewInfo = o->baseViewInfo;
delete o;
}
}
}
void ScrollingList::destroyItems()
{
deallocateSpritePoints();
//todo: who deletes the CollectionInfo?
for(unsigned int i = 0; i < components_.size(); ++i)
{
delete components_.at(i);
components_.at(i) = NULL;
}
componentIndex_ = 0;
}
@ -307,6 +320,15 @@ void ScrollingList::letterChange(bool increment)
}
void ScrollingList::allocateGraphicsMemory()
{
Component::allocateGraphicsMemory();
scrollPeriod_ = startScrollTime_;
allocateSpritePoints();
}
void ScrollingList::freeGraphicsMemory()
{
Component::freeGraphicsMemory();
@ -612,8 +634,7 @@ void ScrollingList::deallocateTexture(unsigned int index)
if(s)
{
delete s;
components_.at(index) = NULL;
s->freeGraphicsMemory();
}
}
@ -704,7 +725,8 @@ void ScrollingList::scroll(bool forward)
ViewInfo *currentvi = scrollPoints_->at(i);
ViewInfo *nextvi = scrollPoints_->at(nextI);
resetTweens(c, tweenPoints_->at(nextI), currentvi, nextvi, scrollPeriod_);
resetTweens
(c, tweenPoints_->at(nextI), currentvi, nextvi, scrollPeriod_);
c->baseViewInfo.font = nextvi->font; // Use the font settings of the next index
c->triggerEvent( "menuScroll" );
}

View File

@ -74,6 +74,7 @@ public:
void setSelectedIndex(int selectedIndex);
Item *getItemByOffset(int offset);
Item *getSelectedItem();
void allocateGraphicsMemory();
void freeGraphicsMemory();
void update(float dt);
void draw();

View File

@ -38,12 +38,14 @@ Text::~Text()
void Text::freeGraphicsMemory()
{
Component::freeGraphicsMemory();
fontInst_->deInitialize();
}
void Text::allocateGraphicsMemory()
{
//todo: make the font blend color a parameter that is passed in
Component::allocateGraphicsMemory();
fontInst_->initialize();
}
void Text::setText(std::string text)

View File

@ -39,16 +39,6 @@ Video::Video(std::string file, std::string altFile, int numLoops, Page &p, float
allocateGraphicsMemory( );
}
void Video::launchEnter()
{
freeGraphicsMemory();
}
void Video::launchExit()
{
allocateGraphicsMemory();
}
Video::~Video( )
{
if (video_ != NULL)

View File

@ -28,8 +28,6 @@ public:
void update(float dt);
void freeGraphicsMemory( );
void allocateGraphicsMemory( );
void launchEnter();
void launchExit();
void draw( );
virtual bool isPlaying( );

View File

@ -82,14 +82,6 @@ void VideoComponent::freeGraphicsMemory()
Component::freeGraphicsMemory();
}
void VideoComponent::launchEnter()
{
freeGraphicsMemory();
}
void VideoComponent::launchExit()
{
allocateGraphicsMemory();
}
void VideoComponent::draw()
{

View File

@ -31,8 +31,6 @@ public:
void draw();
void freeGraphicsMemory();
void allocateGraphicsMemory();
void launchEnter();
void launchExit();
virtual bool isPlaying();
private:

View File

@ -21,8 +21,11 @@
#include <cstdio>
#include <cstring>
Font::Font()
Font::Font(std::string fontPath, int fontSize, SDL_Color color)
: texture(NULL)
, fontPath_(fontPath)
, fontSize_(fontSize)
, color_(color)
{
}
@ -60,9 +63,9 @@ bool Font::getRect(unsigned int charCode, GlyphInfo &glyph)
return false;
}
bool Font::initialize(std::string fontPath, int fontSize, SDL_Color color)
bool Font::initialize()
{
TTF_Font *font = TTF_OpenFont(fontPath.c_str(), fontSize);
TTF_Font *font = TTF_OpenFont(fontPath_.c_str(), fontSize_);
if (!font)
{
@ -84,8 +87,8 @@ bool Font::initialize(std::string fontPath, int fontSize, SDL_Color color)
GlyphInfoBuild *info = new GlyphInfoBuild;
memset(info, 0, sizeof(GlyphInfoBuild));
color.a = 255;
info->surface = TTF_RenderGlyph_Blended(font, i, color);
color_.a = 255;
info->surface = TTF_RenderGlyph_Blended(font, i, color_);
TTF_GlyphMetrics(font, i,
&info->glyph.minX, &info->glyph.maxX,
&info->glyph.minY, &info->glyph.maxY,

View File

@ -32,9 +32,9 @@ public:
SDL_Rect rect;
};
Font();
Font(std::string fontPath, int fontSize, SDL_Color color);
virtual ~Font();
bool initialize(std::string fontPath, int fontSize, SDL_Color color);
bool initialize();
void deInitialize();
SDL_Texture *getTexture();
bool getRect(unsigned int charCode, GlyphInfo &glyph);
@ -52,4 +52,7 @@ private:
int height;
int ascent;
std::map<unsigned int, GlyphInfoBuild *> atlas;
std::string fontPath_;
int fontSize_;
SDL_Color color_;
};

View File

@ -81,8 +81,8 @@ bool FontCache::loadFont(std::string fontPath, int fontSize, SDL_Color color)
if(it == fontFaceMap_.end())
{
Font *f = new Font();
f->initialize(fontPath, fontSize, color);
Font *f = new Font(fontPath, fontSize, color);
f->initialize();
fontFaceMap_[key] = f;
}

View File

@ -48,7 +48,7 @@ Page::~Page()
}
void Page::DeInitialize()
void Page::deInitialize()
{
MenuVector_T::iterator it = menus_.begin();
while(it != menus_.end())
@ -418,7 +418,7 @@ void Page::highlightEnter()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "highlightEnter", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -449,7 +449,7 @@ void Page::highlightExit()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "highlightExit", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -657,7 +657,7 @@ void Page::enterMenu()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "menuEnter", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -688,7 +688,7 @@ void Page::exitMenu()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "menuExit", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -719,7 +719,7 @@ void Page::enterGame()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "gameEnter", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -750,7 +750,7 @@ void Page::exitGame()
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{
ScrollingList *menu = *it2;
if(menuDepth_-1 == distance(menus_.begin(), it))
if(menuDepth_-1 == static_cast<unsigned int>(distance(menus_.begin(), it)))
{
// Also trigger animations for index i for active menu
menu->triggerEvent( "gameExit", MENU_INDEX_HIGH + menuDepth_ - 1 );
@ -1051,17 +1051,6 @@ void Page::allocateGraphicsMemory()
void Page::launchEnter()
{
for(std::vector<ScrollingList *>::iterator it = activeMenu_.begin(); it != activeMenu_.end(); it++)
{
ScrollingList *menu = *it;
if(menu) menu->launchEnter();
}
for(std::vector<Component *>::iterator it = LayerComponents.begin(); it != LayerComponents.end(); ++it)
{
(*it)->launchEnter();
}
if(selectSoundChunk_)
{
selectSoundChunk_->play();
@ -1069,21 +1058,6 @@ void Page::launchEnter()
}
void Page::launchExit()
{
for(std::vector<ScrollingList *>::iterator it = activeMenu_.begin(); it != activeMenu_.end(); it++)
{
ScrollingList *menu = *it;
if(menu) menu->launchExit();
}
for(std::vector<Component *>::iterator it = LayerComponents.begin(); it != LayerComponents.end(); ++it)
{
(*it)->launchExit();
}
}
void Page::reallocateMenuSpritePoints()
{
for(std::vector<ScrollingList *>::iterator it = activeMenu_.begin(); it != activeMenu_.end(); it++)

View File

@ -42,7 +42,7 @@ public:
Page(Configuration &c);
virtual ~Page();
void DeInitialize();
void deInitialize();
virtual void onNewItemSelected();
void highlightLoadArt();
bool pushCollection(CollectionInfo *collection);
@ -88,7 +88,6 @@ public:
void freeGraphicsMemory();
void allocateGraphicsMemory();
void launchEnter();
void launchExit();
std::string getCollectionName();
void setMinShowTime(float value);
float getMinShowTime();

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
*/
#pragma once
#include "Collection/Item.h"
#include "Control/UserInput.h"
#include "Database/DB.h"
@ -28,26 +29,30 @@
#include <stack>
#include <map>
class CollectionInfo;
class Configuration;
class Page;
class RetroFE
{
public:
RetroFE(Configuration &c);
virtual ~RetroFE();
bool deInitialize();
void run();
void freeGraphicsMemory();
void allocateGraphicsMemory();
void launchEnter();
void launchExit();
RetroFE( Configuration &c );
virtual ~RetroFE( );
bool deInitialize( );
void run( );
void freeGraphicsMemory( );
void allocateGraphicsMemory( );
void launchEnter( );
void launchExit( );
private:
volatile bool initialized;
volatile bool initializeError;
SDL_Thread *initializeThread;
static int initialize(void *context);
SDL_Thread *initializeThread;
static int initialize( void *context );
enum RETROFE_STATE
{
@ -65,7 +70,6 @@ private:
RETROFE_HIGHLIGHT_EXIT,
RETROFE_HIGHLIGHT_LOAD_ART,
RETROFE_HIGHLIGHT_ENTER,
RETROFE_HIGHLIGHT_MENU_IDLE,
RETROFE_NEXT_PAGE_REQUEST,
RETROFE_NEXT_PAGE_MENU_EXIT,
RETROFE_NEXT_PAGE_MENU_LOAD_ART,
@ -82,30 +86,31 @@ private:
RETROFE_QUIT,
};
void render();
bool back(bool &exit);
void quit();
Page *loadPage();
Page *loadSplashPage();
RETROFE_STATE processUserInput(Page *page);
void update(float dt, bool scrollActive);
std::string getLayout(std::string collectionName);
CollectionInfo *getCollection(std::string collectionName);
Configuration &config_;
DB *db_;
MetadataDatabase *metadb_;
UserInput input_;
Page *currentPage_;
void render( );
bool back( bool &exit );
void quit( );
Page *loadPage( );
Page *loadSplashPage( );
RETROFE_STATE processUserInput( Page *page );
void update( float dt, bool scrollActive );
CollectionInfo *getCollection( std::string collectionName );
Configuration &config_;
DB *db_;
MetadataDatabase *metadb_;
UserInput input_;
Page *currentPage_;
std::stack<Page *> pages_;
float keyInputDisable_;
float currentTime_;
float lastLaunchReturnTime_;
float keyLastTime_;
float keyDelayTime_;
Item *nextPageItem_;
FontCache fontcache_;
AttractMode attract_;
float keyInputDisable_;
float currentTime_;
float lastLaunchReturnTime_;
float keyLastTime_;
float keyDelayTime_;
Item *nextPageItem_;
FontCache fontcache_;
AttractMode attract_;
std::map<std::string, unsigned int> lastMenuOffsets_;
std::map<std::string, std::string> lastMenuPlaylists_;
std::map<std::string, std::string> lastMenuPlaylists_;
};

View File

@ -14,122 +14,125 @@
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SDL.h"
#include "Database/Configuration.h"
#include "Utility/Log.h"
#include <SDL2/SDL_mixer.h>
SDL_Window *SDL::window_ = NULL;
SDL_Renderer *SDL::renderer_ = NULL;
SDL_mutex *SDL::mutex_ = NULL;
int SDL::displayWidth_ = 0;
int SDL::displayHeight_ = 0;
int SDL::windowWidth_ = 0;
int SDL::windowHeight_ = 0;
bool SDL::fullscreen_ = false;
SDL_Window *SDL::window_ = NULL;
SDL_Renderer *SDL::renderer_ = NULL;
SDL_mutex *SDL::mutex_ = NULL;
int SDL::displayWidth_ = 0;
int SDL::displayHeight_ = 0;
int SDL::windowWidth_ = 0;
int SDL::windowHeight_ = 0;
bool SDL::fullscreen_ = false;
bool SDL::initialize(Configuration &config)
// Initialize SDL
bool SDL::initialize( Configuration &config )
{
bool retVal = true;
bool retVal = true;
std::string hString;
std::string vString;
Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
int audioRate = MIX_DEFAULT_FREQUENCY;
Uint16 audioFormat = MIX_DEFAULT_FORMAT; /* 16-bit stereo */
int audioChannels = 1;
int audioBuffers = 4096;
bool hideMouse;
Uint32 windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
int audioRate = MIX_DEFAULT_FREQUENCY;
Uint16 audioFormat = MIX_DEFAULT_FORMAT; /* 16-bit stereo */
int audioChannels = 1;
int audioBuffers = 4096;
bool hideMouse;
Logger::write(Logger::ZONE_INFO, "SDL", "Initializing");
if (retVal && SDL_Init(SDL_INIT_EVERYTHING) != 0)
Logger::write( Logger::ZONE_INFO, "SDL", "Initializing" );
if (retVal && SDL_Init( SDL_INIT_EVERYTHING ) != 0)
{
std::string error = SDL_GetError();
Logger::write(Logger::ZONE_ERROR, "SDL", "Initialize failed: " + error);
std::string error = SDL_GetError( );
Logger::write( Logger::ZONE_ERROR, "SDL", "Initialize failed: " + error );
retVal = false;
}
if(retVal && config.getProperty("hideMouse", hideMouse))
if ( retVal && config.getProperty( "hideMouse", hideMouse ) )
{
if(hideMouse)
if ( hideMouse )
{
SDL_ShowCursor(SDL_FALSE);
SDL_ShowCursor( SDL_FALSE );
}
else
{
SDL_ShowCursor(SDL_TRUE);
SDL_ShowCursor( SDL_TRUE );
}
}
// check for a few other necessary Configurations
if(retVal)
if ( retVal )
{
// Get current display mode of all displays.
for(int i = 0; i < SDL_GetNumVideoDisplays(); ++i)
for(int i = 0; i < SDL_GetNumVideoDisplays( ); ++i)
{
SDL_DisplayMode mode;
if(SDL_GetCurrentDisplayMode(i, &mode) == 0)
if ( SDL_GetCurrentDisplayMode( i, &mode ) == 0 )
{
displayWidth_ = mode.w;
displayWidth_ = mode.w;
displayHeight_ = mode.h;
break;
}
}
if(!config.getProperty("horizontal", hString))
if ( !config.getProperty( "horizontal", hString ) )
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Missing property \"horizontal\"");
Logger::write( Logger::ZONE_ERROR, "Configuration", "Missing property \"horizontal\"" );
retVal = false;
}
else if(hString == "stretch")
else if ( hString == "stretch" )
{
// Get current display mode of all displays.
for(int i = 0; i < SDL_GetNumVideoDisplays(); ++i)
for(int i = 0; i < SDL_GetNumVideoDisplays( ); ++i)
{
SDL_DisplayMode mode;
if(SDL_GetCurrentDisplayMode(i, &mode) == 0)
if ( SDL_GetCurrentDisplayMode( i, &mode ) == 0 )
{
windowWidth_ = mode.w;
break;
}
}
}
else if(!config.getProperty("horizontal", windowWidth_))
else if ( !config.getProperty( "horizontal", windowWidth_ ) )
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Invalid property value for \"horizontal\"");
Logger::write( Logger::ZONE_ERROR, "Configuration", "Invalid property value for \"horizontal\"" );
}
}
if(retVal)
if ( retVal )
{
if(!config.getProperty("vertical", vString))
if ( !config.getProperty( "vertical", vString ) )
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Missing property \"vertical\"");
Logger::write( Logger::ZONE_ERROR, "Configuration", "Missing property \"vertical\"" );
retVal = false;
}
else if(vString == "stretch")
else if ( vString == "stretch" )
{
// Get current display mode of all displays.
for(int i = 0; i < SDL_GetNumVideoDisplays(); ++i)
for(int i = 0; i < SDL_GetNumVideoDisplays( ); ++i)
{
SDL_DisplayMode mode;
if(SDL_GetDesktopDisplayMode(i, &mode) == 0)
if ( SDL_GetDesktopDisplayMode( i, &mode ) == 0 )
{
windowHeight_ = mode.h;
break;
}
}
}
else if(!config.getProperty("vertical", windowHeight_))
else if ( !config.getProperty( "vertical", windowHeight_ ) )
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Invalid property value for \"vertical\"");
Logger::write( Logger::ZONE_ERROR, "Configuration", "Invalid property value for \"vertical\"" );
}
}
if(retVal && !config.getProperty("fullscreen", fullscreen_))
if ( retVal && !config.getProperty( "fullscreen", fullscreen_ ) )
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Missing property: \"fullscreen\"");
Logger::write( Logger::ZONE_ERROR, "Configuration", "Missing property: \"fullscreen\"" );
retVal = false;
}
@ -142,133 +145,137 @@ bool SDL::initialize(Configuration &config)
#endif
}
if(retVal)
if ( retVal )
{
std::string fullscreenStr = fullscreen_ ? "yes" : "no";
std::stringstream ss;
ss << "Creating "<< windowWidth_ << "x" << windowHeight_ << " window (fullscreen: "
<< fullscreenStr << ")";
ss << "Creating "<< windowWidth_ << "x" << windowHeight_ << " window (fullscreen: " << fullscreenStr << ")";
Logger::write(Logger::ZONE_INFO, "SDL", ss.str());
Logger::write( Logger::ZONE_INFO, "SDL", ss.str( ));
window_ = SDL_CreateWindow("RetroFE",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
windowWidth_,
windowHeight_,
windowFlags);
window_ = SDL_CreateWindow( "RetroFE", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth_, windowHeight_, windowFlags );
if (window_ == NULL)
if ( window_ == NULL )
{
std::string error = SDL_GetError();
Logger::write(Logger::ZONE_ERROR, "SDL", "Create window failed: " + error);
std::string error = SDL_GetError( );
Logger::write( Logger::ZONE_ERROR, "SDL", "Create window failed: " + error );
retVal = false;
}
}
if(retVal)
if ( retVal )
{
renderer_ = SDL_CreateRenderer(window_,
-1,
SDL_RENDERER_ACCELERATED);
renderer_ = SDL_CreateRenderer( window_, -1, SDL_RENDERER_ACCELERATED );
if (renderer_ == NULL)
if ( renderer_ == NULL )
{
std::string error = SDL_GetError();
Logger::write(Logger::ZONE_ERROR, "SDL", "Create renderer failed: " + error);
std::string error = SDL_GetError( );
Logger::write( Logger::ZONE_ERROR, "SDL", "Create renderer failed: " + error );
retVal = false;
}
}
if(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1") != SDL_TRUE)
if ( SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1") != SDL_TRUE )
{
Logger::write(Logger::ZONE_ERROR, "SDL", "Improve scale quality. Continuing with low-quality settings.");
Logger::write( Logger::ZONE_ERROR, "SDL", "Improve scale quality. Continuing with low-quality settings." );
}
bool minimize_on_focus_loss_;
if(config.getProperty("minimize_on_focus_loss", minimize_on_focus_loss_))
if ( config.getProperty( "minimize_on_focus_loss", minimize_on_focus_loss_ ) )
{
if(minimize_on_focus_loss_)
if ( minimize_on_focus_loss_ )
{
SDL_SetHintWithPriority(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1", SDL_HINT_OVERRIDE);
SDL_SetHintWithPriority( SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1", SDL_HINT_OVERRIDE );
}
else
{
SDL_SetHintWithPriority(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0", SDL_HINT_OVERRIDE);
SDL_SetHintWithPriority( SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0", SDL_HINT_OVERRIDE );
}
}
if(retVal)
if ( retVal )
{
mutex_ = SDL_CreateMutex();
mutex_ = SDL_CreateMutex( );
if (mutex_ == NULL)
if ( mutex_ == NULL )
{
std::string error = SDL_GetError();
Logger::write(Logger::ZONE_ERROR, "SDL", "Mutex creation failed: " + error);
std::string error = SDL_GetError( );
Logger::write( Logger::ZONE_ERROR, "SDL", "Mutex creation failed: " + error );
retVal = false;
}
}
//todo: specify in configuration file
if (retVal && Mix_OpenAudio(audioRate, audioFormat, audioChannels, audioBuffers) == -1)
if ( retVal && Mix_OpenAudio( audioRate, audioFormat, audioChannels, audioBuffers ) == -1 )
{
std::string error = Mix_GetError();
Logger::write(Logger::ZONE_ERROR, "SDL", "Audio initialize failed: " + error);
std::string error = Mix_GetError( );
Logger::write( Logger::ZONE_ERROR, "SDL", "Audio initialize failed: " + error );
retVal = false;
}
return retVal;
}
bool SDL::deInitialize()
{
std::string error = SDL_GetError();
Logger::write(Logger::ZONE_INFO, "SDL", "DeInitializing");
Mix_CloseAudio();
Mix_Quit();
if(mutex_)
// Deinitialize SDL
bool SDL::deInitialize( )
{
std::string error = SDL_GetError( );
Logger::write( Logger::ZONE_INFO, "SDL", "DeInitializing" );
Mix_CloseAudio( );
Mix_Quit( );
if ( mutex_ )
{
SDL_DestroyMutex(mutex_);
mutex_ = NULL;
}
if(renderer_)
if ( renderer_ )
{
SDL_DestroyRenderer(renderer_);
renderer_ = NULL;
}
if(window_)
if ( window_ )
{
SDL_DestroyWindow(window_);
window_ = NULL;
}
SDL_ShowCursor(SDL_TRUE);
SDL_ShowCursor( SDL_TRUE );
SDL_Quit();
SDL_Quit( );
return true;
}
SDL_Renderer* SDL::getRenderer()
// Get the renderer
SDL_Renderer* SDL::getRenderer( )
{
return renderer_;
}
SDL_mutex* SDL::getMutex()
// Get the mutex
SDL_mutex* SDL::getMutex( )
{
return mutex_;
}
SDL_Window* SDL::getWindow()
// Get the window
SDL_Window* SDL::getWindow( )
{
return window_;
}
bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo)
// Render a copy of a texture
bool SDL::renderCopy( SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo )
{
SDL_Rect srcRect;
@ -281,7 +288,7 @@ bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect
dstRect.w = dest->w;
dstRect.h = dest->h;
if(fullscreen_)
if ( fullscreen_ )
{
dstRect.x = dest->x + (displayWidth_ - windowWidth_)/2;
dstRect.y = dest->y + (displayHeight_ - windowHeight_)/2;
@ -312,8 +319,8 @@ bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect
}
// Define the scale
scaleX = (dstRect.w > 0) ? static_cast<double>(srcRect.w) / static_cast<double>(dstRect.w) : 0.0;
scaleY = (dstRect.h > 0) ? static_cast<double>(srcRect.h) / static_cast<double>(dstRect.h) : 0.0;
scaleX = (dstRect.w > 0) ? static_cast<double>( srcRect.w ) / static_cast<double>( dstRect.w ) : 0.0;
scaleY = (dstRect.h > 0) ? static_cast<double>( srcRect.h ) / static_cast<double>( dstRect.h ) : 0.0;
// Make a copy
srcRectCopy.x = srcRect.x;
@ -326,77 +333,77 @@ bool SDL::renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect
dstRectCopy.h = dstRect.h;
// If a container has been defined, limit the display to the container boundaries.
if (viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0 &&
dstRectCopy.w > 0 && dstRectCopy.h > 0)
if ( viewInfo.ContainerWidth > 0 && viewInfo.ContainerHeight > 0 &&
dstRectCopy.w > 0 && dstRectCopy.h > 0 )
{
// Correct if the image falls to the left of the container
if (dstRect.x < viewInfo.ContainerX)
if ( dstRect.x < viewInfo.ContainerX )
{
dstRect.x = static_cast<int>(viewInfo.ContainerX);
dstRect.x = static_cast<int>( viewInfo.ContainerX );
dstRect.w = dstRectCopy.w + dstRectCopy.x - dstRect.x;
srcRect.x = srcRectCopy.x + srcRectCopy.w * (dstRect.x - dstRectCopy.x) / dstRectCopy.w;
}
// Correct if the image falls to the right of the container
if ((dstRectCopy.x + dstRectCopy.w) > (viewInfo.ContainerX + viewInfo.ContainerWidth))
if ( (dstRectCopy.x + dstRectCopy.w) > (viewInfo.ContainerX + viewInfo.ContainerWidth) )
{
dstRect.w = static_cast<int>(viewInfo.ContainerX + viewInfo.ContainerWidth) - dstRect.x;
dstRect.w = static_cast<int>( viewInfo.ContainerX + viewInfo.ContainerWidth ) - dstRect.x;
}
// Correct if the image falls to the top of the container
if (dstRect.y < viewInfo.ContainerY)
if ( dstRect.y < viewInfo.ContainerY )
{
dstRect.y = static_cast<int>(viewInfo.ContainerY);
dstRect.y = static_cast<int>( viewInfo.ContainerY );
dstRect.h = dstRectCopy.h + dstRectCopy.y - dstRect.y;
srcRect.y = srcRectCopy.y + srcRectCopy.h * (dstRect.y - dstRectCopy.y) / dstRectCopy.h;
}
// Correct if the image falls to the bottom of the container
if ((dstRectCopy.y + dstRectCopy.h) > (viewInfo.ContainerY + viewInfo.ContainerHeight))
if ( (dstRectCopy.y + dstRectCopy.h) > (viewInfo.ContainerY + viewInfo.ContainerHeight) )
{
dstRect.h = static_cast<int>(viewInfo.ContainerY + viewInfo.ContainerHeight) - dstRect.y;
dstRect.h = static_cast<int>( viewInfo.ContainerY + viewInfo.ContainerHeight ) - dstRect.y;
}
// Define source width and height
srcRect.w = static_cast<int>(dstRect.w * scaleX);
srcRect.h = static_cast<int>(dstRect.h * scaleY);
srcRect.w = static_cast<int>( dstRect.w * scaleX );
srcRect.h = static_cast<int>( dstRect.h * scaleY );
}
SDL_SetTextureAlphaMod(texture, static_cast<char>(alpha * 255));
SDL_RenderCopyEx(getRenderer(), texture, &srcRect, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_NONE);
SDL_SetTextureAlphaMod( texture, static_cast<char>( alpha * 255 ) );
SDL_RenderCopyEx( getRenderer( ), texture, &srcRect, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_NONE );
if (viewInfo.Reflection == "top")
if ( viewInfo.Reflection == "top" )
{
dstRect.h = static_cast<unsigned int>(static_cast<float>(dstRect.h) * viewInfo.ReflectionScale);
dstRect.h = static_cast<unsigned int>( static_cast<float>(dstRect.h ) * viewInfo.ReflectionScale);
dstRect.y = dstRect.y - dstRect.h - viewInfo.ReflectionDistance;
SDL_SetTextureAlphaMod(texture, static_cast<char>(viewInfo.ReflectionAlpha * alpha * 255));
SDL_RenderCopyEx(getRenderer(), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL);
SDL_SetTextureAlphaMod( texture, static_cast<char>( viewInfo.ReflectionAlpha * alpha * 255 ) );
SDL_RenderCopyEx( getRenderer( ), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL );
}
if (viewInfo.Reflection == "bottom")
if ( viewInfo.Reflection == "bottom" )
{
dstRect.y = dstRect.y + dstRect.h + viewInfo.ReflectionDistance;
dstRect.h = static_cast<unsigned int>(static_cast<float>(dstRect.h) * viewInfo.ReflectionScale);
SDL_SetTextureAlphaMod(texture, static_cast<char>(viewInfo.ReflectionAlpha * alpha * 255));
SDL_RenderCopyEx(getRenderer(), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL);
dstRect.h = static_cast<unsigned int>( static_cast<float>(dstRect.h ) * viewInfo.ReflectionScale);
SDL_SetTextureAlphaMod( texture, static_cast<char>( viewInfo.ReflectionAlpha * alpha * 255 ) );
SDL_RenderCopyEx( getRenderer( ), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_VERTICAL );
}
if (viewInfo.Reflection == "left")
if ( viewInfo.Reflection == "left" )
{
dstRect.w = static_cast<unsigned int>(static_cast<float>(dstRect.w) * viewInfo.ReflectionScale);
dstRect.w = static_cast<unsigned int>( static_cast<float>(dstRect.w ) * viewInfo.ReflectionScale);
dstRect.x = dstRect.x - dstRect.w - viewInfo.ReflectionDistance;
SDL_SetTextureAlphaMod(texture, static_cast<char>(viewInfo.ReflectionAlpha * alpha * 255));
SDL_RenderCopyEx(getRenderer(), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL);
SDL_SetTextureAlphaMod( texture, static_cast<char>( viewInfo.ReflectionAlpha * alpha * 255 ) );
SDL_RenderCopyEx( getRenderer( ), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL );
}
if (viewInfo.Reflection == "right")
if ( viewInfo.Reflection == "right" )
{
dstRect.x = dstRect.x + dstRect.w + viewInfo.ReflectionDistance;
dstRect.w = static_cast<unsigned int>(static_cast<float>(dstRect.w) * viewInfo.ReflectionScale);
SDL_SetTextureAlphaMod(texture, static_cast<char>(viewInfo.ReflectionAlpha * alpha * 255));
SDL_RenderCopyEx(getRenderer(), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL);
dstRect.w = static_cast<unsigned int>( static_cast<float>(dstRect.w ) * viewInfo.ReflectionScale);
SDL_SetTextureAlphaMod( texture, static_cast<char>( viewInfo.ReflectionAlpha * alpha * 255 ) );
SDL_RenderCopyEx( getRenderer( ), texture, src, &dstRect, viewInfo.Angle, NULL, SDL_FLIP_HORIZONTAL );
}
return true;

View File

@ -14,42 +14,45 @@
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <SDL2/SDL.h>
#include <string>
#include "Graphics/ViewInfo.h"
// todo: this wrapper could be cleaned up
class Configuration;
class SDL
{
public:
static bool initialize(Configuration &config);
static bool deInitialize();
static SDL_Renderer *getRenderer();
static SDL_mutex *getMutex();
static SDL_Window *getWindow();
static bool renderCopy(SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo);
static int getWindowWidth()
static bool initialize( Configuration &config );
static bool deInitialize( );
static SDL_Renderer *getRenderer( );
static SDL_mutex *getMutex( );
static SDL_Window *getWindow( );
static bool renderCopy( SDL_Texture *texture, float alpha, SDL_Rect *src, SDL_Rect *dest, ViewInfo &viewInfo );
static int getWindowWidth( )
{
return windowWidth_;
}
static int getWindowHeight()
static int getWindowHeight( )
{
return windowHeight_;
}
static bool isFullscreen()
static bool isFullscreen( )
{
return fullscreen_;
}
private:
static SDL_Window *window_;
static SDL_Window *window_;
static SDL_Renderer *renderer_;
static SDL_mutex *mutex_;
static int displayWidth_;
static int displayHeight_;
static int windowWidth_;
static int windowHeight_;
static bool fullscreen_;
static SDL_mutex *mutex_;
static int displayWidth_;
static int displayHeight_;
static int windowWidth_;
static int windowHeight_;
static bool fullscreen_;
};

View File

@ -14,16 +14,17 @@
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Version.h"
#include <string>
std::string retrofe_version_major = "0";
std::string retrofe_version_minor = "8";
std::string retrofe_version_build = "7";
std::string retrofe_version_build = "8";
std::string Version::getString()
std::string Version::getString( )
{
std::string return_string = retrofe_version_major + "." + retrofe_version_minor + "." + retrofe_version_build;
return return_string;

View File

@ -15,10 +15,12 @@
*/
#pragma once
#include <string>
class Version
{
public:
static std::string getString();
static std::string getString( );
};