From 6fb2358eb16e78d664e230f98aebf26471e7f064 Mon Sep 17 00:00:00 2001
From: pineappleEA <pineaea@gmail.com>
Date: Mon, 17 Oct 2022 14:43:31 +0200
Subject: [PATCH] early-access version 3032

---
 README.md                                     |  2 +-
 src/audio_core/sink/sdl2_sink.cpp             |  4 +-
 src/core/file_sys/savedata_factory.cpp        | 58 ++++++++++++++++---
 src/core/file_sys/savedata_factory.h          |  4 +-
 src/core/hid/irs_types.h                      | 20 +++----
 src/core/hle/kernel/k_slab_heap.h             | 25 ++++----
 src/core/hle/service/hid/hid.cpp              |  2 +-
 .../service/hid/irsensor/pointing_processor.h |  4 +-
 .../frontend/maxwell/translate_program.cpp    | 12 ++--
 .../texture_cache/descriptor_table.h          |  2 +-
 src/video_core/texture_cache/texture_cache.h  |  8 +--
 src/yuzu/main.cpp                             | 10 ++--
 12 files changed, 101 insertions(+), 50 deletions(-)

diff --git a/README.md b/README.md
index 7bc92cd45..2a427b840 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 yuzu emulator early access
 =============
 
-This is the source code for early-access 3031.
+This is the source code for early-access 3032.
 
 ## Legal Notice
 
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp
index f12ebf7fe..c138dc628 100755
--- a/src/audio_core/sink/sdl2_sink.cpp
+++ b/src/audio_core/sink/sdl2_sink.cpp
@@ -230,7 +230,9 @@ std::vector<std::string> ListSDLSinkDevices(bool capture) {
 
     const int device_count = SDL_GetNumAudioDevices(capture);
     for (int i = 0; i < device_count; ++i) {
-        device_list.emplace_back(SDL_GetAudioDeviceName(i, 0));
+        if (const char* name = SDL_GetAudioDeviceName(i, capture)) {
+            device_list.emplace_back(name);
+        }
     }
 
     return device_list;
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 8c1b2523c..1567da231 100755
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -5,6 +5,7 @@
 #include "common/assert.h"
 #include "common/common_types.h"
 #include "common/logging/log.h"
+#include "common/uuid.h"
 #include "core/core.h"
 #include "core/file_sys/savedata_factory.h"
 #include "core/file_sys/vfs.h"
@@ -59,6 +60,36 @@ bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataA
             attr.title_id == 0 && attr.save_id == 0);
 }
 
+std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
+                                  u128 user_id) {
+    // Only detect nand user saves.
+    const auto space_id_path = [space_id]() -> std::string_view {
+        switch (space_id) {
+        case SaveDataSpaceId::NandUser:
+            return "/user/save";
+        default:
+            return "";
+        }
+    }();
+
+    if (space_id_path.empty()) {
+        return "";
+    }
+
+    Common::UUID uuid;
+    std::memcpy(uuid.uuid.data(), user_id.data(), sizeof(Common::UUID));
+
+    // Only detect account/device saves from the future location.
+    switch (type) {
+    case SaveDataType::SaveData:
+        return fmt::format("{}/account/{}/{:016X}/1", space_id_path, uuid.RawString(), title_id);
+    case SaveDataType::DeviceSaveData:
+        return fmt::format("{}/device/{:016X}/1", space_id_path, title_id);
+    default:
+        return "";
+    }
+}
+
 } // Anonymous namespace
 
 std::string SaveDataAttribute::DebugInfo() const {
@@ -82,7 +113,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
     PrintSaveDataAttributeWarnings(meta);
 
     const auto save_directory =
-        GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
+        GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
 
     auto out = dir->CreateDirectoryRelative(save_directory);
 
@@ -99,7 +130,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
                                             const SaveDataAttribute& meta) const {
 
     const auto save_directory =
-        GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
+        GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
 
     auto out = dir->GetDirectoryRelative(save_directory);
 
@@ -134,9 +165,9 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
     }
 }
 
-std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId space,
-                                         SaveDataType type, u64 title_id, u128 user_id,
-                                         u64 save_id) {
+std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir,
+                                         SaveDataSpaceId space, SaveDataType type, u64 title_id,
+                                         u128 user_id, u64 save_id) {
     // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
     // be interpreted as the title id of the current process.
     if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
@@ -145,6 +176,17 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s
         }
     }
 
+    // For compat with a future impl.
+    if (std::string future_path =
+            GetFutureSaveDataPath(space, type, title_id & ~(0xFFULL), user_id);
+        !future_path.empty()) {
+        // Check if this location exists, and prefer it over the old.
+        if (const auto future_dir = dir->GetDirectoryRelative(future_path); future_dir != nullptr) {
+            LOG_INFO(Service_FS, "Using save at new location: {}", future_path);
+            return future_path;
+        }
+    }
+
     std::string out = GetSaveDataSpaceIdPath(space);
 
     switch (type) {
@@ -167,7 +209,8 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s
 
 SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
                                                u128 user_id) const {
-    const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+    const auto path =
+        GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
 
     const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME);
