diff options
-rwxr-xr-x | .travis/linux/build.sh | 2 | ||||
-rw-r--r-- | src/common/file_util.cpp | 449 | ||||
-rw-r--r-- | src/common/file_util.h | 73 | ||||
-rw-r--r-- | src/core/file_sys/vfs_real.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 60 | ||||
-rw-r--r-- | src/core/hle/service/nim/nim.cpp | 14 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 2 |
7 files changed, 429 insertions, 179 deletions
diff --git a/.travis/linux/build.sh b/.travis/linux/build.sh index 3929f97fc..0c7fb8c9d 100755 --- a/.travis/linux/build.sh +++ b/.travis/linux/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -ex mkdir -p "$HOME/.ccache" -docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh +docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/home/yuzu/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index a286b9341..18fbfa25b 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include <array> -#include <filesystem> #include <limits> #include <memory> #include <sstream> @@ -68,128 +67,290 @@ #include <algorithm> #include <sys/stat.h> +#ifndef S_ISDIR +#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#endif + +// This namespace has various generic functions related to files and paths. +// The code still needs a ton of cleanup. +// REMEMBER: strdup considered harmful! namespace Common::FS { -namespace fs = std::filesystem; -bool Exists(const fs::path& path) { - std::error_code ec; - return fs::exists(path, ec); +// Remove any ending forward slashes from directory paths +// Modifies argument. +static void StripTailDirSlashes(std::string& fname) { + if (fname.length() <= 1) { + return; + } + + std::size_t i = fname.length(); + while (i > 0 && fname[i - 1] == DIR_SEP_CHR) { + --i; + } + fname.resize(i); } -bool IsDirectory(const fs::path& path) { - std::error_code ec; - return fs::is_directory(path, ec); +bool Exists(const std::string& filename) { + struct stat file_info; + + std::string copy(filename); + StripTailDirSlashes(copy); + +#ifdef _WIN32 + // Windows needs a slash to identify a driver root + if (copy.size() != 0 && copy.back() == ':') + copy += DIR_SEP_CHR; + + int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info); +#else + int result = stat(copy.c_str(), &file_info); +#endif + + return (result == 0); } -bool Delete(const fs::path& path) { - LOG_TRACE(Common_Filesystem, "file {}", path.string()); +bool IsDirectory(const std::string& filename) { + struct stat file_info; - // Return true because we care about the file no - // being there, not the actual delete. - if (!Exists(path)) { - LOG_DEBUG(Common_Filesystem, "{} does not exist", path.string()); - return true; + std::string copy(filename); + StripTailDirSlashes(copy); + +#ifdef _WIN32 + // Windows needs a slash to identify a driver root + if (copy.size() != 0 && copy.back() == ':') + copy += DIR_SEP_CHR; + + int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info); +#else + int result = stat(copy.c_str(), &file_info); +#endif + + if (result < 0) { + LOG_DEBUG(Common_Filesystem, "stat failed on {}: {}", filename, GetLastErrorMsg()); + return false; } - std::error_code ec; - return fs::remove(path, ec); + return S_ISDIR(file_info.st_mode); } -bool CreateDir(const fs::path& path) { - LOG_TRACE(Common_Filesystem, "directory {}", path.string()); +bool Delete(const std::string& filename) { + LOG_TRACE(Common_Filesystem, "file {}", filename); - if (Exists(path)) { - LOG_DEBUG(Common_Filesystem, "path exists {}", path.string()); + // Return true because we care about the file no + // being there, not the actual delete. + if (!Exists(filename)) { + LOG_DEBUG(Common_Filesystem, "{} does not exist", filename); return true; } - std::error_code ec; - const bool success = fs::create_directory(path, ec); + // We can't delete a directory + if (IsDirectory(filename)) { + LOG_ERROR(Common_Filesystem, "Failed: {} is a directory", filename); + return false; + } - if (!success) { - LOG_ERROR(Common_Filesystem, "Unable to create directory: {}", ec.message()); +#ifdef _WIN32 + if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) { + LOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg()); + return false; + } +#else + if (unlink(filename.c_str()) == -1) { + LOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg()); return false; } +#endif return true; } -bool CreateDirs(const fs::path& path) { - LOG_TRACE(Common_Filesystem, "path {}", path.string()); - - if (Exists(path)) { - LOG_DEBUG(Common_Filesystem, "path exists {}", path.string()); +bool CreateDir(const std::string& path) { + LOG_TRACE(Common_Filesystem, "directory {}", path); +#ifdef _WIN32 + if (::CreateDirectoryW(Common::UTF8ToUTF16W(path).c_str(), nullptr)) + return true; + DWORD error = GetLastError(); + if (error == ERROR_ALREADY_EXISTS) { + LOG_DEBUG(Common_Filesystem, "CreateDirectory failed on {}: already exists", path); return true; } + LOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error); + return false; +#else + if (mkdir(path.c_str(), 0755) == 0) + return true; - std::error_code ec; - const bool success = fs::create_directories(path, ec); + int err = errno; - if (!success) { - LOG_ERROR(Common_Filesystem, "Unable to create directories: {}", ec.message()); - return false; + if (err == EEXIST) { + LOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path); + return true; } - return true; + LOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err)); + return false; +#endif } -bool CreateFullPath(const fs::path& path) { - LOG_TRACE(Common_Filesystem, "path {}", path); +bool CreateFullPath(const std::string& fullPath) { + int panicCounter = 100; + LOG_TRACE(Common_Filesystem, "path {}", fullPath); + + if (Exists(fullPath)) { + LOG_DEBUG(Common_Filesystem, "path exists {}", fullPath); + return true; + } + + std::size_t position = 0; + while (true) { + // Find next sub path + position = fullPath.find(DIR_SEP_CHR, position); - // Removes trailing slashes and turns any '\' into '/' - const auto new_path = SanitizePath(path.string(), DirectorySeparator::ForwardSlash); + // we're done, yay! + if (position == fullPath.npos) + return true; - if (new_path.rfind('.') == std::string::npos) { - // The path is a directory - return CreateDirs(new_path); - } else { - // The path is a file - // Creates directory preceding the last '/' - return CreateDirs(new_path.substr(0, new_path.rfind('/'))); + // Include the '/' so the first call is CreateDir("/") rather than CreateDir("") + std::string const subPath(fullPath.substr(0, position + 1)); + if (!IsDirectory(subPath) && !CreateDir(subPath)) { + LOG_ERROR(Common, "CreateFullPath: directory creation failed"); + return false; + } + + // A safety check + panicCounter--; + if (panicCounter <= 0) { + LOG_ERROR(Common, "CreateFullPath: directory structure is too deep"); + return false; + } + position++; } } -bool Rename(const fs::path& src, const fs::path& dst) { - LOG_TRACE(Common_Filesystem, "{} --> {}", src.string(), dst.string()); +bool DeleteDir(const std::string& filename) { + LOG_TRACE(Common_Filesystem, "directory {}", filename); - std::error_code ec; - fs::rename(src, dst, ec); - - if (ec) { - LOG_ERROR(Common_Filesystem, "Unable to rename file from {} to {}: {}", src.string(), - dst.string(), ec.message()); + // check if a directory + if (!IsDirectory(filename)) { + LOG_ERROR(Common_Filesystem, "Not a directory {}", filename); return false; } - return true; +#ifdef _WIN32 + if (::RemoveDirectoryW(Common::UTF8ToUTF16W(filename).c_str())) + return true; +#else + if (rmdir(filename.c_str()) == 0) + return true; +#endif + LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); + + return false; +} + +bool Rename(const std::string& srcFilename, const std::string& destFilename) { + LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); +#ifdef _WIN32 + if (_wrename(Common::UTF8ToUTF16W(srcFilename).c_str(), + Common::UTF8ToUTF16W(destFilename).c_str()) == 0) + return true; +#else + if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) + return true; +#endif + LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, + GetLastErrorMsg()); + return false; } -bool Copy(const fs::path& src, const fs::path& dst) { - LOG_TRACE(Common_Filesystem, "{} --> {}", src.string(), dst.string()); +bool Copy(const std::string& srcFilename, const std::string& destFilename) { + LOG_TRACE(Common_Filesystem, "{} --> {}", srcFilename, destFilename); +#ifdef _WIN32 + if (CopyFileW(Common::UTF8ToUTF16W(srcFilename).c_str(), + Common::UTF8ToUTF16W(destFilename).c_str(), FALSE)) + return true; - std::error_code ec; - const bool success = fs::copy_file(src, dst, fs::copy_options::overwrite_existing, ec); + LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename, + GetLastErrorMsg()); + return false; +#else + using CFilePointer = std::unique_ptr<FILE, decltype(&std::fclose)>; - if (!success) { - LOG_ERROR(Common_Filesystem, "Unable to copy file {} to {}: {}", src.string(), dst.string(), - ec.message()); + // Open input file + CFilePointer input{fopen(srcFilename.c_str(), "rb"), std::fclose}; + if (!input) { + LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename, + destFilename, GetLastErrorMsg()); return false; } + // open output file + CFilePointer output{fopen(destFilename.c_str(), "wb"), std::fclose}; + if (!output) { + LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename, + destFilename, GetLastErrorMsg()); + return false; + } + + // copy loop + std::array<char, 1024> buffer; + while (!feof(input.get())) { + // read input + std::size_t rnum = fread(buffer.data(), sizeof(char), buffer.size(), input.get()); + if (rnum != buffer.size()) { + if (ferror(input.get()) != 0) { + LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", + srcFilename, destFilename, GetLastErrorMsg()); + return false; + } + } + + // write output + std::size_t wnum = fwrite(buffer.data(), sizeof(char), rnum, output.get()); + if (wnum != rnum) { + LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename, + destFilename, GetLastErrorMsg()); + return false; + } + } + return true; +#endif } -u64 GetSize(const fs::path& path) { - std::error_code ec; - const auto size = fs::file_size(path, ec); +u64 GetSize(const std::string& filename) { + if (!Exists(filename)) { + LOG_ERROR(Common_Filesystem, "failed {}: No such file", filename); + return 0; + } - if (ec) { - LOG_ERROR(Common_Filesystem, "Unable to retrieve file size ({}): {}", path.string(), - ec.message()); + if (IsDirectory(filename)) { + LOG_ERROR(Common_Filesystem, "failed {}: is a directory", filename); return 0; } - return size; + struct stat buf; +#ifdef _WIN32 + if (_wstat64(Common::UTF8ToUTF16W(filename).c_str(), &buf) == 0) +#else + if (stat(filename.c_str(), &buf) == 0) +#endif + { + LOG_TRACE(Common_Filesystem, "{}: {}", filename, buf.st_size); + return buf.st_size; + } + + LOG_ERROR(Common_Filesystem, "Stat failed {}: {}", filename, GetLastErrorMsg()); + return 0; +} + +u64 GetSize(const int fd) { + struct stat buf; + if (fstat(fd, &buf) != 0) { + LOG_ERROR(Common_Filesystem, "GetSize: stat failed {}: {}", fd, GetLastErrorMsg()); + return 0; + } + return buf.st_size; } u64 GetSize(FILE* f) { @@ -239,7 +400,7 @@ bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, } // windows loop do { - const std::string virtual_name = std::filesystem::path(ffd.cFileName).string(); + const std::string virtual_name(Common::UTF16ToUTF8(ffd.cFileName)); #else DIR* dirp = opendir(directory.c_str()); if (!dirp) @@ -277,58 +438,132 @@ bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, return true; } -bool DeleteDirRecursively(const fs::path& path) { - std::error_code ec; - fs::remove_all(path, ec); +u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, + unsigned int recursion) { + const auto callback = [recursion, &parent_entry](u64* num_entries_out, + const std::string& directory, + const std::string& virtual_name) -> bool { + FSTEntry entry; + entry.virtualName = virtual_name; + entry.physicalName = directory + DIR_SEP + virtual_name; + + if (IsDirectory(entry.physicalName)) { + entry.isDirectory = true; + // is a directory, lets go inside if we didn't recurse to often + if (recursion > 0) { + entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); + *num_entries_out += entry.size; + } else { + entry.size = 0; + } + } else { // is a file + entry.isDirectory = false; + entry.size = GetSize(entry.physicalName); + } + (*num_entries_out)++; - if (ec) { - LOG_ERROR(Common_Filesystem, "Unable to completely delete directory {}: {}", path.string(), - ec.message()); - return false; - } + // Push into the tree + parent_entry.children.push_back(std::move(entry)); + return true; + }; - return true; + u64 num_entries; + return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; } -void CopyDir(const fs::path& src, const fs::path& dst) { - constexpr auto copy_flags = fs::copy_options::skip_existing | fs::copy_options::recursive; +bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) { + const auto callback = [recursion](u64*, const std::string& directory, + const std::string& virtual_name) { + const std::string new_path = directory + DIR_SEP_CHR + virtual_name; - std::error_code ec; - fs::copy(src, dst, copy_flags, ec); + if (IsDirectory(new_path)) { + if (recursion == 0) { + return false; + } + return DeleteDirRecursively(new_path, recursion - 1); + } + return Delete(new_path); + }; - if (ec) { - LOG_ERROR(Common_Filesystem, "Error copying directory {} to {}: {}", src.string(), - dst.string(), ec.message()); - return; - } + if (!ForeachDirectoryEntry(nullptr, directory, callback)) + return false; - LOG_TRACE(Common_Filesystem, "Successfully copied directory."); + // Delete the outermost directory + DeleteDir(directory); + return true; } -std::optional<fs::path> GetCurrentDir() { - std::error_code ec; - auto path = fs::current_path(ec); +void CopyDir([[maybe_unused]] const std::string& source_path, + [[maybe_unused]] const std::string& dest_path) { +#ifndef _WIN32 + if (source_path == dest_path) { + return; + } + if (!Exists(source_path)) { + return; + } + if (!Exists(dest_path)) { + CreateFullPath(dest_path); + } - if (ec) { - LOG_ERROR(Common_Filesystem, "Unable to retrieve current working directory: {}", - ec.message()); - return std::nullopt; + DIR* dirp = opendir(source_path.c_str()); + if (!dirp) { + return; } - return {std::move(path)}; -} + while (struct dirent* result = readdir(dirp)) { + const std::string virtualName(result->d_name); + // check for "." and ".." + if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || + ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) { + continue; + } -bool SetCurrentDir(const fs::path& path) { - std::error_code ec; - fs::current_path(path, ec); + std::string source, dest; + source = source_path + virtualName; + dest = dest_path + virtualName; + if (IsDirectory(source)) { + source += '/'; + dest += '/'; + if (!Exists(dest)) { + CreateFullPath(dest); + } + CopyDir(source, dest); + } else if (!Exists(dest)) { + Copy(source, dest); + } + } + closedir(dirp); +#endif +} - if (ec) { - LOG_ERROR(Common_Filesystem, "Unable to set {} as working directory: {}", path.string(), - ec.message()); - return false; +std::optional<std::string> GetCurrentDir() { +// Get the current working directory (getcwd uses malloc) +#ifdef _WIN32 + wchar_t* dir = _wgetcwd(nullptr, 0); + if (!dir) { +#else + char* dir = getcwd(nullptr, 0); + if (!dir) { +#endif + LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); + return std::nullopt; } +#ifdef _WIN32 + std::string strDir = Common::UTF16ToUTF8(dir); +#else + std::string strDir = dir; +#endif + free(dir); + return strDir; +} - return true; +bool SetCurrentDir(const std::string& directory) { +#ifdef _WIN32 + return _wchdir(Common::UTF8ToUTF16W(directory).c_str()) == 0; +#else + return chdir(directory.c_str()) == 0; +#endif } #if defined(__APPLE__) diff --git a/src/common/file_util.h b/src/common/file_util.h index cf006cc9d..840cde2a6 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -6,7 +6,6 @@ #include <array> #include <cstdio> -#include <filesystem> #include <fstream> #include <functional> #include <limits> @@ -39,40 +38,48 @@ enum class UserPath { UserDir, }; -// Returns true if the path exists -[[nodiscard]] bool Exists(const std::filesystem::path& path); +// FileSystem tree node/ +struct FSTEntry { + bool isDirectory; + u64 size; // file length or number of entries from children + std::string physicalName; // name on disk + std::string virtualName; // name in FST names table + std::vector<FSTEntry> children; +}; + +// Returns true if file filename exists +[[nodiscard]] bool Exists(const std::string& filename); -// Returns true if path is a directory -[[nodiscard]] bool IsDirectory(const std::filesystem::path& path); +// Returns true if filename is a directory +[[nodiscard]] bool IsDirectory(const std::string& filename); // Returns the size of filename (64bit) -[[nodiscard]] u64 GetSize(const std::filesystem::path& path); +[[nodiscard]] u64 GetSize(const std::string& filename); + +// Overloaded GetSize, accepts file descriptor +[[nodiscard]] u64 GetSize(int fd); // Overloaded GetSize, accepts FILE* [[nodiscard]] u64 GetSize(FILE* f); // Returns true if successful, or path already exists. -bool CreateDir(const std::filesystem::path& path); +bool CreateDir(const std::string& filename); -// Create all directories in path -// Returns true if successful, or path already exists. -[[nodiscard("Directory creation can fail and must be tested")]] bool CreateDirs( - const std::filesystem::path& path); +// Creates the full path of fullPath returns true on success +bool CreateFullPath(const std::string& fullPath); -// Creates directories in path. Returns true on success. -[[deprecated("This function is deprecated, use CreateDirs")]] bool CreateFullPath( - const std::filesystem::path& path); +// Deletes a given filename, return true on success +// Doesn't supports deleting a directory +bool Delete(const std::string& filename); -// Deletes a given file at the path. -// This will also delete empty directories. -// Return true on success -bool Delete(const std::filesystem::path& path); +// Deletes a directory filename, returns true on success +bool DeleteDir(const std::string& filename); -// Renames file src to dst, returns true on success -bool Rename(const std::filesystem::path& src, const std::filesystem::path& dst); +// renames file srcFilename to destFilename, returns true on success +bool Rename(const std::string& srcFilename, const std::string& destFilename); -// copies file src to dst, returns true on success -bool Copy(const std::filesystem::path& src, const std::filesystem::path& dst); +// copies file srcFilename to destFilename, returns true on success +bool Copy(const std::string& srcFilename, const std::string& destFilename); // creates an empty file filename, returns true on success bool CreateEmptyFile(const std::string& filename); @@ -99,17 +106,27 @@ using DirectoryEntryCallable = std::function<bool( bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory, DirectoryEntryCallable callback); -// Deletes the given path and anything under it. Returns true on success. -bool DeleteDirRecursively(const std::filesystem::path& path); +/** + * Scans the directory tree, storing the results. + * @param directory the parent directory to start scanning from + * @param parent_entry FSTEntry where the filesystem tree results will be stored. + * @param recursion Number of children directories to read before giving up. + * @return the total number of files/directories found + */ +u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry, + unsigned int recursion = 0); + +// deletes the given directory and anything under it. Returns true on success. +bool DeleteDirRecursively(const std::string& directory, unsigned int recursion = 256); // Returns the current directory -[[nodiscard]] std::optional<std::filesystem::path> GetCurrentDir(); +[[nodiscard]] std::optional<std::string> GetCurrentDir(); // Create directory and copy contents (does not overwrite existing files) -void CopyDir(const std::filesystem::path& src, const std::filesystem::path& dst); +void CopyDir(const std::string& source_path, const std::string& dest_path); -// Set the current directory to given path -bool SetCurrentDir(const std::filesystem::path& path); +// Set the current directory to given directory +bool SetCurrentDir(const std::string& directory); // Returns a pointer to a string with a yuzu data dir in the user's home // directory. To be used in "multi-user" mode (that is, installed). diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 26ffd8a9d..a287eebe3 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -94,13 +94,9 @@ VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault); - const auto parent_path = FS::GetParentPath(path); - + const auto path_fwd = FS::SanitizePath(path, FS::DirectorySeparator::ForwardSlash); if (!FS::Exists(path)) { - if (!FS::CreateDirs(parent_path)) { - return nullptr; - } - + FS::CreateFullPath(path_fwd); if (!FS::CreateEmptyFile(path)) { return nullptr; } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 95d6e2b4d..c8060f179 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -234,8 +234,7 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, u32 attribute) { - return SetMemoryAttribute(system, static_cast<VAddr>(address), static_cast<std::size_t>(size), - mask, attribute); + return SetMemoryAttribute(system, address, size, mask, attribute); } /// Maps a memory range into a different range. @@ -255,8 +254,7 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr } static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { - return MapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), - static_cast<std::size_t>(size)); + return MapMemory(system, dst_addr, src_addr, size); } /// Unmaps a region that was previously mapped with svcMapMemory @@ -276,8 +274,7 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad } static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { - return UnmapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), - static_cast<std::size_t>(size)); + return UnmapMemory(system, dst_addr, src_addr, size); } /// Connect to an OS service given the port name, returns the handle to the port to out @@ -531,8 +528,7 @@ static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_hand static ResultCode ArbitrateLock32(Core::System& system, Handle holding_thread_handle, u32 mutex_addr, Handle requesting_thread_handle) { - return ArbitrateLock(system, holding_thread_handle, static_cast<VAddr>(mutex_addr), - requesting_thread_handle); + return ArbitrateLock(system, holding_thread_handle, mutex_addr, requesting_thread_handle); } /// Unlock a mutex @@ -555,7 +551,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { } static ResultCode ArbitrateUnlock32(Core::System& system, u32 mutex_addr) { - return ArbitrateUnlock(system, static_cast<VAddr>(mutex_addr)); + return ArbitrateUnlock(system, mutex_addr); } enum class BreakType : u32 { @@ -677,7 +673,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { } static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { - Break(system, reason, static_cast<u64>(info1), static_cast<u64>(info2)); + Break(system, reason, info1, info2); } /// Used to output a message on a debug hardware unit - does nothing on a retail unit @@ -948,7 +944,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low, u32 info_id, u32 handle, u32 sub_id_high) { - const u64 sub_id{static_cast<u64>(sub_id_low | (static_cast<u64>(sub_id_high) << 32))}; + const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)}; u64 res_value{}; const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)}; @@ -1009,7 +1005,7 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) } static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { - return MapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); + return MapPhysicalMemory(system, addr, size); } /// Unmaps memory previously mapped via MapPhysicalMemory @@ -1063,7 +1059,7 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size } static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { - return UnmapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); + return UnmapPhysicalMemory(system, addr, size); } /// Sets the thread activity @@ -1144,7 +1140,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H } static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { - return GetThreadContext(system, static_cast<VAddr>(thread_context), handle); + return GetThreadContext(system, thread_context, handle); } /// Gets the priority for the specified thread @@ -1281,8 +1277,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, u32 size, u32 permissions) { - return MapSharedMemory(system, shared_memory_handle, static_cast<VAddr>(addr), - static_cast<std::size_t>(size), permissions); + return MapSharedMemory(system, shared_memory_handle, addr, size, permissions); } static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, @@ -1552,8 +1547,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { - return CreateThread(system, out_handle, static_cast<VAddr>(entry_point), static_cast<u64>(arg), - static_cast<VAddr>(stack_top), priority, processor_id); + return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id); } /// Starts the thread for the provided handle @@ -1637,8 +1631,7 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { } static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) { - const s64 nanoseconds = static_cast<s64>(static_cast<u64>(nanoseconds_low) | - (static_cast<u64>(nanoseconds_high) << 32)); + const auto nanoseconds = static_cast<s64>(u64{nanoseconds_low} | (u64{nanoseconds_high} << 32)); SleepThread(system, nanoseconds); } @@ -1724,10 +1717,8 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 mutex_addr, u32 condition_variable_addr, Handle thread_handle, u32 nanoseconds_low, u32 nanoseconds_high) { - const s64 nanoseconds = - static_cast<s64>(nanoseconds_low | (static_cast<u64>(nanoseconds_high) << 32)); - return WaitProcessWideKeyAtomic(system, static_cast<VAddr>(mutex_addr), - static_cast<VAddr>(condition_variable_addr), thread_handle, + const auto nanoseconds = static_cast<s64>(nanoseconds_low | (u64{nanoseconds_high} << 32)); + return WaitProcessWideKeyAtomic(system, mutex_addr, condition_variable_addr, thread_handle, nanoseconds); } @@ -1833,8 +1824,8 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, static ResultCode WaitForAddress32(Core::System& system, u32 address, u32 type, s32 value, u32 timeout_low, u32 timeout_high) { - s64 timeout = static_cast<s64>(timeout_low | (static_cast<u64>(timeout_high) << 32)); - return WaitForAddress(system, static_cast<VAddr>(address), type, value, timeout); + const auto timeout = static_cast<s64>(timeout_low | (u64{timeout_high} << 32)); + return WaitForAddress(system, address, type, value, timeout); } // Signals to an address (via Address Arbiter) @@ -1862,7 +1853,7 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, static ResultCode SignalToAddress32(Core::System& system, u32 address, u32 type, s32 value, s32 num_to_wake) { - return SignalToAddress(system, static_cast<VAddr>(address), type, value, num_to_wake); + return SignalToAddress(system, address, type, value, num_to_wake); } static void KernelDebug([[maybe_unused]] Core::System& system, @@ -1893,7 +1884,7 @@ static u64 GetSystemTick(Core::System& system) { } static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) { - u64 time = GetSystemTick(system); + const auto time = GetSystemTick(system); *time_low = static_cast<u32>(time); *time_high = static_cast<u32>(time >> 32); } @@ -1984,8 +1975,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, u32 permissions) { - return CreateTransferMemory(system, handle, static_cast<VAddr>(addr), - static_cast<std::size_t>(size), permissions); + return CreateTransferMemory(system, handle, addr, size, permissions); } static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, @@ -2075,8 +2065,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, u32 affinity_mask_low, u32 affinity_mask_high) { - const u64 affinity_mask = - static_cast<u64>(affinity_mask_low) | (static_cast<u64>(affinity_mask_high) << 32); + const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32); return SetThreadCoreMask(system, thread_handle, core, affinity_mask); } @@ -2341,9 +2330,10 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd return RESULT_SUCCESS; } -static ResultCode FlushProcessDataCache32(Core::System& system, Handle handle, u32 address, - u32 size) { - // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a nope +static ResultCode FlushProcessDataCache32([[maybe_unused]] Core::System& system, + [[maybe_unused]] Handle handle, + [[maybe_unused]] u32 address, [[maybe_unused]] u32 size) { + // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op, // as all emulation is done in the same cache level in host architecture, thus data cache // does not need flushing. LOG_DEBUG(Kernel_SVC, "called"); diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index d33b26129..d16223064 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -217,7 +217,7 @@ public: {1, nullptr, "RefreshDebugAvailability"}, {2, nullptr, "ClearDebugResponse"}, {3, nullptr, "RegisterDebugResponse"}, - {4, nullptr, "IsLargeResourceAvailable"}, + {4, &NIM_ECA::IsLargeResourceAvailable, "IsLargeResourceAvailable"}, }; // clang-format on @@ -231,6 +231,18 @@ private: rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<IShopServiceAccessServer>(system); } + + void IsLargeResourceAvailable(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto unknown{rp.Pop<u64>()}; + + LOG_INFO(Service_NIM, "(STUBBED) called, unknown={}", unknown); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(false); + } }; class NIM_SHP final : public ServiceFramework<NIM_SHP> { diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 0c97a8988..ccbdfe967 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -878,7 +878,7 @@ private: } u32 binding = device.GetBaseBindings(stage).uniform_buffer; - for (const auto [index, info] : ir.GetConstantBuffers()) { + for (const auto& [index, info] : ir.GetConstantBuffers()) { const u32 num_elements = Common::AlignUp(info.GetSize(), 4) / 4; const u32 size = info.IsIndirect() ? MAX_CONSTBUFFER_ELEMENTS : num_elements; code.AddLine("layout (std140, binding = {}) uniform {} {{", binding++, |