diff --git a/CMakeLists.txt b/CMakeLists.txt index cdfcd32..ecf1b4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,7 @@ set(MAIN_HEADERS src/flashable.h src/font.h src/input.h + src/iniconfig.h src/plane.h src/scene.h src/sprite.h @@ -167,6 +168,7 @@ set(MAIN_SOURCE src/filesystem.cpp src/font.cpp src/input.cpp + src/iniconfig.cpp src/plane.cpp src/scene.cpp src/sprite.cpp diff --git a/mkxp.pro b/mkxp.pro index 558727a..ae229d7 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -8,6 +8,10 @@ INCLUDEPATH += . src CONFIG(release, debug|release): DEFINES += NDEBUG +CONFIG += c++11 +# And for older qmake versions.. +QMAKE_CXXFLAGS += -std=c++11 + isEmpty(BINDING) { BINDING = MRI } @@ -89,6 +93,7 @@ HEADERS += \ src/flashable.h \ src/font.h \ src/input.h \ + src/iniconfig.h \ src/plane.h \ src/scene.h \ src/sprite.h \ @@ -145,6 +150,7 @@ SOURCES += \ src/filesystem.cpp \ src/font.cpp \ src/input.cpp \ + src/iniconfig.cpp \ src/plane.cpp \ src/scene.cpp \ src/sprite.cpp \ diff --git a/src/config.cpp b/src/config.cpp index 383a567..b4cf086 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -35,6 +35,7 @@ #include "debugwriter.h" #include "util.h" #include "sdl-util.h" +#include "iniconfig.h" #ifdef INI_ENCODING extern "C" { @@ -321,26 +322,32 @@ void Config::readGameINI() return; } - po::options_description podesc; - podesc.add_options() - ("Game.Title", po::value()) - ("Game.Scripts", po::value()) - ; - - po::variables_map vm; std::string iniFilename = execName + ".ini"; SDLRWStream iniFile(iniFilename.c_str(), "r"); if (iniFile) { - try + INIConfiguration ic; + if(ic.load(iniFile.stream())) { - po::store(po::parse_config_file(iniFile.stream(), podesc, true), vm); - po::notify(vm); + GUARD_ALL( game.title = ic.getStringProperty("Game", "Title"); ); + GUARD_ALL( game.scripts = ic.getStringProperty("Game", "Scripts"); ); + + strReplace(game.scripts, '\\', '/'); + + if (game.title.empty()) + { + Debug() << iniFilename + ": Could not find Game.Title property"; + } + + if (game.scripts.empty()) + { + Debug() << iniFilename + ": Could not find Game.Scripts property"; + } } - catch (po::error &error) + else { - Debug() << iniFilename + ":" << error.what(); + Debug() << iniFilename + ": Failed to parse ini file"; } } else @@ -348,11 +355,6 @@ void Config::readGameINI() Debug() << "FAILED to open" << iniFilename; } - GUARD_ALL( game.title = vm["Game.Title"].as(); ); - GUARD_ALL( game.scripts = vm["Game.Scripts"].as(); ); - - strReplace(game.scripts, '\\', '/'); - #ifdef INI_ENCODING /* Can add more later */ const char *languages[] = diff --git a/src/filesystem.cpp b/src/filesystem.cpp index f02e634..284f141 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -311,18 +311,32 @@ struct FileSystemPrivate bool havePathCache; }; +static void throwPhysfsError(const char *desc) +{ + PHYSFS_ErrorCode ec = PHYSFS_getLastErrorCode(); + const char *englishStr = PHYSFS_getErrorByCode(ec); + + throw Exception(Exception::PHYSFSError, "%s: %s", desc, englishStr); +} + FileSystem::FileSystem(const char *argv0, bool allowSymlinks) { + if (PHYSFS_init(argv0) == 0) + throwPhysfsError("Error initializing PhysFS"); + + /* One error (=return 0) turns the whole product to 0 */ + int er = 1; + er *= PHYSFS_registerArchiver(&RGSS1_Archiver); + er *= PHYSFS_registerArchiver(&RGSS2_Archiver); + er *= PHYSFS_registerArchiver(&RGSS3_Archiver); + + if (er == 0) + throwPhysfsError("Error registering PhysFS RGSS archiver"); + p = new FileSystemPrivate; p->havePathCache = false; - PHYSFS_init(argv0); - - PHYSFS_registerArchiver(&RGSS1_Archiver); - PHYSFS_registerArchiver(&RGSS2_Archiver); - PHYSFS_registerArchiver(&RGSS3_Archiver); - if (allowSymlinks) PHYSFS_permitSymbolicLinks(1); } @@ -469,7 +483,7 @@ fontSetEnumCB (void *data, const char *dir, const char *fname) const char *ext = findExt(fname); if (!ext) - return PHYSFS_ENUM_STOP; + return PHYSFS_ENUM_OK; char lowExt[8]; size_t i; @@ -479,7 +493,7 @@ fontSetEnumCB (void *data, const char *dir, const char *fname) lowExt[i] = '\0'; if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf")) - return PHYSFS_ENUM_STOP; + return PHYSFS_ENUM_OK; char filename[512]; snprintf(filename, sizeof(filename), "%s/%s", dir, fname); diff --git a/src/fluid-fun.cpp b/src/fluid-fun.cpp index d49157d..4bb2dbe 100644 --- a/src/fluid-fun.cpp +++ b/src/fluid-fun.cpp @@ -6,10 +6,6 @@ #include "debugwriter.h" -#ifdef SHARED_FLUID -#include -#endif - #if __LINUX__ || __ANDROID__ #define FLUID_LIB "libfluidsynth.so.1" #elif __MACOSX__ diff --git a/src/fluid-fun.h b/src/fluid-fun.h index f26f9fe..005bdf7 100644 --- a/src/fluid-fun.h +++ b/src/fluid-fun.h @@ -1,6 +1,12 @@ #ifndef FLUIDFUN_H #define FLUIDFUN_H +#ifdef SHARED_FLUID +# include +#else +# define FLUIDSYNTH_VERSION_MAJOR 2 +#endif + typedef struct _fluid_hashtable_t fluid_settings_t; typedef struct _fluid_synth_t fluid_synth_t; @@ -19,7 +25,12 @@ typedef int (*FLUIDSYNTHPROGRAMCHANGEPROC)(fluid_synth_t* synth, int chan, int p typedef fluid_settings_t* (*NEWFLUIDSETTINGSPROC)(void); typedef fluid_synth_t* (*NEWFLUIDSYNTHPROC)(fluid_settings_t* settings); typedef void (*DELETEFLUIDSETTINGSPROC)(fluid_settings_t* settings); + +#if FLUIDSYNTH_VERSION_MAJOR == 1 typedef int (*DELETEFLUIDSYNTHPROC)(fluid_synth_t* synth); +#else +typedef void (*DELETEFLUIDSYNTHPROC)(fluid_synth_t* synth); +#endif #define FLUID_FUNCS \ FLUID_FUN(settings_setnum, FLUIDSETTINGSSETNUMPROC) \ diff --git a/src/graphics.cpp b/src/graphics.cpp index 066bff6..ca47104 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -759,6 +759,9 @@ void Graphics::transition(int duration, setBrightness(255); + /* Capture new scene */ + p->screen.composite(); + /* The PP frontbuffer will hold the current scene after the * composition step. Since the backbuffer is unused during * the transition, we can reuse it as the target buffer for @@ -766,9 +769,6 @@ void Graphics::transition(int duration, TEXFBO ¤tScene = p->screen.getPP().frontBuffer(); TEXFBO &transBuffer = p->screen.getPP().backBuffer(); - /* Capture new scene */ - p->screen.composite(); - /* If no transition bitmap is provided, * we can use a simplified shader */ TransShader &transShader = shState->shaders().trans; diff --git a/src/iniconfig.cpp b/src/iniconfig.cpp new file mode 100644 index 0000000..f3c0485 --- /dev/null +++ b/src/iniconfig.cpp @@ -0,0 +1,114 @@ +#include "iniconfig.h" + +#include + +std::string toLowerCase(const std::string& str) +{ + std::string lower = str; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + return lower; +} + +std::string trim(const std::string& str, const std::string& chars = "\t\n\v\f\r ") +{ + std::string trimmed = str; + trimmed.erase(trimmed.find_last_not_of(chars) + 1); + trimmed.erase(0, trimmed.find_first_not_of(chars)); + return trimmed; +} + +INIConfiguration::Section::Section (const std::string& sname) : m_Name (sname), m_PropertyMap() +{ +} + +bool INIConfiguration::Section::getStringProperty (const std::string& name, std::string& outPropStr) const +{ + try + { + outPropStr = m_PropertyMap.at(toLowerCase(name)).m_Value; + return true; + } + catch (std::out_of_range& oorexcept) + { + return false; + } +} + +bool INIConfiguration::load (std::istream& is) +{ + if (!is.good()) + { + return false; + } + + std::string currSectionName; + + std::string line; + std::getline (is, line); + + while (!is.eof() && !is.bad()) + { + if (line[0] == '[') + { + currSectionName = line.substr (1, line.find_last_of (']') - 1); + } + else if (line[0] != '#' && line.length() > 2) + { + int crloc = line.length() - 1; + + if (crloc >= 0 && line[crloc] == '\r') //check for Windows-style newline + line.resize (crloc); //and correct + + size_t equalsPos = line.find_first_of ("="); + + if (equalsPos != std::string::npos) + { + std::string key = line.substr (0, equalsPos); + std::string val = line.substr (equalsPos + 1); + + addProperty (currSectionName, key , val); + } + } + + std::getline (is, line); + } + + if (is.bad()) + { + return false; + } + + return true; +} + + +std::string INIConfiguration::getStringProperty(const std::string& sname, const std::string& name, const std::string& def) const +{ + auto sectionIt = m_SectionMap.find(toLowerCase(sname)); + + if (sectionIt != m_SectionMap.end()) + { + std::string prop; + + if(sectionIt->second.getStringProperty(name, prop)) + { + return prop; + } + } + + return def; +} + +void INIConfiguration::addProperty (const std::string& sname, const std::string& name, const std::string& val) +{ + if (m_SectionMap.find (toLowerCase(sname)) == m_SectionMap.end()) + { + m_SectionMap.emplace (toLowerCase(sname), Section (sname)); + } + + Section::Property p; + p.m_Name = trim(name); + p.m_Value = trim(val); + + m_SectionMap.at (toLowerCase(sname)).m_PropertyMap[toLowerCase(p.m_Name)] = p; +} diff --git a/src/iniconfig.h b/src/iniconfig.h new file mode 100644 index 0000000..2907df5 --- /dev/null +++ b/src/iniconfig.h @@ -0,0 +1,46 @@ +#ifndef INICONFIG_H +#define INICONFIG_H + +#include +#include + +class INIConfiguration +{ + class Section + { + friend class INIConfiguration; + + struct Property + { + std::string m_Name; + std::string m_Value; + }; + + typedef std::map property_map; + public: + Section (const Section& s) = default; + Section (Section&& s) = default; + + bool getStringProperty (const std::string& name, std::string& outPropStr) const; + + private: + explicit Section (const std::string& name); + + std::string m_Name; + property_map m_PropertyMap; + }; + + typedef std::map section_map; +public: + bool load (std::istream& inStream); + + std::string getStringProperty(const std::string& sname, const std::string& name, const std::string& def = "") const; + +protected: + void addProperty (const std::string& sname, const std::string& name, const std::string& val); + +private: + section_map m_SectionMap; +}; + +#endif // INICONFIG_H diff --git a/src/sprite.cpp b/src/sprite.cpp index 26eb297..f4c8f89 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -35,6 +35,9 @@ #include "quadarray.h" #include +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif #include