From dbdd33d887100414ba6b02061ce2981983969d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Casas=20Sch=C3=B6ssow?= Date: Mon, 14 Nov 2022 20:06:09 +0100 Subject: [PATCH 1/5] Keep Supermodel files (config, nvram, saves, etc.) in a predictable path when running on Linux --- Makefiles/Makefile.UNIX | 3 + Makefiles/Makefile.Win32 | 1 + Src/OSD/FileSystemPath.h | 40 ++++++++++ Src/OSD/SDL/Main.cpp | 29 ++++--- Src/OSD/Unix/FileSystemPath.cpp | 122 +++++++++++++++++++++++++++++ Src/OSD/Windows/FileSystemPath.cpp | 37 +++++++++ 6 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 Src/OSD/FileSystemPath.h create mode 100644 Src/OSD/Unix/FileSystemPath.cpp create mode 100644 Src/OSD/Windows/FileSystemPath.cpp diff --git a/Makefiles/Makefile.UNIX b/Makefiles/Makefile.UNIX index d499234..1e48361 100644 --- a/Makefiles/Makefile.UNIX +++ b/Makefiles/Makefile.UNIX @@ -69,6 +69,9 @@ PLATFORM_LDFLAGS = $(SDL2_LIBS) -lGL -lGLU -lz -lm -lstdc++ -lpthread -lSDL2_net ############################################################################### # Core Makefile ############################################################################### + +PLATFORM_SRC_FILES = \ + Src/OSD/Unix/FileSystemPath.cpp include Makefiles/Rules.inc diff --git a/Makefiles/Makefile.Win32 b/Makefiles/Makefile.Win32 index 3e86534..0d984dc 100644 --- a/Makefiles/Makefile.Win32 +++ b/Makefiles/Makefile.Win32 @@ -103,6 +103,7 @@ PLATFORM_LDFLAGS = -static -L$(sort $(PLATFORM_LIB_DIR)) $(SDL2_LIBS) $(PLATFORM PLATFORM_SRC_FILES = \ Src/OSD/Windows/DirectInputSystem.cpp \ + Src/OSD/Windows/FileSystemPath.cpp \ Src/OSD/Windows/WinOutputs.cpp .PHONY: clean diff --git a/Src/OSD/FileSystemPath.h b/Src/OSD/FileSystemPath.h new file mode 100644 index 0000000..b23a92f --- /dev/null +++ b/Src/OSD/FileSystemPath.h @@ -0,0 +1,40 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2003-2022 The Supermodel Team + ** + ** This file is part of Supermodel. + ** + ** Supermodel is free software: you can redistribute it and/or modify it under + ** the terms of the GNU General Public License as published by the Free + ** Software Foundation, either version 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel is distributed in the hope that it will be useful, but WITHOUT + ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + ** more details. + ** + ** You should have received a copy of the GNU General Public License along + ** with Supermodel. If not, see . + **/ + +/* + * FileSystemPaths.h + * + * Header file for OS-dependent Supermodel files locations. + */ + +#ifndef INCLUDED_FILESYSTEMPATH_H +#define INCLUDED_FILESYSTEMPATH_H + +#include + +namespace FileSystemPath +{ + bool PathExists(std::string fileSystemPath); // Checks if a directory exists (returns true if exists, false if it doesn't) + std::string GetPath(std::string pathType); // Generates a path to be used by Supermodel files +} + + +#endif // INCLUDED_FILESYSTEMPATH_H diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index e0267e9..19fa4f4 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -66,6 +66,7 @@ #include "Util/Format.h" #include "Util/NewConfig.h" #include "Util/ConfigBuilders.h" +#include "OSD/FileSystemPath.h" #include "GameLoader.h" #include "SDLInputSystem.h" #include "SDLIncludes.h" @@ -475,7 +476,7 @@ void Screenshot() time_t now = std::time(nullptr); tm* ltm = std::localtime(&now); - sprintf(file, "Screenshot %.4d-%.2d-%.2d (%.2d-%.2d-%.2d).bmp", 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); + sprintf(file, "%sScreenshot %.4d-%.2d-%.2d (%.2d-%.2d-%.2d).bmp", FileSystemPath::GetPath("Screenshots").c_str(), 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); info += file; puts(info.c_str()); @@ -549,7 +550,7 @@ static void TestPolygonHeaderBits(IEmulator *Emu) if ((unknownPolyBits[idx] & mask)) { Emu->RenderFrame(); - std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << "poly" << "." << idx << "_" << Util::Hex(mask) << ".bmp"; + std::string file = Util::Format() << s_analysisPath << GetFileBaseName(s_gfxStatePath) << "." << "poly" << "." << idx << "_" << Util::Hex(mask) << ".bmp"; SaveFrameBuffer(file); } } @@ -565,7 +566,7 @@ static void TestPolygonHeaderBits(IEmulator *Emu) if ((unknownCullingNodeBits[idx] & mask)) { Emu->RenderFrame(); - std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << "culling" << "." << idx << "_" << Util::Hex(mask) << ".bmp"; + std::string file = Util::Format() << s_analysisPath << GetFileBaseName(s_gfxStatePath) << "." << "culling" << "." << idx << "_" << Util::Hex(mask) << ".bmp"; SaveFrameBuffer(file); } } @@ -574,7 +575,7 @@ static void TestPolygonHeaderBits(IEmulator *Emu) glReadBuffer(readBuffer); // Generate the HTML GUI - std::string file = Util::Format() << "Analysis/_" << GetFileBaseName(s_gfxStatePath) << ".html"; + std::string file = Util::Format() << s_analysisPath << "_" << GetFileBaseName(s_gfxStatePath) << ".html"; std::ofstream fs(file); if (!fs.good()) ErrorLog("Unable to open '%s' for writing.", file.c_str()); @@ -615,7 +616,7 @@ static void SaveState(IEmulator *Model3) { CBlockFile SaveState; - std::string file_path = Util::Format() << "Saves/" << Model3->GetGame().name << ".st" << s_saveSlot; + std::string file_path = Util::Format() << FileSystemPath::GetPath("Saves") << Model3->GetGame().name << ".st" << s_saveSlot; if (OKAY != SaveState.Create(file_path, "Supermodel Save State", "Supermodel Version " SUPERMODEL_VERSION)) { ErrorLog("Unable to save state to '%s'.", file_path.c_str()); @@ -640,7 +641,7 @@ static void LoadState(IEmulator *Model3, std::string file_path = std::string()) // Generate file path if (file_path.empty()) - file_path = Util::Format() << "Saves/" << Model3->GetGame().name << ".st" << s_saveSlot; + file_path = Util::Format() << FileSystemPath::GetPath("Saves") << Model3->GetGame().name << ".st" << s_saveSlot; // Open and check to make sure format is correct if (OKAY != SaveState.Load(file_path)) @@ -674,7 +675,7 @@ static void SaveNVRAM(IEmulator *Model3) { CBlockFile NVRAM; - std::string file_path = Util::Format() << "NVRAM/" << Model3->GetGame().name << ".nv"; + std::string file_path = Util::Format() << FileSystemPath::GetPath("NVRAM") << Model3->GetGame().name << ".nv"; if (OKAY != NVRAM.Create(file_path, "Supermodel NVRAM State", "Supermodel Version " SUPERMODEL_VERSION)) { ErrorLog("Unable to save NVRAM to '%s'. Make sure directory exists!", file_path.c_str()); @@ -697,7 +698,7 @@ static void LoadNVRAM(IEmulator *Model3) CBlockFile NVRAM; // Generate file path - std::string file_path = Util::Format() << "NVRAM/" << Model3->GetGame().name << ".nv"; + std::string file_path = Util::Format() << FileSystemPath::GetPath("NVRAM") << Model3->GetGame().name << ".nv"; // Open and check to make sure format is correct if (OKAY != NVRAM.Load(file_path)) @@ -1448,8 +1449,10 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In Entry Point and Command Line Procesing ******************************************************************************/ -static const char s_configFilePath[] = { "Config/Supermodel.ini" }; -static const char s_gameXMLFilePath[] = { "Config/Games.xml" }; +static const std::string s_analysisPath = Util::Format() << FileSystemPath::GetPath("Analysis"); +static const std::string s_configFilePath = Util::Format() << FileSystemPath::GetPath("Config") << "Supermodel.ini"; +static const std::string s_gameXMLFilePath = Util::Format() << FileSystemPath::GetPath("Config") << "Games.xml"; +static const std::string s_logFilePath = Util::Format() << FileSystemPath::GetPath("Log") << "Supermodel.log"; // Create and configure inputs static bool ConfigureInputs(CInputs *Inputs, Util::Config::Node *fileConfig, Util::Config::Node *runtimeConfig, const Game &game, bool configure) @@ -1640,8 +1643,8 @@ static void Help(void) puts("General Options:"); puts(" -?, -h, -help, --help Print this help text"); puts(" -print-games List supported games and quit"); - printf(" -game-xml-file= ROM set definition file [Default: %s]\n", s_gameXMLFilePath); - puts(" -log-output= Log output destination(s) [Default: Supermodel.log]"); + printf(" -game-xml-file= ROM set definition file [Default: %s]\n", s_gameXMLFilePath.c_str()); + printf(" -log-output= Log output destination(s) [Default: %s]\n", s_logFilePath.c_str()); puts(" -log-level= Logging threshold [Default: info]"); puts(""); puts("Core Options:"); @@ -1737,7 +1740,7 @@ struct ParsedCommandLine { // Logging is special: it is only parsed from the command line and // therefore, defaults are needed early - config.Set("LogOutput", "Supermodel.log"); + config.Set("LogOutput", s_logFilePath.c_str()); config.Set("LogLevel", "info"); } }; diff --git a/Src/OSD/Unix/FileSystemPath.cpp b/Src/OSD/Unix/FileSystemPath.cpp new file mode 100644 index 0000000..b7a8e8c --- /dev/null +++ b/Src/OSD/Unix/FileSystemPath.cpp @@ -0,0 +1,122 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2003-2022 The Supermodel Team + ** + ** This file is part of Supermodel. + ** + ** Supermodel is free software: you can redistribute it and/or modify it under + ** the terms of the GNU General Public License as published by the Free + ** Software Foundation, either version 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel is distributed in the hope that it will be useful, but WITHOUT + ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + ** more details. + ** + ** You should have received a copy of the GNU General Public License along + ** with Supermodel. If not, see . + **/ + +#include "FileSystemPath.h" +#include "Util/Format.h" +#include +#include +#include +#include +#include + +namespace FileSystemPath +{ + // Checks if a directory exists (returns true if exists, false if it doesn't) + bool PathExists(std::string fileSystemPath) + { + bool pathExists = false; + struct stat pathInfo; + + if (stat(fileSystemPath.c_str(), &pathInfo) == 0 && S_ISDIR(pathInfo.st_mode)) + { + pathExists = true; + } + + return pathExists; + + } + + // Generates a path to be used by Supermodel files + std::string GetPath(std::string pathType) + { + std::string finalPath = ""; + std::string homePath = ""; + struct passwd* pwd = getpwuid(getuid()); + + // Get user's HOME directory + if (pwd) + { + homePath = pwd->pw_dir; + } + else + { + homePath = getenv("HOME"); + } + + // If Config path exists in current directory or the user doesn't have a HOME directory use current directory + if (FileSystemPath::PathExists("Config") || homePath.empty()) + { + // Use current directory + if (pathType == "Screenshots" || pathType == "Log") + { + finalPath = ""; + } + else + { + // If directory doesn't exist, create it + if (!FileSystemPath::PathExists(pathType)) mkdir(pathType.c_str(), 0775); + finalPath = pathType; + } + + } + // Check if $HOME/.supermodel exists + else if (FileSystemPath::PathExists(Util::Format() << homePath << "/.supermodel")) + { + // Use $HOME/.supermodel + finalPath = Util::Format() << homePath << "/.supermodel/" << pathType; + // If directory doesn't exist, create it + if (!FileSystemPath::PathExists(finalPath)) + { + mkdir(finalPath.c_str(), 0775); + } + } + // On Linux one may want to follow the XDG base directory specs (https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) + else + { + // Use $HOME/.config/supermodel or $HOME/.local/share/supermodel depending on the file type + if (pathType == "Config") + { + finalPath = Util::Format() << homePath << "/.config/supermodel"; + // If directory doesn't exist, create it + if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + // If directory doesn't exist, create it + finalPath = Util::Format() << homePath << "/.config/supermodel/Config"; + if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + + } + else + { + finalPath = Util::Format() << homePath << "/.local/share/supermodel"; + // If directory doesn't exist, create it + if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + // If directory doesn't exist, create it + finalPath = Util::Format() << homePath << "/.local/share/supermodel/" << pathType; + if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + } + + } + + if (finalPath != "") finalPath = Util::Format() << finalPath << "/"; + + return finalPath; + + } +} diff --git a/Src/OSD/Windows/FileSystemPath.cpp b/Src/OSD/Windows/FileSystemPath.cpp new file mode 100644 index 0000000..66f9126 --- /dev/null +++ b/Src/OSD/Windows/FileSystemPath.cpp @@ -0,0 +1,37 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2003-2022 The Supermodel Team + ** + ** This file is part of Supermodel. + ** + ** Supermodel is free software: you can redistribute it and/or modify it under + ** the terms of the GNU General Public License as published by the Free + ** Software Foundation, either version 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel is distributed in the hope that it will be useful, but WITHOUT + ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + ** more details. + ** + ** You should have received a copy of the GNU General Public License along + ** with Supermodel. If not, see . + **/ + +#include "FileSystemPath.h" +#include + +namespace FileSystemPath +{ + // Generates a path to be used by Supermodel files + std::string GetPath(std::string pathType) + { + if (pathType == "Config") return "Config/"; + if (pathType == "Screenshots") return ""; + if (pathType == "Saves") return "Saves/"; + if (pathType == "NVRAM") return "NVRAM/"; + if (pathType == "Log") return ""; + if (pathType == "Analysis") return "Analysis/"; + } +} From 3aa11008be8207d04dc0be316ed7e1acdd6f36b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Casas=20Sch=C3=B6ssow?= Date: Tue, 15 Nov 2022 17:40:01 +0100 Subject: [PATCH 2/5] Changed pathType from string var to enum --- Src/OSD/FileSystemPath.h | 3 ++- Src/OSD/SDL/Main.cpp | 18 +++++++------- Src/OSD/Unix/FileSystemPath.cpp | 38 ++++++++++++++++++++++++------ Src/OSD/Windows/FileSystemPath.cpp | 23 ++++++++++++------ 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/Src/OSD/FileSystemPath.h b/Src/OSD/FileSystemPath.h index b23a92f..b192f2b 100644 --- a/Src/OSD/FileSystemPath.h +++ b/Src/OSD/FileSystemPath.h @@ -32,8 +32,9 @@ namespace FileSystemPath { + enum fsPathType { Analysis, Config, Log, NVRAM, Saves, Screenshots }; // Filesystem path types bool PathExists(std::string fileSystemPath); // Checks if a directory exists (returns true if exists, false if it doesn't) - std::string GetPath(std::string pathType); // Generates a path to be used by Supermodel files + std::string GetPath(fsPathType pathType); // Generates a path to be used by Supermodel files } diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 19fa4f4..c98d5d9 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -476,7 +476,7 @@ void Screenshot() time_t now = std::time(nullptr); tm* ltm = std::localtime(&now); - sprintf(file, "%sScreenshot %.4d-%.2d-%.2d (%.2d-%.2d-%.2d).bmp", FileSystemPath::GetPath("Screenshots").c_str(), 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); + sprintf(file, "%sScreenshot %.4d-%.2d-%.2d (%.2d-%.2d-%.2d).bmp", FileSystemPath::GetPath(FileSystemPath::Screenshots).c_str(), 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); info += file; puts(info.c_str()); @@ -616,7 +616,7 @@ static void SaveState(IEmulator *Model3) { CBlockFile SaveState; - std::string file_path = Util::Format() << FileSystemPath::GetPath("Saves") << Model3->GetGame().name << ".st" << s_saveSlot; + std::string file_path = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Saves) << Model3->GetGame().name << ".st" << s_saveSlot; if (OKAY != SaveState.Create(file_path, "Supermodel Save State", "Supermodel Version " SUPERMODEL_VERSION)) { ErrorLog("Unable to save state to '%s'.", file_path.c_str()); @@ -641,7 +641,7 @@ static void LoadState(IEmulator *Model3, std::string file_path = std::string()) // Generate file path if (file_path.empty()) - file_path = Util::Format() << FileSystemPath::GetPath("Saves") << Model3->GetGame().name << ".st" << s_saveSlot; + file_path = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Saves) << Model3->GetGame().name << ".st" << s_saveSlot; // Open and check to make sure format is correct if (OKAY != SaveState.Load(file_path)) @@ -675,7 +675,7 @@ static void SaveNVRAM(IEmulator *Model3) { CBlockFile NVRAM; - std::string file_path = Util::Format() << FileSystemPath::GetPath("NVRAM") << Model3->GetGame().name << ".nv"; + std::string file_path = Util::Format() << FileSystemPath::GetPath(FileSystemPath::NVRAM) << Model3->GetGame().name << ".nv"; if (OKAY != NVRAM.Create(file_path, "Supermodel NVRAM State", "Supermodel Version " SUPERMODEL_VERSION)) { ErrorLog("Unable to save NVRAM to '%s'. Make sure directory exists!", file_path.c_str()); @@ -698,7 +698,7 @@ static void LoadNVRAM(IEmulator *Model3) CBlockFile NVRAM; // Generate file path - std::string file_path = Util::Format() << FileSystemPath::GetPath("NVRAM") << Model3->GetGame().name << ".nv"; + std::string file_path = Util::Format() << FileSystemPath::GetPath(FileSystemPath::NVRAM) << Model3->GetGame().name << ".nv"; // Open and check to make sure format is correct if (OKAY != NVRAM.Load(file_path)) @@ -1449,10 +1449,10 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In Entry Point and Command Line Procesing ******************************************************************************/ -static const std::string s_analysisPath = Util::Format() << FileSystemPath::GetPath("Analysis"); -static const std::string s_configFilePath = Util::Format() << FileSystemPath::GetPath("Config") << "Supermodel.ini"; -static const std::string s_gameXMLFilePath = Util::Format() << FileSystemPath::GetPath("Config") << "Games.xml"; -static const std::string s_logFilePath = Util::Format() << FileSystemPath::GetPath("Log") << "Supermodel.log"; +static const std::string s_analysisPath = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Analysis); +static const std::string s_configFilePath = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Config) << "Supermodel.ini"; +static const std::string s_gameXMLFilePath = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Config) << "Games.xml"; +static const std::string s_logFilePath = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Log) << "Supermodel.log"; // Create and configure inputs static bool ConfigureInputs(CInputs *Inputs, Util::Config::Node *fileConfig, Util::Config::Node *runtimeConfig, const Game &game, bool configure) diff --git a/Src/OSD/Unix/FileSystemPath.cpp b/Src/OSD/Unix/FileSystemPath.cpp index b7a8e8c..ce899fe 100644 --- a/Src/OSD/Unix/FileSystemPath.cpp +++ b/Src/OSD/Unix/FileSystemPath.cpp @@ -45,12 +45,36 @@ namespace FileSystemPath } // Generates a path to be used by Supermodel files - std::string GetPath(std::string pathType) + std::string GetPath(fsPathType pathType) { std::string finalPath = ""; std::string homePath = ""; + std::string strPathType = ""; struct passwd* pwd = getpwuid(getuid()); + // Resolve pathType to string for later use + switch (pathType) + { + case Analysis: + strPathType = "Analysis"; + break; + case Config: + strPathType = "Config"; + break; + case Log: + strPathType = "Log"; + break; + case NVRAM: + strPathType = "NVRAM"; + break; + case Saves: + strPathType = "Saves"; + break; + case Screenshots: + strPathType = "Screenshots"; + break; + } + // Get user's HOME directory if (pwd) { @@ -65,15 +89,15 @@ namespace FileSystemPath if (FileSystemPath::PathExists("Config") || homePath.empty()) { // Use current directory - if (pathType == "Screenshots" || pathType == "Log") + if (pathType == Screenshots || pathType == Log) { finalPath = ""; } else { // If directory doesn't exist, create it - if (!FileSystemPath::PathExists(pathType)) mkdir(pathType.c_str(), 0775); - finalPath = pathType; + if (!FileSystemPath::PathExists(strPathType)) mkdir(strPathType.c_str(), 0775); + finalPath = strPathType; } } @@ -81,7 +105,7 @@ namespace FileSystemPath else if (FileSystemPath::PathExists(Util::Format() << homePath << "/.supermodel")) { // Use $HOME/.supermodel - finalPath = Util::Format() << homePath << "/.supermodel/" << pathType; + finalPath = Util::Format() << homePath << "/.supermodel/" << strPathType; // If directory doesn't exist, create it if (!FileSystemPath::PathExists(finalPath)) { @@ -92,7 +116,7 @@ namespace FileSystemPath else { // Use $HOME/.config/supermodel or $HOME/.local/share/supermodel depending on the file type - if (pathType == "Config") + if (pathType == Config) { finalPath = Util::Format() << homePath << "/.config/supermodel"; // If directory doesn't exist, create it @@ -108,7 +132,7 @@ namespace FileSystemPath // If directory doesn't exist, create it if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); // If directory doesn't exist, create it - finalPath = Util::Format() << homePath << "/.local/share/supermodel/" << pathType; + finalPath = Util::Format() << homePath << "/.local/share/supermodel/" << strPathType; if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); } diff --git a/Src/OSD/Windows/FileSystemPath.cpp b/Src/OSD/Windows/FileSystemPath.cpp index 66f9126..4390730 100644 --- a/Src/OSD/Windows/FileSystemPath.cpp +++ b/Src/OSD/Windows/FileSystemPath.cpp @@ -25,13 +25,22 @@ namespace FileSystemPath { // Generates a path to be used by Supermodel files - std::string GetPath(std::string pathType) + std::string GetPath(fsPathType pathType) { - if (pathType == "Config") return "Config/"; - if (pathType == "Screenshots") return ""; - if (pathType == "Saves") return "Saves/"; - if (pathType == "NVRAM") return "NVRAM/"; - if (pathType == "Log") return ""; - if (pathType == "Analysis") return "Analysis/"; + switch (pathType) + { + case Analysis: + return "Analysis/"; + case Config: + return "Config/"; + case Log: + return ""; + case NVRAM: + return "NVRAM/"; + case Saves: + return "Saves/"; + case Screenshots: + return ""; + } } } From 22dac30c031f8c9ff7dcb7ab6a40d8e4c184093c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Casas=20Sch=C3=B6ssow?= Date: Mon, 21 Nov 2022 22:27:15 +0100 Subject: [PATCH 3/5] First review code changes (identation and cosmetic changes) --- Src/OSD/FileSystemPath.h | 4 +- Src/OSD/Unix/FileSystemPath.cpp | 88 ++++++++++++++++++------------ Src/OSD/Windows/FileSystemPath.cpp | 26 ++++----- 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/Src/OSD/FileSystemPath.h b/Src/OSD/FileSystemPath.h index b192f2b..3c04b62 100644 --- a/Src/OSD/FileSystemPath.h +++ b/Src/OSD/FileSystemPath.h @@ -32,9 +32,9 @@ namespace FileSystemPath { - enum fsPathType { Analysis, Config, Log, NVRAM, Saves, Screenshots }; // Filesystem path types + enum PathType { Analysis, Config, Log, NVRAM, Saves, Screenshots }; // Filesystem path types bool PathExists(std::string fileSystemPath); // Checks if a directory exists (returns true if exists, false if it doesn't) - std::string GetPath(fsPathType pathType); // Generates a path to be used by Supermodel files + std::string GetPath(PathType pathType); // Generates a path to be used by Supermodel files } diff --git a/Src/OSD/Unix/FileSystemPath.cpp b/Src/OSD/Unix/FileSystemPath.cpp index ce899fe..4ab5916 100644 --- a/Src/OSD/Unix/FileSystemPath.cpp +++ b/Src/OSD/Unix/FileSystemPath.cpp @@ -45,45 +45,45 @@ namespace FileSystemPath } // Generates a path to be used by Supermodel files - std::string GetPath(fsPathType pathType) + std::string GetPath(PathType pathType) { std::string finalPath = ""; std::string homePath = ""; std::string strPathType = ""; - struct passwd* pwd = getpwuid(getuid()); + struct passwd* pwd = getpwuid(getuid()); // Resolve pathType to string for later use switch (pathType) { - case Analysis: - strPathType = "Analysis"; - break; - case Config: - strPathType = "Config"; - break; - case Log: - strPathType = "Log"; - break; - case NVRAM: - strPathType = "NVRAM"; - break; - case Saves: - strPathType = "Saves"; - break; - case Screenshots: - strPathType = "Screenshots"; - break; + case Analysis: + strPathType = "Analysis"; + break; + case Config: + strPathType = "Config"; + break; + case Log: + strPathType = "Log"; + break; + case NVRAM: + strPathType = "NVRAM"; + break; + case Saves: + strPathType = "Saves"; + break; + case Screenshots: + strPathType = "Screenshots"; + break; } // Get user's HOME directory - if (pwd) - { - homePath = pwd->pw_dir; - } - else - { - homePath = getenv("HOME"); - } + if (pwd) + { + homePath = pwd->pw_dir; + } + else + { + homePath = getenv("HOME"); + } // If Config path exists in current directory or the user doesn't have a HOME directory use current directory if (FileSystemPath::PathExists("Config") || homePath.empty()) @@ -96,10 +96,12 @@ namespace FileSystemPath else { // If directory doesn't exist, create it - if (!FileSystemPath::PathExists(strPathType)) mkdir(strPathType.c_str(), 0775); + if (!FileSystemPath::PathExists(strPathType)) + { + mkdir(strPathType.c_str(), 0775); + } finalPath = strPathType; } - } // Check if $HOME/.supermodel exists else if (FileSystemPath::PathExists(Util::Format() << homePath << "/.supermodel")) @@ -120,25 +122,39 @@ namespace FileSystemPath { finalPath = Util::Format() << homePath << "/.config/supermodel"; // If directory doesn't exist, create it - if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + if (!FileSystemPath::PathExists(finalPath)) + { + mkdir(finalPath.c_str(), 0775); + } // If directory doesn't exist, create it finalPath = Util::Format() << homePath << "/.config/supermodel/Config"; - if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); - + if (!FileSystemPath::PathExists(finalPath)) + { + mkdir(finalPath.c_str(), 0775); + } } else { finalPath = Util::Format() << homePath << "/.local/share/supermodel"; // If directory doesn't exist, create it - if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + if (!FileSystemPath::PathExists(finalPath)) + { + mkdir(finalPath.c_str(), 0775); + } // If directory doesn't exist, create it finalPath = Util::Format() << homePath << "/.local/share/supermodel/" << strPathType; - if (!FileSystemPath::PathExists(finalPath)) mkdir(finalPath.c_str(), 0775); + if (!FileSystemPath::PathExists(finalPath)) + { + mkdir(finalPath.c_str(), 0775); + } } } - if (finalPath != "") finalPath = Util::Format() << finalPath << "/"; + if (finalPath != "") + { + finalPath = Util::Format() << finalPath << "/"; + } return finalPath; diff --git a/Src/OSD/Windows/FileSystemPath.cpp b/Src/OSD/Windows/FileSystemPath.cpp index 4390730..9536d27 100644 --- a/Src/OSD/Windows/FileSystemPath.cpp +++ b/Src/OSD/Windows/FileSystemPath.cpp @@ -25,22 +25,22 @@ namespace FileSystemPath { // Generates a path to be used by Supermodel files - std::string GetPath(fsPathType pathType) + std::string GetPath(PathType pathType) { switch (pathType) { - case Analysis: - return "Analysis/"; - case Config: - return "Config/"; - case Log: - return ""; - case NVRAM: - return "NVRAM/"; - case Saves: - return "Saves/"; - case Screenshots: - return ""; + case Analysis: + return "Analysis/"; + case Config: + return "Config/"; + case Log: + return ""; + case NVRAM: + return "NVRAM/"; + case Saves: + return "Saves/"; + case Screenshots: + return ""; } } } From 1c4a9cd90b3b458623db5c890523b23cd1248472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Casas=20Sch=C3=B6ssow?= Date: Sun, 4 Dec 2022 19:42:19 +0100 Subject: [PATCH 4/5] Switched to Util::Format() to generate screenshot filename --- Src/OSD/SDL/Main.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index c98d5d9..5562543 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -471,15 +471,24 @@ static void SaveFrameBuffer(const std::string& file) void Screenshot() { // Make a screenshot - char file[128]; - std::string info = "Screenshot created: "; time_t now = std::time(nullptr); tm* ltm = std::localtime(&now); - - sprintf(file, "%sScreenshot %.4d-%.2d-%.2d (%.2d-%.2d-%.2d).bmp", FileSystemPath::GetPath(FileSystemPath::Screenshots).c_str(), 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); - - info += file; - puts(info.c_str()); + std::string file = Util::Format() << FileSystemPath::GetPath(FileSystemPath::Screenshots) + << "Screenshot_" + << std::setfill('0') << std::setw(4) << (1900 + ltm->tm_year) + << '-' + << std::setw(2) << (1 + ltm->tm_mon) + << '-' + << std::setw(2) << ltm->tm_mday + << "_(" + << std::setw(2) << ltm->tm_hour + << '-' + << std::setw(2) << ltm->tm_min + << '-' + << std::setw(2) << ltm->tm_sec + << ").bmp"; + + std::cout << "Screenshot created: " << file << std::endl; SaveFrameBuffer(file); } From ace45edffe6ede11e8e0b87a527d2f767eb7e045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Casas=20Sch=C3=B6ssow?= Date: Tue, 6 Dec 2022 13:25:20 +0100 Subject: [PATCH 5/5] Fixed build on macOS --- Makefiles/Makefile.OSX | 3 +++ Src/OSD/OSX/FileSystemPath.cpp | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Src/OSD/OSX/FileSystemPath.cpp diff --git a/Makefiles/Makefile.OSX b/Makefiles/Makefile.OSX index bb07732..1d23d1c 100644 --- a/Makefiles/Makefile.OSX +++ b/Makefiles/Makefile.OSX @@ -72,6 +72,9 @@ PLATFORM_LDFLAGS = $(SDL_LIBS) -lz -lm -lstdc++ -F/Library/Frameworks/ ############################################################################### # Core Makefile ############################################################################### + +PLATFORM_SRC_FILES = \ + Src/OSD/OSX/FileSystemPath.cpp include Makefiles/Rules.inc diff --git a/Src/OSD/OSX/FileSystemPath.cpp b/Src/OSD/OSX/FileSystemPath.cpp new file mode 100644 index 0000000..9536d27 --- /dev/null +++ b/Src/OSD/OSX/FileSystemPath.cpp @@ -0,0 +1,46 @@ +/** + ** Supermodel + ** A Sega Model 3 Arcade Emulator. + ** Copyright 2003-2022 The Supermodel Team + ** + ** This file is part of Supermodel. + ** + ** Supermodel is free software: you can redistribute it and/or modify it under + ** the terms of the GNU General Public License as published by the Free + ** Software Foundation, either version 3 of the License, or (at your option) + ** any later version. + ** + ** Supermodel is distributed in the hope that it will be useful, but WITHOUT + ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + ** more details. + ** + ** You should have received a copy of the GNU General Public License along + ** with Supermodel. If not, see . + **/ + +#include "FileSystemPath.h" +#include + +namespace FileSystemPath +{ + // Generates a path to be used by Supermodel files + std::string GetPath(PathType pathType) + { + switch (pathType) + { + case Analysis: + return "Analysis/"; + case Config: + return "Config/"; + case Log: + return ""; + case NVRAM: + return "NVRAM/"; + case Saves: + return "Saves/"; + case Screenshots: + return ""; + } + } +}