diff --git a/docs/directory_structure.md b/docs/directory_structure.md index 72a62eee42..ba1b7673c8 100644 --- a/docs/directory_structure.md +++ b/docs/directory_structure.md @@ -38,6 +38,17 @@ your operating system: It includes the OpenTTD files (grf+lng) and it will work as long as they are not touched +7. The Atari Transport Tycoon Deluxe directory, if installed (path may vary) + + This refers to the `CD` folder within the Transport Tycoon Deluxe + installation folder (2026 Atari re-release). OpenTTD detects the presence + of this folder based upon the contents of the `installpath.ini` file located + in: + - Windows: `%APPDATA%\Atari\Transport Tycoon Deluxe` + - macOS: `~/Library/Application Support/Atari/Transport Tycoon Deluxe` + - Linux: `$XDG_DATA_HOME/Atari/Transport Tycoon Deluxe` + + This is used only for the loading of base sets (graphics, sound, music). Different types of data or extensions go into different subdirectories of the chosen main OpenTTD directory: diff --git a/src/fileio.cpp b/src/fileio.cpp index 90d943e74a..f1fc868e08 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -167,6 +167,9 @@ std::string FioGetDirectory(Searchpath sp, Subdirectory subdir) assert(subdir < Subdirectory::End); assert(sp < Searchpath::End); + /* For official TTD directory, don't include the subdirectory. */ + if (sp == Searchpath::TransportTycoonDeluxeDir && subdir == Subdirectory::Baseset) return _searchpaths[sp]; + return fmt::format("{}{}", _searchpaths[sp], _subdirs[subdir]); } @@ -197,7 +200,7 @@ static std::optional FioFOpenFileSp(std::string_view filename, std:: if (subdir == Subdirectory::None) { buf = filename; } else { - buf = fmt::format("{}{}{}", _searchpaths[sp], _subdirs[subdir], filename); + buf = fmt::format("{}{}", FioGetDirectory(sp, subdir), filename); } auto f = FileHandle::Open(buf, mode); @@ -871,6 +874,50 @@ extern void CocoaSetApplicationBundleDir(); #else _searchpaths[Searchpath::ApplicationBundleDir].clear(); #endif + + /* Look for Atari release of Transport Tycoon Deluxe for original data files */ + std::string config_file_path; + const std::string atari_ini_filename = "Atari/Transport Tycoon Deluxe/installpath.ini"; + + _searchpaths[Searchpath::TransportTycoonDeluxeDir].clear(); + +#ifdef WITH_COCOA +extern std::string CocoaGetAppSupportDir(); + config_file_path = CocoaGetAppSupportDir(); + + if (!config_file_path.empty()) { + AppendPathSeparator(config_file_path); + config_file_path += atari_ini_filename; + } +#else + config_file_path = GetHomeDir(); + + if (!config_file_path.empty()) { + AppendPathSeparator(config_file_path); + config_file_path += ".local/share/"; + config_file_path += atari_ini_filename; + } +#endif + + if (!config_file_path.empty()) { + size_t installpath_len; + std::unique_ptr installpath = ReadFileToMem(config_file_path, installpath_len, MAX_PATH); + + if (installpath != nullptr && installpath_len > 0) { + std::string ttd_path = installpath.get(); + AppendPathSeparator(ttd_path); + +#ifdef WITH_COCOA + /* The path provided is to the TTD.app/Contents/MacOS folder */ + ttd_path += "../Resources/"; +#endif + + ttd_path += "CD"; + AppendPathSeparator(ttd_path); + + if (FileExists(ttd_path)) _searchpaths[Searchpath::TransportTycoonDeluxeDir] = ttd_path; + } + } } #endif /* defined(_WIN32) */ diff --git a/src/fileio_type.h b/src/fileio_type.h index 208dd43ce6..cef4a0d315 100644 --- a/src/fileio_type.h +++ b/src/fileio_type.h @@ -121,6 +121,7 @@ enum class Searchpath : uint8_t { BinaryDir, ///< Search in the directory where the binary resides. InstallationDir, ///< Search in the installation directory. ApplicationBundleDir, ///< Search within the application bundle. + TransportTycoonDeluxeDir, ///< Search within the Transport Tycoon Deluxe data directory (if installed). AutodownloadDir, ///< Search within the autodownload directory. AutodownloadPersonalDir,///< Search within the autodownload directory located in the personal directory. AutodownloadPersonalDirXdg, ///< Search within the autodownload directory located in the personal directory (XDG variant). diff --git a/src/os/macosx/macos.mm b/src/os/macosx/macos.mm index c8e134588a..493b0f119d 100644 --- a/src/os/macosx/macos.mm +++ b/src/os/macosx/macos.mm @@ -138,6 +138,17 @@ void CocoaSetApplicationBundleDir() } } +/** + * Returns the path to the user's Application Support folder. + */ +std::string CocoaGetAppSupportDir() +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *appSupportPath = [paths firstObject]; + + return [appSupportPath UTF8String]; +} + /** * Setup autorelease for the application pool. * diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 0d2891836e..0d2e45fc79 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -322,6 +322,25 @@ void DetermineBasePaths(std::string_view exe) _searchpaths[Searchpath::InstallationDir].clear(); _searchpaths[Searchpath::ApplicationBundleDir].clear(); + _searchpaths[Searchpath::TransportTycoonDeluxeDir].clear(); + + if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, path))) { + std::string config_file_path(FS2OTTD(path)); + AppendPathSeparator(config_file_path); + config_file_path += "Atari\\Transport Tycoon Deluxe\\installpath.ini"; + + size_t installpath_len; + std::unique_ptr installpath = ReadFileToMem(config_file_path, installpath_len, MAX_PATH); + + if (installpath != nullptr && installpath_len > 0) { + std::string ttd_path = installpath.get(); + AppendPathSeparator(ttd_path); + ttd_path += "CD"; + AppendPathSeparator(ttd_path); + + if (FileExists(ttd_path)) _searchpaths[Searchpath::TransportTycoonDeluxeDir] = ttd_path; + } + } }