Lots of cleaning up to improve user friendliness. Config files are now loaded from the $HOME variable - es_systems.cfg and es_input.cfg.

An example system config file will be created at runtime if one does not exist.
This commit is contained in:
Aloshi 2012-07-23 18:53:33 -05:00
parent 21bd83d5b2
commit 6c5edd3284
9 changed files with 133 additions and 38 deletions

View file

@ -10,7 +10,7 @@ SDL_Event* InputManager::lastEvent = NULL;
std::map<int, InputManager::InputButton> InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap; std::map<int, InputManager::InputButton> InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap;
std::map<int, int> InputManager::axisState; std::map<int, int> InputManager::axisState;
int InputManager::deadzone = 32000; int InputManager::deadzone = 28000;
void InputManager::registerComponent(GuiComponent* comp) void InputManager::registerComponent(GuiComponent* comp)
{ {
@ -138,13 +138,15 @@ void InputManager::processEvent(SDL_Event* event)
} }
} }
void InputManager::loadConfig(std::string path) void InputManager::loadConfig()
{ {
//clear any old config //clear any old config
joystickButtonMap.clear(); joystickButtonMap.clear();
joystickAxisPosMap.clear(); joystickAxisPosMap.clear();
joystickAxisNegMap.clear(); joystickAxisNegMap.clear();
std::string path = getConfigPath();
std::ifstream file(path.c_str()); std::ifstream file(path.c_str());
while(file.good()) while(file.good())
@ -195,3 +197,16 @@ void InputManager::loadConfig(std::string path)
SDL_JoystickOpen(0); SDL_JoystickOpen(0);
} }
} }
std::string InputManager::getConfigPath()
{
std::string home = getenv("HOME");
if(home.empty())
{
std::cerr << "FATAL ERROR - $HOME environment variable is blank or not defined!\n";
exit(1);
return "";
}
return(home + "/.es_input.cfg");
}

View file

