Compare commits

...

30 Commits

Author SHA1 Message Date
6af28cc01b Android #54 2023-08-29 00:57:20 +00:00
1615a86375 Merge pull request #11390 from FearlessTobi/hwopus-multi
hwopus: Implement OpenHardwareOpusDecoderForMultiStreamEx and DecodeInterleavedForMultiStream
2023-08-28 19:14:44 -04:00
199de26995 Merge pull request #11399 from liamwhite/cubeb-latency
audio: allow more latency in cubeb initialization
2023-08-28 19:14:33 -04:00
954144e22b audio: allow more latency in cubeb initialization 2023-08-27 12:46:01 -04:00
c2f827b85e hwopus: Implement OpenHardwareOpusDecoderForMultiStreamEx and DecodeInterleavedForMultiStream
Allows MLB The Show 22 to boot.

Fixes https://github.com/yuzu-emu/yuzu/issues/7911.
2023-08-27 18:03:10 +02:00
ada4697300 Merge pull request #11389 from FernandoS27/discard-fix
Buffer Cache: fix discard writes.
2023-08-27 04:26:59 +02:00
acc99433c7 Buffer Cache: fix discard writes. 2023-08-27 03:45:43 +02:00
6c4abd23be Merge pull request #11356 from lat9nq/console-mode-pg
general,config-qt: Present Console Mode as an enum with separate options in game properties
2023-08-26 19:15:00 -04:00
84b384fbea Merge pull request #11359 from Kelebek1/check_suitable_backend
Pre-test for valid audio backends
2023-08-26 19:14:47 -04:00
3620533995 Merge pull request #11350 from BenjaminHalko/button-padding
ui: Added padding to the reset button
2023-08-26 19:14:30 -04:00
c5105b65d5 Merge pull request #11317 from Kelebek1/macro_dumps
Mark decompiled macros on dump, dump shaders after translation
2023-08-26 19:14:25 -04:00
1ac2615adb Merge pull request #11338 from comex/warning-fixes-august-2023
Warnings cleanup for GCC 13 and Clang 16
2023-08-26 19:14:17 -04:00
d7a0b8c373 Mark decompiled macros as decompiled on dump, dump shaders after translation 2023-08-25 21:47:47 -04:00
6bb02dcb8a Skip additional mbedcrypto warnings options on MSVC 2023-08-25 19:23:34 -04:00
32c453a5f1 Avoid $<CXX_COMPILER_ID:Clang> because it doesn't include AppleClang. 2023-08-25 19:22:31 -04:00
91eb5afd0b Warnings cleanup for GCC 13 and Clang 16
Note: For GCC there are still a huge number of `-Warray-bounds` warnings
coming from `externals/dynarmic`.  I could have added a workaround in
`externals/CMakeLists.txt` similar to what this PR does for other
externals, but given Dynarmic's close affiliation with Yuzu, it would be
better to fix it upstream.

Besides that, on my machine, this makes the build warning-free except
for some warnings from glslangValidator and AutoMoc.

Details:

- Disable some warnings in externals.

- Disable `-Wnullability-completeness`, which is a Clang warning triggered
  by the Vulkan SDK where if any pointers in the header are marked
  _Nullable, it wants all pointers to be marked _Nullable or _Nonnull.
  Most of them are, but some aren't.  Who knows why.

- `src/web_service/verify_user_jwt.cpp`: Disable another warning when
  including `jwt.hpp`.

- `src/input_common/input_poller.cpp`: Add missing `override` specifiers.

- src/common/swap.h: Remove redundant `operator&`.  In general, this
  file declares three overloads of each operator.  Using `+` as an
  example, the overloads are:

  - a member function for `swapped_t + integer`
  - a member function for `swapped_t + swapped_t`
  - a free function for `integer + swapped_t`

  But for `operator&`, there was an additional free function for
  `swapped_t + integer`, which was redundant with the member function.
  This caused a GCC warning saying "ISO C++ says that these are
  ambiguous".
2023-08-25 19:22:31 -04:00
2e55459e03 Updated to only the reset button 2023-08-25 10:45:42 -07:00
8677d98a10 Updated padded style 2023-08-25 10:29:23 -07:00
1cdd11d9f5 main: Fix docked mode button, clang 14 error 2023-08-23 14:26:34 -04:00
39c8ddcda2 Pre-test opening a stream for audio backends, fall back to null if not suitable. 2023-08-23 08:33:26 +01:00
00af46c356 native: Use Docked Mode helper 2023-08-22 22:40:36 -04:00
ce0f1baf51 main: Access by reference
Old Clang is fussy about this.
2023-08-22 22:35:55 -04:00
75f5b3177d config-android: Translate console mode setting
Translates the previous boolean to the enum.
2023-08-22 22:00:28 -04:00
3c45452fae general: Use console mode helper across project 2023-08-22 21:58:23 -04:00
ab862207d7 settings: Add docked mode helper function 2023-08-22 21:58:09 -04:00
7f8335f4ae config(qt): Sanitize docked handheld controller 2023-08-22 16:07:53 -04:00
6ed5b581f0 shared_translation: Define use_docked_mode texts 2023-08-22 16:07:53 -04:00
387ede76d2 general: Convert use_docked_mode to an enumeration
Allows some special interactions with it in the Qt frontend.
2023-08-22 16:07:52 -04:00
8a4cb3f902 shared_widget: Implement radio groups 2023-08-22 16:07:52 -04:00
0e443dcb05 fix: Added padding to buttons
Some buttons did not have enough padding, now they do!
2023-08-22 10:01:12 -07:00
43 changed files with 400 additions and 109 deletions