@@ -185,7 +228,8 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
 
 void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
                                         SaveDataSize new_value) const {
-    const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
+    const auto path =
+        GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
 
     const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h
index a763b94c8..d3633ef03 100755
--- a/src/core/file_sys/savedata_factory.h
+++ b/src/core/file_sys/savedata_factory.h
@@ -95,8 +95,8 @@ public:
     VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;
 
     static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space);
-    static std::string GetFullPath(Core::System& system, SaveDataSpaceId space, SaveDataType type,
-                                   u64 title_id, u128 user_id, u64 save_id);
+    static std::string GetFullPath(Core::System& system, VirtualDir dir, SaveDataSpaceId space,
+                                   SaveDataType type, u64 title_id, u128 user_id, u64 save_id);
 
     SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
     void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
diff --git a/src/core/hid/irs_types.h b/src/core/hid/irs_types.h
index 88c5b016d..0d1bfe53f 100755
--- a/src/core/hid/irs_types.h
+++ b/src/core/hid/irs_types.h
@@ -14,7 +14,7 @@ enum class CameraAmbientNoiseLevel : u32 {
     Low,
     Medium,
     High,
-    Unkown3, // This level can't be reached
+    Unknown3, // This level can't be reached
 };
 
 // This is nn::irsensor::CameraLightTarget
