Compare commits

..

12 Commits

Author SHA1 Message Date
Narr the Reg
d0c7c3f64f svc: Set unique names for function tables 2022-02-08 21:03:31 -06:00
Morph
b720009dc0 Merge pull request #7847 from tech-ticks/master
service: pm: Implement AtmosphereGetProcessInfo
2022-02-05 19:22:45 -05:00
Morph
36910e9020 Merge pull request #7851 from lat9nq/cmd-add-motion
yuzu-cmd: config: Support motion inputs
2022-02-05 19:22:18 -05:00
bunnei
0456ed6b4e Merge pull request #7849 from Morph1984/qt-frameless-window
main: Always remove the frameless window flag when restoring UI state
2022-02-05 15:18:48 -07:00
bunnei
5cb1c2ad84 Merge pull request #7842 from german77/vibration_test
yuzu: config: Vibrate the controller while configuring vibration strength
2022-02-05 02:57:26 -07:00
lat9nq
928380ebf9 config: Support motion inputs
Motion inputs were not being read in by the config when yuzu-cmd boots
up. This adds support for those.

While we're at it, make a reference to the current player controls to
improve readability. Also updates the if statements in the Analog and
Button loops with curly braces to keep the style consistent.
2022-02-05 02:31:55 -05:00
bunnei
0ec5b9bff2 Merge pull request #7839 from german77/battery
yuzu: ui: Improve battery symbols
2022-02-04 18:23:35 -07:00
Mai M
7ad17ae397 Merge pull request #7848 from Morph1984/unused-core-include
input_common: Remove unused core include
2022-02-03 23:21:32 -05:00
Morph
edbfbf2f2f main: Always remove the frameless window flag when restoring UI state
For unknown reasons, this flag may persist after the application has been closed.
Removing this flag when restoring the UI state ensures that a frameless window will not be shown on startup.
2022-02-03 23:12:49 -05:00
tech-ticks
16bf50e610 service: pm: Implement AtmosphereGetProcessInfo 2022-02-04 01:41:36 +01:00
Narr the Reg
694c078655 yuzu: config: Vibrate the controller while configuring vibration strength 2022-02-02 14:54:24 -06:00
Narr the Reg
064aa3de11 yuzu: ui: Improve battery symbols 2022-02-02 13:18:06 -06:00
13 changed files with 307 additions and 133 deletions

View File

