callback_list;
int last_callback_key = 0;
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 60e0e8449b..b36dd46176 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -754,7 +754,7 @@ void BufferCache::BindHostIndexBuffer() {
}
}
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
- const u32 new_offset = offset + draw_state.index_buffer.first * draw_state.index_buffer.FormatSizeInBytes();
+ const u32 new_offset = offset + draw_state.index_buffer.first * u32(draw_state.index_buffer.FormatSizeInBytes());
runtime.BindIndexBuffer(buffer, new_offset, size);
} else {
buffer.MarkUsage(offset, size);
@@ -1252,8 +1252,7 @@ void BufferCache
::UpdateIndexBuffer() {
const GPUVAddr gpu_addr_end = index_buffer_ref.EndAddress();
const std::optional device_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
const u32 address_size = static_cast(gpu_addr_end - gpu_addr_begin);
- const u32 draw_size =
- (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes();
+ const u32 draw_size = (index_buffer_ref.count + index_buffer_ref.first) * u32(index_buffer_ref.FormatSizeInBytes());
const u32 size = (std::min)(address_size, draw_size);
if (size == 0 || !device_addr) {
channel_state->index_buffer = NULL_BINDING;
@@ -1620,24 +1619,38 @@ void BufferCache::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
template
bool BufferCache::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) {
upload_copies.clear();
- u64 total_size_bytes = 0;
+ u64 staging_offset = 0;
u64 largest_copy = 0;
- const DAddr buffer_start = buffer.cpu_addr_cached;
- memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
- upload_copies.push_back(BufferCopy{
- .src_offset = total_size_bytes,
- .dst_offset = device_addr_out - buffer_start,
- .size = range_size,
+ DAddr buffer_start = buffer.CpuAddr();
+ auto push = [&](u64 start, u64 end) {
+ if (start >= end) {
+ return;
+ }
+ u64 sz = end - start;
+ upload_copies.push_back({
+ .src_offset = staging_offset,
+ .dst_offset = start - buffer_start,
+ .size = sz
});
- total_size_bytes += range_size;
- largest_copy = (std::max)(largest_copy, range_size);
+ staging_offset += sz;
+ largest_copy = (std::max)(largest_copy, sz);
+ };
+ memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 addr, u64 range_size) {
+ u64 start = addr;
+ u64 end = addr + range_size;
+ gpu_modified_ranges.ForEachInRange(start, range_size, [&](u64 gstart, u64 gsize) {
+ u64 gend = gstart + gsize;
+ push(start, gstart);
+ start = (std::max)(start, gend);
+ });
+ push(start, end);
+ ClearDownload(addr, range_size);
+ gpu_modified_ranges.Subtract(addr, range_size);
});
- if (total_size_bytes == 0) {
+ if (upload_copies.empty()) {
return true;
}
- const std::span copies_span(upload_copies.data(), upload_copies.size());
- UploadMemory(buffer, total_size_bytes, largest_copy, copies_span);
- any_buffer_uploaded = true;
+ UploadMemory(buffer, staging_offset, largest_copy, std::span(upload_copies));
return false;
}
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 3844a8e2f9..75f1de58a0 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -181,12 +181,12 @@ void DmaPusher::CallMethod(u32 argument) const {
});
} else {
auto subchannel = subchannels[dma_state.subchannel];
- if (!subchannel->execution_mask[dma_state.method]) {
- subchannel->method_sink.emplace_back(dma_state.method, argument);
- } else {
+ if (subchannel->execution_mask[dma_state.method]) {
subchannel->ConsumeSink();
subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset;
subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call);
+ } else {
+ subchannel->method_sink.emplace_back(dma_state.method, argument);
}
}
}
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 9aaa99f7ff..7cf351e458 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -270,31 +270,20 @@ u32 Maxwell3D::GetMaxCurrentVertices() {
size_t Maxwell3D::EstimateIndexBufferSize() {
GPUVAddr start_address = regs.index_buffer.StartAddress();
GPUVAddr end_address = regs.index_buffer.EndAddress();
- static constexpr std::array max_sizes = {(std::numeric_limits::max)(),
- (std::numeric_limits::max)(),
- (std::numeric_limits::max)()};
- const size_t byte_size = regs.index_buffer.FormatSizeInBytes();
- const size_t log2_byte_size = Common::Log2Ceil64(byte_size);
- const size_t cap{GetMaxCurrentVertices() * 4 * byte_size};
- const size_t lower_cap =
- std::min(static_cast(end_address - start_address), cap);
- return std::min(
- memory_manager.GetMemoryLayoutSize(start_address, byte_size * max_sizes[log2_byte_size]) /
- byte_size,
- lower_cap);
+ auto const byte_size = regs.index_buffer.FormatSizeInBytes();
+ auto const max_size = 1ull << (byte_size * CHAR_BIT);
+ auto const upper_cap = GetMaxCurrentVertices() * 4 * byte_size;
+ auto const lower_cap = std::min(size_t(end_address - start_address), upper_cap);
+ return std::min(memory_manager.GetMemoryLayoutSize(start_address, byte_size * max_size) / byte_size, lower_cap);
}
u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) {
// Keep track of the register value in shadow_state when requested.
- const auto control = shadow_state.shadow_ram_control;
- if (control == Regs::ShadowRamControl::Track ||
- control == Regs::ShadowRamControl::TrackWithFilter) {
- shadow_state.reg_array[method] = argument;
- return argument;
- }
- if (control == Regs::ShadowRamControl::Replay) {
+ auto const c = shadow_state.shadow_ram_control;
+ if (c == Regs::ShadowRamControl::Track || c == Regs::ShadowRamControl::TrackWithFilter)
+ return shadow_state.reg_array[method] = argument;
+ else if (c == Regs::ShadowRamControl::Replay)
return shadow_state.reg_array[method];
- }
return argument;
}
@@ -317,10 +306,8 @@ void Maxwell3D::ConsumeSinkImpl() {
void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) {
regs.reg_array[method] = argument;
-
- for (const auto& table : dirty.tables) {
+ for (auto const& table : dirty.tables)
dirty.flags[table[method]] = true;
- }
}
void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call) {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 3ac79e0eb8..864ee27fb6 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -2215,7 +2215,7 @@ public:
u32 first;
u32 count;
- unsigned FormatSizeInBytes() const {
+ size_t FormatSizeInBytes() const {
switch (format) {
case IndexFormat::UnsignedByte:
return 1;
@@ -2224,7 +2224,7 @@ public:
case IndexFormat::UnsignedInt:
return 4;
}
- ASSERT(false);
+ UNREACHABLE();
return 1;
}
@@ -3148,9 +3148,9 @@ public:
}
struct DirtyState {
- using Flags = std::bitset<(std::numeric_limits::max)()>;
+ using Flags = std::bitset<(std::numeric_limits::max)() + 1>;
using Table = std::array;
- using Tables = std::array;
+ using Tables = std::array, 2>;
Flags flags;
Tables tables{};
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index 3f4dd89c7e..a7b7c46f39 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -24,11 +24,8 @@ using namespace Dirty;
using namespace VideoCommon::Dirty;
using Tegra::Engines::Maxwell3D;
using Regs = Maxwell3D::Regs;
-using Tables = Maxwell3D::DirtyState::Tables;
-using Table = Maxwell3D::DirtyState::Table;
-using Flags = Maxwell3D::DirtyState::Flags;
-Flags MakeInvalidationFlags() {
+Maxwell3D::DirtyState::Flags MakeInvalidationFlags() {
static constexpr int INVALIDATION_FLAGS[]{
Viewports,
Scissors,
@@ -68,7 +65,7 @@ Flags MakeInvalidationFlags() {
LineStippleEnable,
LineStippleParams,
};
- Flags flags{};
+ Maxwell3D::DirtyState::Flags flags{};
for (const int flag : INVALIDATION_FLAGS) {
flags[flag] = true;
}
@@ -84,7 +81,7 @@ Flags MakeInvalidationFlags() {
return flags;
}
-void SetupDirtyViewports(Tables& tables) {
+void SetupDirtyViewports(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
FillBlock(tables[1], OFF(surface_clip), NUM(surface_clip), Viewports);
@@ -92,26 +89,26 @@ void SetupDirtyViewports(Tables& tables) {
tables[1][OFF(window_origin)] = Viewports;
}
-void SetupDirtyScissors(Tables& tables) {
+void SetupDirtyScissors(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(scissor_test), NUM(scissor_test), Scissors);
}
-void SetupDirtyDepthBias(Tables& tables) {
+void SetupDirtyDepthBias(Maxwell3D::DirtyState::Tables& tables) {
auto& table = tables[0];
table[OFF(depth_bias)] = DepthBias;
table[OFF(depth_bias_clamp)] = DepthBias;
table[OFF(slope_scale_depth_bias)] = DepthBias;
}
-void SetupDirtyBlendConstants(Tables& tables) {
+void SetupDirtyBlendConstants(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendConstants);
}
-void SetupDirtyDepthBounds(Tables& tables) {
+void SetupDirtyDepthBounds(Maxwell3D::DirtyState::Tables& tables) {
FillBlock(tables[0], OFF(depth_bounds), NUM(depth_bounds), DepthBounds);
}
-void SetupDirtyStencilProperties(Tables& tables) {
+void SetupDirtyStencilProperties(Maxwell3D::DirtyState::Tables& tables) {
const auto setup = [&](size_t position, u8 flag) {
tables[0][position] = flag;
tables[1][position] = StencilProperties;
@@ -125,18 +122,18 @@ void SetupDirtyStencilProperties(Tables& tables) {
setup(OFF(stencil_back_func_mask), StencilCompare);
}
-void SetupDirtyLineWidth(Tables& tables) {
+void SetupDirtyLineWidth(Maxwell3D::DirtyState::Tables& tables) {
tables[0][OFF(line_width_smooth)] = LineWidth;
tables[0][OFF(line_width_aliased)] = LineWidth;
}
-void SetupDirtyCullMode(Tables& tables) {
+void SetupDirtyCullMode(Maxwell3D::DirtyState::Tables& tables) {
auto& table = tables[0];
table[OFF(gl_cull_face)] = CullMode;
table[OFF(gl_cull_test_enabled)] = CullMode;
}
-void SetupDirtyStateEnable(Tables& tables) {
+void SetupDirtyStateEnable(Maxwell3D::DirtyState::Tables& tables) {
const auto setup = [&](size_t position, u8 flag) {
tables[0][position] = flag;
tables[1][position] = StateEnable;
@@ -157,17 +154,17 @@ void SetupDirtyStateEnable(Tables& tables) {
setup(OFF(anti_alias_alpha_control.alpha_to_one), AlphaToOneEnable);
}
-void SetupDirtyDepthCompareOp(Tables& tables) {
+void SetupDirtyDepthCompareOp(Maxwell3D::DirtyState::Tables& tables) {
tables[0][OFF(depth_test_func)] = DepthCompareOp;
}
-void SetupDirtyFrontFace(Tables& tables) {
+void SetupDirtyFrontFace(Maxwell3D::DirtyState::Tables& tables) {
auto& table = tables[0];
table[OFF(gl_front_face)] = FrontFace;
table[OFF(window_origin)] = FrontFace;
}
-void SetupDirtyStencilOp(Tables& tables) {
+void SetupDirtyStencilOp(Maxwell3D::DirtyState::Tables& tables) {
auto& table = tables[0];
table[OFF(stencil_front_op.fail)] = StencilOp;
table[OFF(stencil_front_op.zfail)] = StencilOp;
@@ -182,7 +179,7 @@ void SetupDirtyStencilOp(Tables& tables) {
tables[1][OFF(stencil_two_side_enable)] = StencilOp;
}
-void SetupDirtyBlending(Tables& tables) {
+void SetupDirtyBlending(Maxwell3D::DirtyState::Tables& tables) {
tables[0][OFF(color_mask_common)] = Blending;
tables[1][OFF(color_mask_common)] = ColorMask;
tables[0][OFF(blend_per_target_enabled)] = Blending;
@@ -196,11 +193,11 @@ void SetupDirtyBlending(Tables& tables) {
FillBlock(tables[1], OFF(blend_per_target), NUM(blend_per_target), BlendEquations);
}
-void SetupDirtySpecialOps(Tables& tables) {
+void SetupDirtySpecialOps(Maxwell3D::DirtyState::Tables& tables) {
tables[0][OFF(logic_op.op)] = LogicOp;
}
-void SetupDirtyViewportSwizzles(Tables& tables) {
+void SetupDirtyViewportSwizzles(Maxwell3D::DirtyState::Tables& tables) {
static constexpr size_t swizzle_offset = 6;
for (size_t index = 0; index < Regs::NumViewports; ++index) {
tables[1][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] =
@@ -208,7 +205,7 @@ void SetupDirtyViewportSwizzles(Tables& tables) {
}
}
-void SetupDirtyVertexAttributes(Tables& tables) {
+void SetupDirtyVertexAttributes(Maxwell3D::DirtyState::Tables& tables) {
for (size_t i = 0; i < Regs::NumVertexAttributes; ++i) {
const size_t offset = OFF(vertex_attrib_format) + i * NUM(vertex_attrib_format[0]);
FillBlock(tables[0], offset, NUM(vertex_attrib_format[0]), VertexAttribute0 + i);
@@ -216,7 +213,7 @@ void SetupDirtyVertexAttributes(Tables& tables) {
FillBlock(tables[1], OFF(vertex_attrib_format), Regs::NumVertexAttributes, VertexInput);
}
-void SetupDirtyVertexBindings(Tables& tables) {
+void SetupDirtyVertexBindings(Maxwell3D::DirtyState::Tables& tables) {
// Do NOT include stride here, it's implicit in VertexBuffer
static constexpr size_t divisor_offset = 3;
for (size_t i = 0; i < Regs::NumVertexArrays; ++i) {
@@ -228,7 +225,7 @@ void SetupDirtyVertexBindings(Tables& tables) {
}
}
-void SetupRasterModes(Tables &tables) {
+void SetupRasterModes(Maxwell3D::DirtyState::Tables &tables) {
auto& table = tables[0];
table[OFF(line_stipple_params)] = LineStippleParams;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f8528d9671..29a1f075fa 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -15,6 +15,10 @@
#include "qt_common/gui_settings.h"
#endif
+#ifndef _WIN32
+#include
+#endif
+
#include "main_window.h"
#ifdef _WIN32
@@ -106,10 +110,27 @@ int main(int argc, char* argv[]) {
QCoreApplication::setOrganizationName(QStringLiteral("eden"));
QCoreApplication::setApplicationName(QStringLiteral("eden"));
+ // Increases the maximum open file limit.
+ // TODO: This should be common to all frontends.
#ifdef _WIN32
- // Increases the maximum open file limit to 8192
+ // MSVCRT limits this to 2048 for some inexplicable (and likely arcane) reason,
+ // so we have to account for that as well.
+#ifdef __MSVCRT__
+ _setmaxstdio(2048);
+#else
_setmaxstdio(8192);
-#elif defined(__APPLE__)
+#endif // __MSVCRT__
+#elif defined(__unix__) || defined(__APPLE__)
+ // Set the max open file limit to 8192, or the hard limit.
+ // Most sane systems should not hit the hard limit here.
+ struct rlimit rl;
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ rl.rlim_cur = std::min(8192, rl.rlim_max);
+ setrlimit(RLIMIT_NOFILE, &rl);
+ }
+#endif // _WIN32
+
+#if defined(__APPLE__)
// If you start a bundle (binary) on OSX without the Terminal, the working directory is "/".
// But since we require the working directory to be the executable path for the location of
// the user folder in the Qt Frontend, we need to cd into that working directory
diff --git a/tools/README.md b/tools/README.md
index 767892e7ac..ee82c708b0 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -1,6 +1,6 @@
# Tools
-Tools for Eden and other subprojects.
+Tools for Eden and other subprojects. When adding new scripts please use `#!/bin/sh -e` or `#!/usr/bin/env ` (for `.py`, `.rb`, or `.perl`). Keep scripts POSIX compliant (i.e not require hard `bash` to run, just plain old `sh`).
## Third-Party
diff --git a/tools/clang-format.sh b/tools/clang-format.sh
index e2857d9723..ca5e6fce39 100755
--- a/tools/clang-format.sh
+++ b/tools/clang-format.sh
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
diff --git a/tools/dtrace-tool.pl b/tools/dtrace-tool.pl
index 2c4e7d6876..bb0b212d23 100755
--- a/tools/dtrace-tool.pl
+++ b/tools/dtrace-tool.pl
@@ -1,5 +1,6 @@
-#!/usr/bin/perl
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+#!/usr/bin/env perl
+
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Basic script to run dtrace sampling over the program (requires Flamegraph)
# Usage is either running as: ./dtrace-tool.sh pid (then input the pid of the process)
diff --git a/tools/lanczos-gen.pl b/tools/lanczos-gen.pl
old mode 100644
new mode 100755
index 2e26c8c6b9..3eab5cdb10
--- a/tools/lanczos-gen.pl
+++ b/tools/lanczos-gen.pl
@@ -1,5 +1,5 @@
-#!/usr/bin/perl
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+#!/usr/bin/env perl
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
use strict;
use warnings;
diff --git a/tools/llvmpipe-run.sh b/tools/llvmpipe-run.sh
index c3a5a85d41..f09fe87ef4 100755
--- a/tools/llvmpipe-run.sh
+++ b/tools/llvmpipe-run.sh
@@ -1,5 +1,6 @@
-#!/bin/sh
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+#!/bin/sh -e
+
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# This script basically allows you to "dirtily" use llvmpipe in any configuration
diff --git a/tools/optimize-assets.sh b/tools/optimize-assets.sh
index 70fa2375a5..a9b2888648 100755
--- a/tools/optimize-assets.sh
+++ b/tools/optimize-assets.sh
@@ -1,6 +1,6 @@
#!/bin/sh -e
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
which optipng || exit
diff --git a/tools/stale-translations.sh b/tools/stale-translations.sh
index 3a9362a252..63ea87b19a 100755
--- a/tools/stale-translations.sh
+++ b/tools/stale-translations.sh
@@ -1,6 +1,6 @@
#!/bin/sh -e
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
ANDROID=src/android/app/src/main
diff --git a/tools/svc_generator.py b/tools/svc_generator.py
index d00fe0ba63..9a99c3ba51 100755
--- a/tools/svc_generator.py
+++ b/tools/svc_generator.py
@@ -1,5 +1,5 @@
-#!/usr/bin/python3
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+#!/usr/bin/env python3
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -212,7 +212,7 @@ def emit_size_check():
if type != "void":
lines.append(f"static_assert(sizeof({type}) == {size});")
- return "\n".join(lines)
+ return f"\n{lines}"
# Replaces a type with an arch-specific one, if it exists.
@@ -423,7 +423,7 @@ def emit_lines(lines, indent=' '):
output_lines.append(line)
first = False
- return "\n".join(output_lines)
+ return f"\n{output_lines}"
# Emit a C++ function to wrap a guest SVC.
@@ -601,7 +601,7 @@ def emit_call(bitness, names, suffix):
lines.append(f"{indent}}}")
lines.append("}")
- return "\n".join(lines)
+ return f"\n{lines}"
def build_fn_declaration(return_type, name, arguments):
@@ -623,7 +623,7 @@ def build_enum_declarations():
lines.append(f"{indent}{name} = {hex(imm)},")
lines.append("};")
- return "\n".join(lines)
+ return f"\n{lines}"
def main():
@@ -665,11 +665,11 @@ def main():
with open("src/core/hle/kernel/svc.h", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_H)
- f.write("\n".join(svc_fw_declarations))
+ f.write(f"\n{svc_fw_declarations}")
f.write("\n\n")
- f.write("\n".join(arch_fw_declarations[BIT_32]))
+ f.write(f"\n{arch_fw_declarations[BIT_32]}")
f.write("\n\n")
- f.write("\n".join(arch_fw_declarations[BIT_64]))
+ f.write(f"\n{arch_fw_declarations[BIT_64]}")
f.write("\n\n")
f.write(enum_decls)
f.write(EPILOGUE_H)
@@ -679,7 +679,7 @@ def main():
f.write(PROLOGUE_CPP)
f.write(emit_size_check())
f.write("\n\n")
- f.write("\n\n".join(wrapper_fns))
+ f.write(f"\n\n{wrapper_fns}")
f.write("\n\n")
f.write(call_32)
f.write("\n\n")
diff --git a/tools/translations/qt-source.sh b/tools/translations/qt-source.sh
index 89c881d8c0..707ec2783c 100755
--- a/tools/translations/qt-source.sh
+++ b/tools/translations/qt-source.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -e
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
SOURCES=$(find src/yuzu src/qt_common -type f \( -name "*.ui" -o -name "*.cpp" -o -name "*.h" -o -name "*.plist" \))
diff --git a/tools/translations/update-translations.sh b/tools/translations/update-translations.sh
index 8bcd79142f..6ed740140d 100755
--- a/tools/translations/update-translations.sh
+++ b/tools/translations/update-translations.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/sh -e
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
command -v tx-cli && COMMAND=tx-cli
diff --git a/tools/unused-strings.sh b/tools/unused-strings.sh
index 1165a203aa..10f6a63565 100755
--- a/tools/unused-strings.sh
+++ b/tools/unused-strings.sh
@@ -1,6 +1,6 @@
#!/bin/sh -e
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
ANDROID=src/android/app/src/main
diff --git a/tools/windows/install-vulkan-sdk.sh b/tools/windows/install-vulkan-sdk.sh
index 0f136748cf..2151363793 100644
--- a/tools/windows/install-vulkan-sdk.sh
+++ b/tools/windows/install-vulkan-sdk.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/sh
+#!/bin/sh -e
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later