diff options
Diffstat (limited to 'src/core')
30 files changed, 813 insertions, 487 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index db1c9fdef..e0f207f3e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -439,6 +439,8 @@ add_library(core STATIC | |||
| 439 | hle/service/nvdrv/devices/nvhost_gpu.h | 439 | hle/service/nvdrv/devices/nvhost_gpu.h |
| 440 | hle/service/nvdrv/devices/nvhost_nvdec.cpp | 440 | hle/service/nvdrv/devices/nvhost_nvdec.cpp |
| 441 | hle/service/nvdrv/devices/nvhost_nvdec.h | 441 | hle/service/nvdrv/devices/nvhost_nvdec.h |
| 442 | hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | ||
| 443 | hle/service/nvdrv/devices/nvhost_nvdec_common.h | ||
| 442 | hle/service/nvdrv/devices/nvhost_nvjpg.cpp | 444 | hle/service/nvdrv/devices/nvhost_nvjpg.cpp |
| 443 | hle/service/nvdrv/devices/nvhost_nvjpg.h | 445 | hle/service/nvdrv/devices/nvhost_nvjpg.h |
| 444 | hle/service/nvdrv/devices/nvhost_vic.cpp | 446 | hle/service/nvdrv/devices/nvhost_vic.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 81e8cc338..fde2ccc09 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include "core/hle/service/lm/manager.h" | 40 | #include "core/hle/service/lm/manager.h" |
| 41 | #include "core/hle/service/service.h" | 41 | #include "core/hle/service/service.h" |
| 42 | #include "core/hle/service/sm/sm.h" | 42 | #include "core/hle/service/sm/sm.h" |
| 43 | #include "core/hle/service/time/time_manager.h" | ||
| 43 | #include "core/loader/loader.h" | 44 | #include "core/loader/loader.h" |
| 44 | #include "core/memory.h" | 45 | #include "core/memory.h" |
| 45 | #include "core/memory/cheat_engine.h" | 46 | #include "core/memory/cheat_engine.h" |
| @@ -121,7 +122,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | |||
| 121 | struct System::Impl { | 122 | struct System::Impl { |
| 122 | explicit Impl(System& system) | 123 | explicit Impl(System& system) |
| 123 | : kernel{system}, fs_controller{system}, memory{system}, | 124 | : kernel{system}, fs_controller{system}, memory{system}, |
| 124 | cpu_manager{system}, reporter{system}, applet_manager{system} {} | 125 | cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} |
| 125 | 126 | ||
| 126 | ResultStatus Run() { | 127 | ResultStatus Run() { |
| 127 | status = ResultStatus::Success; | 128 | status = ResultStatus::Success; |
| @@ -189,6 +190,9 @@ struct System::Impl { | |||
| 189 | return ResultStatus::ErrorVideoCore; | 190 | return ResultStatus::ErrorVideoCore; |
| 190 | } | 191 | } |
| 191 | 192 | ||
| 193 | // Initialize time manager, which must happen after kernel is created | ||
| 194 | time_manager.Initialize(); | ||
| 195 | |||
| 192 | is_powered_on = true; | 196 | is_powered_on = true; |
| 193 | exit_lock = false; | 197 | exit_lock = false; |
| 194 | 198 | ||
| @@ -387,6 +391,7 @@ struct System::Impl { | |||
| 387 | /// Service State | 391 | /// Service State |
| 388 | Service::Glue::ARPManager arp_manager; | 392 | Service::Glue::ARPManager arp_manager; |
| 389 | Service::LM::Manager lm_manager{reporter}; | 393 | Service::LM::Manager lm_manager{reporter}; |
| 394 | Service::Time::TimeManager time_manager; | ||
| 390 | 395 | ||
| 391 | /// Service manager | 396 | /// Service manager |
| 392 | std::shared_ptr<Service::SM::ServiceManager> service_manager; | 397 | std::shared_ptr<Service::SM::ServiceManager> service_manager; |
| @@ -717,6 +722,14 @@ const Service::LM::Manager& System::GetLogManager() const { | |||
| 717 | return impl->lm_manager; | 722 | return impl->lm_manager; |
| 718 | } | 723 | } |
| 719 | 724 | ||
| 725 | Service::Time::TimeManager& System::GetTimeManager() { | ||
| 726 | return impl->time_manager; | ||
| 727 | } | ||
| 728 | |||
| 729 | const Service::Time::TimeManager& System::GetTimeManager() const { | ||
| 730 | return impl->time_manager; | ||
| 731 | } | ||
| 732 | |||
| 720 | void System::SetExitLock(bool locked) { | 733 | void System::SetExitLock(bool locked) { |
| 721 | impl->exit_lock = locked; | 734 | impl->exit_lock = locked; |
| 722 | } | 735 | } |
diff --git a/src/core/core.h b/src/core/core.h index 27efe30bb..6db896bae 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -69,6 +69,10 @@ namespace SM { | |||
| 69 | class ServiceManager; | 69 | class ServiceManager; |
| 70 | } // namespace SM | 70 | } // namespace SM |
| 71 | 71 | ||
| 72 | namespace Time { | ||
| 73 | class TimeManager; | ||
| 74 | } // namespace Time | ||
| 75 | |||
| 72 | } // namespace Service | 76 | } // namespace Service |
| 73 | 77 | ||
| 74 | namespace Tegra { | 78 | namespace Tegra { |
| @@ -361,6 +365,10 @@ public: | |||
| 361 | 365 | ||
| 362 | const Service::LM::Manager& GetLogManager() const; | 366 | const Service::LM::Manager& GetLogManager() const; |
| 363 | 367 | ||
| 368 | Service::Time::TimeManager& GetTimeManager(); | ||
| 369 | |||
| 370 | const Service::Time::TimeManager& GetTimeManager() const; | ||
| 371 | |||
| 364 | void SetExitLock(bool locked); | 372 | void SetExitLock(bool locked); |
| 365 | 373 | ||
| 366 | bool GetExitLock() const; | 374 | bool GetExitLock() const; |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 688b99eba..983210197 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -365,6 +365,8 @@ void CpuManager::RunThread(std::size_t core) { | |||
| 365 | data.enter_barrier.reset(); | 365 | data.enter_barrier.reset(); |
| 366 | data.exit_barrier.reset(); | 366 | data.exit_barrier.reset(); |
| 367 | data.initialized = false; | 367 | data.initialized = false; |
| 368 | |||
| 369 | MicroProfileOnThreadExit(); | ||
| 368 | } | 370 | } |
| 369 | 371 | ||
| 370 | } // namespace Core | 372 | } // namespace Core |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index c5d65f2d0..5582091f4 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -19,7 +19,7 @@ DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& se | |||
| 19 | DefaultControllerApplet::~DefaultControllerApplet() = default; | 19 | DefaultControllerApplet::~DefaultControllerApplet() = default; |
| 20 | 20 | ||
| 21 | void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, | 21 | void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, |
| 22 | ControllerParameters parameters) const { | 22 | const ControllerParameters& parameters) const { |
| 23 | LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); | 23 | LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); |
| 24 | 24 | ||
| 25 | auto& npad = | 25 | auto& npad = |
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h index 3e49cdbb9..dff71d8d9 100644 --- a/src/core/frontend/applets/controller.h +++ b/src/core/frontend/applets/controller.h | |||
| @@ -38,7 +38,7 @@ public: | |||
| 38 | virtual ~ControllerApplet(); | 38 | virtual ~ControllerApplet(); |
| 39 | 39 | ||
| 40 | virtual void ReconfigureControllers(std::function<void()> callback, | 40 | virtual void ReconfigureControllers(std::function<void()> callback, |
| 41 | ControllerParameters parameters) const = 0; | 41 | const ControllerParameters& parameters) const = 0; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | class DefaultControllerApplet final : public ControllerApplet { | 44 | class DefaultControllerApplet final : public ControllerApplet { |
| @@ -47,7 +47,7 @@ public: | |||
| 47 | ~DefaultControllerApplet() override; | 47 | ~DefaultControllerApplet() override; |
| 48 | 48 | ||
| 49 | void ReconfigureControllers(std::function<void()> callback, | 49 | void ReconfigureControllers(std::function<void()> callback, |
| 50 | ControllerParameters parameters) const override; | 50 | const ControllerParameters& parameters) const override; |
| 51 | 51 | ||
| 52 | private: | 52 | private: |
| 53 | Service::SM::ServiceManager& service_manager; | 53 | Service::SM::ServiceManager& service_manager; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b2b5b8adf..bb3e312a7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -86,8 +86,6 @@ struct KernelCore::Impl { | |||
| 86 | } | 86 | } |
| 87 | cores.clear(); | 87 | cores.clear(); |
| 88 | 88 | ||
| 89 | registered_core_threads.reset(); | ||
| 90 | |||
| 91 | process_list.clear(); | 89 | process_list.clear(); |
| 92 | current_process = nullptr; | 90 | current_process = nullptr; |
| 93 | 91 | ||
| @@ -199,9 +197,7 @@ struct KernelCore::Impl { | |||
| 199 | const auto it = std::find(register_host_thread_keys.begin(), end, this_id); | 197 | const auto it = std::find(register_host_thread_keys.begin(), end, this_id); |
| 200 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); | 198 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); |
| 201 | ASSERT(it == end); | 199 | ASSERT(it == end); |
| 202 | ASSERT(!registered_core_threads[core_id]); | ||
| 203 | InsertHostThread(static_cast<u32>(core_id)); | 200 | InsertHostThread(static_cast<u32>(core_id)); |
| 204 | registered_core_threads.set(core_id); | ||
| 205 | } | 201 | } |
| 206 | 202 | ||
| 207 | void RegisterHostThread() { | 203 | void RegisterHostThread() { |
| @@ -332,7 +328,6 @@ struct KernelCore::Impl { | |||
| 332 | 328 | ||
| 333 | // 0-3 IDs represent core threads, >3 represent others | 329 | // 0-3 IDs represent core threads, >3 represent others |
| 334 | std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | 330 | std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; |
| 335 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; | ||
| 336 | 331 | ||
| 337 | // Number of host threads is a relatively high number to avoid overflowing | 332 | // Number of host threads is a relatively high number to avoid overflowing |
| 338 | static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; | 333 | static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index ff9d9248b..b17529dee 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <bitset> | 6 | #include <bitset> |
| 7 | #include <ctime> | ||
| 7 | #include <memory> | 8 | #include <memory> |
| 8 | #include <random> | 9 | #include <random> |
| 9 | #include "common/alignment.h" | 10 | #include "common/alignment.h" |
| @@ -123,7 +124,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 123 | : kernel.CreateNewUserProcessID(); | 124 | : kernel.CreateNewUserProcessID(); |
| 124 | process->capabilities.InitializeForMetadatalessProcess(); | 125 | process->capabilities.InitializeForMetadatalessProcess(); |
| 125 | 126 | ||
| 126 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(0)); | 127 | std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))); |
| 127 | std::uniform_int_distribution<u64> distribution; | 128 | std::uniform_int_distribution<u64> distribution; |
| 128 | std::generate(process->random_entropy.begin(), process->random_entropy.end(), | 129 | std::generate(process->random_entropy.begin(), process->random_entropy.end(), |
| 129 | [&] { return distribution(rng); }); | 130 | [&] { return distribution(rng); }); |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d7a81f64a..2ce742e35 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1201,6 +1201,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1201 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, | 1201 | {151, nullptr, "TryPopFromNotificationStorageChannel"}, |
| 1202 | {160, nullptr, "GetHealthWarningDisappearedSystemEvent"}, | 1202 | {160, nullptr, "GetHealthWarningDisappearedSystemEvent"}, |
| 1203 | {170, nullptr, "SetHdcpAuthenticationActivated"}, | 1203 | {170, nullptr, "SetHdcpAuthenticationActivated"}, |
| 1204 | {180, nullptr, "GetLaunchRequiredVersion"}, | ||
| 1205 | {181, nullptr, "UpgradeLaunchRequiredVersion"}, | ||
| 1204 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, | 1206 | {500, nullptr, "StartContinuousRecordingFlushForDebug"}, |
| 1205 | {1000, nullptr, "CreateMovieMaker"}, | 1207 | {1000, nullptr, "CreateMovieMaker"}, |
| 1206 | {1001, nullptr, "PrepareForJit"}, | 1208 | {1001, nullptr, "PrepareForJit"}, |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 8918946a1..50f709b25 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -260,7 +260,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 260 | {404, nullptr, "HasLeftRightBattery"}, | 260 | {404, nullptr, "HasLeftRightBattery"}, |
| 261 | {405, nullptr, "GetNpadInterfaceType"}, | 261 | {405, nullptr, "GetNpadInterfaceType"}, |
| 262 | {406, nullptr, "GetNpadLeftRightInterfaceType"}, | 262 | {406, nullptr, "GetNpadLeftRightInterfaceType"}, |
| 263 | {407, nullptr, "GetNpadOfHighestBatteryLevelForJoyLeft"}, | 263 | {407, nullptr, "GetNpadOfHighestBatteryLevel"}, |
| 264 | {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"}, | 264 | {408, nullptr, "GetNpadOfHighestBatteryLevelForJoyRight"}, |
| 265 | {500, nullptr, "GetPalmaConnectionHandle"}, | 265 | {500, nullptr, "GetPalmaConnectionHandle"}, |
| 266 | {501, nullptr, "InitializePalma"}, | 266 | {501, nullptr, "InitializePalma"}, |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index b81bf6277..d7080b715 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -47,6 +47,7 @@ public: | |||
| 47 | {23, nullptr, "Convert"}, | 47 | {23, nullptr, "Convert"}, |
| 48 | {24, nullptr, "ConvertCoreDataToCharInfo"}, | 48 | {24, nullptr, "ConvertCoreDataToCharInfo"}, |
| 49 | {25, nullptr, "ConvertCharInfoToCoreData"}, | 49 | {25, nullptr, "ConvertCharInfoToCoreData"}, |
| 50 | {26, nullptr, "Append"}, | ||
| 50 | }; | 51 | }; |
| 51 | // clang-format on | 52 | // clang-format on |
| 52 | 53 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index fcb612864..b6df48360 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -2,15 +2,17 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | |||
| 7 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" | 8 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" |
| 9 | #include "video_core/memory_manager.h" | ||
| 10 | #include "video_core/renderer_base.h" | ||
| 10 | 11 | ||
| 11 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 12 | 13 | ||
| 13 | nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {} | 14 | nvhost_nvdec::nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) |
| 15 | : nvhost_nvdec_common(system, std::move(nvmap_dev)) {} | ||
| 14 | nvhost_nvdec::~nvhost_nvdec() = default; | 16 | nvhost_nvdec::~nvhost_nvdec() = default; |
| 15 | 17 | ||
| 16 | u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 18 | u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, |
| @@ -21,7 +23,7 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std:: | |||
| 21 | 23 | ||
| 22 | switch (static_cast<IoctlCommand>(command.raw)) { | 24 | switch (static_cast<IoctlCommand>(command.raw)) { |
| 23 | case IoctlCommand::IocSetNVMAPfdCommand: | 25 | case IoctlCommand::IocSetNVMAPfdCommand: |
| 24 | return SetNVMAPfd(input, output); | 26 | return SetNVMAPfd(input); |
| 25 | case IoctlCommand::IocSubmit: | 27 | case IoctlCommand::IocSubmit: |
| 26 | return Submit(input, output); | 28 | return Submit(input, output); |
| 27 | case IoctlCommand::IocGetSyncpoint: | 29 | case IoctlCommand::IocGetSyncpoint: |
| @@ -29,79 +31,29 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std:: | |||
| 29 | case IoctlCommand::IocGetWaitbase: | 31 | case IoctlCommand::IocGetWaitbase: |
| 30 | return GetWaitbase(input, output); | 32 | return GetWaitbase(input, output); |
| 31 | case IoctlCommand::IocMapBuffer: | 33 | case IoctlCommand::IocMapBuffer: |
| 32 | return MapBuffer(input, output); | 34 | case IoctlCommand::IocMapBuffer2: |
| 35 | case IoctlCommand::IocMapBuffer3: | ||
| 33 | case IoctlCommand::IocMapBufferEx: | 36 | case IoctlCommand::IocMapBufferEx: |
| 34 | return MapBufferEx(input, output); | 37 | return MapBuffer(input, output); |
| 35 | case IoctlCommand::IocUnmapBufferEx: | 38 | case IoctlCommand::IocUnmapBufferEx: { |
| 36 | return UnmapBufferEx(input, output); | 39 | // This command is sent when the video stream has ended, flush all video contexts |
| 40 | // This is usually sent in the folowing order: vic, nvdec, vic. | ||
| 41 | // Inform the GPU to clear any remaining nvdec buffers when this is detected. | ||
| 42 | LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); | ||
| 43 | Tegra::ChCommandHeaderList cmdlist(1); | ||
| 44 | cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; | ||
| 45 | system.GPU().PushCommandBuffer(cmdlist); | ||
| 46 | [[fallthrough]]; // fallthrough to unmap buffers | ||
| 47 | }; | ||
| 48 | case IoctlCommand::IocUnmapBuffer: | ||
| 49 | case IoctlCommand::IocUnmapBuffer2: | ||
| 50 | case IoctlCommand::IocUnmapBuffer3: | ||
| 51 | return UnmapBuffer(input, output); | ||
| 52 | case IoctlCommand::IocSetSubmitTimeout: | ||
| 53 | return SetSubmitTimeout(input, output); | ||
| 37 | } | 54 | } |
| 38 | 55 | ||
| 39 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 56 | UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); |
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 44 | IoctlSetNvmapFD params{}; | ||
| 45 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | ||
| 46 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||
| 47 | |||
| 48 | nvmap_fd = params.nvmap_fd; | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | u32 nvhost_nvdec::Submit(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 53 | IoctlSubmit params{}; | ||
| 54 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | ||
| 55 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||
| 56 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | u32 nvhost_nvdec::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 61 | IoctlGetSyncpoint params{}; | ||
| 62 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | ||
| 63 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | ||
| 64 | params.value = 0; // Seems to be hard coded at 0 | ||
| 65 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | u32 nvhost_nvdec::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 70 | IoctlGetWaitbase params{}; | ||
| 71 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||
| 72 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | ||
| 73 | params.value = 0; // Seems to be hard coded at 0 | ||
| 74 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | u32 nvhost_nvdec::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 79 | IoctlMapBuffer params{}; | ||
| 80 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||
| 81 | LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2, | ||
| 82 | params.address_1); | ||
| 83 | params.address_1 = 0; | ||
| 84 | params.address_2 = 0; | ||
| 85 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | u32 nvhost_nvdec::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 90 | IoctlMapBufferEx params{}; | ||
| 91 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx)); | ||
| 92 | LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2, | ||
| 93 | params.address_1); | ||
| 94 | params.address_1 = 0; | ||
| 95 | params.address_2 = 0; | ||
| 96 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx)); | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | u32 nvhost_nvdec::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 101 | IoctlUnmapBufferEx params{}; | ||
| 102 | std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx)); | ||
| 103 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||
| 104 | std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx)); | ||
| 105 | return 0; | 57 | return 0; |
| 106 | } | 58 | } |
| 107 | 59 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 4332db118..102777ddd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | |||
| @@ -4,16 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | 7 | #include <memory> |
| 8 | #include "common/common_types.h" | 8 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h" |
| 9 | #include "common/swap.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 11 | 9 | ||
| 12 | namespace Service::Nvidia::Devices { | 10 | namespace Service::Nvidia::Devices { |
| 13 | 11 | ||
| 14 | class nvhost_nvdec final : public nvdevice { | 12 | class nvhost_nvdec final : public nvhost_nvdec_common { |
| 15 | public: | 13 | public: |
| 16 | explicit nvhost_nvdec(Core::System& system); | 14 | explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 17 | ~nvhost_nvdec() override; | 15 | ~nvhost_nvdec() override; |
| 18 | 16 | ||
| 19 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 17 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, |
| @@ -27,62 +25,15 @@ private: | |||
| 27 | IocGetSyncpoint = 0xC0080002, | 25 | IocGetSyncpoint = 0xC0080002, |
| 28 | IocGetWaitbase = 0xC0080003, | 26 | IocGetWaitbase = 0xC0080003, |
| 29 | IocMapBuffer = 0xC01C0009, | 27 | IocMapBuffer = 0xC01C0009, |
| 28 | IocMapBuffer2 = 0xC16C0009, | ||
| 29 | IocMapBuffer3 = 0xC15C0009, | ||
| 30 | IocMapBufferEx = 0xC0A40009, | 30 | IocMapBufferEx = 0xC0A40009, |
| 31 | IocUnmapBufferEx = 0xC0A4000A, | 31 | IocUnmapBuffer = 0xC0A4000A, |
| 32 | IocUnmapBuffer2 = 0xC16C000A, | ||
| 33 | IocUnmapBufferEx = 0xC01C000A, | ||
| 34 | IocUnmapBuffer3 = 0xC15C000A, | ||
| 35 | IocSetSubmitTimeout = 0x40040007, | ||
| 32 | }; | 36 | }; |
| 33 | |||
| 34 | struct IoctlSetNvmapFD { | ||
| 35 | u32_le nvmap_fd; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(IoctlSetNvmapFD) == 0x4, "IoctlSetNvmapFD is incorrect size"); | ||
| 38 | |||
| 39 | struct IoctlSubmit { | ||
| 40 | INSERT_PADDING_BYTES(0x40); // TODO(DarkLordZach): RE this structure | ||
| 41 | }; | ||
| 42 | static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit has incorrect size"); | ||
| 43 | |||
| 44 | struct IoctlGetSyncpoint { | ||
| 45 | u32 unknown; // seems to be ignored? Nintendo added this | ||
| 46 | u32 value; | ||
| 47 | }; | ||
| 48 | static_assert(sizeof(IoctlGetSyncpoint) == 0x08, "IoctlGetSyncpoint has incorrect size"); | ||
| 49 | |||
| 50 | struct IoctlGetWaitbase { | ||
| 51 | u32 unknown; // seems to be ignored? Nintendo added this | ||
| 52 | u32 value; | ||
| 53 | }; | ||
| 54 | static_assert(sizeof(IoctlGetWaitbase) == 0x08, "IoctlGetWaitbase has incorrect size"); | ||
| 55 | |||
| 56 | struct IoctlMapBuffer { | ||
| 57 | u32 unknown; | ||
| 58 | u32 address_1; | ||
| 59 | u32 address_2; | ||
| 60 | INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure | ||
| 61 | }; | ||
| 62 | static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size"); | ||
| 63 | |||
| 64 | struct IoctlMapBufferEx { | ||
| 65 | u32 unknown; | ||
| 66 | u32 address_1; | ||
| 67 | u32 address_2; | ||
| 68 | INSERT_PADDING_BYTES(0x98); // TODO(DarkLordZach): RE this structure | ||
| 69 | }; | ||
| 70 | static_assert(sizeof(IoctlMapBufferEx) == 0xA4, "IoctlMapBufferEx has incorrect size"); | ||
| 71 | |||
| 72 | struct IoctlUnmapBufferEx { | ||
| 73 | INSERT_PADDING_BYTES(0xA4); // TODO(DarkLordZach): RE this structure | ||
| 74 | }; | ||
| 75 | static_assert(sizeof(IoctlUnmapBufferEx) == 0xA4, "IoctlUnmapBufferEx has incorrect size"); | ||
| 76 | |||
| 77 | u32_le nvmap_fd{}; | ||
| 78 | |||
| 79 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 80 | u32 Submit(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 81 | u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 82 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 83 | u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 84 | u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 85 | u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 86 | }; | 37 | }; |
| 87 | 38 | ||
| 88 | } // namespace Service::Nvidia::Devices | 39 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp new file mode 100644 index 000000000..85792495f --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstring> | ||
| 7 | |||
| 8 | #include "common/assert.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "core/core.h" | ||
| 12 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h" | ||
| 13 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 14 | #include "core/memory.h" | ||
| 15 | #include "video_core/memory_manager.h" | ||
| 16 | #include "video_core/renderer_base.h" | ||
| 17 | |||
| 18 | namespace Service::Nvidia::Devices { | ||
| 19 | |||
| 20 | namespace { | ||
| 21 | // Splice vectors will copy count amount of type T from the input vector into the dst vector. | ||
| 22 | template <typename T> | ||
| 23 | std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, | ||
| 24 | std::size_t offset) { | ||
| 25 | std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); | ||
| 26 | offset += count * sizeof(T); | ||
| 27 | return offset; | ||
| 28 | } | ||
| 29 | |||
| 30 | // Write vectors will write data to the output buffer | ||
| 31 | template <typename T> | ||
| 32 | std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { | ||
| 33 | std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T)); | ||
| 34 | offset += src.size() * sizeof(T); | ||
| 35 | return offset; | ||
| 36 | } | ||
| 37 | } // Anonymous namespace | ||
| 38 | |||
| 39 | namespace NvErrCodes { | ||
| 40 | constexpr u32 Success{}; | ||
| 41 | constexpr u32 OutOfMemory{static_cast<u32>(-12)}; | ||
| 42 | constexpr u32 InvalidInput{static_cast<u32>(-22)}; | ||
| 43 | } // namespace NvErrCodes | ||
| 44 | |||
| 45 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | ||
| 46 | : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} | ||
| 47 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; | ||
| 48 | |||
| 49 | u32 nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { | ||
| 50 | IoctlSetNvmapFD params{}; | ||
| 51 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | ||
| 52 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||
| 53 | |||
| 54 | nvmap_fd = params.nvmap_fd; | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 59 | IoctlSubmit params{}; | ||
| 60 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | ||
| 61 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | ||
| 62 | |||
| 63 | // Instantiate param buffers | ||
| 64 | std::size_t offset = sizeof(IoctlSubmit); | ||
| 65 | std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count); | ||
| 66 | std::vector<Reloc> relocs(params.relocation_count); | ||
| 67 | std::vector<u32> reloc_shifts(params.relocation_count); | ||
| 68 | std::vector<SyncptIncr> syncpt_increments(params.syncpoint_count); | ||
| 69 | std::vector<SyncptIncr> wait_checks(params.syncpoint_count); | ||
| 70 | std::vector<Fence> fences(params.fence_count); | ||
| 71 | |||
| 72 | // Splice input into their respective buffers | ||
| 73 | offset = SpliceVectors(input, command_buffers, params.cmd_buffer_count, offset); | ||
| 74 | offset = SpliceVectors(input, relocs, params.relocation_count, offset); | ||
| 75 | offset = SpliceVectors(input, reloc_shifts, params.relocation_count, offset); | ||
| 76 | offset = SpliceVectors(input, syncpt_increments, params.syncpoint_count, offset); | ||
| 77 | offset = SpliceVectors(input, wait_checks, params.syncpoint_count, offset); | ||
| 78 | offset = SpliceVectors(input, fences, params.fence_count, offset); | ||
| 79 | |||
| 80 | // TODO(ameerj): For async gpu, utilize fences for syncpoint 'max' increment | ||
| 81 | |||
| 82 | auto& gpu = system.GPU(); | ||
| 83 | |||
| 84 | for (const auto& cmd_buffer : command_buffers) { | ||
| 85 | auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); | ||
| 86 | ASSERT_OR_EXECUTE(object, return NvErrCodes::InvalidInput;); | ||
| 87 | const auto map = FindBufferMap(object->dma_map_addr); | ||
| 88 | if (!map) { | ||
| 89 | LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}", | ||
| 90 | object->addr, object->dma_map_addr); | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); | ||
| 94 | gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), | ||
| 95 | cmdlist.size() * sizeof(u32)); | ||
| 96 | gpu.PushCommandBuffer(cmdlist); | ||
| 97 | } | ||
| 98 | |||
| 99 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||
| 100 | // Some games expect command_buffers to be written back | ||
| 101 | offset = sizeof(IoctlSubmit); | ||
| 102 | offset = WriteVectors(output, command_buffers, offset); | ||
| 103 | offset = WriteVectors(output, relocs, offset); | ||
| 104 | offset = WriteVectors(output, reloc_shifts, offset); | ||
| 105 | offset = WriteVectors(output, syncpt_increments, offset); | ||
| 106 | offset = WriteVectors(output, wait_checks, offset); | ||
| 107 | |||
| 108 | return NvErrCodes::Success; | ||
| 109 | } | ||
| 110 | |||
| 111 | u32 nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 112 | IoctlGetSyncpoint params{}; | ||
| 113 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | ||
| 114 | LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); | ||
| 115 | |||
| 116 | // We found that implementing this causes deadlocks with async gpu, along with degraded | ||
| 117 | // performance. TODO: RE the nvdec async implementation | ||
| 118 | params.value = 0; | ||
| 119 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | ||
| 120 | |||
| 121 | return NvErrCodes::Success; | ||
| 122 | } | ||
| 123 | |||
| 124 | u32 nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 125 | IoctlGetWaitbase params{}; | ||
| 126 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||
| 127 | params.value = 0; // Seems to be hard coded at 0 | ||
| 128 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 133 | IoctlMapBuffer params{}; | ||
| 134 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||
| 135 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | ||
| 136 | |||
| 137 | SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||
| 138 | |||
| 139 | auto& gpu = system.GPU(); | ||
| 140 | |||
| 141 | for (auto& cmf_buff : cmd_buffer_handles) { | ||
| 142 | auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; | ||
| 143 | if (!object) { | ||
| 144 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | ||
| 145 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 146 | return NvErrCodes::InvalidInput; | ||
| 147 | } | ||
| 148 | if (object->dma_map_addr == 0) { | ||
| 149 | // NVDEC and VIC memory is in the 32-bit address space | ||
| 150 | // MapAllocate32 will attempt to map a lower 32-bit value in the shared gpu memory space | ||
| 151 | const GPUVAddr low_addr = gpu.MemoryManager().MapAllocate32(object->addr, object->size); | ||
| 152 | object->dma_map_addr = static_cast<u32>(low_addr); | ||
| 153 | // Ensure that the dma_map_addr is indeed in the lower 32-bit address space. | ||
| 154 | ASSERT(object->dma_map_addr == low_addr); | ||
| 155 | } | ||
| 156 | if (!object->dma_map_addr) { | ||
| 157 | LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); | ||
| 158 | } else { | ||
| 159 | cmf_buff.map_address = object->dma_map_addr; | ||
| 160 | AddBufferMap(object->dma_map_addr, object->size, object->addr, | ||
| 161 | object->status == nvmap::Object::Status::Allocated); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||
| 165 | std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), | ||
| 166 | cmd_buffer_handles.size() * sizeof(MapBufferEntry)); | ||
| 167 | |||
| 168 | return NvErrCodes::Success; | ||
| 169 | } | ||
| 170 | |||
| 171 | u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 172 | IoctlMapBuffer params{}; | ||
| 173 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||
| 174 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | ||
| 175 | SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||
| 176 | |||
| 177 | auto& gpu = system.GPU(); | ||
| 178 | |||
| 179 | for (auto& cmf_buff : cmd_buffer_handles) { | ||
| 180 | const auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; | ||
| 181 | if (!object) { | ||
| 182 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | ||
| 183 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 184 | return NvErrCodes::InvalidInput; | ||
| 185 | } | ||
| 186 | if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { | ||
| 187 | gpu.MemoryManager().Unmap(object->dma_map_addr, *size); | ||
| 188 | } else { | ||
| 189 | // This occurs quite frequently, however does not seem to impact functionality | ||
| 190 | LOG_DEBUG(Service_NVDRV, "invalid offset=0x{:X} dma=0x{:X}", object->addr, | ||
| 191 | object->dma_map_addr); | ||
| 192 | } | ||
| 193 | object->dma_map_addr = 0; | ||
| 194 | } | ||
| 195 | std::memset(output.data(), 0, output.size()); | ||
| 196 | return NvErrCodes::Success; | ||
| 197 | } | ||
| 198 | |||
| 199 | u32 nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 200 | std::memcpy(&submit_timeout, input.data(), input.size()); | ||
| 201 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||
| 202 | return NvErrCodes::Success; | ||
| 203 | } | ||
| 204 | |||
| 205 | std::optional<nvhost_nvdec_common::BufferMap> nvhost_nvdec_common::FindBufferMap( | ||
| 206 | GPUVAddr gpu_addr) const { | ||
| 207 | const auto it = std::find_if( | ||
| 208 | buffer_mappings.begin(), buffer_mappings.upper_bound(gpu_addr), [&](const auto& entry) { | ||
| 209 | return (gpu_addr >= entry.second.StartAddr() && gpu_addr < entry.second.EndAddr()); | ||
| 210 | }); | ||
| 211 | |||
| 212 | ASSERT(it != buffer_mappings.end()); | ||
| 213 | return it->second; | ||
| 214 | } | ||
| 215 | |||
| 216 | void nvhost_nvdec_common::AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, | ||
| 217 | bool is_allocated) { | ||
| 218 | buffer_mappings.insert_or_assign(gpu_addr, BufferMap{gpu_addr, size, cpu_addr, is_allocated}); | ||
| 219 | } | ||
| 220 | |||
| 221 | std::optional<std::size_t> nvhost_nvdec_common::RemoveBufferMap(GPUVAddr gpu_addr) { | ||
| 222 | const auto iter{buffer_mappings.find(gpu_addr)}; | ||
| 223 | if (iter == buffer_mappings.end()) { | ||
| 224 | return std::nullopt; | ||
| 225 | } | ||
| 226 | std::size_t size = 0; | ||
| 227 | if (iter->second.IsAllocated()) { | ||
| 228 | size = iter->second.Size(); | ||
| 229 | } | ||
| 230 | buffer_mappings.erase(iter); | ||
| 231 | return size; | ||
| 232 | } | ||
| 233 | |||
| 234 | } // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h new file mode 100644 index 000000000..c249c5349 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/swap.h" | ||
| 11 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 12 | |||
| 13 | namespace Service::Nvidia::Devices { | ||
| 14 | class nvmap; | ||
| 15 | |||
| 16 | class nvhost_nvdec_common : public nvdevice { | ||
| 17 | public: | ||
| 18 | explicit nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); | ||
| 19 | ~nvhost_nvdec_common() override; | ||
| 20 | |||
| 21 | virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | ||
| 22 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | ||
| 23 | IoctlVersion version) = 0; | ||
| 24 | |||
| 25 | protected: | ||
| 26 | class BufferMap final { | ||
| 27 | public: | ||
| 28 | constexpr BufferMap() = default; | ||
| 29 | |||
| 30 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size) | ||
| 31 | : start_addr{start_addr}, end_addr{start_addr + size} {} | ||
| 32 | |||
| 33 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size, VAddr cpu_addr, | ||
| 34 | bool is_allocated) | ||
| 35 | : start_addr{start_addr}, end_addr{start_addr + size}, cpu_addr{cpu_addr}, | ||
| 36 | is_allocated{is_allocated} {} | ||
| 37 | |||
| 38 | constexpr VAddr StartAddr() const { | ||
| 39 | return start_addr; | ||
| 40 | } | ||
| 41 | |||
| 42 | constexpr VAddr EndAddr() const { | ||
| 43 | return end_addr; | ||
| 44 | } | ||
| 45 | |||
| 46 | constexpr std::size_t Size() const { | ||
| 47 | return end_addr - start_addr; | ||
| 48 | } | ||
| 49 | |||
| 50 | constexpr VAddr CpuAddr() const { | ||
| 51 | return cpu_addr; | ||
| 52 | } | ||
| 53 | |||
| 54 | constexpr bool IsAllocated() const { | ||
| 55 | return is_allocated; | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | GPUVAddr start_addr{}; | ||
| 60 | GPUVAddr end_addr{}; | ||
| 61 | VAddr cpu_addr{}; | ||
| 62 | bool is_allocated{}; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct IoctlSetNvmapFD { | ||
| 66 | u32_le nvmap_fd; | ||
| 67 | }; | ||
| 68 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | ||
| 69 | |||
| 70 | struct IoctlSubmitCommandBuffer { | ||
| 71 | u32_le id; | ||
| 72 | u32_le offset; | ||
| 73 | u32_le count; | ||
| 74 | }; | ||
| 75 | static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC, | ||
| 76 | "IoctlSubmitCommandBuffer is incorrect size"); | ||
| 77 | struct IoctlSubmit { | ||
| 78 | u32_le cmd_buffer_count; | ||
| 79 | u32_le relocation_count; | ||
| 80 | u32_le syncpoint_count; | ||
| 81 | u32_le fence_count; | ||
| 82 | }; | ||
| 83 | static_assert(sizeof(IoctlSubmit) == 0x10, "IoctlSubmit has incorrect size"); | ||
| 84 | |||
| 85 | struct CommandBuffer { | ||
| 86 | s32 memory_id; | ||
| 87 | u32 offset; | ||
| 88 | s32 word_count; | ||
| 89 | }; | ||
| 90 | static_assert(sizeof(CommandBuffer) == 0xC, "CommandBuffer has incorrect size"); | ||
| 91 | |||
| 92 | struct Reloc { | ||
| 93 | s32 cmdbuffer_memory; | ||
| 94 | s32 cmdbuffer_offset; | ||
| 95 | s32 target; | ||
| 96 | s32 target_offset; | ||
| 97 | }; | ||
| 98 | static_assert(sizeof(Reloc) == 0x10, "CommandBuffer has incorrect size"); | ||
| 99 | |||
| 100 | struct SyncptIncr { | ||
| 101 | u32 id; | ||
| 102 | u32 increments; | ||
| 103 | }; | ||
| 104 | static_assert(sizeof(SyncptIncr) == 0x8, "CommandBuffer has incorrect size"); | ||
| 105 | |||
| 106 | struct Fence { | ||
| 107 | u32 id; | ||
| 108 | u32 value; | ||
| 109 | }; | ||
| 110 | static_assert(sizeof(Fence) == 0x8, "CommandBuffer has incorrect size"); | ||
| 111 | |||
| 112 | struct IoctlGetSyncpoint { | ||
| 113 | // Input | ||
| 114 | u32_le param; | ||
| 115 | // Output | ||
| 116 | u32_le value; | ||
| 117 | }; | ||
| 118 | static_assert(sizeof(IoctlGetSyncpoint) == 8, "IocGetIdParams has wrong size"); | ||
| 119 | |||
| 120 | struct IoctlGetWaitbase { | ||
| 121 | u32_le unknown; // seems to be ignored? Nintendo added this | ||
| 122 | u32_le value; | ||
| 123 | }; | ||
| 124 | static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size"); | ||
| 125 | |||
| 126 | struct IoctlMapBuffer { | ||
| 127 | u32_le num_entries; | ||
| 128 | u32_le data_address; // Ignored by the driver. | ||
| 129 | u32_le attach_host_ch_das; | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | ||
| 132 | |||
| 133 | struct IocGetIdParams { | ||
| 134 | // Input | ||
| 135 | u32_le param; | ||
| 136 | // Output | ||
| 137 | u32_le value; | ||
| 138 | }; | ||
| 139 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | ||
| 140 | |||
| 141 | // Used for mapping and unmapping command buffers | ||
| 142 | struct MapBufferEntry { | ||
| 143 | u32_le map_handle; | ||
| 144 | u32_le map_address; | ||
| 145 | }; | ||
| 146 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | ||
| 147 | |||
| 148 | /// Ioctl command implementations | ||
| 149 | u32 SetNVMAPfd(const std::vector<u8>& input); | ||
| 150 | u32 Submit(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 151 | u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 152 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 153 | u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 154 | u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 155 | u32 SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 156 | |||
| 157 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; | ||
| 158 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); | ||
| 159 | std::optional<std::size_t> RemoveBufferMap(GPUVAddr gpu_addr); | ||
| 160 | |||
| 161 | u32_le nvmap_fd{}; | ||
| 162 | u32_le submit_timeout{}; | ||
| 163 | std::shared_ptr<nvmap> nvmap_dev; | ||
| 164 | |||
| 165 | // This is expected to be ordered, therefore we must use a map, not unordered_map | ||
| 166 | std::map<GPUVAddr, BufferMap> buffer_mappings; | ||
| 167 | }; | ||
| 168 | }; // namespace Service::Nvidia::Devices | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 9da19ad56..60db54d00 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -2,15 +2,17 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | |||
| 7 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" | 8 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" |
| 9 | #include "video_core/memory_manager.h" | ||
| 10 | #include "video_core/renderer_base.h" | ||
| 10 | 11 | ||
| 11 | namespace Service::Nvidia::Devices { | 12 | namespace Service::Nvidia::Devices { |
| 13 | nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) | ||
| 14 | : nvhost_nvdec_common(system, std::move(nvmap_dev)) {} | ||
| 12 | 15 | ||
| 13 | nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system) {} | ||
| 14 | nvhost_vic::~nvhost_vic() = default; | 16 | nvhost_vic::~nvhost_vic() = default; |
| 15 | 17 | ||
| 16 | u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 18 | u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, |
| @@ -21,7 +23,7 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve | |||
| 21 | 23 | ||
| 22 | switch (static_cast<IoctlCommand>(command.raw)) { | 24 | switch (static_cast<IoctlCommand>(command.raw)) { |
| 23 | case IoctlCommand::IocSetNVMAPfdCommand: | 25 | case IoctlCommand::IocSetNVMAPfdCommand: |
| 24 | return SetNVMAPfd(input, output); | 26 | return SetNVMAPfd(input); |
| 25 | case IoctlCommand::IocSubmit: | 27 | case IoctlCommand::IocSubmit: |
| 26 | return Submit(input, output); | 28 | return Submit(input, output); |
| 27 | case IoctlCommand::IocGetSyncpoint: | 29 | case IoctlCommand::IocGetSyncpoint: |
| @@ -29,83 +31,19 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve | |||
| 29 | case IoctlCommand::IocGetWaitbase: | 31 | case IoctlCommand::IocGetWaitbase: |
| 30 | return GetWaitbase(input, output); | 32 | return GetWaitbase(input, output); |
| 31 | case IoctlCommand::IocMapBuffer: | 33 | case IoctlCommand::IocMapBuffer: |
| 32 | return MapBuffer(input, output); | 34 | case IoctlCommand::IocMapBuffer2: |
| 35 | case IoctlCommand::IocMapBuffer3: | ||
| 36 | case IoctlCommand::IocMapBuffer4: | ||
| 33 | case IoctlCommand::IocMapBufferEx: | 37 | case IoctlCommand::IocMapBufferEx: |
| 34 | return MapBuffer(input, output); | 38 | return MapBuffer(input, output); |
| 39 | case IoctlCommand::IocUnmapBuffer: | ||
| 40 | case IoctlCommand::IocUnmapBuffer2: | ||
| 41 | case IoctlCommand::IocUnmapBuffer3: | ||
| 35 | case IoctlCommand::IocUnmapBufferEx: | 42 | case IoctlCommand::IocUnmapBufferEx: |
| 36 | return UnmapBufferEx(input, output); | 43 | return UnmapBuffer(input, output); |
| 37 | } | 44 | } |
| 38 | 45 | ||
| 39 | UNIMPLEMENTED_MSG("Unimplemented ioctl"); | 46 | UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); |
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 44 | IoctlSetNvmapFD params{}; | ||
| 45 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | ||
| 46 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||
| 47 | |||
| 48 | nvmap_fd = params.nvmap_fd; | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | u32 nvhost_vic::Submit(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 53 | IoctlSubmit params{}; | ||
| 54 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | ||
| 55 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||
| 56 | |||
| 57 | // Workaround for Luigi's Mansion 3, as nvhost_vic is not implemented for asynch GPU | ||
| 58 | params.command_buffer = {}; | ||
| 59 | |||
| 60 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | u32 nvhost_vic::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 65 | IoctlGetSyncpoint params{}; | ||
| 66 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | ||
| 67 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | ||
| 68 | params.value = 0; // Seems to be hard coded at 0 | ||
| 69 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | u32 nvhost_vic::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 74 | IoctlGetWaitbase params{}; | ||
| 75 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||
| 76 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | ||
| 77 | params.value = 0; // Seems to be hard coded at 0 | ||
| 78 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | u32 nvhost_vic::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 83 | IoctlMapBuffer params{}; | ||
| 84 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||
| 85 | LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2, | ||
| 86 | params.address_1); | ||
| 87 | params.address_1 = 0; | ||
| 88 | params.address_2 = 0; | ||
| 89 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | u32 nvhost_vic::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 94 | IoctlMapBufferEx params{}; | ||
| 95 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx)); | ||
| 96 | LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2, | ||
| 97 | params.address_1); | ||
| 98 | params.address_1 = 0; | ||
| 99 | params.address_2 = 0; | ||
| 100 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx)); | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | u32 nvhost_vic::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 105 | IoctlUnmapBufferEx params{}; | ||
| 106 | std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx)); | ||
| 107 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||
| 108 | std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx)); | ||
| 109 | return 0; | 47 | return 0; |
| 110 | } | 48 | } |
| 111 | 49 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index a7bb7bbd5..f975b190c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -4,19 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h" |
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/swap.h" | ||
| 11 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 12 | 8 | ||
| 13 | namespace Service::Nvidia::Devices { | 9 | namespace Service::Nvidia::Devices { |
| 10 | class nvmap; | ||
| 14 | 11 | ||
| 15 | class nvhost_vic final : public nvdevice { | 12 | class nvhost_vic final : public nvhost_nvdec_common { |
| 16 | public: | 13 | public: |
| 17 | explicit nvhost_vic(Core::System& system); | 14 | explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); |
| 18 | ~nvhost_vic() override; | 15 | ~nvhost_vic(); |
| 19 | |||
| 20 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, | 16 | u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, |
| 21 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, | 17 | std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, |
| 22 | IoctlVersion version) override; | 18 | IoctlVersion version) override; |
| @@ -28,74 +24,14 @@ private: | |||
| 28 | IocGetSyncpoint = 0xC0080002, | 24 | IocGetSyncpoint = 0xC0080002, |
| 29 | IocGetWaitbase = 0xC0080003, | 25 | IocGetWaitbase = 0xC0080003, |
| 30 | IocMapBuffer = 0xC01C0009, | 26 | IocMapBuffer = 0xC01C0009, |
| 27 | IocMapBuffer2 = 0xC0340009, | ||
| 28 | IocMapBuffer3 = 0xC0140009, | ||
| 29 | IocMapBuffer4 = 0xC00C0009, | ||
| 31 | IocMapBufferEx = 0xC03C0009, | 30 | IocMapBufferEx = 0xC03C0009, |
| 32 | IocUnmapBufferEx = 0xC03C000A, | 31 | IocUnmapBuffer = 0xC03C000A, |
| 33 | }; | 32 | IocUnmapBuffer2 = 0xC034000A, |
| 34 | 33 | IocUnmapBuffer3 = 0xC00C000A, | |
| 35 | struct IoctlSetNvmapFD { | 34 | IocUnmapBufferEx = 0xC01C000A, |
| 36 | u32_le nvmap_fd; | ||
| 37 | }; | ||
| 38 | static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); | ||
| 39 | |||
| 40 | struct IoctlSubmitCommandBuffer { | ||
| 41 | u32 id; | ||
| 42 | u32 offset; | ||
| 43 | u32 count; | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC, | ||
| 46 | "IoctlSubmitCommandBuffer is incorrect size"); | ||
| 47 | |||
| 48 | struct IoctlSubmit { | ||
| 49 | u32 command_buffer_count; | ||
| 50 | u32 relocations_count; | ||
| 51 | u32 syncpt_count; | ||
| 52 | u32 wait_count; | ||
| 53 | std::array<IoctlSubmitCommandBuffer, 4> command_buffer; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit is incorrect size"); | ||
| 56 | |||
| 57 | struct IoctlGetSyncpoint { | ||
| 58 | u32 unknown; // seems to be ignored? Nintendo added this | ||
| 59 | u32 value; | ||
| 60 | }; | ||
| 61 | static_assert(sizeof(IoctlGetSyncpoint) == 0x8, "IoctlGetSyncpoint is incorrect size"); | ||
| 62 | |||
| 63 | struct IoctlGetWaitbase { | ||
| 64 | u32 unknown; // seems to be ignored? Nintendo added this | ||
| 65 | u32 value; | ||
| 66 | }; | ||
| 67 | static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size"); | ||
| 68 | |||
| 69 | struct IoctlMapBuffer { | ||
| 70 | u32 unknown; | ||
| 71 | u32 address_1; | ||
| 72 | u32 address_2; | ||
| 73 | INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure | ||
| 74 | }; | ||
| 75 | static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size"); | ||
| 76 | |||
| 77 | struct IoctlMapBufferEx { | ||
| 78 | u32 unknown; | ||
| 79 | u32 address_1; | ||
| 80 | u32 address_2; | ||
| 81 | INSERT_PADDING_BYTES(0x30); // TODO(DarkLordZach): RE this structure | ||
| 82 | }; | 35 | }; |
| 83 | static_assert(sizeof(IoctlMapBufferEx) == 0x3C, "IoctlMapBufferEx is incorrect size"); | ||
| 84 | |||
| 85 | struct IoctlUnmapBufferEx { | ||
| 86 | INSERT_PADDING_BYTES(0x3C); // TODO(DarkLordZach): RE this structure | ||
| 87 | }; | ||
| 88 | static_assert(sizeof(IoctlUnmapBufferEx) == 0x3C, "IoctlUnmapBufferEx is incorrect size"); | ||
| 89 | |||
| 90 | u32_le nvmap_fd{}; | ||
| 91 | |||
| 92 | u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 93 | u32 Submit(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 94 | u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 95 | u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 96 | u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 97 | u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 98 | u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 99 | }; | 36 | }; |
| 100 | |||
| 101 | } // namespace Service::Nvidia::Devices | 37 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 84624be00..04b9ef540 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -37,6 +37,7 @@ public: | |||
| 37 | VAddr addr; | 37 | VAddr addr; |
| 38 | Status status; | 38 | Status status; |
| 39 | u32 refcount; | 39 | u32 refcount; |
| 40 | u32 dma_map_addr; | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | std::shared_ptr<Object> GetObject(u32 handle) const { | 43 | std::shared_ptr<Object> GetObject(u32 handle) const { |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 197c77db0..803c1a984 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -51,9 +51,9 @@ Module::Module(Core::System& system) { | |||
| 51 | devices["/dev/nvmap"] = nvmap_dev; | 51 | devices["/dev/nvmap"] = nvmap_dev; |
| 52 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev); | 52 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev); |
| 53 | devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>(system, events_interface); | 53 | devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>(system, events_interface); |
| 54 | devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>(system); | 54 | devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>(system, nvmap_dev); |
| 55 | devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system); | 55 | devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system); |
| 56 | devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>(system); | 56 | devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>(system, nvmap_dev); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | Module::~Module() = default; | 59 | Module::~Module() = default; |
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index e64777668..ffbf90b00 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -202,6 +202,7 @@ SET::SET() : ServiceFramework("set") { | |||
| 202 | {8, &SET::GetQuestFlag, "GetQuestFlag"}, | 202 | {8, &SET::GetQuestFlag, "GetQuestFlag"}, |
| 203 | {9, &SET::GetKeyCodeMap2, "GetKeyCodeMap2"}, | 203 | {9, &SET::GetKeyCodeMap2, "GetKeyCodeMap2"}, |
| 204 | {10, nullptr, "GetFirmwareVersionForDebug"}, | 204 | {10, nullptr, "GetFirmwareVersionForDebug"}, |
| 205 | {11, nullptr, "GetDeviceNickName"}, | ||
| 205 | }; | 206 | }; |
| 206 | // clang-format on | 207 | // clang-format on |
| 207 | 208 | ||
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 8bd4c7e79..080b5743e 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp | |||
| @@ -300,6 +300,8 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") { | |||
| 300 | {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, | 300 | {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, |
| 301 | {199, nullptr, "GetButtonConfigRegisteredSettings"}, | 301 | {199, nullptr, "GetButtonConfigRegisteredSettings"}, |
| 302 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, | 302 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, |
| 303 | {201, nullptr, "GetFieldTestingFlag"}, | ||
| 304 | {202, nullptr, "SetFieldTestingFlag"}, | ||
| 303 | }; | 305 | }; |
| 304 | // clang-format on | 306 | // clang-format on |
| 305 | 307 | ||
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index ee4fa4b48..7d0474e0b 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/kernel/client_port.h" | 11 | #include "core/hle/kernel/client_port.h" |
| 12 | #include "core/hle/kernel/client_session.h" | 12 | #include "core/hle/kernel/client_session.h" |
| 13 | #include "core/hle/kernel/kernel.h" | ||
| 13 | #include "core/hle/kernel/scheduler.h" | 14 | #include "core/hle/kernel/scheduler.h" |
| 14 | #include "core/hle/service/time/interface.h" | 15 | #include "core/hle/service/time/interface.h" |
| 15 | #include "core/hle/service/time/time.h" | 16 | #include "core/hle/service/time/time.h" |
| @@ -125,7 +126,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | |||
| 125 | Kernel::Thread* thread, Clock::SystemClockContext user_context, | 126 | Kernel::Thread* thread, Clock::SystemClockContext user_context, |
| 126 | Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { | 127 | Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { |
| 127 | 128 | ||
| 128 | auto& time_manager{module->GetTimeManager()}; | 129 | auto& time_manager{system.GetTimeManager()}; |
| 129 | 130 | ||
| 130 | clock_snapshot.is_automatic_correction_enabled = | 131 | clock_snapshot.is_automatic_correction_enabled = |
| 131 | time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); | 132 | time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); |
| @@ -182,7 +183,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct | |||
| 182 | LOG_DEBUG(Service_Time, "called"); | 183 | LOG_DEBUG(Service_Time, "called"); |
| 183 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 184 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 184 | rb.Push(RESULT_SUCCESS); | 185 | rb.Push(RESULT_SUCCESS); |
| 185 | rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore(), | 186 | rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardUserSystemClockCore(), |
| 186 | system); | 187 | system); |
| 187 | } | 188 | } |
| 188 | 189 | ||
| @@ -190,7 +191,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& | |||
| 190 | LOG_DEBUG(Service_Time, "called"); | 191 | LOG_DEBUG(Service_Time, "called"); |
| 191 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 192 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 192 | rb.Push(RESULT_SUCCESS); | 193 | rb.Push(RESULT_SUCCESS); |
| 193 | rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore(), | 194 | rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardNetworkSystemClockCore(), |
| 194 | system); | 195 | system); |
| 195 | } | 196 | } |
| 196 | 197 | ||
| @@ -198,29 +199,28 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | |||
| 198 | LOG_DEBUG(Service_Time, "called"); | 199 | LOG_DEBUG(Service_Time, "called"); |
| 199 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 200 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 200 | rb.Push(RESULT_SUCCESS); | 201 | rb.Push(RESULT_SUCCESS); |
| 201 | rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore(), | 202 | rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system); |
| 202 | system); | ||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | 205 | void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { |
| 206 | LOG_DEBUG(Service_Time, "called"); | 206 | LOG_DEBUG(Service_Time, "called"); |
| 207 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 207 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 208 | rb.Push(RESULT_SUCCESS); | 208 | rb.Push(RESULT_SUCCESS); |
| 209 | rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager()); | 209 | rb.PushIpcInterface<ITimeZoneService>(system.GetTimeManager().GetTimeZoneContentManager()); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { | 212 | void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { |
| 213 | LOG_DEBUG(Service_Time, "called"); | 213 | LOG_DEBUG(Service_Time, "called"); |
| 214 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 214 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 215 | rb.Push(RESULT_SUCCESS); | 215 | rb.Push(RESULT_SUCCESS); |
| 216 | rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore(), | 216 | rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardLocalSystemClockCore(), |
| 217 | system); | 217 | system); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( | 220 | void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( |
| 221 | Kernel::HLERequestContext& ctx) { | 221 | Kernel::HLERequestContext& ctx) { |
| 222 | LOG_DEBUG(Service_Time, "called"); | 222 | LOG_DEBUG(Service_Time, "called"); |
| 223 | auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()}; | 223 | auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()}; |
| 224 | IPC::ResponseBuilder rb{ctx, 3}; | 224 | IPC::ResponseBuilder rb{ctx, 3}; |
| 225 | rb.Push(RESULT_SUCCESS); | 225 | rb.Push(RESULT_SUCCESS); |
| 226 | rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system)); | 226 | rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system)); |
| @@ -229,7 +229,7 @@ void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( | |||
| 229 | void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) { | 229 | void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) { |
| 230 | LOG_DEBUG(Service_Time, "called"); | 230 | LOG_DEBUG(Service_Time, "called"); |
| 231 | 231 | ||
| 232 | auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()}; | 232 | auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()}; |
| 233 | if (!steady_clock_core.IsInitialized()) { | 233 | if (!steady_clock_core.IsInitialized()) { |
| 234 | IPC::ResponseBuilder rb{ctx, 2}; | 234 | IPC::ResponseBuilder rb{ctx, 2}; |
| 235 | rb.Push(ERROR_UNINITIALIZED_CLOCK); | 235 | rb.Push(ERROR_UNINITIALIZED_CLOCK); |
| @@ -262,8 +262,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | |||
| 262 | 262 | ||
| 263 | Clock::SystemClockContext user_context{}; | 263 | Clock::SystemClockContext user_context{}; |
| 264 | if (const ResultCode result{ | 264 | if (const ResultCode result{ |
| 265 | module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext( | 265 | system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system, |
| 266 | system, user_context)}; | 266 | user_context)}; |
| 267 | result.IsError()) { | 267 | result.IsError()) { |
| 268 | IPC::ResponseBuilder rb{ctx, 2}; | 268 | IPC::ResponseBuilder rb{ctx, 2}; |
| 269 | rb.Push(result); | 269 | rb.Push(result); |
| @@ -271,7 +271,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | |||
| 271 | } | 271 | } |
| 272 | Clock::SystemClockContext network_context{}; | 272 | Clock::SystemClockContext network_context{}; |
| 273 | if (const ResultCode result{ | 273 | if (const ResultCode result{ |
| 274 | module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( | 274 | system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( |
| 275 | system, network_context)}; | 275 | system, network_context)}; |
| 276 | result.IsError()) { | 276 | result.IsError()) { |
| 277 | IPC::ResponseBuilder rb{ctx, 2}; | 277 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -372,7 +372,7 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c | |||
| 372 | LOG_DEBUG(Service_Time, "called"); | 372 | LOG_DEBUG(Service_Time, "called"); |
| 373 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 373 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 374 | rb.Push(RESULT_SUCCESS); | 374 | rb.Push(RESULT_SUCCESS); |
| 375 | rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder()); | 375 | rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem())); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) | 378 | Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) |
| @@ -381,7 +381,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& syste | |||
| 381 | Module::Interface::~Interface() = default; | 381 | Module::Interface::~Interface() = default; |
| 382 | 382 | ||
| 383 | void InstallInterfaces(Core::System& system) { | 383 | void InstallInterfaces(Core::System& system) { |
| 384 | auto module{std::make_shared<Module>(system)}; | 384 | auto module{std::make_shared<Module>()}; |
| 385 | std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager()); | 385 | std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager()); |
| 386 | std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager()); | 386 | std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager()); |
| 387 | std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager()); | 387 | std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager()); |
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 41f3002e9..49f4aac0a 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h | |||
| @@ -16,7 +16,7 @@ namespace Service::Time { | |||
| 16 | 16 | ||
| 17 | class Module final { | 17 | class Module final { |
| 18 | public: | 18 | public: |
| 19 | Module(Core::System& system) : time_manager{system} {} | 19 | Module() = default; |
| 20 | 20 | ||
| 21 | class Interface : public ServiceFramework<Interface> { | 21 | class Interface : public ServiceFramework<Interface> { |
| 22 | public: | 22 | public: |
| @@ -46,13 +46,6 @@ public: | |||
| 46 | std::shared_ptr<Module> module; | 46 | std::shared_ptr<Module> module; |
| 47 | Core::System& system; | 47 | Core::System& system; |
| 48 | }; | 48 | }; |
| 49 | |||
| 50 | TimeManager& GetTimeManager() { | ||
| 51 | return time_manager; | ||
| 52 | } | ||
| 53 | |||
| 54 | private: | ||
| 55 | TimeManager time_manager; | ||
| 56 | }; | 49 | }; |
| 57 | 50 | ||
| 58 | /// Registers all Time services with the specified service manager. | 51 | /// Registers all Time services with the specified service manager. |
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp index b4dfe45e5..858623e2b 100644 --- a/src/core/hle/service/time/time_manager.cpp +++ b/src/core/hle/service/time/time_manager.cpp | |||
| @@ -22,125 +22,282 @@ static std::chrono::seconds GetSecondsSinceEpoch() { | |||
| 22 | Settings::values.custom_rtc_differential; | 22 | Settings::values.custom_rtc_differential; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | static s64 GetExternalTimeZoneOffset() { | ||
| 26 | // With "auto" timezone setting, we use the external system's timezone offset | ||
| 27 | if (Settings::GetTimeZoneString() == "auto") { | ||
| 28 | return Common::TimeZone::GetCurrentOffsetSeconds().count(); | ||
| 29 | } | ||
| 30 | return 0; | ||
| 31 | } | ||
| 32 | |||
| 33 | static s64 GetExternalRtcValue() { | 25 | static s64 GetExternalRtcValue() { |
| 34 | return GetSecondsSinceEpoch().count() + GetExternalTimeZoneOffset(); | 26 | return GetSecondsSinceEpoch().count() + TimeManager::GetExternalTimeZoneOffset(); |
| 35 | } | ||
| 36 | |||
| 37 | TimeManager::TimeManager(Core::System& system) | ||
| 38 | : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core}, | ||
| 39 | standard_network_system_clock_core{standard_steady_clock_core}, | ||
| 40 | standard_user_system_clock_core{standard_local_system_clock_core, | ||
| 41 | standard_network_system_clock_core, system}, | ||
| 42 | ephemeral_network_system_clock_core{tick_based_steady_clock_core}, | ||
| 43 | local_system_clock_context_writer{ | ||
| 44 | std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)}, | ||
| 45 | network_system_clock_context_writer{ | ||
| 46 | std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)}, | ||
| 47 | ephemeral_network_system_clock_context_writer{ | ||
| 48 | std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, | ||
| 49 | time_zone_content_manager{*this, system} { | ||
| 50 | |||
| 51 | const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; | ||
| 52 | SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); | ||
| 53 | SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); | ||
| 54 | SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); | ||
| 55 | SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); | ||
| 56 | SetupEphemeralNetworkSystemClock(); | ||
| 57 | } | 27 | } |
| 58 | 28 | ||
| 59 | TimeManager::~TimeManager() = default; | 29 | struct TimeManager::Impl final { |
| 30 | explicit Impl(Core::System& system) | ||
| 31 | : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core}, | ||
| 32 | standard_network_system_clock_core{standard_steady_clock_core}, | ||
| 33 | standard_user_system_clock_core{standard_local_system_clock_core, | ||
| 34 | standard_network_system_clock_core, system}, | ||
| 35 | ephemeral_network_system_clock_core{tick_based_steady_clock_core}, | ||
| 36 | local_system_clock_context_writer{ | ||
| 37 | std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)}, | ||
| 38 | network_system_clock_context_writer{ | ||
| 39 | std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)}, | ||
| 40 | ephemeral_network_system_clock_context_writer{ | ||
| 41 | std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, | ||
| 42 | time_zone_content_manager{system} { | ||
| 60 | 43 | ||
| 61 | void TimeManager::SetupTimeZoneManager(std::string location_name, | 44 | const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; |
| 62 | Clock::SteadyClockTimePoint time_zone_updated_time_point, | 45 | SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); |
| 63 | std::size_t total_location_name_count, | 46 | SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); |
| 64 | u128 time_zone_rule_version, | 47 | SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); |
| 65 | FileSys::VirtualFile& vfs_file) { | 48 | SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); |
| 66 | if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( | 49 | SetupEphemeralNetworkSystemClock(); |
| 67 | location_name, vfs_file) != RESULT_SUCCESS) { | 50 | } |
| 68 | UNREACHABLE(); | 51 | |
| 69 | return; | 52 | ~Impl() = default; |
| 70 | } | 53 | |
| 71 | 54 | Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() { | |
| 72 | time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); | 55 | return standard_steady_clock_core; |
| 73 | time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( | 56 | } |
| 74 | total_location_name_count); | 57 | |
| 75 | time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version); | 58 | const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const { |
| 76 | time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); | 59 | return standard_steady_clock_core; |
| 77 | } | 60 | } |
| 78 | 61 | ||
| 79 | void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | 62 | Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() { |
| 80 | Clock::TimeSpanType setup_value, | 63 | return standard_local_system_clock_core; |
| 81 | Clock::TimeSpanType internal_offset, | 64 | } |
| 82 | bool is_rtc_reset_detected) { | 65 | |
| 83 | standard_steady_clock_core.SetClockSourceId(clock_source_id); | 66 | const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const { |
| 84 | standard_steady_clock_core.SetSetupValue(setup_value); | 67 | return standard_local_system_clock_core; |
| 85 | standard_steady_clock_core.SetInternalOffset(internal_offset); | 68 | } |
| 86 | standard_steady_clock_core.MarkAsInitialized(); | 69 | |
| 87 | 70 | Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() { | |
| 88 | const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; | 71 | return standard_network_system_clock_core; |
| 89 | shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); | 72 | } |
| 90 | } | 73 | |
| 91 | 74 | const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const { | |
| 92 | void TimeManager::SetupStandardLocalSystemClock(Core::System& system, | 75 | return standard_network_system_clock_core; |
| 93 | Clock::SystemClockContext clock_context, | 76 | } |
| 94 | s64 posix_time) { | 77 | |
| 95 | standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer); | 78 | Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() { |
| 96 | 79 | return standard_user_system_clock_core; | |
| 97 | const auto current_time_point{ | 80 | } |
| 98 | standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; | 81 | |
| 99 | if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { | 82 | const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const { |
| 100 | standard_local_system_clock_core.SetSystemClockContext(clock_context); | 83 | return standard_user_system_clock_core; |
| 101 | } else { | 84 | } |
| 102 | if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) { | 85 | |
| 86 | TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() { | ||
| 87 | return time_zone_content_manager; | ||
| 88 | } | ||
| 89 | |||
| 90 | const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const { | ||
| 91 | return time_zone_content_manager; | ||
| 92 | } | ||
| 93 | |||
| 94 | SharedMemory& GetSharedMemory() { | ||
| 95 | return shared_memory; | ||
| 96 | } | ||
| 97 | |||
| 98 | const SharedMemory& GetSharedMemory() const { | ||
| 99 | return shared_memory; | ||
| 100 | } | ||
| 101 | |||
| 102 | void SetupTimeZoneManager(std::string location_name, | ||
| 103 | Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||
| 104 | std::size_t total_location_name_count, u128 time_zone_rule_version, | ||
| 105 | FileSys::VirtualFile& vfs_file) { | ||
| 106 | if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( | ||
| 107 | location_name, vfs_file) != RESULT_SUCCESS) { | ||
| 103 | UNREACHABLE(); | 108 | UNREACHABLE(); |
| 104 | return; | 109 | return; |
| 105 | } | 110 | } |
| 111 | |||
| 112 | time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); | ||
| 113 | time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( | ||
| 114 | total_location_name_count); | ||
| 115 | time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion( | ||
| 116 | time_zone_rule_version); | ||
| 117 | time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); | ||
| 106 | } | 118 | } |
| 107 | 119 | ||
| 108 | standard_local_system_clock_core.MarkAsInitialized(); | 120 | static s64 GetExternalTimeZoneOffset() { |
| 109 | } | 121 | // With "auto" timezone setting, we use the external system's timezone offset |
| 122 | if (Settings::GetTimeZoneString() == "auto") { | ||
| 123 | return Common::TimeZone::GetCurrentOffsetSeconds().count(); | ||
| 124 | } | ||
| 125 | return 0; | ||
| 126 | } | ||
| 110 | 127 | ||
| 111 | void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | 128 | void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, |
| 112 | Clock::TimeSpanType sufficient_accuracy) { | 129 | Clock::TimeSpanType setup_value, |
| 113 | standard_network_system_clock_core.SetUpdateCallbackInstance( | 130 | Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { |
| 114 | network_system_clock_context_writer); | 131 | standard_steady_clock_core.SetClockSourceId(clock_source_id); |
| 132 | standard_steady_clock_core.SetSetupValue(setup_value); | ||
| 133 | standard_steady_clock_core.SetInternalOffset(internal_offset); | ||
| 134 | standard_steady_clock_core.MarkAsInitialized(); | ||
| 115 | 135 | ||
| 116 | if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) { | 136 | const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; |
| 117 | UNREACHABLE(); | 137 | shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); |
| 118 | return; | ||
| 119 | } | 138 | } |
| 120 | 139 | ||
| 121 | standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy( | 140 | void SetupStandardLocalSystemClock(Core::System& system, |
| 122 | sufficient_accuracy); | 141 | Clock::SystemClockContext clock_context, s64 posix_time) { |
| 123 | standard_network_system_clock_core.MarkAsInitialized(); | 142 | standard_local_system_clock_core.SetUpdateCallbackInstance( |
| 124 | } | 143 | local_system_clock_context_writer); |
| 144 | |||
| 145 | const auto current_time_point{ | ||
| 146 | standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; | ||
| 147 | if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { | ||
| 148 | standard_local_system_clock_core.SetSystemClockContext(clock_context); | ||
| 149 | } else { | ||
| 150 | if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != | ||
| 151 | RESULT_SUCCESS) { | ||
| 152 | UNREACHABLE(); | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | standard_local_system_clock_core.MarkAsInitialized(); | ||
| 158 | } | ||
| 159 | |||
| 160 | void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | ||
| 161 | Clock::TimeSpanType sufficient_accuracy) { | ||
| 162 | standard_network_system_clock_core.SetUpdateCallbackInstance( | ||
| 163 | network_system_clock_context_writer); | ||
| 125 | 164 | ||
| 126 | void TimeManager::SetupStandardUserSystemClock( | 165 | if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != |
| 127 | Core::System& system, bool is_automatic_correction_enabled, | 166 | RESULT_SUCCESS) { |
| 128 | Clock::SteadyClockTimePoint steady_clock_time_point) { | 167 | UNREACHABLE(); |
| 129 | if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( | 168 | return; |
| 130 | system, is_automatic_correction_enabled) != RESULT_SUCCESS) { | 169 | } |
| 131 | UNREACHABLE(); | 170 | |
| 132 | return; | 171 | standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy( |
| 172 | sufficient_accuracy); | ||
| 173 | standard_network_system_clock_core.MarkAsInitialized(); | ||
| 133 | } | 174 | } |
| 134 | 175 | ||
| 135 | standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point); | 176 | void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled, |
| 136 | standard_user_system_clock_core.MarkAsInitialized(); | 177 | Clock::SteadyClockTimePoint steady_clock_time_point) { |
| 137 | shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled); | 178 | if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( |
| 179 | system, is_automatic_correction_enabled) != RESULT_SUCCESS) { | ||
| 180 | UNREACHABLE(); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point); | ||
| 185 | standard_user_system_clock_core.MarkAsInitialized(); | ||
| 186 | shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled); | ||
| 187 | } | ||
| 188 | |||
| 189 | void SetupEphemeralNetworkSystemClock() { | ||
| 190 | ephemeral_network_system_clock_core.SetUpdateCallbackInstance( | ||
| 191 | ephemeral_network_system_clock_context_writer); | ||
| 192 | ephemeral_network_system_clock_core.MarkAsInitialized(); | ||
| 193 | } | ||
| 194 | |||
| 195 | void UpdateLocalSystemClockTime(Core::System& system, s64 posix_time) { | ||
| 196 | const auto timespan{Service::Time::Clock::TimeSpanType::FromSeconds(posix_time)}; | ||
| 197 | if (GetStandardLocalSystemClockCore() | ||
| 198 | .SetCurrentTime(system, timespan.ToSeconds()) | ||
| 199 | .IsError()) { | ||
| 200 | UNREACHABLE(); | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | SharedMemory shared_memory; | ||
| 206 | |||
| 207 | Clock::StandardSteadyClockCore standard_steady_clock_core; | ||
| 208 | Clock::TickBasedSteadyClockCore tick_based_steady_clock_core; | ||
| 209 | Clock::StandardLocalSystemClockCore standard_local_system_clock_core; | ||
| 210 | Clock::StandardNetworkSystemClockCore standard_network_system_clock_core; | ||
| 211 | Clock::StandardUserSystemClockCore standard_user_system_clock_core; | ||
| 212 | Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core; | ||
| 213 | |||
| 214 | std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer; | ||
| 215 | std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer; | ||
| 216 | std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter> | ||
| 217 | ephemeral_network_system_clock_context_writer; | ||
| 218 | |||
| 219 | TimeZone::TimeZoneContentManager time_zone_content_manager; | ||
| 220 | }; | ||
| 221 | |||
| 222 | TimeManager::TimeManager(Core::System& system) : system{system} {} | ||
| 223 | |||
| 224 | TimeManager::~TimeManager() = default; | ||
| 225 | |||
| 226 | void TimeManager::Initialize() { | ||
| 227 | impl = std::make_unique<Impl>(system); | ||
| 228 | |||
| 229 | // Time zones can only be initialized after impl is valid | ||
| 230 | impl->time_zone_content_manager.Initialize(*this); | ||
| 231 | } | ||
| 232 | |||
| 233 | Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() { | ||
| 234 | return impl->standard_steady_clock_core; | ||
| 235 | } | ||
| 236 | |||
| 237 | const Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() const { | ||
| 238 | return impl->standard_steady_clock_core; | ||
| 239 | } | ||
| 240 | |||
| 241 | Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() { | ||
| 242 | return impl->standard_local_system_clock_core; | ||
| 243 | } | ||
| 244 | |||
| 245 | const Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() const { | ||
| 246 | return impl->standard_local_system_clock_core; | ||
| 247 | } | ||
| 248 | |||
| 249 | Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() { | ||
| 250 | return impl->standard_network_system_clock_core; | ||
| 138 | } | 251 | } |
| 139 | 252 | ||
| 140 | void TimeManager::SetupEphemeralNetworkSystemClock() { | 253 | const Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() |
| 141 | ephemeral_network_system_clock_core.SetUpdateCallbackInstance( | 254 | const { |
| 142 | ephemeral_network_system_clock_context_writer); | 255 | return impl->standard_network_system_clock_core; |
| 143 | ephemeral_network_system_clock_core.MarkAsInitialized(); | 256 | } |
| 257 | |||
| 258 | Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() { | ||
| 259 | return impl->standard_user_system_clock_core; | ||
| 260 | } | ||
| 261 | |||
| 262 | const Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() const { | ||
| 263 | return impl->standard_user_system_clock_core; | ||
| 264 | } | ||
| 265 | |||
| 266 | TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() { | ||
| 267 | return impl->time_zone_content_manager; | ||
| 268 | } | ||
| 269 | |||
| 270 | const TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() const { | ||
| 271 | return impl->time_zone_content_manager; | ||
| 272 | } | ||
| 273 | |||
| 274 | SharedMemory& TimeManager::GetSharedMemory() { | ||
| 275 | return impl->shared_memory; | ||
| 276 | } | ||
| 277 | |||
| 278 | const SharedMemory& TimeManager::GetSharedMemory() const { | ||
| 279 | return impl->shared_memory; | ||
| 280 | } | ||
| 281 | |||
| 282 | void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) { | ||
| 283 | impl->UpdateLocalSystemClockTime(system, posix_time); | ||
| 284 | } | ||
| 285 | |||
| 286 | void TimeManager::SetupTimeZoneManager(std::string location_name, | ||
| 287 | Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||
| 288 | std::size_t total_location_name_count, | ||
| 289 | u128 time_zone_rule_version, | ||
| 290 | FileSys::VirtualFile& vfs_file) { | ||
| 291 | impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, | ||
| 292 | total_location_name_count, time_zone_rule_version, vfs_file); | ||
| 293 | } | ||
| 294 | |||
| 295 | /*static*/ s64 TimeManager::GetExternalTimeZoneOffset() { | ||
| 296 | // With "auto" timezone setting, we use the external system's timezone offset | ||
| 297 | if (Settings::GetTimeZoneString() == "auto") { | ||
| 298 | return Common::TimeZone::GetCurrentOffsetSeconds().count(); | ||
| 299 | } | ||
| 300 | return 0; | ||
| 144 | } | 301 | } |
| 145 | 302 | ||
| 146 | } // namespace Service::Time | 303 | } // namespace Service::Time |
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h index 8e65f0d22..993c7c288 100644 --- a/src/core/hle/service/time/time_manager.h +++ b/src/core/hle/service/time/time_manager.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/time_zone.h" | ||
| 8 | #include "core/file_sys/vfs_types.h" | 9 | #include "core/file_sys/vfs_types.h" |
| 9 | #include "core/hle/service/time/clock_types.h" | 10 | #include "core/hle/service/time/clock_types.h" |
| 10 | #include "core/hle/service/time/ephemeral_network_system_clock_core.h" | 11 | #include "core/hle/service/time/ephemeral_network_system_clock_core.h" |
| @@ -32,86 +33,46 @@ public: | |||
| 32 | explicit TimeManager(Core::System& system); | 33 | explicit TimeManager(Core::System& system); |
| 33 | ~TimeManager(); | 34 | ~TimeManager(); |
| 34 | 35 | ||
| 35 | Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() { | 36 | void Initialize(); |
| 36 | return standard_steady_clock_core; | ||
| 37 | } | ||
| 38 | 37 | ||
| 39 | const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const { | 38 | Clock::StandardSteadyClockCore& GetStandardSteadyClockCore(); |
| 40 | return standard_steady_clock_core; | ||
| 41 | } | ||
| 42 | 39 | ||
| 43 | Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() { | 40 | const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const; |
| 44 | return standard_local_system_clock_core; | ||
| 45 | } | ||
| 46 | 41 | ||
| 47 | const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const { | 42 | Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore(); |
| 48 | return standard_local_system_clock_core; | ||
| 49 | } | ||
| 50 | 43 | ||
| 51 | Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() { | 44 | const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const; |
| 52 | return standard_network_system_clock_core; | ||
| 53 | } | ||
| 54 | 45 | ||
| 55 | const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const { | 46 | Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore(); |
| 56 | return standard_network_system_clock_core; | ||
| 57 | } | ||
| 58 | 47 | ||
| 59 | Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() { | 48 | const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const; |
| 60 | return standard_user_system_clock_core; | ||
| 61 | } | ||
| 62 | 49 | ||
| 63 | const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const { | 50 | Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore(); |
| 64 | return standard_user_system_clock_core; | ||
| 65 | } | ||
| 66 | 51 | ||
| 67 | TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() { | 52 | const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const; |
| 68 | return time_zone_content_manager; | ||
| 69 | } | ||
| 70 | 53 | ||
| 71 | const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const { | 54 | TimeZone::TimeZoneContentManager& GetTimeZoneContentManager(); |
| 72 | return time_zone_content_manager; | ||
| 73 | } | ||
| 74 | 55 | ||
| 75 | SharedMemory& GetSharedMemory() { | 56 | const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const; |
| 76 | return shared_memory; | ||
| 77 | } | ||
| 78 | 57 | ||
| 79 | const SharedMemory& GetSharedMemory() const { | 58 | void UpdateLocalSystemClockTime(s64 posix_time); |
| 80 | return shared_memory; | 59 | |
| 81 | } | 60 | SharedMemory& GetSharedMemory(); |
| 61 | |||
| 62 | const SharedMemory& GetSharedMemory() const; | ||
| 82 | 63 | ||
| 83 | void SetupTimeZoneManager(std::string location_name, | 64 | void SetupTimeZoneManager(std::string location_name, |
| 84 | Clock::SteadyClockTimePoint time_zone_updated_time_point, | 65 | Clock::SteadyClockTimePoint time_zone_updated_time_point, |
| 85 | std::size_t total_location_name_count, u128 time_zone_rule_version, | 66 | std::size_t total_location_name_count, u128 time_zone_rule_version, |
| 86 | FileSys::VirtualFile& vfs_file); | 67 | FileSys::VirtualFile& vfs_file); |
| 87 | 68 | ||
| 69 | static s64 GetExternalTimeZoneOffset(); | ||
| 70 | |||
| 88 | private: | 71 | private: |
| 89 | void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | 72 | Core::System& system; |
| 90 | Clock::TimeSpanType setup_value, | 73 | |
| 91 | Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected); | 74 | struct Impl; |
| 92 | void SetupStandardLocalSystemClock(Core::System& system, | 75 | std::unique_ptr<Impl> impl; |
| 93 | Clock::SystemClockContext clock_context, s64 posix_time); | ||
| 94 | void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | ||
| 95 | Clock::TimeSpanType sufficient_accuracy); | ||
| 96 | void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled, | ||
| 97 | Clock::SteadyClockTimePoint steady_clock_time_point); | ||
| 98 | void SetupEphemeralNetworkSystemClock(); | ||
| 99 | |||
| 100 | SharedMemory shared_memory; | ||
| 101 | |||
| 102 | Clock::StandardSteadyClockCore standard_steady_clock_core; | ||
| 103 | Clock::TickBasedSteadyClockCore tick_based_steady_clock_core; | ||
| 104 | Clock::StandardLocalSystemClockCore standard_local_system_clock_core; | ||
| 105 | Clock::StandardNetworkSystemClockCore standard_network_system_clock_core; | ||
| 106 | Clock::StandardUserSystemClockCore standard_user_system_clock_core; | ||
| 107 | Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core; | ||
| 108 | |||
| 109 | std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer; | ||
| 110 | std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer; | ||
| 111 | std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter> | ||
| 112 | ephemeral_network_system_clock_context_writer; | ||
| 113 | |||
| 114 | TimeZone::TimeZoneContentManager time_zone_content_manager; | ||
| 115 | }; | 76 | }; |
| 116 | 77 | ||
| 117 | } // namespace Service::Time | 78 | } // namespace Service::Time |
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index 320672add..4177d0a41 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -68,9 +68,10 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) { | |||
| 68 | return location_name_cache; | 68 | return location_name_cache; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system) | 71 | TimeZoneContentManager::TimeZoneContentManager(Core::System& system) |
| 72 | : system{system}, location_name_cache{BuildLocationNameCache(system)} { | 72 | : system{system}, location_name_cache{BuildLocationNameCache(system)} {} |
| 73 | 73 | ||
| 74 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { | ||
| 74 | std::string location_name; | 75 | std::string location_name; |
| 75 | const auto timezone_setting = Settings::GetTimeZoneString(); | 76 | const auto timezone_setting = Settings::GetTimeZoneString(); |
| 76 | if (timezone_setting == "auto" || timezone_setting == "default") { | 77 | if (timezone_setting == "auto" || timezone_setting == "default") { |
diff --git a/src/core/hle/service/time/time_zone_content_manager.h b/src/core/hle/service/time/time_zone_content_manager.h index 4f302c3b9..52dd1a020 100644 --- a/src/core/hle/service/time/time_zone_content_manager.h +++ b/src/core/hle/service/time/time_zone_content_manager.h | |||
| @@ -21,7 +21,9 @@ namespace Service::Time::TimeZone { | |||
| 21 | 21 | ||
| 22 | class TimeZoneContentManager final { | 22 | class TimeZoneContentManager final { |
| 23 | public: | 23 | public: |
| 24 | TimeZoneContentManager(TimeManager& time_manager, Core::System& system); | 24 | explicit TimeZoneContentManager(Core::System& system); |
| 25 | |||
| 26 | void Initialize(TimeManager& time_manager); | ||
| 25 | 27 | ||
| 26 | TimeZoneManager& GetTimeZoneManager() { | 28 | TimeZoneManager& GetTimeZoneManager() { |
| 27 | return time_zone_manager; | 29 | return time_zone_manager; |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 28d3f9099..e14c02045 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -63,6 +63,7 @@ void LogSettings() { | |||
| 63 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); | 63 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); |
| 64 | log_setting("Renderer_UseAsynchronousGpuEmulation", | 64 | log_setting("Renderer_UseAsynchronousGpuEmulation", |
| 65 | values.use_asynchronous_gpu_emulation.GetValue()); | 65 | values.use_asynchronous_gpu_emulation.GetValue()); |
| 66 | log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); | ||
| 66 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); | 67 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); |
| 67 | log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); | 68 | log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); |
| 68 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); | 69 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); |
| @@ -119,6 +120,7 @@ void RestoreGlobalState() { | |||
| 119 | values.use_disk_shader_cache.SetGlobal(true); | 120 | values.use_disk_shader_cache.SetGlobal(true); |
| 120 | values.gpu_accuracy.SetGlobal(true); | 121 | values.gpu_accuracy.SetGlobal(true); |
| 121 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | 122 | values.use_asynchronous_gpu_emulation.SetGlobal(true); |
| 123 | values.use_nvdec_emulation.SetGlobal(true); | ||
| 122 | values.use_vsync.SetGlobal(true); | 124 | values.use_vsync.SetGlobal(true); |
| 123 | values.use_assembly_shaders.SetGlobal(true); | 125 | values.use_assembly_shaders.SetGlobal(true); |
| 124 | values.use_asynchronous_shaders.SetGlobal(true); | 126 | values.use_asynchronous_shaders.SetGlobal(true); |
diff --git a/src/core/settings.h b/src/core/settings.h index 9834f44bb..604805615 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -111,6 +111,7 @@ struct Values { | |||
| 111 | Setting<bool> use_disk_shader_cache; | 111 | Setting<bool> use_disk_shader_cache; |
| 112 | Setting<GPUAccuracy> gpu_accuracy; | 112 | Setting<GPUAccuracy> gpu_accuracy; |
| 113 | Setting<bool> use_asynchronous_gpu_emulation; | 113 | Setting<bool> use_asynchronous_gpu_emulation; |
| 114 | Setting<bool> use_nvdec_emulation; | ||
| 114 | Setting<bool> use_vsync; | 115 | Setting<bool> use_vsync; |
| 115 | Setting<bool> use_assembly_shaders; | 116 | Setting<bool> use_assembly_shaders; |
| 116 | Setting<bool> use_asynchronous_shaders; | 117 | Setting<bool> use_asynchronous_shaders; |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index da09c0dbc..ebc19e18a 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -206,6 +206,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 206 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); | 206 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); |
| 207 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", | 207 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", |
| 208 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 208 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 209 | AddField(field_type, "Renderer_UseNvdecEmulation", | ||
| 210 | Settings::values.use_nvdec_emulation.GetValue()); | ||
| 209 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); | 211 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); |
| 210 | AddField(field_type, "Renderer_UseAssemblyShaders", | 212 | AddField(field_type, "Renderer_UseAssemblyShaders", |
| 211 | Settings::values.use_assembly_shaders.GetValue()); | 213 | Settings::values.use_assembly_shaders.GetValue()); |