mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-17 00:30:46 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| caef97f84b | |||
| fd34024f0e | |||
| d76f8f91c4 | |||
| a7061eb4c8 | |||
| fa4e7c6992 | |||
| b77308ced6 | |||
| defddec47f | |||
| c5405250d1 | |||
| 10c07d700c | |||
| 505b157647 |
@@ -1,13 +0,0 @@
|
||||
diff --git a/libs/cobalt/include/boost/cobalt/concepts.hpp b/libs/cobalt/include/boost/cobalt/concepts.hpp
|
||||
index d49f2ec..a9bdb80 100644
|
||||
--- a/libs/cobalt/include/boost/cobalt/concepts.hpp
|
||||
+++ b/libs/cobalt/include/boost/cobalt/concepts.hpp
|
||||
@@ -62,7 +62,7 @@ struct enable_awaitables
|
||||
template <typename T>
|
||||
concept with_get_executor = requires (T& t)
|
||||
{
|
||||
- {t.get_executor()} -> asio::execution::executor;
|
||||
+ t.get_executor();
|
||||
};
|
||||
|
||||
|
||||
+3
-7
@@ -417,12 +417,9 @@ AddJsonPackage(boost)
|
||||
set(BOOST_NO_HEADERS ${Boost_ADDED})
|
||||
|
||||
if (Boost_ADDED)
|
||||
if (MSVC OR ANDROID)
|
||||
add_compile_definitions(YUZU_BOOST_v1)
|
||||
endif()
|
||||
|
||||
add_compile_definitions(YUZU_BOOST_v1)
|
||||
if (NOT MSVC OR CXX_CLANG)
|
||||
# boost sucks
|
||||
# solaris sucks
|
||||
if (SOLARIS)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-pthreads>)
|
||||
endif()
|
||||
@@ -431,8 +428,7 @@ if (Boost_ADDED)
|
||||
target_compile_options(boost_icl INTERFACE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-shadow>)
|
||||
target_compile_options(boost_asio INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-conversion>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-implicit-fallthrough>
|
||||
)
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-implicit-fallthrough>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
+6
-9
@@ -6,22 +6,19 @@
|
||||
"version": "v0.19.0"
|
||||
},
|
||||
"boost": {
|
||||
"artifact": "%VERSION%-cmake.tar.xz",
|
||||
"artifact": "boost-%VERSION%.tar.zst",
|
||||
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
|
||||
"hash": "6ae6e94664fe7f2fb01976b59b276ac5df8085c7503fa829d810fbfe495960cfec44fa2c36e2cb23480bc19c956ed199d4952b02639a00a6c07625d4e7130c2d",
|
||||
"hash": "681d97be4386767662e230b2e7c9754d45e709cc5db4e747c23c27d1f5b0e87770bdf19b0bc44dcb0e8349324887bbb8fffb432098f4d0ce74a5043021a90afc",
|
||||
"min_version": "1.57",
|
||||
"package": "Boost",
|
||||
"patches": [
|
||||
"0001-clang-cl.patch"
|
||||
],
|
||||
"repo": "boostorg/boost",
|
||||
"version": "boost-1.90.0"
|
||||
"repo": "eden-emulator/ext-boost",
|
||||
"version": "1.92.0"
|
||||
},
|
||||
"boost_headers": {
|
||||
"bundled": true,
|
||||
"hash": "4ef845775e2277a8104ded6ddf749aa262ce52cf8438042869a048f9a0156dd772fbbcfa74efa1378fecef339b7286f6fe4b4feb5c45d49966b35d08e3e83507",
|
||||
"hash": "c5fa2cd72f6e6666b7963b97bc359c75284b8fb540c30f3629a028b85270c9bc66c8a051383964f2bd4c1e005a4691593d15696e7ef39ea87cf6cff9e5691fb2",
|
||||
"repo": "boostorg/headers",
|
||||
"version": "boost-1.90.0"
|
||||
"version": "boost-1.91.0"
|
||||
},
|
||||
"catch2": {
|
||||
"hash": "7eea385d79d88a5690cde131fe7ccda97d5c54ea09d6f515000d7bf07c828809d61c1ac99912c1ee507cf933f61c1c47ecdcc45df7850ffa82714034b0fccf35",
|
||||
|
||||
@@ -24,7 +24,7 @@ std::string NativeErrorToString(int e) {
|
||||
DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
|
||||
LPSTR(&err_str), 1, nullptr);
|
||||
if (!res) {
|
||||
return "(FormatMessageA failed to format error)";
|
||||
}
|
||||
@@ -32,9 +32,10 @@ std::string NativeErrorToString(int e) {
|
||||
LocalFree(err_str);
|
||||
return ret;
|
||||
#else
|
||||
char err_str[255];
|
||||
#if defined(__ANDROID__) || \
|
||||
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
|
||||
char err_str[256];
|
||||
// See https://github.com/llvm/llvm-project/blob/c8fdb5f8b93c3e1da5e2ff3ba8b18627d6147b51/openmp/runtime/src/kmp_i18n.cpp#L711
|
||||
// musl doesn't provide a macro gate but defines strerror_r() even if _GNU_SOURCE is defined
|
||||
#if defined(__managarm__) || (defined(__GLIBC__) || defined(__BIONIC__)) || defined(_GNU_SOURCE)
|
||||
// Thread safe (GNU-specific)
|
||||
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
||||
return std::string(str);
|
||||
|
||||
@@ -796,6 +796,8 @@ add_library(core STATIC
|
||||
hle/service/ns/application_manager_interface.h
|
||||
hle/service/ns/application_version_interface.cpp
|
||||
hle/service/ns/application_version_interface.h
|
||||
hle/service/ns/async_result.cpp
|
||||
hle/service/ns/async_result.h
|
||||
hle/service/ns/content_management_interface.cpp
|
||||
hle/service/ns/content_management_interface.h
|
||||
hle/service/ns/develop_interface.cpp
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "hid_core/frontend/emulated_controller.h"
|
||||
#include "hid_core/hid_core.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
#include <array>
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
@@ -29,23 +30,39 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
|
||||
|
||||
const std::size_t min_supported_players =
|
||||
parameters.enable_single_mode ? 1 : parameters.min_players;
|
||||
using Core::HID::NpadStyleIndex;
|
||||
const std::size_t max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
|
||||
std::size_t num_selected_players = 0;
|
||||
std::array<bool, HID::HIDCore::available_controllers> keep_connected{};
|
||||
|
||||
// Disconnect Handheld first.
|
||||
// reserve existing AND valid players before filling slots. include Handheld, but not other
|
||||
for (std::size_t index = 0; index < hid_core.available_controllers - 1; ++index) {
|
||||
const auto* controller = hid_core.GetEmulatedControllerByIndex(index);
|
||||
if (!parameters.keep_controllers_connected || !controller->IsConnected() || num_selected_players >= max_supported_players) continue;
|
||||
|
||||
const auto style = controller->GetNpadStyleIndex();
|
||||
keep_connected[index] =
|
||||
(style == NpadStyleIndex::Fullkey && parameters.allow_pro_controller) ||
|
||||
(style == NpadStyleIndex::JoyconDual && parameters.allow_dual_joycons) ||
|
||||
(style == NpadStyleIndex::JoyconLeft && parameters.allow_left_joycon) ||
|
||||
(style == NpadStyleIndex::JoyconRight && parameters.allow_right_joycon) ||
|
||||
(style == NpadStyleIndex::Handheld && parameters.enable_single_mode && parameters.allow_handheld && !Settings::IsDockedMode()) ||
|
||||
(style == NpadStyleIndex::GameCube && parameters.allow_gamecube_controller);
|
||||
num_selected_players += keep_connected[index];
|
||||
}
|
||||
auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
handheld->Disconnect();
|
||||
if (!keep_connected[hid_core.available_controllers - 2]) handheld->Disconnect();
|
||||
|
||||
// Deduce the best configuration based on the input parameters.
|
||||
for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) {
|
||||
auto* controller = hid_core.GetEmulatedControllerByIndex(index);
|
||||
|
||||
// First, disconnect all controllers regardless of the value of keep_controllers_connected.
|
||||
// This makes it easy to connect the desired controllers.
|
||||
if (keep_connected[index]) continue;
|
||||
controller->Disconnect();
|
||||
|
||||
// Only connect the minimum number of required players.
|
||||
if (index >= min_supported_players) {
|
||||
continue;
|
||||
}
|
||||
// only add players still needed to reach the minimum
|
||||
if (num_selected_players >= min_supported_players) continue;
|
||||
++num_selected_players;
|
||||
|
||||
// Connect controllers based on the following priority list from highest to lowest priority:
|
||||
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
|
||||
|
||||
@@ -228,9 +228,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{930, nullptr, "Unknown930"}, //20.0.0+
|
||||
{931, nullptr, "Unknown931"}, //20.0.0+
|
||||
{933, nullptr, "Unknown933"}, //20.0.0+
|
||||
{934, nullptr, "Unknown934"}, //20.0.0+
|
||||
{935, nullptr, "Unknown935"}, //20.0.0+
|
||||
{936, nullptr, "Unknown936"}, //20.0.0+
|
||||
{934, nullptr, "Unknown934"}, //21.0.0+
|
||||
{935, nullptr, "Unknown935"}, //21.0.0+
|
||||
{936, D<&IApplicationManagerInterface::Unknown936>, "Unknown936"}, //21.0.0+
|
||||
{1000, nullptr, "RequestVerifyApplicationDeprecated"},
|
||||
{1001, nullptr, "CorruptApplicationForDebug"},
|
||||
{1002, nullptr, "RequestVerifyAddOnContentsRights"},
|
||||
@@ -422,7 +422,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{4039, nullptr, "Unknown4039"}, //20.0.0+
|
||||
{4040, nullptr, "Unknown4040"}, //20.0.0+
|
||||
{4041, nullptr, "Unknown4041"}, //20.0.0+
|
||||
{4042, nullptr, "Unknown4042"}, //20.0.0+
|
||||
{4042, D<&IApplicationManagerInterface::Unknown4042>, "Unknown4042"}, //20.0.0+
|
||||
{4043, nullptr, "Unknown4043"}, //20.0.0+
|
||||
{4044, nullptr, "Unknown4044"}, //20.0.0+
|
||||
{4045, nullptr, "Unknown4045"}, //20.0.0+
|
||||
@@ -639,6 +639,12 @@ Result IApplicationManagerInterface::IsGameCardApplicationRunning(Out<bool> out_
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::Unknown936(Out<u64> out_result) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called.");
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
|
||||
Out<bool> out_is_any_application_entity_installed) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
@@ -862,6 +868,15 @@ Result IApplicationManagerInterface::Unknown4023(Out<u64> out_result) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::Unknown4042(OutInterface<IAsyncResult> out_interface,
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event,
|
||||
u64 arg1, u64 arg2) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, arg1={:016X}, arg2={:016X}", arg1, arg2);
|
||||
*out_event = unknown_event.GetHandle();
|
||||
*out_interface = std::make_shared<IAsyncResult>(system, &unknown_event);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::Unknown4053() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called.");
|
||||
R_SUCCEED();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/async_result.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/os/event.h"
|
||||
@@ -34,6 +35,7 @@ public:
|
||||
Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetGameCardWakenReadyEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result IsGameCardApplicationRunning(Out<bool> out_is_running);
|
||||
Result Unknown936(Out<u64> out_result);
|
||||
Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
|
||||
Result GetApplicationViewDeprecated(
|
||||
OutArray<ApplicationViewV19, BufferAttr_HipcMapAlias> out_application_views,
|
||||
@@ -71,6 +73,9 @@ public:
|
||||
InBuffer<BufferAttr_HipcMapAlias> logo_path_buffer);
|
||||
Result Unknown4022(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result Unknown4023(Out<u64> out_result);
|
||||
Result Unknown4042(OutInterface<IAsyncResult> out_interface,
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event,
|
||||
u64 arg1, u64 arg2);
|
||||
Result Unknown4053();
|
||||
Result Unknown4105();
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/async_result.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IAsyncResult::IAsyncResult(Core::System& system_, Service::Event* event_)
|
||||
: ServiceFramework{system_, "nn::ns::detail::IAsyncResult"}, event{event_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Get"},
|
||||
{1, D<&IAsyncResult::Cancel>, "Cancel"},
|
||||
{2, nullptr, "GetErrorContext"}, // 4.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IAsyncResult::~IAsyncResult() = default;
|
||||
|
||||
Result IAsyncResult::Cancel() {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
if (event != nullptr) {
|
||||
event->Signal(system.Kernel());
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IAsyncResult final : public ServiceFramework<IAsyncResult> {
|
||||
public:
|
||||
explicit IAsyncResult(Core::System& system_, Service::Event* event_);
|
||||
~IAsyncResult() override;
|
||||
|
||||
private:
|
||||
Result Cancel();
|
||||
|
||||
Service::Event* event{};
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
||||
@@ -311,27 +311,30 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
|
||||
// u64 - app count
|
||||
memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64));
|
||||
out_length += sizeof(u64);
|
||||
ASSERT(out_length <= t_mem->GetSize());
|
||||
// [list of u64] - size of icons
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
u64 full_size = control.second->GetSize();
|
||||
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
|
||||
if (const auto control = pm.GetControlMetadata(); control.second) {
|
||||
u64 full_size = control.second->GetSize();
|
||||
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
|
||||
}
|
||||
out_length += sizeof(u64);
|
||||
ASSERT(out_length <= t_mem->GetSize());
|
||||
}
|
||||
// [list of raw icon data]
|
||||
std::vector<u8> full_icon_data;
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
auto const full_size = control.second->GetSize();
|
||||
if (full_size > 0) {
|
||||
full_icon_data.resize(full_size);
|
||||
control.second->Read(full_icon_data.data(), full_size, 0);
|
||||
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
|
||||
out_length += full_size;
|
||||
if (const auto control = pm.GetControlMetadata(); control.second) {
|
||||
if (auto const full_size = control.second->GetSize(); full_size > 0) {
|
||||
std::vector<u8> full_icon_data(full_size);
|
||||
control.second->Read(full_icon_data.data(), full_size, 0);
|
||||
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
|
||||
out_length += full_size;
|
||||
ASSERT(out_length <= t_mem->GetSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,6 +348,12 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
|
||||
std::vector<u64> application_ids(app_count);
|
||||
if (app_count > 0) {
|
||||
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
|
||||
}
|
||||
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
|
||||
@@ -354,8 +363,9 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestCo
|
||||
auto& memory = system.ApplicationMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const u64 app_id = application_ids[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
FileSys::LanguageEntry entry{};
|
||||
if (control.first != nullptr) {
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ConfigurationShared {
|
||||
|
||||
std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
||||
std::unique_ptr<TranslationMap> translations = std::make_unique<TranslationMap>();
|
||||
const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); };
|
||||
const auto& tr = [](const char* text) -> QString { return QCoreApplication::translate("ConfigurationShared", text); };
|
||||
|
||||
#define INSERT(SETTINGS, ID, NAME, TOOLTIP) \
|
||||
translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{(NAME), (TOOLTIP)}})
|
||||
@@ -151,6 +151,9 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
||||
tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA "
|
||||
"can produce a more stable picture in lower resolutions."));
|
||||
INSERT(Settings, post_shader_chain, QString(), QString());
|
||||
INSERT(Settings, post_shader_preset, QString(), QString());
|
||||
INSERT(Settings, post_shader_enabled, tr("Enable post-processing effects"),
|
||||
tr("Applies post-processing effects to the final image."));
|
||||
INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"),
|
||||
tr("The method used to render the window in fullscreen.\nBorderless offers the best "
|
||||
"compatibility with the on-screen keyboard that some games request for "
|
||||
@@ -368,8 +371,8 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
||||
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent) {
|
||||
std::unique_ptr<ComboboxTranslationMap> translations =
|
||||
std::make_unique<ComboboxTranslationMap>();
|
||||
const auto& tr = [&](const char* text, const char* context = "") {
|
||||
return parent->tr(text, context);
|
||||
const auto& tr = [](const char* text, const char* context = "") {
|
||||
return QCoreApplication::translate("ConfigurationShared", text, context);
|
||||
};
|
||||
|
||||
#define PAIR(ENUM, VALUE, TRANSLATION) {static_cast<u32>(Settings::ENUM::VALUE), (TRANSLATION)}
|
||||
|
||||
@@ -2850,8 +2850,6 @@ Sampler::VariantKey Sampler::MakeKey(const ImageView& image_view, bool is_depth)
|
||||
VariantKey key{};
|
||||
key.reduce_anisotropy = has_added_anisotropy && !image_view.SupportsAnisotropy();
|
||||
key.force_nearest = has_linear_filtering && IsPixelFormatInteger(image_view.format);
|
||||
key.drop_depth_comparison =
|
||||
is_depth && has_depth_comparison && !image_view.SupportsDepthComparison();
|
||||
key.drop_reduction = has_minmax_reduction && !image_view.SupportsMinmaxFilter();
|
||||
key.drop_custom_border = has_custom_border_colors && image_view.RequiresBorderColorFormat();
|
||||
key.srgb_border = has_srgb_border_color && IsPixelFormatSRGB(image_view.format);
|
||||
@@ -2929,9 +2927,6 @@ VkSampler Sampler::Emplace(VariantKey key) {
|
||||
create_info.anisotropyEnable = static_cast<VkBool32>(default_anisotropy > 1.0f);
|
||||
create_info.maxAnisotropy = default_anisotropy;
|
||||
}
|
||||
if (key.drop_depth_comparison) {
|
||||
create_info.compareEnable = VK_FALSE;
|
||||
}
|
||||
if (!custom_border) {
|
||||
create_info.borderColor = ConvertBorderColor(color);
|
||||
}
|
||||
|
||||
@@ -536,7 +536,6 @@ private:
|
||||
struct VariantKey {
|
||||
bool reduce_anisotropy;
|
||||
bool force_nearest;
|
||||
bool drop_depth_comparison;
|
||||
bool drop_reduction;
|
||||
bool drop_custom_border;
|
||||
bool srgb_border;
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
#include "yuzu/configuration/configure_graphics.h"
|
||||
#include "yuzu/configuration/shared_widget.h"
|
||||
|
||||
#ifdef HAS_RESHADE
|
||||
#include "yuzu/configuration/configure_post_processing.h"
|
||||
#endif
|
||||
|
||||
ConfigureGraphics::ConfigureGraphics(
|
||||
const Core::System& system_, std::vector<VkDeviceInfo::Record>& records_,
|
||||
const std::function<void()>& expose_compute_option_,
|
||||
@@ -216,6 +220,12 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
|
||||
std::vector<QWidget*> hold_api;
|
||||
|
||||
for (const auto setting : Settings::values.linkage.by_category[Settings::Category::Renderer]) {
|
||||
#ifndef HAS_RESHADE
|
||||
if (setting->Id() == Settings::values.post_shader_enabled.Id()) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
ConfigurationShared::Widget* widget = [&]() {
|
||||
if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) {
|
||||
// FSR needs a reversed slider and a 0.5 multiplier
|
||||
@@ -295,6 +305,23 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
|
||||
// Keep track of the resolution combobox to update other UI tabs that need it
|
||||
resolution_combobox = widget->combobox;
|
||||
hold_graphics.emplace(setting->Id(), widget);
|
||||
#ifdef HAS_RESHADE
|
||||
} else if (setting->Id() == Settings::values.post_shader_enabled.Id()) {
|
||||
QPushButton* post_shader_button = new QPushButton(tr("Configure Effects..."), widget);
|
||||
post_shader_button->setVisible(widget->checkbox->isChecked());
|
||||
|
||||
connect(post_shader_button, &QAbstractButton::clicked, this, [this]() {
|
||||
ConfigurePostProcessing dialog(this);
|
||||
dialog.exec();
|
||||
});
|
||||
connect(widget->checkbox, &QCheckBox::toggled, post_shader_button,
|
||||
&QWidget::setVisible);
|
||||
|
||||
QBoxLayout* row = qobject_cast<QBoxLayout*>(widget->layout());
|
||||
row->insertWidget(1, post_shader_button);
|
||||
|
||||
hold_graphics.emplace(setting->Id(), widget);
|
||||
#endif
|
||||
} else {
|
||||
hold_graphics.emplace(setting->Id(), widget);
|
||||
}
|
||||
|
||||
@@ -70,10 +70,8 @@ ConfigurePostProcessing::ConfigurePostProcessing(QWidget* parent) : QDialog(pare
|
||||
|
||||
auto* root = new QVBoxLayout(this);
|
||||
|
||||
auto* description = new QLabel(
|
||||
tr("ReShade FX effects are loaded from the post_shaders folder in the Eden data "
|
||||
"directory. Changes apply immediately while a game is running."),
|
||||
this);
|
||||
auto* description =
|
||||
new QLabel(tr("Changes apply immediately while a game is running."), this);
|
||||
description->setWordWrap(true);
|
||||
root->addWidget(description);
|
||||
|
||||
@@ -128,17 +126,15 @@ ConfigurePostProcessing::ConfigurePostProcessing(QWidget* parent) : QDialog(pare
|
||||
});
|
||||
preset_row->addWidget(save_button);
|
||||
|
||||
auto* delete_button = new QPushButton(tr("Delete"), this);
|
||||
connect(delete_button, &QPushButton::clicked, this, [this]() {
|
||||
const QString name = preset_combo->currentData().toString();
|
||||
if (name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
VideoCore::DeleteFxPreset(name.toStdString());
|
||||
PopulatePresetCombo();
|
||||
RefreshPresetStatus();
|
||||
auto* clear_button = new QPushButton(tr("Clear"), this);
|
||||
clear_button->setToolTip(tr("Remove every effect in use and deselect the preset."));
|
||||
connect(clear_button, &QPushButton::clicked, this, [this]() {
|
||||
VideoCore::FxChain::Instance().Clear();
|
||||
VideoCore::SetActiveFxPreset(std::string());
|
||||
preset_combo->setCurrentIndex(0);
|
||||
ApplyStructuralChange();
|
||||
});
|
||||
preset_row->addWidget(delete_button);
|
||||
preset_row->addWidget(clear_button);
|
||||
|
||||
root->addLayout(preset_row);
|
||||
|
||||
@@ -203,6 +199,7 @@ void ConfigurePostProcessing::ApplyStructuralChange() {
|
||||
void ConfigurePostProcessing::PopulatePresetCombo() {
|
||||
const QString previous = preset_combo->currentData().toString();
|
||||
preset_combo->clear();
|
||||
preset_combo->addItem(tr("None"), QString());
|
||||
|
||||
for (const auto& preset : VideoCore::GetFxPresetCatalog()) {
|
||||
const QString name = QString::fromStdString(preset.name);
|
||||
@@ -212,7 +209,7 @@ void ConfigurePostProcessing::PopulatePresetCombo() {
|
||||
}
|
||||
|
||||
const int restored = preset_combo->findData(previous);
|
||||
if (restored >= 0) {
|
||||
if (!previous.isEmpty() && restored >= 0) {
|
||||
preset_combo->setCurrentIndex(restored);
|
||||
return;
|
||||
}
|
||||
@@ -220,12 +217,21 @@ void ConfigurePostProcessing::PopulatePresetCombo() {
|
||||
const int active = preset_combo->findData(QString::fromStdString(VideoCore::GetActiveFxPreset()));
|
||||
if (active >= 0) {
|
||||
preset_combo->setCurrentIndex(active);
|
||||
return;
|
||||
}
|
||||
|
||||
preset_combo->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void ConfigurePostProcessing::RefreshPresetStatus() {
|
||||
const std::string active = VideoCore::GetActiveFxPreset();
|
||||
if (active.empty()) {
|
||||
if (VideoCore::FxChain::Instance().Size() == 0) {
|
||||
preset_status->setText(
|
||||
tr("No effects in use. Pick a preset and press Apply, or add effects one "
|
||||
"by one."));
|
||||
return;
|
||||
}
|
||||
preset_status->setText(tr("Custom chain. Pick a preset above and press Apply to replace it."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "render/performance_overlay.h"
|
||||
#ifdef HAS_RESHADE
|
||||
#include "configuration/configure_post_processing.h"
|
||||
#include "video_core/post_processing/fx_preset.h"
|
||||
#endif
|
||||
#include "updater/update_dialog.h"
|
||||
|
||||
@@ -1090,6 +1091,41 @@ void MainWindow::InitializeWidgets() {
|
||||
|
||||
statusBar()->insertPermanentWidget(0, volume_button);
|
||||
|
||||
#ifdef HAS_RESHADE
|
||||
post_shader_status_button = new QPushButton();
|
||||
post_shader_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
|
||||
post_shader_status_button->setFocusPolicy(Qt::NoFocus);
|
||||
post_shader_status_button->setCheckable(true);
|
||||
connect(post_shader_status_button, &QPushButton::clicked, this, [this] {
|
||||
const bool enabled = Settings::values.post_shader_enabled.GetValue();
|
||||
Settings::values.post_shader_enabled.SetValue(!enabled);
|
||||
UpdatePostShaderText();
|
||||
});
|
||||
UpdatePostShaderText();
|
||||
post_shader_status_button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(post_shader_status_button, &QPushButton::customContextMenuRequested,
|
||||
[this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
|
||||
for (auto const& preset : VideoCore::GetFxPresetCatalog()) {
|
||||
context_menu.addAction(QString::fromStdString(preset.name),
|
||||
[this, name = preset.name] {
|
||||
VideoCore::ApplyFxPreset(name);
|
||||
Settings::values.post_shader_enabled.SetValue(true);
|
||||
UpdatePostShaderText();
|
||||
});
|
||||
}
|
||||
|
||||
context_menu.addSeparator();
|
||||
context_menu.addAction(tr("Configure Effects..."), this,
|
||||
&MainWindow::OnPostProcessingShaders);
|
||||
|
||||
context_menu.exec(post_shader_status_button->mapToGlobal(menu_location));
|
||||
post_shader_status_button->repaint();
|
||||
});
|
||||
statusBar()->insertPermanentWidget(0, post_shader_status_button);
|
||||
#endif
|
||||
|
||||
// setup AA button
|
||||
aa_status_button = new QPushButton();
|
||||
aa_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
|
||||
@@ -3908,6 +3944,7 @@ void MainWindow::OnPostProcessingShaders() {
|
||||
connect(post_processing_dialog, &QDialog::finished, post_processing_dialog, [this]() {
|
||||
post_processing_dialog->deleteLater();
|
||||
post_processing_dialog = nullptr;
|
||||
UpdatePostShaderText();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4262,6 +4299,26 @@ void MainWindow::UpdateAAText() {
|
||||
: aa_text.toUpper());
|
||||
}
|
||||
|
||||
#ifdef HAS_RESHADE
|
||||
void MainWindow::UpdatePostShaderText() {
|
||||
const bool enabled = Settings::values.post_shader_enabled.GetValue();
|
||||
post_shader_status_button->setChecked(enabled);
|
||||
|
||||
if (!enabled) {
|
||||
post_shader_status_button->setText(tr("NO FX"));
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string preset = VideoCore::GetActiveFxPreset();
|
||||
if (preset.empty()) {
|
||||
post_shader_status_button->setText(tr("FX"));
|
||||
return;
|
||||
}
|
||||
|
||||
post_shader_status_button->setText(QString::fromStdString(preset).toUpper());
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::UpdateVolumeUI() {
|
||||
const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
|
||||
volume_slider->setValue(volume_value);
|
||||
|
||||
@@ -448,6 +448,7 @@ private:
|
||||
void UpdateAPIText();
|
||||
void UpdateFilterText();
|
||||
void UpdateAAText();
|
||||
void UpdatePostShaderText();
|
||||
void UpdateVolumeUI();
|
||||
void UpdateStatusBar();
|
||||
void UpdateGPUAccuracyButton();
|
||||
@@ -524,6 +525,7 @@ private:
|
||||
QPushButton* dock_status_button = nullptr;
|
||||
QPushButton* filter_status_button = nullptr;
|
||||
QPushButton* aa_status_button = nullptr;
|
||||
QPushButton* post_shader_status_button = nullptr;
|
||||
VolumeButton* volume_button = nullptr;
|
||||
QWidget* volume_popup = nullptr;
|
||||
QSlider* volume_slider = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user