summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.cpp31
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h2
-rw-r--r--src/core/hid/emulated_controller.cpp30
-rw-r--r--src/core/hid/emulated_controller.h7
-rw-r--r--src/core/hid/hid_types.h12
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp77
-rw-r--r--src/yuzu/CMakeLists.txt14
-rw-r--r--src/yuzu/configuration/configure_ui.cpp1
-rw-r--r--src/yuzu/main.cpp14
11 files changed, 163 insertions, 37 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 2e0e16b6e..1638bc41d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -144,7 +144,7 @@ public:
u64 GetTicksRemaining() override {
if (parent.uses_wall_clock) {
- if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) {
+ if (!IsInterrupted()) {
return minimum_run_cycles;
}
return 0U;
@@ -174,6 +174,10 @@ public:
parent.jit.load()->HaltExecution(hr);
}
+ bool IsInterrupted() {
+ return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
+ }
+
ARM_Dynarmic_32& parent;
Core::Memory::Memory& memory;
std::size_t num_interpreted_instructions{};
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index bf971b7dc..921a5a734 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -183,7 +183,7 @@ public:
u64 GetTicksRemaining() override {
if (parent.uses_wall_clock) {
- if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) {
+ if (!IsInterrupted()) {
return minimum_run_cycles;
}
return 0U;
@@ -217,6 +217,10 @@ public:
parent.jit.load()->HaltExecution(hr);
}
+ bool IsInterrupted() {
+ return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
+ }
+
ARM_Dynarmic_64& parent;
Core::Memory::Memory& memory;
u64 tpidrro_el0 = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
index e9123c13d..200efe4db 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
@@ -8,6 +8,10 @@
#include "core/core.h"
#include "core/core_timing.h"
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
using Callback = Dynarmic::A32::Coprocessor::Callback;
using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
@@ -47,12 +51,31 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1
switch (opc2) {
case 4:
// CP15_DATA_SYNC_BARRIER
- // This is a dummy write, we ignore the value written here.
- return &dummy_value;
+ return Callback{
+ [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
+#ifdef _MSC_VER
+ _mm_mfence();
+ _mm_lfence();
+#else
+ asm volatile("mfence\n\tlfence\n\t" : : : "memory");
+#endif
+ return 0;
+ },
+ std::nullopt,
+ };
case 5:
// CP15_DATA_MEMORY_BARRIER
- // This is a dummy write, we ignore the value written here.
- return &dummy_value;
+ return Callback{
+ [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
+#ifdef _MSC_VER
+ _mm_mfence();
+#else
+ asm volatile("mfence\n\t" : : : "memory");
+#endif
+ return 0;
+ },
+ std::nullopt,
+ };
}
}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
index 5b2a51636..d90b3e568 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
@@ -35,6 +35,8 @@ public:
ARM_Dynarmic_32& parent;
u32 uprw = 0;
u32 uro = 0;
+
+ friend class ARM_Dynarmic_32;
};
} // namespace Core
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 8c3895937..049602e7d 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "common/thread.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/input_converter.h"
@@ -84,18 +85,19 @@ void EmulatedController::ReloadFromSettings() {
motion_params[index] = Common::ParamPackage(player.motions[index]);
}
+ controller.colors_state.fullkey = {
+ .body = GetNpadColor(player.body_color_left),
+ .button = GetNpadColor(player.button_color_left),
+ };
controller.colors_state.left = {
- .body = player.body_color_left,
- .button = player.button_color_left,
+ .body = GetNpadColor(player.body_color_left),
+ .button = GetNpadColor(player.button_color_left),
};
-
- controller.colors_state.right = {
- .body = player.body_color_right,
- .button = player.button_color_right,
+ controller.colors_state.left = {
+ .body = GetNpadColor(player.body_color_right),
+ .button = GetNpadColor(player.button_color_right),
};
- controller.colors_state.fullkey = controller.colors_state.left;
-
// Other or debug controller should always be a pro controller
if (npad_id_type != NpadIdType::Other) {
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
@@ -949,6 +951,9 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
// Send a slight vibration to test for rumble support
output_devices[device_index]->SetVibration(test_vibration);
+ // Wait for about 15ms to ensure the controller is ready for the stop command
+ std::this_thread::sleep_for(std::chrono::milliseconds(15));
+
// Stop any vibration and return the result
return output_devices[device_index]->SetVibration(zero_vibration) ==
Common::Input::VibrationError::None;
@@ -1310,6 +1315,15 @@ const CameraState& EmulatedController::GetCamera() const {
return controller.camera_state;
}
+NpadColor EmulatedController::GetNpadColor(u32 color) {
+ return {
+ .r = static_cast<u8>((color >> 16) & 0xFF),
+ .g = static_cast<u8>((color >> 8) & 0xFF),
+ .b = static_cast<u8>(color & 0xFF),
+ .a = 0xff,
+ };
+}
+
void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
std::scoped_lock lock{callback_mutex};
for (const auto& poller_pair : callback_list) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 823c1700c..cbd7c26d3 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -425,6 +425,13 @@ private:
void SetCamera(const Common::Input::CallbackStatus& callback);
/**
+ * Converts a color format from bgra to rgba
+ * @param color in bgra format
+ * @return NpadColor in rgba format
+ */
+ NpadColor GetNpadColor(u32 color);
+
+ /**
* Triggers a callback that something has changed on the controller status
* @param type Input type of the event to trigger
* @param is_service_update indicates if this event should only be sent to HID services
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index e49223016..e3b1cfbc6 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -327,10 +327,18 @@ struct TouchState {
};
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
+struct NpadColor {
+ u8 r{};
+ u8 g{};
+ u8 b{};
+ u8 a{};
+};
+static_assert(sizeof(NpadColor) == 4, "NpadColor is an invalid size");
+
// This is nn::hid::NpadControllerColor
struct NpadControllerColor {
- u32 body{};
- u32 button{};
+ NpadColor body{};
+ NpadColor button{};
};
static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 3c28dee76..cb29004e8 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -163,28 +163,51 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
}
LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
const auto controller_type = controller.device->GetNpadStyleIndex();
+ const auto& body_colors = controller.device->GetColors();
+ const auto& battery_level = controller.device->GetBattery();
auto* shared_memory = controller.shared_memory;
if (controller_type == Core::HID::NpadStyleIndex::None) {
controller.styleset_changed_event->GetWritableEvent().Signal();
return;
}
+
+ // Reset memory values
shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None;
shared_memory->device_type.raw = 0;
shared_memory->system_properties.raw = 0;
+ shared_memory->joycon_color.attribute = ColorAttribute::NoController;
+ shared_memory->joycon_color.attribute = ColorAttribute::NoController;
+ shared_memory->fullkey_color = {};
+ shared_memory->joycon_color.left = {};
+ shared_memory->joycon_color.right = {};
+ shared_memory->battery_level_dual = {};
+ shared_memory->battery_level_left = {};
+ shared_memory->battery_level_right = {};
+
switch (controller_type) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
+ shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
+ shared_memory->fullkey_color.fullkey = body_colors.fullkey;
+ shared_memory->battery_level_dual = battery_level.dual.battery_level;
shared_memory->style_tag.fullkey.Assign(1);
shared_memory->device_type.fullkey.Assign(1);
shared_memory->system_properties.is_vertical.Assign(1);
shared_memory->system_properties.use_plus.Assign(1);
shared_memory->system_properties.use_minus.Assign(1);
+ shared_memory->system_properties.is_charging_joy_dual.Assign(
+ battery_level.dual.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::Handheld:
+ shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
+ shared_memory->joycon_color.attribute = ColorAttribute::Ok;
+ shared_memory->fullkey_color.fullkey = body_colors.fullkey;
+ shared_memory->joycon_color.left = body_colors.left;
+ shared_memory->joycon_color.right = body_colors.right;
shared_memory->style_tag.handheld.Assign(1);
shared_memory->device_type.handheld_left.Assign(1);
shared_memory->device_type.handheld_right.Assign(1);
@@ -192,47 +215,86 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
shared_memory->system_properties.use_plus.Assign(1);
shared_memory->system_properties.use_minus.Assign(1);
shared_memory->system_properties.use_directional_buttons.Assign(1);
+ shared_memory->system_properties.is_charging_joy_dual.Assign(
+ battery_level.left.is_charging);
+ shared_memory->system_properties.is_charging_joy_left.Assign(
+ battery_level.left.is_charging);
+ shared_memory->system_properties.is_charging_joy_right.Assign(
+ battery_level.right.is_charging);
shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
shared_memory->applet_nfc_xcd.applet_footer.type =
AppletFooterUiType::HandheldJoyConLeftJoyConRight;
shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::JoyconDual:
+ shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
+ shared_memory->joycon_color.attribute = ColorAttribute::Ok;
shared_memory->style_tag.joycon_dual.Assign(1);
if (controller.is_dual_left_connected) {
+ shared_memory->joycon_color.left = body_colors.left;
+ shared_memory->battery_level_left = battery_level.left.battery_level;
shared_memory->device_type.joycon_left.Assign(1);
shared_memory->system_properties.use_minus.Assign(1);
+ shared_memory->system_properties.is_charging_joy_left.Assign(
+ battery_level.left.is_charging);
shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1);
}
if (controller.is_dual_right_connected) {
+ shared_memory->joycon_color.right = body_colors.right;
+ shared_memory->battery_level_right = battery_level.right.battery_level;
shared_memory->device_type.joycon_right.Assign(1);
shared_memory->system_properties.use_plus.Assign(1);
+ shared_memory->system_properties.is_charging_joy_right.Assign(
+ battery_level.right.is_charging);
shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1);
}
shared_memory->system_properties.use_directional_buttons.Assign(1);
shared_memory->system_properties.is_vertical.Assign(1);
shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
+
if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;
+ shared_memory->fullkey_color.fullkey = body_colors.left;
+ shared_memory->battery_level_dual = battery_level.left.battery_level;
+ shared_memory->system_properties.is_charging_joy_dual.Assign(
+ battery_level.left.is_charging);
} else if (controller.is_dual_left_connected) {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
+ shared_memory->fullkey_color.fullkey = body_colors.left;
+ shared_memory->battery_level_dual = battery_level.left.battery_level;
+ shared_memory->system_properties.is_charging_joy_dual.Assign(
+ battery_level.left.is_charging);
} else {
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
+ shared_memory->fullkey_color.fullkey = body_colors.right;
+ shared_memory->battery_level_dual = battery_level.right.battery_level;
+ shared_memory->system_properties.is_charging_joy_dual.Assign(
+ battery_level.right.is_charging);
}
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
+ shared_memory->joycon_color.attribute = ColorAttribute::Ok;
+ shared_memory->joycon_color.left = body_colors.left;
+ shared_memory->battery_level_dual = battery_level.left.battery_level;
shared_memory->style_tag.joycon_left.Assign(1);
shared_memory->device_type.joycon_left.Assign(1);
shared_memory->system_properties.is_horizontal.Assign(1);
shared_memory->system_properties.use_minus.Assign(1);
+ shared_memory->system_properties.is_charging_joy_left.Assign(
+ battery_level.left.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
+ shared_memory->joycon_color.attribute = ColorAttribute::Ok;
+ shared_memory->joycon_color.right = body_colors.right;
+ shared_memory->battery_level_right = battery_level.right.battery_level;
shared_memory->style_tag.joycon_right.Assign(1);
shared_memory->device_type.joycon_right.Assign(1);
shared_memory->system_properties.is_horizontal.Assign(1);
shared_memory->system_properties.use_plus.Assign(1);
+ shared_memory->system_properties.is_charging_joy_right.Assign(
+ battery_level.right.is_charging);
shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
break;
@@ -269,21 +331,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
break;
}
- const auto& body_colors = controller.device->GetColors();
-
- shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
- shared_memory->fullkey_color.fullkey = body_colors.fullkey;
-
- shared_memory->joycon_color.attribute = ColorAttribute::Ok;
- shared_memory->joycon_color.left = body_colors.left;
- shared_memory->joycon_color.right = body_colors.right;
-
- // TODO: Investigate when we should report all batery types
- const auto& battery_level = controller.device->GetBattery();
- shared_memory->battery_level_dual = battery_level.dual.battery_level;
- shared_memory->battery_level_left = battery_level.left.battery_level;
- shared_memory->battery_level_right = battery_level.right.battery_level;
-
controller.is_connected = true;
controller.device->Connect();
SignalStyleSetChangedEvent(npad_id);
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index f6b389ede..50007338f 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -221,6 +221,9 @@ if (ENABLE_QT_TRANSLATION)
# Update source TS file if enabled
if (GENERATE_QT_TRANSLATION)
get_target_property(SRCS yuzu SOURCES)
+ # these calls to qt_create_translation also creates a rule to generate en.qm which conflicts with providing english plurals
+ # so we have to set a OUTPUT_LOCATION so that we don't have multiple rules to generate en.qm
+ set_source_files_properties(${YUZU_QT_LANGUAGES}/en.ts PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
qt_create_translation(QM_FILES
${SRCS}
${UIS}
@@ -229,7 +232,13 @@ if (ENABLE_QT_TRANSLATION)
-source-language en_US
-target-language en_US
)
- add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
+
+ # Generate plurals into dist/english_plurals/generated_en.ts so it can be used to revise dist/english_plurals/en.ts
+ set(GENERATED_PLURALS_FILE ${PROJECT_SOURCE_DIR}/dist/english_plurals/generated_en.ts)
+ set_source_files_properties(${GENERATED_PLURALS_FILE} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/plurals")
+ qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US)
+
+ add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts ${GENERATED_PLURALS_FILE})
endif()
# Find all TS files except en.ts
@@ -239,6 +248,9 @@ if (ENABLE_QT_TRANSLATION)
# Compile TS files to QM files
qt_add_translation(LANGUAGES_QM ${LANGUAGES_TS})
+ # Compile english plurals TS file to en.qm
+ qt_add_translation(LANGUAGES_QM ${PROJECT_SOURCE_DIR}/dist/english_plurals/en.ts)
+
# Build a QRC file from the QM file list
set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc)
file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n")
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 2e98ede8e..48f71b53c 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -219,6 +219,7 @@ void ConfigureUi::InitializeLanguageComboBox() {
for (const auto& lang : languages) {
if (QString::fromLatin1(lang.id) == QStringLiteral("en")) {
ui->language_combobox->addItem(lang.name, QStringLiteral("en"));
+ language_files.removeOne(QStringLiteral("en.qm"));
continue;
}
for (int i = 0; i < language_files.size(); ++i) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 653280642..f82bec3b7 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3980,11 +3980,6 @@ void GMainWindow::UpdateUITheme() {
}
void GMainWindow::LoadTranslation() {
- // If the selected language is English, no need to install any translation
- if (UISettings::values.language == QStringLiteral("en")) {
- return;
- }
-
bool loaded;
if (UISettings::values.language.isEmpty()) {
@@ -4072,6 +4067,15 @@ int main(int argc, char* argv[]) {
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv);
+ // Workaround for QTBUG-85409, for Suzhou numerals the number 1 is actually \u3021
+ // so we can see if we get \u3008 instead
+ // TL;DR all other number formats are consecutive in unicode code points
+ // This bug is fixed in Qt6, specifically 6.0.0-alpha1
+ const QLocale locale = QLocale::system();
+ if (QStringLiteral("\u3008") == locale.toString(1)) {
+ QLocale::setDefault(QLocale::system().name());
+ }
+
// Qt changes the locale and causes issues in float conversion using std::to_string() when
// generating shaders
setlocale(LC_ALL, "C");