From c725641f13772aa7d5705227e8fbe2c5b85ebb6a Mon Sep 17 00:00:00 2001 From: MaranBr Date: Sun, 28 Sep 2025 07:29:19 +0200 Subject: [PATCH 01/12] [video_core] Fix fast buffers without performance loss (#2605) Fixes games that have some elements flickering on the screen, such as Kirby Star Allies and others, without impacting performance. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2605 Reviewed-by: CamilleLaVey Reviewed-by: Lizzie Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/video_core/buffer_cache/buffer_cache.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index eb18a4bd66..6f6e0c23a8 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -785,18 +785,13 @@ void BufferCache

::BindHostGraphicsUniformBuffers(size_t stage) { } template -void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, - bool needs_bind) { +void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, bool needs_bind) { + ++channel_state->uniform_cache_shots[0]; const Binding& binding = channel_state->uniform_buffers[stage][index]; const DAddr device_addr = binding.device_addr; const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); - const bool sync_buffer = SynchronizeBuffer(buffer, device_addr, size); - if (sync_buffer) { - ++channel_state->uniform_cache_hits[0]; - } - ++channel_state->uniform_cache_shots[0]; const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && size <= channel_state->uniform_buffer_skip_cache_size && !memory_tracker.IsRegionGpuModified(device_addr, size); @@ -827,7 +822,10 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 device_memory.ReadBlockUnsafe(device_addr, span.data(), size); return; } - + // Classic cached path + if (SynchronizeBuffer(buffer, device_addr, size)) { + ++channel_state->uniform_cache_hits[0]; + } // Skip binding if it's not needed and if the bound buffer is not the fast version // This exists to avoid instances where the fast buffer is bound and a GPU write happens needs_bind |= HasFastUniformBufferBound(stage, binding_index); From d19a7c3782d8402a5c3d8c730fb2ef080da7a8b5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Sep 2025 18:43:01 +0200 Subject: [PATCH 02/12] [service] unstub process winding (#2590) It's used on FW19+ and FW20+ but since all 20+ applets stuck on HID, you still can't boot into applets. Should fix: Bioshock Infinite on FW19 Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2590 Reviewed-by: Shinmegumi Reviewed-by: MaranBr Co-authored-by: unknown Co-committed-by: unknown --- src/core/hle/service/am/applet.h | 5 ++ .../am/service/process_winding_controller.cpp | 54 ++++++++++++++++--- .../am/service/process_winding_controller.h | 10 ++++ .../service/am/service/self_controller.cpp | 12 +++++ .../hle/service/am/service/self_controller.h | 4 ++ 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index 6cc8cdf741..ad84f39dc7 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -8,6 +8,7 @@ #include #include +#include #include "common/math_util.h" #include "core/hle/service/apm/apm_controller.h" @@ -23,6 +24,7 @@ #include "core/hle/service/am/hid_registration.h" #include "core/hle/service/am/lifecycle_manager.h" #include "core/hle/service/am/process_holder.h" +#include "core/hle/service/am/service/storage.h" namespace Service::AM { @@ -97,6 +99,9 @@ struct Applet { std::deque> preselected_user_launch_parameter{}; std::deque> friend_invitation_storage_channel{}; + // Context Stack + std::stack> context_stack{}; + // Caller applet std::weak_ptr caller_applet{}; std::shared_ptr caller_applet_broker{}; diff --git a/src/core/hle/service/am/service/process_winding_controller.cpp b/src/core/hle/service/am/service/process_winding_controller.cpp index 10df830d70..30529de550 100644 --- a/src/core/hle/service/am/service/process_winding_controller.cpp +++ b/src/core/hle/service/am/service/process_winding_controller.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,12 +18,12 @@ IProcessWindingController::IProcessWindingController(Core::System& system_, static const FunctionInfo functions[] = { {0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"}, {11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"}, - {21, nullptr, "PushContext"}, - {22, nullptr, "PopContext"}, - {23, nullptr, "CancelWindingReservation"}, - {30, nullptr, "WindAndDoReserved"}, - {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, - {41, nullptr, "ReserveToStartAndWait"}, + {21, D<&IProcessWindingController::PushContext>, "PushContext"}, + {22, D<&IProcessWindingController::PopContext>, "PopContext"}, + {23, D<&IProcessWindingController::CancelWindingReservation>, "CancelWindingReservation"}, + {30, D<&IProcessWindingController::WindAndDoReserved>, "WindAndDoReserved"}, + {40, D<&IProcessWindingController::ReserveToStartAndWaitAndUnwindThis>, "ReserveToStartAndWaitAndUnwindThis"}, + {41, D<&IProcessWindingController::ReserveToStartAndWait>, "ReserveToStartAndWait"}, }; // clang-format on @@ -51,4 +54,43 @@ Result IProcessWindingController::OpenCallingLibraryApplet( R_SUCCEED(); } +Result IProcessWindingController::PushContext(SharedPointer context) { + LOG_INFO(Service_AM, "called"); + m_applet->context_stack.push(context); + R_SUCCEED(); +} + +Result IProcessWindingController::PopContext(Out> out_context) { + LOG_INFO(Service_AM, "called"); + + if (m_applet->context_stack.empty()) { + LOG_ERROR(Service_AM, "Context stack is empty"); + R_THROW(ResultUnknown); + } + + *out_context = m_applet->context_stack.top(); + m_applet->context_stack.pop(); + R_SUCCEED(); +} + +Result IProcessWindingController::CancelWindingReservation() { + LOG_WARNING(Service_AM, "STUBBED"); + R_SUCCEED(); +} + +Result IProcessWindingController::WindAndDoReserved() { + LOG_WARNING(Service_AM, "STUBBED"); + R_SUCCEED(); +} + +Result IProcessWindingController::ReserveToStartAndWaitAndUnwindThis() { + LOG_WARNING(Service_AM, "STUBBED"); + R_SUCCEED(); +} + +Result IProcessWindingController::ReserveToStartAndWait() { + LOG_WARNING(Service_AM, "STUBBED"); + R_SUCCEED(); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/service/process_winding_controller.h b/src/core/hle/service/am/service/process_winding_controller.h index 4408af1f1d..0d53223033 100644 --- a/src/core/hle/service/am/service/process_winding_controller.h +++ b/src/core/hle/service/am/service/process_winding_controller.h @@ -1,8 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once +#include "core/hle/service/am/service/storage.h" #include "core/hle/service/am/am_types.h" #include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" @@ -21,6 +25,12 @@ private: Result GetLaunchReason(Out out_launch_reason); Result OpenCallingLibraryApplet( Out> out_calling_library_applet); + Result PushContext(SharedPointer in_context); + Result PopContext(Out> out_context); + Result CancelWindingReservation(); + Result WindAndDoReserved(); + Result ReserveToStartAndWaitAndUnwindThis(); + Result ReserveToStartAndWait(); const std::shared_ptr m_applet; }; diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 1db02b88fd..1b58cbea27 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -67,6 +70,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr {110, nullptr, "SetApplicationAlbumUserData"}, {120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"}, {130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"}, + {230, D<&ISelfController::Unknown230>, "Unknown230"}, {1000, nullptr, "GetDebugStorageChannel"}, }; // clang-format on @@ -404,4 +408,12 @@ Result ISelfController::SetRecordVolumeMuted(bool muted) { R_SUCCEED(); } +Result ISelfController::Unknown230(u32 in_val, Out out_val) { + LOG_WARNING(Service_AM, "(STUBBED) called, in_val={}", in_val); + + *out_val = 0; + + R_SUCCEED(); +} + } // namespace Service::AM diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h index eca083cfe5..86cd9f1118 100644 --- a/src/core/hle/service/am/service/self_controller.h +++ b/src/core/hle/service/am/service/self_controller.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -63,6 +66,7 @@ private: Result SetAlbumImageTakenNotificationEnabled(bool enabled); Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); Result SetRecordVolumeMuted(bool muted); + Result Unknown230(u32 in_val, Out out_val); Kernel::KProcess* const m_process; const std::shared_ptr m_applet; From 6dbc3e96016869ea23b2592818f65ea8491156bd Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 28 Sep 2025 18:03:09 +0000 Subject: [PATCH 03/12] [dynarmic] get rid of mcl intrusive list Signed-off-by: lizzie --- .../src/dynarmic/backend/x64/emit_x64.cpp | 5 ----- .../src/dynarmic/backend/x64/emit_x64.h | 2 -- src/dynarmic/src/dynarmic/ir/basic_block.cpp | 2 +- src/dynarmic/src/dynarmic/ir/basic_block.h | 5 ++--- src/dynarmic/src/dynarmic/ir/ir_emitter.h | 15 +++---------- .../src/dynarmic/ir/microinstruction.h | 5 ++--- src/dynarmic/src/dynarmic/ir/opt_passes.cpp | 22 +++++++++---------- 7 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index 3bc93e6fd5..3c41664464 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -38,11 +38,6 @@ EmitContext::EmitContext(RegAlloc& reg_alloc, IR::Block& block) EmitContext::~EmitContext() = default; -void EmitContext::EraseInstruction(IR::Inst* inst) { - block.Instructions().erase(inst); - inst->ClearArgs(); -} - EmitX64::EmitX64(BlockOfCode& code) : code(code) { exception_handler.Register(code); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index fbe749b2ab..5f0019b62e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -54,8 +54,6 @@ struct EmitContext { EmitContext(RegAlloc& reg_alloc, IR::Block& block); virtual ~EmitContext(); - void EraseInstruction(IR::Inst* inst); - virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0; virtual bool HasOptimization(OptimizationFlag flag) const = 0; diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp index b00ab3cb20..6100303faa 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp +++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp @@ -46,7 +46,7 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s inst->SetArg(index, arg); index++; }); - return instructions.insert_before(insertion_point, inst); + return instructions.insert(insertion_point, *inst);; } static std::string TerminalToString(const Terminal& terminal_variant) noexcept { diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.h b/src/dynarmic/src/dynarmic/ir/basic_block.h index e88dc92fc4..6757bfafc6 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.h +++ b/src/dynarmic/src/dynarmic/ir/basic_block.h @@ -12,10 +12,9 @@ #include #include #include +#include -#include #include "dynarmic/common/common_types.h" - #include "dynarmic/ir/location_descriptor.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/terminal.h" @@ -35,7 +34,7 @@ enum class Opcode; class Block final { public: //using instruction_list_type = dense_list; - using instruction_list_type = mcl::intrusive_list; + using instruction_list_type = boost::intrusive::list; using size_type = instruction_list_type::size_type; using iterator = instruction_list_type::iterator; using const_iterator = instruction_list_type::const_iterator; diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h index dba34bcc56..6f00cec8ac 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -10,10 +10,10 @@ #include -#include "dynarmic/common/common_types.h" -#include "dynarmic/common/assert.h" #include +#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/acc_type.h" #include "dynarmic/ir/basic_block.h" @@ -124,7 +124,7 @@ public: ASSERT(value.GetType() == Type::U64); return value; } - ASSERT_FALSE("Invalid bitsize"); + ASSERT_MSG(false, "Invalid bitsize"); } U32 LeastSignificantWord(const U64& value) { @@ -2950,19 +2950,10 @@ public: block.SetTerminal(terminal); } - void SetInsertionPointBefore(IR::Inst* new_insertion_point) { - insertion_point = IR::Block::iterator{*new_insertion_point}; - } - void SetInsertionPointBefore(IR::Block::iterator new_insertion_point) { insertion_point = new_insertion_point; } - void SetInsertionPointAfter(IR::Inst* new_insertion_point) { - insertion_point = IR::Block::iterator{*new_insertion_point}; - ++insertion_point; - } - void SetInsertionPointAfter(IR::Block::iterator new_insertion_point) { insertion_point = new_insertion_point; ++insertion_point; diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index 6651aab7c5..9e8febfcd5 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -9,10 +9,9 @@ #pragma once #include +#include -#include #include "dynarmic/common/common_types.h" - #include "dynarmic/ir/value.h" #include "dynarmic/ir/opcodes.h" @@ -26,7 +25,7 @@ constexpr size_t max_arg_count = 4; /// A representation of a microinstruction. A single ARM/Thumb instruction may be /// converted into zero or more microinstructions. //class Inst final { -class Inst final : public mcl::intrusive_list_node { +class Inst final : public boost::intrusive::list_base_hook<> { public: explicit Inst(Opcode op) : op(op) {} diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 844e29023c..56815065fb 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -85,12 +85,10 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { } static void FlagsPass(IR::Block& block) { - using Iterator = std::reverse_iterator; - struct FlagInfo { bool set_not_required = false; bool has_value_request = false; - Iterator value_request = {}; + IR::Block::reverse_iterator value_request = {}; }; struct ValuelessFlagInfo { bool set_not_required = false; @@ -101,7 +99,7 @@ static void FlagsPass(IR::Block& block) { FlagInfo c_flag; FlagInfo ge; - auto do_set = [&](FlagInfo& info, IR::Value value, Iterator inst) { + auto do_set = [&](FlagInfo& info, IR::Value value, IR::Block::reverse_iterator const inst) { if (info.has_value_request) { info.value_request->ReplaceUsesWith(value); } @@ -113,14 +111,14 @@ static void FlagsPass(IR::Block& block) { info.set_not_required = true; }; - auto do_set_valueless = [&](ValuelessFlagInfo& info, Iterator inst) { + auto do_set_valueless = [&](ValuelessFlagInfo& info, IR::Block::reverse_iterator const inst) { if (info.set_not_required) { inst->Invalidate(); } info.set_not_required = true; }; - auto do_get = [](FlagInfo& info, Iterator inst) { + auto do_get = [](FlagInfo& info, IR::Block::reverse_iterator const inst) { if (info.has_value_request) { info.value_request->ReplaceUsesWith(IR::Value{&*inst}); } @@ -447,7 +445,8 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) return; } - for (auto& inst : block) { + for (auto it = block.begin(); it != block.end(); it++) { + auto& inst = *it; if (inst.GetOpcode() != IR::Opcode::A64DataCacheOperationRaised) { continue; } @@ -456,7 +455,7 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) if (op == A64::DataCacheOperation::ZeroByVA) { A64::IREmitter ir{block}; ir.current_location = A64::LocationDescriptor{IR::LocationDescriptor{inst.GetArg(0).GetU64()}}; - ir.SetInsertionPointBefore(&inst); + ir.SetInsertionPointBefore(it); size_t bytes = 4 << static_cast(conf.dczid_el0 & 0b1111); IR::U64 addr{inst.GetArg(2)}; @@ -1243,7 +1242,7 @@ static void IdentityRemovalPass(IR::Block& block) { } if (inst.GetOpcode() == IR::Opcode::Identity || inst.GetOpcode() == IR::Opcode::Void) { - iter = block.Instructions().erase(inst); + iter = block.Instructions().erase(iter); to_invalidate.push_back(&inst); } else { ++iter; @@ -1405,8 +1404,9 @@ static void PolyfillPass(IR::Block& block, const PolyfillOptions& polyfill) { IR::IREmitter ir{block}; - for (auto& inst : block) { - ir.SetInsertionPointBefore(&inst); + for (auto it = block.begin(); it != block.end(); it++) { + auto& inst = *it; + ir.SetInsertionPointBefore(it); switch (inst.GetOpcode()) { case IR::Opcode::SHA256MessageSchedule0: From 0bb6e12cc442d5a537e5c780f8b9aeec56e16a74 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 28 Sep 2025 18:04:38 +0000 Subject: [PATCH 04/12] fix license Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/x64/emit_x64.h | 3 +++ src/dynarmic/src/dynarmic/ir/basic_block.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index 5f0019b62e..87801a7208 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp index 6100303faa..7316c3d4f7 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp +++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp @@ -46,7 +46,7 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s inst->SetArg(index, arg); index++; }); - return instructions.insert(insertion_point, *inst);; + return instructions.insert(insertion_point, *inst); } static std::string TerminalToString(const Terminal& terminal_variant) noexcept { From bf302d7917f2bd4b2638ac61a751fedd5727c7a6 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Sep 2025 18:40:29 +0200 Subject: [PATCH 05/12] [common] No need to specify min/max for settings; fix crash when OOB value is given for some settings (#2609) This fixes issues when migrating settings that refer to invalid filters/scales. For example if we had 5 filters, but we set filter=6, the program would crash. This also makes so specifying min/max manually isn't needed (but can still be set for cases like NCE). Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2609 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/settings.h | 41 ++----- src/common/settings_enums.h | 120 ++++++++------------- src/common/settings_setting.h | 67 ++++++------ src/yuzu/configuration/configure_audio.cpp | 6 +- 4 files changed, 84 insertions(+), 150 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 8605445837..891bde608c 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -178,7 +178,7 @@ struct Values { SwitchableSetting audio_input_device_id{ linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; SwitchableSetting sound_index{ - linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, + linkage, AudioMode::Stereo, "sound_index", Category::SystemAudio, Specialization::Default, true, true}; SwitchableSetting volume{linkage, @@ -199,8 +199,6 @@ struct Values { SwitchableSetting use_multi_core{linkage, true, "use_multi_core", Category::Core}; SwitchableSetting memory_layout_mode{linkage, MemoryLayout::Memory_4Gb, - MemoryLayout::Memory_4Gb, - MemoryLayout::Memory_12Gb, "memory_layout_mode", Category::Core, Specialization::Default, @@ -240,9 +238,8 @@ struct Values { #endif "cpu_backend", Category::Cpu}; - SwitchableSetting cpu_accuracy{linkage, CpuAccuracy::Auto, - CpuAccuracy::Auto, CpuAccuracy::Paranoid, - "cpu_accuracy", Category::Cpu}; + SwitchableSetting cpu_accuracy{linkage, CpuAccuracy::Auto, + "cpu_accuracy", Category::Cpu}; SwitchableSetting use_fast_cpu_time{linkage, false, @@ -324,10 +321,10 @@ struct Values { // Renderer SwitchableSetting renderer_backend{ - linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, + linkage, RendererBackend::Vulkan, "backend", Category::Renderer}; SwitchableSetting shader_backend{ - linkage, ShaderBackend::SpirV, ShaderBackend::Glsl, ShaderBackend::SpirV, + linkage, ShaderBackend::SpirV, "shader_backend", Category::Renderer, Specialization::RuntimeList}; SwitchableSetting vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, Specialization::RuntimeList}; @@ -342,8 +339,6 @@ struct Values { Category::Renderer}; SwitchableSetting optimize_spirv_output{linkage, SpirvOptimizeMode::Never, - SpirvOptimizeMode::Never, - SpirvOptimizeMode::Always, "optimize_spirv_output", Category::Renderer}; SwitchableSetting use_asynchronous_gpu_emulation{ @@ -354,12 +349,10 @@ struct Values { #else AstcDecodeMode::Gpu, #endif - AstcDecodeMode::Cpu, - AstcDecodeMode::CpuAsynchronous, "accelerate_astc", Category::Renderer}; SwitchableSetting vsync_mode{ - linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed, + linkage, VSyncMode::Fifo, "use_vsync", Category::Renderer, Specialization::RuntimeList, true, true}; SwitchableSetting nvdec_emulation{linkage, NvdecEmulation::Gpu, @@ -372,8 +365,6 @@ struct Values { #else FullscreenMode::Exclusive, #endif - FullscreenMode::Borderless, - FullscreenMode::Exclusive, "fullscreen_mode", Category::Renderer, Specialization::Default, @@ -381,8 +372,6 @@ struct Values { true}; SwitchableSetting aspect_ratio{linkage, AspectRatio::R16_9, - AspectRatio::R16_9, - AspectRatio::Stretch, "aspect_ratio", Category::Renderer, Specialization::Default, @@ -430,8 +419,6 @@ struct Values { #else GpuAccuracy::High, #endif - GpuAccuracy::Normal, - GpuAccuracy::Extreme, "gpu_accuracy", Category::RendererAdvanced, Specialization::Default, @@ -442,8 +429,6 @@ struct Values { SwitchableSetting dma_accuracy{linkage, DmaAccuracy::Default, - DmaAccuracy::Default, - DmaAccuracy::Safe, "dma_accuracy", Category::RendererAdvanced, Specialization::Default, @@ -456,20 +441,14 @@ struct Values { #else AnisotropyMode::Automatic, #endif - AnisotropyMode::Automatic, - AnisotropyMode::X16, "max_anisotropy", Category::RendererAdvanced}; SwitchableSetting astc_recompression{linkage, AstcRecompression::Uncompressed, - AstcRecompression::Uncompressed, - AstcRecompression::Bc3, "astc_recompression", Category::RendererAdvanced}; SwitchableSetting vram_usage_mode{linkage, VramUsageMode::Conservative, - VramUsageMode::Conservative, - VramUsageMode::Aggressive, "vram_usage_mode", Category::RendererAdvanced}; SwitchableSetting skip_cpu_inner_invalidation{linkage, @@ -595,14 +574,10 @@ struct Values { // System SwitchableSetting language_index{linkage, Language::EnglishAmerican, - Language::Japanese, - Language::Serbian, "language_index", Category::System}; - SwitchableSetting region_index{linkage, Region::Usa, Region::Japan, - Region::Taiwan, "region_index", Category::System}; - SwitchableSetting time_zone_index{linkage, TimeZone::Auto, - TimeZone::Auto, TimeZone::Zulu, + SwitchableSetting region_index{linkage, Region::Usa, "region_index", Category::System}; + SwitchableSetting time_zone_index{linkage, TimeZone::Auto, "time_zone_index", Category::System}; // Measured in seconds since epoch SwitchableSetting custom_rtc_enabled{ diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index ebfa4ceb9e..0e5a08d845 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include #include "common/common_types.h" @@ -18,8 +19,10 @@ namespace Settings { template struct EnumMetadata { - static std::vector> Canonicalizations(); + static std::vector> Canonicalizations(); static u32 Index(); + static constexpr T GetFirst(); + static constexpr T GetLast(); }; #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) @@ -69,138 +72,101 @@ struct EnumMetadata { #define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__)) #define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__)) -#define ENUM(NAME, ...) \ - enum class NAME : u32 { __VA_ARGS__ }; \ - template <> \ - inline std::vector> EnumMetadata::Canonicalizations() { \ - return {PAIR(NAME, __VA_ARGS__)}; \ - } \ - template <> \ - inline u32 EnumMetadata::Index() { \ - return __COUNTER__; \ +#define PP_HEAD(A, ...) A + +#define ENUM(NAME, ...) \ + enum class NAME : u32 { __VA_ARGS__ }; \ + template<> inline std::vector> EnumMetadata::Canonicalizations() { \ + return {PAIR(NAME, __VA_ARGS__)}; \ + } \ + template<> inline u32 EnumMetadata::Index() { \ + return __COUNTER__; \ + } \ + template<> inline constexpr NAME EnumMetadata::GetFirst() { \ + return NAME::PP_HEAD(__VA_ARGS__); \ + } \ + template<> inline constexpr NAME EnumMetadata::GetLast() { \ + return (std::vector>{PAIR(NAME, __VA_ARGS__)}).back().second; \ } // AudioEngine must be specified discretely due to having existing but slightly different // canonicalizations // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id -enum class AudioEngine : u32 { - Auto, - Cubeb, - Sdl2, - Null, - Oboe, -}; - -template <> -inline std::vector> -EnumMetadata::Canonicalizations() { +enum class AudioEngine : u32 { Auto, Cubeb, Sdl2, Null, Oboe, }; +template<> +inline std::vector> EnumMetadata::Canonicalizations() { return { {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2}, {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, }; } - -template <> +/// @brief This is just a sufficiently large number that is more than the number of other enums declared here +template<> inline u32 EnumMetadata::Index() { - // This is just a sufficiently large number that is more than the number of other enums declared - // here return 100; } +template<> +inline constexpr AudioEngine EnumMetadata::GetFirst() { + return AudioEngine::Auto; +} +template<> +inline constexpr AudioEngine EnumMetadata::GetLast() { + return AudioEngine::Oboe; +} ENUM(AudioMode, Mono, Stereo, Surround); +static_assert(EnumMetadata::GetFirst() == AudioMode::Mono); +static_assert(EnumMetadata::GetLast() == AudioMode::Surround); ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch, Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin, ChineseSimplified, ChineseTraditional, PortugueseBrazilian, Serbian); - ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan); - ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt, - GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, - Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, - Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); - + GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, + Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, + Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16); - ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous); - ENUM(AstcRecompression, Uncompressed, Bc1, Bc3); - ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed); - ENUM(VramUsageMode, Conservative, Aggressive); - ENUM(RendererBackend, OpenGL, Vulkan, Null); - ENUM(ShaderBackend, Glsl, Glasm, SpirV); - ENUM(GpuAccuracy, Normal, High, Extreme); - ENUM(DmaAccuracy, Default, Unsafe, Safe); - ENUM(CpuBackend, Dynarmic, Nce); - ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); - ENUM(CpuClock, Boost, Fast) - ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb); - ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); - ENUM(FullscreenMode, Borderless, Exclusive); - ENUM(NvdecEmulation, Off, Cpu, Gpu); - -ENUM(ResolutionSetup, - Res1_4X, - Res1_2X, - Res3_4X, - Res1X, - Res3_2X, - Res2X, - Res3X, - Res4X, - Res5X, - Res6X, - Res7X, - Res8X); - +ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Spline1, Gaussian, Lanczos, ScaleForce, Fsr, Area, MaxEnum); - ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); - ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); - ENUM(ConsoleMode, Handheld, Docked); - ENUM(AppletMode, HLE, LLE); - ENUM(SpirvOptimizeMode, Never, OnLoad, Always); - ENUM(GpuOverclock, Low, Medium, High) - ENUM(TemperatureUnits, Celsius, Fahrenheit) template -inline std::string CanonicalizeEnum(Type id) { +inline std::string_view CanonicalizeEnum(Type id) { const auto group = EnumMetadata::Canonicalizations(); - for (auto& [name, value] : group) { - if (value == id) { + for (auto& [name, value] : group) + if (value == id) return name; - } - } return "unknown"; } template inline Type ToEnum(const std::string& canonicalization) { const auto group = EnumMetadata::Canonicalizations(); - for (auto& [name, value] : group) { - if (name == canonicalization) { + for (auto& [name, value] : group) + if (name == canonicalization) return value; - } - } return {}; } } // namespace Settings diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index 0aba2e11c9..a7e6bb6168 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h @@ -72,10 +72,17 @@ public: u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) requires(ranged) - : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, - other_setting_), + : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_), value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {} + explicit Setting(Linkage& linkage, const Type& default_val, + const std::string& name, Category category_, + u32 specialization_ = Specialization::Default, bool save_ = true, + bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) + requires(ranged && std::is_enum_v) + : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_), + value{default_val}, default_value{default_val}, maximum{EnumMetadata::GetLast()}, minimum{EnumMetadata::GetFirst()} {} + /** * Returns a reference to the setting's value. * @@ -119,9 +126,6 @@ protected: return value_.has_value() ? std::to_string(*value_) : "none"; } else if constexpr (std::is_same_v) { return value_ ? "true" : "false"; - } else if constexpr (std::is_same_v) { - // Compatibility with old AudioEngine setting being a string - return CanonicalizeEnum(value_); } else if constexpr (std::is_floating_point_v) { return fmt::format("{:f}", value_); } else if constexpr (std::is_enum_v) { @@ -207,7 +211,7 @@ public: [[nodiscard]] std::string Canonicalize() const override final { if constexpr (std::is_enum_v) { - return CanonicalizeEnum(this->GetValue()); + return std::string{CanonicalizeEnum(this->GetValue())}; } else { return ToString(this->GetValue()); } @@ -288,41 +292,32 @@ public: * @param other_setting_ A second Setting to associate to this one in metadata */ template - explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, - Category category_, u32 specialization_ = Specialization::Default, - bool save_ = true, bool runtime_modifiable_ = false, - typename std::enable_if::type other_setting_ = nullptr) - : Setting{ - linkage, default_val, name, category_, specialization_, - save_, runtime_modifiable_, other_setting_} { + explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(!ranged) + : Setting{ linkage, default_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); } virtual ~SwitchableSetting() = default; - /** - * Sets a default value, minimum value, maximum value, and label. - * - * @param linkage Setting registry - * @param default_val Initial value of the setting, and default value of the setting - * @param min_val Sets the minimum allowed value of the setting - * @param max_val Sets the maximum allowed value of the setting - * @param name Label for the setting - * @param category_ Category of the setting AKA INI group - * @param specialization_ Suggestion for how frontend implementations represent this in a config - * @param save_ Suggests that this should or should not be saved to a frontend config file - * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded - * @param other_setting_ A second Setting to associate to this one in metadata - */ + /// @brief Sets a default value, minimum value, maximum value, and label. + /// @param linkage Setting registry + /// @param default_val Initial value of the setting, and default value of the setting + /// @param min_val Sets the minimum allowed value of the setting + /// @param max_val Sets the maximum allowed value of the setting + /// @param name Label for the setting + /// @param category_ Category of the setting AKA INI group + /// @param specialization_ Suggestion for how frontend implementations represent this in a config + /// @param save_ Suggests that this should or should not be saved to a frontend config file + /// @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded + /// @param other_setting_ A second Setting to associate to this one in metadata template - explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, - const Type& max_val, const std::string& name, Category category_, - u32 specialization_ = Specialization::Default, bool save_ = true, - bool runtime_modifiable_ = false, - typename std::enable_if::type other_setting_ = nullptr) - : Setting{linkage, default_val, min_val, - max_val, name, category_, - specialization_, save_, runtime_modifiable_, - other_setting_} { + explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, const Type& max_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged) + : Setting{linkage, default_val, min_val, max_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { + linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); + } + + template + explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged) + : Setting{linkage, default_val, EnumMetadata::GetFirst(), EnumMetadata::GetLast(), name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); } diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index a7ebae91f8..af81ef552e 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -270,10 +270,8 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) { void ConfigureAudio::InitializeAudioSinkComboBox() { sink_combo_box->clear(); sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); - - for (const auto& id : AudioCore::Sink::GetSinkIDs()) { - sink_combo_box->addItem(QString::fromStdString(Settings::CanonicalizeEnum(id))); - } + for (const auto& id : AudioCore::Sink::GetSinkIDs()) + sink_combo_box->addItem(QString::fromStdString(std::string{Settings::CanonicalizeEnum(id)})); } void ConfigureAudio::RetranslateUI() { From ecb811ad04e75b221e0eee31f6bbd582620bd7c7 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Sep 2025 18:41:28 +0200 Subject: [PATCH 06/12] [qt] move addons row to rightmost side (#2610) This is because the rightmost row is "extended" to the rest of the table, and add-ons have long names, play time doesn't need that much space. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2610 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/yuzu/game_list.h | 4 ++-- src/yuzu/game_list_worker.cpp | 36 ++++++++++++----------------------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 94e7b2dc42..cd71fb2139 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -58,11 +58,11 @@ class GameList : public QWidget { public: enum { COLUMN_NAME, - COLUMN_COMPATIBILITY, - COLUMN_ADD_ONS, COLUMN_FILE_TYPE, COLUMN_SIZE, COLUMN_PLAY_TIME, + COLUMN_ADD_ONS, + COLUMN_COMPATIBILITY, COLUMN_COUNT, // Number of columns }; diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 538c7ab822..2914c275a8 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -204,36 +204,24 @@ QList MakeGameListEntry(const std::string& path, const PlayTime::PlayTimeManager& play_time_manager, const FileSys::PatchManager& patch) { - const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); + auto const it = FindMatchingCompatibilityEntry(compatibility_list, program_id); + // The game list uses 99 as compatibility number for untested games + QString compatibility = it != compatibility_list.end() ? it->second.first : QStringLiteral("99"); - // The game list uses this as compatibility number for untested games - QString compatibility{QStringLiteral("99")}; - if (it != compatibility_list.end()) { - compatibility = it->second.first; - } + auto const file_type = loader.GetFileType(); + auto const file_type_string = QString::fromStdString(Loader::GetFileTypeString(file_type)); - const auto file_type = loader.GetFileType(); - const auto file_type_string = QString::fromStdString(Loader::GetFileTypeString(file_type)); - - QList list{ - new GameListItemPath(FormatGameName(path), icon, QString::fromStdString(name), - file_type_string, program_id), - new GameListItemCompat(compatibility), + QString patch_versions = GetGameListCachedObject(fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { + return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); + }); + return QList{ + new GameListItemPath(FormatGameName(path), icon, QString::fromStdString(name), file_type_string, program_id), new GameListItem(file_type_string), new GameListItemSize(size), new GameListItemPlayTime(play_time_manager.GetPlayTime(program_id)), + new GameListItem(patch_versions), + new GameListItemCompat(compatibility), }; - - QString patch_versions; - - patch_versions = GetGameListCachedObject( - fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { - return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); - }); - - list.insert(2, new GameListItem(patch_versions)); - - return list; } } // Anonymous namespace From 50ceb9a43a6dfe417a7760042e4710ce59553d94 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Mon, 29 Sep 2025 18:42:04 +0200 Subject: [PATCH 07/12] [.ci] install-msvc: fix installation on MSVC (#2611) * changed from Build Tools to Community (congrats Microsoft very cool) * add spining to show it didnt stopped installing Signed-off-by: Caio Oliveira Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2611 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: Caio Oliveira Co-committed-by: Caio Oliveira --- .ci/windows/install-msvc.ps1 | 40 ++++++++++++++++++++++++++---------- docs/Deps.md | 6 +++--- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.ci/windows/install-msvc.ps1 b/.ci/windows/install-msvc.ps1 index b88f727ed8..788b2848ad 100755 --- a/.ci/windows/install-msvc.ps1 +++ b/.ci/windows/install-msvc.ps1 @@ -10,7 +10,7 @@ if (-not ([bool](net session 2>$null))) { } $VSVer = "17" -$ExeFile = "vs_BuildTools.exe" +$ExeFile = "vs_community.exe" $Uri = "https://aka.ms/vs/$VSVer/release/$ExeFile" $Destination = "./$ExeFile" @@ -19,21 +19,39 @@ $WebClient = New-Object System.Net.WebClient $WebClient.DownloadFile($Uri, $Destination) Write-Host "Finished downloading $ExeFile" -$VSROOT = "C:/VSBuildTools/$VSVer" $Arguments = @( - "--installPath `"$VSROOT`"", # set custom installation path - "--quiet", # suppress UI - "--wait", # wait for installation to complete - "--norestart", # prevent automatic restart - "--add Microsoft.VisualStudio.Workload.VCTools", # add C++ build tools workload - "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64", # add core x86/x64 C++ tools - "--add Microsoft.VisualStudio.Component.Windows10SDK.19041" # add specific Windows SDK + "--quiet", # Suppress installer UI + "--wait", # Wait for installation to complete + "--norestart", # Prevent automatic restart + "--force", # Force installation even if components are already installed + "--add Microsoft.VisualStudio.Workload.NativeDesktop", # Desktop development with C++ + "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64", # Core C++ compiler/tools for x86/x64 + "--add Microsoft.VisualStudio.Component.Windows11SDK.26100",# Windows 11 SDK (26100) + "--add Microsoft.VisualStudio.Component.Windows10SDK.19041",# Windows 10 SDK (19041) + "--add Microsoft.VisualStudio.Component.VC.Llvm.Clang", # LLVM Clang compiler + "--add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset", # LLVM Clang integration toolset + "--add Microsoft.VisualStudio.Component.Windows11SDK.22621",# Windows 11 SDK (22621) + "--add Microsoft.VisualStudio.Component.VC.CMake.Project", # CMake project support + "--add Microsoft.VisualStudio.ComponentGroup.VC.Tools.142.x86.x64", # VC++ 14.2 toolset + "--add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang" # LLVM Clang for native desktop ) Write-Host "Installing Visual Studio Build Tools" -$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -Wait -ArgumentList $Arguments -$ExitCode = $InstallProcess.ExitCode +$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -ArgumentList $Arguments +# Spinner while installing +$Spinner = "|/-\" +$i = 0 +while (-not $InstallProcess.HasExited) { + Write-Host -NoNewline ("`rInstalling... " + $Spinner[$i % $Spinner.Length]) + Start-Sleep -Milliseconds 250 + $i++ +} + +# Clear spinner line +Write-Host "`rSetup completed! " + +$ExitCode = $InstallProcess.ExitCode if ($ExitCode -ne 0) { Write-Host "Error installing Visual Studio Build Tools (Error: $ExitCode)" Exit $ExitCode diff --git a/docs/Deps.md b/docs/Deps.md index cfc6f0365b..0e7b7cff62 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -4,8 +4,8 @@ To build Eden, you MUST have a C++ compiler. * On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+ - GCC 12 also requires Clang 14+ * On Windows, this is either: - - **[MSVC](https://visualstudio.microsoft.com/downloads/)**, - * *A convenience script to install the **minimal** version (Visual Build Tools) is provided in `.ci/windows/install-msvc.ps1`* + - **[MSVC](https://visualstudio.microsoft.com/downloads/)** (you should select *Community* option), + * *A convenience script to install the Visual Community Studio 2022 with necessary tools is provided in `.ci/windows/install-msvc.ps1`* - clang-cl - can be downloaded from the MSVC installer, - or **[MSYS2](https://www.msys2.org)** * On macOS, this is Apple Clang @@ -211,4 +211,4 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l ## All Done -You may now return to the **[root build guide](Build.md)**. \ No newline at end of file +You may now return to the **[root build guide](Build.md)**. From 9f423a24b82e1b3223d8d4204455e637f86271fa Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Sep 2025 18:42:28 +0200 Subject: [PATCH 08/12] [linux] fix aarch64 builds (again) + fix with slightly outdated qt (#2612) Fixes issues building on aarch64 linux with a slightly outdated system qt; also fixes linker selection process Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2612 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- CMakeLists.txt | 5 ++--- src/dynarmic/tests/CMakeLists.txt | 4 +++- src/yuzu/configuration/shared_widget.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef3c0bef6e..f5d7126f92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -895,13 +895,13 @@ if (MSVC AND CXX_CLANG) endif() if (YUZU_USE_FASTER_LD) + # fallback if everything fails (bfd) + set(LINKER bfd) # clang should always use lld find_program(LLD lld) - if (LLD) set(LINKER lld) endif() - # GNU appears to work better with mold # TODO: mold has been slow lately, see if better options exist (search for gold?) if (CXX_GCC) @@ -910,7 +910,6 @@ if (YUZU_USE_FASTER_LD) set(LINKER mold) endif() endif() - message(NOTICE "Selecting ${LINKER} as linker") add_link_options("-fuse-ld=${LINKER}") endif() diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index 4ace6c2afd..df90168a52 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -135,6 +135,8 @@ target_include_directories(dynarmic_tests PRIVATE . ../src) target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS}) target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) -target_compile_options(dynarmic_tests PRIVATE -mavx2) +if ("x86_64" IN_LIST ARCHITECTURE) + target_compile_options(dynarmic_tests PRIVATE -mavx2) +endif() add_test(dynarmic_tests dynarmic_tests --durations yes) diff --git a/src/yuzu/configuration/shared_widget.h b/src/yuzu/configuration/shared_widget.h index 9e718098a3..dd5d5b7257 100644 --- a/src/yuzu/configuration/shared_widget.h +++ b/src/yuzu/configuration/shared_widget.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "qt_common/shared_translation.h" From 33f93ad003a47419d545a6bae018d3bb1c5ee3fb Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Sep 2025 18:42:51 +0200 Subject: [PATCH 09/12] [macos, qt] workaround upstream rendering bug (#2616) See https://bugreports.qt.io/browse/QTBUG-138942 Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2616 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/yuzu/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yuzu/Info.plist b/src/yuzu/Info.plist index 96096c84d1..0c43c834d4 100644 --- a/src/yuzu/Info.plist +++ b/src/yuzu/Info.plist @@ -49,5 +49,7 @@ SPDX-License-Identifier: GPL-2.0-or-later NSApplication NSHighResolutionCapable True + UIDesignRequiresCompatibility + From 324ace3cd635bac4230a04c4a769bed236ed1e8d Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Sep 2025 18:43:13 +0200 Subject: [PATCH 10/12] [macos] associate .XCI/NSP file extensions (#2617) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2617 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/yuzu/Info.plist | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/yuzu/Info.plist b/src/yuzu/Info.plist index 0c43c834d4..773c4ee302 100644 --- a/src/yuzu/Info.plist +++ b/src/yuzu/Info.plist @@ -45,6 +45,26 @@ SPDX-License-Identifier: GPL-2.0-or-later NSHumanReadableCopyright + + LSApplicationCategoryType + public.app-category.games + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + nsp + xci + nro + + CFBundleTypeName + Switch File + CFBundleTypeRole + Viewer + LSHandlerRank + Default + + NSPrincipalClass NSApplication NSHighResolutionCapable From 20663c774d5272b7da786ac065f31163c5a582de Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 28 Sep 2025 18:03:09 +0000 Subject: [PATCH 11/12] [dynarmic] get rid of mcl intrusive list Signed-off-by: lizzie --- .../src/dynarmic/backend/x64/emit_x64.cpp | 5 ----- .../src/dynarmic/backend/x64/emit_x64.h | 2 -- src/dynarmic/src/dynarmic/ir/basic_block.cpp | 2 +- src/dynarmic/src/dynarmic/ir/basic_block.h | 5 ++--- src/dynarmic/src/dynarmic/ir/ir_emitter.h | 15 +++---------- .../src/dynarmic/ir/microinstruction.h | 5 ++--- src/dynarmic/src/dynarmic/ir/opt_passes.cpp | 22 +++++++++---------- 7 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index 3bc93e6fd5..3c41664464 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -38,11 +38,6 @@ EmitContext::EmitContext(RegAlloc& reg_alloc, IR::Block& block) EmitContext::~EmitContext() = default; -void EmitContext::EraseInstruction(IR::Inst* inst) { - block.Instructions().erase(inst); - inst->ClearArgs(); -} - EmitX64::EmitX64(BlockOfCode& code) : code(code) { exception_handler.Register(code); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index fbe749b2ab..5f0019b62e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -54,8 +54,6 @@ struct EmitContext { EmitContext(RegAlloc& reg_alloc, IR::Block& block); virtual ~EmitContext(); - void EraseInstruction(IR::Inst* inst); - virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0; virtual bool HasOptimization(OptimizationFlag flag) const = 0; diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp index b00ab3cb20..6100303faa 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp +++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp @@ -46,7 +46,7 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s inst->SetArg(index, arg); index++; }); - return instructions.insert_before(insertion_point, inst); + return instructions.insert(insertion_point, *inst);; } static std::string TerminalToString(const Terminal& terminal_variant) noexcept { diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.h b/src/dynarmic/src/dynarmic/ir/basic_block.h index e88dc92fc4..6757bfafc6 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.h +++ b/src/dynarmic/src/dynarmic/ir/basic_block.h @@ -12,10 +12,9 @@ #include #include #include +#include -#include #include "dynarmic/common/common_types.h" - #include "dynarmic/ir/location_descriptor.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/terminal.h" @@ -35,7 +34,7 @@ enum class Opcode; class Block final { public: //using instruction_list_type = dense_list; - using instruction_list_type = mcl::intrusive_list; + using instruction_list_type = boost::intrusive::list; using size_type = instruction_list_type::size_type; using iterator = instruction_list_type::iterator; using const_iterator = instruction_list_type::const_iterator; diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h index dba34bcc56..6f00cec8ac 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -10,10 +10,10 @@ #include -#include "dynarmic/common/common_types.h" -#include "dynarmic/common/assert.h" #include +#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/acc_type.h" #include "dynarmic/ir/basic_block.h" @@ -124,7 +124,7 @@ public: ASSERT(value.GetType() == Type::U64); return value; } - ASSERT_FALSE("Invalid bitsize"); + ASSERT_MSG(false, "Invalid bitsize"); } U32 LeastSignificantWord(const U64& value) { @@ -2950,19 +2950,10 @@ public: block.SetTerminal(terminal); } - void SetInsertionPointBefore(IR::Inst* new_insertion_point) { - insertion_point = IR::Block::iterator{*new_insertion_point}; - } - void SetInsertionPointBefore(IR::Block::iterator new_insertion_point) { insertion_point = new_insertion_point; } - void SetInsertionPointAfter(IR::Inst* new_insertion_point) { - insertion_point = IR::Block::iterator{*new_insertion_point}; - ++insertion_point; - } - void SetInsertionPointAfter(IR::Block::iterator new_insertion_point) { insertion_point = new_insertion_point; ++insertion_point; diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index 6651aab7c5..9e8febfcd5 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -9,10 +9,9 @@ #pragma once #include +#include -#include #include "dynarmic/common/common_types.h" - #include "dynarmic/ir/value.h" #include "dynarmic/ir/opcodes.h" @@ -26,7 +25,7 @@ constexpr size_t max_arg_count = 4; /// A representation of a microinstruction. A single ARM/Thumb instruction may be /// converted into zero or more microinstructions. //class Inst final { -class Inst final : public mcl::intrusive_list_node { +class Inst final : public boost::intrusive::list_base_hook<> { public: explicit Inst(Opcode op) : op(op) {} diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 844e29023c..56815065fb 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -85,12 +85,10 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { } static void FlagsPass(IR::Block& block) { - using Iterator = std::reverse_iterator; - struct FlagInfo { bool set_not_required = false; bool has_value_request = false; - Iterator value_request = {}; + IR::Block::reverse_iterator value_request = {}; }; struct ValuelessFlagInfo { bool set_not_required = false; @@ -101,7 +99,7 @@ static void FlagsPass(IR::Block& block) { FlagInfo c_flag; FlagInfo ge; - auto do_set = [&](FlagInfo& info, IR::Value value, Iterator inst) { + auto do_set = [&](FlagInfo& info, IR::Value value, IR::Block::reverse_iterator const inst) { if (info.has_value_request) { info.value_request->ReplaceUsesWith(value); } @@ -113,14 +111,14 @@ static void FlagsPass(IR::Block& block) { info.set_not_required = true; }; - auto do_set_valueless = [&](ValuelessFlagInfo& info, Iterator inst) { + auto do_set_valueless = [&](ValuelessFlagInfo& info, IR::Block::reverse_iterator const inst) { if (info.set_not_required) { inst->Invalidate(); } info.set_not_required = true; }; - auto do_get = [](FlagInfo& info, Iterator inst) { + auto do_get = [](FlagInfo& info, IR::Block::reverse_iterator const inst) { if (info.has_value_request) { info.value_request->ReplaceUsesWith(IR::Value{&*inst}); } @@ -447,7 +445,8 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) return; } - for (auto& inst : block) { + for (auto it = block.begin(); it != block.end(); it++) { + auto& inst = *it; if (inst.GetOpcode() != IR::Opcode::A64DataCacheOperationRaised) { continue; } @@ -456,7 +455,7 @@ static void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) if (op == A64::DataCacheOperation::ZeroByVA) { A64::IREmitter ir{block}; ir.current_location = A64::LocationDescriptor{IR::LocationDescriptor{inst.GetArg(0).GetU64()}}; - ir.SetInsertionPointBefore(&inst); + ir.SetInsertionPointBefore(it); size_t bytes = 4 << static_cast(conf.dczid_el0 & 0b1111); IR::U64 addr{inst.GetArg(2)}; @@ -1243,7 +1242,7 @@ static void IdentityRemovalPass(IR::Block& block) { } if (inst.GetOpcode() == IR::Opcode::Identity || inst.GetOpcode() == IR::Opcode::Void) { - iter = block.Instructions().erase(inst); + iter = block.Instructions().erase(iter); to_invalidate.push_back(&inst); } else { ++iter; @@ -1405,8 +1404,9 @@ static void PolyfillPass(IR::Block& block, const PolyfillOptions& polyfill) { IR::IREmitter ir{block}; - for (auto& inst : block) { - ir.SetInsertionPointBefore(&inst); + for (auto it = block.begin(); it != block.end(); it++) { + auto& inst = *it; + ir.SetInsertionPointBefore(it); switch (inst.GetOpcode()) { case IR::Opcode::SHA256MessageSchedule0: From 245906e147a85b89d893456ed602d428414a96eb Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 28 Sep 2025 18:04:38 +0000 Subject: [PATCH 12/12] fix license Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/x64/emit_x64.h | 3 +++ src/dynarmic/src/dynarmic/ir/basic_block.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index 5f0019b62e..87801a7208 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.cpp b/src/dynarmic/src/dynarmic/ir/basic_block.cpp index 6100303faa..7316c3d4f7 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.cpp +++ b/src/dynarmic/src/dynarmic/ir/basic_block.cpp @@ -46,7 +46,7 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, s inst->SetArg(index, arg); index++; }); - return instructions.insert(insertion_point, *inst);; + return instructions.insert(insertion_point, *inst); } static std::string TerminalToString(const Terminal& terminal_variant) noexcept {