From ae59fcd112ef6ae323c7b72b50a01c8d78085306 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Mon, 21 May 2018 12:15:05 +0200 Subject: [PATCH 1/9] Graphics: Fix transition when new scene has gray tone effect Rendering the scene may cause PingPong swaps of front / backbuffer, so don't take references to those buffers until after rendering. Fixes #199 --- src/graphics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphics.cpp b/src/graphics.cpp index 6a12cb3..c53fe0e 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -708,6 +708,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 @@ -715,9 +718,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; From bab22d87be12da193e94e2dd6527504c874661b0 Mon Sep 17 00:00:00 2001 From: Eliza Velasquez <4576666+elizagamedev@users.noreply.github.com> Date: Sun, 7 Oct 2018 20:07:58 +0000 Subject: [PATCH 2/9] Fix font enumeration Currently, the font enumeration callback erroneously stops searching if it finds any files that aren't fonts. In the case that you have, say, a desktop.ini or a .DS_Store or a license file, it may prevent all of the fonts from being loaded. This commit resolves this. --- src/filesystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 33d383d..b898daa 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -469,7 +469,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 +479,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); From 43cb31886217c766fd3309edd1398e92da4420d0 Mon Sep 17 00:00:00 2001 From: Luis Caceres Date: Tue, 25 Sep 2018 18:58:10 +0100 Subject: [PATCH 3/9] Config: Add case-insensitive ini file parser --- CMakeLists.txt | 2 + mkxp.pro | 2 + src/config.cpp | 36 ++++++++------- src/iniconfig.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++ src/iniconfig.h | 46 +++++++++++++++++++ 5 files changed, 183 insertions(+), 17 deletions(-) create mode 100644 src/iniconfig.cpp create mode 100644 src/iniconfig.h 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..a275157 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -89,6 +89,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 +146,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 fee3b5a..85d148d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -33,6 +33,7 @@ #include "debugwriter.h" #include "util.h" #include "sdl-util.h" +#include "iniconfig.h" #ifdef INI_ENCODING extern "C" { @@ -310,26 +311,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 @@ -337,11 +344,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/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 From d4b9adc1d16cea45b30c9e4f6b8b020ef2b4a41a Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Thu, 21 Mar 2019 08:00:47 +0100 Subject: [PATCH 4/9] fluid-fun: Adjust function signature to fluidsynth 2.0 This breaks compilation with FLUID_SHARED against <2.0 versions, which should be reasonable given that the default mode can still dynamically load both variants. Fixes #219. --- src/fluid-fun.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fluid-fun.h b/src/fluid-fun.h index f26f9fe..8521348 100644 --- a/src/fluid-fun.h +++ b/src/fluid-fun.h @@ -19,7 +19,7 @@ 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); -typedef int (*DELETEFLUIDSYNTHPROC)(fluid_synth_t* synth); +typedef void (*DELETEFLUIDSYNTHPROC)(fluid_synth_t* synth); #define FLUID_FUNCS \ FLUID_FUN(settings_setnum, FLUIDSETTINGSSETNUMPROC) \ From 9dcfb66e86abc32061eaaacf1f842abdc5f9c34c Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Fri, 22 Mar 2019 21:15:03 +0100 Subject: [PATCH 5/9] fluid-fun: Define destructor signature based on fluidsynth version As per @carstene1ns 's suggestion. --- src/fluid-fun.cpp | 4 ---- src/fluid-fun.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) 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 8521348..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) \ From d6b477b887708441be066976d52859b1aa9c5a0e Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 18 May 2019 16:17:09 +0200 Subject: [PATCH 6/9] qmake.pro: Add explicit C++11 flags --- mkxp.pro | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mkxp.pro b/mkxp.pro index a275157..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 } From 6fa5b8c856a4e8cdd85b9080d051d604b8760a38 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 18 May 2019 16:21:21 +0200 Subject: [PATCH 7/9] Sprite: Define M_PI manually Apparently (older?) mingw-w64 with C++11 enabled doesn't have it. --- src/sprite.cpp | 3 +++ 1 file changed, 3 insertions(+) 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 From 98bdfcf7585ef3b3fcd4377a6d63b3f77cb6a33b Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 18 May 2019 16:22:53 +0200 Subject: [PATCH 8/9] FileSystem: Check PHYSFS_init() for success Move it above the allocations so exceptions don't leak memory. --- src/filesystem.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index b898daa..f448ac5 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -311,14 +311,23 @@ 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"); + p = new FileSystemPrivate; p->havePathCache = false; - PHYSFS_init(argv0); - PHYSFS_registerArchiver(&RGSS1_Archiver); PHYSFS_registerArchiver(&RGSS2_Archiver); PHYSFS_registerArchiver(&RGSS3_Archiver); From 86194118a366fa84414394a6b2da4563584b65e3 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 18 May 2019 16:48:17 +0200 Subject: [PATCH 9/9] FileSystem: Check PHYSFS_registerArchiver() for success --- src/filesystem.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index f448ac5..70d5065 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -325,13 +325,18 @@ FileSystem::FileSystem(const char *argv0, 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_registerArchiver(&RGSS1_Archiver); - PHYSFS_registerArchiver(&RGSS2_Archiver); - PHYSFS_registerArchiver(&RGSS3_Archiver); - if (allowSymlinks) PHYSFS_permitSymbolicLinks(1); }