Files
eden/src/common/fs/path_util.h
T
CamilleLaVey ed566919f4 [vulkan, android] Add feature of post-processing shaders on Android (#4348)
Very self-explanatory; implementation of the feature for post-processing shaders for Android (at least for now); will allow users to enhance the graphic quality of video games based on the use of multiple shaders adjustable, presets and more, inspired on the PPSSPP implementation, this feature adds 22 customizable shaders (1 pass) that lives on the overlay of the screen, which means that aside of the capability to chain multiple shaders on the screen, this doesn't have depths (pixel/ depth z-buffer) so it ensures the performance with it's use. Few shaders were a faithful port from PPSSPP with their respective attribution on the shader headers for their respective owners; and there are adaptations from public references/ cinematographic (Anime4K) and the rest are my own addition.

_Special Credits:_

1.- PPSSPP Team for their contribution on the public references for shaders: Henrik Rydgard, ShadX, SimoneT, KillaMaaki and guest(r).
2.- Niklas Haas.
3.- bloc97.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4348
Reviewed-by: lizzie <lizzie@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-09-10 15:14:02 +02:00

377 lines
13 KiB
C++

// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <filesystem>
#include <vector>
#include "common/fs/fs_util.h"
namespace Common::FS {
enum class EdenPath {
EdenDir, // Where yuzu stores its data.
AmiiboDir, // Where Amiibo backups are stored.
CacheDir, // Where cached filesystem data is stored.
ConfigDir, // Where config files are stored.
CrashDumpsDir, // Where crash dumps are stored.
DumpDir, // Where dumped data is stored.
KeysDir, // Where key files are stored.
LoadDir, // Where cheat/mod files are stored.
LogDir, // Where log files are stored.
LosslessDir, // Where the user-supplied Lossless Scaling library is stored.
NANDDir, // Where the emulated NAND is stored.
PlayTimeDir, // Where play time data is stored.
PostPresetDir,
PostShaderDir, // Where user post-processing shaders are stored.
SaveDir, // Where save data is stored.
ScreenshotsDir, // Where yuzu screenshots are stored.
SDMCDir, // Where the emulated SDMC is stored.
ShaderDir, // Where shaders are stored.
TASDir, // Where TAS scripts are stored.
IconsDir, // Where Icons for Windows shortcuts are stored.
};
// migration/compat dirs
enum EmuPath {
CitronDir,
CitronConfigDir,
CitronCacheDir,
SudachiDir,
SudachiConfigDir,
SudachiCacheDir,
YuzuDir,
YuzuConfigDir,
YuzuCacheDir,
SuyuDir,
SuyuConfigDir,
SuyuCacheDir,
// used exclusively for save data linking
RyujinxDir,
};
/**
* Validates a given path.
*
* A given path is valid if it meets these conditions:
* - The path is not empty
* - The path is not too long
*
* @param path Filesystem path
*
* @returns True if the path is valid, false otherwise.
*/
[[nodiscard]] bool ValidatePath(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool ValidatePath(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return ValidatePath(ToU8String(path));
} else {
return ValidatePath(std::filesystem::path{path});
}
}
#endif
/**
* Concatenates two filesystem paths together.
*
* This is needed since the following occurs when using std::filesystem::path's operator/:
* first: "/first/path"
* second: "/second/path" (Note that the second path has a directory separator in the front)
* first / second yields "/second/path" when the desired result is first/path/second/path
*
* @param first First filesystem path
* @param second Second filesystem path
*
* @returns A concatenated filesystem path.
*/
[[nodiscard]] std::filesystem::path ConcatPath(const std::filesystem::path& first,
const std::filesystem::path& second);
#ifdef _WIN32
template <typename Path1, typename Path2>
[[nodiscard]] std::filesystem::path ConcatPath(const Path1& first, const Path2& second) {
using ValueType1 = typename Path1::value_type;
using ValueType2 = typename Path2::value_type;
if constexpr (IsChar<ValueType1> && IsChar<ValueType2>) {
return ConcatPath(ToU8String(first), ToU8String(second));
} else if constexpr (IsChar<ValueType1> && !IsChar<ValueType2>) {
return ConcatPath(ToU8String(first), second);
} else if constexpr (!IsChar<ValueType1> && IsChar<ValueType2>) {
return ConcatPath(first, ToU8String(second));
} else {
return ConcatPath(std::filesystem::path{first}, std::filesystem::path{second});
}
}
#endif
/**
* Safe variant of ConcatPath that takes in a base path and an offset path from the given base path.
*
* If ConcatPath(base, offset) resolves to a path that is sandboxed within the base path,
* this will return the concatenated path. Otherwise this will return the base path.
*
* @param base Base filesystem path
* @param offset Offset filesystem path
*
* @returns A concatenated filesystem path if it is within the base path,
* returns the base path otherwise.
*/
[[nodiscard]] std::filesystem::path ConcatPathSafe(const std::filesystem::path& base,
const std::filesystem::path& offset);
#ifdef _WIN32
template <typename Path1, typename Path2>
[[nodiscard]] std::filesystem::path ConcatPathSafe(const Path1& base, const Path2& offset) {
using ValueType1 = typename Path1::value_type;
using ValueType2 = typename Path2::value_type;
if constexpr (IsChar<ValueType1> && IsChar<ValueType2>) {
return ConcatPathSafe(ToU8String(base), ToU8String(offset));
} else if constexpr (IsChar<ValueType1> && !IsChar<ValueType2>) {
return ConcatPathSafe(ToU8String(base), offset);
} else if constexpr (!IsChar<ValueType1> && IsChar<ValueType2>) {
return ConcatPathSafe(base, ToU8String(offset));
} else {
return ConcatPathSafe(std::filesystem::path{base}, std::filesystem::path{offset});
}
}
#endif
/**
* Checks whether a given path is sandboxed within a given base path.
*
* @param base Base filesystem path
* @param path Filesystem path
*
* @returns True if the given path is sandboxed within the given base path, false otherwise.
*/
[[nodiscard]] bool IsPathSandboxed(const std::filesystem::path& base,
const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path1, typename Path2>
[[nodiscard]] bool IsPathSandboxed(const Path1& base, const Path2& path) {
using ValueType1 = typename Path1::value_type;
using ValueType2 = typename Path2::value_type;
if constexpr (IsChar<ValueType1> && IsChar<ValueType2>) {
return IsPathSandboxed(ToU8String(base), ToU8String(path));
} else if constexpr (IsChar<ValueType1> && !IsChar<ValueType2>) {
return IsPathSandboxed(ToU8String(base), path);
} else if constexpr (!IsChar<ValueType1> && IsChar<ValueType2>) {
return IsPathSandboxed(base, ToU8String(path));
} else {
return IsPathSandboxed(std::filesystem::path{base}, std::filesystem::path{path});
}
}
#endif
/**
* Checks if a character is a directory separator (either a forward slash or backslash).
*
* @param character Character
*
* @returns True if the character is a directory separator, false otherwise.
*/
[[nodiscard]] bool IsDirSeparator(char character);
/**
* Checks if a character is a directory separator (either a forward slash or backslash).
*
* @param character Character
*
* @returns True if the character is a directory separator, false otherwise.
*/
[[nodiscard]] bool IsDirSeparator(char8_t character);
/**
* Removes any trailing directory separators if they exist in the given path.
*
* @param path Filesystem path
*
* @returns The filesystem path without any trailing directory separators.
*/
[[nodiscard]] std::filesystem::path RemoveTrailingSeparators(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] std::filesystem::path RemoveTrailingSeparators(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveTrailingSeparators(ToU8String(path));
} else {
return RemoveTrailingSeparators(std::filesystem::path{path});
}
}
#endif
/**
* Sets the directory used for application storage. Used on Android where we do not know internal
* storage until informed by the frontend.
*
* @param app_directory Directory to use for application storage.
*/
void SetAppDirectory(const std::string& app_directory);
/**
* Gets the filesystem path associated with the EdenPath enum.
*
* @param eden_path EdenPath enum
*
* @returns The filesystem path associated with the EdenPath enum.
*/
[[nodiscard]] const std::filesystem::path& GetEdenPath(EdenPath eden_path);
/**
* Gets the filesystem path associated with the LegacyPath enum.
*
* @param legacy_path LegacyPath enum
*
* @returns The filesystem path associated with the LegacyPath enum.
*/
[[nodiscard]] const std::filesystem::path& GetLegacyPath(EmuPath legacy_path);
/**
* Gets the filesystem path associated with the EdenPath enum as a UTF-8 encoded std::string.
*
* @param eden_path EdenPath enum
*
* @returns The filesystem path associated with the EdenPath enum as a UTF-8 encoded std::string.
*/
[[nodiscard]] std::string GetEdenPathString(EdenPath eden_path);
/**
* Gets the filesystem path associated with the LegacyPath enum as a UTF-8 encoded std::string.
*
* @param legacy_path LegacyPath enum
*
* @returns The filesystem path associated with the LegacyPath enum as a UTF-8 encoded std::string.
*/
[[nodiscard]] std::string GetLegacyPathString(EmuPath legacy_path);
/**
* Sets a new filesystem path associated with the EdenPath enum.
* If the filesystem object at new_path is not a directory, this function will not do anything.
*
* @param eden_path EdenPath enum
* @param new_path New filesystem path
*/
void SetEdenPath(EdenPath eden_path, const std::filesystem::path& new_path);
/**
* Creates all necessary Eden paths in the filesystem.
*/
void CreateEdenPaths();
#ifdef _WIN32
template <typename Path>
void SetEdenPath(EdenPath eden_path, const Path& new_path) {
if constexpr (IsChar<typename Path::value_type>) {
SetEdenPath(eden_path, ToU8String(new_path));
} else {
SetEdenPath(eden_path, std::filesystem::path{new_path});
}
}
#endif
#ifdef _WIN32
/**
* Gets the path of the directory containing the executable of the current process.
*
* @returns The path of the directory containing the executable of the current process.
*/
[[nodiscard]] std::filesystem::path GetExeDirectory();
/**
* Gets the path of the current user's %APPDATA% directory (%USERPROFILE%/AppData/Roaming).
*
* @returns The path of the current user's %APPDATA% directory.
*/
[[nodiscard]] std::filesystem::path GetAppDataRoamingDirectory();
#else
/**
* Gets the path of the directory specified by the #HOME environment variable.
* If $HOME is not defined, it will attempt to query the user database in passwd instead.
*
* @returns The path of the current user's home directory.
*/
[[nodiscard]] std::filesystem::path GetHomeDirectory();
/**
* Gets the relevant paths for yuzu to store its data based on the given XDG environment variable.
* See https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
* Defaults to $HOME/.local/share for main application data,
* $HOME/.cache for cached data, and $HOME/.config for configuration files.
*
* @param env_name XDG environment variable name
*
* @returns The path where yuzu should store its data.
*/
[[nodiscard]] std::filesystem::path GetDataDirectory(const std::string& env_name);
#endif
#ifdef __APPLE__
[[nodiscard]] std::filesystem::path GetBundleDirectory();
#endif
// vvvvvvvvvv Deprecated vvvvvvvvvv //
// Removes the final '/' or '\' if one exists
[[nodiscard]] std::string_view RemoveTrailingSlash(std::string_view path);
enum class DirectorySeparator {
ForwardSlash,
BackwardSlash,
PlatformDefault,
};
// Splits the path on '/' or '\' and put the components into a vector
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
[[nodiscard]] std::vector<std::string_view> SplitPathComponents(std::string_view filename);
// Splits the path on '/' or '\' and put the components into a vector
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
[[nodiscard]] std::vector<std::string> SplitPathComponentsCopy(std::string_view filename);
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
[[nodiscard]] std::string SanitizePath(
std::string_view path,
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
// Gets all of the text up to the last '/' or '\' in the path.
[[nodiscard]] std::string GetParentPath(std::string_view path);
// Gets all of the text after the first '/' or '\' in the path.
[[nodiscard]] std::string_view GetPathWithoutTop(std::string_view path);
// Gets the filename of the path
[[nodiscard]] inline std::string_view GetFilename(const std::string_view path) noexcept {
if (auto const name_index = path.find_last_of("\\/"); name_index != std::string_view::npos)
return path.substr(name_index + 1);
return {};
}
// Gets the extension of the filename
[[nodiscard]] inline std::string_view GetExtensionFromFilename(const std::string_view name) noexcept {
if (auto const index = name.rfind('.'); index != std::string_view::npos)
return name.substr(index + 1);
return {};
}
} // namespace Common::FS