summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/api_version.h17
-rw-r--r--src/core/hle/kernel/k_handle_table.cpp2
-rw-r--r--src/core/hle/kernel/k_priority_queue.h27
-rw-r--r--src/core/hle/kernel/k_scheduler.h2
-rw-r--r--src/core/hle/kernel/k_scoped_lock.h15
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h2
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/service/acc/acc.cpp69
-rw-r--r--src/core/hle/service/acc/async_context.cpp68
-rw-r--r--src/core/hle/service/acc/async_context.h37
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp9
-rw-r--r--src/core/hle/service/am/am.cpp24
-rw-r--r--src/core/hle/service/am/am.h2
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.cpp2
-rw-r--r--src/core/hle/service/audio/audctl.cpp8
-rw-r--r--src/core/hle/service/audio/audin_u.cpp79
-rw-r--r--src/core/hle/service/audio/audin_u.h14
-rw-r--r--src/core/hle/service/audio/audren_u.cpp3
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp548
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.h64
-rw-r--r--src/core/hle/service/bcat/bcat_module.cpp7
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp4
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp1
-rw-r--r--src/core/hle/service/es/es.cpp6
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp38
-rw-r--r--src/core/hle/service/filesystem/filesystem.h6
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp20
-rw-r--r--src/core/hle/service/hid/controllers/npad.h1
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h14
-rw-r--r--src/core/hle/service/hid/hid.cpp25
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/ngct/ngct.cpp15
-rw-r--r--src/core/hle/service/npns/npns.cpp1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp11
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp25
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h15
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.cpp14
-rw-r--r--src/core/hle/service/sockets/bsd.h1
-rw-r--r--src/core/hle/service/time/system_clock_core.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp4
-rw-r--r--src/core/hle/service/usb/usb.cpp6
-rw-r--r--src/core/hle/service/vi/vi.cpp1
43 files changed, 465 insertions, 750 deletions
diff --git a/src/core/hle/api_version.h b/src/core/hle/api_version.h
index 43d5670a9..626e30753 100644
--- a/src/core/hle/api_version.h
+++ b/src/core/hle/api_version.h
@@ -28,13 +28,20 @@ constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0";
// Atmosphere version constants.
-constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
-constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
-constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 5;
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1;
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0;
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0;
+
+constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) {
+ return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev};
+}
+
+constexpr u32 AtmosphereTargetFirmware(u8 major, u8 minor, u8 micro) {
+ return AtmosphereTargetFirmwareWithRevision(major, minor, micro, 0);
+}
constexpr u32 GetTargetFirmware() {
- return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
- u32{HOS_VERSION_MICRO} << 8 | 0U;
+ return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO);
}
} // namespace HLE::ApiVersion
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp
index 6a420d5b0..44d13169f 100644
--- a/src/core/hle/kernel/k_handle_table.cpp
+++ b/src/core/hle/kernel/k_handle_table.cpp
@@ -7,7 +7,7 @@
namespace Kernel {
KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
-KHandleTable ::~KHandleTable() = default;
+KHandleTable::~KHandleTable() = default;
ResultCode KHandleTable::Finalize() {
// Get the table and clear our record of it.
diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h
index 4aa669d95..f4d71ad7e 100644
--- a/src/core/hle/kernel/k_priority_queue.h
+++ b/src/core/hle/kernel/k_priority_queue.h
@@ -22,12 +22,10 @@ class KThread;
template <typename T>
concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) {
- { t.GetAffinityMask() }
- ->Common::ConvertibleTo<u64>;
+ { t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
{t.SetAffinityMask(0)};
- { t.GetAffinity(0) }
- ->std::same_as<bool>;
+ { t.GetAffinity(0) } -> std::same_as<bool>;
{t.SetAffinity(0, false)};
{t.SetAll()};
};
@@ -38,25 +36,20 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
{(typename T::QueueEntry()).Initialize()};
{(typename T::QueueEntry()).SetPrev(std::addressof(t))};
{(typename T::QueueEntry()).SetNext(std::addressof(t))};
- { (typename T::QueueEntry()).GetNext() }
- ->std::same_as<T*>;
- { (typename T::QueueEntry()).GetPrev() }
- ->std::same_as<T*>;
- { t.GetPriorityQueueEntry(0) }
- ->std::same_as<typename T::QueueEntry&>;
+ { (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
+ { (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
+ { t.GetPriorityQueueEntry(0) } -> std::same_as<typename T::QueueEntry&>;
{t.GetAffinityMask()};
- { std::remove_cvref_t<decltype(t.GetAffinityMask())>() }
- ->KPriorityQueueAffinityMask;
+ { std::remove_cvref_t<decltype(t.GetAffinityMask())>() } -> KPriorityQueueAffinityMask;
- { t.GetActiveCore() }
- ->Common::ConvertibleTo<s32>;
- { t.GetPriority() }
- ->Common::ConvertibleTo<s32>;
+ { t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
+ { t.GetPriority() } -> Common::ConvertibleTo<s32>;
};
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
-requires KPriorityQueueMember<Member> class KPriorityQueue {
+requires KPriorityQueueMember<Member>
+class KPriorityQueue {
public:
using AffinityMaskType = std::remove_cv_t<
std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>;
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index 12cfae919..c8ccc1ae4 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -197,7 +197,7 @@ private:
class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> {
public:
- explicit KScopedSchedulerLock(KernelCore & kernel);
+ explicit KScopedSchedulerLock(KernelCore& kernel);
~KScopedSchedulerLock();
};
diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h
index 72c3b0252..4fb180fc6 100644
--- a/src/core/hle/kernel/k_scoped_lock.h
+++ b/src/core/hle/kernel/k_scoped_lock.h
@@ -13,19 +13,18 @@ namespace Kernel {
template <typename T>
concept KLockable = !std::is_reference_v<T> && requires(T & t) {
- { t.Lock() }
- ->std::same_as<void>;
- { t.Unlock() }
- ->std::same_as<void>;
+ { t.Lock() } -> std::same_as<void>;
+ { t.Unlock() } -> std::same_as<void>;
};
template <typename T>
-requires KLockable<T> class [[nodiscard]] KScopedLock {
+requires KLockable<T>
+class [[nodiscard]] KScopedLock {
public:
- explicit KScopedLock(T * l) : lock_ptr(l) {
+ explicit KScopedLock(T* l) : lock_ptr(l) {
this->lock_ptr->Lock();
}
- explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {}
+ explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) {}
~KScopedLock() {
this->lock_ptr->Unlock();
@@ -34,7 +33,7 @@ public:
KScopedLock(const KScopedLock&) = delete;
KScopedLock& operator=(const KScopedLock&) = delete;
- KScopedLock(KScopedLock &&) = delete;
+ KScopedLock(KScopedLock&&) = delete;
KScopedLock& operator=(KScopedLock&&) = delete;
private:
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
index a86af56dd..f6c75f2d9 100644
--- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
+++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
@@ -17,7 +17,7 @@ namespace Kernel {
class [[nodiscard]] KScopedSchedulerLockAndSleep {
public:
- explicit KScopedSchedulerLockAndSleep(KernelCore & kernel_, KThread * t, s64 timeout)
+ explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout)
: kernel(kernel_), thread(t), timeout_tick(timeout) {
// Lock the scheduler.
kernel.GlobalSchedulerContext().scheduler_lock.Lock();
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 3a6db0b1c..901d43da9 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -5,6 +5,7 @@
#pragma once
#include <array>
+#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 882fc1492..689b36056 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -23,6 +23,7 @@
#include "core/hle/service/acc/acc_su.h"
#include "core/hle/service/acc/acc_u0.h"
#include "core/hle/service/acc/acc_u1.h"
+#include "core/hle/service/acc/async_context.h"
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/glue/arp.h"
@@ -454,22 +455,6 @@ public:
: IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {}
};
-class IAsyncContext final : public ServiceFramework<IAsyncContext> {
-public:
- explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetSystemEvent"},
- {1, nullptr, "Cancel"},
- {2, nullptr, "HasDone"},
- {3, nullptr, "GetResult"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
class ISessionObject final : public ServiceFramework<ISessionObject> {
public:
explicit ISessionObject(Core::System& system_, Common::UUID)
@@ -504,16 +489,44 @@ public:
}
};
+class EnsureTokenIdCacheAsyncInterface final : public IAsyncContext {
+public:
+ explicit EnsureTokenIdCacheAsyncInterface(Core::System& system_) : IAsyncContext{system_} {
+ MarkComplete();
+ }
+ ~EnsureTokenIdCacheAsyncInterface() = default;
+
+ void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+ }
+
+protected:
+ bool IsComplete() const override {
+ return true;
+ }
+
+ void Cancel() override {}
+
+ ResultCode GetResult() const override {
+ return ResultSuccess;
+ }
+};
+
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_)
- : ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} {
+ : ServiceFramework{system_, "IManagerForApplication"},
+ ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
+ user_id{user_id_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
- {2, nullptr, "EnsureIdTokenCacheAsync"},
- {3, nullptr, "LoadIdTokenCache"},
+ {2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"},
+ {3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"},
{130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
@@ -540,6 +553,20 @@ private:
rb.PushRaw<u64>(user_id.GetNintendoID());
}
+ void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface(ensure_token_id);
+ }
+
+ void LoadIdTokenCache(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+
+ ensure_token_id->LoadIdTokenCache(ctx);
+ }
+
void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
@@ -562,6 +589,7 @@ private:
rb.Push(ResultSuccess);
}
+ std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
Common::UUID user_id{Common::INVALID_UUID};
};
@@ -901,8 +929,7 @@ void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContex
}
const auto user_list = profile_manager->GetAllUsers();
- if (std::all_of(user_list.begin(), user_list.end(),
- [](const auto& user) { return user.uuid == Common::INVALID_UUID; })) {
+ if (std::ranges::all_of(user_list, [](const auto& user) { return user.IsInvalid(); })) {
rb.Push(ResultUnknown); // TODO(ogniK): Find the correct error code
rb.PushRaw<u128>(Common::INVALID_UUID);
return;
diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp
new file mode 100644
index 000000000..459323132
--- /dev/null
+++ b/src/core/hle/service/acc/async_context.cpp
@@ -0,0 +1,68 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/core.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/service/acc/async_context.h"
+
+namespace Service::Account {
+IAsyncContext::IAsyncContext(Core::System& system_)
+ : ServiceFramework{system_, "IAsyncContext"}, compeletion_event{system_.Kernel()} {
+
+ Kernel::KAutoObject::Create(std::addressof(compeletion_event));
+ compeletion_event.Initialize("IAsyncContext:CompletionEvent");
+
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"},
+ {1, &IAsyncContext::Cancel, "Cancel"},
+ {2, &IAsyncContext::HasDone, "HasDone"},
+ {3, &IAsyncContext::GetResult, "GetResult"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_ACC, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(compeletion_event.GetReadableEvent());
+}
+
+void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_ACC, "called");
+
+ Cancel();
+ MarkComplete();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_ACC, "called");
+
+ is_complete.store(IsComplete());
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(is_complete.load());
+}
+
+void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_ACC, "called");
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(GetResult());
+}
+
+void IAsyncContext::MarkComplete() {
+ is_complete.store(true);
+ compeletion_event.GetWritableEvent().Signal();
+}
+
+} // namespace Service::Account
diff --git a/src/core/hle/service/acc/async_context.h b/src/core/hle/service/acc/async_context.h
new file mode 100644
index 000000000..c694b4946
--- /dev/null
+++ b/src/core/hle/service/acc/async_context.h
@@ -0,0 +1,37 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Account {
+
+class IAsyncContext : public ServiceFramework<IAsyncContext> {
+public:
+ explicit IAsyncContext(Core::System& system_);
+
+ void GetSystemEvent(Kernel::HLERequestContext& ctx);
+ void Cancel(Kernel::HLERequestContext& ctx);
+ void HasDone(Kernel::HLERequestContext& ctx);
+ void GetResult(Kernel::HLERequestContext& ctx);
+
+protected:
+ virtual bool IsComplete() const = 0;
+ virtual void Cancel() = 0;
+ virtual ResultCode GetResult() const = 0;
+
+ void MarkComplete();
+
+ std::atomic<bool> is_complete{false};
+ Kernel::KEvent compeletion_event;
+};
+
+} // namespace Service::Account
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 24a1c9157..568303ced 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -208,9 +208,10 @@ bool ProfileManager::UserExists(UUID uuid) const {
}
bool ProfileManager::UserExistsIndex(std::size_t index) const {
- if (index >= MAX_USERS)
+ if (index >= MAX_USERS) {
return false;
- return profiles[index].user_uuid.uuid != Common::INVALID_UUID;
+ }
+ return profiles[index].user_uuid.IsValid();
}
/// Opens a specific user
@@ -304,7 +305,7 @@ bool ProfileManager::RemoveUser(UUID uuid) {
bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
const auto index = GetUserIndex(uuid);
- if (!index || profile_new.user_uuid == UUID(Common::INVALID_UUID)) {
+ if (!index || profile_new.user_uuid.IsInvalid()) {
return false;
}
@@ -346,7 +347,7 @@ void ProfileManager::ParseUserSaveFile() {
}
for (const auto& user : data.users) {
- if (user.uuid == UUID(Common::INVALID_UUID)) {
+ if (user.uuid.IsInvalid()) {
continue;
}
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index a538f82e3..49e9787a4 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -275,12 +275,14 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
{19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
+ {21, nullptr, "GetScreenShotProgramId"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
+ {46, nullptr, "SetRecordingLayerCompositionEnabled"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
@@ -302,6 +304,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
{100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
{110, nullptr, "SetApplicationAlbumUserData"},
{120, nullptr, "SaveCurrentScreenshot"},
+ {130, nullptr, "SetRecordVolumeMuted"},
{1000, nullptr, "GetDebugStorageChannel"},
};
// clang-format on
@@ -329,10 +332,10 @@ ISelfController::~ISelfController() = default;
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
- system.Shutdown();
-
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
+
+ system.Exit();
}
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
@@ -683,6 +686,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{91, nullptr, "GetCurrentPerformanceConfiguration"},
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
{110, nullptr, "OpenMyGpuErrorHandler"},
+ {120, nullptr, "GetAppletLaunchedHistory"},
{200, nullptr, "GetOperationModeSystemInfo"},
{300, nullptr, "GetSettingsPlatformRegion"},
{400, nullptr, "ActivateMigrationService"},
@@ -1270,7 +1274,8 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
: ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()},
friend_invitation_storage_channel_event{system.Kernel()},
- health_warning_disappeared_system_event{system.Kernel()} {
+ notification_storage_channel_event{system.Kernel()}, health_warning_disappeared_system_event{
+ system.Kernel()} {
// clang-format off
static const FunctionInfo functions[] = {
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
@@ -1322,7 +1327,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
- {150, nullptr, "GetNotificationStorageChannelEvent"},
+ {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
{151, nullptr, "TryPopFromNotificationStorageChannel"},
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
{170, nullptr, "SetHdcpAuthenticationActivated"},
@@ -1340,11 +1345,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event));
Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event));
+ Kernel::KAutoObject::Create(std::addressof(notification_storage_channel_event));
Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event));
gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent");
friend_invitation_storage_channel_event.Initialize(
"IApplicationFunctions:FriendInvitationStorageChannelEvent");
+ notification_storage_channel_event.Initialize(
+ "IApplicationFunctions:NotificationStorageChannelEvent");
health_warning_disappeared_system_event.Initialize(
"IApplicationFunctions:HealthWarningDisappearedSystemEvent");
}
@@ -1762,6 +1770,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
rb.Push(ERR_NO_DATA_IN_CHANNEL);
}
+void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_AM, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(notification_storage_channel_event.GetReadableEvent());
+}
+
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 184030a8e..c13aa5787 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -295,6 +295,7 @@ private:
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
+ void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx);
void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
@@ -302,6 +303,7 @@ private:
s32 previous_program_index{-1};
Kernel::KEvent gpu_error_detected_event;
Kernel::KEvent friend_invitation_storage_channel_event;
+ Kernel::KEvent notification_storage_channel_event;
Kernel::KEvent health_warning_disappeared_system_event;
};
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index bdc21778e..a6e891944 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -60,7 +60,7 @@ void ProfileSelect::Execute() {
void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
UserSelectionOutput output{};
- if (uuid.has_value() && uuid->uuid != Common::INVALID_UUID) {
+ if (uuid.has_value() && uuid->IsValid()) {
output.result = 0;
output.uuid_selected = uuid->uuid;
} else {
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index 8c4c49b85..2e46e7161 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -41,6 +41,14 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
+ {30, nullptr, "Unknown30"},
+ {31, nullptr, "Unknown31"},
+ {32, nullptr, "Unknown32"},
+ {33, nullptr, "Unknown33"},
+ {34, nullptr, "Unknown34"},
+ {10000, nullptr, "Unknown10000"},
+ {10001, nullptr, "Unknown10001"},
+ {10002, nullptr, "Unknown10002"},
};
// clang-format on
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 3e7fd6024..570525019 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -3,38 +3,65 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_event.h"
#include "core/hle/service/audio/audin_u.h"
namespace Service::Audio {
-class IAudioIn final : public ServiceFramework<IAudioIn> {
-public:
- explicit IAudioIn(Core::System& system_) : ServiceFramework{system_, "IAudioIn"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetAudioInState"},
- {1, nullptr, "Start"},
- {2, nullptr, "Stop"},
- {3, nullptr, "AppendAudioInBuffer"},
- {4, nullptr, "RegisterBufferEvent"},
- {5, nullptr, "GetReleasedAudioInBuffer"},
- {6, nullptr, "ContainsAudioInBuffer"},
- {7, nullptr, "AppendUacInBuffer"},
- {8, nullptr, "AppendAudioInBufferAuto"},
- {9, nullptr, "GetReleasedAudioInBuffersAuto"},
- {10, nullptr, "AppendUacInBufferAuto"},
- {11, nullptr, "GetAudioInBufferCount"},
- {12, nullptr, "SetDeviceGain"},
- {13, nullptr, "GetDeviceGain"},
- {14, nullptr, "FlushAudioInBuffers"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
+IAudioIn::IAudioIn(Core::System& system_)
+ : ServiceFramework{system_, "IAudioIn"}, buffer_event{system_.Kernel()} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetAudioInState"},
+ {1, &IAudioIn::Start, "Start"},
+ {2, nullptr, "Stop"},
+ {3, nullptr, "AppendAudioInBuffer"},
+ {4, &IAudioIn::RegisterBufferEvent, "RegisterBufferEvent"},
+ {5, nullptr, "GetReleasedAudioInBuffer"},
+ {6, nullptr, "ContainsAudioInBuffer"},
+ {7, nullptr, "AppendUacInBuffer"},
+ {8, &IAudioIn::AppendAudioInBufferAuto, "AppendAudioInBufferAuto"},
+ {9, nullptr, "GetReleasedAudioInBuffersAuto"},
+ {10, nullptr, "AppendUacInBufferAuto"},
+ {11, nullptr, "GetAudioInBufferCount"},
+ {12, nullptr, "SetDeviceGain"},
+ {13, nullptr, "GetDeviceGain"},
+ {14, nullptr, "FlushAudioInBuffers"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ Kernel::KAutoObject::Create(std::addressof(buffer_event));
+ buffer_event.Initialize("IAudioIn:BufferEvent");
+}
+
+IAudioIn::~IAudioIn() = default;
+
+void IAudioIn::Start(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_Audio, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioIn::RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_Audio, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(buffer_event.GetReadableEvent());
+}
+
+void IAudioIn::AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_Audio, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
AudInU::AudInU(Core::System& system_) : ServiceFramework{system_, "audin:u"} {
// clang-format off
diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h
index 0d75ae5ac..f2f7f9932 100644
--- a/src/core/hle/service/audio/audin_u.h
+++ b/src/core/hle/service/audio/audin_u.h
@@ -4,6 +4,7 @@
#pragma once
+#include "core/hle/kernel/k_event.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -16,6 +17,19 @@ class HLERequestContext;
namespace Service::Audio {
+class IAudioIn final : public ServiceFramework<IAudioIn> {
+public:
+ explicit IAudioIn(Core::System& system_);
+ ~IAudioIn() override;
+
+private:
+ void Start(Kernel::HLERequestContext& ctx);
+ void RegisterBufferEvent(Kernel::HLERequestContext& ctx);
+ void AppendAudioInBufferAuto(Kernel::HLERequestContext& ctx);
+
+ Kernel::KEvent buffer_event;
+};
+
class AudInU final : public ServiceFramework<AudInU> {
public:
explicit AudInU(Core::System& system_);
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index b769fe959..1a91719f5 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -187,7 +187,8 @@ public:
{10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
{11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
{12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
- {13, nullptr, "GetAudioSystemMasterVolumeSetting"},
+ {13, nullptr, "GetActiveAudioOutputDeviceName"},
+ {14, nullptr, "ListAudioOutputDeviceName"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
deleted file mode 100644
index 7ca7f2aac..000000000
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-// Copyright 2019 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <fmt/ostream.h>
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wshadow"
-#ifndef __clang__
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-#endif
-#include <httplib.h>
-#include <mbedtls/sha256.h>
-#include <nlohmann/json.hpp>
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-#include "common/fs/file.h"
-#include "common/fs/fs.h"
-#include "common/fs/path_util.h"
-#include "common/hex_util.h"
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/core.h"
-#include "core/file_sys/vfs.h"
-#include "core/file_sys/vfs_libzip.h"
-#include "core/file_sys/vfs_vector.h"
-#include "core/frontend/applets/error.h"
-#include "core/hle/service/am/applets/applets.h"
-#include "core/hle/service/bcat/backend/boxcat.h"
-
-namespace Service::BCAT {
-namespace {
-
-// Prevents conflicts with windows macro called CreateFile
-FileSys::VirtualFile VfsCreateFileWrap(FileSys::VirtualDir dir, std::string_view name) {
- return dir->CreateFile(name);
-}
-
-// Prevents conflicts with windows macro called DeleteFile
-bool VfsDeleteFileWrap(FileSys::VirtualDir dir, std::string_view name) {
- return dir->DeleteFile(name);
-}
-
-constexpr ResultCode ERROR_GENERAL_BCAT_FAILURE{ErrorModule::BCAT, 1};
-
-constexpr char BOXCAT_HOSTNAME[] = "api.yuzu-emu.org";
-
-// Formatted using fmt with arg[0] = hex title id
-constexpr char BOXCAT_PATHNAME_DATA[] = "/game-assets/{:016X}/boxcat";
-constexpr char BOXCAT_PATHNAME_LAUNCHPARAM[] = "/game-assets/{:016X}/launchparam";
-
-constexpr char BOXCAT_PATHNAME_EVENTS[] = "/game-assets/boxcat/events";
-
-constexpr char BOXCAT_API_VERSION[] = "1";
-constexpr char BOXCAT_CLIENT_TYPE[] = "yuzu";
-
-// HTTP status codes for Boxcat
-enum class ResponseStatus {
- Ok = 200, ///< Operation completed successfully.
- BadClientVersion = 301, ///< The Boxcat-Client-Version doesn't match the server.
- NoUpdate = 304, ///< The digest provided would match the new data, no need to update.
- NoMatchTitleId = 404, ///< The title ID provided doesn't have a boxcat implementation.
- NoMatchBuildId = 406, ///< The build ID provided is blacklisted (potentially because of format
- ///< issues or whatnot) and has no data.
-};
-
-enum class DownloadResult {
- Success = 0,
- NoResponse,
- GeneralWebError,
- NoMatchTitleId,
- NoMatchBuildId,
- InvalidContentType,
- GeneralFSError,
- BadClientVersion,
-};
-
-constexpr std::array<const char*, 8> DOWNLOAD_RESULT_LOG_MESSAGES{
- "Success",
- "There was no response from the server.",
- "There was a general web error code returned from the server.",
- "The title ID of the current game doesn't have a boxcat implementation. If you believe an "
- "implementation should be added, contact yuzu support.",
- "The build ID of the current version of the game is marked as incompatible with the current "
- "BCAT distribution. Try upgrading or downgrading your game version or contacting yuzu support.",
- "The content type of the web response was invalid.",
- "There was a general filesystem error while saving the zip file.",
- "The server is either too new or too old to serve the request. Try using the latest version of "
- "an official release of yuzu.",
-};
-
-std::ostream& operator<<(std::ostream& os, DownloadResult result) {
- return os << DOWNLOAD_RESULT_LOG_MESSAGES.at(static_cast<std::size_t>(result));
-}
-
-constexpr u32 PORT = 443;
-constexpr u32 TIMEOUT_SECONDS = 30;
-[[maybe_unused]] constexpr u64 VFS_COPY_BLOCK_SIZE = 1ULL << 24; // 4MB
-
-std::filesystem::path GetBINFilePath(u64 title_id) {
- return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
- fmt::format("{:016X}/launchparam.bin", title_id);
-}
-
-std::filesystem::path GetZIPFilePath(u64 title_id) {
- return Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "bcat" /
- fmt::format("{:016X}/data.zip", title_id);
-}
-
-// If the error is something the user should know about (build ID mismatch, bad client version),
-// display an error.
-void HandleDownloadDisplayResult(const AM::Applets::AppletManager& applet_manager,
- DownloadResult res) {
- if (res == DownloadResult::Success || res == DownloadResult::NoResponse ||
- res == DownloadResult::GeneralWebError || res == DownloadResult::GeneralFSError ||
- res == DownloadResult::NoMatchTitleId || res == DownloadResult::InvalidContentType) {
- return;
- }
-
- const auto& frontend{applet_manager.GetAppletFrontendSet()};
- frontend.error->ShowCustomErrorText(
- ResultUnknown, "There was an error while attempting to use Boxcat.",
- DOWNLOAD_RESULT_LOG_MESSAGES[static_cast<std::size_t>(res)], [] {});
-}
-
-bool VfsRawCopyProgress(FileSys::VirtualFile src, FileSys::VirtualFile dest,
- std::string_view dir_name, ProgressServiceBackend& progress,
- std::size_t block_size = 0x1000) {
- if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
- return false;
- if (!dest->Resize(src->GetSize()))
- return false;
-
- progress.StartDownloadingFile(dir_name, src->GetName(), src->GetSize());
-
- 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);
-
- if (src->Read(temp.data(), read, i) != read) {
- return false;
- }
-
- if (dest->Write(temp.data(), read, i) != read) {
- return false;
- }
-
- progress.UpdateFileProgress(i);
- }
-
- progress.FinishDownloadingFile();
-
- return true;
-}
-
-bool VfsRawCopyDProgressSingle(FileSys::VirtualDir src, FileSys::VirtualDir dest,
- ProgressServiceBackend& progress, std::size_t block_size = 0x1000) {
- if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
- return false;
-
- for (const auto& file : src->GetFiles()) {
- const auto out_file = VfsCreateFileWrap(dest, file->GetName());
- if (!VfsRawCopyProgress(file, out_file, src->GetName(), progress, block_size)) {
- return false;
- }
- }
- progress.CommitDirectory(src->GetName());
-
- return true;
-}
-
-bool VfsRawCopyDProgress(FileSys::VirtualDir src, FileSys::VirtualDir dest,
- ProgressServiceBackend& progress, std::size_t block_size = 0x1000) {
- if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
- return false;
-
- for (const auto& dir : src->GetSubdirectories()) {
- const auto out = dest->CreateSubdirectory(dir->GetName());
- if (!VfsRawCopyDProgressSingle(dir, out, progress, block_size)) {
- return false;
- }
- }
-
- return true;
-}
-
-} // Anonymous namespace
-
-class Boxcat::Client {
-public:
- Client(std::filesystem::path path_, u64 title_id_, u64 build_id_)
- : path(std::move(path_)), title_id(title_id_), build_id(build_id_) {}
-
- DownloadResult DownloadDataZip() {
- return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS,
- "application/zip");
- }
-
- DownloadResult DownloadLaunchParam() {
- return DownloadInternal(fmt::format(BOXCAT_PATHNAME_LAUNCHPARAM, title_id),
- TIMEOUT_SECONDS / 3, "application/octet-stream");
- }
-
-private:
- DownloadResult DownloadInternal(const std::string& resolved_path, u32 timeout_seconds,
- const std::string& content_type_name) {
- if (client == nullptr) {
- client = std::make_unique<httplib::SSLClient>(BOXCAT_HOSTNAME, PORT);
- client->set_connection_timeout(timeout_seconds);
- client->set_read_timeout(timeout_seconds);
- client->set_write_timeout(timeout_seconds);
- }
-
- httplib::Headers headers{
- {std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
- {std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)},
- {std::string("Game-Build-Id"), fmt::format("{:016X}", build_id)},
- };
-
- if (Common::FS::Exists(path)) {
- Common::FS::IOFile file{path, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
- if (file.IsOpen()) {
- std::vector<u8> bytes(file.GetSize());
- void(file.Read(bytes));
- const auto digest = DigestFile(bytes);
- headers.insert({std::string("If-None-Match"), Common::HexToString(digest, false)});
- }
- }
-
- const auto response = client->Get(resolved_path.c_str(), headers);
- if (response == nullptr)
- return DownloadResult::NoResponse;
-
- if (response->status == static_cast<int>(ResponseStatus::NoUpdate))
- return DownloadResult::Success;
- if (response->status == static_cast<int>(ResponseStatus::BadClientVersion))
- return DownloadResult::BadClientVersion;
- if (response->status == static_cast<int>(ResponseStatus::NoMatchTitleId))
- return DownloadResult::NoMatchTitleId;
- if (response->status == static_cast<int>(ResponseStatus::NoMatchBuildId))
- return DownloadResult::NoMatchBuildId;
- if (response->status != static_cast<int>(ResponseStatus::Ok))
- return DownloadResult::GeneralWebError;
-
- const auto content_type = response->headers.find("content-type");
- if (content_type == response->headers.end() ||
- content_type->second.find(content_type_name) == std::string::npos) {
- return DownloadResult::InvalidContentType;
- }
-
- if (!Common::FS::CreateDirs(path)) {
- return DownloadResult::GeneralFSError;
- }
-
- Common::FS::IOFile file{path, Common::FS::FileAccessMode::Append,
- Common::FS::FileType::BinaryFile};
- if (!file.IsOpen()) {
- return DownloadResult::GeneralFSError;
- }
-
- if (!file.SetSize(response->body.size())) {
- return DownloadResult::GeneralFSError;
- }
-
- if (file.Write(response->body) != response->body.size()) {
- return DownloadResult::GeneralFSError;
- }
-
- return DownloadResult::Success;
- }
-
- using Digest = std::array<u8, 0x20>;
- static Digest DigestFile(std::vector<u8> bytes) {
- Digest out{};
- mbedtls_sha256_ret(bytes.data(), bytes.size(), out.data(), 0);
- return out;
- }
-
- std::unique_ptr<httplib::SSLClient> client;
- std::filesystem::path path;
- u64 title_id;
- u64 build_id;
-};
-
-Boxcat::Boxcat(AM::Applets::AppletManager& applet_manager_, DirectoryGetter getter)
- : Backend(std::move(getter)), applet_manager{applet_manager_} {}
-
-Boxcat::~Boxcat() = default;
-
-void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGetter dir_getter,
- TitleIDVersion title, ProgressServiceBackend& progress,
- std::optional<std::string> dir_name = {}) {
- progress.SetNeedHLELock(true);
-
- if (Settings::values.bcat_boxcat_local) {
- LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download.");
- const auto dir = dir_getter(title.title_id);
- if (dir)
- progress.SetTotalSize(dir->GetSize());
- progress.FinishDownload(ResultSuccess);
- return;
- }
-
- const auto zip_path = GetZIPFilePath(title.title_id);
- Boxcat::Client client{zip_path, title.title_id, title.build_id};
-
- progress.StartConnecting();
-
- const auto res = client.DownloadDataZip();
- if (res != DownloadResult::Success) {
- LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
-
- if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
- Common::FS::RemoveFile(zip_path);
- }
-
- HandleDownloadDisplayResult(applet_manager, res);
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
-
- progress.StartProcessingDataList();
-
- Common::FS::IOFile zip{zip_path, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
- const auto size = zip.GetSize();
- std::vector<u8> bytes(size);
- if (!zip.IsOpen() || size == 0 || zip.Read(bytes) != bytes.size()) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to read ZIP file at path '{}'!",
- Common::FS::PathToUTF8String(zip_path));
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
-
- const auto extracted = FileSys::ExtractZIP(std::make_shared<FileSys::VectorVfsFile>(bytes));
- if (extracted == nullptr) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to extract ZIP file!");
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
-
- if (dir_name == std::nullopt) {
- progress.SetTotalSize(extracted->GetSize());
-
- const auto target_dir = dir_getter(title.title_id);
- if (target_dir == nullptr || !VfsRawCopyDProgress(extracted, target_dir, progress)) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to copy extracted ZIP to target directory!");
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
- } else {
- const auto target_dir = dir_getter(title.title_id);
- if (target_dir == nullptr) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to get directory for title ID!");
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
-
- const auto target_sub = target_dir->GetSubdirectory(*dir_name);
- const auto source_sub = extracted->GetSubdirectory(*dir_name);
-
- progress.SetTotalSize(source_sub->GetSize());
-
- std::vector<std::string> filenames;
- {
- const auto files = target_sub->GetFiles();
- std::transform(files.begin(), files.end(), std::back_inserter(filenames),
- [](const auto& vfile) { return vfile->GetName(); });
- }
-
- for (const auto& filename : filenames) {
- VfsDeleteFileWrap(target_sub, filename);
- }
-
- if (target_sub == nullptr || source_sub == nullptr ||
- !VfsRawCopyDProgressSingle(source_sub, target_sub, progress)) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to copy extracted ZIP to target directory!");
- progress.FinishDownload(ERROR_GENERAL_BCAT_FAILURE);
- return;
- }
- }
-
- progress.FinishDownload(ResultSuccess);
-}
-
-bool Boxcat::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) {
- is_syncing.exchange(true);
-
- std::thread([this, title, &progress] {
- SynchronizeInternal(applet_manager, dir_getter, title, progress);
- }).detach();
-
- return true;
-}
-
-bool Boxcat::SynchronizeDirectory(TitleIDVersion title, std::string name,
- ProgressServiceBackend& progress) {
- is_syncing.exchange(true);
-
- std::thread([this, title, name, &progress] {
- SynchronizeInternal(applet_manager, dir_getter, title, progress, name);
- }).detach();
-
- return true;
-}
-
-bool Boxcat::Clear(u64 title_id) {
- if (Settings::values.bcat_boxcat_local) {
- LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping clear.");
- return true;
- }
-
- const auto dir = dir_getter(title_id);
-
- std::vector<std::string> dirnames;
-
- for (const auto& subdir : dir->GetSubdirectories())
- dirnames.push_back(subdir->GetName());
-
- for (const auto& subdir : dirnames) {
- if (!dir->DeleteSubdirectoryRecursive(subdir))
- return false;
- }
-
- return true;
-}
-
-void Boxcat::SetPassphrase(u64 title_id, const Passphrase& passphrase) {
- LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id,
- Common::HexToString(passphrase));
-}
-
-std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title) {
- const auto bin_file_path = GetBINFilePath(title.title_id);
-
- if (Settings::values.bcat_boxcat_local) {
- LOG_INFO(Service_BCAT, "Boxcat using local data by override, skipping download.");
- } else {
- Client launch_client{bin_file_path, title.title_id, title.build_id};
-
- const auto res = launch_client.DownloadLaunchParam();
- if (res != DownloadResult::Success) {
- LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
-
- if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
- Common::FS::RemoveFile(bin_file_path);
- }
-
- HandleDownloadDisplayResult(applet_manager, res);
- return std::nullopt;
- }
- }
-
- Common::FS::IOFile bin{bin_file_path, Common::FS::FileAccessMode::Read,
- Common::FS::FileType::BinaryFile};
- const auto size = bin.GetSize();
- std::vector<u8> bytes(size);
- if (!bin.IsOpen() || size == 0 || bin.Read(bytes) != bytes.size()) {
- LOG_ERROR(Service_BCAT, "Boxcat failed to read launch parameter binary at path '{}'!",
- Common::FS::PathToUTF8String(bin_file_path));
- return std::nullopt;
- }
-
- return bytes;
-}
-
-Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
- std::map<std::string, EventStatus>& games) {
- httplib::SSLClient client{BOXCAT_HOSTNAME, static_cast<int>(PORT)};
- client.set_connection_timeout(static_cast<int>(TIMEOUT_SECONDS));
- client.set_read_timeout(static_cast<int>(TIMEOUT_SECONDS));
- client.set_write_timeout(static_cast<int>(TIMEOUT_SECONDS));
-
- httplib::Headers headers{
- {std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
- {std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)},
- };
-
- if (!client.is_valid()) {
- LOG_ERROR(Service_BCAT, "Client is invalid, going offline!");
- return StatusResult::Offline;
- }
-
- if (!client.is_socket_open()) {
- LOG_ERROR(Service_BCAT, "Failed to open socket, going offline!");
- return StatusResult::Offline;
- }
-
- const auto response = client.Get(BOXCAT_PATHNAME_EVENTS, headers);
- if (response == nullptr)
- return StatusResult::Offline;
-
- if (response->status == static_cast<int>(ResponseStatus::BadClientVersion))
- return StatusResult::BadClientVersion;
-
- try {
- nlohmann::json json = nlohmann::json::parse(response->body);
-
- if (!json["online"].get<bool>())
- return StatusResult::Offline;
-
- if (json["global"].is_null())
- global = std::nullopt;
- else
- global = json["global"].get<std::string>();
-
- if (json["games"].is_array()) {
- for (const auto& object : json["games"]) {
- if (object.is_object() && object.find("name") != object.end()) {
- EventStatus detail{};
- if (object["header"].is_string()) {
- detail.header = object["header"].get<std::string>();
- } else {
- detail.header = std::nullopt;
- }
-
- if (object["footer"].is_string()) {
- detail.footer = object["footer"].get<std::string>();
- } else {
- detail.footer = std::nullopt;
- }
-
- if (object["events"].is_array()) {
- for (const auto& event : object["events"]) {
- if (!event.is_string())
- continue;
- detail.events.push_back(event.get<std::string>());
- }
- }
-
- games.insert_or_assign(object["name"], std::move(detail));
- }
- }
- }
-
- return StatusResult::Success;
- } catch (const nlohmann::json::parse_error& error) {
- LOG_ERROR(Service_BCAT, "{}", error.what());
- return StatusResult::ParseError;
- }
-}
-
-} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/backend/boxcat.h b/src/core/hle/service/bcat/backend/boxcat.h
deleted file mode 100644
index d65b42e58..000000000
--- a/src/core/hle/service/bcat/backend/boxcat.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2019 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <atomic>
-#include <map>
-#include <optional>
-#include "core/hle/service/bcat/backend/backend.h"
-
-namespace Service::AM::Applets {
-class AppletManager;
-}
-
-namespace Service::BCAT {
-
-struct EventStatus {
- std::optional<std::string> header;
- std::optional<std::string> footer;
- std::vector<std::string> events;
-};
-
-/// Boxcat is yuzu's custom backend implementation of Nintendo's BCAT service. It is free to use and
-/// doesn't require a switch or nintendo account. The content is controlled by the yuzu team.
-class Boxcat final : public Backend {
- friend void SynchronizeInternal(AM::Applets::AppletManager& applet_manager,
- DirectoryGetter dir_getter, TitleIDVersion title,
- ProgressServiceBackend& progress,
- std::optional<std::string> dir_name);
-
-public:
- explicit Boxcat(AM::Applets::AppletManager& applet_manager_, DirectoryGetter getter);
- ~Boxcat() override;
-
- bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override;
- bool SynchronizeDirectory(TitleIDVersion title, std::string name,
- ProgressServiceBackend& progress) override;
-
- bool Clear(u64 title_id) override;
-
- void SetPassphrase(u64 title_id, const Passphrase& passphrase) override;
-
- std::optional<std::vector<u8>> GetLaunchParameter(TitleIDVersion title) override;
-
- enum class StatusResult {
- Success,
- Offline,
- ParseError,
- BadClientVersion,
- };
-
- static StatusResult GetStatus(std::optional<std::string>& global,
- std::map<std::string, EventStatus>& games);
-
-private:
- std::atomic_bool is_syncing{false};
-
- class Client;
- std::unique_ptr<Client> client;
- AM::Applets::AppletManager& applet_manager;
-};
-
-} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp
index 72294eb2e..701f634f8 100644
--- a/src/core/hle/service/bcat/bcat_module.cpp
+++ b/src/core/hle/service/bcat/bcat_module.cpp
@@ -4,7 +4,6 @@
#include <cctype>
#include <mbedtls/md5.h>
-#include "backend/boxcat.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/settings.h"
@@ -578,12 +577,6 @@ void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId(
std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System& system,
DirectoryGetter getter) {
-#ifdef YUZU_ENABLE_BOXCAT
- if (Settings::values.bcat_backend.GetValue() == "boxcat") {
- return std::make_unique<Boxcat>(system.GetAppletManager(), std::move(getter));
- }
-#endif
-
return std::make_unique<NullBackend>(std::move(getter));
}
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 46da438ef..acf791de2 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -175,6 +175,10 @@ public:
{143, nullptr, "GetAudioControlInputState"},
{144, nullptr, "AcquireAudioConnectionStateChangedEvent"},
{145, nullptr, "GetConnectedAudioDevice"},
+ {146, nullptr, "CloseAudioControlInput"},
+ {147, nullptr, "RegisterAudioControlNotification"},
+ {148, nullptr, "SendAudioControlPassthroughCommand"},
+ {149, nullptr, "SendAudioControlSetAbsoluteVolumeCommand"},
{256, nullptr, "IsManufacturingMode"},
{257, nullptr, "EmulateBluetoothCrash"},
{258, nullptr, "GetBleChannelMap"},
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
index 2b5314691..33a976ddf 100644
--- a/src/core/hle/service/caps/caps_ss.cpp
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -15,6 +15,7 @@ CAPS_SS::CAPS_SS(Core::System& system_) : ServiceFramework{system_, "caps:ss"} {
{204, nullptr, "SaveEditedScreenShotEx0"},
{206, nullptr, "Unknown206"},
{208, nullptr, "SaveScreenShotOfMovieEx1"},
+ {1000, nullptr, "Unknown1000"},
};
// clang-format on
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index 110c7cb1c..f6184acc9 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -55,6 +55,8 @@ public:
{36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"},
{37, nullptr, "OwnTicket2"},
{38, nullptr, "OwnTicket3"},
+ {39, nullptr, "DeleteAllInactivePersonalizedTicket"},
+ {40, nullptr, "DeletePrepurchaseRecordByNintendoAccountId"},
{501, nullptr, "Unknown501"},
{502, nullptr, "Unknown502"},
{503, nullptr, "GetTitleKey"},
@@ -88,11 +90,15 @@ public:
{1503, nullptr, "Unknown1503"},
{1504, nullptr, "Unknown1504"},
{1505, nullptr, "Unknown1505"},
+ {1506, nullptr, "Unknown1506"},
{2000, nullptr, "Unknown2000"},
{2001, nullptr, "Unknown2001"},
+ {2002, nullptr, "Unknown2002"},
+ {2003, nullptr, "Unknown2003"},
{2100, nullptr, "Unknown2100"},
{2501, nullptr, "Unknown2501"},
{2502, nullptr, "Unknown2502"},
+ {2601, nullptr, "Unknown2601"},
{3001, nullptr, "Unknown3001"},
{3002, nullptr, "Unknown3002"},
};
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 4a9b13e45..f8f9e32f7 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -97,14 +97,24 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
std::string path(Common::FS::SanitizePath(path_));
- auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
- if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) {
- dir = backing;
- }
- auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path));
- if (new_dir == nullptr) {
- // TODO(DarkLordZach): Find a better error code for this
- return ResultUnknown;
+
+ // NOTE: This is inaccurate behavior. CreateDirectory is not recursive.
+ // CreateDirectory should return PathNotFound if the parent directory does not exist.
+ // This is here temporarily in order to have UMM "work" in the meantime.
+ // TODO (Morph): Remove this when a hardware test verifies the correct behavior.
+ const auto components = Common::FS::SplitPathComponents(path);
+ std::string relative_path;
+ for (const auto& component : components) {
+ // Skip empty path components
+ if (component.empty()) {
+ continue;
+ }
+ relative_path = Common::FS::SanitizePath(relative_path + '/' + component);
+ auto new_dir = backing->CreateSubdirectory(relative_path);
+ if (new_dir == nullptr) {
+ // TODO(DarkLordZach): Find a better error code for this
+ return ResultUnknown;
+ }
}
return ResultSuccess;
}
@@ -251,6 +261,18 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
return FileSys::ERROR_PATH_NOT_FOUND;
}
+ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
+ const std::string& path) const {
+ auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
+ if (dir == nullptr) {
+ return FileSys::ERROR_PATH_NOT_FOUND;
+ }
+ if (GetEntryType(path).Failed()) {
+ return FileSys::ERROR_PATH_NOT_FOUND;
+ }
+ return MakeResult(dir->GetFileTimeStamp(Common::FS::GetFilename(path)));
+}
+
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
FileSystemController::~FileSystemController() = default;
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index d387af3cb..b155e0811 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -240,6 +240,12 @@ public:
*/
ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
+ /**
+ * Get the timestamp of the specified path
+ * @return The timestamp of the specified path or error code
+ */
+ ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const;
+
private:
FileSys::VirtualDir backing;
};
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index db4d44c12..50c788dd6 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -326,7 +326,7 @@ public:
{11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"},
{12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"},
{13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"},
- {14, nullptr, "GetFileTimeStampRaw"},
+ {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"},
{15, nullptr, "QueryEntry"},
};
RegisterHandlers(functions);
@@ -501,6 +501,24 @@ public:
rb.Push(size.get_total_size());
}
+ void GetFileTimeStampRaw(Kernel::HLERequestContext& ctx) {
+ const auto file_buffer = ctx.ReadBuffer();
+ const std::string name = Common::StringFromBuffer(file_buffer);
+
+ LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name);
+
+ auto result = backend.GetFileTimeStampRaw(name);
+ if (result.Failed()) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result.Code());
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 10};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(*result);
+ }
+
private:
VfsDirectoryServiceWrapper backend;
SizeGetter size;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 4fcc6f93a..9ee146caf 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -507,6 +507,7 @@ private:
LarkNesRight = 18,
Lucia = 19,
Verification = 20,
+ Lagon = 21,
};
struct NPadEntry {
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index ef2becefd..8e9b40c0a 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -15,6 +15,20 @@
namespace Service::HID {
class Controller_Touchscreen final : public ControllerBase {
public:
+ enum class TouchScreenModeForNx : u8 {
+ UseSystemSetting,
+ Finger,
+ Heat2,
+ };
+
+ struct TouchScreenConfigurationForNx {
+ TouchScreenModeForNx mode;
+ INSERT_PADDING_BYTES_NOINIT(0x7);
+ INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
+ };
+ static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
+ "TouchScreenConfigurationForNx is an invalid size");
+
explicit Controller_Touchscreen(Core::System& system_);
~Controller_Touchscreen() override;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index b8b80570d..8c363142c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -106,7 +106,7 @@ void IAppletResource::DeactivateController(HidController controller) {
controllers[static_cast<size_t>(controller)]->DeactivateController();
}
-IAppletResource ::~IAppletResource() {
+IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
}
@@ -239,6 +239,12 @@ Hid::Hid(Core::System& system_)
{81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
{82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
+ {84, nullptr, "EnableSixAxisSensorUnalteredPassthrough"},
+ {85, nullptr, "IsSixAxisSensorUnalteredPassthroughEnabled"},
+ {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
+ {87, nullptr, "LoadSixAxisSensorCalibrationParameter"},
+ {88, nullptr, "GetSixAxisSensorIcInformation"},
+ {89, nullptr, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
{91, &Hid::ActivateGesture, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
@@ -331,7 +337,7 @@ Hid::Hid(Core::System& system_)
{529, nullptr, "SetDisallowedPalmaConnection"},
{1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"},
{1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
- {1002, nullptr, "SetTouchScreenConfiguration"},
+ {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
{1003, nullptr, "IsFirmwareUpdateNeededForNotification"},
{2000, nullptr, "ActivateDigitizer"},
};
@@ -1631,6 +1637,18 @@ void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) {
.GetNpadCommunicationMode());
}
+void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
+ touchscreen_mode.mode, applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} {
@@ -1644,6 +1662,9 @@ public:
{12, nullptr, "UnsetTouchScreenAutoPilotState"},
{13, nullptr, "GetTouchScreenConfiguration"},
{14, nullptr, "ProcessTouchScreenAutoTune"},
+ {15, nullptr, "ForceStopTouchScreenManagement"},
+ {16, nullptr, "ForceRestartTouchScreenManagement"},
+ {17, nullptr, "IsTouchScreenManaged"},
{20, nullptr, "DeactivateMouse"},
{21, nullptr, "SetMouseAutoPilotState"},
{22, nullptr, "UnsetMouseAutoPilotState"},
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 9c5c7f252..b1fe75e94 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -159,6 +159,7 @@ private:
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
+ void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx);
enum class VibrationDeviceType : u32 {
Unknown = 0,
diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp
index deb3abb28..8ec7d5266 100644
--- a/src/core/hle/service/ngct/ngct.cpp
+++ b/src/core/hle/service/ngct/ngct.cpp
@@ -15,7 +15,7 @@ public:
explicit IService(Core::System& system_) : ServiceFramework{system_, "ngct:u"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "Match"},
+ {0, &IService::Match, "Match"},
{1, &IService::Filter, "Filter"},
};
// clang-format on
@@ -24,6 +24,19 @@ public:
}
private:
+ void Match(Kernel::HLERequestContext& ctx) {
+ const auto buffer = ctx.ReadBuffer();
+ const auto text = Common::StringFromFixedZeroTerminatedBuffer(
+ reinterpret_cast<const char*>(buffer.data()), buffer.size());
+
+ LOG_WARNING(Service_NGCT, "(STUBBED) called, text={}", text);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ // Return false since we don't censor anything
+ rb.Push(false);
+ }
+
void Filter(Kernel::HLERequestContext& ctx) {
const auto buffer = ctx.ReadBuffer();
const auto text = Common::StringFromFixedZeroTerminatedBuffer(
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp
index e4c703da4..32533cd94 100644
--- a/src/core/hle/service/npns/npns.cpp
+++ b/src/core/hle/service/npns/npns.cpp
@@ -31,6 +31,7 @@ public:
{24, nullptr, "DestroyTokenWithApplicationId"},
{25, nullptr, "QueryIsTokenValid"},
{26, nullptr, "ListenToMyApplicationId"},
+ {27, nullptr, "DestroyTokenAll"},
{31, nullptr, "UploadTokenToBaaS"},
{32, nullptr, "DestroyTokenForBaaS"},
{33, nullptr, "CreateTokenForBaaS"},
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index ce6065db2..789000294 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices {
nvdisp_disp0::nvdisp_disp0(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_)
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)} {}
-nvdisp_disp0 ::~nvdisp_disp0() = default;
+nvdisp_disp0::~nvdisp_disp0() = default;
NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
std::vector<u8>& output) {
@@ -42,15 +42,14 @@ void nvdisp_disp0::OnClose(DeviceFD fd) {}
void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform,
const Common::Rectangle<int>& crop_rect) {
- VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
+ const VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
LOG_TRACE(Service,
"Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
addr, offset, width, height, stride, format);
- using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
- const Tegra::FramebufferConfig framebuffer{
- addr, offset, width, height, stride, static_cast<PixelFormat>(format),
- transform, crop_rect};
+ const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format);
+ const Tegra::FramebufferConfig framebuffer{addr, offset, width, height,
+ stride, pixel_format, transform, crop_rect};
system.GetPerfStats().EndSystemFrame();
system.GPU().SwapBuffers(&framebuffer);
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 59ddf6298..b4c3a6099 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -9,17 +9,20 @@
#include "core/core.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service::NVFlinger {
-BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_)
- : id(id_), layer_id(layer_id_), buffer_wait_event{kernel} {
- Kernel::KAutoObject::Create(std::addressof(buffer_wait_event));
- buffer_wait_event.Initialize("BufferQueue:WaitEvent");
+BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
+ KernelHelpers::ServiceContext& service_context_)
+ : id(id_), layer_id(layer_id_), service_context{service_context_} {
+ buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
}
-BufferQueue::~BufferQueue() = default;
+BufferQueue::~BufferQueue() {
+ service_context.CloseEvent(buffer_wait_event);
+}
void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
ASSERT(slot < buffer_slots);
@@ -41,7 +44,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
.multi_fence = {},
};
- buffer_wait_event.GetWritableEvent().Signal();
+ buffer_wait_event->GetWritableEvent().Signal();
}
std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +122,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
}
free_buffers_condition.notify_one();
- buffer_wait_event.GetWritableEvent().Signal();
+ buffer_wait_event->GetWritableEvent().Signal();
}
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +157,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
}
free_buffers_condition.notify_one();
- buffer_wait_event.GetWritableEvent().Signal();
+ buffer_wait_event->GetWritableEvent().Signal();
}
void BufferQueue::Connect() {
@@ -169,7 +172,7 @@ void BufferQueue::Disconnect() {
std::unique_lock lock{queue_sequence_mutex};
queue_sequence.clear();
}
- buffer_wait_event.GetWritableEvent().Signal();
+ buffer_wait_event->GetWritableEvent().Signal();
is_connect = false;
free_buffers_condition.notify_one();
}
@@ -189,11 +192,11 @@ u32 BufferQueue::Query(QueryType type) {
}
Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() {
- return buffer_wait_event.GetWritableEvent();
+ return buffer_wait_event->GetWritableEvent();
}
Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() {
- return buffer_wait_event.GetReadableEvent();
+ return buffer_wait_event->GetReadableEvent();
}
} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 61e337ac5..78de3f354 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -24,6 +24,10 @@ class KReadableEvent;
class KWritableEvent;
} // namespace Kernel
+namespace Service::KernelHelpers {
+class ServiceContext;
+} // namespace Service::KernelHelpers
+
namespace Service::NVFlinger {
constexpr u32 buffer_slots = 0x40;
@@ -38,7 +42,9 @@ struct IGBPBuffer {
u32_le index;
INSERT_PADDING_WORDS(3);
u32_le gpu_buffer_id;
- INSERT_PADDING_WORDS(17);
+ INSERT_PADDING_WORDS(6);
+ u32_le external_format;
+ INSERT_PADDING_WORDS(10);
u32_le nvmap_handle;
u32_le offset;
INSERT_PADDING_WORDS(60);
@@ -54,7 +60,8 @@ public:
NativeWindowFormat = 2,
};
- explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_);
+ explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
+ KernelHelpers::ServiceContext& service_context_);
~BufferQueue();
enum class BufferTransformFlags : u32 {
@@ -130,12 +137,14 @@ private:
std::list<u32> free_buffers;
std::array<Buffer, buffer_slots> buffers;
std::list<u32> queue_sequence;
- Kernel::KEvent buffer_wait_event;
+ Kernel::KEvent* buffer_wait_event{};
std::mutex free_buffers_mutex;
std::condition_variable free_buffers_condition;
std::mutex queue_sequence_mutex;
+
+ KernelHelpers::ServiceContext& service_context;
};
} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 32d4e360a..3ead813b0 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -147,7 +147,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
const u32 buffer_queue_id = next_buffer_queue_id++;
buffer_queues.emplace_back(
- std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id));
+ std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id, service_context));
display.CreateLayer(layer_id, *buffer_queues.back());
}
@@ -298,7 +298,7 @@ void NVFlinger::Compose() {
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
ASSERT(nvdisp);
- nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
+ nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.external_format,
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride,
buffer->get().transform, buffer->get().crop_rect);
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 7d85ecb6a..b9e765f1d 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -415,6 +415,18 @@ void BSD::Write(Kernel::HLERequestContext& ctx) {
});
}
+void BSD::Read(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const s32 fd = rp.Pop<s32>();
+
+ LOG_WARNING(Service, "(STUBBED) called. fd={} len={}", fd, ctx.GetWriteBufferSize());
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(ResultSuccess);
+ rb.Push<u32>(0); // ret
+ rb.Push<u32>(0); // bsd errno
+}
+
void BSD::Close(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -855,7 +867,7 @@ BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
{22, &BSD::Shutdown, "Shutdown"},
{23, nullptr, "ShutdownAllSockets"},
{24, &BSD::Write, "Write"},
- {25, nullptr, "Read"},
+ {25, &BSD::Read, "Read"},
{26, &BSD::Close, "Close"},
{27, nullptr, "DuplicateSocket"},
{28, nullptr, "GetResourceStatistics"},
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 1d2df9c61..d68beef5c 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -135,6 +135,7 @@ private:
void Send(Kernel::HLERequestContext& ctx);
void SendTo(Kernel::HLERequestContext& ctx);
void Write(Kernel::HLERequestContext& ctx);
+ void Read(Kernel::HLERequestContext& ctx);
void Close(Kernel::HLERequestContext& ctx);
void EventFd(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp
index bd334bbef..5c2354cdd 100644
--- a/src/core/hle/service/time/system_clock_core.cpp
+++ b/src/core/hle/service/time/system_clock_core.cpp
@@ -13,7 +13,7 @@ SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_)
context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
}
-SystemClockCore ::~SystemClockCore() = default;
+SystemClockCore::~SystemClockCore() = default;
ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
posix_time = 0;
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index 5c3108768..3871e7316 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -10,8 +10,8 @@
namespace Service::Time {
-ITimeZoneService ::ITimeZoneService(Core::System& system_,
- TimeZone::TimeZoneContentManager& time_zone_manager_)
+ITimeZoneService::ITimeZoneService(Core::System& system_,
+ TimeZone::TimeZoneContentManager& time_zone_manager_)
: ServiceFramework{system_, "ITimeZoneService"}, time_zone_content_manager{time_zone_manager_} {
static const FunctionInfo functions[] = {
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
index 7f436c3bb..2ee103b37 100644
--- a/src/core/hle/service/usb/usb.cpp
+++ b/src/core/hle/service/usb/usb.cpp
@@ -97,7 +97,7 @@ public:
{3, nullptr, "GetAlternateInterface"},
{4, nullptr, "GetCurrentFrame"},
{5, nullptr, "CtrlXferAsync"},
- {6, nullptr, "Unknown6"},
+ {6, nullptr, "GetCtrlXferCompletionEvent"},
{7, nullptr, "GetCtrlXferReport"},
{8, nullptr, "ResetDevice"},
{9, nullptr, "OpenUsbEp"},
@@ -183,8 +183,8 @@ public:
{4, nullptr, "GetHostPdcFirmwareRevision"},
{5, nullptr, "GetHostPdcManufactureId"},
{6, nullptr, "GetHostPdcDeviceId"},
- {7, nullptr, "AwakeCradle"},
- {8, nullptr, "SleepCradle"},
+ {7, nullptr, "EnableCradleRecovery"},
+ {8, nullptr, "DisableCradleRecovery"},
};
// clang-format on
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 8e8fc40ca..be3d52d54 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -831,6 +831,7 @@ public:
{6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
{6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
{6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
+ {6013, nullptr, "SetLayerOpacity"},
{7000, nullptr, "SetContentVisibility"},
{8000, nullptr, "SetConductorLayer"},
{8001, nullptr, "SetTimestampTracking"},