View File

@ -1,3 +1,11 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
End of merge log. You can find the original README.md below the break.
-----
<!--
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later

View File

@ -78,6 +78,11 @@ QPushButton#buttonRefreshDevices {
max-height: 21px;
}
QPushButton#button_reset_defaults {
min-width: 57px;
padding: 4px 8px;
}
QWidget#bottomPerGameInput,
QWidget#topControllerApplet,
QWidget#bottomControllerApplet,

View File

@ -2228,6 +2228,10 @@ QPushButton#buttonRefreshDevices {
padding: 0px 0px;
}
QPushButton#button_reset_defaults {
padding: 3px 6px;
}
QSpinBox#spinboxLStickRange,
QSpinBox#spinboxRStickRange,
QSpinBox#vibrationSpinPlayer1,

View File

@ -42,6 +42,11 @@ endif()
# mbedtls
add_subdirectory(mbedtls)
target_include_directories(mbedtls PUBLIC ./mbedtls/include)
if (NOT MSVC)
target_compile_options(mbedcrypto PRIVATE
-Wno-unused-but-set-variable
-Wno-string-concatenation)
endif()
# MicroProfile
add_library(microprofile INTERFACE)
@ -94,6 +99,12 @@ if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb)
set(BUILD_TOOLS OFF)
add_subdirectory(cubeb)
add_library(cubeb::cubeb ALIAS cubeb)
if (NOT MSVC)
if (TARGET speex)
target_compile_options(speex PRIVATE -Wno-sign-compare)
endif()
target_compile_options(cubeb PRIVATE -Wno-implicit-const-int-float-conversion)
endif()
endif()
# DiscordRPC
@ -151,6 +162,9 @@ endif()
if (NOT TARGET LLVM::Demangle)
add_library(demangle demangle/ItaniumDemangle.cpp)
target_include_directories(demangle PUBLIC ./demangle)
if (NOT MSVC)
target_compile_options(demangle PRIVATE -Wno-deprecated-declarations) # std::is_pod
endif()
add_library(LLVM::Demangle ALIAS demangle)
endif()

View File

@ -114,16 +114,19 @@ else()
-Wno-attributes
-Wno-invalid-offsetof
-Wno-unused-parameter
$<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init>
$<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field>
$<$<CXX_COMPILER_ID:Clang>:-Werror=shadow-uncaptured-local>
$<$<CXX_COMPILER_ID:Clang>:-Werror=implicit-fallthrough>
$<$<CXX_COMPILER_ID:Clang>:-Werror=type-limits>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-braced-scalar-init>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-private-field>
)
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
add_compile_options(
-Wno-braced-scalar-init
-Wno-unused-private-field
-Wno-nullability-completeness
-Werror=shadow-uncaptured-local
-Werror=implicit-fallthrough
-Werror=type-limits
)
endif()
if (ARCHITECTURE_x86_64)
add_compile_options("-mcx16")
add_compile_options("-fwrapv")

View File

