diff options
28 files changed, 261 insertions, 187 deletions
diff --git a/src/audio_core/time_stretch.cpp b/src/audio_core/time_stretch.cpp index d72d67994..cee8b12dd 100644 --- a/src/audio_core/time_stretch.cpp +++ b/src/audio_core/time_stretch.cpp @@ -10,8 +10,7 @@  namespace AudioCore { -TimeStretcher::TimeStretcher(u32 sample_rate, u32 channel_count) -    : m_sample_rate(sample_rate), m_channel_count(channel_count) { +TimeStretcher::TimeStretcher(u32 sample_rate, u32 channel_count) : m_sample_rate{sample_rate} {      m_sound_touch.setChannels(channel_count);      m_sound_touch.setSampleRate(sample_rate);      m_sound_touch.setPitch(1.0); diff --git a/src/audio_core/time_stretch.h b/src/audio_core/time_stretch.h index decd760f1..bb2270b96 100644 --- a/src/audio_core/time_stretch.h +++ b/src/audio_core/time_stretch.h @@ -27,7 +27,6 @@ public:  private:      u32 m_sample_rate; -    u32 m_channel_count;      soundtouch::SoundTouch m_sound_touch;      double m_stretch_ratio = 1.0;  }; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 9f5918851..6d5218465 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -196,6 +196,7 @@ void FileBackend::Write(const Entry& entry) {      SUB(Service, NFP)                                                                              \      SUB(Service, NIFM)                                                                             \      SUB(Service, NIM)                                                                              \ +    SUB(Service, NPNS)                                                                             \      SUB(Service, NS)                                                                               \      SUB(Service, NVDRV)                                                                            \      SUB(Service, PCIE)                                                                             \ @@ -204,10 +205,12 @@ void FileBackend::Write(const Entry& entry) {      SUB(Service, PM)                                                                               \      SUB(Service, PREPO)                                                                            \      SUB(Service, PSC)                                                                              \ +    SUB(Service, PSM)                                                                              \      SUB(Service, SET)                                                                              \      SUB(Service, SM)                                                                               \      SUB(Service, SPL)                                                                              \      SUB(Service, SSL)                                                                              \ +    SUB(Service, TCAP)                                                                             \      SUB(Service, Time)                                                                             \      SUB(Service, USB)                                                                              \      SUB(Service, VI)                                                                               \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index c9161155a..d4ec31ec3 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -83,6 +83,7 @@ enum class Class : ClassType {      Service_NFP,       ///< The NFP service      Service_NIFM,      ///< The NIFM (Network interface) service      Service_NIM,       ///< The NIM service +    Service_NPNS,      ///< The NPNS service      Service_NS,        ///< The NS services      Service_NVDRV,     ///< The NVDRV (Nvidia driver) service      Service_PCIE,      ///< The PCIe service @@ -96,6 +97,7 @@ enum class Class : ClassType {      Service_SM,        ///< The SM (Service manager) service      Service_SPL,       ///< The SPL service      Service_SSL,       ///< The SSL service +    Service_TCAP,      ///< The TCAP service.      Service_Time,      ///< The time service      Service_USB,       ///< The USB (Universal Serial Bus) service      Service_VI,        ///< The VI (Video interface) service diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index fd0786068..fefc3c747 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -713,7 +713,6 @@ void KeyManager::DeriveBase() {      const auto sbk = GetKey(S128KeyType::SecureBoot);      const auto tsec = GetKey(S128KeyType::TSEC); -    const auto master_source = GetKey(S128KeyType::Source, static_cast<u64>(SourceKeyType::Master));      for (size_t i = 0; i < revisions.size(); ++i) {          if (!revisions[i]) diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index bfe50da73..3824c74e0 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -472,10 +472,14 @@ bool VfsRawCopy(const VirtualFile& src, const VirtualFile& dest, std::size_t blo      std::vector<u8> temp(std::min(block_size, src->GetSize()));      for (std::size_t i = 0; i < src->GetSize(); i += block_size) {          const auto read = std::min(block_size, src->GetSize() - i); -        const auto block = src->Read(temp.data(), read, i); -        if (dest->Write(temp.data(), read, i) != read) +        if (src->Read(temp.data(), read, i) != read) {              return false; +        } + +        if (dest->Write(temp.data(), read, i) != read) { +            return false; +        }      }      return true; diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 06f7d1b15..3cac1b4ff 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -3,7 +3,7 @@  // Refer to the license.txt file included.  #include <random> -#include <boost/optional.hpp> +  #include "common/file_util.h"  #include "core/hle/service/acc/profile_manager.h"  #include "core/settings.h" @@ -58,11 +58,11 @@ ProfileManager::~ProfileManager() {  /// After a users creation it needs to be "registered" to the system. AddToProfiles handles the  /// internal management of the users profiles -boost::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& user) { +std::optional<std::size_t> ProfileManager::AddToProfiles(const ProfileInfo& profile) {      if (user_count >= MAX_USERS) { -        return boost::none; +        return {};      } -    profiles[user_count] = user; +    profiles[user_count] = profile;      return user_count++;  } @@ -81,7 +81,7 @@ bool ProfileManager::RemoveProfileAtIndex(std::size_t index) {  /// Helper function to register a user to the system  ResultCode ProfileManager::AddUser(const ProfileInfo& user) { -    if (AddToProfiles(user) == boost::none) { +    if (!AddToProfiles(user)) {          return ERROR_TOO_MANY_USERS;      }      return RESULT_SUCCESS; @@ -126,37 +126,40 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username)      return CreateNewUser(uuid, username_output);  } -boost::optional<UUID> ProfileManager::GetUser(std::size_t index) const { -    if (index >= MAX_USERS) -        return boost::none; +std::optional<UUID> ProfileManager::GetUser(std::size_t index) const { +    if (index >= MAX_USERS) { +        return {}; +    } +      return profiles[index].user_uuid;  }  /// Returns a users profile index based on their user id. -boost::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const { +std::optional<std::size_t> ProfileManager::GetUserIndex(const UUID& uuid) const {      if (!uuid) { -        return boost::none; +        return {};      } -    auto iter = std::find_if(profiles.begin(), profiles.end(), -                             [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; }); + +    const auto iter = std::find_if(profiles.begin(), profiles.end(), +                                   [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; });      if (iter == profiles.end()) { -        return boost::none; +        return {};      } +      return static_cast<std::size_t>(std::distance(profiles.begin(), iter));  }  /// Returns a users profile index based on their profile -boost::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user) const { +std::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user) const {      return GetUserIndex(user.user_uuid);  }  /// Returns the data structure used by the switch when GetProfileBase is called on acc:* -bool ProfileManager::GetProfileBase(boost::optional<std::size_t> index, -                                    ProfileBase& profile) const { -    if (index == boost::none || index >= MAX_USERS) { +bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const { +    if (!index || index >= MAX_USERS) {          return false;      } -    const auto& prof_info = profiles[index.get()]; +    const auto& prof_info = profiles[*index];      profile.user_uuid = prof_info.user_uuid;      profile.username = prof_info.username;      profile.timestamp = prof_info.creation_time; @@ -165,7 +168,7 @@ bool ProfileManager::GetProfileBase(boost::optional<std::size_t> index,  /// Returns the data structure used by the switch when GetProfileBase is called on acc:*  bool ProfileManager::GetProfileBase(UUID uuid, ProfileBase& profile) const { -    auto idx = GetUserIndex(uuid); +    const auto idx = GetUserIndex(uuid);      return GetProfileBase(idx, profile);  } @@ -192,7 +195,7 @@ std::size_t ProfileManager::GetOpenUserCount() const {  /// Checks if a user id exists in our profile manager  bool ProfileManager::UserExists(UUID uuid) const { -    return (GetUserIndex(uuid) != boost::none); +    return GetUserIndex(uuid) != std::nullopt;  }  bool ProfileManager::UserExistsIndex(std::size_t index) const { @@ -203,21 +206,23 @@ bool ProfileManager::UserExistsIndex(std::size_t index) const {  /// Opens a specific user  void ProfileManager::OpenUser(UUID uuid) { -    auto idx = GetUserIndex(uuid); -    if (idx == boost::none) { +    const auto idx = GetUserIndex(uuid); +    if (!idx) {          return;      } -    profiles[idx.get()].is_open = true; + +    profiles[*idx].is_open = true;      last_opened_user = uuid;  }  /// Closes a specific user  void ProfileManager::CloseUser(UUID uuid) { -    auto idx = GetUserIndex(uuid); -    if (idx == boost::none) { +    const auto idx = GetUserIndex(uuid); +    if (!idx) {          return;      } -    profiles[idx.get()].is_open = false; + +    profiles[*idx].is_open = false;  }  /// Gets all valid user ids on the system @@ -247,10 +252,10 @@ UUID ProfileManager::GetLastOpenedUser() const {  }  /// Return the users profile base and the unknown arbitary data. -bool ProfileManager::GetProfileBaseAndData(boost::optional<std::size_t> index, ProfileBase& profile, +bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,                                             ProfileData& data) const {      if (GetProfileBase(index, profile)) { -        data = profiles[index.get()].data; +        data = profiles[*index].data;          return true;      }      return false; @@ -259,7 +264,7 @@ bool ProfileManager::GetProfileBaseAndData(boost::optional<std::size_t> index, P  /// Return the users profile base and the unknown arbitary data.  bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile,                                             ProfileData& data) const { -    auto idx = GetUserIndex(uuid); +    const auto idx = GetUserIndex(uuid);      return GetProfileBaseAndData(idx, profile, data);  } @@ -277,8 +282,8 @@ bool ProfileManager::CanSystemRegisterUser() const {  }  bool ProfileManager::RemoveUser(UUID uuid) { -    auto index = GetUserIndex(uuid); -    if (index == boost::none) { +    const auto index = GetUserIndex(uuid); +    if (!index) {          return false;      } @@ -289,8 +294,8 @@ bool ProfileManager::RemoveUser(UUID uuid) {  }  bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) { -    auto index = GetUserIndex(uuid); -    if (profile_new.user_uuid == UUID(INVALID_UUID) || index == boost::none) { +    const auto index = GetUserIndex(uuid); +    if (!index || profile_new.user_uuid == UUID(INVALID_UUID)) {          return false;      } diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h index 235208d56..1cd2e51b2 100644 --- a/src/core/hle/service/acc/profile_manager.h +++ b/src/core/hle/service/acc/profile_manager.h @@ -5,8 +5,8 @@  #pragma once  #include <array> +#include <optional> -#include "boost/optional.hpp"  #include "common/common_types.h"  #include "common/swap.h"  #include "core/hle/result.h" @@ -96,13 +96,13 @@ public:      ResultCode AddUser(const ProfileInfo& user);      ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username);      ResultCode CreateNewUser(UUID uuid, const std::string& username); -    boost::optional<UUID> GetUser(std::size_t index) const; -    boost::optional<std::size_t> GetUserIndex(const UUID& uuid) const; -    boost::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; -    bool GetProfileBase(boost::optional<std::size_t> index, ProfileBase& profile) const; +    std::optional<UUID> GetUser(std::size_t index) const; +    std::optional<std::size_t> GetUserIndex(const UUID& uuid) const; +    std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; +    bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const;      bool GetProfileBase(UUID uuid, ProfileBase& profile) const;      bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const; -    bool GetProfileBaseAndData(boost::optional<std::size_t> index, ProfileBase& profile, +    bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,                                 ProfileData& data) const;      bool GetProfileBaseAndData(UUID uuid, ProfileBase& profile, ProfileData& data) const;      bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, @@ -120,16 +120,16 @@ public:      bool CanSystemRegisterUser() const;      bool RemoveUser(UUID uuid); -    bool SetProfileBase(UUID uuid, const ProfileBase& profile); +    bool SetProfileBase(UUID uuid, const ProfileBase& profile_new);  private:      void ParseUserSaveFile();      void WriteUserSaveFile(); +    std::optional<std::size_t> AddToProfiles(const ProfileInfo& profile); +    bool RemoveProfileAtIndex(std::size_t index);      std::array<ProfileInfo, MAX_USERS> profiles{};      std::size_t user_count = 0; -    boost::optional<std::size_t> AddToProfiles(const ProfileInfo& profile); -    bool RemoveProfileAtIndex(std::size_t index);      UUID last_opened_user{INVALID_UUID};  }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4ed66d817..59aafd616 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -743,7 +743,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {      Account::ProfileManager profile_manager{};      const auto uuid = profile_manager.GetUser(Settings::values.current_user); -    ASSERT(uuid != boost::none); +    ASSERT(uuid != std::nullopt);      params.current_user = uuid->uuid;      IPC::ResponseBuilder rb{ctx, 2, 0, 1}; diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 428069df2..54305cf05 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -24,8 +24,8 @@ namespace Service::AOC {  constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;  constexpr u64 DLC_BASE_TO_AOC_ID = 0x1000; -static bool CheckAOCTitleIDMatchesBase(u64 base, u64 aoc) { -    return (aoc & DLC_BASE_TITLE_ID_MASK) == base; +static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) { +    return (title_id & DLC_BASE_TITLE_ID_MASK) == base;  }  static std::vector<u64> AccumulateAOCTitleIDs() { @@ -74,7 +74,7 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {      const auto current = Core::System::GetInstance().CurrentProcess()->GetTitleID();      rb.Push<u32>(static_cast<u32>(          std::count_if(add_on_content.begin(), add_on_content.end(), -                      [¤t](u64 tid) { return (tid & DLC_BASE_TITLE_ID_MASK) == current; }))); +                      [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); })));  }  void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index b06e65a77..4b4d1324f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -108,9 +108,10 @@ void Controller_NPad::OnInit() {      styleset_changed_event =          Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); -    if (!IsControllerActivated()) +    if (!IsControllerActivated()) {          return; -    std::size_t controller{}; +    } +      if (style.raw == 0) {          // We want to support all controllers          style.handheld.Assign(1); diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 7d95816fe..c716a462b 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp @@ -74,10 +74,6 @@ double PerfStats::GetLastFrameTimeScale() {  }  void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { -    // Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher -    // values increase the time needed to recover and limit framerate again after spikes. -    constexpr microseconds MAX_LAG_TIME_US = 25000us; -      if (!Settings::values.use_frame_limit) {          return;      } diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index bca014a4a..78ba29fc1 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -155,7 +155,6 @@ void Maxwell3D::ProcessQueryGet() {      ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,                 "Units other than CROP are unimplemented"); -    u32 value = Memory::Read32(*address);      u64 result = 0;      // TODO(Subv): Support the other query variables diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 6cd08d28b..af7756266 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -79,6 +79,7 @@ union Attribute {      constexpr explicit Attribute(u64 value) : value(value) {}      enum class Index : u64 { +        PointSize = 6,          Position = 7,          Attribute_0 = 8,          Attribute_31 = 39, diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 9c8925383..591ec7998 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -78,6 +78,29 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {      }  } +std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const { +    const u32 compression_factor{GetCompressionFactor(pixel_format)}; +    const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; +    u32 m_depth = (layer_only ? 1U : depth); +    u32 m_width = std::max(1U, width / compression_factor); +    u32 m_height = std::max(1U, height / compression_factor); +    std::size_t size = Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height, +                                                     m_depth, block_height, block_depth); +    u32 m_block_height = block_height; +    u32 m_block_depth = block_depth; +    std::size_t block_size_bytes = 512 * block_height * block_depth; // 512 is GOB size +    for (u32 i = 1; i < max_mip_level; i++) { +        m_width = std::max(1U, m_width / 2); +        m_height = std::max(1U, m_height / 2); +        m_depth = std::max(1U, m_depth / 2); +        m_block_height = std::max(1U, m_block_height / 2); +        m_block_depth = std::max(1U, m_block_depth / 2); +        size += Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height, m_depth, +                                              m_block_height, m_block_depth); +    } +    return is_tiled ? Common::AlignUp(size, block_size_bytes) : size; +} +  /*static*/ SurfaceParams SurfaceParams::CreateForTexture(      const Tegra::Texture::FullTextureInfo& config, const GLShader::SamplerEntry& entry) {      SurfaceParams params{}; @@ -124,6 +147,7 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {          break;      } +    params.is_layered = SurfaceTargetIsLayered(params.target);      params.max_mip_level = config.tic.max_mip_level + 1;      params.rt = {}; @@ -150,6 +174,7 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {      params.target = SurfaceTarget::Texture2D;      params.depth = 1;      params.max_mip_level = 0; +    params.is_layered = false;      // Render target specific parameters, not used for caching      params.rt.index = static_cast<u32>(index); @@ -182,6 +207,7 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {      params.target = SurfaceTarget::Texture2D;      params.depth = 1;      params.max_mip_level = 0; +    params.is_layered = false;      params.rt = {};      params.InitCacheParameters(zeta_address); @@ -361,10 +387,11 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 d      }  } -static constexpr std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t, VAddr), -                            SurfaceParams::MaxPixelFormat> -    morton_to_gl_fns = { -        // clang-format off +using GLConversionArray = std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t, VAddr), +                                     SurfaceParams::MaxPixelFormat>; + +static constexpr GLConversionArray morton_to_gl_fns = { +    // clang-format off          MortonCopy<true, PixelFormat::ABGR8U>,          MortonCopy<true, PixelFormat::ABGR8S>,          MortonCopy<true, PixelFormat::ABGR8UI>, @@ -418,13 +445,11 @@ static constexpr std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t,          MortonCopy<true, PixelFormat::Z24S8>,          MortonCopy<true, PixelFormat::S8Z24>,          MortonCopy<true, PixelFormat::Z32FS8>, -        // clang-format on +    // clang-format on  }; -static constexpr std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t, VAddr), -                            SurfaceParams::MaxPixelFormat> -    gl_to_morton_fns = { -        // clang-format off +static constexpr GLConversionArray gl_to_morton_fns = { +    // clang-format off          MortonCopy<false, PixelFormat::ABGR8U>,          MortonCopy<false, PixelFormat::ABGR8S>,          MortonCopy<false, PixelFormat::ABGR8UI>, @@ -479,9 +504,35 @@ static constexpr std::array<void (*)(u32, u32, u32, u32, u32, u8*, std::size_t,          MortonCopy<false, PixelFormat::Z24S8>,          MortonCopy<false, PixelFormat::S8Z24>,          MortonCopy<false, PixelFormat::Z32FS8>, -        // clang-format on +    // clang-format on  }; +void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params, +                 std::vector<u8>& gl_buffer) { +    u32 depth = params.depth; +    if (params.target == SurfaceParams::SurfaceTarget::Texture2D) { +        // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented. +        depth = 1U; +    } +    if (params.is_layered) { +        u64 offset = 0; +        u64 offset_gl = 0; +        u64 layer_size = params.LayerMemorySize(); +        u64 gl_size = params.LayerSizeGL(); +        for (u32 i = 0; i < depth; i++) { +            functions[static_cast<std::size_t>(params.pixel_format)]( +                params.width, params.block_height, params.height, params.block_depth, 1, +                gl_buffer.data() + offset_gl, gl_size, params.addr + offset); +            offset += layer_size; +            offset_gl += gl_size; +        } +    } else { +        functions[static_cast<std::size_t>(params.pixel_format)]( +            params.width, params.block_height, params.height, params.block_depth, depth, +            gl_buffer.data(), gl_buffer.size(), params.addr); +    } +} +  static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,                          GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0,                          GLenum dst_attachment = 0, std::size_t cubemap_face = 0) { @@ -881,21 +932,10 @@ void CachedSurface::LoadGLBuffer() {      gl_buffer.resize(params.size_in_bytes_gl);      if (params.is_tiled) { -        u32 depth = params.depth; -        u32 block_depth = params.block_depth; -          ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",                     params.block_width, static_cast<u32>(params.target)); -        if (params.target == SurfaceParams::SurfaceTarget::Texture2D) { -            // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented. -            depth = 1U; -            block_depth = 1U; -        } - -        morton_to_gl_fns[static_cast<std::size_t>(params.pixel_format)]( -            params.width, params.block_height, params.height, block_depth, depth, gl_buffer.data(), -            gl_buffer.size(), params.addr); +        SwizzleFunc(morton_to_gl_fns, params, gl_buffer);      } else {          const auto texture_src_data{Memory::GetPointer(params.addr)};          const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; @@ -929,19 +969,10 @@ void CachedSurface::FlushGLBuffer() {      const u8* const texture_src_data = Memory::GetPointer(params.addr);      ASSERT(texture_src_data);      if (params.is_tiled) { -        u32 depth = params.depth; -        u32 block_depth = params.block_depth; -          ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",                     params.block_width, static_cast<u32>(params.target)); -        if (params.target == SurfaceParams::SurfaceTarget::Texture2D) { -            // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented. -            depth = 1U; -        } -        gl_to_morton_fns[static_cast<size_t>(params.pixel_format)]( -            params.width, params.block_height, params.height, block_depth, depth, gl_buffer.data(), -            gl_buffer.size(), GetAddr()); +        SwizzleFunc(gl_to_morton_fns, params, gl_buffer);      } else {          std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer.data(), GetSizeInBytes());      } @@ -1179,7 +1210,7 @@ void RasterizerCacheOpenGL::AccurateCopySurface(const Surface& src_surface,                                                  const Surface& dst_surface) {      const auto& src_params{src_surface->GetSurfaceParams()};      const auto& dst_params{dst_surface->GetSurfaceParams()}; -    FlushRegion(src_params.addr, dst_params.size_in_bytes); +    FlushRegion(src_params.addr, dst_params.MemorySize());      LoadSurface(dst_surface);  } @@ -1221,44 +1252,10 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,              CopySurface(old_surface, new_surface, copy_pbo.handle);          }          break; +    case SurfaceParams::SurfaceTarget::TextureCubemap:      case SurfaceParams::SurfaceTarget::Texture3D:          AccurateCopySurface(old_surface, new_surface);          break; -    case SurfaceParams::SurfaceTarget::TextureCubemap: { -        if (old_params.rt.array_mode != 1) { -            // TODO(bunnei): This is used by Breath of the Wild, I'm not sure how to implement this -            // yet (array rendering used as a cubemap texture). -            LOG_CRITICAL(HW_GPU, "Unhandled rendertarget array_mode {}", old_params.rt.array_mode); -            UNREACHABLE(); -            return new_surface; -        } - -        // This seems to be used for render-to-cubemap texture -        ASSERT_MSG(old_params.target == SurfaceParams::SurfaceTarget::Texture2D, "Unexpected"); -        ASSERT_MSG(old_params.pixel_format == new_params.pixel_format, "Unexpected"); -        ASSERT_MSG(old_params.rt.base_layer == 0, "Unimplemented"); - -        // TODO(bunnei): Verify the below - this stride seems to be in 32-bit words, not pixels. -        // Tested with Splatoon 2, Super Mario Odyssey, and Breath of the Wild. -        const std::size_t byte_stride{old_params.rt.layer_stride * sizeof(u32)}; - -        for (std::size_t index = 0; index < new_params.depth; ++index) { -            Surface face_surface{TryGetReservedSurface(old_params)}; -            ASSERT_MSG(face_surface, "Unexpected"); - -            if (is_blit) { -                BlitSurface(face_surface, new_surface, read_framebuffer.handle, -                            draw_framebuffer.handle, face_surface->GetSurfaceParams().rt.index, -                            new_params.rt.index, index); -            } else { -                CopySurface(face_surface, new_surface, copy_pbo.handle, -                            face_surface->GetSurfaceParams().rt.index, new_params.rt.index, index); -            } - -            old_params.addr += byte_stride; -        } -        break; -    }      default:          LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",                       static_cast<u32>(new_params.target)); @@ -1266,7 +1263,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,      }      return new_surface; -} +} // namespace OpenGL  Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr addr) const {      return TryGet(addr); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 0dd0d90a3..50a7ab47d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -168,6 +168,23 @@ struct SurfaceParams {          }      } +    static bool SurfaceTargetIsLayered(SurfaceTarget target) { +        switch (target) { +        case SurfaceTarget::Texture1D: +        case SurfaceTarget::Texture2D: +        case SurfaceTarget::Texture3D: +            return false; +        case SurfaceTarget::Texture1DArray: +        case SurfaceTarget::Texture2DArray: +        case SurfaceTarget::TextureCubemap: +            return true; +        default: +            LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target)); +            UNREACHABLE(); +            return false; +        } +    } +      /**       * Gets the compression factor for the specified PixelFormat. This applies to just the       * "compressed width" and "compressed height", not the overall compression factor of a @@ -742,6 +759,25 @@ struct SurfaceParams {          return size_in_bytes_gl / 6;      } +    /// Returns the exact size of memory occupied by the texture in VRAM, including mipmaps. +    std::size_t MemorySize() const { +        std::size_t size = InnerMemorySize(is_layered); +        if (is_layered) +            return size * depth; +        return size; +    } + +    /// Returns the exact size of the memory occupied by a layer in a texture in VRAM, including +    /// mipmaps. +    std::size_t LayerMemorySize() const { +        return InnerMemorySize(true); +    } + +    /// Returns the size of a layer of this surface in OpenGL. +    std::size_t LayerSizeGL() const { +        return SizeInBytesRaw(true) / depth; +    } +      /// Creates SurfaceParams from a texture configuration      static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config,                                            const GLShader::SamplerEntry& entry); @@ -782,6 +818,7 @@ struct SurfaceParams {      u32 unaligned_height;      SurfaceTarget target;      u32 max_mip_level; +    bool is_layered;      // Parameters used for caching      VAddr addr; @@ -797,6 +834,9 @@ struct SurfaceParams {          u32 layer_stride;          u32 base_layer;      } rt; + +private: +    std::size_t InnerMemorySize(bool layer_only = false) const;  };  }; // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index fe4d1bd83..81ffb24e4 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -6,6 +6,7 @@  #include <set>  #include <string>  #include <string_view> +#include <unordered_set>  #include <boost/optional.hpp>  #include <fmt/format.h> @@ -276,7 +277,8 @@ public:      GLSLRegisterManager(ShaderWriter& shader, ShaderWriter& declarations,                          const Maxwell3D::Regs::ShaderStage& stage, const std::string& suffix,                          const Tegra::Shader::Header& header) -        : shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix}, header{header} { +        : shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix}, header{header}, +          fixed_pipeline_output_attributes_used{} {          BuildRegisterList();          BuildInputList();      } @@ -480,7 +482,12 @@ public:                                 std::to_string(static_cast<u32>(attribute)) + ']' +                                 GetSwizzle(elem) + " = " + src + ';');              } else { -                shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); +                if (attribute == Attribute::Index::PointSize) { +                    fixed_pipeline_output_attributes_used.insert(attribute); +                    shader.AddLine(dest + " = " + src + ';'); +                } else { +                    shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); +                }              }          }      } @@ -524,6 +531,7 @@ public:      /// Add declarations.      void GenerateDeclarations(const std::string& suffix) { +        GenerateVertex();          GenerateRegisters(suffix);          GenerateInternalFlags();          GenerateInputAttrs(); @@ -683,6 +691,20 @@ private:          declarations.AddNewLine();      } +    void GenerateVertex() { +        if (stage != Maxwell3D::Regs::ShaderStage::Vertex) +            return; +        declarations.AddLine("out gl_PerVertex {"); +        ++declarations.scope; +        declarations.AddLine("vec4 gl_Position;"); +        for (auto& o : fixed_pipeline_output_attributes_used) { +            if (o == Attribute::Index::PointSize) +                declarations.AddLine("float gl_PointSize;"); +        } +        --declarations.scope; +        declarations.AddLine("};"); +    } +      /// Generates code representing a temporary (GPR) register.      std::string GetRegister(const Register& reg, unsigned elem) {          if (reg == Register::ZeroIndex) { @@ -836,6 +858,8 @@ private:      /// Generates code representing the declaration name of an output attribute register.      std::string GetOutputAttribute(Attribute::Index attribute) {          switch (attribute) { +        case Attribute::Index::PointSize: +            return "gl_PointSize";          case Attribute::Index::Position:              return "position";          default: @@ -870,6 +894,7 @@ private:      const Maxwell3D::Regs::ShaderStage& stage;      const std::string& suffix;      const Tegra::Shader::Header& header; +    std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used;  };  class GLSLGenerator { diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index e883ffb1d..dfb562706 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -19,9 +19,6 @@ ProgramResult GenerateVertexShader(const ShaderSetup& setup) {      out += Decompiler::GetCommonDeclarations();      out += R"( -out gl_PerVertex { -    vec4 gl_Position; -};  layout (location = 0) out vec4 position; diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index f1b40e7f5..550ca856c 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -142,7 +142,6 @@ void SwizzledData(u8* swizzled_data, u8* unswizzled_data, const bool unswizzle,      const u32 blocks_on_x = div_ceil(width, block_x_elements);      const u32 blocks_on_y = div_ceil(height, block_y_elements);      const u32 blocks_on_z = div_ceil(depth, block_z_elements); -    const u32 blocks = blocks_on_x * blocks_on_y * blocks_on_z;      const u32 gob_size = gob_x_bytes * gob_elements_y * gob_elements_z;      const u32 xy_block_size = gob_size * block_height;      const u32 block_size = xy_block_size * block_depth; @@ -320,13 +319,13 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat  std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,                            u32 block_height, u32 block_depth) {      if (tiled) { -        const u32 gobs_in_x = 64 / bytes_per_pixel; +        const u32 gobs_in_x = 64;          const u32 gobs_in_y = 8;          const u32 gobs_in_z = 1; -        const u32 aligned_width = Common::AlignUp(width, gobs_in_x); +        const u32 aligned_width = Common::AlignUp(width * bytes_per_pixel, gobs_in_x);          const u32 aligned_height = Common::AlignUp(height, gobs_in_y * block_height);          const u32 aligned_depth = Common::AlignUp(depth, gobs_in_z * block_depth); -        return aligned_width * aligned_height * aligned_depth * bytes_per_pixel; +        return aligned_width * aligned_height * aligned_depth;      } else {          return width * height * depth * bytes_per_pixel;      } diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index e8ab23326..39eef8858 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -8,7 +8,6 @@  #include "common/microprofile.h"  #include "common/scm_rev.h" -#include "common/string_util.h"  #include "core/core.h"  #include "core/frontend/framebuffer_layout.h"  #include "core/settings.h" @@ -107,9 +106,8 @@ private:  GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)      : QWidget(parent), child(nullptr), emu_thread(emu_thread) { -    std::string window_title = fmt::format("yuzu {} | {}-{}", Common::g_build_name, -                                           Common::g_scm_branch, Common::g_scm_desc); -    setWindowTitle(QString::fromStdString(window_title)); +    setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") +                       .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));      setAttribute(Qt::WA_AcceptTouchEvents);      InputCommon::Init(); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 1fe9a7edd..d4fd60a73 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -13,11 +13,16 @@ Config::Config() {      // TODO: Don't hardcode the path; let the frontend decide where to put the config files.      qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "qt-config.ini";      FileUtil::CreateFullPath(qt_config_loc); -    qt_config = new QSettings(QString::fromStdString(qt_config_loc), QSettings::IniFormat); +    qt_config = +        std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);      Reload();  } +Config::~Config() { +    Save(); +} +  const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {      Qt::Key_A, Qt::Key_S, Qt::Key_Z,    Qt::Key_X,  Qt::Key_3,     Qt::Key_4,    Qt::Key_Q,      Qt::Key_W, Qt::Key_1, Qt::Key_2,    Qt::Key_N,  Qt::Key_M,     Qt::Key_F,    Qt::Key_T, @@ -342,9 +347,3 @@ void Config::Reload() {  void Config::Save() {      SaveValues();  } - -Config::~Config() { -    Save(); - -    delete qt_config; -} diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index cbf745ea2..9c99c1b75 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -5,6 +5,7 @@  #pragma once  #include <array> +#include <memory>  #include <string>  #include <QVariant>  #include "core/settings.h" @@ -12,12 +13,6 @@  class QSettings;  class Config { -    QSettings* qt_config; -    std::string qt_config_loc; - -    void ReadValues(); -    void SaveValues(); -  public:      Config();      ~Config(); @@ -27,4 +22,11 @@ public:      static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;      static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs; + +private: +    void ReadValues(); +    void SaveValues(); + +    std::unique_ptr<QSettings> qt_config; +    std::string qt_config_loc;  }; diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 83cc49dfc..0bc307e99 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -153,7 +153,7 @@ void ConfigureSystem::UpdateCurrentUser() {      ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS);      const auto& current_user = profile_manager->GetUser(Settings::values.current_user); -    ASSERT(current_user != boost::none); +    ASSERT(current_user != std::nullopt);      const auto username = GetAccountUsername(*current_user);      scene->clear(); @@ -252,7 +252,7 @@ void ConfigureSystem::AddUser() {  void ConfigureSystem::RenameUser() {      const auto user = tree_view->currentIndex().row();      const auto uuid = profile_manager->GetUser(user); -    ASSERT(uuid != boost::none); +    ASSERT(uuid != std::nullopt);      const auto username = GetAccountUsername(*uuid);      Service::Account::ProfileBase profile; @@ -292,7 +292,7 @@ void ConfigureSystem::RenameUser() {  void ConfigureSystem::DeleteUser() {      const auto index = tree_view->currentIndex().row();      const auto uuid = profile_manager->GetUser(index); -    ASSERT(uuid != boost::none); +    ASSERT(uuid != std::nullopt);      const auto username = GetAccountUsername(*uuid);      const auto confirm = @@ -320,7 +320,7 @@ void ConfigureSystem::DeleteUser() {  void ConfigureSystem::SetUserImage() {      const auto index = tree_view->currentIndex().row();      const auto uuid = profile_manager->GetUser(index); -    ASSERT(uuid != boost::none); +    ASSERT(uuid != std::nullopt);      const auto username = GetAccountUsername(*uuid);      const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(), diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp index b5c88f944..67ed0ba6d 100644 --- a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp +++ b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp @@ -2,7 +2,6 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. -#include <map>  #include <QLabel>  #include <QMetaType>  #include <QPushButton> @@ -32,21 +31,8 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const {      switch (role) {      case Qt::DisplayRole: {          if (index.column() == 0) { -            static const std::map<Tegra::DebugContext::Event, QString> map = { -                {Tegra::DebugContext::Event::MaxwellCommandLoaded, tr("Maxwell command loaded")}, -                {Tegra::DebugContext::Event::MaxwellCommandProcessed, -                 tr("Maxwell command processed")}, -                {Tegra::DebugContext::Event::IncomingPrimitiveBatch, -                 tr("Incoming primitive batch")}, -                {Tegra::DebugContext::Event::FinishedPrimitiveBatch, -                 tr("Finished primitive batch")}, -            }; - -            DEBUG_ASSERT(map.size() == -                         static_cast<std::size_t>(Tegra::DebugContext::Event::NumEvents)); -            return (map.find(event) != map.end()) ? map.at(event) : QString(); +            return DebugContextEventToString(event);          } -          break;      } @@ -128,6 +114,23 @@ void BreakPointModel::OnResumed() {      active_breakpoint = context->active_breakpoint;  } +QString BreakPointModel::DebugContextEventToString(Tegra::DebugContext::Event event) { +    switch (event) { +    case Tegra::DebugContext::Event::MaxwellCommandLoaded: +        return tr("Maxwell command loaded"); +    case Tegra::DebugContext::Event::MaxwellCommandProcessed: +        return tr("Maxwell command processed"); +    case Tegra::DebugContext::Event::IncomingPrimitiveBatch: +        return tr("Incoming primitive batch"); +    case Tegra::DebugContext::Event::FinishedPrimitiveBatch: +        return tr("Finished primitive batch"); +    case Tegra::DebugContext::Event::NumEvents: +        break; +    } + +    return tr("Unknown debug context event"); +} +  GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(      std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent)      : QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver( diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints_p.h b/src/yuzu/debugger/graphics/graphics_breakpoints_p.h index 7112b87e6..fb488e38f 100644 --- a/src/yuzu/debugger/graphics/graphics_breakpoints_p.h +++ b/src/yuzu/debugger/graphics/graphics_breakpoints_p.h @@ -29,6 +29,8 @@ public:      void OnResumed();  private: +    static QString DebugContextEventToString(Tegra::DebugContext::Event event); +      std::weak_ptr<Tegra::DebugContext> context_weak;      bool at_breakpoint;      Tegra::DebugContext::Event active_breakpoint; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 67890455a..a5a4aa432 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -16,7 +16,6 @@  #include <fmt/format.h>  #include "common/common_paths.h"  #include "common/common_types.h" -#include "common/file_util.h"  #include "common/logging/log.h"  #include "core/file_sys/patch_manager.h"  #include "yuzu/compatibility_list.h" @@ -217,11 +216,11 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent)      tree_view->setContextMenuPolicy(Qt::CustomContextMenu);      item_model->insertColumns(0, COLUMN_COUNT); -    item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); -    item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, "Compatibility"); -    item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, "Add-ons"); -    item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); -    item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); +    item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); +    item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); +    item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); +    item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); +    item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));      connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);      connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); @@ -387,9 +386,9 @@ void GameList::LoadCompatibilityList() {  }  void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { -    if (!FileUtil::Exists(dir_path.toStdString()) || -        !FileUtil::IsDirectory(dir_path.toStdString())) { -        LOG_ERROR(Frontend, "Could not find game list folder at {}", dir_path.toLocal8Bit().data()); +    const QFileInfo dir_info{dir_path}; +    if (!dir_info.exists() || !dir_info.isDir()) { +        LOG_ERROR(Frontend, "Could not find game list folder at {}", dir_path.toStdString());          search_field->setFilterResult(0, 0);          return;      } diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 3881aba5f..3d865a12d 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -62,19 +62,24 @@ QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager,      FileSys::VirtualFile update_raw;      loader.ReadUpdateRaw(update_raw);      for (const auto& kv : patch_manager.GetPatchVersionNames(update_raw)) { -        if (!updatable && kv.first == "Update") +        const bool is_update = kv.first == "Update"; +        if (!updatable && is_update) {              continue; +        } + +        const QString type = QString::fromStdString(kv.first);          if (kv.second.empty()) { -            out.append(fmt::format("{}\n", kv.first).c_str()); +            out.append(QStringLiteral("%1\n").arg(type));          } else {              auto ver = kv.second;              // Display container name for packed updates -            if (ver == "PACKED" && kv.first == "Update") +            if (is_update && ver == "PACKED") {                  ver = Loader::GetFileTypeString(loader.GetFileType()); +            } -            out.append(fmt::format("{} ({})\n", kv.first, ver).c_str()); +            out.append(QStringLiteral("%1 (%2)\n").arg(type, QString::fromStdString(ver)));          }      } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 47f494841..55508b1e1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -785,7 +785,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target          ASSERT(index != -1 && index < 8);          const auto user_id = manager.GetUser(index); -        ASSERT(user_id != boost::none); +        ASSERT(user_id != std::nullopt);          path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser,                                                                  FileSys::SaveDataType::SaveData,                                                                  program_id, user_id->uuid, 0);  | 