@ -12,7 +12,7 @@ namespace InputManager {
void registerComponent(GuiComponent* comp); void registerComponent(GuiComponent* comp);
void unregisterComponent(GuiComponent* comp); void unregisterComponent(GuiComponent* comp);
void loadConfig(std::string path); void loadConfig();
//enum for identifying input, regardless of configuration //enum for identifying input, regardless of configuration
enum InputButton { UNKNOWN, UP, DOWN, LEFT, RIGHT, BUTTON1, BUTTON2 }; enum InputButton { UNKNOWN, UP, DOWN, LEFT, RIGHT, BUTTON1, BUTTON2 };
@ -22,6 +22,7 @@ namespace InputManager {
extern std::vector<GuiComponent*> inputVector; extern std::vector<GuiComponent*> inputVector;
extern SDL_Event* lastEvent; //mostly for GuiInputConfig extern SDL_Event* lastEvent; //mostly for GuiInputConfig
extern int deadzone; extern int deadzone;
std::string getConfigPath();
extern std::map<int, InputButton> joystickButtonMap; extern std::map<int, InputButton> joystickButtonMap;
extern std::map<int, InputButton> joystickAxisPosMap, joystickAxisNegMap; extern std::map<int, InputButton> joystickAxisPosMap, joystickAxisNegMap;

View file

@ -3,6 +3,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <fstream> #include <fstream>
#include <stdlib.h> #include <stdlib.h>
#include <SDL/SDL_joystick.h>
std::vector<SystemData*> SystemData::sSystemVector; std::vector<SystemData*> SystemData::sSystemVector;
@ -33,6 +34,9 @@ void SystemData::launchGame(unsigned int i)
{ {
std::cout << "Attempting to launch game...\n"; std::cout << "Attempting to launch game...\n";
//suspend SDL joystick events (these'll pile up even while something else is running)
SDL_JoystickEventState(0);
std::string command = mLaunchCommand; std::string command = mLaunchCommand;
GameData* game = mGameVector.at(i); GameData* game = mGameVector.at(i);
@ -44,6 +48,9 @@ void SystemData::launchGame(unsigned int i)
std::cout << "=====================================================\n"; std::cout << "=====================================================\n";
std::cout << "...launch terminated!\n"; std::cout << "...launch terminated!\n";
//re-enable SDL joystick events
SDL_JoystickEventState(1);
} }
void SystemData::deleteGames() void SystemData::deleteGames()
@ -62,6 +69,21 @@ void SystemData::buildGameList()
deleteGames(); deleteGames();
//expand home symbol if necessary
if(mStartPath[0] == '~')
{
mStartPath.erase(0, 1);
std::string home = getenv("HOME");
if(home.empty())
{
std::cerr << "ERROR - System start path contains ~ but $HOME is not set!\n";
return;
}else{
mStartPath.insert(0, home);
}
}
if(!fs::is_directory(mStartPath)) if(!fs::is_directory(mStartPath))
{ {
std::cout << "Error - system \"" << mName << "\"'s start path does not exist!\n"; std::cout << "Error - system \"" << mName << "\"'s start path does not exist!\n";
@ -109,10 +131,12 @@ std::string SystemData::getName()
//creates systems from information located in a config file //creates systems from information located in a config file
void SystemData::loadConfig(std::string path) void SystemData::loadConfig()
{ {
deleteSystems(); deleteSystems();
std::string path = getConfigPath();
std::cout << "Loading system config file \"" << path << "\"...\n"; std::cout << "Loading system config file \"" << path << "\"...\n";
std::ifstream file(path.c_str()); std::ifstream file(path.c_str());
@ -179,6 +203,34 @@ void SystemData::loadConfig(std::string path)
return; return;
} }
void SystemData::writeExampleConfig()
{
std::string path = getConfigPath();
std::ofstream file(path.c_str());
file << "# This is the EmulationStation Systems configuration file." << std::endl;
file << "# Lines that begin with a hash (#) are ignored, as are empty lines." << std::endl;
file << "# A sample system might look like this:" << std::endl;
file << "#NAME=Nintendo Entertainment System" << std::endl;
file << "#PATH=~/ROMs/nes/" << std::endl;
file << "#EXTENSION=.nes" << std::endl;
file << "#COMMAND=retroarch -L ~/cores/libretro-fceumm.so %ROM%" << std::endl << std::endl;
file << "#NAME is just a name to identify the system." << std::endl;
file << "#PATH is the path to start the recursive search for ROMs in. ~ will be expanded into the $HOME variable." << std::endl;
file << "#EXTENSION is the exact extension to search for. You MUST include the period, and it must be exact - no regex or wildcard support (sorry!)." << std::endl;
file << "#COMMAND is the shell command to execute when a game is selected. %ROM% will be replaced with the path to the ROM." << std::endl << std::endl;
file << "#Now try your own!" << std::endl;
file << "NAME=" << std::endl;
file << "PATH=" << std::endl;
file << "EXTENSION=" << std::endl;
file << "COMMAND=" << std::endl;
file.close();
}
void SystemData::deleteSystems() void SystemData::deleteSystems()
{ {
for(unsigned int i = 0; i < sSystemVector.size(); i++) for(unsigned int i = 0; i < sSystemVector.size(); i++)
@ -187,3 +239,16 @@ void SystemData::deleteSystems()
} }
sSystemVector.clear(); sSystemVector.clear();
} }
std::string SystemData::getConfigPath()
{
std::string home = getenv("HOME");
if(home.empty())
{
std::cerr << "FATAL ERROR - $HOME environment variable empty or nonexistant!\n";
exit(1);
return "";
}
return(home + "/.es_systems.cfg");
}

View file

@ -18,9 +18,10 @@ public:
void buildGameList(); void buildGameList();
void launchGame(unsigned int i); void launchGame(unsigned int i);
//static std::vector<SystemData*> loadConfig(std::string path);
static void deleteSystems(); static void deleteSystems();
static void loadConfig(std::string path); static void loadConfig();
static void writeExampleConfig();
static std::string getConfigPath();
static std::vector<SystemData*> sSystemVector; static std::vector<SystemData*> sSystemVector;
private: private:

View file

@ -25,6 +25,12 @@ GuiGameList::~GuiGameList()
void GuiGameList::setSystemId(int id) void GuiGameList::setSystemId(int id)
{ {
if(SystemData::sSystemVector.size() == 0)
{
std::cerr << "Error - no systems found!\n";
return;
}
//make sure the id is within range //make sure the id is within range
if(id >= (int)SystemData::sSystemVector.size()) if(id >= (int)SystemData::sSystemVector.size())
id -= SystemData::sSystemVector.size(); id -= SystemData::sSystemVector.size();
@ -48,10 +54,8 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
{ {
if(button == InputManager::BUTTON1 && mSystem->getGameCount() > 0) if(button == InputManager::BUTTON1 && mSystem->getGameCount() > 0)
{ {
//SDL_EnableKeyRepeat(0, 0);
if(!keyDown) if(!keyDown)
mSystem->launchGame(mList->getSelection()); mSystem->launchGame(mList->getSelection());
//SDL_EnableKeyRepeat(500, 100);
} }
if(button == InputManager::RIGHT && keyDown) if(button == InputManager::RIGHT && keyDown)

View file

@ -38,24 +38,29 @@ void GuiInputConfig::onRender()
{ {
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF); Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
Renderer::drawCenteredText("It looks like you have a joystick plugged in!", 2, 0x000000);
Renderer::drawCenteredText("POV hats (some D-Pads) are automatically mapped to directions.", 90, 0x000000);
Renderer::drawCenteredText("You can press a keyboard key to skip any input.", 130, 0x000000);
Renderer::drawCenteredText("If you want to remap later, just delete ~/.es_input.cfg.", 170, 0x000000);
if(mDone) if(mDone)
Renderer::drawCenteredText("All done!", 2, 0x000000); Renderer::drawCenteredText("All done! Press a keyboard key to continue.", 250, 0x00BB00);
else else
Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 2, 0x000000); Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 250, 0x00C000);
} }
void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown) void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown)
{ {
if(mDone) if(mDone)
{ {
if(keyDown) if(InputManager::lastEvent->type == SDL_KEYUP)
{ {
writeConfig(sConfigPath); writeConfig();
if(mJoystick) if(mJoystick)
SDL_JoystickClose(mJoystick); SDL_JoystickClose(mJoystick);
InputManager::loadConfig(sConfigPath); InputManager::loadConfig();
delete this; delete this;
new GuiGameList(); new GuiGameList();
} }
@ -102,8 +107,10 @@ void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown)
} }
} }
void GuiInputConfig::writeConfig(std::string path) void GuiInputConfig::writeConfig()
{ {
std::string path = InputManager::getConfigPath();
std::ofstream file(path.c_str()); std::ofstream file(path.c_str());
typedef std::map<int, InputManager::InputButton>::iterator it_type; typedef std::map<int, InputManager::InputButton>::iterator it_type;

View file

@ -25,7 +25,7 @@ private:
std::map<int, InputManager::InputButton> mButtonMap; std::map<int, InputManager::InputButton> mButtonMap;
std::map<int, InputManager::InputButton> mAxisPosMap; std::map<int, InputManager::InputButton> mAxisPosMap;
std::map<int, InputManager::InputButton> mAxisNegMap; std::map<int, InputManager::InputButton> mAxisNegMap;
void writeConfig(std::string path); void writeConfig();
}; };
#endif #endif