@ -11,6 +11,7 @@
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/hle/service/acc/profile_manager.h"
#include "input_common/main.h"
#include "jni/config.h"
@ -144,7 +145,9 @@ void Config::ReadValues() {
Service::Account::MAX_USERS - 1);
// Disable docked mode by default on Android
Settings::values.use_docked_mode = config->GetBoolean("System", "use_docked_mode", false);
Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false)
? Settings::ConsoleMode::Docked
: Settings::ConsoleMode::Handheld);
const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false);
if (rng_seed_enabled) {

View File

@ -420,7 +420,7 @@ public:
return false;
}
return !Settings::values.use_docked_mode.GetValue();
return !Settings::IsDockedMode();
}
void SetDeviceType([[maybe_unused]] int index, int type) {

View File

@ -8,6 +8,7 @@
#include "audio_core/sink/cubeb_sink.h"
#include "audio_core/sink/sink_stream.h"
#include "common/logging/log.h"
#include "common/scope_exit.h"
#include "core/core.h"
#ifdef _WIN32
@ -332,25 +333,38 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
return device_list;
}
u32 GetCubebLatency() {
cubeb* ctx;
namespace {
static long TmpDataCallback(cubeb_stream*, void*, const void*, void*, long) {
return TargetSampleCount;
}
static void TmpStateCallback(cubeb_stream*, void*, cubeb_state) {}
} // namespace
bool IsCubebSuitable() {
#if !defined(HAVE_CUBEB)
return false;
#else
cubeb* ctx{nullptr};
#ifdef _WIN32
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
// Init cubeb
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
// Return a large latency so we choose SDL instead.
return 10000u;
LOG_ERROR(Audio_Sink, "Cubeb failed to init, it is not suitable.");
return false;
}
SCOPE_EXIT({ cubeb_destroy(ctx); });
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {
CoUninitialize();
}
#endif
// Get min latency
cubeb_stream_params params{};
params.rate = TargetSampleRate;
params.channels = 2;
@ -361,12 +375,27 @@ u32 GetCubebLatency() {
u32 latency{0};
const auto latency_error = cubeb_get_min_latency(ctx, &params, &latency);
if (latency_error != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error getting minimum latency, error: {}", latency_error);
latency = TargetSampleCount * 2;
LOG_ERROR(Audio_Sink, "Cubeb could not get min latency, it is not suitable.");
return false;
}
latency = std::max(latency, TargetSampleCount * 2);
cubeb_destroy(ctx);
return latency;
// Test opening a device with standard parameters
cubeb_devid output_device{0};
cubeb_devid input_device{0};
std::string name{"Yuzu test"};
cubeb_stream* stream{nullptr};
if (cubeb_stream_init(ctx, &stream, name.c_str(), input_device, nullptr, output_device, &params,
latency, &TmpDataCallback, &TmpStateCallback, nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Cubeb could not open a device, it is not suitable.");
return false;
}
cubeb_stream_stop(stream);
cubeb_stream_destroy(stream);
return true;
#endif
}
} // namespace AudioCore::Sink

View File

@ -97,10 +97,11 @@ private:
std::vector<std::string> ListCubebSinkDevices(bool capture);
/**
* Get the reported latency for this sink.
* Check if this backend is suitable for use.
* Checks if enabled, its latency, whether it opens successfully, etc.
*
* @return Minimum latency for this sink.
* @return True is this backend is suitable, false otherwise.
*/
u32 GetCubebLatency();
bool IsCubebSuitable();
} // namespace AudioCore::Sink

View File

@ -9,6 +9,7 @@
#include "audio_core/sink/sdl2_sink.h"
#include "audio_core/sink/sink_stream.h"
#include "common/logging/log.h"
#include "common/scope_exit.h"
#include "core/core.h"
namespace AudioCore::Sink {
@ -84,6 +85,7 @@ public:
}
Stop();
SDL_ClearQueuedAudio(device);
SDL_CloseAudioDevice(device);
}
@ -227,8 +229,42 @@ std::vector<std::string> ListSDLSinkDevices(bool capture) {
return device_list;
}
u32 GetSDLLatency() {
return TargetSampleCount * 2;
bool IsSDLSuitable() {
#if !defined(HAVE_SDL2)
return false;
#else
// Check SDL can init
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
LOG_ERROR(Audio_Sink, "SDL failed to init, it is not suitable. Error: {}",
SDL_GetError());
return false;
}
}
// We can set any latency frequency we want with SDL, so no need to check that.
// Check we can open a device with standard parameters
SDL_AudioSpec spec;
spec.freq = TargetSampleRate;
spec.channels = 2u;
spec.format = AUDIO_S16SYS;
spec.samples = TargetSampleCount * 2;
spec.callback = nullptr;
spec.userdata = nullptr;
SDL_AudioSpec obtained;
auto device = SDL_OpenAudioDevice(nullptr, false, &spec, &obtained, false);
if (device == 0) {
LOG_ERROR(Audio_Sink, "SDL failed to open a device, it is not suitable. Error: {}",
SDL_GetError());
return false;
}
SDL_CloseAudioDevice(device);
return true;
#endif
}
} // namespace AudioCore::Sink

View File

@ -88,10 +88,11 @@ private:
std::vector<std::string> ListSDLSinkDevices(bool capture);
/**
* Get the reported latency for this sink.
* Check if this backend is suitable for use.
* Checks if enabled, its latency, whether it opens successfully, etc.
*
* @return Minimum latency for this sink.
* @return True is this backend is suitable, false otherwise.
*/
u32 GetSDLLatency();
bool IsSDLSuitable();
} // namespace AudioCore::Sink

View File

