Compare commits

..

8 Commits

Author SHA1 Message Date
lizzie ac35358b3f [common] Replace Common::SpinLock with std::mutex (#4436)
`std::mutex` can be better than the spin-lock specially since we don't waste CPU cycles for no reason.

Test less stuttering/heat consumption.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4436
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-09-16 15:35:13 +02:00
lizzie 7bf95be2c2 [dynarmic] fix A32 crash due to wrong LEA encoding (#4444)
LEA 1<<n, not just n

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4444
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-09-16 09:29:12 +02:00
lizzie 4ce45b3b37 [hle] Fix crash on MK8D and SM3DW LDN (#4417)
Crash is due to SIGILL due to mismatched N and span<> ctor().
Also some astray nullptr references.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4417
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-09-16 08:10:29 +02:00
lizzie fd34024f0e [hle/ns] fix build error due to missing async_result.h (#4440)
We may have merged quite a bit too fast before letting CI finish.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4440
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-09-16 04:45:45 +02:00
lizzie d76f8f91c4 [hle] Fix nullptr on ListApplicationIcon (#4438)
Control could be null, handle such case

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4438
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-09-16 04:00:59 +02:00
PavelBARABANOV a7061eb4c8 [ns] Rename i_async_result -> async_result (#4439)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4439
Reviewed-by: lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-09-16 03:46:44 +02:00
PavelBARABANOV fa4e7c6992 [vk_texture_cache] drop depth comparison sampler fallback (#4408)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

This fixes the flashlight in Alan Wake.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4408
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-09-16 01:42:37 +02:00
xbzk b77308ced6 [applet] ReconfigureControllers fallback unconditional disconnect fix (#4420)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

So, about Absolum's no overlay applet P2 issue:

The fallback controller applet ignored keep_controllers_connected, according comment: "This makes it easy to connect the desired controllers". Unfortunately it was not good enough. It disconnected every controller, then reconnected only the minimum player count. That disconnect interacts with some guests (absolum in this case) causing undesired behaviors.

The fix is entwined to original routine but it is a lot simple tho: preserves compatible connected controllers within the requested player range, while the existing routine configures only the remaining slots.

This may fix some games, and should not harm others. Let us give it a go.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4420
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-09-15 21:53:07 +02:00
20 changed files with 66 additions and 224 deletions
-1
View File
@@ -110,7 +110,6 @@ add_library(
socket_types.h socket_types.h
sparse_large_vector.cpp sparse_large_vector.cpp
sparse_large_vector.h sparse_large_vector.h
spin_lock.h
stb.cpp stb.cpp
stb.h stb.h
steady_clock.cpp steady_clock.cpp
-50
View File
@@ -1,50 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef _MSC_VER
#include <intrin.h>
#elif defined(ARCHITECTURE_x86_64)
#include <xmmintrin.h>
#endif
#include <atomic>
namespace Common {
/// @brief A lock similar to mutex that forces a thread to spin wait instead calling the
/// supervisor. Should be used on short sequences of code.
struct SpinLock {
SpinLock() noexcept = default;
SpinLock(const SpinLock&) noexcept = delete;
SpinLock& operator=(const SpinLock&) noexcept = delete;
SpinLock(SpinLock&&) noexcept = delete;
SpinLock& operator=(SpinLock&&) noexcept = delete;
inline void lock() noexcept {
while (lck.test_and_set(std::memory_order_acquire)) {
#if defined(ARCHITECTURE_x86_64)
_mm_pause();
#elif defined(ARCHITECTURE_arm64) && defined(_MSC_VER)
__yield();
#elif defined(ARCHITECTURE_arm64)
asm("yield");
#endif
}
}
inline void unlock() noexcept {
lck.clear(std::memory_order_release);
}
[[nodiscard]] inline bool try_lock() noexcept {
return !lck.test_and_set(std::memory_order_acquire);
}
std::atomic_flag lck = ATOMIC_FLAG_INIT;
};
} // namespace Common
+2 -2
View File
@@ -208,9 +208,9 @@ UUID UUID::MakeRandomRFC4122V4() {
return uuid; return uuid;
} }
UUID UUID::MakeRFC4122V5(std::span<u8, 20> sha1) { UUID UUID::MakeRFC4122V5(std::span<u8, 16> sha1) {
UUID uuid{}; UUID uuid{};
std::memcpy(&uuid.uuid, sha1.data(), sizeof(UUID)); std::memcpy(&uuid.uuid, sha1.data(), sha1.size());
uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F); uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
uuid.uuid[6] = 0x50 | (uuid.uuid[6] & 0xF); uuid.uuid[6] = 0x50 | (uuid.uuid[6] & 0xF);
return uuid; return uuid;
+1 -1
View File
@@ -104,7 +104,7 @@ struct UUID {
/// @returns A random UUID that is RFC 4122 Version 4 compliant. /// @returns A random UUID that is RFC 4122 Version 4 compliant.
[[nodiscard]] static UUID MakeRandomRFC4122V4(); [[nodiscard]] static UUID MakeRandomRFC4122V4();
[[nodiscard]] static UUID MakeRFC4122V5(std::span<u8, 20> sha1); [[nodiscard]] static UUID MakeRFC4122V5(std::span<u8, 16> sha1);
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default; friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
}; };
+2 -2
View File
@@ -796,6 +796,8 @@ add_library(core STATIC
hle/service/ns/application_manager_interface.h hle/service/ns/application_manager_interface.h
hle/service/ns/application_version_interface.cpp hle/service/ns/application_version_interface.cpp
hle/service/ns/application_version_interface.h hle/service/ns/application_version_interface.h
hle/service/ns/async_result.cpp
hle/service/ns/async_result.h
hle/service/ns/content_management_interface.cpp hle/service/ns/content_management_interface.cpp
hle/service/ns/content_management_interface.h hle/service/ns/content_management_interface.h
hle/service/ns/develop_interface.cpp hle/service/ns/develop_interface.cpp
@@ -810,8 +812,6 @@ add_library(core STATIC
hle/service/ns/ecommerce_interface.h hle/service/ns/ecommerce_interface.h
hle/service/ns/factory_reset_interface.cpp hle/service/ns/factory_reset_interface.cpp
hle/service/ns/factory_reset_interface.h hle/service/ns/factory_reset_interface.h
hle/service/ns/i_async_result.cpp
hle/service/ns/i_async_result.h
hle/service/ns/language.cpp hle/service/ns/language.cpp
hle/service/ns/language.h hle/service/ns/language.h
hle/service/ns/ns.cpp hle/service/ns/ns.cpp
+25 -8
View File
@@ -12,6 +12,7 @@
#include "hid_core/frontend/emulated_controller.h" #include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h" #include "hid_core/hid_core.h"
#include "hid_core/hid_types.h" #include "hid_core/hid_types.h"
#include <array>
namespace Core::Frontend { namespace Core::Frontend {
@@ -29,23 +30,39 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
const std::size_t min_supported_players = const std::size_t min_supported_players =
parameters.enable_single_mode ? 1 : parameters.min_players; parameters.enable_single_mode ? 1 : parameters.min_players;
using Core::HID::NpadStyleIndex;
const std::size_t max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
std::size_t num_selected_players = 0;
std::array<bool, HID::HIDCore::available_controllers> keep_connected{};
// Disconnect Handheld first. // reserve existing AND valid players before filling slots. include Handheld, but not other
for (std::size_t index = 0; index < hid_core.available_controllers - 1; ++index) {
const auto* controller = hid_core.GetEmulatedControllerByIndex(index);
if (!parameters.keep_controllers_connected || !controller->IsConnected() || num_selected_players >= max_supported_players) continue;
const auto style = controller->GetNpadStyleIndex();
keep_connected[index] =
(style == NpadStyleIndex::Fullkey && parameters.allow_pro_controller) ||
(style == NpadStyleIndex::JoyconDual && parameters.allow_dual_joycons) ||
(style == NpadStyleIndex::JoyconLeft && parameters.allow_left_joycon) ||
(style == NpadStyleIndex::JoyconRight && parameters.allow_right_joycon) ||
(style == NpadStyleIndex::Handheld && parameters.enable_single_mode && parameters.allow_handheld && !Settings::IsDockedMode()) ||
(style == NpadStyleIndex::GameCube && parameters.allow_gamecube_controller);
num_selected_players += keep_connected[index];
}
auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
handheld->Disconnect(); if (!keep_connected[hid_core.available_controllers - 2]) handheld->Disconnect();
// Deduce the best configuration based on the input parameters. // Deduce the best configuration based on the input parameters.
for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) { for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) {
auto* controller = hid_core.GetEmulatedControllerByIndex(index); auto* controller = hid_core.GetEmulatedControllerByIndex(index);
// First, disconnect all controllers regardless of the value of keep_controllers_connected. if (keep_connected[index]) continue;
// This makes it easy to connect the desired controllers.
controller->Disconnect(); controller->Disconnect();
// Only connect the minimum number of required players. // only add players still needed to reach the minimum
if (index >= min_supported_players) { if (num_selected_players >= min_supported_players) continue;
continue; ++num_selected_players;
}
// Connect controllers based on the following priority list from highest to lowest priority: // Connect controllers based on the following priority list from highest to lowest priority:
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
+3 -4
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -12,7 +12,6 @@
#include "common/atomic_ops.h" #include "common/atomic_ops.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/spin_lock.h"
namespace Kernel { namespace Kernel {
@@ -30,7 +29,7 @@ public:
}; };
public: public:
constexpr KSlabHeapImpl() = default; KSlabHeapImpl() = default;
void Initialize() { void Initialize() {
ASSERT(m_head == nullptr); ASSERT(m_head == nullptr);
@@ -68,7 +67,7 @@ public:
private: private:
std::atomic<Node*> m_head{}; std::atomic<Node*> m_head{};
Common::SpinLock m_lock; std::mutex m_lock;
}; };
} // namespace impl } // namespace impl
+1 -2
View File
@@ -19,7 +19,6 @@
#include "common/intrusive_red_black_tree.h" #include "common/intrusive_red_black_tree.h"
#include "common/scratch_buffer.h" #include "common/scratch_buffer.h"
#include "common/spin_lock.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/hle/kernel/k_affinity_mask.h" #include "core/hle/kernel/k_affinity_mask.h"
#include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_light_lock.h"
@@ -920,7 +919,7 @@ private:
bool m_resource_limit_release_hint{}; bool m_resource_limit_release_hint{};
bool m_is_kernel_address_key{}; bool m_is_kernel_address_key{};
StackParameters m_stack_parameters{}; StackParameters m_stack_parameters{};
Common::SpinLock m_context_guard{}; std::mutex m_context_guard{};
// For emulation // For emulation
std::shared_ptr<Common::Fiber> m_host_context{}; std::shared_ptr<Common::Fiber> m_host_context{};
@@ -23,12 +23,6 @@ constexpr std::size_t profile_username_size{32};
using ProfileUsername = std::array<u8, profile_username_size>; using ProfileUsername = std::array<u8, profile_username_size>;
using UserIDArray = std::array<Common::UUID, MAX_USERS>; using UserIDArray = std::array<Common::UUID, MAX_USERS>;
// This is nn::account::Uid
struct Uid {
std::array<u8, 0x10> unk0;
};
static_assert(sizeof(Uid) == 0x10);
/// Contains extra data related to a user. /// Contains extra data related to a user.
/// TODO: RE this structure /// TODO: RE this structure
struct UserData { struct UserData {
@@ -347,21 +347,22 @@ Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) { Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
LOG_WARNING(Service_AM, "(stubbed)"); LOG_WARNING(Service_AM, "(stubbed)");
R_UNLESS(out_pseudo_device_id, ResultUnknown); R_UNLESS(out_pseudo_device_id != nullptr, ResultUnknown);
// This should be hashed with the device specific hash // This should be hashed with the device specific hash
// for now this will do // for now this will do
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id); const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
u8 hash[EVP_MAX_MD_SIZE]; R_UNLESS(res.first != nullptr, ResultUnknown);
std::array<u8, EVP_MAX_MD_SIZE> hash;
unsigned int hash_len = 0; unsigned int hash_len = 0;
auto const seed = res.first->raw.seed_for_pseudo_device_id; auto const seed = res.first->raw.seed_for_pseudo_device_id;
EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_MD_CTX *ctx = EVP_MD_CTX_new();
auto const algorithm = EVP_sha1(); auto const algorithm = EVP_sha1();
EVP_DigestInit_ex(ctx, algorithm, nullptr); EVP_DigestInit_ex(ctx, algorithm, nullptr);
EVP_DigestUpdate(ctx, &seed, sizeof(seed)); EVP_DigestUpdate(ctx, &seed, sizeof(seed));
EVP_DigestFinal_ex(ctx, hash, &hash_len); EVP_DigestFinal_ex(ctx, hash.data(), &hash_len);
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
*out_pseudo_device_id = Common::UUID::MakeRFC4122V5(std::span<u8, 20>{hash, std::size(hash)}); *out_pseudo_device_id = Common::UUID::MakeRFC4122V5(std::span<u8, 16>{hash.begin(), hash.begin() + 16});
R_SUCCEED(); R_SUCCEED();
} }
@@ -154,9 +154,6 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{720, nullptr, "AbandonAccessFailure"}, {720, nullptr, "AbandonAccessFailure"},
{800, nullptr, "GetAndClearFileSystemProxyErrorInfo"}, {800, nullptr, "GetAndClearFileSystemProxyErrorInfo"},
{810, nullptr, "RegisterProgramIndexMapInfo"}, {810, nullptr, "RegisterProgramIndexMapInfo"},
{820, nullptr, "GetContentStorageInfoIndex"},
{830, nullptr, "EncryptStreamPlaySaveData"},
{831, nullptr, "DecryptStreamPlaySaveData"},
{1000, nullptr, "SetBisRootForHost"}, {1000, nullptr, "SetBisRootForHost"},
{1001, nullptr, "SetSaveDataSize"}, {1001, nullptr, "SetSaveDataSize"},
{1002, nullptr, "SetSaveDataRootPath"}, {1002, nullptr, "SetSaveDataRootPath"},
-1
View File
@@ -22,7 +22,6 @@
namespace IPC { namespace IPC {
constexpr Result ResultNotSupported{ErrorModule::HIPC, 1};
constexpr Result ResultSessionClosed{ErrorModule::HIPC, 301}; constexpr Result ResultSessionClosed{ErrorModule::HIPC, 301};
struct ResponseBuilder { struct ResponseBuilder {
-117
View File
@@ -6,16 +6,10 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/result.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/ngc/ngc.h" #include "core/hle/service/ngc/ngc.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "frontend_common/firmware_manager.h"
namespace Service::NGC { namespace Service::NGC {
@@ -172,123 +166,12 @@ public:
} }
}; };
struct SaveDataHandle {
u64 unk0;
};
static_assert(sizeof(SaveDataHandle) == 0x08);
class IUserShimScopedObject final : public ServiceFramework<IUserShimScopedObject> {
public:
explicit IUserShimScopedObject(Core::System& system_) : ServiceFramework(system_, "IUserShimScopedObject") {
// clang-format off
static const FunctionInfo functions[] = {
{450, nullptr, "InitializeForSaveData"},
{451, nullptr, "FinalizeForSaveData"},
{452, D<&IUserShimScopedObject::OpenSaveData>, "OpenSaveData"},
{453, nullptr, "CloseSaveData"},
{454, D<&IUserShimScopedObject::ReadSaveSlot>, "ReadSaveSlot"},
{455, D<&IUserShimScopedObject::WriteSaveSlot>, "WriteSaveSlot"},
{456, nullptr, "FlushSaveSlot"},
{457, nullptr, "CommitSaveData"},
};
// clang-format on
RegisterHandlers(functions);
}
Result OpenSaveData(Account::Uid unk0, Out<SaveDataHandle> unk1) {
LOG_WARNING(Service_NGC, "stubbed");
R_THROW(IPC::ResultNotSupported);
}
Result ReadSaveSlot(s32 offset, SaveDataHandle handle, OutBuffer<BufferAttr_HipcAutoSelect> out_data, Out<u32> out_size) {
LOG_WARNING(Service_NGC, "stubbed");
R_THROW(IPC::ResultNotSupported);
}
Result WriteSaveSlot(s32 offset, SaveDataHandle handle, InBuffer<BufferAttr_HipcAutoSelect> out_data) {
LOG_WARNING(Service_NGC, "stubbed");
// to implement
R_SUCCEED();
}
};
class IUserService final : public ServiceFramework<IUserService> {
public:
explicit IUserService(Core::System& system_) : ServiceFramework(system_, "stpl:u") {
// clang-format off
static const FunctionInfo functions[] = {
{0 , D<&IUserService::Cmd0>, "Cmd0"},
};
// clang-format on
RegisterHandlers(functions);
}
Result Cmd0(u32 unk0, OutInterface<IUserShimScopedObject> out_interface) {
LOG_WARNING(Service_NGC, "stubbed");
*out_interface = std::make_shared<IUserShimScopedObject>(system);
R_SUCCEED();
}
};
class ISystemShimScopedObject final : public ServiceFramework<ISystemShimScopedObject> {
public:
explicit ISystemShimScopedObject(Core::System& system_) : ServiceFramework(system_, "ISystemShimScopedObject") {
// clang-format off
static const FunctionInfo functions[] = {
{106, nullptr, "Cmd106"},
{107, nullptr, "Cmd107"},
{108, D<&ISystemShimScopedObject::Cmd108>, "Cmd108"},
{207, nullptr, "Cmd207"},
{208, D<&ISystemShimScopedObject::Cmd208>, "Cmd208"},
{209, nullptr, "Cmd209"},
{210, nullptr, "Cmd210"},
{211, nullptr, "Cmd211"},
{212, nullptr, "Cmd212"},
};
// clang-format on
RegisterHandlers(functions);
}
Result Cmd108() {
LOG_WARNING(Service_NGC, "stubbed");
R_THROW(IPC::ResultNotSupported);
}
Result Cmd208(Out<std::array<u8, 0x20>> unk0) {
LOG_WARNING(Service_NGC, "stubbed");
R_THROW(IPC::ResultNotSupported);
}
};
class ISystemService final : public ServiceFramework<ISystemService> {
public:
explicit ISystemService(Core::System& system_) : ServiceFramework(system_, "stpl:sys") {
// clang-format off
static const FunctionInfo functions[] = {
{0 , D<&ISystemService::Cmd0>, "Cmd0"},
};
// clang-format on
RegisterHandlers(functions);
}
Result Cmd0(OutInterface<ISystemShimScopedObject> out_interface) {
LOG_WARNING(Service_NGC, "stubbed");
*out_interface = std::make_shared<ISystemShimScopedObject>(system);
R_SUCCEED();
}
};
void LoopProcess(Core::System& system) { void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system); auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("ngct:u", std::make_shared<IService>(system), 4); server_manager->RegisterNamedService("ngct:u", std::make_shared<IService>(system), 4);
server_manager->RegisterNamedService("ngct:s", std::make_shared<IServiceWithManagementApi>(system), 4); server_manager->RegisterNamedService("ngct:s", std::make_shared<IServiceWithManagementApi>(system), 4);
server_manager->RegisterNamedService("ngc:u", std::make_shared<NgcServiceImpl>(system), 4); server_manager->RegisterNamedService("ngc:u", std::make_shared<NgcServiceImpl>(system), 4);
// +23.0.0
if (FirmwareManager::GetFirmwareVersion(system).first.major >= 23) {
server_manager->RegisterNamedService("stpl:u", std::make_shared<IUserService>(system), 4);
server_manager->RegisterNamedService("stpl:sys", std::make_shared<ISystemService>(system), 4);
}
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }
@@ -7,7 +7,7 @@
#pragma once #pragma once
#include "core/hle/service/cmif_types.h" #include "core/hle/service/cmif_types.h"
#include "core/hle/service/ns/i_async_result.h" #include "core/hle/service/ns/async_result.h"
#include "core/hle/service/ns/language.h" #include "core/hle/service/ns/language.h"
#include "core/hle/service/ns/ns_types.h" #include "core/hle/service/ns/ns_types.h"
#include "core/hle/service/os/event.h" #include "core/hle/service/os/event.h"
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ns/i_async_result.h" #include "core/hle/service/ns/async_result.h"
#include <cstring> #include <cstring>
@@ -311,27 +311,30 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
// u64 - app count // u64 - app count
memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64)); memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64));
out_length += sizeof(u64); out_length += sizeof(u64);
ASSERT(out_length <= t_mem->GetSize());
// [list of u64] - size of icons // [list of u64] - size of icons
for (size_t i = 0; i < app_count; ++i) { for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = app_ids_buffer[i]; const u64 app_id = app_ids_buffer[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()}; const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
const auto control = pm.GetControlMetadata(); if (const auto control = pm.GetControlMetadata(); control.second) {
u64 full_size = control.second->GetSize(); u64 full_size = control.second->GetSize();
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64)); memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
}
out_length += sizeof(u64); out_length += sizeof(u64);
ASSERT(out_length <= t_mem->GetSize());
} }
// [list of raw icon data] // [list of raw icon data]
std::vector<u8> full_icon_data;
for (size_t i = 0; i < app_count; ++i) { for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = app_ids_buffer[i]; const u64 app_id = app_ids_buffer[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()}; const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
const auto control = pm.GetControlMetadata(); if (const auto control = pm.GetControlMetadata(); control.second) {
auto const full_size = control.second->GetSize(); if (auto const full_size = control.second->GetSize(); full_size > 0) {
if (full_size > 0) { std::vector<u8> full_icon_data(full_size);
full_icon_data.resize(full_size); control.second->Read(full_icon_data.data(), full_size, 0);
control.second->Read(full_icon_data.data(), full_size, 0); memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size); out_length += full_size;
out_length += full_size; ASSERT(out_length <= t_mem->GetSize());
}
} }
} }
} }
@@ -345,6 +348,12 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) { void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
const auto app_ids_buffer = ctx.ReadBuffer(); const auto app_ids_buffer = ctx.ReadBuffer();
const size_t app_count = app_ids_buffer.size() / sizeof(u64); const size_t app_count = app_ids_buffer.size() / sizeof(u64);
std::vector<u64> application_ids(app_count);
if (app_count > 0) {
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
}
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0)); auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
auto* t_mem = t_mem_obj.GetPointerUnsafe(); auto* t_mem = t_mem_obj.GetPointerUnsafe();
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry); constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
@@ -354,8 +363,9 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestCo
auto& memory = system.ApplicationMemory(); auto& memory = system.ApplicationMemory();
const auto t_mem_address = t_mem->GetSourceAddress(); const auto t_mem_address = t_mem->GetSourceAddress();
for (size_t i = 0; i < app_count; ++i) { for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = app_ids_buffer[i]; const u64 app_id = application_ids[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()}; const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
system.GetContentProvider()};
const auto control = pm.GetControlMetadata(); const auto control = pm.GetControlMetadata();
FileSys::LanguageEntry entry{}; FileSys::LanguageEntry entry{};
if (control.first != nullptr) { if (control.first != nullptr) {
@@ -90,7 +90,7 @@ template<>
code.shl(tmp, int(ctx.conf.page_table_log2_stride)); code.shl(tmp, int(ctx.conf.page_table_log2_stride));
code.mov(page, qword[r14 + tmp.cvt64()]); code.mov(page, qword[r14 + tmp.cvt64()]);
} else { } else {
code.mov(page, qword[r14 + tmp.cvt64() * int(ctx.conf.page_table_log2_stride)]); code.mov(page, qword[r14 + tmp.cvt64() * int(1 << ctx.conf.page_table_log2_stride)]);
} }
// check for marked bit, use as unmapped if marked // check for marked bit, use as unmapped if marked
@@ -2850,8 +2850,6 @@ Sampler::VariantKey Sampler::MakeKey(const ImageView& image_view, bool is_depth)
VariantKey key{}; VariantKey key{};
key.reduce_anisotropy = has_added_anisotropy && !image_view.SupportsAnisotropy(); key.reduce_anisotropy = has_added_anisotropy && !image_view.SupportsAnisotropy();
key.force_nearest = has_linear_filtering && IsPixelFormatInteger(image_view.format); key.force_nearest = has_linear_filtering && IsPixelFormatInteger(image_view.format);
key.drop_depth_comparison =
is_depth && has_depth_comparison && !image_view.SupportsDepthComparison();
key.drop_reduction = has_minmax_reduction && !image_view.SupportsMinmaxFilter(); key.drop_reduction = has_minmax_reduction && !image_view.SupportsMinmaxFilter();
key.drop_custom_border = has_custom_border_colors && image_view.RequiresBorderColorFormat(); key.drop_custom_border = has_custom_border_colors && image_view.RequiresBorderColorFormat();
key.srgb_border = has_srgb_border_color && IsPixelFormatSRGB(image_view.format); key.srgb_border = has_srgb_border_color && IsPixelFormatSRGB(image_view.format);
@@ -2929,9 +2927,6 @@ VkSampler Sampler::Emplace(VariantKey key) {
create_info.anisotropyEnable = static_cast<VkBool32>(default_anisotropy > 1.0f); create_info.anisotropyEnable = static_cast<VkBool32>(default_anisotropy > 1.0f);
create_info.maxAnisotropy = default_anisotropy; create_info.maxAnisotropy = default_anisotropy;
} }
if (key.drop_depth_comparison) {
create_info.compareEnable = VK_FALSE;
}
if (!custom_border) { if (!custom_border) {
create_info.borderColor = ConvertBorderColor(color); create_info.borderColor = ConvertBorderColor(color);
} }
@@ -536,7 +536,6 @@ private:
struct VariantKey { struct VariantKey {
bool reduce_anisotropy; bool reduce_anisotropy;
bool force_nearest; bool force_nearest;
bool drop_depth_comparison;
bool drop_reduction; bool drop_reduction;
bool drop_custom_border; bool drop_custom_border;
bool srgb_border; bool srgb_border;