diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 40c63424bc..2148ce3f53 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -165,7 +165,6 @@ jobs: cmake --build build-cmake --config Release -j4 (cd build-cmake && cpack -G External) - mv README.md readme.txt mv build-cmake/*.appimage soh.appimage env: CC: gcc-12 @@ -174,9 +173,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: soh-linux - path: | - soh.appimage - readme.txt + path: soh.appimage - name: Save Cache deps folder if: ${{ github.ref_name == github.event.repository.default_branch }} uses: actions/cache/save@v5 diff --git a/README.md b/README.md index 4dd7f0315b..70a4fafb0d 100644 --- a/README.md +++ b/README.md @@ -21,27 +21,14 @@ You can verify you have dumped a supported copy of the game by using the compati * Launch `soh.exe` #### Linux -* Place your supported copy of the game in the same folder as the appimage. * Execute `soh.appimage`. You may have to `chmod +x` the appimage via terminal. +* When prompted, select your supported copy of the game. +* Saves, settings and `oot.o2r` are stored in `~/.local/share/soh/`. If the folder you launch from already has `shipofharkinian.json`, `oot.o2r` or `oot-mq.o2r`, that folder is used instead. Set `SHIP_HOME` to choose another folder. #### macOS * Run `soh.app`. When prompted, select your supported copy of the game. * You should see a notification saying `Processing OTR`, then, once the process is complete, you should get a notification saying `OTR Successfully Generated`, then the game should start. -#### Nintendo Switch -* Run one of the PC releases to generate an `oot.o2r` and/or `oot-mq.o2r` file. After launching the game on PC, you will be able to find these files in the same directory as `soh.exe` or `soh.appimage`. On macOS, these files can be found in `/Users//Library/Application Support/com.shipofharkinian.soh/` -* Copy the files to your sd card -``` -sdcard -└── switch - └── soh - ├── oot-mq.o2r - ├── oot.o2r - ├── soh.nro - └── soh.o2r -``` -* Launch via Atmosphere's `Game+R` launcher method. - ### 4. Play! Congratulations, you are now sailing with the Ship of Harkinian! Have fun! diff --git a/soh/soh/Extractor/Extract.cpp b/soh/soh/Extractor/Extract.cpp index b4c98f3927..4e6e26b768 100644 --- a/soh/soh/Extractor/Extract.cpp +++ b/soh/soh/Extractor/Extract.cpp @@ -257,15 +257,15 @@ void Extractor::GetRoms(std::vector& roms) { // Go through each file in the directory while ((dir = readdir(d)) != NULL) { struct stat path; + std::string fullPath = mSearchPath + "/" + dir->d_name; // Check if current entry is not folder - stat(dir->d_name, &path); - if (S_ISREG(path.st_mode)) { + if (stat(fullPath.c_str(), &path) == 0 && S_ISREG(path.st_mode)) { // Get the position of the extension character. char* ext = strrchr(dir->d_name, '.'); if (ext != NULL && (strcmp(ext, ".z64") == 0 || strcmp(ext, ".n64") == 0 || strcmp(ext, ".v64") == 0)) { - roms.push_back(dir->d_name); + roms.push_back(fullPath); } } } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 30b7dcd910..0341e4f366 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2,6 +2,7 @@ #include "OTRAudio.h" #include #include +#include #include #include #include @@ -1545,7 +1546,44 @@ bool VerifyArchiveVersion(OTRVersion version) { return version.major != INT16_MAX && version.major != gBuildVersionMajor; } +#ifdef __linux__ +// When run as an AppImage, keep user data in ~/.local/share/soh instead of the launch folder. +// Keep using the launch folder if it already has data from older versions. +static void SetAppImageHome() { + if (getenv("APPIMAGE") == nullptr || getenv("SHIP_HOME") != nullptr) { + return; + } + + for (const char* file : { "shipofharkinian.json", "oot.o2r", "oot-mq.o2r" }) { + if (std::filesystem::exists(file)) { + return; + } + } + + std::filesystem::path home; + const char* dataHome = getenv("XDG_DATA_HOME"); + const char* userHome = getenv("HOME"); + if (dataHome != nullptr && std::filesystem::path(dataHome).is_absolute()) { + home = dataHome; + } else if (userHome != nullptr && userHome[0] != '\0') { + home = std::filesystem::path(userHome) / ".local" / "share"; + } else { + return; + } + home /= appShortName; + + std::error_code ec; + std::filesystem::create_directories(home, ec); + if (!ec) { + setenv("SHIP_HOME", home.c_str(), 0); + } +} +#endif + extern "C" void InitOTR(int argc, char* argv[]) { +#ifdef __linux__ + SetAppImageHome(); +#endif OTRGlobals::Instance = new OTRGlobals(); OTRGlobals::Instance->RunExtract(argc, argv);