@ -22,7 +22,7 @@ namespace {
struct SinkDetails {
using FactoryFn = std::unique_ptr<Sink> (*)(std::string_view);
using ListDevicesFn = std::vector<std::string> (*)(bool);
using LatencyFn = u32 (*)();
using SuitableFn = bool (*)();
/// Name for this sink.
Settings::AudioEngine id;
@ -30,8 +30,8 @@ struct SinkDetails {
FactoryFn factory;
/// A method to call to list available devices.
ListDevicesFn list_devices;
/// Method to get the latency of this backend.
LatencyFn latency;
/// Check whether this backend is suitable to be used.
SuitableFn is_suitable;
};
// sink_details is ordered in terms of desirability, with the best choice at the top.
@ -43,7 +43,7 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<CubebSink>(device_id);
},
&ListCubebSinkDevices,
&GetCubebLatency,
&IsCubebSuitable,
},
#endif
#ifdef HAVE_SDL2
@ -53,14 +53,17 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<SDLSink>(device_id);
},
&ListSDLSinkDevices,
&GetSDLLatency,
&IsSDLSuitable,
},
#endif
SinkDetails{Settings::AudioEngine::Null,
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<NullSink>(device_id);
},
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
SinkDetails{
Settings::AudioEngine::Null,
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<NullSink>(device_id);
},
[](bool capture) { return std::vector<std::string>{"null"}; },
[]() { return true; },
},
};
const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
@ -72,18 +75,22 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
auto iter = find_backend(sink_id);
if (sink_id == Settings::AudioEngine::Auto) {
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
// causes audio issues, in that case go with SDL.
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
iter = find_backend(Settings::AudioEngine::Cubeb);
if (iter->latency() > TargetSampleCount * 3) {
iter = find_backend(Settings::AudioEngine::Sdl2);
// Auto-select a backend. Use the sink details ordering, preferring cubeb first, checking
// that the backend is available and suitable to use.
for (auto& details : sink_details) {
if (details.is_suitable()) {
iter = &details;
break;
}
}
#else
iter = std::begin(sink_details);
#endif
LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
Settings::CanonicalizeEnum(iter->id));
} else {
if (iter != std::end(sink_details) && !iter->is_suitable()) {
LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null",
Settings::CanonicalizeEnum(iter->id));
iter = find_backend(Settings::AudioEngine::Null);
}
}
if (iter == std::end(sink_details)) {

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <version>
#include "common/settings_enums.h"
#if __cpp_lib_chrono >= 201907L
#include <chrono>
#include <exception>
@ -145,6 +146,10 @@ bool IsFastmemEnabled() {
return true;
}
bool IsDockedMode() {
return values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
}
float Volume() {
if (values.audio_muted) {
return 0.0f;

View File

@ -379,7 +379,13 @@ struct Values {
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
ConsoleMode::Docked,
"use_docked_mode",
Category::System,
Specialization::Radio,
true,
true};
// Controls
InputSetting<std::array<PlayerInput, 10>> players;
@ -519,6 +525,8 @@ bool IsGPULevelHigh();
bool IsFastmemEnabled();
bool IsDockedMode();
float Volume();
std::string GetTimeZoneString(TimeZone time_zone);

View File

@ -56,6 +56,7 @@ enum Specialization : u8 {
Scalar = 5, // Values are continuous
Countable = 6, // Can be stepped through
Paired = 7, // Another setting is associated with this setting
Radio = 8, // Setting should be presented in a radio group
Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage
};

View File

@ -146,6 +146,8 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
ENUM(ConsoleMode, Handheld, Docked);
template <typename Type>
inline std::string CanonicalizeEnum(Type id) {
const auto group = EnumMetadata<Type>::Canonicalizations();

View File

@ -460,11 +460,6 @@ S operator&(const S& i, const swap_struct_t<T, F> v) {
return i & v.swap();
}
template <typename S, typename T, typename F>
S operator&(const swap_struct_t<T, F> v, const S& i) {
return static_cast<S>(v.swap() & i);
}
// Comparison
template <typename S, typename T, typename F>
bool operator<(const S& p, const swap_struct_t<T, F> v) {

View File

@ -3,6 +3,8 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/frontend/applets/controller.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
@ -62,7 +64,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
controller->Connect(true);
}
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
!Settings::values.use_docked_mode.GetValue()) {
!Settings::IsDockedMode()) {
// We should *never* reach here under any normal circumstances.
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
controller->Connect(true);

View File

@ -5,6 +5,7 @@
#include "common/assert.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/frontend/framebuffer_layout.h"
namespace Layout {
@ -49,7 +50,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
}
FramebufferLayout FrameLayoutFromResolutionScale(f32 res_scale) {
const bool is_docked = Settings::values.use_docked_mode.GetValue();
const bool is_docked = Settings::IsDockedMode();
const u32 screen_width = is_docked ? ScreenDocked::Width : ScreenUndocked::Width;
const u32 screen_height = is_docked ? ScreenDocked::Height : ScreenUndocked::Height;

View File

@ -6,6 +6,7 @@
#include <cinttypes>
#include <cstring>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
@ -833,7 +834,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::IsDockedMode()) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
} else {
@ -921,7 +922,7 @@ void IStorage::Open(HLERequestContext& ctx) {
}
void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
const bool use_docked_mode{Settings::IsDockedMode()};
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
IPC::ResponseBuilder rb{ctx, 3};

View File

@ -7,6 +7,7 @@
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core_timing.h"
#include "core/hle/service/apm/apm_controller.h"
@ -67,8 +68,7 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
}
PerformanceMode Controller::GetCurrentPerformanceMode() const {
return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Boost
: PerformanceMode::Normal;
return Settings::IsDockedMode() ? PerformanceMode::Boost : PerformanceMode::Normal;
}
PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {

View File

@ -174,7 +174,7 @@ public:
{6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"},
{7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
{8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
{9, nullptr, "DecodeInterleavedForMultiStream"},
{9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
};
// clang-format on
@ -206,6 +206,16 @@ private:
decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
}
void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
LOG_DEBUG(Audio, "called");
IPC::RequestParser rp{ctx};
const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext
: OpusDecoderState::ExtraBehavior::None;
decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
}
OpusDecoderState decoder_state;
};
@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
}
void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
OpusMultiStreamParametersEx params;
std::memcpy(&params, ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
const auto& sample_rate = params.sample_rate;
const auto& channel_count = params.channel_count;
LOG_INFO(
Audio,
"called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}",
sample_rate, channel_count, params.number_streams, params.number_stereo_streams);
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
sample_rate == 12000 || sample_rate == 8000,
"Invalid sample rate");
int error = 0;
OpusDecoderPtr decoder{opus_multistream_decoder_create(
sample_rate, static_cast<int>(channel_count), params.number_streams,
params.number_stereo_streams, params.channel_mappings.data(), &error)};
if (error != OPUS_OK || decoder == nullptr) {
LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error);
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
rb.Push(ResultUnknown);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IHardwareOpusDecoderManager>(
system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
}
HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
static const FunctionInfo functions[] = {
{0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
{3, nullptr, "GetWorkBufferSizeForMultiStream"},
{4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
{5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
{6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"},
{6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
"OpenHardwareOpusDecoderForMultiStreamEx"},
{7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
{8, nullptr, "GetWorkBufferSizeExEx"},
{9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"},

View File

@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx {
u32 number_stereo_streams;
u32 use_large_frame_size;
u32 padding;
std::array<u32, 64> channel_mappings;
std::array<u8, 0x100> channel_mappings;
};
static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
"OpusMultiStreamParametersEx has incorrect size");
class HwOpus final : public ServiceFramework<HwOpus> {
public:
@ -29,6 +31,7 @@ public:
private:
void OpenHardwareOpusDecoder(HLERequestContext& ctx);
void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
void GetWorkBufferSize(HLERequestContext& ctx);
void GetWorkBufferSizeEx(HLERequestContext& ctx);
void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);

View File

@ -331,7 +331,7 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties()
};
// Hack: There is no touch in docked but games still allow it
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::IsDockedMode()) {
gesture.points[id] = {
.x = static_cast<s32>(active_x * Layout::ScreenDocked::Width),
.y = static_cast<s32>(active_y * Layout::ScreenDocked::Height),

View File

@ -1518,7 +1518,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
return false;
}
// Handheld shouldn't be supported in docked mode
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::IsDockedMode()) {
return false;
}

View File

@ -217,7 +217,7 @@ private:
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::IsDockedMode()) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
} else {

View File

@ -14,6 +14,7 @@
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/loader/loader.h"
@ -275,7 +276,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
static_cast<u32>(Settings::values.shader_backend.GetValue()));
AddField(field_type, "Renderer_UseAsynchronousShaders",
Settings::values.use_asynchronous_shaders.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::IsDockedMode());
}
bool TelemetrySession::SubmitTestcase() {

View File

@ -835,15 +835,15 @@ public:
return input_engine->SupportsNfc(identifier);
}
Common::Input::NfcState StartNfcPolling() {
Common::Input::NfcState StartNfcPolling() override {
return input_engine->StartNfcPolling(identifier);
}
Common::Input::NfcState StopNfcPolling() {
Common::Input::NfcState StopNfcPolling() override {
return input_engine->StopNfcPolling(identifier);
}
Common::Input::NfcState ReadAmiiboData(std::vector<u8>& out_data) {
Common::Input::NfcState ReadAmiiboData(std::vector<u8>& out_data) override {
return input_engine->ReadAmiiboData(identifier, out_data);
}
@ -852,11 +852,11 @@ public:
}
Common::Input::NfcState ReadMifareData(const Common::Input::MifareRequest& request,
Common::Input::MifareRequest& out_data) {
Common::Input::MifareRequest& out_data) override {
return input_engine->ReadMifareData(identifier, request, out_data);
}
Common::Input::NfcState WriteMifareData(const Common::Input::MifareRequest& request) {
Common::Input::NfcState WriteMifareData(const Common::Input::MifareRequest& request) override {
return input_engine->WriteMifareData(identifier, request);
}

View File

@ -289,8 +289,11 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad
MarkWrittenBuffer(buffer_id, *cpu_addr, size);
break;
case ObtainBufferOperation::DiscardWrite: {
IntervalType interval{*cpu_addr, size};
VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
IntervalType interval{cpu_addr_start, cpu_addr_end};
ClearDownload(interval);
common_ranges.subtract(interval);
break;
}
default:
@ -1159,6 +1162,11 @@ void BufferCache<P>::UpdateDrawIndirect() {
.size = static_cast<u32>(size),
.buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)),
};
VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
IntervalType interval{cpu_addr_start, cpu_addr_end};
ClearDownload(interval);
common_ranges.subtract(interval);
};
if (current_draw_indirect->include_count) {
update(current_draw_indirect->count_start_address, sizeof(u32),

View File

@ -27,14 +27,24 @@ MICROPROFILE_DEFINE(MacroHLE, "GPU", "Execute macro HLE", MP_RGB(128, 192, 192))
namespace Tegra {
static void Dump(u64 hash, std::span<const u32> code) {
static void Dump(u64 hash, std::span<const u32> code, bool decompiled = false) {
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)};
auto name{macro_dir / fmt::format("{:016x}.macro", hash)};
if (decompiled) {
auto new_name{macro_dir / fmt::format("decompiled_{:016x}.macro", hash)};
if (Common::FS::Exists(name)) {
(void)Common::FS::RenameFile(name, new_name);
return;
}
name = new_name;
}
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 {}",
@ -90,9 +100,6 @@ 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 = Common::HashValue(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();
@ -102,9 +109,6 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
code.size() * sizeof(u32));
cache_info.hash = Common::HashValue(code);
cache_info.lle_program = Compile(code);
if (Settings::values.dump_macros) {
Dump(cache_info.hash, code);
}
}
auto hle_program = hle_macros->GetHLEProgram(cache_info.hash);
@ -117,6 +121,10 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
MICROPROFILE_SCOPE(MacroHLE);
cache_info.hle_program->Execute(parameters, method);
}
if (Settings::values.dump_macros) {
Dump(cache_info.hash, macro_code->second, cache_info.has_hle_program);
}
}
}

View File

@ -611,9 +611,6 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))};
Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0);
if (Settings::values.dump_shaders) {
env.Dump(hash, key.unique_hashes[index]);
}
if (!uses_vertex_a || index != 1) {
// Normal path
programs[index] = TranslateProgram(pools.inst, pools.block, env, cfg, host_info);
@ -624,6 +621,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
programs[index] = MergeDualVertexPrograms(program_va, program_vb, env);
}
if (Settings::values.dump_shaders) {
env.Dump(hash, key.unique_hashes[index]);
}
if (programs[index].info.requires_layer_emulation) {
layer_source_program = &programs[index];
}

