Compare commits

...

41 Commits

Author SHA1 Message Date
Kyle K 017a18f42e Logging: Report Post Windows 10 2004 versions, like Windows 11
Qt5 and Qt6 don't really do a good job of reporting Windows versions past the 2004 version.

Current: Windows 10 Version 2009
This Patch: Windows 10 Version 21H1 (Build 19043.1706)
Also: Windows 11 Version 21H2 (Build 22000.675)

Fixes: #8362
2022-05-28 20:48:19 -07:00
Mai M 8a858c2623 Merge pull request #8385 from lat9nq/just-subsys-win
yuzu-qt: Call -Wl,--subsystem,windows directly
2022-05-28 14:30:15 -04:00
lat9nq 6e12eb80a0 yuzu-qt: Call -Wl,--subsystem,windows directly
-mwindows doesn't work with Clang. tpoechtrager/wclang resolves this by
just using MinGW-GCC to link the executable, however this prevents us
from using LLVM-exclusive tools when building yuzu.

Solution is to send the linker argument we need from -mwindows directly
to the linker.
From https://gcc-help.gcc.gnu.narkive.com/FogklN5J/gcc-wl-subsystem-windows-mwindows-options
2022-05-28 04:07:46 -04:00
bunnei d879741ec6 Merge pull request #8374 from german77/asnycvibrations
input_common: Make vibration request async
2022-05-28 00:55:53 -07:00
bunnei 439e621674 Merge pull request #8372 from german77/touch
input_common: touch: Rewrite touch driver to support multiple touch points
2022-05-27 12:16:03 -07:00
Mai M b01541f4e4 Merge pull request #8381 from lat9nq/path-util-pointer-bool
path_util: Resolve `-Wpointer-bool-conversion` warning
2022-05-26 19:20:47 -04:00
lat9nq 0e5a6676c3 path_util: Resolve -Wpointer-bool-conversion warning
Clang (rightfully) warns that we are checking for the existence of
pointer to something just allocated on the stack, which is always true.

Instead, check whether GetModuleFileNameW failed.

Co-authored-by: Mai M <mathew1800@gmail.com>
2022-05-26 19:01:26 -04:00
bunnei a9beb4746e Merge pull request #8379 from lat9nq/amd-push-desc-workaround
vulkan_device: Block AMDVLK's VK_KHR_push_descriptor
2022-05-25 13:07:39 -07:00
bunnei 79352ee9d5 Merge pull request #8369 from lat9nq/amd-wmel-workaround
vulkan_device: Workaround extension bug
2022-05-25 13:07:28 -07:00
lat9nq 3a8c2ae328 vulkan_device: Workaround extension bug
A bug occurs in yuzu when VK_KHR_workgroup_memory_explicit_layout is
available but 16-bit integers are not supported in the host driver.

Disable usage of the extension when this case arises.
2022-05-25 01:22:15 -04:00
lat9nq 7f53cd1e96 vulkan_device: Block AMDVLK's VK_KHR_push_descriptor
Recent AMD Vulkan drivers (22.5.2 or 2.0.226 for specifically Vulkan)
have a broken VK_KHR_push_descriptor implementation that causes a crash
in yuzu. Disable it for the time being.
2022-05-25 01:17:48 -04:00
bunnei 4118aad491 Merge pull request #8311 from asLody/fix-stencil-faces
vk_rasterizer: fix stencil test when two faces are disabled
2022-05-24 18:37:31 -07:00
Narr the Reg bf948b5790 input_common: Make vibration request async 2022-05-23 12:25:02 -05:00
german77 c82806f9cb input_common: touch: Rewrite touch driver to support multiple touch points 2022-05-23 11:01:14 -05:00
liamwhite 4eb7f6c044 Merge pull request #8342 from lat9nq/clang-latest-stdc++
general: Use Common::U16StringFromBuffer in place of QString::toStdU16String
2022-05-20 23:35:10 -04:00
Mai M b57df1dcb9 Merge pull request #8351 from abouvier/patch-2
video_core: Support new VkResult
2022-05-17 14:10:00 -04:00
Alexandre Bouvier 020982508d video_core: Support new VkResult 2022-05-17 17:37:10 +02:00
lat9nq 5035df27c3 qt_software_keyboard: Address review feedback
Use auto and a more descriptive variable name.

Secondly, fix some C++ misconceptions or constructing too many objects.

Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: Lioncash <mathew1800@gmail.com>
2022-05-16 14:44:01 -04:00
lat9nq 3ca3254b9f main: Use Common::U16StringFromBuffer
See ffd3afcf2
2022-05-15 18:09:19 -04:00
lat9nq f7908eebb9 qt_software_keyboard: Use Common::U16StringFromBuffer
See ffd3afcf2
2022-05-15 18:08:08 -04:00
lat9nq ffd3afcf2f string_util: Add U16StringFromBuffer
Qt's QString::toStdU16String doesn't work when compiling against the
latest libstdc++, at least when using Clang. This function effectively
does the same thing as the aforementioned one.
2022-05-15 18:06:33 -04:00
Mai M 5808e76fae Merge pull request #8336 from abouvier/unspirv
sirit: Allow using system spirv-headers
2022-05-15 09:24:05 -04:00
Mai M 5c20373db3 Merge pull request #8337 from lioncash/fmt
general: Avoid ambiguous format_to compilation errors
2022-05-14 18:51:23 -04:00
Lioncash f981e90af3 general: Avoid ambiguous format_to compilation errors
Ensures that we're using the fmt version of format_to.

