early-access version 2901
This commit is contained in:
parent
7ce78aaa94
commit
7a7b98c00a
16 changed files with 734 additions and 65 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2897.
|
This is the source code for early-access 2901.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,9 @@ public:
|
||||||
constexpr s32 max{std::numeric_limits<s16>::max()};
|
constexpr s32 max{std::numeric_limits<s16>::max()};
|
||||||
|
|
||||||
auto yuzu_volume{Settings::Volume()};
|
auto yuzu_volume{Settings::Volume()};
|
||||||
|
if (yuzu_volume > 1.0f) {
|
||||||
|
yuzu_volume = 0.6f + 20 * std::log10(yuzu_volume);
|
||||||
|
}
|
||||||
auto volume{system_volume * device_volume * yuzu_volume};
|
auto volume{system_volume * device_volume * yuzu_volume};
|
||||||
|
|
||||||
if (system_channels == 6 && device_channels == 2) {
|
if (system_channels == 6 && device_channels == 2) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ float Volume() {
|
||||||
if (values.audio_muted) {
|
if (values.audio_muted) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
return values.volume.GetValue() / 100.0f;
|
return values.volume.GetValue() / static_cast<f32>(values.volume.GetDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateRescalingInfo() {
|
void UpdateRescalingInfo() {
|
||||||
|
|
|
@ -374,7 +374,7 @@ struct Values {
|
||||||
Setting<std::string> audio_output_device_id{"auto", "output_device"};
|
Setting<std::string> audio_output_device_id{"auto", "output_device"};
|
||||||
Setting<std::string> audio_input_device_id{"auto", "input_device"};
|
Setting<std::string> audio_input_device_id{"auto", "input_device"};
|
||||||
Setting<bool> audio_muted{false, "audio_muted"};
|
Setting<bool> audio_muted{false, "audio_muted"};
|
||||||
SwitchableSetting<u8, true> volume{100, 0, 100, "volume"};
|
SwitchableSetting<u8, true> volume{100, 0, 200, "volume"};
|
||||||
Setting<bool> dump_audio_commands{false, "dump_audio_commands"};
|
Setting<bool> dump_audio_commands{false, "dump_audio_commands"};
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
|
|
|
@ -500,9 +500,10 @@ add_library(core STATIC
|
||||||
hle/service/jit/jit.h
|
hle/service/jit/jit.h
|
||||||
hle/service/lbl/lbl.cpp
|
hle/service/lbl/lbl.cpp
|
||||||
hle/service/lbl/lbl.h
|
hle/service/lbl/lbl.h
|
||||||
hle/service/ldn/errors.h
|
hle/service/ldn/ldn_results.h
|
||||||
hle/service/ldn/ldn.cpp
|
hle/service/ldn/ldn.cpp
|
||||||
hle/service/ldn/ldn.h
|
hle/service/ldn/ldn.h
|
||||||
|
hle/service/ldn/ldn_types.h
|
||||||
hle/service/ldr/ldr.cpp
|
hle/service/ldr/ldr.cpp
|
||||||
hle/service/ldr/ldr.h
|
hle/service/ldr/ldr.h
|
||||||
hle/service/lm/lm.cpp
|
hle/service/lm/lm.cpp
|
||||||
|
|
|
@ -287,7 +287,8 @@ void IPSwitchCompiler::Parse() {
|
||||||
std::copy(value.begin(), value.end(), std::back_inserter(replace));
|
std::copy(value.begin(), value.end(), std::back_inserter(replace));
|
||||||
} else {
|
} else {
|
||||||
// hex replacement
|
// hex replacement
|
||||||
const auto value = patch_line.substr(9);
|
const auto value =
|
||||||
|
patch_line.substr(9, patch_line.find_first_of(" /\r\n", 9) - 9);
|
||||||
replace = Common::HexStringToVector(value, is_little_endian);
|
replace = Common::HexStringToVector(value, is_little_endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/result.h"
|
|
||||||
#include "core/hle/service/ldn/errors.h"
|
|
||||||
#include "core/hle/service/ldn/ldn.h"
|
#include "core/hle/service/ldn/ldn.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/ldn/ldn_results.h"
|
||||||
|
#include "core/hle/service/ldn/ldn_types.h"
|
||||||
|
#include "core/internal_network/network.h"
|
||||||
|
#include "core/internal_network/network_interface.h"
|
||||||
|
|
||||||
|
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
|
||||||
|
#undef CreateEvent
|
||||||
|
|
||||||
namespace Service::LDN {
|
namespace Service::LDN {
|
||||||
|
|
||||||
|
@ -100,74 +104,418 @@ class IUserLocalCommunicationService final
|
||||||
: public ServiceFramework<IUserLocalCommunicationService> {
|
: public ServiceFramework<IUserLocalCommunicationService> {
|
||||||
public:
|
public:
|
||||||
explicit IUserLocalCommunicationService(Core::System& system_)
|
explicit IUserLocalCommunicationService(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IUserLocalCommunicationService"} {
|
: ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
|
||||||
|
service_context{system, "IUserLocalCommunicationService"}, room_network{
|
||||||
|
system_.GetRoomNetwork()} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IUserLocalCommunicationService::GetState, "GetState"},
|
{0, &IUserLocalCommunicationService::GetState, "GetState"},
|
||||||
{1, nullptr, "GetNetworkInfo"},
|
{1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
|
||||||
{2, nullptr, "GetIpv4Address"},
|
{2, nullptr, "GetIpv4Address"},
|
||||||
{3, nullptr, "GetDisconnectReason"},
|
{3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
|
||||||
{4, nullptr, "GetSecurityParameter"},
|
{4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
|
||||||
{5, nullptr, "GetNetworkConfig"},
|
{5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
|
||||||
{100, nullptr, "AttachStateChangeEvent"},
|
{100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
|
||||||
{101, nullptr, "GetNetworkInfoLatestUpdate"},
|
{101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
|
||||||
{102, nullptr, "Scan"},
|
{102, &IUserLocalCommunicationService::Scan, "Scan"},
|
||||||
{103, nullptr, "ScanPrivate"},
|
{103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
|
||||||
{104, nullptr, "SetWirelessControllerRestriction"},
|
{104, nullptr, "SetWirelessControllerRestriction"},
|
||||||
{200, nullptr, "OpenAccessPoint"},
|
{200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
|
||||||
{201, nullptr, "CloseAccessPoint"},
|
{201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
|
||||||
{202, nullptr, "CreateNetwork"},
|
{202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
|
||||||
{203, nullptr, "CreateNetworkPrivate"},
|
{203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
|
||||||
{204, nullptr, "DestroyNetwork"},
|
{204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
|
||||||
{205, nullptr, "Reject"},
|
{205, nullptr, "Reject"},
|
||||||
{206, nullptr, "SetAdvertiseData"},
|
{206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
|
||||||
{207, nullptr, "SetStationAcceptPolicy"},
|
{207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
|
||||||
{208, nullptr, "AddAcceptFilterEntry"},
|
{208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
|
||||||
{209, nullptr, "ClearAcceptFilter"},
|
{209, nullptr, "ClearAcceptFilter"},
|
||||||
{300, nullptr, "OpenStation"},
|
{300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
|
||||||
{301, nullptr, "CloseStation"},
|
{301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
|
||||||
{302, nullptr, "Connect"},
|
{302, &IUserLocalCommunicationService::Connect, "Connect"},
|
||||||
{303, nullptr, "ConnectPrivate"},
|
{303, nullptr, "ConnectPrivate"},
|
||||||
{304, nullptr, "Disconnect"},
|
{304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
|
||||||
{400, nullptr, "Initialize"},
|
{400, &IUserLocalCommunicationService::Initialize, "Initialize"},
|
||||||
{401, nullptr, "Finalize"},
|
{401, &IUserLocalCommunicationService::Finalize, "Finalize"},
|
||||||
{402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+
|
{402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
state_change_event =
|
||||||
|
service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
|
||||||
|
}
|
||||||
|
|
||||||
|
~IUserLocalCommunicationService() {
|
||||||
|
service_context.CloseEvent(state_change_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEventFired() {
|
||||||
|
state_change_event->GetWritableEvent().Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetState(Kernel::HLERequestContext& ctx) {
|
void GetState(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
State state = State::Error;
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushEnum(state);
|
||||||
|
}
|
||||||
|
|
||||||
// Indicate a network error, as we do not actually emulate LDN
|
void GetNetworkInfo(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push(static_cast<u32>(State::Error));
|
const auto write_buffer_size = ctx.GetWriteBufferSize();
|
||||||
|
|
||||||
|
if (write_buffer_size != sizeof(NetworkInfo)) {
|
||||||
|
LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultBadInput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkInfo network_info{};
|
||||||
|
const auto rc = ResultSuccess;
|
||||||
|
if (rc.IsError()) {
|
||||||
|
LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
|
||||||
|
network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
|
||||||
|
|
||||||
|
ctx.WriteBuffer<NetworkInfo>(network_info);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetDisconnectReason(Kernel::HLERequestContext& ctx) {
|
||||||
|
const auto disconnect_reason = DisconnectReason::None;
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushEnum(disconnect_reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetSecurityParameter(Kernel::HLERequestContext& ctx) {
|
||||||
|
SecurityParameter security_parameter{};
|
||||||
|
NetworkInfo info{};
|
||||||
|
const Result rc = ResultSuccess;
|
||||||
|
|
||||||
|
if (rc.IsError()) {
|
||||||
|
LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
security_parameter.session_id = info.network_id.session_id;
|
||||||
|
std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
|
||||||
|
sizeof(SecurityParameter::data));
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 10};
|
||||||
|
rb.Push(rc);
|
||||||
|
rb.PushRaw<SecurityParameter>(security_parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetNetworkConfig(Kernel::HLERequestContext& ctx) {
|
||||||
|
NetworkConfig config{};
|
||||||
|
NetworkInfo info{};
|
||||||
|
const Result rc = ResultSuccess;
|
||||||
|
|
||||||
|
if (rc.IsError()) {
|
||||||
|
LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.intent_id = info.network_id.intent_id;
|
||||||
|
config.channel = info.common.channel;
|
||||||
|
config.node_count_max = info.ldn.node_count_max;
|
||||||
|
config.local_communication_version = info.ldn.nodes[0].local_communication_version;
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN,
|
||||||
|
"(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
|
||||||
|
"local_communication_version={}",
|
||||||
|
config.intent_id.local_communication_id, config.intent_id.scene_id,
|
||||||
|
config.channel, config.node_count_max, config.local_communication_version);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 10};
|
||||||
|
rb.Push(rc);
|
||||||
|
rb.PushRaw<NetworkConfig>(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_LDN, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(state_change_event->GetReadableEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
|
||||||
|
const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
|
||||||
|
const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
|
||||||
|
|
||||||
|
if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
|
||||||
|
LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
|
||||||
|
node_buffer_count);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultBadInput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkInfo info;
|
||||||
|
std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
|
||||||
|
|
||||||
|
const auto rc = ResultSuccess;
|
||||||
|
if (rc.IsError()) {
|
||||||
|
LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
|
||||||
|
info.common.ssid.GetStringValue(), info.ldn.node_count);
|
||||||
|
|
||||||
|
ctx.WriteBuffer(info, 0);
|
||||||
|
ctx.WriteBuffer(latest_update, 1);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scan(Kernel::HLERequestContext& ctx) {
|
||||||
|
ScanImpl(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScanPrivate(Kernel::HLERequestContext& ctx) {
|
||||||
|
ScanImpl(ctx, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto channel{rp.PopEnum<WifiChannel>()};
|
||||||
|
const auto scan_filter{rp.PopRaw<ScanFilter>()};
|
||||||
|
|
||||||
|
const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
|
||||||
|
|
||||||
|
if (network_info_size == 0) {
|
||||||
|
LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultBadInput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 count = 0;
|
||||||
|
std::vector<NetworkInfo> network_infos(network_info_size);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN,
|
||||||
|
"(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
|
||||||
|
channel, scan_filter.flag, scan_filter.network_type);
|
||||||
|
|
||||||
|
ctx.WriteBuffer(network_infos);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenAccessPoint(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseAccessPoint(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateNetwork(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
struct Parameters {
|
||||||
|
SecurityConfig security_config;
|
||||||
|
UserConfig user_config;
|
||||||
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
|
NetworkConfig network_config;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
const auto parameters{rp.PopRaw<Parameters>()};
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN,
|
||||||
|
"(STUBBED) called, passphrase_size={}, security_mode={}, "
|
||||||
|
"local_communication_version={}",
|
||||||
|
parameters.security_config.passphrase_size,
|
||||||
|
parameters.security_config.security_mode,
|
||||||
|
parameters.network_config.local_communication_version);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
struct Parameters {
|
||||||
|
SecurityConfig security_config;
|
||||||
|
SecurityParameter security_parameter;
|
||||||
|
UserConfig user_config;
|
||||||
|
NetworkConfig network_config;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
const auto parameters{rp.PopRaw<Parameters>()};
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN,
|
||||||
|
"(STUBBED) called, passphrase_size={}, security_mode={}, "
|
||||||
|
"local_communication_version={}",
|
||||||
|
parameters.security_config.passphrase_size,
|
||||||
|
parameters.security_config.security_mode,
|
||||||
|
parameters.network_config.local_communication_version);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyNetwork(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
|
||||||
|
std::vector<u8> read_buffer = ctx.ReadBuffer();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenStation(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseStation(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connect(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
struct Parameters {
|
||||||
|
SecurityConfig security_config;
|
||||||
|
UserConfig user_config;
|
||||||
|
u32 local_communication_version;
|
||||||
|
u32 option;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
const auto parameters{rp.PopRaw<Parameters>()};
|
||||||
|
|
||||||
|
LOG_WARNING(Service_LDN,
|
||||||
|
"(STUBBED) called, passphrase_size={}, security_mode={}, "
|
||||||
|
"local_communication_version={}",
|
||||||
|
parameters.security_config.passphrase_size,
|
||||||
|
parameters.security_config.security_mode,
|
||||||
|
parameters.local_communication_version);
|
||||||
|
|
||||||
|
const std::vector<u8> read_buffer = ctx.ReadBuffer();
|
||||||
|
NetworkInfo network_info{};
|
||||||
|
|
||||||
|
if (read_buffer.size() != sizeof(NetworkInfo)) {
|
||||||
|
LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultBadInput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disconnect(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
void Initialize(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
const auto rc = InitializeImpl(ctx);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize(Kernel::HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
|
is_initialized = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize2(Kernel::HLERequestContext& ctx) {
|
void Initialize2(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_LDN, "called");
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
is_initialized = true;
|
const auto rc = InitializeImpl(ctx);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERROR_DISABLED);
|
rb.Push(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
Result InitializeImpl(Kernel::HLERequestContext& ctx) {
|
||||||
enum class State {
|
const auto network_interface = Network::GetSelectedNetworkInterface();
|
||||||
None,
|
if (!network_interface) {
|
||||||
Initialized,
|
LOG_ERROR(Service_LDN, "No network interface is set");
|
||||||
AccessPointOpened,
|
return ResultAirplaneModeEnabled;
|
||||||
AccessPointCreated,
|
}
|
||||||
StationOpened,
|
|
||||||
StationConnected,
|
is_initialized = true;
|
||||||
Error,
|
// TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
|
||||||
};
|
return ResultAirplaneModeEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
Kernel::KEvent* state_change_event;
|
||||||
|
Network::RoomNetwork& room_network;
|
||||||
|
|
||||||
bool is_initialized{};
|
bool is_initialized{};
|
||||||
};
|
};
|
||||||
|
@ -273,7 +621,7 @@ public:
|
||||||
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERROR_DISABLED);
|
rb.Push(ResultDisabled);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/ipc_helpers.h"
|
||||||
|
#include "core/hle/kernel/k_event.h"
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
27
src/core/hle/service/ldn/ldn_results.h
Executable file
27
src/core/hle/service/ldn/ldn_results.h
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Service::LDN {
|
||||||
|
|
||||||
|
constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10};
|
||||||
|
constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20};
|
||||||
|
constexpr Result ResultDisabled{ErrorModule::LDN, 22};
|
||||||
|
constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23};
|
||||||
|
constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30};
|
||||||
|
constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31};
|
||||||
|
constexpr Result ResultBadState{ErrorModule::LDN, 32};
|
||||||
|
constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33};
|
||||||
|
constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50};
|
||||||
|
constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65};
|
||||||
|
constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66};
|
||||||
|
constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67};
|
||||||
|
constexpr Result ResultBadInput{ErrorModule::LDN, 96};
|
||||||
|
constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97};
|
||||||
|
constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113};
|
||||||
|
constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114};
|
||||||
|
|
||||||
|
} // namespace Service::LDN
|
284
src/core/hle/service/ldn/ldn_types.h
Executable file
284
src/core/hle/service/ldn/ldn_types.h
Executable file
|
@ -0,0 +1,284 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "network/network.h"
|
||||||
|
|
||||||
|
namespace Service::LDN {
|
||||||
|
|
||||||
|
constexpr size_t SsidLengthMax = 32;
|
||||||
|
constexpr size_t AdvertiseDataSizeMax = 384;
|
||||||
|
constexpr size_t UserNameBytesMax = 32;
|
||||||
|
constexpr int NodeCountMax = 8;
|
||||||
|
constexpr int StationCountMax = NodeCountMax - 1;
|
||||||
|
constexpr size_t PassphraseLengthMax = 64;
|
||||||
|
|
||||||
|
enum class SecurityMode : u16 {
|
||||||
|
All,
|
||||||
|
Retail,
|
||||||
|
Debug,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NodeStateChange : u8 {
|
||||||
|
None,
|
||||||
|
Connect,
|
||||||
|
Disconnect,
|
||||||
|
DisconnectAndConnect,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ScanFilterFlag : u32 {
|
||||||
|
None = 0,
|
||||||
|
LocalCommunicationId = 1 << 0,
|
||||||
|
SessionId = 1 << 1,
|
||||||
|
NetworkType = 1 << 2,
|
||||||
|
Ssid = 1 << 4,
|
||||||
|
SceneId = 1 << 5,
|
||||||
|
IntentId = LocalCommunicationId | SceneId,
|
||||||
|
NetworkId = IntentId | SessionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NetworkType : u32 {
|
||||||
|
None,
|
||||||
|
General,
|
||||||
|
Ldn,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PackedNetworkType : u8 {
|
||||||
|
None,
|
||||||
|
General,
|
||||||
|
Ldn,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class State : u32 {
|
||||||
|
None,
|
||||||
|
Initialized,
|
||||||
|
AccessPointOpened,
|
||||||
|
AccessPointCreated,
|
||||||
|
StationOpened,
|
||||||
|
StationConnected,
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DisconnectReason : s16 {
|
||||||
|
Unknown = -1,
|
||||||
|
None,
|
||||||
|
DisconnectedByUser,
|
||||||
|
DisconnectedBySystem,
|
||||||
|
DestroyedByUser,
|
||||||
|
DestroyedBySystem,
|
||||||
|
Rejected,
|
||||||
|
SignalLost,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NetworkError {
|
||||||
|
Unknown = -1,
|
||||||
|
None = 0,
|
||||||
|
PortUnreachable,
|
||||||
|
TooManyPlayers,
|
||||||
|
VersionTooLow,
|
||||||
|
VersionTooHigh,
|
||||||
|
ConnectFailure,
|
||||||
|
ConnectNotFound,
|
||||||
|
ConnectTimeout,
|
||||||
|
ConnectRejected,
|
||||||
|
RejectFailed,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AcceptPolicy : u8 {
|
||||||
|
AcceptAll,
|
||||||
|
RejectAll,
|
||||||
|
BlackList,
|
||||||
|
WhiteList,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class WifiChannel : s16 {
|
||||||
|
Default = 0,
|
||||||
|
wifi24_1 = 1,
|
||||||
|
wifi24_6 = 6,
|
||||||
|
wifi24_11 = 11,
|
||||||
|
wifi50_36 = 36,
|
||||||
|
wifi50_40 = 40,
|
||||||
|
wifi50_44 = 44,
|
||||||
|
wifi50_48 = 48,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LinkLevel : s8 {
|
||||||
|
Bad,
|
||||||
|
Low,
|
||||||
|
Good,
|
||||||
|
Excelent,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NodeLatestUpdate {
|
||||||
|
NodeStateChange state_change;
|
||||||
|
INSERT_PADDING_BYTES(0x7); // Unknown
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size");
|
||||||
|
|
||||||
|
struct SessionId {
|
||||||
|
u64 high;
|
||||||
|
u64 low;
|
||||||
|
|
||||||
|
bool operator==(const SessionId&) const = default;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
|
||||||
|
|
||||||
|
struct IntentId {
|
||||||
|
u64 local_communication_id;
|
||||||
|
INSERT_PADDING_BYTES(0x2); // Reserved
|
||||||
|
u16 scene_id;
|
||||||
|
INSERT_PADDING_BYTES(0x4); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
|
||||||
|
|
||||||
|
struct NetworkId {
|
||||||
|
IntentId intent_id;
|
||||||
|
SessionId session_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
|
||||||
|
|
||||||
|
struct Ssid {
|
||||||
|
u8 length;
|
||||||
|
std::array<char, SsidLengthMax + 1> raw;
|
||||||
|
|
||||||
|
std::string GetStringValue() const {
|
||||||
|
return std::string(raw.data(), length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size");
|
||||||
|
|
||||||
|
struct Ipv4Address {
|
||||||
|
union {
|
||||||
|
u32 raw{};
|
||||||
|
std::array<u8, 4> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string GetStringValue() const {
|
||||||
|
return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
|
||||||
|
|
||||||
|
struct MacAddress {
|
||||||
|
std::array<u8, 6> raw{};
|
||||||
|
|
||||||
|
friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size");
|
||||||
|
|
||||||
|
struct ScanFilter {
|
||||||
|
NetworkId network_id;
|
||||||
|
NetworkType network_type;
|
||||||
|
MacAddress mac_address;
|
||||||
|
Ssid ssid;
|
||||||
|
INSERT_PADDING_BYTES(0x10);
|
||||||
|
ScanFilterFlag flag;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size");
|
||||||
|
|
||||||
|
struct CommonNetworkInfo {
|
||||||
|
MacAddress bssid;
|
||||||
|
Ssid ssid;
|
||||||
|
WifiChannel channel;
|
||||||
|
LinkLevel link_level;
|
||||||
|
PackedNetworkType network_type;
|
||||||
|
INSERT_PADDING_BYTES(0x4);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
|
||||||
|
|
||||||
|
struct NodeInfo {
|
||||||
|
Ipv4Address ipv4_address;
|
||||||
|
MacAddress mac_address;
|
||||||
|
s8 node_id;
|
||||||
|
u8 is_connected;
|
||||||
|
std::array<u8, UserNameBytesMax + 1> user_name;
|
||||||
|
INSERT_PADDING_BYTES(0x1); // Reserved
|
||||||
|
s16 local_communication_version;
|
||||||
|
INSERT_PADDING_BYTES(0x10); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
|
||||||
|
|
||||||
|
struct LdnNetworkInfo {
|
||||||
|
std::array<u8, 0x10> security_parameter;
|
||||||
|
SecurityMode security_mode;
|
||||||
|
AcceptPolicy station_accept_policy;
|
||||||
|
u8 has_action_frame;
|
||||||
|
INSERT_PADDING_BYTES(0x2); // Padding
|
||||||
|
u8 node_count_max;
|
||||||
|
u8 node_count;
|
||||||
|
std::array<NodeInfo, NodeCountMax> nodes;
|
||||||
|
INSERT_PADDING_BYTES(0x2); // Reserved
|
||||||
|
u16 advertise_data_size;
|
||||||
|
std::array<u8, AdvertiseDataSizeMax> advertise_data;
|
||||||
|
INSERT_PADDING_BYTES(0x8C); // Reserved
|
||||||
|
u64 random_authentication_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
|
||||||
|
|
||||||
|
struct NetworkInfo {
|
||||||
|
NetworkId network_id;
|
||||||
|
CommonNetworkInfo common;
|
||||||
|
LdnNetworkInfo ldn;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
|
||||||
|
|
||||||
|
struct SecurityConfig {
|
||||||
|
SecurityMode security_mode;
|
||||||
|
u16 passphrase_size;
|
||||||
|
std::array<u8, PassphraseLengthMax> passphrase;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size");
|
||||||
|
|
||||||
|
struct UserConfig {
|
||||||
|
std::array<u8, UserNameBytesMax + 1> user_name;
|
||||||
|
INSERT_PADDING_BYTES(0xF); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size");
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
struct ConnectRequest {
|
||||||
|
SecurityConfig security_config;
|
||||||
|
UserConfig user_config;
|
||||||
|
u32 local_communication_version;
|
||||||
|
u32 option_unknown;
|
||||||
|
NetworkInfo network_info;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size");
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct SecurityParameter {
|
||||||
|
std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig
|
||||||
|
SessionId session_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size");
|
||||||
|
|
||||||
|
struct NetworkConfig {
|
||||||
|
IntentId intent_id;
|
||||||
|
WifiChannel channel;
|
||||||
|
u8 node_count_max;
|
||||||
|
INSERT_PADDING_BYTES(0x1); // Reserved
|
||||||
|
u16 local_communication_version;
|
||||||
|
INSERT_PADDING_BYTES(0xA); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size");
|
||||||
|
|
||||||
|
struct AddressEntry {
|
||||||
|
Ipv4Address ipv4_address;
|
||||||
|
MacAddress mac_address;
|
||||||
|
INSERT_PADDING_BYTES(0x2); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size");
|
||||||
|
|
||||||
|
struct AddressList {
|
||||||
|
std::array<AddressEntry, 0x8> addresses;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
|
||||||
|
|
||||||
|
} // namespace Service::LDN
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>616</width>
|
<width>616</width>
|
||||||
<height>261</height>
|
<height>294</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -165,6 +165,7 @@ p, li { white-space: pre-wrap; }
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../dist/qt_themes_default/default/default.qrc"/>
|
<include location="../../dist/qt_themes_default/default/default.qrc"/>
|
||||||
|
<include location="../../dist/qt_themes/default/default.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|
|
@ -73,7 +73,7 @@ const std::array<int, 2> Config::default_ringcon_analogs{{
|
||||||
const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
|
const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}},
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}},
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}},
|
||||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}},
|
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}},
|
||||||
|
|
|
@ -120,10 +120,10 @@
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>100</number>
|
<number>200</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="pageStep">
|
<property name="pageStep">
|
||||||
<number>10</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
|
|
|
@ -258,7 +258,7 @@ static QString PrettyProductName() {
|
||||||
return QSysInfo::prettyProductName();
|
return QSysInfo::prettyProductName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GMainWindow::check_dark_mode() {
|
bool GMainWindow::CheckDarkMode() {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
const QPalette test_palette(qApp->palette());
|
const QPalette test_palette(qApp->palette());
|
||||||
const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
|
const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
|
||||||
|
@ -288,7 +288,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
statusBar()->hide();
|
statusBar()->hide();
|
||||||
|
|
||||||
// Check dark mode before a theme is loaded
|
// Check dark mode before a theme is loaded
|
||||||
os_dark_mode = check_dark_mode();
|
os_dark_mode = CheckDarkMode();
|
||||||
startup_icon_theme = QIcon::themeName();
|
startup_icon_theme = QIcon::themeName();
|
||||||
// fallback can only be set once, colorful theme icons are okay on both light/dark
|
// fallback can only be set once, colorful theme icons are okay on both light/dark
|
||||||
QIcon::setFallbackThemeName(QStringLiteral("colorful"));
|
QIcon::setFallbackThemeName(QStringLiteral("colorful"));
|
||||||
|
@ -1095,7 +1095,7 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
connect_shortcut(QStringLiteral("Audio Mute/Unmute"),
|
connect_shortcut(QStringLiteral("Audio Mute/Unmute"),
|
||||||
[] { Settings::values.audio_muted = !Settings::values.audio_muted; });
|
[] { Settings::values.audio_muted = !Settings::values.audio_muted; });
|
||||||
connect_shortcut(QStringLiteral("Audio Volume Down"), [] {
|
connect_shortcut(QStringLiteral("Audio Volume Down"), [] {
|
||||||
const auto current_volume = static_cast<int>(Settings::values.volume.GetValue());
|
const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
|
||||||
int step = 5;
|
int step = 5;
|
||||||
if (current_volume <= 30) {
|
if (current_volume <= 30) {
|
||||||
step = 2;
|
step = 2;
|
||||||
|
@ -1103,11 +1103,10 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
if (current_volume <= 6) {
|
if (current_volume <= 6) {
|
||||||
step = 1;
|
step = 1;
|
||||||
}
|
}
|
||||||
const auto new_volume = std::max(current_volume - step, 0);
|
Settings::values.volume.SetValue(std::max(current_volume - step, 0));
|
||||||
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
|
|
||||||
});
|
});
|
||||||
connect_shortcut(QStringLiteral("Audio Volume Up"), [] {
|
connect_shortcut(QStringLiteral("Audio Volume Up"), [] {
|
||||||
const auto current_volume = static_cast<int>(Settings::values.volume.GetValue());
|
const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
|
||||||
int step = 5;
|
int step = 5;
|
||||||
if (current_volume < 30) {
|
if (current_volume < 30) {
|
||||||
step = 2;
|
step = 2;
|
||||||
|
@ -1115,8 +1114,7 @@ void GMainWindow::InitializeHotkeys() {
|
||||||
if (current_volume < 6) {
|
if (current_volume < 6) {
|
||||||
step = 1;
|
step = 1;
|
||||||
}
|
}
|
||||||
const auto new_volume = std::min(current_volume + step, 100);
|
Settings::values.volume.SetValue(current_volume + step);
|
||||||
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
|
|
||||||
});
|
});
|
||||||
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
|
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
|
||||||
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
|
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
|
||||||
|
@ -3986,7 +3984,7 @@ void GMainWindow::UpdateUITheme() {
|
||||||
QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
|
QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
|
||||||
: startup_icon_theme);
|
: startup_icon_theme);
|
||||||
QIcon::setThemeSearchPaths(theme_paths);
|
QIcon::setThemeSearchPaths(theme_paths);
|
||||||
if (check_dark_mode()) {
|
if (CheckDarkMode()) {
|
||||||
current_theme = QStringLiteral("default_dark");
|
current_theme = QStringLiteral("default_dark");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -348,6 +348,7 @@ private:
|
||||||
void OpenURL(const QUrl& url);
|
void OpenURL(const QUrl& url);
|
||||||
void LoadTranslation();
|
void LoadTranslation();
|
||||||
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
||||||
|
bool CheckDarkMode();
|
||||||
|
|
||||||
QString GetTasStateDescription() const;
|
QString GetTasStateDescription() const;
|
||||||
|
|
||||||
|
@ -395,7 +396,6 @@ private:
|
||||||
|
|
||||||
QString startup_icon_theme;
|
QString startup_icon_theme;
|
||||||
bool os_dark_mode = false;
|
bool os_dark_mode = false;
|
||||||
bool check_dark_mode();
|
|
||||||
|
|
||||||
// FS
|
// FS
|
||||||
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="placeholderText">
|
<property name="placeholderText">
|
||||||
<string>24872</string>
|
<string notr="true" extracomment="placeholder string that tells user default port">24872</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
Loading…
Reference in a new issue