View file

@ -4,11 +4,13 @@
#include "Renderer.h" #include "Renderer.h"
#include "components/GuiGameList.h" #include "components/GuiGameList.h"
#include "SystemData.h" #include "SystemData.h"
#include <boost/filesystem.hpp>
#include "components/GuiInputConfig.h" #include "components/GuiInputConfig.h"
int main() int main()
{ {
bool running = true;
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0) if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)
{ {
std::cerr << "Error - could not initialize SDL!\n"; std::cerr << "Error - could not initialize SDL!\n";
@ -35,16 +37,31 @@ int main()
SDL_EnableKeyRepeat(500, 100); SDL_EnableKeyRepeat(500, 100);
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
//GuiTitleScreen* testGui = new GuiTitleScreen(); if(!boost::filesystem::exists(SystemData::getConfigPath()))
{
std::cerr << "A system config file in $HOME/.es_systems.cfg was not found. An example will be created.\n";
SystemData::writeExampleConfig();
std::cerr << "Set it up, then re-run EmulationStation.\n";
running = false;
}else{
SystemData::loadConfig();
SystemData::loadConfig("./systems.cfg"); if(boost::filesystem::exists(InputManager::getConfigPath()))
{
InputManager::loadConfig();
new GuiGameList();
}else{
if(SDL_NumJoysticks() > 0)
{
new GuiInputConfig();
}else{
std::cout << "Note - it looks like you have no joysticks connected.\n";
new GuiGameList();
}
}
}
//InputManager::loadConfig("./input.cfg");
//GuiGameList* testGui = new GuiGameList();
GuiInputConfig* testGui = new GuiInputConfig();
bool running = true;
while(running) while(running)
{ {
SDL_Event event; SDL_Event event;

View file

@ -1,15 +0,0 @@
NAME=Super Nintendo Entertainment System
PATH=../ROMs/snes/
EXTENSION=.smc
COMMAND=retroarch -L ~/cores/libretro-pocketsnes.so %ROM%
NAME=Nintendo Entertainment System
PATH=../ROMs/nes/
EXTENSION=.nes
COMMAND=retroarch -L ~/cores/libretro-fceumm.so %ROM%
# This is just a dud to test error handling. Also, comment support! Woo!
NAME=Fake System
PATH=./fakedir/
EXTENSION=.fake
COMMAND=this will never be called