These are also the only three outliers. All of the other formatters we
have are properly qualified.
2022-05-14 16:48:34 -04:00
Alexandre Bouvier 55b0dda57c sirit: Allow using system spirv-headers 2022-05-14 22:03:23 +02:00
Morph 0b9ef3c0b8 Merge pull request #8308 from german77/disablesix
service: hid: Disable correctly motion input
2022-05-11 17:51:54 -04:00
Morph 2fb6df3fe9 Merge pull request #8314 from liamwhite/gl-flip-2
OpenGL: interpret face flips according to GL NDC
2022-05-11 17:51:18 -04:00
Morph dca63391b6 Merge pull request #8313 from liamwhite/dma-bpp
maxwell_dma: fix bytes_per_pixel
2022-05-11 17:51:02 -04:00
Morph c2b583c911 Merge pull request #8328 from liamwhite/macro-clear
video_core/macro: clear code on upload address assignment
2022-05-11 17:49:25 -04:00
Liam e7ba9fd7e1 maxwell_dma: use fallback if remapping is enabled 2022-05-10 19:26:48 -04:00
Liam e158951695 video_core/macro: clear code on upload address assignment 2022-05-10 17:07:21 -04:00
Mai M f345ffdc0f Merge pull request #8325 from zhaobot/tx-update-20220509164742
Update translations (2022-05-09)
2022-05-09 18:10:34 -04:00
The yuzu Community 26e5bc6082 Update translations (2022-05-09) 2022-05-09 16:48:01 +00:00
Mai M 2123594ce2 Merge pull request #8320 from liamwhite/macro-dump
video_core/macro: Add option to dump macros
2022-05-08 22:56:01 -04:00
Fernando Sahmkow 5562ae9cc5 VideoCore: Add option to dump the macros.
Co-Authored-By: liamwhite <liamwhite@users.noreply.github.com>
2022-05-08 21:37:34 -04:00
Mai M 4087f1d10f Merge pull request #8319 from liamwhite/macro-warn
video_core/macro_jit_x64: warn on invalid parameter access
2022-05-08 04:58:33 -04:00
Liam b317f54f22 OpenGL: implement face flips according to NDC 2022-05-06 20:05:21 -04:00
Liam 4f1a2c2562 maxwell_dma: fix bytes per pixel 2022-05-06 18:18:00 -04:00
Narr the Reg babd580c64 service: hid: Fix motion refresh rate 2022-05-06 11:13:49 -05:00
german77 7eb0992d2c service: hid: Disable correctly motion input 2022-05-06 11:13:48 -05:00
Lody 535bc61b4c vk_rasterizer: fix stencil test when two faces are disabled 2022-05-06 14:47:55 +08:00
59 changed files with 16427 additions and 13174 deletions
+676 -547
View File
File diff suppressed because it is too large Load Diff
+681 -552
View File
File diff suppressed because it is too large Load Diff
+676 -547
View File
File diff suppressed because it is too large Load Diff
+687 -550
View File
File diff suppressed because it is too large Load Diff
+732 -603
View File
File diff suppressed because it is too large Load Diff
+679 -544
View File
File diff suppressed because it is too large Load Diff
+679 -549
View File
File diff suppressed because it is too large Load Diff
+693 -561
View File
File diff suppressed because it is too large Load Diff
+681 -552
View File
File diff suppressed because it is too large Load Diff
+679 -550
View File
File diff suppressed because it is too large Load Diff
+721 -569
View File
File diff suppressed because it is too large Load Diff
+682 -553
View File
File diff suppressed because it is too large Load Diff
+680 -551
View File
File diff suppressed because it is too large Load Diff
+679 -550
View File
File diff suppressed because it is too large Load Diff
+674 -539
View File
File diff suppressed because it is too large Load Diff
+678 -543
View File
File diff suppressed because it is too large Load Diff
+985 -840
View File
File diff suppressed because it is too large Load Diff
+679 -550
View File
File diff suppressed because it is too large Load Diff
+678 -549
View File
File diff suppressed because it is too large Load Diff
+679 -550
View File
File diff suppressed because it is too large Load Diff
+679 -550
View File
File diff suppressed because it is too large Load Diff
+680 -545
View File
File diff suppressed because it is too large Load Diff
+678 -543
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -232,9 +232,7 @@ void SetYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
fs::path GetExeDirectory() {
wchar_t exe_path[MAX_PATH];
GetModuleFileNameW(nullptr, exe_path, MAX_PATH);
if (!exe_path) {
if (GetModuleFileNameW(nullptr, exe_path, MAX_PATH) == 0) {
LOG_ERROR(Common_Filesystem,
"Failed to get the path to the executable of the current process");
}
+1
View File
@@ -72,6 +72,7 @@ enum class PollingError {
enum class VibrationAmplificationType {
Linear,
Exponential,
Test,
};
// Analog properties for calibration
+1
View File
@@ -606,6 +606,7 @@ struct Values {
BasicSetting<bool> dump_exefs{false, "dump_exefs"};
BasicSetting<bool> dump_nso{false, "dump_nso"};
BasicSetting<bool> dump_shaders{false, "dump_shaders"};
BasicSetting<bool> dump_macros{false, "dump_macros"};
BasicSetting<bool> enable_fs_access_log{false, "enable_fs_access_log"};
BasicSetting<bool> reporting_services{false, "reporting_services"};
BasicSetting<bool> quest_flag{false, "quest_flag"};
+4
View File
@@ -178,6 +178,10 @@ std::wstring UTF8ToUTF16W(const std::string& input) {
#endif
std::u16string U16StringFromBuffer(const u16* input, std::size_t length) {
return std::u16string(reinterpret_cast<const char16_t*>(input), length);
}
std::string StringFromFixedZeroTerminatedBuffer(std::string_view buffer, std::size_t max_len) {
std::size_t len = 0;
while (len < buffer.length() && len < max_len && buffer[len] != '\0') {
+2
View File
@@ -44,6 +44,8 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
#endif
[[nodiscard]] std::u16string U16StringFromBuffer(const u16* input, std::size_t length);
/**
* Compares the string defined by the range [`begin`, `end`) to the null-terminated C-string
* `other` for equality.
+1 -1
View File
@@ -20,7 +20,7 @@ struct fmt::formatter<Dynarmic::A32::CoprocReg> {
}
template <typename FormatContext>
auto format(const Dynarmic::A32::CoprocReg& reg, FormatContext& ctx) {
return format_to(ctx.out(), "cp{}", static_cast<size_t>(reg));
return fmt::format_to(ctx.out(), "cp{}", static_cast<size_t>(reg));
}
};
+11 -4
View File
@@ -27,12 +27,19 @@ void EmulatedConsole::SetTouchParams() {
// We can't use mouse as touch if native mouse is enabled
touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
}
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
touch_params[index++] =
Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};
Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"};
touch_params[index++] =
Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"};
Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"};
touch_params[index++] =
Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"};
touch_params[index++] =
Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"};
touch_params[index++] =
Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"};
touch_params[index++] =
Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"};
const auto button_index =
static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
+29 -5
View File
@@ -884,18 +884,42 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
}
bool EmulatedController::TestVibration(std::size_t device_index) {
static constexpr VibrationValue test_vibration = {
if (device_index >= output_devices.size()) {
return false;
}
if (!output_devices[device_index]) {
return false;
}
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
if (!player.vibration_enabled) {
return false;
}
const Common::Input::VibrationStatus test_vibration = {
.low_amplitude = 0.001f,
.low_frequency = 160.0f,
.low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency,
.high_amplitude = 0.001f,
.high_frequency = 320.0f,
.high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
.type = Common::Input::VibrationAmplificationType::Test,
};
const Common::Input::VibrationStatus zero_vibration = {
.low_amplitude = DEFAULT_VIBRATION_VALUE.low_amplitude,
.low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency,
.high_amplitude = DEFAULT_VIBRATION_VALUE.high_amplitude,
.high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
.type = Common::Input::VibrationAmplificationType::Test,
};
// Send a slight vibration to test for rumble support
SetVibration(device_index, test_vibration);
output_devices[device_index]->SetVibration(test_vibration);
// Stop any vibration and return the result
return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
return output_devices[device_index]->SetVibration(zero_vibration) ==
Common::Input::VibrationError::None;
}
bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {
+4
View File
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <random>
#include "common/input.h"
@@ -196,6 +197,9 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
x = std::clamp(x, 0.0f, 1.0f);
y = std::clamp(y, 0.0f, 1.0f);
// Limit id to maximum number of fingers
status.id = std::clamp(status.id, 0, 16);
if (status.pressed.inverted) {
status.pressed.value = !status.pressed.value;
}
+46 -50
View File
@@ -3,7 +3,9 @@
#include <algorithm>
#include <array>
#include <chrono>
#include <cstring>
#include "common/assert.h"
#include "common/bit_field.h"
#include "common/common_types.h"
@@ -529,6 +531,14 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
// Clear previous state
sixaxis_fullkey_state = {};
sixaxis_handheld_state = {};
sixaxis_dual_left_state = {};
sixaxis_dual_right_state = {};
sixaxis_left_lifo_state = {};
sixaxis_right_lifo_state = {};
if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
controller.sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_state.size(); ++e) {
@@ -537,69 +547,55 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
}
}
const auto set_motion_state = [&](SixAxisSensorState& state,
const Core::HID::ControllerMotion& hid_state) {
using namespace std::literals::chrono_literals;
static constexpr SixAxisSensorState default_motion_state = {
.delta_time = std::chrono::nanoseconds(5ms).count(),
.accel = {0, 0, -1.0f},
.orientation =
{
Common::Vec3f{1.0f, 0, 0},
Common::Vec3f{0, 1.0f, 0},
Common::Vec3f{0, 0, 1.0f},
},
.attribute = {1},
};
if (!controller.sixaxis_sensor_enabled) {
state = default_motion_state;
return;
}
if (!Settings::values.motion_enabled.GetValue()) {
state = default_motion_state;
return;
}
state.attribute.is_connected.Assign(1);
state.delta_time = std::chrono::nanoseconds(5ms).count();
state.accel = hid_state.accel;
state.gyro = hid_state.gyro;
state.rotation = hid_state.rotation;
state.orientation = hid_state.orientation;
};
switch (controller_type) {
case Core::HID::NpadStyleIndex::None:
UNREACHABLE();
break;
case Core::HID::NpadStyleIndex::ProController:
sixaxis_fullkey_state.attribute.raw = 0;
if (controller.sixaxis_sensor_enabled) {
sixaxis_fullkey_state.attribute.is_connected.Assign(1);
sixaxis_fullkey_state.accel = motion_state[0].accel;
sixaxis_fullkey_state.gyro = motion_state[0].gyro;
sixaxis_fullkey_state.rotation = motion_state[0].rotation;
sixaxis_fullkey_state.orientation = motion_state[0].orientation;
}
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::Handheld:
sixaxis_handheld_state.attribute.raw = 0;
if (controller.sixaxis_sensor_enabled) {
sixaxis_handheld_state.attribute.is_connected.Assign(1);
sixaxis_handheld_state.accel = motion_state[0].accel;
sixaxis_handheld_state.gyro = motion_state[0].gyro;
sixaxis_handheld_state.rotation = motion_state[0].rotation;
sixaxis_handheld_state.orientation = motion_state[0].orientation;
}
set_motion_state(sixaxis_handheld_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconDual:
sixaxis_dual_left_state.attribute.raw = 0;
sixaxis_dual_right_state.attribute.raw = 0;
if (controller.sixaxis_sensor_enabled) {
// Set motion for the left joycon
sixaxis_dual_left_state.attribute.is_connected.Assign(1);
sixaxis_dual_left_state.accel = motion_state[0].accel;
sixaxis_dual_left_state.gyro = motion_state[0].gyro;
sixaxis_dual_left_state.rotation = motion_state[0].rotation;
sixaxis_dual_left_state.orientation = motion_state[0].orientation;
}
if (controller.sixaxis_sensor_enabled) {
// Set motion for the right joycon
sixaxis_dual_right_state.attribute.is_connected.Assign(1);
sixaxis_dual_right_state.accel = motion_state[1].accel;
sixaxis_dual_right_state.gyro = motion_state[1].gyro;
sixaxis_dual_right_state.rotation = motion_state[1].rotation;
sixaxis_dual_right_state.orientation = motion_state[1].orientation;
}
set_motion_state(sixaxis_dual_left_state, motion_state[0]);
set_motion_state(sixaxis_dual_right_state, motion_state[1]);
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
sixaxis_left_lifo_state.attribute.raw = 0;
if (controller.sixaxis_sensor_enabled) {
sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
sixaxis_left_lifo_state.accel = motion_state[0].accel;
sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
sixaxis_left_lifo_state.rotation = motion_state[0].rotation;
sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
}
set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
sixaxis_right_lifo_state.attribute.raw = 0;
if (controller.sixaxis_sensor_enabled) {
sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
sixaxis_right_lifo_state.accel = motion_state[1].accel;
sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
sixaxis_right_lifo_state.rotation = motion_state[1].rotation;
sixaxis_right_lifo_state.orientation = motion_state[1].orientation;
}
set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
break;
default:
break;
@@ -44,7 +44,6 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
for (std::size_t id = 0; id < MAX_FINGERS; id++) {
const auto& current_touch = touch_status[id];
auto& finger = fingers[id];
finger.position = current_touch.position;
finger.id = current_touch.id;
if (finger.attribute.start_touch) {
@@ -61,13 +60,18 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
if (!finger.pressed && current_touch.pressed) {
finger.attribute.start_touch.Assign(1);
finger.pressed = true;
finger.position = current_touch.position;
continue;
}
if (finger.pressed && !current_touch.pressed) {
finger.attribute.raw = 0;
finger.attribute.end_touch.Assign(1);
continue;
}
// Only update position if touch is not on a special frame
finger.position = current_touch.position;
}
std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers;
+1 -2
View File
@@ -37,8 +37,7 @@ namespace Service::HID {
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz)
constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
// TODO: Correct update rate for motion is 5ms. Check why some games don't behave at that speed
constexpr auto motion_update_ns = std::chrono::nanoseconds{10 * 1000 * 1000}; // (10ms, 100Hz)
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
IAppletResource::IAppletResource(Core::System& system_,
KernelHelpers::ServiceContext& service_context_)
+21 -2
View File
@@ -434,6 +434,7 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
using namespace std::chrono_literals;
while (initialized) {
SDL_PumpEvents();
SendVibrations();
std::this_thread::sleep_for(1ms);
}
});
@@ -531,13 +532,31 @@ Common::Input::VibrationError SDLDriver::SetRumble(
.type = Common::Input::VibrationAmplificationType::Exponential,
};
if (!joystick->RumblePlay(new_vibration)) {
return Common::Input::VibrationError::Unknown;
if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
if (!joystick->RumblePlay(new_vibration)) {
return Common::Input::VibrationError::Unknown;
}
return Common::Input::VibrationError::None;
}
vibration_queue.Push(VibrationRequest{
.identifier = identifier,
.vibration = new_vibration,
});
return Common::Input::VibrationError::None;
}
void SDLDriver::SendVibrations() {
while (!vibration_queue.Empty()) {
VibrationRequest request;
vibration_queue.Pop(request);
const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
static_cast<int>(request.identifier.port));
joystick->RumblePlay(request.vibration);
}
}
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
s32 axis, float value) const {
Common::ParamPackage params{};
+12
View File
@@ -12,6 +12,7 @@
#include <SDL.h>
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
#include "input_common/input_engine.h"
union SDL_Event;
@@ -64,12 +65,20 @@ public:
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
private:
struct VibrationRequest {
PadIdentifier identifier;
Common::Input::VibrationStatus vibration;
};
void InitJoystick(int joystick_index);
void CloseJoystick(SDL_Joystick* sdl_joystick);
/// Needs to be called before SDL_QuitSubSystem.
void CloseJoysticks();
/// Takes all vibrations from the queue and sends the command to the controller
void SendVibrations();
Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
float value = 0.1f) const;
Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid,
@@ -107,6 +116,9 @@ private:
/// Returns true if the button is on the left joycon
bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const;
/// Queue of vibration request to controllers
Common::SPSCQueue<VibrationRequest> vibration_queue;
/// Map of GUID of a list of corresponding virtual Joysticks
std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
std::mutex joystick_map_mutex;
+72 -17
View File
@@ -14,38 +14,93 @@ constexpr PadIdentifier identifier = {
TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(identifier);
ReleaseAllTouch();
}
void TouchScreen::TouchMoved(float x, float y, std::size_t finger) {
if (finger >= 16) {
void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) {
const auto index = GetIndexFromFingerId(finger_id);
if (!index) {
// Touch doesn't exist handle it as a new one
TouchPressed(x, y, finger_id);
return;
}
TouchPressed(x, y, finger);
const auto i = index.value();
fingers[i].is_active = true;
SetButton(identifier, static_cast<int>(i), true);
SetAxis(identifier, static_cast<int>(i * 2), x);
SetAxis(identifier, static_cast<int>(i * 2 + 1), y);
}
void TouchScreen::TouchPressed(float x, float y, std::size_t finger) {
if (finger >= 16) {
void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) {
if (GetIndexFromFingerId(finger_id)) {
// Touch already exist. Just update the data
TouchMoved(x, y, finger_id);
return;
}
SetButton(identifier, static_cast<int>(finger), true);
SetAxis(identifier, static_cast<int>(finger * 2), x);
SetAxis(identifier, static_cast<int>(finger * 2 + 1), y);
const auto index = GetNextFreeIndex();
if (!index) {
// No free entries. Ignore input
return;
}
const auto i = index.value();
fingers[i].is_enabled = true;
fingers[i].finger_id = finger_id;
TouchMoved(x, y, finger_id);
}
void TouchScreen::TouchReleased(std::size_t finger) {
if (finger >= 16) {
void TouchScreen::TouchReleased(std::size_t finger_id) {
const auto index = GetIndexFromFingerId(finger_id);
if (!index) {
return;
}
SetButton(identifier, static_cast<int>(finger), false);
SetAxis(identifier, static_cast<int>(finger * 2), 0.0f);
SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f);
const auto i = index.value();
fingers[i].is_enabled = false;
SetButton(identifier, static_cast<int>(i), false);
SetAxis(identifier, static_cast<int>(i * 2), 0.0f);
SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f);
}
std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const {
for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
const auto& finger = fingers[index];
if (!finger.is_enabled) {
continue;
}
if (finger.finger_id == finger_id) {
return index;
}
}
return std::nullopt;
}
std::optional<std::size_t> TouchScreen::GetNextFreeIndex() const {
for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
if (!fingers[index].is_enabled) {
return index;
}
}
return std::nullopt;
}
void TouchScreen::ClearActiveFlag() {
for (auto& finger : fingers) {
finger.is_active = false;
}
}
void TouchScreen::ReleaseInactiveTouch() {
for (const auto& finger : fingers) {
if (!finger.is_active) {
TouchReleased(finger.finger_id);
}
}
}
void TouchScreen::ReleaseAllTouch() {
for (int index = 0; index < 16; ++index) {
SetButton(identifier, index, false);
SetAxis(identifier, index * 2, 0.0f);
SetAxis(identifier, index * 2 + 1, 0.0f);
for (const auto& finger : fingers) {
if (finger.is_enabled) {
TouchReleased(finger.finger_id);
}
}
}
+38 -14
View File
@@ -3,41 +3,65 @@
#pragma once
#include <optional>
#include "input_common/input_engine.h"
namespace InputCommon {
/**
* A button device factory representing a keyboard. It receives keyboard events and forward them
* to all button devices it created.
* A touch device factory representing a touch screen. It receives touch events and forward them
* to all touch devices it created.
*/
class TouchScreen final : public InputEngine {
public:
explicit TouchScreen(std::string input_engine_);
/**
* Signals that mouse has moved.
* @param x the x-coordinate of the cursor
* @param y the y-coordinate of the cursor
* @param center_x the x-coordinate of the middle of the screen
* @param center_y the y-coordinate of the middle of the screen
* Signals that touch has moved and marks this touch point as active
* @param x new horizontal position
* @param y new vertical position
* @param finger_id of the touch point to be updated
*/
void TouchMoved(float x, float y, std::size_t finger);
void TouchMoved(float x, float y, std::size_t finger_id);
/**
* Sets the status of all buttons bound with the key to pressed
* @param key_code the code of the key to press
* Signals and creates a new touch point with this finger id
* @param x starting horizontal position
* @param y starting vertical position
* @param finger_id to be assigned to the new touch point
*/
void TouchPressed(float x, float y, std::size_t finger);
void TouchPressed(float x, float y, std::size_t finger_id);
/**
* Sets the status of all buttons bound with the key to released
* @param key_code the code of the key to release
* Signals and resets the touch point related to the this finger id
* @param finger_id to be released
*/
void TouchReleased(std::size_t finger);
void TouchReleased(std::size_t finger_id);
/// Resets the active flag for each touch point
void ClearActiveFlag();
/// Releases all touch that haven't been marked as active
void ReleaseInactiveTouch();
/// Resets all inputs to their initial value
void ReleaseAllTouch();
private:
static constexpr std::size_t MAX_FINGER_COUNT = 16;
struct TouchStatus {
std::size_t finger_id{};
bool is_enabled{};
bool is_active{};
};
std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const;
std::optional<std::size_t> GetNextFreeIndex() const;
std::array<TouchStatus, MAX_FINGER_COUNT> fingers{};
};
} // namespace InputCommon
+1 -1
View File
@@ -103,6 +103,6 @@ struct fmt::formatter<Shader::IR::Opcode> {
}
template <typename FormatContext>
auto format(const Shader::IR::Opcode& op, FormatContext& ctx) {
return format_to(ctx.out(), "{}", Shader::IR::NameOf(op));
return fmt::format_to(ctx.out(), "{}", Shader::IR::NameOf(op));
}
};
@@ -24,6 +24,6 @@ struct fmt::formatter<Shader::Maxwell::Opcode> {
}
template <typename FormatContext>
auto format(const Shader::Maxwell::Opcode& opcode, FormatContext& ctx) {
return format_to(ctx.out(), "{}", NameOf(opcode));
return fmt::format_to(ctx.out(), "{}", NameOf(opcode));
}
};
+2
View File
@@ -173,6 +173,8 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
case MAXWELL3D_REG_INDEX(shadow_ram_control):
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(nonshadow_argument);
return;
case MAXWELL3D_REG_INDEX(macros.upload_address):
return macro_engine->ClearCode(regs.macros.upload_address);
case MAXWELL3D_REG_INDEX(macros.data):
return macro_engine->AddCode(regs.macros.upload_address, argument);
case MAXWELL3D_REG_INDEX(macros.bind):
+6 -3
View File
@@ -134,7 +134,8 @@ void MaxwellDMA::CopyBlockLinearToPitch() {
// Deswizzle the input and copy it over.
UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0);
const u32 bytes_per_pixel = regs.pitch_out / regs.line_length_in;
const u32 bytes_per_pixel =
regs.launch_dma.remap_enable ? regs.pitch_out / regs.line_length_in : 1;
const Parameters& src_params = regs.src_params;
const u32 width = src_params.width;
const u32 height = src_params.height;
@@ -166,7 +167,8 @@ void MaxwellDMA::CopyPitchToBlockLinear() {
UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0);
const auto& dst_params = regs.dst_params;
const u32 bytes_per_pixel = regs.pitch_in / regs.line_length_in;
const u32 bytes_per_pixel =
regs.launch_dma.remap_enable ? regs.pitch_in / regs.line_length_in : 1;
const u32 width = dst_params.width;
const u32 height = dst_params.height;
const u32 depth = dst_params.depth;
@@ -210,7 +212,8 @@ void MaxwellDMA::CopyPitchToBlockLinear() {
}
void MaxwellDMA::FastCopyBlockLinearToPitch() {
const u32 bytes_per_pixel = regs.pitch_out / regs.line_length_in;
const u32 bytes_per_pixel =
regs.launch_dma.remap_enable ? regs.pitch_out / regs.line_length_in : 1;
const size_t src_size = GOB_SIZE;
const size_t dst_size = static_cast<size_t>(regs.pitch_out) * regs.line_count;
u32 pos_x = regs.src_params.origin.x;
+32
View File
@@ -2,11 +2,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <fstream>
#include <optional>
#include <span>
#include <boost/container_hash/hash.hpp>
#include "common/assert.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/settings.h"
#include "video_core/macro/macro.h"
#include "video_core/macro/macro_hle.h"
@@ -15,6 +19,23 @@
namespace Tegra {
static void Dump(u64 hash, std::span<const u32> code) {
const auto base_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)};
const auto macro_dir{base_dir / "macros"};
if (!Common::FS::CreateDir(base_dir) || !Common::FS::CreateDir(macro_dir)) {
LOG_ERROR(Common_Filesystem, "Failed to create macro dump directories");
return;
}
const auto name{macro_dir / fmt::format("{:016x}.macro", hash)};
std::fstream macro_file(name, std::ios::out | std::ios::binary);
if (!macro_file) {
LOG_ERROR(Common_Filesystem, "Unable to open or create file at {}",
Common::FS::PathToUTF8String(name));
return;
}
macro_file.write(reinterpret_cast<const char*>(code.data()), code.size_bytes());
}
MacroEngine::MacroEngine(Engines::Maxwell3D& maxwell3d)
: hle_macros{std::make_unique<Tegra::HLEMacro>(maxwell3d)} {}
@@ -24,6 +45,11 @@ void MacroEngine::AddCode(u32 method, u32 data) {
uploaded_macro_code[method].push_back(data);
}
void MacroEngine::ClearCode(u32 method) {
macro_cache.erase(method);
uploaded_macro_code.erase(method);
}
void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
auto compiled_macro = macro_cache.find(method);
if (compiled_macro != macro_cache.end()) {
@@ -54,6 +80,9 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
if (!mid_method.has_value()) {
cache_info.lle_program = Compile(macro_code->second);
cache_info.hash = boost::hash_value(macro_code->second);
if (Settings::values.dump_macros) {
Dump(cache_info.hash, macro_code->second);
}
} else {
const auto& macro_cached = uploaded_macro_code[mid_method.value()];
const auto rebased_method = method - mid_method.value();
@@ -63,6 +92,9 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
code.size() * sizeof(u32));
cache_info.hash = boost::hash_value(code);
cache_info.lle_program = Compile(code);
if (Settings::values.dump_macros) {
Dump(cache_info.hash, code);
}
}
if (auto hle_program = hle_macros->GetHLEProgram(cache_info.hash)) {
+3
View File
@@ -117,6 +117,9 @@ public:
// Store the uploaded macro code to compile them when they're called.
void AddCode(u32 method, u32 data);
// Clear the code associated with a method.
void ClearCode(u32 method);
// Compiles the macro if its not in the cache, and executes the compiled macro
void Execute(u32 method, const std::vector<u32>& parameters);
@@ -563,12 +563,11 @@ void RasterizerOpenGL::SyncViewport() {
flags[Dirty::FrontFace] = false;
GLenum mode = MaxwellToGL::FrontFace(regs.front_face);
bool flip_faces = false;
if (regs.screen_y_control.triangle_rast_flip != 0 &&
regs.viewport_transform[0].scale_y < 0.0f) {
bool flip_faces = true;
if (regs.screen_y_control.triangle_rast_flip != 0) {
flip_faces = !flip_faces;
}
if (regs.viewport_transform[0].scale_z < 0.0f) {
if (regs.viewport_transform[0].scale_y < 0.0f) {
flip_faces = !flip_faces;
}
if (flip_faces) {
@@ -784,8 +784,8 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
});
} else {
// Front face defines both faces
scheduler.Record([ref = regs.stencil_back_func_ref, write_mask = regs.stencil_back_mask,
test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) {
scheduler.Record([ref = regs.stencil_front_func_ref, write_mask = regs.stencil_front_mask,
test_mask = regs.stencil_front_func_mask](vk::CommandBuffer cmdbuf) {
cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref);
cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask);
cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask);
+17 -1
View File
@@ -566,7 +566,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
}
VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR workgroup_layout;
if (khr_workgroup_memory_explicit_layout) {
if (khr_workgroup_memory_explicit_layout && is_shader_int16_supported) {
workgroup_layout = {
.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR,
@@ -577,6 +577,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
.workgroupMemoryExplicitLayout16BitAccess = VK_TRUE,
};
SetNext(next, workgroup_layout);
} else if (khr_workgroup_memory_explicit_layout) {
// TODO(lat9nq): Find a proper fix for this
LOG_WARNING(Render_Vulkan, "Disabling VK_KHR_workgroup_memory_explicit_layout due to a "
"yuzu bug when host driver does not support 16-bit integers");
khr_workgroup_memory_explicit_layout = false;
}
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR executable_properties;
@@ -664,6 +669,17 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const bool is_amd =
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
if (is_amd) {
// TODO(lat9nq): Add an upper bound when AMD fixes their VK_KHR_push_descriptor
const bool has_broken_push_descriptor = VK_VERSION_MAJOR(properties.driverVersion) == 2 &&
VK_VERSION_MINOR(properties.driverVersion) == 0 &&
VK_VERSION_PATCH(properties.driverVersion) >= 226;
if (khr_push_descriptor && has_broken_push_descriptor) {
LOG_WARNING(
Render_Vulkan,
"Disabling AMD driver 2.0.226 and later from broken VK_KHR_push_descriptor");
khr_push_descriptor = false;
}
// AMD drivers need a higher amount of Sets per Pool in certain circunstances like in XC2.
sets_per_pool = 96;
// Disable VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT on AMD GCN4 and lower as it is broken.
@@ -325,6 +325,8 @@ const char* ToString(VkResult result) noexcept {
return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
case VkResult::VK_RESULT_MAX_ENUM:
return "VK_RESULT_MAX_ENUM";
case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT:
return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
}
return "Unknown";
}
+1 -1
View File
@@ -240,7 +240,7 @@ elseif(WIN32)
if(MSVC)
set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
elseif(MINGW)
set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-mwindows")
set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-Wl,--subsystem,windows")
endif()
endif()
+15 -14
View File
@@ -411,11 +411,11 @@ void QtSoftwareKeyboardDialog::ShowTextCheckDialog(
break;
}
auto text = ui->topOSK->currentIndex() == 1
? ui->text_edit_osk->toPlainText().toStdU16String()
: ui->line_edit_osk->text().toStdU16String();
const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText()
: ui->line_edit_osk->text();
auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size());
emit SubmitNormalText(SwkbdResult::Ok, std::move(text), true);
emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str), true);
break;
}
}
@@ -562,7 +562,7 @@ void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) {
return;
}
InlineTextInsertString(entered_text.toStdU16String());
InlineTextInsertString(Common::U16StringFromBuffer(entered_text.utf16(), entered_text.size()));
}
void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) {
@@ -1119,11 +1119,11 @@ void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button)
}
if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) {
auto text = ui->topOSK->currentIndex() == 1
? ui->text_edit_osk->toPlainText().toStdU16String()
: ui->line_edit_osk->text().toStdU16String();
const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText()
: ui->line_edit_osk->text();
auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size());
emit SubmitNormalText(SwkbdResult::Ok, std::move(text));
emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str));
return;
}
@@ -1189,7 +1189,8 @@ void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button)
return;
}
InlineTextInsertString(button->text().toStdU16String());
const auto button_text = button->text();
InlineTextInsertString(Common::U16StringFromBuffer(button_text.utf16(), button_text.size()));
// Revert the keyboard to lowercase if the shift key is active.
if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) {
@@ -1282,11 +1283,11 @@ void QtSoftwareKeyboardDialog::TranslateButtonPress(Core::HID::NpadButton button
if (is_inline) {
emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position);
} else {
auto text = ui->topOSK->currentIndex() == 1
? ui->text_edit_osk->toPlainText().toStdU16String()
: ui->line_edit_osk->text().toStdU16String();
const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText()
: ui->line_edit_osk->text();
auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size());
emit SubmitNormalText(SwkbdResult::Cancel, std::move(text));
emit SubmitNormalText(SwkbdResult::Cancel, std::move(text_str));
}
break;
case Core::HID::NpadButton::Y:
+9 -49
View File
@@ -772,65 +772,25 @@ void GRenderWindow::wheelEvent(QWheelEvent* event) {
void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
for (const auto& touch_point : touch_points) {
if (!TouchUpdate(touch_point)) {
TouchStart(touch_point);
}
const auto [x, y] = ScaleTouch(touch_point.pos());
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, touch_point.id());
}
}
void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) {
QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
input_subsystem->GetTouchScreen()->ClearActiveFlag();
for (const auto& touch_point : touch_points) {
if (!TouchUpdate(touch_point)) {
TouchStart(touch_point);
}
}
// Release all inactive points
for (std::size_t id = 0; id < touch_ids.size(); ++id) {
if (!TouchExist(touch_ids[id], touch_points)) {
touch_ids[id] = 0;
input_subsystem->GetTouchScreen()->TouchReleased(id);
}
const auto [x, y] = ScaleTouch(touch_point.pos());
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, touch_point.id());
}
input_subsystem->GetTouchScreen()->ReleaseInactiveTouch();
}
void GRenderWindow::TouchEndEvent() {
for (std::size_t id = 0; id < touch_ids.size(); ++id) {
if (touch_ids[id] != 0) {
touch_ids[id] = 0;
input_subsystem->GetTouchScreen()->TouchReleased(id);
}
}
}
void GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) {
for (std::size_t id = 0; id < touch_ids.size(); ++id) {
if (touch_ids[id] == 0) {
touch_ids[id] = touch_point.id() + 1;
const auto [x, y] = ScaleTouch(touch_point.pos());
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
}
}
}
bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) {
for (std::size_t id = 0; id < touch_ids.size(); ++id) {
if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) {
const auto [x, y] = ScaleTouch(touch_point.pos());
const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
return true;
}
}
return false;
}
bool GRenderWindow::TouchExist(std::size_t id,
const QList<QTouchEvent::TouchPoint>& touch_points) const {
return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) {
return id == static_cast<std::size_t>(point.id() + 1);
});
input_subsystem->GetTouchScreen()->ReleaseAllTouch();
}
bool GRenderWindow::event(QEvent* event) {
-6
View File
@@ -217,10 +217,6 @@ private:
void TouchUpdateEvent(const QTouchEvent* event);
void TouchEndEvent();
void TouchStart(const QTouchEvent::TouchPoint& touch_point);
bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point);
bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const;
void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
bool InitializeOpenGL();
@@ -246,8 +242,6 @@ private:
bool first_frame = false;
InputCommon::TasInput::TasState last_tas_state;
std::array<std::size_t, 16> touch_ids{};
Core::System& system;
protected:
@@ -53,6 +53,8 @@ void ConfigureDebug::SetConfiguration() {
ui->enable_nsight_aftermath->setChecked(Settings::values.enable_nsight_aftermath.GetValue());
ui->dump_shaders->setEnabled(runtime_lock);
ui->dump_shaders->setChecked(Settings::values.dump_shaders.GetValue());
ui->dump_macros->setEnabled(runtime_lock);
ui->dump_macros->setChecked(Settings::values.dump_macros.GetValue());
ui->disable_macro_jit->setEnabled(runtime_lock);
ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue());
ui->disable_loop_safety_checks->setEnabled(runtime_lock);
@@ -83,6 +85,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();
Settings::values.dump_shaders = ui->dump_shaders->isChecked();
Settings::values.dump_macros = ui->dump_macros->isChecked();
Settings::values.disable_shader_loop_safety_checks =
ui->disable_loop_safety_checks->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
+13
View File
@@ -118,6 +118,19 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="dump_macros">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>When checked, it will dump all the macro programs of the GPU</string>
</property>
<property name="text">
<string>Dump Maxwell Macros</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="disable_macro_jit">
<property name="enabled">
+30 -3
View File
@@ -198,6 +198,31 @@ static void RemoveCachedContents() {
Common::FS::RemoveDirRecursively(offline_system_data);
}
static QString PrettyProductName() {
#ifdef _WIN32
// After Windows 10 Version 2004, Microsoft decided to switch to a different notation: 20H2
// With that notation change they changed the registry key used to denote the current version
QSettings windows_registry(
QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
QSettings::NativeFormat);
const QString release_id = windows_registry.value(QStringLiteral("ReleaseId")).toString();
if (release_id == QStringLiteral("2009")) {
const u32 current_build = windows_registry.value(QStringLiteral("CurrentBuild")).toUInt();
const QString display_version =
windows_registry.value(QStringLiteral("DisplayVersion")).toString();
const u32 ubr = windows_registry.value(QStringLiteral("UBR")).toUInt();
u32 version = 10;
if (current_build >= 22000) {
version = 11;
}
return QStringLiteral("Windows %1 Version %2 (Build %3.%4)")
.arg(QString::number(version), display_version, QString::number(current_build),
QString::number(ubr));
}
#endif
return QSysInfo::prettyProductName();
}
GMainWindow::GMainWindow()
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
@@ -259,7 +284,7 @@ GMainWindow::GMainWindow()
}
LOG_INFO(Frontend, "Host CPU: {}", cpu_string);
#endif
LOG_INFO(Frontend, "Host OS: {}", QSysInfo::prettyProductName().toStdString());
LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString());
LOG_INFO(Frontend, "Host RAM: {:.2f} GiB",
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
@@ -1401,7 +1426,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success &&
type == StartGameType::Normal) {
// Load per game settings
const auto file_path = std::filesystem::path{filename.toStdU16String()};
const auto file_path =
std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())};
const auto config_file_name = title_id == 0
? Common::FS::PathToUTF8String(file_path.filename())
: fmt::format("{:016X}", title_id);
@@ -1482,7 +1508,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
}
if (res != Loader::ResultStatus::Success || title_name.empty()) {
title_name = Common::FS::PathToUTF8String(
std::filesystem::path{filename.toStdU16String()}.filename());
std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())}
.filename());
}
const bool is_64bit = system->Kernel().CurrentProcess()->Is64BitProcess();
const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)");
+1 -1
View File
@@ -93,7 +93,7 @@ void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) {
}
void EmuWindow_SDL2::OnFingerUp() {
input_subsystem->GetTouchScreen()->TouchReleased(0);
input_subsystem->GetTouchScreen()->ReleaseAllTouch();
}
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {