diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 92fec9575b..e1cd8cc8b5 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -212,6 +212,11 @@ void ConfigCache::RestoreConfig(SConfig* config) static ConfigCache config_cache; +void SetEmulationSpeedReset(bool value) +{ + config_cache.bSetEmulationSpeed = value; +} + static GPUDeterminismMode ParseGPUDeterminismMode(const std::string& mode) { if (mode == "auto") diff --git a/Source/Core/Core/BootManager.h b/Source/Core/Core/BootManager.h index d9c66c370c..50b896849c 100644 --- a/Source/Core/Core/BootManager.h +++ b/Source/Core/Core/BootManager.h @@ -12,6 +12,7 @@ struct WindowSystemInfo; namespace BootManager { bool BootCore(std::unique_ptr parameters, const WindowSystemInfo& wsi); +void SetEmulationSpeedReset(bool value); // Synchronise Dolphin's configuration with the SYSCONF (which may have changed during emulation), // and restore settings that were overriden by per-game INIs or for some other reason. diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 1034351992..2b7c141e68 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -320,6 +320,8 @@ add_library(core IOS/Device.h IOS/DeviceStub.cpp IOS/DeviceStub.h + IOS/DolphinDevice.cpp + IOS/DolphinDevice.h IOS/IOS.cpp IOS/IOS.h IOS/IOSC.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 20e23993b0..65007c2bac 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -197,6 +197,7 @@ + @@ -473,6 +474,7 @@ + @@ -629,4 +631,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 06bc1fa6b2..c85b54aedd 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -707,6 +707,9 @@ IOS + + IOS + IOS\DI @@ -1435,6 +1438,9 @@ IOS + + IOS + IOS\DI @@ -1668,4 +1674,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Core/IOS/DolphinDevice.cpp b/Source/Core/Core/IOS/DolphinDevice.cpp new file mode 100644 index 0000000000..c215d7f804 --- /dev/null +++ b/Source/Core/Core/IOS/DolphinDevice.cpp @@ -0,0 +1,151 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/Logging/Log.h" +#include "Common/Timer.h" +#include "Common/scmrev.h" +#include "Core/BootManager.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/Memmap.h" +#include "Core/IOS/DolphinDevice.h" + +namespace IOS::HLE::Device +{ +namespace +{ +enum +{ + IOCTL_DOLPHIN_GET_SYSTEM_TIME = 0x01, + IOCTL_DOLPHIN_GET_VERSION = 0x02, + IOCTL_DOLPHIN_GET_SPEED_LIMIT = 0x03, + IOCTL_DOLPHIN_SET_SPEED_LIMIT = 0x04, + IOCTL_DOLPHIN_GET_CPU_SPEED = 0x05, + +}; + +IPCCommandResult GetSystemTime(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(0, 1)) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + if (request.io_vectors[0].size != 4) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + const u32 milliseconds = Common::Timer::GetTimeMs(); + + Memory::Write_U32(milliseconds, request.io_vectors[0].address); + return DolphinDevice::GetDefaultReply(IPC_SUCCESS); +} + +IPCCommandResult GetVersion(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(0, 1)) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + const auto length = std::min(size_t(request.io_vectors[0].size), std::strlen(SCM_DESC_STR)); + + Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size); + Memory::CopyToEmu(request.io_vectors[0].address, SCM_DESC_STR, length); + + return DolphinDevice::GetDefaultReply(IPC_SUCCESS); +} + +IPCCommandResult GetCPUSpeed(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(0, 1)) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + if (request.io_vectors[0].size != 4) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + const SConfig& config = SConfig::GetInstance(); + const float oc = config.m_OCEnable ? config.m_OCFactor : 1.0f; + + const u32 core_clock = u32(float(SystemTimers::GetTicksPerSecond()) * oc); + + Memory::Write_U32(core_clock, request.io_vectors[0].address); + + return DolphinDevice::GetDefaultReply(IPC_SUCCESS); +} + +IPCCommandResult GetSpeedLimit(const IOCtlVRequest& request) +{ + // get current speed limit + if (!request.HasNumberOfValidVectors(0, 1)) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + if (request.io_vectors[0].size != 4) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + const SConfig& config = SConfig::GetInstance(); + const u32 speed_percent = config.m_EmulationSpeed * 100; + Memory::Write_U32(speed_percent, request.io_vectors[0].address); + + return DolphinDevice::GetDefaultReply(IPC_SUCCESS); +} + +IPCCommandResult SetSpeedLimit(const IOCtlVRequest& request) +{ + // set current speed limit + if (!request.HasNumberOfValidVectors(1, 0)) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + if (request.in_vectors[0].size != 4) + { + return DolphinDevice::GetDefaultReply(IPC_EINVAL); + } + + const float speed = float(Memory::Read_U32(request.in_vectors[0].address)) / 100.0f; + SConfig::GetInstance().m_EmulationSpeed = speed; + BootManager::SetEmulationSpeedReset(true); + + return DolphinDevice::GetDefaultReply(IPC_SUCCESS); +} + +} // namespace + +IPCCommandResult DolphinDevice::IOCtlV(const IOCtlVRequest& request) +{ + if (Core::WantsDeterminism()) + { + return DolphinDevice::GetDefaultReply(IPC_EACCES); + } + + switch (request.request) + { + case IOCTL_DOLPHIN_GET_SYSTEM_TIME: + return GetSystemTime(request); + case IOCTL_DOLPHIN_GET_VERSION: + return GetVersion(request); + case IOCTL_DOLPHIN_GET_SPEED_LIMIT: + return GetSpeedLimit(request); + case IOCTL_DOLPHIN_SET_SPEED_LIMIT: + return SetSpeedLimit(request); + case IOCTL_DOLPHIN_GET_CPU_SPEED: + return GetCPUSpeed(request); + default: + return GetDefaultReply(IPC_EINVAL); + } +} +} // namespace IOS::HLE::Device diff --git a/Source/Core/Core/IOS/DolphinDevice.h b/Source/Core/Core/IOS/DolphinDevice.h new file mode 100644 index 0000000000..217ce53f20 --- /dev/null +++ b/Source/Core/Core/IOS/DolphinDevice.h @@ -0,0 +1,18 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Core/IOS/Device.h" + +namespace IOS::HLE::Device +{ +class DolphinDevice final : public Device +{ +public: + // Inherit the constructor from the Device class, since we don't need to do anything special. + using Device::Device; + IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; +}; +} // namespace IOS::HLE::Device diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 6a45ae4e57..72c304b772 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -30,6 +30,7 @@ #include "Core/IOS/DI/DI.h" #include "Core/IOS/Device.h" #include "Core/IOS/DeviceStub.h" +#include "Core/IOS/DolphinDevice.h" #include "Core/IOS/ES/ES.h" #include "Core/IOS/FS/FileSystem.h" #include "Core/IOS/FS/FileSystemProxy.h" @@ -372,6 +373,7 @@ void Kernel::AddCoreDevices() std::lock_guard lock(m_device_map_mutex); AddDevice(std::make_unique(*this, "/dev/fs")); AddDevice(std::make_unique(*this, "/dev/es")); + AddDevice(std::make_unique(*this, "/dev/dolphin")); } void Kernel::AddStaticDevices()