diff --git a/src/InputManager.cpp b/src/InputManager.cpp index b7637ddf9..22fc942e2 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -10,7 +10,7 @@ SDL_Event* InputManager::lastEvent = NULL; std::map InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap; std::map InputManager::axisState; -int InputManager::deadzone = 32000; +int InputManager::deadzone = 28000; 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 joystickButtonMap.clear(); joystickAxisPosMap.clear(); joystickAxisNegMap.clear(); + std::string path = getConfigPath(); + std::ifstream file(path.c_str()); while(file.good()) @@ -195,3 +197,16 @@ void InputManager::loadConfig(std::string path) 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"); +} diff --git a/src/InputManager.h b/src/InputManager.h index a39a4ecbf..c4d8320c6 100644 --- a/src/InputManager.h +++ b/src/InputManager.h @@ -12,7 +12,7 @@ namespace InputManager { void registerComponent(GuiComponent* comp); void unregisterComponent(GuiComponent* comp); - void loadConfig(std::string path); + void loadConfig(); //enum for identifying input, regardless of configuration enum InputButton { UNKNOWN, UP, DOWN, LEFT, RIGHT, BUTTON1, BUTTON2 }; @@ -22,6 +22,7 @@ namespace InputManager { extern std::vector inputVector; extern SDL_Event* lastEvent; //mostly for GuiInputConfig extern int deadzone; + std::string getConfigPath(); extern std::map joystickButtonMap; extern std::map joystickAxisPosMap, joystickAxisNegMap; diff --git a/src/SystemData.cpp b/src/SystemData.cpp index f498e9d6c..8ca2814bf 100644 --- a/src/SystemData.cpp +++ b/src/SystemData.cpp @@ -3,6 +3,7 @@ #include #include #include +#include std::vector SystemData::sSystemVector; @@ -33,6 +34,9 @@ void SystemData::launchGame(unsigned int i) { 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; GameData* game = mGameVector.at(i); @@ -44,6 +48,9 @@ void SystemData::launchGame(unsigned int i) std::cout << "=====================================================\n"; std::cout << "...launch terminated!\n"; + + //re-enable SDL joystick events + SDL_JoystickEventState(1); } void SystemData::deleteGames() @@ -62,6 +69,21 @@ void SystemData::buildGameList() 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)) { 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 -void SystemData::loadConfig(std::string path) +void SystemData::loadConfig() { deleteSystems(); + std::string path = getConfigPath(); + std::cout << "Loading system config file \"" << path << "\"...\n"; std::ifstream file(path.c_str()); @@ -179,6 +203,34 @@ void SystemData::loadConfig(std::string path) 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() { for(unsigned int i = 0; i < sSystemVector.size(); i++) @@ -187,3 +239,16 @@ void SystemData::deleteSystems() } 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"); +} diff --git a/src/SystemData.h b/src/SystemData.h index 12451b953..c52463e89 100644 --- a/src/SystemData.h +++ b/src/SystemData.h @@ -18,9 +18,10 @@ public: void buildGameList(); void launchGame(unsigned int i); - //static std::vector loadConfig(std::string path); static void deleteSystems(); - static void loadConfig(std::string path); + static void loadConfig(); + static void writeExampleConfig(); + static std::string getConfigPath(); static std::vector sSystemVector; private: diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index d5cca07be..0d1ae5434 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -25,6 +25,12 @@ GuiGameList::~GuiGameList() 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 if(id >= (int)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) { - //SDL_EnableKeyRepeat(0, 0); if(!keyDown) mSystem->launchGame(mList->getSelection()); - //SDL_EnableKeyRepeat(500, 100); } if(button == InputManager::RIGHT && keyDown) diff --git a/src/components/GuiInputConfig.cpp b/src/components/GuiInputConfig.cpp index 17e6dd823..65191be20 100644 --- a/src/components/GuiInputConfig.cpp +++ b/src/components/GuiInputConfig.cpp @@ -38,24 +38,29 @@ void GuiInputConfig::onRender() { 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) - Renderer::drawCenteredText("All done!", 2, 0x000000); + Renderer::drawCenteredText("All done! Press a keyboard key to continue.", 250, 0x00BB00); 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) { if(mDone) { - if(keyDown) + if(InputManager::lastEvent->type == SDL_KEYUP) { - writeConfig(sConfigPath); + writeConfig(); if(mJoystick) SDL_JoystickClose(mJoystick); - InputManager::loadConfig(sConfigPath); + InputManager::loadConfig(); delete this; 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()); typedef std::map::iterator it_type; diff --git a/src/components/GuiInputConfig.h b/src/components/GuiInputConfig.h index 7900750f6..65c1a27ec 100644 --- a/src/components/GuiInputConfig.h +++ b/src/components/GuiInputConfig.h @@ -25,7 +25,7 @@ private: std::map mButtonMap; std::map mAxisPosMap; std::map mAxisNegMap; - void writeConfig(std::string path); + void writeConfig(); }; #endif diff --git a/src/main.cpp b/src/main.cpp index 099db9403..b2c50656a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,13 @@ #include "Renderer.h" #include "components/GuiGameList.h" #include "SystemData.h" - +#include #include "components/GuiInputConfig.h" int main() { + bool running = true; + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0) { std::cerr << "Error - could not initialize SDL!\n"; @@ -35,16 +37,31 @@ int main() SDL_EnableKeyRepeat(500, 100); 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) { SDL_Event event; diff --git a/systems.cfg b/systems.cfg deleted file mode 100644 index 1bc3d9afb..000000000 --- a/systems.cfg +++ /dev/null @@ -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