View File

@ -4,6 +4,7 @@
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // for deprecated OpenSSL functions
#endif
#include <jwt/jwt.hpp>
#if defined(__GNUC__) || defined(__clang__)

View File

@ -5,6 +5,8 @@
#include <thread>
#include "common/assert.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hid/emulated_controller.h"
@ -226,9 +228,11 @@ int QtControllerSelectorDialog::exec() {
}
void QtControllerSelectorDialog::ApplyConfiguration() {
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
const bool pre_docked_mode = Settings::IsDockedMode();
const bool docked_mode_selected = ui->radioDocked->isChecked();
Settings::values.use_docked_mode.SetValue(
docked_mode_selected ? Settings::ConsoleMode::Docked : Settings::ConsoleMode::Handheld);
OnDockedModeChanged(pre_docked_mode, docked_mode_selected, system);
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@ -616,8 +620,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
ui->radioDocked->setChecked(Settings::IsDockedMode());
ui->radioUndocked->setChecked(!Settings::IsDockedMode());
// Also force into undocked mode if the controller type is handheld.
if (is_handheld) {

View File

@ -928,8 +928,8 @@ void GRenderWindow::CaptureScreenshot(const QString& screenshot_path) {
const Layout::FramebufferLayout layout{[]() {
u32 height = UISettings::values.screenshot_height.GetValue();
if (height == 0) {
height = Settings::values.use_docked_mode.GetValue() ? Layout::ScreenDocked::Height
: Layout::ScreenUndocked::Height;
height = Settings::IsDockedMode() ? Layout::ScreenDocked::Height
: Layout::ScreenUndocked::Height;
height *= Settings::values.resolution_info.up_factor;
}
const u32 width =

View File

@ -9,6 +9,7 @@
#include "common/fs/path_util.h"
#include "common/settings.h"
#include "common/settings_common.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/hid/controllers/npad.h"
@ -85,9 +86,9 @@ const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_ma
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
};
const std::map<bool, QString> Config::use_docked_mode_texts_map = {
{true, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
{false, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = {
{Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
{Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
};
const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = {
@ -376,7 +377,7 @@ void Config::ReadControlValues() {
const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
if (controller_type == Settings::ControllerType::Handheld) {
Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
Settings::values.use_docked_mode.SetValue(false);
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
}
if (IsCustomConfig()) {

View File

@ -9,6 +9,7 @@
#include <QMetaType>
#include <QVariant>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "yuzu/uisettings.h"
class QSettings;
@ -51,7 +52,7 @@ public:
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;
static const std::map<bool, QString> use_docked_mode_texts_map;
static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map;
static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map;
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;

View File

@ -4,6 +4,8 @@
#include <memory>
#include <thread>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
@ -197,9 +199,11 @@ void ConfigureInput::ApplyConfiguration() {
advanced->ApplyConfiguration();
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
const bool pre_docked_mode = Settings::IsDockedMode();
const bool docked_mode_selected = ui->radioDocked->isChecked();
Settings::values.use_docked_mode.SetValue(
docked_mode_selected ? Settings::ConsoleMode::Docked : Settings::ConsoleMode::Handheld);
OnDockedModeChanged(pre_docked_mode, docked_mode_selected, system);
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@ -267,8 +271,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
ui->radioDocked->setChecked(Settings::IsDockedMode());
ui->radioUndocked->setChecked(!Settings::IsDockedMode());
// Also force into undocked mode if the controller type is handheld.
if (is_handheld) {

View File

@ -18,6 +18,7 @@
#include "common/fs/fs_util.h"
#include "common/settings_enums.h"
#include "common/settings_input.h"
#include "configuration/shared_widget.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
@ -98,6 +99,12 @@ void ConfigurePerGame::ApplyConfiguration() {
addons_tab->ApplyConfiguration();
input_tab->ApplyConfiguration();
if (Settings::IsDockedMode() && Settings::values.players.GetValue()[0].controller_type ==
Settings::ControllerType::Handheld) {
Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
Settings::values.use_docked_mode.SetGlobal(true);
}
system.ApplySettings();
Settings::LogSettings();

View File

@ -106,6 +106,11 @@ void ConfigureSystem::Setup(const ConfigurationShared::Builder& builder) {
push(Settings::values.linkage.by_category[Settings::Category::System]);
for (auto setting : settings) {
if (setting->Id() == Settings::values.use_docked_mode.Id() &&
Settings::IsConfiguringGlobal()) {
continue;
}
ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs);
if (widget == nullptr) {

View File

@ -135,7 +135,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
INSERT(Settings, region_index, "Region:", "");
INSERT(Settings, time_zone_index, "Time Zone:", "");
INSERT(Settings, sound_index, "Sound Output Mode:", "");
INSERT(Settings, use_docked_mode, "", "");
INSERT(Settings, use_docked_mode, "Console Mode:", "");
INSERT(Settings, current_user, "", "");
// Controls
@ -379,6 +379,9 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
PAIR(MemoryLayout, Memory_6Gb, "6GB DRAM (Unsafe)"),
PAIR(MemoryLayout, Memory_8Gb, "8GB DRAM (Unsafe)"),
}});
translations->insert(
{Settings::EnumMetadata<Settings::ConsoleMode>::Index(),
{PAIR(ConsoleMode, Docked, "Docked"), PAIR(ConsoleMode, Handheld, "Handheld")}});
#undef PAIR
#undef CTX_PAIR

View File

@ -23,6 +23,7 @@
#include <QLineEdit>
#include <QObject>
#include <QPushButton>
#include <QRadioButton>
#include <QRegularExpression>
#include <QSizePolicy>
#include <QSlider>
@ -171,6 +172,65 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
return combobox;
}
QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
std::function<void()>& restore_func,
const std::function<void()>& touch) {
const auto type = setting.EnumIndex();
QWidget* group = new QWidget(this);
QHBoxLayout* layout = new QHBoxLayout(group);
layout->setContentsMargins(0, 0, 0, 0);
group->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
const ComboboxTranslations* enumeration{nullptr};
if (combobox_enumerations.contains(type)) {
enumeration = &combobox_enumerations.at(type);
for (const auto& [id, name] : *enumeration) {
QRadioButton* radio_button = new QRadioButton(name, group);
layout->addWidget(radio_button);
radio_buttons.push_back({id, radio_button});
}
} else {
return group;
}
const auto get_selected = [=]() -> u32 {
for (const auto& [id, button] : radio_buttons) {
if (button->isChecked()) {
return id;
}
}
return -1;
};
const auto set_index = [=](u32 value) {
for (const auto& [id, button] : radio_buttons) {
button->setChecked(id == value);
}
};
const u32 setting_value = std::stoi(setting.ToString());
set_index(setting_value);
serializer = [get_selected]() {
int current = get_selected();
return std::to_string(current);
};
restore_func = [this, set_index]() {
const u32 global_value = std::stoi(RelevantDefault(setting));
set_index(global_value);
};
if (!Settings::IsConfiguringGlobal()) {
for (const auto& [id, button] : radio_buttons) {
QObject::connect(button, &QAbstractButton::clicked, [touch]() { touch(); });
}
}
return group;
}
QWidget* Widget::CreateLineEdit(std::function<std::string()>& serializer,
std::function<void()>& restore_func,
const std::function<void()>& touch, bool managed) {
@ -411,6 +471,8 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
return RequestType::Slider;
case Settings::Specialization::Countable:
return RequestType::SpinBox;
case Settings::Specialization::Radio:
return RequestType::RadioGroup;
default:
break;
}
@ -439,7 +501,11 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
if (setting.TypeId() == typeid(bool)) {
data_component = CreateCheckBox(&setting, label, serializer, restore_func, touch);
} else if (setting.IsEnum()) {
data_component = CreateCombobox(serializer, restore_func, touch);
if (request == RequestType::RadioGroup) {
data_component = CreateRadioGroup(serializer, restore_func, touch);
} else {
data_component = CreateCombobox(serializer, restore_func, touch);
}
} else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) ||
type == typeid(s64) || type == typeid(u8)) {
switch (request) {

View File

@ -22,6 +22,7 @@ class QObject;
class QPushButton;
class QSlider;
class QSpinBox;
class QRadioButton;
namespace Settings {
class BasicSetting;
@ -38,6 +39,7 @@ enum class RequestType {
LineEdit,
HexEdit,
DateTimeEdit,
RadioGroup,
MaxEnum,
};
@ -91,6 +93,7 @@ public:
QSlider* slider{};
QComboBox* combobox{};
QDateTimeEdit* date_time_edit{};
std::vector<std::pair<u32, QRadioButton*>> radio_buttons{};
private:
void SetupComponent(const QString& label, std::function<void()>& load_func, bool managed,
@ -106,6 +109,9 @@ private:
QWidget* CreateCombobox(std::function<std::string()>& serializer,
std::function<void()>& restore_func,
const std::function<void()>& touch);
QWidget* CreateRadioGroup(std::function<std::string()>& serializer,
std::function<void()>& restore_func,
const std::function<void()>& touch);
QWidget* CreateLineEdit(std::function<std::string()>& serializer,
std::function<void()>& restore_func, const std::function<void()>& touch,
bool managed = true);

View File

@ -1158,9 +1158,9 @@ void GMainWindow::InitializeWidgets() {
[this](const QPoint& menu_location) {
QMenu context_menu;
for (auto const& docked_mode_pair : Config::use_docked_mode_texts_map) {
context_menu.addAction(docked_mode_pair.second, [this, docked_mode_pair] {
if (docked_mode_pair.first != Settings::values.use_docked_mode.GetValue()) {
for (auto const& pair : Config::use_docked_mode_texts_map) {
context_menu.addAction(pair.second, [this, &pair] {
if (pair.first != Settings::values.use_docked_mode.GetValue()) {
OnToggleDockedMode();
}
});
@ -3674,7 +3674,7 @@ void GMainWindow::OnTasReset() {
}
void GMainWindow::OnToggleDockedMode() {
const bool is_docked = Settings::values.use_docked_mode.GetValue();
const bool is_docked = Settings::IsDockedMode();
auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
@ -3688,7 +3688,8 @@ void GMainWindow::OnToggleDockedMode() {
controller_dialog->refreshConfiguration();
}
Settings::values.use_docked_mode.SetValue(!is_docked);
Settings::values.use_docked_mode.SetValue(is_docked ? Settings::ConsoleMode::Handheld
: Settings::ConsoleMode::Docked);
UpdateDockedButton();
OnDockedModeChanged(is_docked, !is_docked, *system);
}
@ -4118,10 +4119,10 @@ void GMainWindow::UpdateGPUAccuracyButton() {
}
void GMainWindow::UpdateDockedButton() {
const bool is_docked = Settings::values.use_docked_mode.GetValue();
dock_status_button->setChecked(is_docked);
const auto console_mode = Settings::values.use_docked_mode.GetValue();
dock_status_button->setChecked(Settings::IsDockedMode());
dock_status_button->setText(
Config::use_docked_mode_texts_map.find(is_docked)->second.toUpper());
Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
}
void GMainWindow::UpdateAPIText() {