@@ -75,9 +75,9 @@ enum class IrCameraStatus : u32 {
 enum class IrCameraInternalStatus : u32 {
     Stopped,
     FirmwareUpdateNeeded,
-    Unkown2,
-    Unkown3,
-    Unkown4,
+    Unknown2,
+    Unknown3,
+    Unknown4,
     FirmwareVersionRequested,
     FirmwareVersionIsInvalid,
     Ready,
@@ -121,20 +121,20 @@ enum class IrSensorFunctionLevel : u8 {
 
 // This is nn::irsensor::MomentProcessorPreprocess
 enum class MomentProcessorPreprocess : u32 {
-    Unkown0,
-    Unkown1,
+    Unknown0,
+    Unknown1,
 };
 
 // This is nn::irsensor::PackedMomentProcessorPreprocess
 enum class PackedMomentProcessorPreprocess : u8 {
-    Unkown0,
-    Unkown1,
+    Unknown0,
+    Unknown1,
 };
 
 // This is nn::irsensor::PointingStatus
 enum class PointingStatus : u32 {
-    Unkown0,
-    Unkown1,
+    Unknown0,
+    Unknown1,
 };
 
 struct IrsRect {
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h
index 2b303537e..b9479c495 100755
--- a/src/core/hle/kernel/k_slab_heap.h
+++ b/src/core/hle/kernel/k_slab_heap.h
@@ -8,6 +8,7 @@
 #include "common/assert.h"
 #include "common/common_funcs.h"
 #include "common/common_types.h"
+#include "common/spin_lock.h"
 
 namespace Kernel {
 
@@ -36,28 +37,30 @@ public:
     }
 
     void* Allocate() {
-        Node* ret = m_head.load();
+        m_lock.lock();
 
-        do {
-            if (ret == nullptr) {
-                break;
-            }
-        } while (!m_head.compare_exchange_weak(ret, ret->next));
+        Node* ret = m_head;
+        if (ret != nullptr) [[likely]] {
+            m_head = ret->next;
+        }
 
+        m_lock.unlock();
         return ret;
     }
 
     void Free(void* obj) {
-        Node* node = static_cast<Node*>(obj);
+        m_lock.lock();
 
-        Node* cur_head = m_head.load();
-        do {
-            node->next = cur_head;
-        } while (!m_head.compare_exchange_weak(cur_head, node));
+        Node* node = static_cast<Node*>(obj);
+        node->next = m_head;
+        m_head = node;
+
+        m_lock.unlock();
     }
 
 private:
     std::atomic<Node*> m_head{};
+    Common::SpinLock m_lock;
 };
 
 } // namespace impl
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 46bad7871..79375bd2f 100755
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -2118,7 +2118,7 @@ void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) {
     ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size");
 
     LOG_WARNING(Service_HID,
-                "(STUBBED) called, connection_handle={}, wave_set={}, unkown={}, "
+                "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, "
                 "t_mem_handle=0x{:08X}, t_mem_size={}, size={}",
                 connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size);
 
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.h b/src/core/hle/service/hid/irsensor/pointing_processor.h
index cf4930794..d63423aff 100755
--- a/src/core/hle/service/hid/irsensor/pointing_processor.h
+++ b/src/core/hle/service/hid/irsensor/pointing_processor.h
@@ -37,10 +37,10 @@ private:
         u8 pointing_status;
         INSERT_PADDING_BYTES(3);
         u32 unknown;
-        float unkown_float1;
+        float unknown_float1;
         float position_x;
         float position_y;
-        float unkown_float2;
+        float unknown_float2;
         Core::IrSensor::IrsRect window_of_interest;
     };
     static_assert(sizeof(PointingProcessorMarkerData) == 0x20,
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index 3aee33a96..b58741d4d 100755
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -272,14 +272,14 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b
 void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
     auto& stores = program.info.stores;
     if (stores.Legacy()) {
-        std::queue<IR::Attribute> ununsed_output_generics{};
+        std::queue<IR::Attribute> unused_output_generics{};
         for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
             if (!stores.Generic(index)) {
-                ununsed_output_generics.push(IR::Attribute::Generic0X + index * 4);
+                unused_output_generics.push(IR::Attribute::Generic0X + index * 4);
             }
         }
         program.info.legacy_stores_mapping =
-            GenerateLegacyToGenericMappings(stores, ununsed_output_generics, {});
+            GenerateLegacyToGenericMappings(stores, unused_output_generics, {});
         for (IR::Block* const block : program.post_order_blocks) {
             for (IR::Inst& inst : block->Instructions()) {
                 switch (inst.GetOpcode()) {
@@ -300,16 +300,16 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run
 
     auto& loads = program.info.loads;
     if (loads.Legacy()) {
-        std::queue<IR::Attribute> ununsed_input_generics{};
+        std::queue<IR::Attribute> unused_input_generics{};
         for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
             const AttributeType input_type{runtime_info.generic_input_types[index]};
             if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
                 input_type == AttributeType::Disabled) {
-                ununsed_input_generics.push(IR::Attribute::Generic0X + index * 4);
+                unused_input_generics.push(IR::Attribute::Generic0X + index * 4);
             }
         }
         auto mappings = GenerateLegacyToGenericMappings(
-            loads, ununsed_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
+            loads, unused_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
         for (IR::Block* const block : program.post_order_blocks) {
             for (IR::Inst& inst : block->Instructions()) {
                 switch (inst.GetOpcode()) {
diff --git a/src/video_core/texture_cache/descriptor_table.h b/src/video_core/texture_cache/descriptor_table.h
index b18e3838f..ee4240288 100755
--- a/src/video_core/texture_cache/descriptor_table.h
+++ b/src/video_core/texture_cache/descriptor_table.h
@@ -18,7 +18,7 @@ class DescriptorTable {
 public:
     explicit DescriptorTable(Tegra::MemoryManager& gpu_memory_) : gpu_memory{gpu_memory_} {}
 
-    [[nodiscard]] bool Synchornize(GPUVAddr gpu_addr, u32 limit) {
+    [[nodiscard]] bool Synchronize(GPUVAddr gpu_addr, u32 limit) {
         [[likely]] if (current_gpu_addr == gpu_addr && current_limit == limit) {
             return false;
         }
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 413baf730..0e0fd410f 100755
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -193,11 +193,11 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() {
     const bool linked_tsc = maxwell3d->regs.sampler_binding == SamplerBinding::ViaHeaderBinding;
     const u32 tic_limit = maxwell3d->regs.tex_header.limit;
     const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tex_sampler.limit;
-    if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tex_sampler.Address(),
+    if (channel_state->graphics_sampler_table.Synchronize(maxwell3d->regs.tex_sampler.Address(),
                                                           tsc_limit)) {
         channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
     }
-    if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tex_header.Address(),
+    if (channel_state->graphics_image_table.Synchronize(maxwell3d->regs.tex_header.Address(),
                                                         tic_limit)) {
         channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
     }
@@ -209,10 +209,10 @@ void TextureCache<P>::SynchronizeComputeDescriptors() {
     const u32 tic_limit = kepler_compute->regs.tic.limit;
     const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
     const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
-    if (channel_state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) {
+    if (channel_state->compute_sampler_table.Synchronize(tsc_gpu_addr, tsc_limit)) {
         channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
     }
-    if (channel_state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(),
+    if (channel_state->compute_image_table.Synchronize(kepler_compute->regs.tic.Address(),
                                                        tic_limit)) {
         channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
     }
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1ceeb65c7..a43a110ac 100755
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1895,6 +1895,8 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
     case GameListOpenTarget::SaveData: {
         open_target = tr("Save Data");
         const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
+        auto vfs_nand_dir =
+            vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read);
 
         if (has_user_save) {
             // User save data
@@ -1921,15 +1923,15 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
             ASSERT(user_id);
 
             const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
-                *system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
-                program_id, user_id->AsU128(), 0);
+                *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
+                FileSys::SaveDataType::SaveData, program_id, user_id->AsU128(), 0);
 
             path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
         } else {
             // Device save data
             const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath(
-                *system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData,
-                program_id, {}, 0);
+                *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser,
+                FileSys::SaveDataType::SaveData, program_id, {}, 0);
 
             path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path);
         }