@@ -28,7 +28,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta
if (value > 0.8f) {
battery = Common::Input::BatteryLevel::Full;
}
if (value >= 1.0f) {
if (value >= 0.95f) {
battery = Common::Input::BatteryLevel::Charging;
}
break;

View File

@@ -396,7 +396,7 @@ static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle
// Get the process id.
*out_process_id = process->GetId();
return ResultInvalidHandle;
return ResultSuccess;
}
static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low,
@@ -2559,9 +2559,9 @@ struct FunctionDef {
} // namespace
static const FunctionDef SVC_Table_32[] = {
{0x00, nullptr, "Unknown"},
{0x00, nullptr, "Unknown0"},
{0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"},
{0x02, nullptr, "Unknown"},
{0x02, nullptr, "SetMemoryPermission32"},
{0x03, SvcWrap32<SetMemoryAttribute32>, "SetMemoryAttribute32"},
{0x04, SvcWrap32<MapMemory32>, "MapMemory32"},
{0x05, SvcWrap32<UnmapMemory32>, "UnmapMemory32"},
@@ -2591,97 +2591,97 @@ static const FunctionDef SVC_Table_32[] = {
{0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"},
{0x1e, SvcWrap32<GetSystemTick32>, "GetSystemTick32"},
{0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"},
{0x20, nullptr, "Unknown"},
{0x20, nullptr, "SendSyncRequestLight32"},
{0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"},
{0x22, nullptr, "SendSyncRequestWithUserBuffer32"},
{0x23, nullptr, "Unknown"},
{0x23, nullptr, "SendAsyncRequestWithUserBuffer32"},
{0x24, SvcWrap32<GetProcessId32>, "GetProcessId32"},
{0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"},
{0x26, SvcWrap32<Break32>, "Break32"},
{0x27, nullptr, "OutputDebugString32"},
{0x28, nullptr, "Unknown"},
{0x28, nullptr, "ReturnFromException32"},
{0x29, SvcWrap32<GetInfo32>, "GetInfo32"},
{0x2a, nullptr, "Unknown"},
{0x2b, nullptr, "Unknown"},
{0x2a, nullptr, "FlushEntireDataCache32"},
{0x2b, nullptr, "FlushDataCache32"},
{0x2c, SvcWrap32<MapPhysicalMemory32>, "MapPhysicalMemory32"},
{0x2d, SvcWrap32<UnmapPhysicalMemory32>, "UnmapPhysicalMemory32"},
{0x2e, nullptr, "Unknown"},
{0x2f, nullptr, "Unknown"},
{0x30, nullptr, "Unknown"},
{0x31, nullptr, "Unknown"},
{0x2e, nullptr, "GetDebugFutureThreadInfo32"},
{0x2f, nullptr, "GetLastThreadInfo32"},
{0x30, nullptr, "GetResourceLimitLimitValue32"},
{0x31, nullptr, "GetResourceLimitCurrentValue32"},
{0x32, SvcWrap32<SetThreadActivity32>, "SetThreadActivity32"},
{0x33, SvcWrap32<GetThreadContext32>, "GetThreadContext32"},
{0x34, SvcWrap32<WaitForAddress32>, "WaitForAddress32"},
{0x35, SvcWrap32<SignalToAddress32>, "SignalToAddress32"},
{0x36, SvcWrap32<SynchronizePreemptionState>, "SynchronizePreemptionState32"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
{0x3a, nullptr, "Unknown"},
{0x3b, nullptr, "Unknown"},
{0x3c, nullptr, "Unknown"},
{0x3d, nullptr, "Unknown"},
{0x3e, nullptr, "Unknown"},
{0x3f, nullptr, "Unknown"},
{0x37, nullptr, "GetResourceLimitPeakValue32"},
{0x38, nullptr, "Unknown38"},
{0x39, nullptr, "CreateIoPool32"},
{0x3a, nullptr, "CreateIoRegion32"},
{0x3b, nullptr, "Unknown3b"},
{0x3c, nullptr, "KernelDebug32"},
{0x3d, nullptr, "ChangeKernelTraceState32"},
{0x3e, nullptr, "Unknown3e"},
{0x3f, nullptr, "Unknown3f"},
{0x40, nullptr, "CreateSession32"},
{0x41, nullptr, "AcceptSession32"},
{0x42, nullptr, "Unknown"},
{0x42, nullptr, "ReplyAndReceiveLight32"},
{0x43, nullptr, "ReplyAndReceive32"},
{0x44, nullptr, "Unknown"},
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer32"},
{0x45, SvcWrap32<CreateEvent32>, "CreateEvent32"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x48, nullptr, "Unknown"},
{0x49, nullptr, "Unknown"},
{0x4a, nullptr, "Unknown"},
{0x4b, nullptr, "Unknown"},
{0x4c, nullptr, "Unknown"},
{0x4d, nullptr, "Unknown"},
{0x4e, nullptr, "Unknown"},
{0x4f, nullptr, "Unknown"},
{0x50, nullptr, "Unknown"},
{0x51, nullptr, "Unknown"},
{0x52, nullptr, "Unknown"},
{0x53, nullptr, "Unknown"},
{0x54, nullptr, "Unknown"},
{0x55, nullptr, "Unknown"},
{0x56, nullptr, "Unknown"},
{0x57, nullptr, "Unknown"},
{0x58, nullptr, "Unknown"},
{0x59, nullptr, "Unknown"},
{0x5a, nullptr, "Unknown"},
{0x5b, nullptr, "Unknown"},
{0x5c, nullptr, "Unknown"},
{0x5d, nullptr, "Unknown"},
{0x5e, nullptr, "Unknown"},
{0x46, nullptr, "MapIoRegion32"},
{0x47, nullptr, "UnmapIoRegion32"},
{0x48, nullptr, "MapPhysicalMemoryUnsafe32"},
{0x49, nullptr, "UnmapPhysicalMemoryUnsafe32"},
{0x4a, nullptr, "SetUnsafeLimit32"},
{0x4b, nullptr, "CreateCodeMemory32"},
{0x4c, nullptr, "ControlCodeMemory32"},
{0x4d, nullptr, "SleepSystem32"},
{0x4e, nullptr, "ReadWriteRegister32"},
{0x4f, nullptr, "SetProcessActivity32"},
{0x50, nullptr, "CreateSharedMemory32"},
{0x51, nullptr, "MapTransferMemory32"},
{0x52, nullptr, "UnmapTransferMemory32"},
{0x53, nullptr, "CreateInterruptEvent32"},
{0x54, nullptr, "QueryPhysicalAddress32"},
{0x55, nullptr, "QueryIoMapping32"},
{0x56, nullptr, "CreateDeviceAddressSpace32"},
{0x57, nullptr, "AttachDeviceAddressSpace32"},
{0x58, nullptr, "DetachDeviceAddressSpace32"},
{0x59, nullptr, "MapDeviceAddressSpaceByForce32"},
{0x5a, nullptr, "MapDeviceAddressSpaceAligned32"},
{0x5b, nullptr, "MapDeviceAddressSpace32"},
{0x5c, nullptr, "UnmapDeviceAddressSpace32"},
{0x5d, nullptr, "InvalidateProcessDataCache32"},
{0x5e, nullptr, "StoreProcessDataCache32"},
{0x5F, SvcWrap32<FlushProcessDataCache32>, "FlushProcessDataCache32"},
{0x60, nullptr, "Unknown"},
{0x61, nullptr, "Unknown"},
{0x62, nullptr, "Unknown"},
{0x63, nullptr, "Unknown"},
{0x64, nullptr, "Unknown"},
{0x60, nullptr, "StoreProcessDataCache32"},
{0x61, nullptr, "BreakDebugProcess32"},
{0x62, nullptr, "TerminateDebugProcess32"},
{0x63, nullptr, "GetDebugEvent32"},
{0x64, nullptr, "ContinueDebugEvent32"},
{0x65, nullptr, "GetProcessList32"},
{0x66, nullptr, "Unknown"},
{0x67, nullptr, "Unknown"},
{0x68, nullptr, "Unknown"},
{0x69, nullptr, "Unknown"},
{0x6A, nullptr, "Unknown"},
{0x6B, nullptr, "Unknown"},
{0x6C, nullptr, "Unknown"},
{0x6D, nullptr, "Unknown"},
{0x6E, nullptr, "Unknown"},
{0x66, nullptr, "GetThreadList"},
{0x67, nullptr, "GetDebugThreadContext32"},
{0x68, nullptr, "SetDebugThreadContext32"},
{0x69, nullptr, "QueryDebugProcessMemory32"},
{0x6A, nullptr, "ReadDebugProcessMemory32"},
{0x6B, nullptr, "WriteDebugProcessMemory32"},
{0x6C, nullptr, "SetHardwareBreakPoint32"},
{0x6D, nullptr, "GetDebugThreadParam32"},
{0x6E, nullptr, "Unknown6E"},
{0x6f, nullptr, "GetSystemInfo32"},
{0x70, nullptr, "CreatePort32"},
{0x71, nullptr, "ManageNamedPort32"},
{0x72, nullptr, "ConnectToPort32"},
{0x73, nullptr, "SetProcessMemoryPermission32"},
{0x74, nullptr, "Unknown"},
{0x75, nullptr, "Unknown"},
{0x76, nullptr, "Unknown"},
{0x74, nullptr, "MapProcessMemory32"},
{0x75, nullptr, "UnmapProcessMemory32"},
{0x76, nullptr, "QueryProcessMemory32"},
{0x77, nullptr, "MapProcessCodeMemory32"},
{0x78, nullptr, "UnmapProcessCodeMemory32"},
{0x79, nullptr, "Unknown"},
{0x7A, nullptr, "Unknown"},
{0x79, nullptr, "CreateProcess32"},
{0x7A, nullptr, "StartProcess32"},
{0x7B, nullptr, "TerminateProcess32"},
{0x7C, nullptr, "GetProcessInfo32"},
{0x7D, nullptr, "CreateResourceLimit32"},
@@ -2754,7 +2754,7 @@ static const FunctionDef SVC_Table_32[] = {
};
static const FunctionDef SVC_Table_64[] = {
{0x00, nullptr, "Unknown"},
{0x00, nullptr, "Unknown0"},
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
@@ -2809,23 +2809,23 @@ static const FunctionDef SVC_Table_64[] = {
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
{0x36, SvcWrap64<SynchronizePreemptionState>, "SynchronizePreemptionState"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
{0x3A, nullptr, "Unknown"},
{0x3B, nullptr, "Unknown"},
{0x37, nullptr, "GetResourceLimitPeakValue"},
{0x38, nullptr, "Unknown38"},
{0x39, nullptr, "CreateIoPool"},
{0x3A, nullptr, "CreateIoRegion"},
{0x3B, nullptr, "Unknown3B"},
{0x3C, SvcWrap64<KernelDebug>, "KernelDebug"},
{0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
{0x3E, nullptr, "Unknown"},
{0x3F, nullptr, "Unknown"},
{0x3E, nullptr, "Unknown3e"},
{0x3F, nullptr, "Unknown3f"},
{0x40, nullptr, "CreateSession"},
{0x41, nullptr, "AcceptSession"},
{0x42, nullptr, "ReplyAndReceiveLight"},
{0x43, nullptr, "ReplyAndReceive"},
{0x44, nullptr, "ReplyAndReceiveWithUserBuffer"},
{0x45, SvcWrap64<CreateEvent>, "CreateEvent"},
{0x46, nullptr, "Unknown"},
{0x47, nullptr, "Unknown"},
{0x46, nullptr, "MapIoRegion"},
{0x47, nullptr, "UnmapIoRegion"},
{0x48, nullptr, "MapPhysicalMemoryUnsafe"},
{0x49, nullptr, "UnmapPhysicalMemoryUnsafe"},
{0x4A, nullptr, "SetUnsafeLimit"},
@@ -2864,7 +2864,7 @@ static const FunctionDef SVC_Table_64[] = {
{0x6B, nullptr, "WriteDebugProcessMemory"},
{0x6C, nullptr, "SetHardwareBreakPoint"},
{0x6D, nullptr, "GetDebugThreadParam"},
{0x6E, nullptr, "Unknown"},
{0x6E, nullptr, "Unknown6E"},
{0x6F, nullptr, "GetSystemInfo"},
{0x70, nullptr, "CreatePort"},
{0x71, nullptr, "ManageNamedPort"},

View File

@@ -91,6 +91,8 @@ public:
{4, &DebugMonitor::GetApplicationProcessId, "GetApplicationProcessId"},
{5, nullptr, "HookToCreateApplicationProgress"},
{6, nullptr, "ClearHook"},
{65000, &DebugMonitor::AtmosphereGetProcessInfo, "AtmosphereGetProcessInfo"},
{65001, nullptr, "AtmosphereGetCurrentLimitInfo"},
};
// clang-format on
@@ -125,6 +127,49 @@ private:
GetApplicationPidGeneric(ctx, kernel.GetProcessList());
}
void AtmosphereGetProcessInfo(Kernel::HLERequestContext& ctx) {
// https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/pm/source/impl/pm_process_manager.cpp#L614
// This implementation is incomplete; only a handle to the process is returned.
IPC::RequestParser rp{ctx};
const auto pid = rp.PopRaw<u64>();
LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) {
return proc->GetProcessID() == pid;
});
if (!process.has_value()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultProcessNotFound);
return;
}
struct ProgramLocation {
u64 program_id;
u8 storage_id;
};
static_assert(sizeof(ProgramLocation) == 0x10, "ProgramLocation has an invalid size");
struct OverrideStatus {
u64 keys_held;
u64 flags;
};
static_assert(sizeof(OverrideStatus) == 0x10, "OverrideStatus has an invalid size");
OverrideStatus override_status{};
ProgramLocation program_location{
.program_id = (*process)->GetProgramID(),
.storage_id = 0,
};
IPC::ResponseBuilder rb{ctx, 10, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(*process);
rb.PushRaw(program_location);
rb.PushRaw(override_status);
}
const Kernel::KernelCore& kernel;
};

View File

@@ -181,11 +181,10 @@ public:
case SDL_JOYSTICK_POWER_EMPTY:
return BatteryLevel::Empty;
case SDL_JOYSTICK_POWER_LOW:
return BatteryLevel::Critical;
case SDL_JOYSTICK_POWER_MEDIUM:
return BatteryLevel::Low;
case SDL_JOYSTICK_POWER_FULL:
case SDL_JOYSTICK_POWER_MEDIUM:
return BatteryLevel::Medium;
case SDL_JOYSTICK_POWER_FULL:
case SDL_JOYSTICK_POWER_MAX:
return BatteryLevel::Full;
case SDL_JOYSTICK_POWER_UNKNOWN:

View File

@@ -257,7 +257,7 @@ void QtControllerSelectorDialog::LoadConfiguration() {
}
void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
ConfigureVibration dialog(this);
ConfigureVibration dialog(this, system.HIDCore());
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint);

View File

@@ -164,7 +164,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
});
connect(ui->vibrationButton, &QPushButton::clicked,
[this] { CallConfigureDialog<ConfigureVibration>(*this); });
[this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); });
connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);

View File

@@ -70,7 +70,6 @@ void PlayerControlPreview::UpdateColors() {
colors.slider_arrow = QColor(14, 15, 18);
colors.font2 = QColor(255, 255, 255);
colors.indicator = QColor(170, 238, 255);
colors.indicator2 = QColor(100, 255, 100);
colors.deadzone = QColor(204, 136, 136);
colors.slider_button = colors.button;
}
@@ -88,7 +87,6 @@ void PlayerControlPreview::UpdateColors() {
colors.slider_arrow = QColor(65, 68, 73);
colors.font2 = QColor(0, 0, 0);
colors.indicator = QColor(0, 0, 200);
colors.indicator2 = QColor(0, 150, 0);
colors.deadzone = QColor(170, 0, 0);
colors.slider_button = QColor(153, 149, 149);
}
@@ -101,6 +99,8 @@ void PlayerControlPreview::UpdateColors() {
colors.font = QColor(255, 255, 255);
colors.led_on = QColor(255, 255, 0);
colors.led_off = QColor(170, 238, 255);
colors.indicator2 = QColor(59, 165, 93);
colors.charging = QColor(250, 168, 26);
colors.left = colors.primary;
colors.right = colors.primary;
@@ -357,7 +357,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)
DrawCircle(p, center + QPoint(26, 71), 5);
// Draw battery
DrawBattery(p, center + QPoint(-170, -140),
DrawBattery(p, center + QPoint(-160, -140),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
}
@@ -484,7 +484,7 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center
DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
// Draw battery
DrawBattery(p, center + QPoint(110, -140),
DrawBattery(p, center + QPoint(120, -140),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
}
@@ -621,9 +621,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)
DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
// Draw battery
DrawBattery(p, center + QPoint(-100, -160),
DrawBattery(p, center + QPoint(-200, -10),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
DrawBattery(p, center + QPoint(40, -160),
DrawBattery(p, center + QPoint(160, -10),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
}
@@ -694,12 +694,12 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
// ZL and ZR buttons
p.setPen(colors.outline);
DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]);
DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);
p.setPen(colors.transparent);
p.setBrush(colors.font);
DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f);
DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);
// Minus and Plus button
p.setPen(colors.outline);
@@ -725,9 +725,9 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
// Draw battery
DrawBattery(p, center + QPoint(-200, 110),
DrawBattery(p, center + QPoint(-188, 95),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
DrawBattery(p, center + QPoint(130, 110),
DrawBattery(p, center + QPoint(150, 95),
battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);
}
@@ -781,12 +781,12 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
// ZL and ZR buttons
p.setPen(colors.outline);
DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]);
DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);
p.setPen(colors.transparent);
p.setBrush(colors.font);
DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f);
DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);
// Minus and Plus buttons
p.setPen(colors.outline);
@@ -818,7 +818,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
// Draw battery
DrawBattery(p, center + QPoint(-30, -160),
DrawBattery(p, center + QPoint(-20, -160),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
}
@@ -875,7 +875,7 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
// Draw battery
DrawBattery(p, center + QPoint(-30, -165),
DrawBattery(p, center + QPoint(-20, 110),
battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);
}
@@ -1030,6 +1030,10 @@ constexpr std::array<float, 30 * 2> symbol_c = {
-2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f,
};
constexpr std::array<float, 6 * 2> symbol_charging = {
6.5f, -1.0f, 1.0f, -1.0f, 1.0f, -3.0f, -6.5f, 1.0f, -1.0f, 1.0f, -1.0f, 3.0f,
};
constexpr std::array<float, 12 * 2> house = {
-1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f,
0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f,
@@ -2674,36 +2678,43 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,
if (battery == Common::Input::BatteryLevel::None) {
return;
}
p.setPen(colors.outline);
// Draw outline
p.setPen(QPen(colors.button, 5));
p.setBrush(colors.transparent);
p.drawRect(center.x(), center.y(), 56, 20);
p.drawRect(center.x() + 56, center.y() + 6, 3, 8);
p.setBrush(colors.deadzone);
p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
p.setPen(QPen(colors.button, 3));
p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
// Draw Battery shape
p.setPen(QPen(colors.indicator2, 3));
p.setBrush(colors.transparent);
p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2);
p.setPen(QPen(colors.indicator2, 1));
p.setBrush(colors.indicator2);
p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);
switch (battery) {
case Common::Input::BatteryLevel::Charging:
p.setBrush(colors.indicator2);
p.drawText(center + QPoint(2, 14), tr("Charging"));
p.drawRect(center.x(), center.y(), 34, 16);
p.setPen(colors.slider);
p.setBrush(colors.charging);
DrawSymbol(p, center + QPointF(17.0f, 8.0f), Symbol::Charging, 2.1f);
break;
case Common::Input::BatteryLevel::Full:
p.drawRect(center.x() + 42, center.y(), 14, 20);
p.drawRect(center.x() + 28, center.y(), 14, 20);
p.drawRect(center.x() + 14, center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 34, 16);
break;
case Common::Input::BatteryLevel::Medium:
p.drawRect(center.x() + 28, center.y(), 14, 20);
p.drawRect(center.x() + 14, center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 25, 16);
break;
case Common::Input::BatteryLevel::Low:
p.drawRect(center.x() + 14, center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 17, 16);
break;
case Common::Input::BatteryLevel::Critical:
p.drawRect(center.x(), center.y(), 14, 20);
p.drawRect(center.x(), center.y(), 6, 16);
break;
case Common::Input::BatteryLevel::Empty:
p.drawRect(center.x(), center.y(), 5, 20);
p.drawRect(center.x(), center.y(), 3, 16);
break;
default:
break;
@@ -2724,6 +2735,7 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol
std::array<QPointF, symbol_sl.size() / 2> sl_icon;
std::array<QPointF, symbol_zr.size() / 2> zr_icon;
std::array<QPointF, symbol_sr.size() / 2> sr_icon;
std::array<QPointF, symbol_charging.size() / 2> charging_icon;
switch (symbol) {
case Symbol::House:
for (std::size_t point = 0; point < house.size() / 2; ++point) {
@@ -2809,6 +2821,13 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol
}
p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));
break;
case Symbol::Charging:
for (std::size_t point = 0; point < symbol_charging.size() / 2; ++point) {
charging_icon[point] = center + QPointF(symbol_charging[point * 2] * icon_size,
symbol_charging[point * 2 + 1] * icon_size);
}
p.drawPolygon(charging_icon.data(), static_cast<int>(charging_icon.size()));
break;
}
}

