diff --git a/Common/Cpp/Filesystem/Filesystem.h b/Common/Cpp/Filesystem/Filesystem.h index 2396d86ea0..63b7f3f2c2 100644 --- a/Common/Cpp/Filesystem/Filesystem.h +++ b/Common/Cpp/Filesystem/Filesystem.h @@ -61,7 +61,8 @@ void rename(const Path& old_path, const Path& new_path, std::error_code& ec); Path current_path(); -Path application_path(); +Path application_binary_path(); +Path application_working_path(); diff --git a/Common/Cpp/Filesystem/Filesystem_Linux.h b/Common/Cpp/Filesystem/Filesystem_Linux.h index 51d3109835..f2264c22ef 100644 --- a/Common/Cpp/Filesystem/Filesystem_Linux.h +++ b/Common/Cpp/Filesystem/Filesystem_Linux.h @@ -12,7 +12,7 @@ namespace PokemonAutomation{ namespace Filesystem{ -Path application_path(){ +Path application_binary_path(){ char buffer[PATH_MAX]; ssize_t count = readlink("/proc/self/exe", buffer, PATH_MAX); if (count != -1) { @@ -20,6 +20,9 @@ Path application_path(){ } return Path(); } +Path application_working_path(){ + return application_binary_path(); +} diff --git a/Common/Cpp/Filesystem/Filesystem_Mac.h b/Common/Cpp/Filesystem/Filesystem_Mac.h index bf9b26abfd..95636fc1cb 100644 --- a/Common/Cpp/Filesystem/Filesystem_Mac.h +++ b/Common/Cpp/Filesystem/Filesystem_Mac.h @@ -4,15 +4,18 @@ * */ -#include #include +#include +#include +#include +#include #include "FilePath.h" namespace PokemonAutomation{ namespace Filesystem{ -Path application_path(){ +Path application_binary_path(){ char buffer[PATH_MAX]; uint32_t size = sizeof(buffer); if (_NSGetExecutablePath(buffer, &size) == 0) { @@ -23,5 +26,54 @@ Path application_path(){ +std::filesystem::path CFString_to_path(CFStringRef cfString) { + if (!cfString) { + return {}; + } + + // 1. Get the exact buffer size needed for the file system representation + CFIndex maxLength = CFStringGetMaximumSizeOfFileSystemRepresentation(cfString); + + // 2. Allocate a buffer to store the raw file system bytes + std::vector buffer(maxLength); + + // 3. Extract the file system representation directly into the buffer + if (CFStringGetFileSystemRepresentation(cfString, buffer.data(), buffer.size())) { + return std::filesystem::path(buffer.data()); + } + + // Fallback: If file-system specific translation failed, try standard UTF-8 text extraction + CFIndex length = CFStringGetLength(cfString); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; + std::vector fallbackBuffer(maxSize); + + if (CFStringGetCString(cfString, fallbackBuffer.data(), fallbackBuffer.size(), kCFStringEncodingUTF8)) { + return std::filesystem::path(fallbackBuffer.data()); + } + + return {}; +} +Path application_working_path(){ + // Use CFBundle to find the .app bundle path. + // Change working directory to the folder that hosts the .app bundle. + CFURLRef bundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + if (bundleURL){ + CFStringRef cfPath = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); + CFRelease(bundleURL); + if (cfPath){ + std::filesystem::path bundlePath = CFString_to_path(cfPath); + CFRelease(cfPath); + if (bundlePath.extension() == ".app"){ + return std::filesystem::absolute(bundlePath).parent_path().lexically_normal(); + } + } + } + + // Fallback + return application_binary_path(); +} + + + } } diff --git a/Common/Cpp/Filesystem/Filesystem_Qt.h b/Common/Cpp/Filesystem/Filesystem_Qt.h index 5a6aa70358..c9e3e7b0f1 100644 --- a/Common/Cpp/Filesystem/Filesystem_Qt.h +++ b/Common/Cpp/Filesystem/Filesystem_Qt.h @@ -11,10 +11,13 @@ namespace PokemonAutomation{ namespace Filesystem{ -Path application_path(){ +Path application_binary_path(){ QString application_dir_path = qApp->applicationDirPath(); return Path(application_dir_path.toStdString()); } +Path application_working_path(){ + return application_binary_path(); +} diff --git a/Common/Cpp/Filesystem/Filesystem_Windows.h b/Common/Cpp/Filesystem/Filesystem_Windows.h index 264876dd68..ddfbdb576e 100644 --- a/Common/Cpp/Filesystem/Filesystem_Windows.h +++ b/Common/Cpp/Filesystem/Filesystem_Windows.h @@ -11,11 +11,14 @@ namespace PokemonAutomation{ namespace Filesystem{ -Path application_path(){ +Path application_binary_path(){ wchar_t buffer[MAX_PATH]; GetModuleFileNameW(nullptr, buffer, MAX_PATH); return std::filesystem::path(buffer).parent_path(); } +Path application_working_path(){ + return application_binary_path(); +} diff --git a/SerialPrograms/Source/CommonFramework/GlobalAutoPaths.cpp b/SerialPrograms/Source/CommonFramework/GlobalAutoPaths.cpp index 185be4f0f0..844f0de064 100644 --- a/SerialPrograms/Source/CommonFramework/GlobalAutoPaths.cpp +++ b/SerialPrograms/Source/CommonFramework/GlobalAutoPaths.cpp @@ -11,9 +11,6 @@ #include #include #include -#if defined(__APPLE__) -#include -#endif #include "Common/Cpp/Filesystem/Filesystem.h" #include "GlobalAutoPaths.h" @@ -58,21 +55,7 @@ namespace{ Filesystem::Path get_application_base_dir_path(){ -#if defined(__APPLE__) - // Use CFBundle to find the .app bundle path. Change working directory to the folder that hosts the .app bundle. - CFURLRef bundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - if (bundleURL){ - CFStringRef cfPath = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); - CFRelease(bundleURL); - if (cfPath){ - QString bundlePath = QDir::cleanPath(QString::fromCFString(cfPath)); - CFRelease(cfPath); - if (bundlePath.endsWith(".app")){ - return QFileInfo(bundlePath).dir().absolutePath().toStdString(); - } - } - } -#elif defined(__linux__) +#if defined(__linux__) // Check for AppImage environment variables to find the root directory, if running as an AppImage. // PA_APPIMAGE_DIR is set by Azure via a patched AppRun script. QByteArray dir = qgetenv("PA_APPIMAGE_DIR"); @@ -108,7 +91,7 @@ Filesystem::Path get_application_base_dir_path(){ } } #endif - return Filesystem::application_path(); + return Filesystem::application_working_path(); } std::string get_resource_path(){ // Find the resource directory. diff --git a/SerialPrograms/Source/CommonFramework/Main.cpp b/SerialPrograms/Source/CommonFramework/Main.cpp index 61aa9eb129..744f84f9b2 100644 --- a/SerialPrograms/Source/CommonFramework/Main.cpp +++ b/SerialPrograms/Source/CommonFramework/Main.cpp @@ -109,7 +109,7 @@ int run_program(int argc, char *argv[]){ logger.log("================================================================================"); logger.log("Starting Program..."); logger.log("Current path: " + Filesystem::current_path().string_slash_normalized()); - logger.log("Executable path: " + Filesystem::application_path().string_slash_normalized()); + logger.log("Executable path: " + Filesystem::application_binary_path().string_slash_normalized()); logger.log("Program setting folder: " + SETTINGS_PATH()); logger.log("Program resources folder: " + RESOURCE_PATH());