summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp15
-rw-r--r--src/core/file_sys/kernel_executable.h1
-rw-r--r--src/core/file_sys/vfs.cpp4
-rw-r--r--src/core/file_sys/vfs.h3
-rw-r--r--src/core/file_sys/vfs_real.cpp29
-rw-r--r--src/core/file_sys/vfs_real.h1
-rw-r--r--src/core/file_sys/vfs_types.h9
-rw-r--r--src/core/hle/api_version.h17
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/service/acc/acc.cpp66
-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/am/am.cpp16
-rw-r--r--src/core/hle/service/am/am.h2
-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/touchscreen.h14
-rw-r--r--src/core/hle/service/hid/hid.cpp14
-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/nvdrv/devices/nvdisp_disp0.cpp9
-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/network/network.cpp5
-rw-r--r--src/core/telemetry_session.cpp16
28 files changed, 388 insertions, 65 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 87d47e2e5..7140d0db8 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -263,6 +263,8 @@ add_library(core STATIC
hle/service/acc/acc_u0.h
hle/service/acc/acc_u1.cpp
hle/service/acc/acc_u1.h
+ hle/service/acc/async_context.cpp
+ hle/service/acc/async_context.h
hle/service/acc/errors.h
hle/service/acc/profile_manager.cpp
hle/service/acc/profile_manager.h
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ba4629993..b13350f6e 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -83,6 +83,12 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
}
}
+void KProcessDeleter(Kernel::KProcess* process) {
+ process->Destroy();
+}
+
+using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
+
} // Anonymous namespace
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
@@ -233,8 +239,8 @@ struct System::Impl {
}
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
- auto main_process = Kernel::KProcess::Create(system.Kernel());
- ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
+ main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
+ ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
Kernel::KProcess::ProcessType::Userland)
.IsSuccess());
main_process->Open();
@@ -247,7 +253,7 @@ struct System::Impl {
static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
- kernel.MakeCurrentProcess(main_process);
+ kernel.MakeCurrentProcess(main_process.get());
kernel.InitializeCores();
// Initialize cheat engine
@@ -316,6 +322,8 @@ struct System::Impl {
kernel.Shutdown();
memory.Reset();
applet_manager.ClearAll();
+ // TODO: The main process should be freed based on KAutoObject ref counting.
+ main_process.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -374,6 +382,7 @@ struct System::Impl {
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
std::unique_ptr<Core::DeviceMemory> device_memory;
+ KProcessPtr main_process{nullptr, KProcessDeleter};
Core::Memory::Memory memory;
CpuManager cpu_manager;
std::atomic_bool is_powered_on{};
diff --git a/src/core/file_sys/kernel_executable.h b/src/core/file_sys/kernel_executable.h
index 044c554d3..79ca82f8b 100644
--- a/src/core/file_sys/kernel_executable.h
+++ b/src/core/file_sys/kernel_executable.h
@@ -5,6 +5,7 @@
#pragma once
#include <array>
+#include <string>
#include <vector>
#include "common/common_funcs.h"
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 368419eca..f5ad10b15 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -273,6 +273,10 @@ VirtualFile VfsDirectory::GetFile(std::string_view name) const {
return iter == files.end() ? nullptr : *iter;
}
+FileTimeStampRaw VfsDirectory::GetFileTimeStamp([[maybe_unused]] std::string_view path) const {
+ return {};
+}
+
VirtualDir VfsDirectory::GetSubdirectory(std::string_view name) const {
const auto& subs = GetSubdirectories();
const auto iter = std::find_if(subs.begin(), subs.end(),
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index afd64e95c..ff6935da6 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -199,6 +199,9 @@ public:
// file with name.
virtual VirtualFile GetFile(std::string_view name) const;
+ // Returns a struct containing the file's timestamp.
+ virtual FileTimeStampRaw GetFileTimeStamp(std::string_view path) const;
+
// Returns a vector containing all of the subdirectories in this directory.
virtual std::vector<VirtualDir> GetSubdirectories() const = 0;
// Returns the directory with name matching name. Returns nullptr if directory dosen't have a
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 3dad54f49..f4073b76a 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -13,6 +13,13 @@
#include "common/logging/log.h"
#include "core/file_sys/vfs_real.h"
+// For FileTimeStampRaw
+#include <sys/stat.h>
+
+#ifdef _MSC_VER
+#define stat _stat64
+#endif
+
namespace FileSys {
namespace FS = Common::FS;
@@ -392,6 +399,28 @@ std::vector<VirtualFile> RealVfsDirectory::GetFiles() const {
return IterateEntries<RealVfsFile, VfsFile>();
}
+FileTimeStampRaw RealVfsDirectory::GetFileTimeStamp(std::string_view path_) const {
+ const auto full_path = FS::SanitizePath(path + '/' + std::string(path_));
+ const auto fs_path = std::filesystem::path{FS::ToU8String(full_path)};
+ struct stat file_status;
+
+#ifdef _WIN32
+ const auto stat_result = _wstat64(fs_path.c_str(), &file_status);
+#else
+ const auto stat_result = stat(fs_path.c_str(), &file_status);
+#endif
+
+ if (stat_result != 0) {
+ return {};
+ }
+
+ return {
+ .created{static_cast<u64>(file_status.st_ctime)},
+ .accessed{static_cast<u64>(file_status.st_atime)},
+ .modified{static_cast<u64>(file_status.st_mtime)},
+ };
+}
+
std::vector<VirtualDir> RealVfsDirectory::GetSubdirectories() const {
return IterateEntries<RealVfsDirectory, VfsDirectory>();
}
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index e4d1bba79..746e624cb 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -86,6 +86,7 @@ public:
VirtualDir CreateDirectoryRelative(std::string_view relative_path) override;
bool DeleteSubdirectoryRecursive(std::string_view name) override;
std::vector<VirtualFile> GetFiles() const override;
+ FileTimeStampRaw GetFileTimeStamp(std::string_view path) const override;
std::vector<VirtualDir> GetSubdirectories() const override;
bool IsWritable() const override;
bool IsReadable() const override;
diff --git a/src/core/file_sys/vfs_types.h b/src/core/file_sys/vfs_types.h
index 6215ed7af..ed0724717 100644
--- a/src/core/file_sys/vfs_types.h
+++ b/src/core/file_sys/vfs_types.h
@@ -6,6 +6,8 @@
#include <memory>
+#include "common/common_types.h"
+
namespace FileSys {
class VfsDirectory;
@@ -18,4 +20,11 @@ using VirtualDir = std::shared_ptr<VfsDirectory>;
using VirtualFile = std::shared_ptr<VfsFile>;
using VirtualFilesystem = std::shared_ptr<VfsFilesystem>;
+struct FileTimeStampRaw {
+ u64 created{};
+ u64 accessed{};
+ u64 modified{};
+ u64 padding{};
+};
+
} // namespace FileSys
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/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..6d9ec0a8a 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};
};
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/am/am.cpp b/src/core/hle/service/am/am.cpp
index a538f82e3..c3ac73131 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1270,7 +1270,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 +1323,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 +1341,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 +1766,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/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/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..a1707a72a 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -331,7 +331,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 +1631,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"} {
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/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index ce6065db2..a33e47d0b 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -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/network/network.cpp b/src/core/network/network.cpp
index 4732d4485..72eea52f0 100644
--- a/src/core/network/network.cpp
+++ b/src/core/network/network.cpp
@@ -7,7 +7,8 @@
#include <limits>
#include <utility>
#include <vector>
-#include "common/common_funcs.h"
+
+#include "common/error.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -223,7 +224,7 @@ Errno GetAndLogLastError() {
if (err == Errno::AGAIN) {
return err;
}
- LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e));
+ LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e));
return err;
}
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index 5a8cfd301..1f1607998 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -72,6 +72,18 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) {
return "Unknown";
}
+static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) {
+ switch (backend) {
+ case Settings::NvdecEmulation::Off:
+ return "Off";
+ case Settings::NvdecEmulation::CPU:
+ return "CPU";
+ case Settings::NvdecEmulation::GPU:
+ return "GPU";
+ }
+ return "Unknown";
+}
+
u64 GetTelemetryId() {
u64 telemetry_id{};
const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id";
@@ -229,8 +241,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue()));
AddField(field_type, "Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation.GetValue());
- AddField(field_type, "Renderer_UseNvdecEmulation",
- Settings::values.use_nvdec_emulation.GetValue());
+ AddField(field_type, "Renderer_NvdecEmulation",
+ TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue()));
AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue());
AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue());
AddField(field_type, "Renderer_ShaderBackend",