View File

@@ -72,6 +72,7 @@ private:
ZL,
ZR,
SR,
Charging,
};
struct ColorMapping {
@@ -94,6 +95,7 @@ private:
QColor slider_button{};
QColor slider_arrow{};
QColor deadzone{};
QColor charging{};
};
void UpdateColors();

View File

@@ -9,11 +9,14 @@
#include "common/param_package.h"
#include "common/settings.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
#include "ui_configure_vibration.h"
#include "yuzu/configuration/configure_vibration.h"
ConfigureVibration::ConfigureVibration(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) {
ConfigureVibration::ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()), hid_core{hid_core_} {
ui->setupUi(this);
vibration_groupboxes = {
@@ -31,6 +34,13 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
const auto& players = Settings::values.players.GetValue();
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
auto controller = hid_core.GetEmulatedControllerByIndex(i);
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this,
i](Core::HID::ControllerTriggerType type) { VibrateController(type, i); },
.is_npad_service = false,
};
controller_callback_key[i] = controller->SetCallback(engine_callback);
vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);
vibration_spinboxes[i]->setValue(players[i].vibration_strength);
}
@@ -45,7 +55,14 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)
RetranslateUI();
}
ConfigureVibration::~ConfigureVibration() = default;
ConfigureVibration::~ConfigureVibration() {
StopVibrations();
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
auto controller = hid_core.GetEmulatedControllerByIndex(i);
controller->DeleteCallback(controller_callback_key[i]);
}
};
void ConfigureVibration::ApplyConfiguration() {
auto& players = Settings::values.players.GetValue();
@@ -70,3 +87,54 @@ void ConfigureVibration::changeEvent(QEvent* event) {
void ConfigureVibration::RetranslateUI() {
ui->retranslateUi(this);
}
void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type,
std::size_t player_index) {
if (type != Core::HID::ControllerTriggerType::Button) {
return;
}
auto& player = Settings::values.players.GetValue()[player_index];
auto controller = hid_core.GetEmulatedControllerByIndex(player_index);
const int vibration_strenght = vibration_spinboxes[player_index]->value();
const auto& buttons = controller->GetButtonsValues();
bool button_is_pressed = false;
for (std::size_t i = 0; i < buttons.size(); ++i) {
if (buttons[i].value) {
button_is_pressed = true;
break;
}
}
if (!button_is_pressed) {
StopVibrations();
return;
}
const int old_vibration_enabled = player.vibration_enabled;
const bool old_vibration_strenght = player.vibration_strength;
player.vibration_enabled = true;
player.vibration_strength = vibration_strenght;
const Core::HID::VibrationValue vibration{
.low_amplitude = 1.0f,
.low_frequency = 160.0f,
.high_amplitude = 1.0f,
.high_frequency = 320.0f,
};
controller->SetVibration(0, vibration);
controller->SetVibration(1, vibration);
// Restore previous values
player.vibration_enabled = old_vibration_enabled;
player.vibration_strength = old_vibration_strenght;
}
void ConfigureVibration::StopVibrations() {
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
auto controller = hid_core.GetEmulatedControllerByIndex(i);
controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE);
controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE);
}
}

