mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-28 15:31:12 +02:00
Compare commits
4 Commits
descriptor
..
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f1f9be7a4 | |||
| c59d12b0cd | |||
| 4a5bec1cfc | |||
| 4f6195881c |
+1
@@ -16,6 +16,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
|
||||
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
|
||||
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
|
||||
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
|
||||
CPUOPT_UNSAFE_HOST_MMU("cpuopt_unsafe_host_mmu"),
|
||||
USE_DOCKED_MODE("use_docked_mode"),
|
||||
USE_AUTO_STUB("use_auto_stub"),
|
||||
|
||||
+7
@@ -719,6 +719,13 @@ abstract class SettingsItem(
|
||||
descriptionId = R.string.skip_cpu_inner_invalidation_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.FIX_BLOOM_EFFECTS,
|
||||
titleId = R.string.fix_bloom_effects,
|
||||
descriptionId = R.string.fix_bloom_effects_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.CPUOPT_UNSAFE_HOST_MMU,
|
||||
|
||||
+1
@@ -280,6 +280,7 @@ class SettingsFragmentPresenter(
|
||||
|
||||
add(IntSetting.FAST_GPU_TIME.key)
|
||||
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
||||
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||
add(IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.key)
|
||||
add(IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.key)
|
||||
|
||||
@@ -498,6 +498,8 @@
|
||||
<string name="fast_gpu_time_description">Forces most games to run at their highest native resolution. Use 256 for maximal performance and 512 for maximal graphics fidelity.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
|
||||
<string name="fix_bloom_effects">Fix Bloom Effects</string>
|
||||
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno 700), removes bloom in Burnout</string>
|
||||
<string name="renderer_asynchronous_shaders">Use asynchronous shaders</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches.</string>
|
||||
<string name="gpu_unswizzle_texture_size">GPU Unswizzle Max Texture Size</string>
|
||||
|
||||
+7
-6
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||
@@ -16,6 +16,7 @@
|
||||
void AssertFailSoftImpl();
|
||||
[[noreturn]] void AssertFatalImpl();
|
||||
|
||||
// Prevents errors on old GCC... smh...
|
||||
#ifdef _MSC_VER
|
||||
#define YUZU_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
@@ -23,9 +24,9 @@ void AssertFailSoftImpl();
|
||||
#endif
|
||||
|
||||
#define ASSERT_MSG(_a_, ...) \
|
||||
([&]() YUZU_NO_INLINE { \
|
||||
([&]() YUZU_NO_INLINE { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": assert\n" __VA_ARGS__); \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": assert " __VA_ARGS__); \
|
||||
AssertFailSoftImpl(); \
|
||||
} \
|
||||
}())
|
||||
@@ -33,7 +34,7 @@ void AssertFailSoftImpl();
|
||||
|
||||
#define UNREACHABLE_MSG(...) \
|
||||
do { \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": unreachable\n" __VA_ARGS__); \
|
||||
LOG_CRITICAL(Debug, __FILE__ ": unreachable " __VA_ARGS__); \
|
||||
AssertFatalImpl(); \
|
||||
} while (0)
|
||||
#define UNREACHABLE() UNREACHABLE_MSG("")
|
||||
@@ -50,10 +51,10 @@ void AssertFailSoftImpl();
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")
|
||||
#define UNIMPLEMENTED() ASSERT(false && "Unimplemented!")
|
||||
#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
|
||||
|
||||
#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
|
||||
#define UNIMPLEMENTED_IF(cond) ASSERT((!(cond)) && "Unimplemented!")
|
||||
#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)
|
||||
|
||||
// If the assert is ignored, execute _b_
|
||||
|
||||
@@ -347,11 +347,7 @@ void TranslateResolutionInfo(ResolutionSetup setup, ResolutionScalingInfo& info)
|
||||
}
|
||||
info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift);
|
||||
info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale;
|
||||
#ifdef __ANDROID__
|
||||
info.active = info.up_scale != 1 || info.down_shift != 0;
|
||||
#else
|
||||
info.active = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UpdateRescalingInfo() {
|
||||
|
||||
@@ -503,6 +503,9 @@ struct Values {
|
||||
#endif
|
||||
"async_presentation", Category::RendererHacks};
|
||||
|
||||
SwitchableSetting<bool> fix_bloom_effects{linkage, false, "fix_bloom_effects",
|
||||
Category::RendererHacks};
|
||||
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||
Category::RendererHacks};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ IRemoteStorageController::IRemoteStorageController(Core::System& system_)
|
||||
{15, nullptr, "RegisterUploadSaveDataTransferTaskForAutonomyRegistration"},
|
||||
{16, nullptr, "CreateCleanupToDeleteSaveDataArchiveInfoTask"},
|
||||
{17, nullptr, "ListDataInfo"},
|
||||
{18, nullptr, "GetDataInfo"},
|
||||
{18, D<&IRemoteStorageController::GetDataInfo>, "GetDataInfoV1"},
|
||||
{19, nullptr, "GetDataInfoCacheUpdateNativeHandleHolder"},
|
||||
{20, nullptr, "CreateSaveDataArchiveInfoCacheForSaveDataBackupUpdationTask"},
|
||||
{21, nullptr, "ListSecondarySaves"},
|
||||
@@ -37,7 +37,7 @@ IRemoteStorageController::IRemoteStorageController(Core::System& system_)
|
||||
{24, nullptr, "GetSecondarySaveDataInfo"},
|
||||
{25, nullptr, "RegisterDownloadSaveDataTransferTaskForAutonomyRegistration"},
|
||||
{26, nullptr, "Unknown26"}, //20.0.0+
|
||||
{27, D<&IRemoteStorageController::Unknown27>, "Unknown27"}, //20.0.0+
|
||||
{27, D<&IRemoteStorageController::GetDataInfo>, "GetDataInfoV2"}, //20.0.0+
|
||||
{28, nullptr, "Unknown28"}, //20.0.0+
|
||||
{29, nullptr, "Unknown29"}, //21.0.0+
|
||||
{800, nullptr, "Unknown800"}, //20.0.0+
|
||||
@@ -67,7 +67,7 @@ Result IRemoteStorageController::GetDataNewnessByApplicationId(Out<u8> out_newne
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IRemoteStorageController::Unknown27(Out<std::array<u8, 0x38>> out_data, u64 application_id) {
|
||||
Result IRemoteStorageController::GetDataInfo(Out<std::array<u8, 0x38>> out_data, u64 application_id) {
|
||||
LOG_WARNING(Service_OLSC, "(STUBBED) called, application_id={:016X}", application_id);
|
||||
out_data->fill(0);
|
||||
R_SUCCEED();
|
||||
|
||||
@@ -18,7 +18,7 @@ private:
|
||||
Result GetSecondarySave(Out<bool> out_has_secondary_save, Out<std::array<u64, 3>> out_unknown,
|
||||
u64 application_id);
|
||||
Result GetDataNewnessByApplicationId(Out<u8> out_newness, u64 application_id);
|
||||
Result Unknown27(Out<std::array<u8, 0x38>> out_data, u64 application_id);
|
||||
Result GetDataInfo(Out<std::array<u8, 0x38>> out_data, u64 application_id);
|
||||
};
|
||||
|
||||
} // namespace Service::OLSC
|
||||
|
||||
@@ -329,6 +329,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
||||
barrier_feedback_loops,
|
||||
tr("Barrier feedback loops"),
|
||||
tr("Improves rendering of transparency effects in specific games."));
|
||||
INSERT(Settings,
|
||||
fix_bloom_effects,
|
||||
tr("Fix bloom effects"),
|
||||
tr("Removes bloom in Burnout."));
|
||||
|
||||
// Renderer (Extensions)
|
||||
INSERT(Settings, dyna_state, tr("Extended Dynamic State"),
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
|
||||
#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
|
||||
@@ -471,9 +475,16 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
|
||||
Id lod, const IR::Value& offset) {
|
||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||
const ImageOperands operands(ctx, false, true, false, lod, offset);
|
||||
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
||||
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
|
||||
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
||||
|
||||
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
||||
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
|
||||
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
||||
#ifdef ANDROID
|
||||
if (Settings::values.fix_bloom_effects.GetValue()) {
|
||||
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f));
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
||||
@@ -304,9 +304,17 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
||||
Optimization::GlobalMemoryToStorageBufferPass(program, host_info);
|
||||
Optimization::TexturePass(env, program, host_info);
|
||||
|
||||
if (Settings::values.resolution_info.active) {
|
||||
bool should_rescale =
|
||||
#ifdef __ANDROID__
|
||||
Settings::values.resolution_info.active;
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
|
||||
if (should_rescale) {
|
||||
Optimization::RescalingPass(program);
|
||||
}
|
||||
|
||||
Optimization::DeadCodeEliminationPass(program);
|
||||
if (Settings::values.renderer_debug) {
|
||||
Optimization::VerificationPass(program);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
||||
@@ -97,28 +97,8 @@ VkDescriptorSet DescriptorAllocator::Commit() {
|
||||
return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
|
||||
}
|
||||
|
||||
VkDescriptorSet DescriptorAllocator::CommitWithTracking(u64 current_frame, const void* descriptor_data) {
|
||||
const size_t index = CommitResource();
|
||||
const size_t group = index / SETS_GROW_RATE;
|
||||
const size_t slot = index % SETS_GROW_RATE;
|
||||
set_states[group][slot].set = sets[group][slot];
|
||||
set_states[group][slot].last_update_frame = current_frame;
|
||||
set_states[group][slot].last_data_ptr = descriptor_data;
|
||||
return set_states[group][slot].set;
|
||||
}
|
||||
|
||||
bool DescriptorAllocator::NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const {
|
||||
for (const auto& group : set_states)
|
||||
for (const auto& st : group)
|
||||
if (st.set == set) // Update if pointer changed or the set hasn't been updated this frame
|
||||
return st.last_data_ptr != descriptor_data || st.last_update_frame != current_frame;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
|
||||
const size_t count = end - begin;
|
||||
sets.push_back(AllocateDescriptors(count));
|
||||
set_states.emplace_back(count); // create parallel state storage
|
||||
sets.push_back(AllocateDescriptors(end - begin));
|
||||
}
|
||||
|
||||
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -9,7 +6,7 @@
|
||||
#include <shared_mutex>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "shader_recompiler/shader_info.h"
|
||||
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
@@ -47,15 +44,7 @@ public:
|
||||
DescriptorAllocator(const DescriptorAllocator&) = delete;
|
||||
|
||||
VkDescriptorSet Commit();
|
||||
// commit + remember when/with what we last updated this set
|
||||
struct DescriptorSetState {
|
||||
VkDescriptorSet set = VK_NULL_HANDLE;
|
||||
u64 last_update_frame = 0;
|
||||
const void* last_data_ptr = nullptr; // fast pointer compare
|
||||
};
|
||||
|
||||
VkDescriptorSet CommitWithTracking(u64 current_frame, const void* descriptor_data);
|
||||
bool NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const;
|
||||
private:
|
||||
explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
|
||||
DescriptorBank& bank_, VkDescriptorSetLayout layout_);
|
||||
@@ -69,7 +58,6 @@ private:
|
||||
VkDescriptorSetLayout layout{};
|
||||
|
||||
std::vector<vk::DescriptorSets> sets;
|
||||
std::vector<std::vector<DescriptorSetState>> set_states;
|
||||
};
|
||||
|
||||
class DescriptorPool {
|
||||
|
||||
@@ -514,20 +514,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||
const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
|
||||
const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
|
||||
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
||||
|
||||
// allocate/bind descriptor set and only update if needed
|
||||
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
|
||||
bool needs_update = false;
|
||||
if (descriptor_set_layout && !uses_push_descriptor) {
|
||||
descriptor_set = descriptor_allocator.CommitWithTracking(current_frame_number, descriptor_data);
|
||||
needs_update = descriptor_allocator.NeedsUpdate(descriptor_set, current_frame_number, descriptor_data);
|
||||
if (needs_update) {
|
||||
const vk::Device& dev{device.GetLogical()};
|
||||
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.Record([this, descriptor_data, descriptor_set, bind_pipeline, rescaling_data = rescaling.Data(),
|
||||
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
|
||||
is_rescaling, update_rescaling,
|
||||
uses_render_area = render_area.uses_render_area,
|
||||
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
||||
@@ -553,8 +540,12 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||
return;
|
||||
}
|
||||
if (uses_push_descriptor) {
|
||||
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout, 0, descriptor_data);
|
||||
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
|
||||
0, descriptor_data);
|
||||
} else {
|
||||
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
|
||||
const vk::Device& dev{device.GetLogical()};
|
||||
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0,
|
||||
descriptor_set, nullptr);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
maxwell3d = maxwell3d_;
|
||||
gpu_memory = gpu_memory_;
|
||||
}
|
||||
void SetFrameNumber(u64 frame) { current_frame_number = frame; }
|
||||
|
||||
private:
|
||||
template <typename Spec>
|
||||
bool ConfigureImpl(bool is_indexed);
|
||||
@@ -172,7 +172,6 @@ private:
|
||||
std::mutex build_mutex;
|
||||
std::atomic_bool is_built{false};
|
||||
bool uses_push_descriptor{false};
|
||||
u64 current_frame_number{0};
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -222,7 +222,6 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||
// update engine as channel may be different.
|
||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||
pipeline->SetFrameNumber(current_frame_number);
|
||||
if (!pipeline->Configure(is_indexed))
|
||||
return;
|
||||
|
||||
@@ -807,7 +806,6 @@ void RasterizerVulkan::FlushCommands() {
|
||||
}
|
||||
|
||||
void RasterizerVulkan::TickFrame() {
|
||||
current_frame_number++;
|
||||
draw_counter = 0;
|
||||
guest_descriptor_queue.TickFrame();
|
||||
compute_pass_descriptor_queue.TickFrame();
|
||||
|
||||
@@ -160,7 +160,7 @@ private:
|
||||
void UpdateDynamicStates();
|
||||
|
||||
void HandleTransformFeedback();
|
||||
u64 current_frame_number{0};
|
||||
|
||||
void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
@@ -1313,7 +1313,7 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
|
||||
case PixelFormat::R32G32_FLOAT:
|
||||
case PixelFormat::R32G32_SINT:
|
||||
case PixelFormat::R32_FLOAT:
|
||||
if (src_view.format == PixelFormat::D32_FLOAT) {
|
||||
if ((src_view.format == PixelFormat::D32_FLOAT) && Settings::values.fix_bloom_effects.GetValue()) {
|
||||
const Region2D region{
|
||||
.start = {0, 0},
|
||||
.end = {static_cast<s32>(dst->RenderArea().width),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
|
||||
Reference in New Issue
Block a user