diff --git a/.gitignore b/.gitignore
index 4d087d107..063da9dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,13 +14,18 @@
# Dependency makefiles
*.d
-#Compiled executable
+# Compiled executable
emulationstation
-#build directory
-EmulationStation_vs2010
+# build directory
build
Debug
Release
MinSizeRel
-RelWithDebInfo
\ No newline at end of file
+RelWithDebInfo
+
+# CMake
+CMakeCache.txt
+CMakeFiles
+cmake_install.cmake
+Makefile
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba96dd160..ab88f5c13 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,7 +117,7 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/FolderData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Font.h
${CMAKE_CURRENT_SOURCE_DIR}/src/GameData.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/Gui.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/GuiComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.h
${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.h
${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.h
@@ -125,21 +125,28 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/MathExp.h
${CMAKE_CURRENT_SOURCE_DIR}/src/platform.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/Vector2.h
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.h
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiAnimation.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentListComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextListComponent.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiImage.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiList.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.h
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiTheme.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.h
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugiconfig.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.hpp
${CMAKE_CURRENT_SOURCE_DIR}/data/Resources.h
@@ -149,7 +156,7 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/FolderData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Font.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/GameData.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/Gui.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/GuiComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.cpp
@@ -159,21 +166,26 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/platform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer_draw_gl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer_init.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiAnimation.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimationComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ComponentListComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ThemeComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiBox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiDetectDevice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiImage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.cpp
-# ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiList.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiTheme.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.cpp
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_16.cpp
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_32.cpp
diff --git a/EmulationStation_vs2010/EmulationStation_vs2010.sln b/EmulationStation_vs2010/EmulationStation_vs2010.sln
deleted file mode 100644
index 2e2783b31..000000000
--- a/EmulationStation_vs2010/EmulationStation_vs2010.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmulationStation_vs2010", "EmulationStation_vs2010\EmulationStation_vs2010.vcxproj", "{0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}.Debug|Win32.Build.0 = Debug|Win32
- {0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}.Release|Win32.ActiveCfg = Release|Win32
- {0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj b/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj
deleted file mode 100644
index d29e27a3d..000000000
--- a/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
- {0AB5C397-7B64-4AAD-92AD-E6B72FEDE8C3}
- EmulationStation_vs2010
-
-
-
- Application
- true
- MultiByte
-
-
- Application
- false
- true
- MultiByte
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Level3
- Disabled
-
-
- true
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- USE_OPENGL_DESKTOP;%(PreprocessorDefinitions)
-
-
- true
- true
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj.filters b/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj.filters
deleted file mode 100644
index 4be1df7e5..000000000
--- a/EmulationStation_vs2010/EmulationStation_vs2010/EmulationStation_vs2010.vcxproj.filters
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
- {31a8e8d1-9795-42bf-99fd-500e57ac87d4}
-
-
- {bec1ca52-69f2-42eb-b134-57016057661a}
-
-
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- Source Files
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- PugiXML
-
-
- Source Files
-
-
- Source Files
-
-
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- components
-
-
- PugiXML
-
-
- PugiXML
-
-
-
\ No newline at end of file
diff --git a/EmulationStation_vs2010/EmulationStation_vs2010/lib_paths.props b/EmulationStation_vs2010/EmulationStation_vs2010/lib_paths.props
deleted file mode 100644
index 4b9b5bf1d..000000000
--- a/EmulationStation_vs2010/EmulationStation_vs2010/lib_paths.props
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
- $(IncludePath)
- $(LibraryPath)
-
-
-
- _DESKTOP_;%(PreprocessorDefinitions)
-
-
- SDLmain.lib;SDL.lib;FreeImage.lib;freetype.lib;opengl32.lib;%(AdditionalDependencies)
- Windows
-
-
-
-
\ No newline at end of file
diff --git a/Makefile b/Makefile
deleted file mode 100644
index f64e41ea6..000000000
--- a/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-CPPFLAGS=-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -I/usr/include/freetype2 -I/usr/include/SDL -D_RPI_
-LIBS=-L/opt/vc/lib -lbcm_host -lEGL -lGLESv2 -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage -lSDL_mixer
-
-include Makefile.common
diff --git a/Makefile.common b/Makefile.common
deleted file mode 100644
index 15ec7a98c..000000000
--- a/Makefile.common
+++ /dev/null
@@ -1,25 +0,0 @@
-CXX=g++
-CXXFLAGS=-Wall -g -O2
-LDFLAGS=
-
-SRC_SOURCES=platform.cpp AudioManager.cpp Window.cpp InputConfig.cpp Log.cpp FolderData.cpp Font.cpp GameData.cpp Gui.cpp InputManager.cpp main.cpp MathExp.cpp Renderer_draw_gl.cpp Renderer_init.cpp Sound.cpp SystemData.cpp XMLReader.cpp components/GuiAnimation.cpp components/GuiBox.cpp components/GuiFastSelect.cpp components/GuiGameList.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp components/GuiInputConfig.cpp components/GuiDetectDevice.cpp pugiXML/pugixml.cpp
-SOURCES=$(addprefix src/,$(SRC_SOURCES))
-OBJECTS=$(SOURCES:.cpp=.o)
-DEPS=$(SOURCES:.cpp=.d)
-EXECUTABLE=emulationstation
-
-all: $(EXECUTABLE)
-
-$(EXECUTABLE): $(DEPS) $(OBJECTS)
- $(CXX) -o $@ $(LDFLAGS) $(OBJECTS) $(LIBS)
-
-include $(wildcard src/*.d src/components/*.d src/pugiXML/*.d)
-
-%.d: %.cpp
- $(SHELL) -ec '$(CXX) -M $(CPPFLAGS) $< | tr -d "\\\\\n" | sed -e "s|$(*F).o|$(*D)/& $@|" -e "s|: \(.*\)|: \$$\(wildcard \1\)|" > $@'
-
-.PHONY: clean
-
-clean:
- rm -f src/*.[do] src/components/*.[do] src/pugiXML/*.[do] $(EXECUTABLE)
-
diff --git a/Makefile.x86 b/Makefile.x86
deleted file mode 100644
index 1217a1f00..000000000
--- a/Makefile.x86
+++ /dev/null
@@ -1,4 +0,0 @@
-CPPFLAGS=-I/usr/include/freetype2 -I/usr/include/SDL -D_DESKTOP_
-LIBS=-lGL -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage -lSDL_mixer
-
-include Makefile.common
diff --git a/README.md b/README.md
index 9b9b5868f..5a1700639 100644
--- a/README.md
+++ b/README.md
@@ -1,44 +1,54 @@
EmulationStation
================
-A graphical front-end for emulators with controller navigation. Developed for the Raspbery Pi, but runs on most Linux systems.
+A cross-platform graphical front-end for emulators with controller navigation.
-A cool guy named petrockblog made a script which automatically installs RetroArch, its cores, and ES. It also includes options for configuring your RPi and setting it up to boot directly into ES. You can find it here: https://github.com/petrockblog/RetroPie-Setup
+**Raspberry Pi users:**
+A cool guy named petrockblog made a script which automatically installs many emulators and ES. It also includes options for configuring your RPi and setting it up to boot directly into ES. You can find it here: https://github.com/petrockblog/RetroPie-Setup
Building
========
-**On the Raspberry Pi:**
+EmulationStation uses some C++11 code, which means you'll need to install at least g++-4.7 on Linux, or VS2010 on Windows.
-EmulationStation has a few dependencies. For building, you'll need SDL 1.2, SDL_mixer, FreeImage, FreeType, and Boost.Filesystem, which can easily be obtained with apt-get:
+EmulationStation has a few dependencies. For building, you'll need SDL 1.2, Boost.System, Boost.Filesystem, FreeImage, FreeType, and the DejaVu TrueType font.
+
+**On Linux:**
+All of this be easily installed with apt-get:
```
sudo apt-get install libsdl1.2-dev libboost-system-dev libboost-filesystem-dev libfreeimage-dev libfreetype6-dev ttf-dejavu
```
-There are also a few libraries already on the RPi (located in /opt/vc/, like the Broadcom libraries, EGL, and GLES). You can build EmulationStation by simply running `make`.
-
-
-**On something else (desktop):**
-
-EmulationStation can also be built on a "normal" Linux system. You'll need the same libraries listed above:
-```
-sudo apt-get install libsdl1.2-dev libboost-system-dev libboost-filesystem-dev libfreeimage-dev libfreetype6-dev ttf-dejavu
-```
-
-You'll also need OpenGL. I you don't have `/usr/include/GL/gl.h` and `libGL` try installing the MESA development package with:
+On "desktop" Linux (that is, *not* the Raspberry Pi), you'll also need OpenGL. Try installing the MESA development package with:
```
sudo apt-get libgl1-mesa-dev
```
-You can build with `make -f Makefile.x86` (badly named Makefile, I know). For some reason it doesn't seem to run with X closed on desktop.
+On the Raspberry Pi, there are also a few special libraries, located in /opt/vc/: the Broadcom libraries, libEGL, and GLES. You shouldn't need to install them.
-
-**Via CMake:**
-
+**Generate and Build Makefile with CMake:**
+```
cd EmulationStation
cmake .
make
-
+```
+
+**On Windows:**
+
+[Boost](http://www.boost.org/users/download/) (you'll need to compile for Boost.Filesystem)
+
+[FreeImage](http://downloads.sourceforge.net/freeimage/FreeImage3154Win32.zip)
+
+[FreeType2](http://download.savannah.gnu.org/releases/freetype/freetype-2.4.9.tar.bz2) (you'll need to compile)
+
+[SDL-1.2](http://www.libsdl.org/release/SDL-devel-1.2.15-VC.zip)
+
+(remember to copy necessary .DLLs into the same folder as the executable: FreeImage.dll, freetype6.dll, SDL.dll, and zlib1.dll)
+
+[CMake](http://www.cmake.org/cmake/resources/software.html) (this is used for generating the Visual Studio project)
+
+(If you don't know how to use CMake, here are some hints: run CMake-gui and point it at your EmulationStation folder. Point the "build" directory somewhere - I use EmulationStation/build. Click configure, choose "Visual Studio 2010 Project", fill in red fields as they appear, then click Generate.)
+
Configuring
===========
@@ -97,10 +107,12 @@ The COMMAND is the shell command ES will execute to start your emulator. As it i
The following "tags" are replaced by ES in COMMANDs:
-`%ROM%` - Replaced with absolute path to the selected ROM.
+`%ROM%` - Replaced with absolute path to the selected ROM, with most Bash special characters escaped with a backslash.
`%BASENAME%` - Replaced with the "base" name of the path to the selected ROM. For example, a path of "/foo/bar.rom", this tag would be "bar". This tag is useful for setting up AdvanceMAME.
+`%ROM_RAW%` - Replaced with the unescaped absolute path to the selected ROM. If your emulator is picky about paths, you might want to use this instead of %ROM%, but enclosed in quotes.
+
gamelist.xml
============
diff --git a/src/AudioManager.cpp b/src/AudioManager.cpp
index 9f68dde8d..47887ede7 100644
--- a/src/AudioManager.cpp
+++ b/src/AudioManager.cpp
@@ -23,7 +23,7 @@ void AudioManager::mixAudio(void *unused, Uint8 *stream, int len)
{
//calculate rest length of current sample
Uint32 restLength = (sound->getLength() - sound->getPosition());
- if (restLength > len) {
+ if (restLength > (Uint32)len) {
//if stream length is smaller than smaple lenght, clip it
restLength = len;
}
diff --git a/src/EmulationStation.h b/src/EmulationStation.h
index 9420daa8c..5c5f8640b 100644
--- a/src/EmulationStation.h
+++ b/src/EmulationStation.h
@@ -4,9 +4,9 @@
// Do this version number update as the very last commit for the new release version.
#define PROGRAM_VERSION_MAJOR 1
#define PROGRAM_VERSION_MINOR 0
-#define PROGRAM_VERSION_MAINTENANCE 0
+#define PROGRAM_VERSION_MAINTENANCE 1
#define PROGRAM_VERSION_REVISION 0
-#define PROGRAM_VERSION_STRING "1.0.0.0 - built " __DATE__ " - " __TIME__
-#define RESOURCE_VERSION_STRING "1,0,0,0\0"
+#define PROGRAM_VERSION_STRING "1.0.1.0 - built " __DATE__ " - " __TIME__
+#define RESOURCE_VERSION_STRING "1,0,1,0\0"
#define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE,PROGRAM_VERSION_REVISION
diff --git a/src/FolderData.cpp b/src/FolderData.cpp
index 8d0d43596..2bc937cca 100644
--- a/src/FolderData.cpp
+++ b/src/FolderData.cpp
@@ -37,7 +37,9 @@ bool filesort(FileData* file1, FileData* file2)
std::string name1 = file1->getName();
std::string name2 = file2->getName();
- for(unsigned int i = 0; i < name1.length(); i++)
+ //min of name1/name2 .length()s
+ unsigned int count = name1.length() > name2.length() ? name2.length() : name1.length();
+ for(unsigned int i = 0; i < count; i++)
{
if(toupper(name1[i]) != toupper(name2[i]))
{
diff --git a/src/Font.cpp b/src/Font.cpp
index 02eff9d3b..f085c7586 100644
--- a/src/Font.cpp
+++ b/src/Font.cpp
@@ -5,6 +5,7 @@
#include "Renderer.h"
#include
#include "Log.h"
+#include "Vector2.h"
FT_Library Font::sLibrary;
bool Font::libraryInitialized = false;
@@ -199,7 +200,7 @@ void Font::buildAtlas()
if((y + maxHeight) >= textureHeight)
{
//failed to create a proper font texture
- LOG(LogError) << "Error - font with size " << mSize << " exceeded texture size! Trying again...";
+ LOG(LogWarning) << "Font with size " << mSize << " exceeded max texture size! Trying again...";
//try a 3/4th smaller size and redo initialization
fontScale *= 1.25f;
mSize = (int)(mSize * (1.0f / fontScale));
@@ -207,10 +208,8 @@ void Font::buildAtlas()
init();
}
else {
- LOG(LogInfo) << "Created font with size " << mSize << std::endl;
+ LOG(LogInfo) << "Created font with size " << mSize << ".";
}
-
- //std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl;
}
Font::~Font()
@@ -220,33 +219,10 @@ Font::~Font()
}
-
-//why these aren't in an array:
-//openGL reads these in the order they are in memory
-//if I use an array, it will be 4 x values then 4 y values
-//it'll read XX, XX, YY instead of XY, XY, XY
-//...
-//that was the thinking at the time and honestly an array would have been smarter wow I'm dumb
-struct point {
- GLfloat pos0x;
- GLfloat pos0y;
-
- GLfloat pos1x;
- GLfloat pos1y;
-
- GLfloat pos2x;
- GLfloat pos2y;
-};
-
-struct tex {
- GLfloat tex0x;
- GLfloat tex0y;
-
- GLfloat tex1x;
- GLfloat tex1y;
-
- GLfloat tex2x;
- GLfloat tex2y;
+struct Vertex
+{
+ Vector2 pos;
+ Vector2 tex;
};
void Font::drawText(std::string text, int startx, int starty, int color)
@@ -257,10 +233,9 @@ void Font::drawText(std::string text, int startx, int starty, int color)
return;
}
- int pointCount = text.length() * 2;
- point* points = new point[pointCount];
- tex* texs = new tex[pointCount];
- GLubyte* colors = new GLubyte[pointCount * 3 * 4];
+ const int triCount = text.length() * 2;
+ Vertex* vert = new Vertex[triCount * 3];
+ GLubyte* colors = new GLubyte[triCount * 3 * 4];
glBindTexture(GL_TEXTURE_2D, textureID);
glEnable(GL_TEXTURE_2D);
@@ -274,58 +249,51 @@ void Font::drawText(std::string text, int startx, int starty, int color)
float x = (float)startx;
float y = starty + mMaxGlyphHeight * 1.1f * fontScale; //padding (another 0.5% is added to the bottom through the sizeText function)
- int p = 0;
- for(int i = 0; p < pointCount; i++, p++)
+ int charNum = 0;
+ for(int i = 0; i < triCount * 3; i += 6, charNum++)
{
- unsigned char letter = text[i];
+ unsigned char letter = text[charNum];
if(letter < 32 || letter >= 128)
letter = 127; //print [X] if character is not standard ASCII
- points[p].pos0x = x;
- points[p].pos0y = y + (charData[letter].texH - charData[letter].bearingY) * fontScale;
- points[p].pos1x = x + charData[letter].texW * fontScale;
- points[p].pos1y = y - charData[letter].bearingY * fontScale;
- points[p].pos2x = x;
- points[p].pos2y = points[p].pos1y;
+ //order is bottom left, top right, top left
+ vert[i + 0].pos = Vector2(x, y + (charData[letter].texH - charData[letter].bearingY) * fontScale);
+ vert[i + 1].pos = Vector2(x + charData[letter].texW * fontScale, y - charData[letter].bearingY * fontScale);
+ vert[i + 2].pos = Vector2(x, vert[i + 1].pos.y);
- texs[p].tex0x = charData[letter].texX / tw;
- texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
- texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw;
- texs[p].tex1y = charData[letter].texY / th;
- texs[p].tex2x = texs[p].tex0x;
- texs[p].tex2y = texs[p].tex1y;
+ Vector2 charTexCoord(charData[letter].texX, charData[letter].texY);
+ Vector2 charTexSize(charData[letter].texW, charData[letter].texH);
- p++;
+ vert[i + 0].tex = Vector2(charTexCoord.x / tw, (charTexCoord.y + charTexSize.y) / th);
+ vert[i + 1].tex = Vector2((charTexCoord.x + charTexSize.x) / tw, charTexCoord.y / th);
+ vert[i + 2].tex = Vector2(vert[i + 0].tex.x, vert[i + 1].tex.y);
- points[p].pos0x = points[p-1].pos0x;
- points[p].pos0y = points[p-1].pos0y;
- points[p].pos1x = points[p-1].pos1x;
- points[p].pos1y = points[p-1].pos1y;
- points[p].pos2x = points[p-1].pos1x;
- points[p].pos2y = points[p-1].pos0y;
+ //next triangle (second half of the quad)
+ vert[i + 3].pos = vert[i + 0].pos;
+ vert[i + 4].pos = vert[i + 1].pos;
+ vert[i + 5].pos.x = vert[i + 1].pos.x;
+ vert[i + 5].pos.y = vert[i + 0].pos.y;
- texs[p].tex0x = texs[p-1].tex0x;
- texs[p].tex0y = texs[p-1].tex0y;
- texs[p].tex1x = texs[p-1].tex1x;
- texs[p].tex1y = texs[p-1].tex1y;
- texs[p].tex2x = texs[p-1].tex1x;
- texs[p].tex2y = texs[p-1].tex0y;
+ vert[i + 3].tex = vert[i + 0].tex;
+ vert[i + 4].tex = vert[i + 1].tex;
+ vert[i + 5].tex.x = vert[i + 1].tex.x;
+ vert[i + 5].tex.y = vert[i + 0].tex.y;
x += charData[letter].advX * fontScale;
}
- Renderer::buildGLColorArray(colors, color, pointCount * 3);
+ Renderer::buildGLColorArray(colors, color, triCount * 3);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
- glTexCoordPointer(2, GL_FLOAT, 0, texs);
+ glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vert[0].pos);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert[0].tex);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
- glDrawArrays(GL_TRIANGLES, 0, pointCount * 3);
+ glDrawArrays(GL_TRIANGLES, 0, triCount * 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -334,14 +302,13 @@ void Font::drawText(std::string text, int startx, int starty, int color)
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- delete[] points;
- delete[] texs;
+ delete[] vert;
delete[] colors;
}
void Font::sizeText(std::string text, int* w, int* h)
{
- int cwidth = 0;
+ float cwidth = 0.0f;
for(unsigned int i = 0; i < text.length(); i++)
{
unsigned char letter = text[i];
@@ -352,10 +319,10 @@ void Font::sizeText(std::string text, int* w, int* h)
}
if(w != NULL)
- *w = cwidth;
+ *w = (int)cwidth;
if(h != NULL)
- *h = (int)(mMaxGlyphHeight * 1.5f * fontScale);
+ *h = getHeight();
}
int Font::getHeight()
diff --git a/src/GameData.cpp b/src/GameData.cpp
index b6d981fbd..bb656be01 100644
--- a/src/GameData.cpp
+++ b/src/GameData.cpp
@@ -22,6 +22,7 @@ std::string GameData::getBashPath()
{
//a quick and dirty way to insert a backslash before most characters that would mess up a bash path
std::string path = mPath;
+
const char* invalidChars = " '\"\\!$^&*(){}[]?;<>";
for(unsigned int i = 0; i < path.length(); i++)
{
diff --git a/src/Gui.cpp b/src/Gui.cpp
deleted file mode 100644
index b36053d3a..000000000
--- a/src/Gui.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "Gui.h"
-#include "Window.h"
-
-Gui::Gui(Window* window) : mWindow(window)
-{
-}
-
-Gui::~Gui()
-{
- mWindow->removeGui(this);
-}
-
-void Gui::setOffset(int x, int y) { mOffsetX = x; mOffsetY = y; }
-void Gui::setOffsetX(int x) { mOffsetX = x; }
-void Gui::setOffsetY(int y) { mOffsetY = y; }
-int Gui::getOffsetX() { return mOffsetX; }
-int Gui::getOffsetY() { return mOffsetY; }
diff --git a/src/Gui.h b/src/Gui.h
deleted file mode 100644
index d8ba72dd8..000000000
--- a/src/Gui.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _GUI_H_
-#define _GUI_H_
-
-#include "InputConfig.h"
-
-class Window;
-
-class Gui
-{
-public:
- Gui(Window* window);
- virtual ~Gui();
-
- virtual void input(InputConfig* config, Input input) { };
- virtual void update(int deltaTime) { };
- virtual void render() { };
-
- virtual void init() { };
- virtual void deinit() { };
-
- void setOffsetX(int x);
- void setOffsetY(int y);
- void setOffset(int x, int y);
- int getOffsetX();
- int getOffsetY();
-protected:
- int mOffsetX;
- int mOffsetY;
-
- Window* mWindow;
-};
-
-#endif
diff --git a/src/GuiComponent.cpp b/src/GuiComponent.cpp
new file mode 100644
index 000000000..4a5ee0195
--- /dev/null
+++ b/src/GuiComponent.cpp
@@ -0,0 +1,158 @@
+#include "GuiComponent.h"
+#include "Window.h"
+#include "Log.h"
+#include "Renderer.h"
+
+GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL)
+{
+}
+
+GuiComponent::~GuiComponent()
+{
+ mWindow->removeGui(this);
+
+ if(mParent)
+ mParent->removeChild(this);
+
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ getChild(i)->setParent(NULL);
+}
+
+bool GuiComponent::input(InputConfig* config, Input input)
+{
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ {
+ if(getChild(i)->input(config, input))
+ return true;
+ }
+
+ return false;
+}
+
+void GuiComponent::update(int deltaTime)
+{
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ {
+ getChild(i)->update(deltaTime);
+ }
+}
+
+void GuiComponent::render()
+{
+ Renderer::translate(mOffset);
+
+ onRender();
+
+ Renderer::translate(-mOffset);
+}
+
+void GuiComponent::onRender()
+{
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ {
+ getChild(i)->render();
+ }
+}
+
+void GuiComponent::init()
+{
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ {
+ getChild(i)->init();
+ }
+}
+
+void GuiComponent::deinit()
+{
+ for(unsigned int i = 0; i < getChildCount(); i++)
+ {
+ getChild(i)->deinit();
+ }
+}
+
+//Offset stuff.
+Vector2i GuiComponent::getGlobalOffset()
+{
+ if(mParent)
+ return mParent->getGlobalOffset() + mOffset;
+ else
+ return mOffset;
+}
+
+Vector2i GuiComponent::getOffset()
+{
+ return mOffset;
+}
+
+void GuiComponent::setOffset(Vector2i offset)
+{
+ setOffset(offset.x, offset.y);
+ onOffsetChanged();
+}
+
+void GuiComponent::setOffset(int x, int y)
+{
+ mOffset.x = x;
+ mOffset.y = y;
+ onOffsetChanged();
+}
+
+Vector2u GuiComponent::getSize()
+{
+ return mSize;
+}
+
+//Children stuff.
+void GuiComponent::addChild(GuiComponent* cmp)
+{
+ mChildren.push_back(cmp);
+
+ if(cmp->getParent())
+ cmp->getParent()->removeChild(cmp);
+
+ cmp->setParent(this);
+}
+
+void GuiComponent::removeChild(GuiComponent* cmp)
+{
+ if(cmp->getParent() != this)
+ {
+ LOG(LogError) << "Tried to remove child from incorrect parent!";
+ }
+
+ cmp->setParent(NULL);
+
+ for(auto i = mChildren.begin(); i != mChildren.end(); i++)
+ {
+ if(*i == cmp)
+ {
+ mChildren.erase(i);
+ return;
+ }
+ }
+}
+
+void GuiComponent::clearChildren()
+{
+ mChildren.clear();
+}
+
+unsigned int GuiComponent::getChildCount()
+{
+ return mChildren.size();
+}
+
+GuiComponent* GuiComponent::getChild(unsigned int i)
+{
+ return mChildren.at(i);
+}
+
+void GuiComponent::setParent(GuiComponent* parent)
+{
+ mParent = parent;
+}
+
+GuiComponent* GuiComponent::getParent()
+{
+ return mParent;
+}
diff --git a/src/GuiComponent.h b/src/GuiComponent.h
new file mode 100644
index 000000000..b7f36af64
--- /dev/null
+++ b/src/GuiComponent.h
@@ -0,0 +1,60 @@
+#ifndef _GUICOMPONENT_H_
+#define _GUICOMPONENT_H_
+
+#include "InputConfig.h"
+#include "Vector2.h"
+
+class Window;
+
+class GuiComponent
+{
+public:
+ GuiComponent(Window* window);
+ virtual ~GuiComponent();
+
+ //Called when input is received.
+ //Return true if the input is consumed, false if it should continue to be passed to other children.
+ virtual bool input(InputConfig* config, Input input);
+
+ //Called when time passes. Default implementation also calls update(deltaTime) on children - so you should probably call GuiComponent::update(deltaTime) at some point.
+ virtual void update(int deltaTime);
+
+ //Called when it's time to render. Translates the OpenGL matrix, calls onRender() (which renders children), then un-translates the OpenGL matrix.
+ //You probably don't need to override this, and should use the protected method onRender.
+ virtual void render();
+
+ //Called when the Renderer initializes. Passes to children.
+ virtual void init();
+
+ //Called when the Renderer deinitializes. Passes to children.
+ virtual void deinit();
+
+ virtual Vector2i getGlobalOffset();
+ Vector2i getOffset();
+ void setOffset(Vector2i offset);
+ void setOffset(int x, int y);
+ virtual void onOffsetChanged() {};
+
+ Vector2u getSize();
+
+ void setParent(GuiComponent* parent);
+ GuiComponent* getParent();
+
+ void addChild(GuiComponent* cmp);
+ void removeChild(GuiComponent* cmp);
+ void clearChildren();
+ unsigned int getChildCount();
+ GuiComponent* getChild(unsigned int i);
+
+protected:
+ //Default implementation just renders children - you should probably always call GuiComponent::onRender at some point in your custom onRender.
+ virtual void onRender();
+
+ Window* mWindow;
+ GuiComponent* mParent;
+ Vector2i mOffset;
+ Vector2u mSize;
+ std::vector mChildren;
+};
+
+#endif
diff --git a/src/InputConfig.cpp b/src/InputConfig.cpp
index 2e6d8319b..0036e3d11 100644
--- a/src/InputConfig.cpp
+++ b/src/InputConfig.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include "Log.h"
//some util functions
std::string inputTypeToString(InputType type)
@@ -138,7 +139,7 @@ void InputConfig::loadFromXML(pugi::xml_node node, int playerNum)
if(typeEnum == TYPE_COUNT)
{
- std::cout << "ERROR - input type \"" << type << "\" is invalid! Skipping input \"" << name << "\".\n";
+ LOG(LogError) << "InputConfig load error - input of type \"" << type << "\" is invalid! Skipping input \"" << name << "\".\n";
continue;
}
@@ -146,7 +147,7 @@ void InputConfig::loadFromXML(pugi::xml_node node, int playerNum)
int value = input.attribute("value").as_int();
if(value == 0)
- std::cout << "WARNING: InputConfig value is 0 for " << type << " " << id << "!\n";
+ LOG(LogWarning) << "WARNING: InputConfig value is 0 for " << type << " " << id << "!\n";
mNameMap[toLower(name)] = Input(mDeviceId, typeEnum, id, value, true);
}
@@ -167,6 +168,9 @@ void InputConfig::writeToXML(pugi::xml_node parent)
typedef std::map::iterator it_type;
for(it_type iterator = mNameMap.begin(); iterator != mNameMap.end(); iterator++)
{
+ if(!iterator->second.configured)
+ continue;
+
pugi::xml_node input = cfg.append_child("input");
input.append_attribute("name") = iterator->first.c_str();
input.append_attribute("type") = inputTypeToString(iterator->second.type).c_str();
diff --git a/src/InputManager.cpp b/src/InputManager.cpp
index 4f8f15394..5df74a951 100644
--- a/src/InputManager.cpp
+++ b/src/InputManager.cpp
@@ -72,7 +72,7 @@ std::vector InputManager::getInputDevices() const
if (GetRawInputDeviceList(deviceList, &nrOfDevices, sizeof(RAWINPUTDEVICELIST)) != -1)
{
//loop through input devices
- for (int i = 0; i < nrOfDevices; i++)
+ for (unsigned int i = 0; i < nrOfDevices; i++)
{
//get device name
char * rawName = new char[2048];
diff --git a/src/Renderer.h b/src/Renderer.h
index 7cbce0b39..f70b8c83b 100644
--- a/src/Renderer.h
+++ b/src/Renderer.h
@@ -3,6 +3,7 @@
#include
#include
+#include "Vector2.h"
#include "platform.h"
#include GLHEADER
//#include "Font.h"
@@ -28,8 +29,16 @@ namespace Renderer
Font* getDefaultFont(FontSize size);
void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount);
- //drawing commands
+ //graphics commands
void swapBuffers();
+
+ void translatef(float x, float y);
+ void translate(Vector2i offset);
+
+ void pushClipRect(int x, int y, unsigned int w, unsigned int h);
+ void pushClipRect(Vector2i offset, Vector2u size);
+ void popClipRect();
+
void drawRect(int x, int y, int w, int h, unsigned int color);
void drawText(std::string text, int x, int y, unsigned int color, Font* font);
void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font);
diff --git a/src/Renderer_draw_gl.cpp b/src/Renderer_draw_gl.cpp
index ee2058d30..22dcf4c1e 100644
--- a/src/Renderer_draw_gl.cpp
+++ b/src/Renderer_draw_gl.cpp
@@ -5,10 +5,13 @@
#include "Font.h"
#include
#include "Log.h"
+#include
namespace Renderer {
bool loadedFonts = false;
+ std::stack clipStack;
+
void setColor4bArray(GLubyte* array, unsigned int color)
{
array[0] = (color & 0xff000000) / 0x1000000;
@@ -26,6 +29,56 @@ namespace Renderer {
}
}
+ void translatef(float x, float y)
+ {
+ glTranslatef(x, y, 0);
+ }
+
+ void translate(Vector2i offset)
+ {
+ translatef((float)offset.x, (float)offset.y);
+ }
+
+ void pushClipRect(int x, int y, unsigned int w, unsigned int h)
+ {
+ Rect rect(x, y, w, h);
+ if(rect.size.x == 0)
+ rect.size.x = Renderer::getScreenWidth() - rect.pos.x;
+ if(rect.size.y == 0)
+ rect.size.y = Renderer::getScreenHeight() - rect.pos.y;
+
+ //glScissor starts at the bottom left of the window
+ //so (0, 0, 1, 1) is the bottom left pixel
+ //everything else uses y+ = down, so flip it to be consistent
+ rect.pos.y = Renderer::getScreenHeight() - rect.pos.y - rect.size.y;
+
+ clipStack.push(rect);
+ glScissor(rect.pos.x, rect.pos.y, rect.size.x, rect.size.y);
+ glEnable(GL_SCISSOR_TEST);
+ }
+
+ void pushClipRect(Vector2i pos, Vector2u size)
+ {
+ pushClipRect(pos.x, pos.y, size.x, size.y);
+ }
+
+ void popClipRect()
+ {
+ if(clipStack.empty())
+ {
+ LOG(LogError) << "Tried to popClipRect while the stack was empty!";
+ return;
+ }
+ clipStack.pop();
+ if(clipStack.empty())
+ {
+ glDisable(GL_SCISSOR_TEST);
+ }else{
+ Rect top = clipStack.top();
+ glScissor(top.pos.x, top.pos.y, top.size.x, top.size.y);
+ }
+ }
+
void drawRect(int x, int y, int w, int h, unsigned int color)
{
#ifdef USE_OPENGL_ES
diff --git a/src/Renderer_init_sdlgl.cpp b/src/Renderer_init_sdlgl.cpp
index 3a464fd08..9659e3b0a 100644
--- a/src/Renderer_init_sdlgl.cpp
+++ b/src/Renderer_init_sdlgl.cpp
@@ -15,8 +15,7 @@
#include "ImageIO.h"
#include "../data/Resources.h"
#include "EmulationStation.h"
-
-extern bool WINDOWED;
+#include "Settings.h"
namespace Renderer
{
@@ -71,7 +70,8 @@ namespace Renderer
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- sdlScreen = SDL_SetVideoMode(display_width, display_height, 16, SDL_OPENGL | (WINDOWED ? 0 : SDL_FULLSCREEN) | SDL_DOUBLEBUF);
+ //SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); //vsync
+ sdlScreen = SDL_SetVideoMode(display_width, display_height, 16, SDL_OPENGL | (Settings::getInstance()->getBool("WINDOWED") ? 0 : SDL_FULLSCREEN));
if(sdlScreen == NULL)
{
@@ -88,7 +88,7 @@ namespace Renderer
LOG(LogInfo) << "Created surface successfully.";
//hide mouse cursor
- initialCursorState = SDL_ShowCursor(0);
+ initialCursorState = SDL_ShowCursor(0) == 1;
return true;
}
diff --git a/src/Settings.cpp b/src/Settings.cpp
new file mode 100644
index 000000000..52111668d
--- /dev/null
+++ b/src/Settings.cpp
@@ -0,0 +1,101 @@
+#include "Settings.h"
+#include "Log.h"
+#include "pugiXML/pugixml.hpp"
+#include "platform.h"
+#include
+
+Settings* Settings::sInstance = NULL;
+
+Settings::Settings()
+{
+ setDefaults();
+ loadFile();
+}
+
+Settings* Settings::getInstance()
+{
+ if(sInstance == NULL)
+ sInstance = new Settings();
+
+ return sInstance;
+}
+
+void Settings::setDefaults()
+{
+ mBoolMap.clear();
+ mIntMap.clear();
+
+ mBoolMap["PARSEGAMELISTONLY"] = false;
+ mBoolMap["IGNOREGAMELIST"] = false;
+ mBoolMap["DRAWFRAMERATE"] = false;
+ mBoolMap["DONTSHOWEXIT"] = false;
+ mBoolMap["DEBUG"] = false;
+ mBoolMap["WINDOWED"] = false;
+
+ mIntMap["DIMTIME"] = 30*1000;
+}
+
+template
+void saveMap(pugi::xml_document& doc, std::map& map, const char* type)
+{
+ for(auto iter = map.begin(); iter != map.end(); iter++)
+ {
+ pugi::xml_node node = doc.append_child(type);
+ node.append_attribute("name").set_value(iter->first.c_str());
+ node.append_attribute("value").set_value(iter->second);
+ }
+}
+
+void Settings::saveFile()
+{
+ const std::string path = getHomePath() + "/.emulationstation/es_settings.cfg";
+
+ pugi::xml_document doc;
+
+ saveMap(doc, mBoolMap, "bool");
+ saveMap(doc, mIntMap, "int");
+ saveMap(doc, mFloatMap, "float");
+
+ doc.save_file(path.c_str());
+}
+
+void Settings::loadFile()
+{
+ const std::string path = getHomePath() + "/.emulationstation/es_settings.cfg";
+
+ if(!boost::filesystem::exists(path))
+ return;
+
+ pugi::xml_document doc;
+ pugi::xml_parse_result result = doc.load_file(path.c_str());
+ if(!result)
+ {
+ LOG(LogError) << "Could not parse Settings file!\n " << result.description();
+ return;
+ }
+
+ for(pugi::xml_node node = doc.child("bool"); node; node = node.next_sibling())
+ setBool(node.attribute("name").as_string(), node.attribute("value").as_bool());
+ for(pugi::xml_node node = doc.child("int"); node; node = node.next_sibling())
+ setInt(node.attribute("name").as_string(), node.attribute("value").as_int());
+ for(pugi::xml_node node = doc.child("float"); node; node = node.next_sibling())
+ setFloat(node.attribute("name").as_string(), node.attribute("value").as_float());
+}
+
+//Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map.
+#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) type Settings::getMethodName(const std::string& name) \
+{ \
+ if(mapName.find(name) == mapName.end()) \
+ { \
+ LOG(LogError) << "Tried to use unset setting " << name << "!"; \
+ } \
+ return mapName[name]; \
+} \
+void Settings::setMethodName(const std::string& name, type value) \
+{ \
+ mapName[name] = value; \
+}
+
+SETTINGS_GETSET(bool, mBoolMap, getBool, setBool);
+SETTINGS_GETSET(int, mIntMap, getInt, setInt);
+SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat);
diff --git a/src/Settings.h b/src/Settings.h
new file mode 100644
index 000000000..099a0afa7
--- /dev/null
+++ b/src/Settings.h
@@ -0,0 +1,38 @@
+#ifndef _SETTINGS_H_
+#define _SETTINGS_H_
+
+#include
+#include