View File

@@ -15,11 +15,16 @@ namespace Ui {
class ConfigureVibration;
}
namespace Core::HID {
enum class ControllerTriggerType;
class HIDCore;
} // namespace Core::HID
class ConfigureVibration : public QDialog {
Q_OBJECT
public:
explicit ConfigureVibration(QWidget* parent);
explicit ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_);
~ConfigureVibration() override;
void ApplyConfiguration();
@@ -27,14 +32,21 @@ public:
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
void VibrateController(Core::HID::ControllerTriggerType type, std::size_t player_index);
void StopVibrations();
std::unique_ptr<Ui::ConfigureVibration> ui;
static constexpr std::size_t NUM_PLAYERS = 8;
// Groupboxes encapsulating the vibration strength spinbox.
/// Groupboxes encapsulating the vibration strength spinbox.
std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes;
// Spinboxes representing the vibration strength percentage.
/// Spinboxes representing the vibration strength percentage.
std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes;
/// Callback index to stop the controllers events
std::array<int, NUM_PLAYERS> controller_callback_key;
Core::HID::HIDCore& hid_core;
};

View File

@@ -17,6 +17,13 @@
<string notr="true"/>
</property>
<layout class="QVBoxLayout">
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="label_1">
<property name="text">
<string>Press any controller button to vibrate the controller.</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationStrengthGroup">
<property name="title">

