diff --git a/.gitignore b/.gitignore index 275e8b6..57b9c15 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ logs/ **/*.exe **/*.out* resources/databases/* -games/* +games/ **/*.o ArcadeMachine **/.DS_Store diff --git a/include/ConfigData.h b/include/ConfigData.h index 348cc99..77d4015 100644 --- a/include/ConfigData.h +++ b/include/ConfigData.h @@ -63,7 +63,7 @@ class ConfigData //Setters: auto setId(int &i) { m_id = i; } - auto setFolder(std::string &dir) { m_folder = dir; } + void setFolder(std::string &dir); // Getters: auto id() const -> const int& { return m_id; } auto repo() const -> const std::string& { return m_repo; } diff --git a/include/Configuration.h b/include/Configuration.h index 537c24f..891ab0e 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -28,4 +28,13 @@ #define ARCADE_MACHINE_BINARY_EXT ".out" #endif -#endif \ No newline at end of file + +// Grid layout dimensions; guarded to prevent redefinition if ArcadeMachine.h is also included +#ifndef ROWS +#define ROWS 7 +#endif +#ifndef COLS +#define COLS 15 +#endif + +#endif diff --git a/include/Database.h b/include/Database.h index bc91bd9..e887e84 100644 --- a/include/Database.h +++ b/include/Database.h @@ -9,6 +9,30 @@ #include #include +// --------------------------------------------------------------------------- +// TEMPORARY: SplashKit database API is missing on Windows builds. +// These stubs allow the project to compile on Windows. On Linux/RPi, +// SplashKit provides the real API so no stubs are needed. +// TODO: Rewrite Database.h using raw SQLite3 (-lsqlite3) to restore functionality. +// --------------------------------------------------------------------------- +#if 1 +struct database {}; +struct query_result {}; +inline database open_database(std::string, std::string) { return {}; } +inline void free_database(database) {} +inline query_result run_sql(database, std::string) { return {}; } +inline bool query_success(query_result) { return false; } +inline bool has_row(query_result) { return false; } +inline bool get_next_row(query_result) { return false; } +inline void free_all_query_results() {} +inline int query_column_count(query_result) { return 0; } +inline std::string query_column_for_string(query_result, int) { return ""; } +inline double query_column_for_double(query_result, int) { return 0.0; } +inline int query_column_for_int(query_result, int) { return 0; } +inline std::string query_type_of_col(query_result, int) { return "NULL"; } +#endif +// --------------------------------------------------------------------------- + class Database { private: std::string m_databaseName; diff --git a/include/Helper.h b/include/Helper.h index 1f67fb9..3243f6d 100644 --- a/include/Helper.h +++ b/include/Helper.h @@ -32,6 +32,9 @@ class Helper { string getFolderName(string entryPath) { string dir = fs::path(entryPath).remove_filename().generic_string(); + // Remove trailing slash to prevent double-slash when concatenating paths later + if (!dir.empty() && (dir.back() == '/' || dir.back() == '\\')) + dir.pop_back(); std::cout << "Game-Directory Path: " << dir << "\n"; return dir; } @@ -46,6 +49,12 @@ class Helper { { vector files; + if (!fs::exists(dir) || !fs::is_directory(dir)) + { + std::cerr << "Warning: Games directory not found: " << dir << "\n"; + return files; + } + for (const auto & entry : fs::recursive_directory_iterator(dir)) { if (entry.path().filename() == "config.txt") @@ -55,6 +64,8 @@ class Helper { } } + std::cerr << "[Helper] found " << files.size() << " config files in " << dir << std::endl; + return files; } diff --git a/include/Rating.h b/include/Rating.h index 3fcfc92..51e5395 100644 --- a/include/Rating.h +++ b/include/Rating.h @@ -38,7 +38,7 @@ class Rating if (key_typed(LEFT_KEY)) { --_rating; - if (_rating < 0) + if (_rating < 1) _rating = _maxRating; updateGrid(); } diff --git a/resources/bundles/resources.txt b/resources/bundles/resources.txt index a632c5d..1e3bbb5 100644 --- a/resources/bundles/resources.txt +++ b/resources/bundles/resources.txt @@ -62,10 +62,10 @@ SOUND,intro_start,completed.wav // Music MUSIC,music_mainmenu,main_menu.mp3 -MUSIC, 1, 1.mp3 -MUSIC, 2, 2.mp3 -MUSIC, 3, 3.mp3 -MUSIC, music_about, insert-no-coins.ogg +MUSIC,1,1.mp3 +MUSIC,2,2.mp3 +MUSIC,3,3.mp3 +MUSIC,music_about,insert-no-coins.ogg // Animations ANIM,info-script,information.txt diff --git a/src/ConfigData.cpp b/src/ConfigData.cpp index 776ef46..3d17de7 100644 --- a/src/ConfigData.cpp +++ b/src/ConfigData.cpp @@ -3,12 +3,20 @@ #include "Configuration.h" #include #include -#include -#include +#include #include +#ifndef _WIN32 +#include +#endif +#if __cplusplus >= 201703L +#include +namespace fs = std::filesystem; +#else +#define _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_FILESYSTEM #include namespace fs = std::experimental::filesystem; +#endif /** * @brief Construct a new Config Data object @@ -18,6 +26,48 @@ namespace fs = std::experimental::filesystem; ConfigData::ConfigData(std::string configFile) { collectConfigData(readTxt(openFile(configFile))); + + if (this->m_title.empty()) + std::cerr << "[Config] missing field 'title' in: " << configFile << std::endl; + if (this->m_image.empty()) + std::cerr << "[Config] missing field 'image' in: " << configFile << std::endl; +} + +void ConfigData::setFolder(std::string &dir) +{ + m_folder = dir; + + fs::path buildsPath = fs::path(dir) / "builds"; + + if (!fs::exists(buildsPath) || !fs::is_directory(buildsPath)) + { + std::cerr << "[Config] no builds/ directory: " << dir << std::endl; + return; + } + + bool hasLinuxArm = false, hasLinuxX86 = false, hasWindows = false; + + for (const auto &entry : fs::directory_iterator(buildsPath)) + { + std::string name = entry.path().filename().string(); + if (name == "linux-arm.out") hasLinuxArm = true; + if (name == "linux-x86.out") hasLinuxX86 = true; + if (name == "windows-x86.exe") hasWindows = true; + } + + if (!hasLinuxArm && !hasLinuxX86 && !hasWindows) + { + std::cerr << "[Config] builds/ is empty: " << dir << std::endl; + return; + } + + std::string platforms = ""; + if (hasLinuxArm) platforms += "Linux ARM, "; + if (hasLinuxX86) platforms += "Linux x86, "; + if (hasWindows) platforms += "Windows, "; + platforms = platforms.substr(0, platforms.size() - 2); // trim trailing ", " + + std::cerr << "[Config] " << m_title << " supports: " << platforms << std::endl; } /** @@ -34,7 +84,7 @@ std::ifstream ConfigData::openFile(std::string file) if(configFile.fail()) { - std::cerr << "Error Opening File" << std::endl; + std::cerr << "[Config] failed to open file: " << file << std::endl; exit(1); } @@ -139,25 +189,34 @@ void ConfigData::collectJsonData(json json_configs) */ bool ConfigData::getFromGit(std::string url, const char* dir) { - // info struct lets us query the directory to see if it exists - struct stat info; - if (stat(dir, &info) != 0) - { - // cant access dir -- clone from scratch - system(("git clone " + url + " " + dir).c_str()); - } - else if (info.st_mode &S_IFDIR) + fs::path dirPath(dir); + bool isPull = fs::is_directory(dirPath) && fs::exists(dirPath / ".git"); + + int exitCode; + + if (isPull) { - // dir exists -- pull instead - system(("git -C " + std::string(dir) + " pull " + url).c_str()); + std::cerr << "[Git] pulling: " << url << " → " << dir << std::endl; + exitCode = system(("git -C " + std::string(dir) + " pull " + url).c_str()); } else { - // dir does not exist -- clone from scratch - system(("git clone " + url + " " + dir).c_str()); + std::cerr << "[Git] cloning: " << url << " → " << dir << std::endl; + exitCode = system(("git clone " + url + " " + dir).c_str()); } - return true; +#ifdef _WIN32 + bool success = (exitCode == 0); +#else + bool success = WIFEXITED(exitCode) && (WEXITSTATUS(exitCode) == 0); +#endif + + if (success) + std::cerr << "[Git] " << (isPull ? "pull" : "clone") << " succeeded: " << dir << std::endl; + else + std::cerr << "[Git] " << (isPull ? "pull" : "clone") << " failed: " << dir << std::endl; + + return success; } /**