| 1361 | } |
| 1362 | |
| 1363 | String FileSystem::GetSavePath(StringView applicationName) |
| 1364 | { |
| 1365 | #if defined(DEATH_TARGET_ANDROID) |
| 1366 | StringView savePath = AndroidAssetStream::GetInternalDataPath(); |
| 1367 | if (!DirectoryExists(savePath)) { |
| 1368 | // Trying to create the data directory |
| 1369 | if (!CreateDirectories(savePath)) { |
| 1370 | return {}; |
| 1371 | } |
| 1372 | } |
| 1373 | return savePath; |
| 1374 | #elif defined(DEATH_TARGET_APPLE) |
| 1375 | StringView home = ::getenv("HOME"); |
| 1376 | if (home.empty()) { |
| 1377 | LOGE("Cannot find home directory"); |
| 1378 | return {}; |
| 1379 | } |
| 1380 | |
| 1381 | return CombinePath({ home, "Library/Application Support"_s, applicationName }); |
| 1382 | #elif defined(DEATH_TARGET_UNIX) || defined(DEATH_TARGET_EMSCRIPTEN) || defined(DEATH_TARGET_VITA) |
| 1383 | StringView config = ::getenv("XDG_CONFIG_HOME"); |
| 1384 | if (IsAbsolutePath(config)) { |
| 1385 | return CombinePath(config, applicationName); |
| 1386 | } |
| 1387 | |
| 1388 | StringView home = ::getenv("HOME"); |
| 1389 | if (home.empty()) { |
| 1390 | LOGE("Cannot find home directory"); |
| 1391 | return {}; |
| 1392 | } |
| 1393 | |
| 1394 | return CombinePath({ home, ".config"_s, applicationName }); |
| 1395 | #elif defined(DEATH_TARGET_WINDOWS_RT) |
| 1396 | auto appData = winrt::Windows::Storage::ApplicationData::Current().LocalFolder().Path(); |
| 1397 | return Death::Utf8::FromUtf16(appData.data(), appData.size()); |
| 1398 | #elif defined(DEATH_TARGET_WINDOWS) |
| 1399 | String result; |
| 1400 | wchar_t* pathW = nullptr; |
| 1401 | bool success = SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_SavedGames, KF_FLAG_DEFAULT, nullptr, &pathW)); |
| 1402 | if (!success || pathW == nullptr || pathW[0] == L'\0') { |
| 1403 | ::CoTaskMemFree(pathW); |
| 1404 | pathW = nullptr; |
| 1405 | // Fallback to "%AppData%\Roaming" if "%UserProfile%\Saved Games" cannot be found |
| 1406 | success = SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &pathW)); |
| 1407 | } |
| 1408 | if (success && pathW != nullptr && pathW[0] != L'\0') { |
| 1409 | std::int32_t pathLengthW = std::int32_t(wcslen(pathW)); |
| 1410 | SmallVector<char, MAX_PATH + 1> path(DefaultInit, pathLengthW * 4 + 1); |
| 1411 | std::size_t pathLength = Utf8::FromUtf16(path.data(), std::int32_t(path.size()), pathW, pathLengthW); |
| 1412 | result = CombinePath({ path.data(), pathLength }, applicationName); |
| 1413 | } else { |
| 1414 | LOGE("SHGetKnownFolderPath(FOLDERID_RoamingAppData) failed with error 0x{:.8x}", ::GetLastError()); |
| 1415 | } |
| 1416 | ::CoTaskMemFree(pathW); |
| 1417 | return result; |
| 1418 | #endif |
| 1419 | } |
| 1420 | |