Add /dev/dolphin for homebrew to get information about Dolphin

Adds a /dev/dolphin interface that can be used by
Dolphin-aware software to get information like the
real system time and the Dolphin version.
This commit is contained in:
Florian Bach
2019-11-01 23:30:30 +01:00
parent a7d4be79ae
commit 2d55a6b0b7
8 changed files with 189 additions and 2 deletions

View File

@ -0,0 +1,151 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <cstring>
#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