View File

@@ -1052,8 +1052,10 @@ void GMainWindow::SetDefaultUIGeometry() {
}
void GMainWindow::RestoreUIState() {
setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);
restoreGeometry(UISettings::values.geometry);
restoreState(UISettings::values.state);
render_window->setWindowFlags(render_window->windowFlags() & ~Qt::FramelessWindowHint);
render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
#if MICROPROFILE_ENABLED
microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);

View File

@@ -66,6 +66,11 @@ static const std::array<int, Settings::NativeButton::NumButtons> default_buttons
SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
};
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions = {
SDL_SCANCODE_7,
SDL_SCANCODE_8,
};
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs{{
{
SDL_SCANCODE_UP,
@@ -102,27 +107,42 @@ void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>&
void Config::ReadValues() {
// Controls
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
auto& player = Settings::values.players.GetValue()[p];
const auto group = fmt::format("ControlsP{}", p);
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
Settings::values.players.GetValue()[p].buttons[i] =
player.buttons[i] =
sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
if (Settings::values.players.GetValue()[p].buttons[i].empty())
Settings::values.players.GetValue()[p].buttons[i] = default_param;
if (player.buttons[i].empty()) {
player.buttons[i] = default_param;
}
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
Settings::values.players.GetValue()[p].analogs[i] =
player.analogs[i] =
sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
if (Settings::values.players.GetValue()[p].analogs[i].empty())
Settings::values.players.GetValue()[p].analogs[i] = default_param;
if (player.analogs[i].empty()) {
player.analogs[i] = default_param;
}
}
Settings::values.players.GetValue()[p].connected =
sdl2_config->GetBoolean(group, "connected", false);
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_motions[i]);
auto& player_motions = player.motions[i];
player_motions =
sdl2_config->Get(group, Settings::NativeMotion::mapping[i], default_param);
if (player_motions.empty()) {
player_motions = default_param;
}
}
player.connected = sdl2_config->GetBoolean(group, "connected", false);
}
ReadSetting("ControlsGeneral", Settings::values.mouse_enabled);