mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-05 04:29:09 -06:00

Instead of constructing IPCCommandResult with static member functions in the Device class, we can just add the relevant constructors to the reply struct itself. Makes more sense than putting it in Device when the struct is used in the kernel code and doesn't use any Device specific members... This commit also changes the IPC command handlers to return an optional IPCCommandResult rather than an IPCCommandResult. This removes the need for a separate boolean that indicates whether the "result" is actually a reply, and also avoids the need to set dummy result values and ticks. It also makes it really obvious which commands can result in no reply being generated. Finally, this commit renames IPCCommandResult to IPCReply since the struct is now only used for actual replies. This new name is less verbose in my opinion. The diff is quite large since this touches every command handler, but the only functional change is that I fixed EnqueueIPCReply to take a s64 for cycles_in_future to match IPCReply.
189 lines
4.6 KiB
C++
189 lines
4.6 KiB
C++
// Copyright 2019 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
|
|
#include "Common/CommonPaths.h"
|
|
#include "Common/FileUtil.h"
|
|
#include "Common/IOFile.h"
|
|
#include "Common/Logging/Log.h"
|
|
#include "Common/NandPaths.h"
|
|
#include "Common/SettingsHandler.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
|
|
{
|
|
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,
|
|
IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE = 0x06,
|
|
|
|
};
|
|
|
|
IPCReply GetSystemTime(const IOCtlVRequest& request)
|
|
{
|
|
if (!request.HasNumberOfValidVectors(0, 1))
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
if (request.io_vectors[0].size != 4)
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
const u32 milliseconds = Common::Timer::GetTimeMs();
|
|
|
|
Memory::Write_U32(milliseconds, request.io_vectors[0].address);
|
|
return IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
IPCReply GetVersion(const IOCtlVRequest& request)
|
|
{
|
|
if (!request.HasNumberOfValidVectors(0, 1))
|
|
{
|
|
return IPCReply(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 IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
IPCReply GetCPUSpeed(const IOCtlVRequest& request)
|
|
{
|
|
if (!request.HasNumberOfValidVectors(0, 1))
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
if (request.io_vectors[0].size != 4)
|
|
{
|
|
return IPCReply(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 IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
IPCReply GetSpeedLimit(const IOCtlVRequest& request)
|
|
{
|
|
// get current speed limit
|
|
if (!request.HasNumberOfValidVectors(0, 1))
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
if (request.io_vectors[0].size != 4)
|
|
{
|
|
return IPCReply(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 IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
IPCReply SetSpeedLimit(const IOCtlVRequest& request)
|
|
{
|
|
// set current speed limit
|
|
if (!request.HasNumberOfValidVectors(1, 0))
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
if (request.in_vectors[0].size != 4)
|
|
{
|
|
return IPCReply(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 IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
IPCReply GetRealProductCode(const IOCtlVRequest& request)
|
|
{
|
|
if (!request.HasNumberOfValidVectors(0, 1))
|
|
{
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
|
|
const std::string backup_file_path = File::GetUserPath(D_BACKUP_IDX) + DIR_SEP + WII_SETTING;
|
|
|
|
File::IOFile file(backup_file_path, "rb");
|
|
if (!file)
|
|
return IPCReply(IPC_ENOENT);
|
|
|
|
Common::SettingsHandler::Buffer data;
|
|
|
|
if (!file.ReadBytes(data.data(), data.size()))
|
|
return IPCReply(IPC_ENOENT);
|
|
|
|
Common::SettingsHandler gen;
|
|
gen.SetBytes(std::move(data));
|
|
const std::string code = gen.GetValue("CODE");
|
|
|
|
const size_t length = std::min<size_t>(request.io_vectors[0].size, code.length());
|
|
if (length == 0)
|
|
return IPCReply(IPC_ENOENT);
|
|
|
|
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
|
|
Memory::CopyToEmu(request.io_vectors[0].address, code.c_str(), length);
|
|
return IPCReply(IPC_SUCCESS);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::optional<IPCReply> DolphinDevice::IOCtlV(const IOCtlVRequest& request)
|
|
{
|
|
if (Core::WantsDeterminism())
|
|
return IPCReply(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);
|
|
case IOCTL_DOLPHIN_GET_REAL_PRODUCTCODE:
|
|
return GetRealProductCode(request);
|
|
default:
|
|
return IPCReply(IPC_EINVAL);
|
|
}
|
|
}
|
|
} // namespace IOS::HLE
|