Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
440ee4916d
[nca] Use better tight loop allocation schemes (none at all) for AES decrypt/encrypt and force MbedTLS to use AES x86_64 instructions (#2750)
Uses stack instead of allocating stuff haphazardly (16 bytes and 512 bytes respectively) - removes malloc() pollution and all that nasty stuff from tight loops
Original work by Ribbit but edited by me.
Will NOT bring a massive speedup since the main bottleneck is mbedtls itself, but may bring nice oddities to STARTUP TIMES nonetheless.
AES instructions being forced wont affect CPUs without them since there is always a runtime check for them.

Signed-off-by: lizzie lizzie@eden-emu.dev
Co-authored-by: Ribbit <ribbit@placeholder.com>
Reviewed-on: eden-emu/eden#2750
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-10-17 05:08:51 +02:00
551f244dfd
[dynarmic, qt] fix build with QuaZip <=1.4 and fmt v9 (#2755)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: eden-emu/eden#2755
2025-10-17 04:20:11 +02:00
23 changed files with 308 additions and 185 deletions

View file

@ -0,0 +1,13 @@
diff --git a/library/aesni.h b/library/aesni.h
index 754c984c79..59e27afd3e 100644
--- a/library/aesni.h
+++ b/library/aesni.h
@@ -35,7 +35,7 @@
/* GCC-like compilers: currently, we only support intrinsics if the requisite
* target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
* or `clang -maes -mpclmul`). */
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)
+#if defined(__GNUC__) || defined(__clang__)
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* For 32-bit, we only support intrinsics */

View file

@ -0,0 +1,22 @@
diff --git a/library/aesni.c b/library/aesni.c
index 2857068..3e104ab 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -31,16 +31,14 @@
#include <immintrin.h>
#endif
-#if defined(MBEDTLS_ARCH_IS_X86)
#if defined(MBEDTLS_COMPILER_IS_GCC)
#pragma GCC push_options
#pragma GCC target ("pclmul,sse2,aes")
#define MBEDTLS_POP_TARGET_PRAGMA
-#elif defined(__clang__) && (__clang_major__ >= 5)
+#elif defined(__clang__)
#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
#endif
-#endif
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*

View file

@ -0,0 +1,55 @@
diff --git a/include/mcl/assert.hpp b/include/mcl/assert.hpp
index f77dbe7..9ec0b9c 100644
--- a/include/mcl/assert.hpp
+++ b/include/mcl/assert.hpp
@@ -23,8 +23,11 @@ template<typename... Ts>
} // namespace mcl::detail
+#ifndef UNREACHABLE
#define UNREACHABLE() ASSERT_FALSE("Unreachable code!")
+#endif
+#ifndef ASSERT
#define ASSERT(expr) \
[&] { \
if (std::is_constant_evaluated()) { \
@@ -37,7 +40,9 @@ template<typename... Ts>
} \
} \
}()
+#endif
+#ifndef ASSERT_MSG
#define ASSERT_MSG(expr, ...) \
[&] { \
if (std::is_constant_evaluated()) { \
@@ -50,13 +55,24 @@ template<typename... Ts>
} \
} \
}()
+#endif
+#ifndef ASSERT_FALSE
#define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false", __VA_ARGS__)
+#endif
#if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS)
-# define DEBUG_ASSERT(expr) ASSUME(expr)
-# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
+# ifndef DEBUG_ASSERT
+# define DEBUG_ASSERT(expr) ASSUME(expr)
+# endif
+# ifndef DEBUG_ASSERT_MSG
+# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
+# endif
#else
-# define DEBUG_ASSERT(expr) ASSERT(expr)
-# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
+# ifndef DEBUG_ASSERT
+# define DEBUG_ASSERT(expr) ASSERT(expr)
+# endif
+# ifndef DEBUG_ASSERT_MSG
+# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
+# endif
#endif

View file

@ -52,6 +52,10 @@ if (PLATFORM_SUN)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
if (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
endif()
endif()
# Needed for FFmpeg w/ VAAPI and DRM

View file

@ -1,27 +1,33 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
find_package(DiscordRPC CONFIG QUIET)
find_library(DiscordRPC_LIBRARY discord-rpc)
if (NOT DiscordRPC_FOUND)
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
find_library(DiscordRPC_LIBRARY discord-rpc)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DiscordRPC
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DiscordRPC
REQUIRED_VARS
DiscordRPC_LIBRARY
DiscordRPC_INCLUDE_DIR
)
)
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
add_library(DiscordRPC::discord-rpc UNKNOWN IMPORTED)
set_target_properties(DiscordRPC::discord-rpc PROPERTIES
IMPORTED_LOCATION "${DiscordRPC_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${DiscordRPC_INCLUDE_DIR}"
)
endif()
endif()
mark_as_advanced(
mark_as_advanced(
DiscordRPC_INCLUDE_DIR
DiscordRPC_LIBRARY
)
)
endif()

View file

@ -97,7 +97,11 @@
"version": "3",
"git_version": "3.6.4",
"artifact": "%TAG%.tar.bz2",
"skip_updates": true
"skip_updates": true,
"patches": [
"0002-aesni-fix.patch",
"0003-aesni-fix.patch"
]
},
"enet": {
"repo": "lsalzman/enet",

View file

@ -40,22 +40,22 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
#endif
#define LOG_DEBUG(log_class, ...) \
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \
::Common::Log::FmtLogMessage(::Common::Log::Class::log_class, ::Common::Log::Level::Debug, \
__FILE__, __LINE__, __func__, \
__VA_ARGS__)
#define LOG_INFO(log_class, ...) \
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \
::Common::Log::FmtLogMessage(::Common::Log::Class::log_class, ::Common::Log::Level::Info, \
__FILE__, __LINE__, __func__, \
__VA_ARGS__)
#define LOG_WARNING(log_class, ...) \
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \
::Common::Log::FmtLogMessage(::Common::Log::Class::log_class, ::Common::Log::Level::Warning, \
__FILE__, __LINE__, __func__, \
__VA_ARGS__)
#define LOG_ERROR(log_class, ...) \
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \
::Common::Log::FmtLogMessage(::Common::Log::Class::log_class, ::Common::Log::Level::Error, \
__FILE__, __LINE__, __func__, \
__VA_ARGS__)
#define LOG_CRITICAL(log_class, ...) \
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \
::Common::Log::FmtLogMessage(::Common::Log::Class::log_class, ::Common::Log::Level::Critical, \
__FILE__, __LINE__, __func__, \
__VA_ARGS__)

View file

@ -1,7 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <vector>
#include <mbedtls/cipher.h>
#include "common/assert.h"
#include "common/logging/log.h"
@ -71,14 +75,16 @@ void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* des
mbedtls_cipher_reset(context);
// Only ECB strictly requires block sized chunks.
std::size_t written = 0;
if (mbedtls_cipher_get_cipher_mode(context) == MBEDTLS_MODE_XTS) {
if (mbedtls_cipher_get_cipher_mode(context) != MBEDTLS_MODE_ECB) {
mbedtls_cipher_update(context, src, size, dest, &written);
if (written != size) {
LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
size, written);
if (written != size)
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", size, written);
return;
}
} else {
// ECB path: operate in block sized chunks and mirror previous behavior.
const auto block_size = mbedtls_cipher_get_block_size(context);
if (size < block_size) {
std::vector<u8> block(block_size);
@ -89,7 +95,7 @@ void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* des
}
for (std::size_t offset = 0; offset < size; offset += block_size) {
auto length = std::min<std::size_t>(block_size, size - offset);
const auto length = std::min<std::size_t>(block_size, size - offset);
mbedtls_cipher_update(context, src + offset, length, dest + offset, &written);
if (written != length) {
if (length < block_size) {
@ -99,9 +105,7 @@ void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* des
std::memcpy(dest + offset, block.data(), length);
return;
}
LOG_WARNING(Crypto, "Not all data was decrypted requested={:016X}, actual={:016X}.",
length, written);
}
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", length, written);
}
}
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -15,26 +18,36 @@ std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t o
if (length == 0)
return 0;
const auto sector_offset = offset & 0xF;
if (sector_offset == 0) {
std::size_t total_read = 0;
// Handle an initial misaligned portion if needed.
if (auto const sector_offset = offset & 0xF; sector_offset != 0) {
const std::size_t aligned_off = offset - sector_offset;
std::array<u8, 0x10> block{};
if (auto const got = base->Read(block.data(), block.size(), aligned_off); got != 0) {
UpdateIV(base_offset + aligned_off);
cipher.Transcode(block.data(), got, block.data(), Op::Decrypt);
auto const to_copy = std::min<std::size_t>(length, got > sector_offset ? got - sector_offset : 0);
if (to_copy > 0) {
std::memcpy(data, block.data() + sector_offset, to_copy);
data += to_copy;
offset += to_copy;
length -= to_copy;
total_read += to_copy;
}
} else {
return 0;
}
}
if (length > 0) {
// Now aligned to 0x10
UpdateIV(base_offset + offset);
std::vector<u8> raw = base->ReadBytes(length, offset);
cipher.Transcode(raw.data(), raw.size(), data, Op::Decrypt);
return length;
const std::size_t got = base->Read(data, length, offset);
if (got > 0) {
cipher.Transcode(data, got, data, Op::Decrypt);
total_read += got;
}
// offset does not fall on block boundary (0x10)
std::vector<u8> block = base->ReadBytes(0x10, offset - sector_offset);
UpdateIV(base_offset + offset - sector_offset);
cipher.Transcode(block.data(), block.size(), block.data(), Op::Decrypt);
std::size_t read = 0x10 - sector_offset;
if (length + sector_offset < 0x10) {
std::memcpy(data, block.data() + sector_offset, std::min<u64>(length, read));
return std::min<u64>(length, read);
}
std::memcpy(data, block.data() + sector_offset, read);
return read + Read(data + read, length - read, offset + read);
return total_read;
}
void CTREncryptionLayer::SetIV(const IVData& iv_) {

View file

@ -5,12 +5,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <array>
#include <cstring>
#include "core/crypto/xts_encryption_layer.h"
namespace Core::Crypto {
constexpr u64 XTS_SECTOR_SIZE = 0x4000;
constexpr std::size_t XTS_SECTOR_SIZE = 0x4000;
XTSEncryptionLayer::XTSEncryptionLayer(FileSys::VirtualFile base_, Key256 key_)
: EncryptionLayer(std::move(base_)), cipher(key_, Mode::XTS) {}
@ -19,41 +20,67 @@ std::size_t XTSEncryptionLayer::Read(u8* data, std::size_t length, std::size_t o
if (length == 0)
return 0;
const auto sector_offset = offset & 0x3FFF;
if (sector_offset == 0) {
if (length % XTS_SECTOR_SIZE == 0) {
std::vector<u8> raw = base->ReadBytes(length, offset);
cipher.XTSTranscode(raw.data(), raw.size(), data, offset / XTS_SECTOR_SIZE,
std::size_t total_read = 0;
// Handle initial unaligned part within a sector.
if (auto const sector_offset = offset % XTS_SECTOR_SIZE; sector_offset != 0) {
const std::size_t aligned_off = offset - sector_offset;
std::array<u8, XTS_SECTOR_SIZE> block{};
if (auto const got = base->Read(block.data(), XTS_SECTOR_SIZE, aligned_off); got > 0) {
if (got < XTS_SECTOR_SIZE)
std::memset(block.data() + got, 0, XTS_SECTOR_SIZE - got);
cipher.XTSTranscode(block.data(), XTS_SECTOR_SIZE, block.data(), aligned_off / XTS_SECTOR_SIZE,
XTS_SECTOR_SIZE, Op::Decrypt);
return raw.size();
auto const to_copy = std::min<std::size_t>(length, got > sector_offset ? got - sector_offset : 0);
if (to_copy > 0) {
std::memcpy(data, block.data() + sector_offset, to_copy);
data += to_copy;
offset += to_copy;
length -= to_copy;
total_read += to_copy;
}
if (length > XTS_SECTOR_SIZE) {
const auto rem = length % XTS_SECTOR_SIZE;
const auto read = length - rem;
return Read(data, read, offset) + Read(data + read, rem, offset + read);
} else {
return 0;
}
std::vector<u8> buffer = base->ReadBytes(XTS_SECTOR_SIZE, offset);
if (buffer.size() < XTS_SECTOR_SIZE)
buffer.resize(XTS_SECTOR_SIZE);
cipher.XTSTranscode(buffer.data(), buffer.size(), buffer.data(), offset / XTS_SECTOR_SIZE,
XTS_SECTOR_SIZE, Op::Decrypt);
std::memcpy(data, buffer.data(), (std::min)(buffer.size(), length));
return (std::min)(buffer.size(), length);
}
// offset does not fall on block boundary (0x4000)
std::vector<u8> block = base->ReadBytes(0x4000, offset - sector_offset);
if (block.size() < XTS_SECTOR_SIZE)
block.resize(XTS_SECTOR_SIZE);
cipher.XTSTranscode(block.data(), block.size(), block.data(),
(offset - sector_offset) / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt);
const std::size_t read = XTS_SECTOR_SIZE - sector_offset;
if (length + sector_offset < XTS_SECTOR_SIZE) {
std::memcpy(data, block.data() + sector_offset, std::min<u64>(length, read));
return std::min<u64>(length, read);
if (length > 0) {
// Process aligned middle inplace, in sector sized multiples.
while (length >= XTS_SECTOR_SIZE) {
const std::size_t req = (length / XTS_SECTOR_SIZE) * XTS_SECTOR_SIZE;
const std::size_t got = base->Read(data, req, offset);
if (got == 0) {
return total_read;
}
std::memcpy(data, block.data() + sector_offset, read);
return read + Read(data + read, length - read, offset + read);
const std::size_t got_rounded = got - (got % XTS_SECTOR_SIZE);
if (got_rounded > 0) {
cipher.XTSTranscode(data, got_rounded, data, offset / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt);
data += got_rounded;
offset += got_rounded;
length -= got_rounded;
total_read += got_rounded;
}
// If we didn't get a full sector next, break to handle tail.
if (got_rounded != got) {
break;
}
}
// Handle tail within a sector, if any.
if (length > 0) {
std::array<u8, XTS_SECTOR_SIZE> block{};
const std::size_t got = base->Read(block.data(), XTS_SECTOR_SIZE, offset);
if (got > 0) {
if (got < XTS_SECTOR_SIZE) {
std::memset(block.data() + got, 0, XTS_SECTOR_SIZE - got);
}
cipher.XTSTranscode(block.data(), XTS_SECTOR_SIZE, block.data(),
offset / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt);
const std::size_t to_copy = std::min<std::size_t>(length, got);
std::memcpy(data, block.data(), to_copy);
total_read += to_copy;
}
}
}
return total_read;
}
} // namespace Core::Crypto

View file

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <boost/container/static_vector.hpp>
#include "common/alignment.h"
#include "common/swap.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
@ -83,32 +84,24 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) {
std::memcpy(ctr.data(), m_iv.data(), IvSize);
AddCounter(ctr.data(), IvSize, offset / BlockSize);
// Loop until all data is written.
size_t remaining = size;
s64 cur_offset = 0;
// Get a pooled buffer.
std::vector<char> pooled_buffer(BlockSize);
while (remaining > 0) {
// Loop until all data is written using a pooled buffer residing on the stack (blocksize = 0x10)
boost::container::static_vector<u8, BlockSize> pooled_buffer;
for (size_t remaining = size; remaining > 0; ) {
// Determine data we're writing and where.
const size_t write_size = std::min(pooled_buffer.size(), remaining);
u8* write_buf = reinterpret_cast<u8*>(pooled_buffer.data());
auto const write_size = (std::min)(pooled_buffer.size(), remaining);
u8* write_buf = pooled_buffer.data();
// Encrypt the data.
// Encrypt the data and then write it.
m_cipher->SetIV(ctr);
m_cipher->Transcode(buffer, write_size, write_buf, Core::Crypto::Op::Encrypt);
m_base_storage->Write(write_buf, write_size, offset);
// Write the encrypted data.
m_base_storage->Write(write_buf, write_size, offset + cur_offset);
// Advance.
cur_offset += write_size;
// Advance next write chunk
offset += write_size;
remaining -= write_size;
if (remaining > 0) {
if (remaining > 0)
AddCounter(ctr.data(), IvSize, write_size / BlockSize);
}
}
return size;
}

View file

@ -4,9 +4,13 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <array>
#include <boost/container/static_vector.hpp>
#include "common/alignment.h"
#include "common/swap.h"
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
#include "core/file_sys/fssystem/fssystem_nca_header.h"
#include "core/file_sys/fssystem/fssystem_utility.h"
namespace FileSys {
@ -41,18 +45,12 @@ AesXtsStorage::AesXtsStorage(VirtualFile base, const void* key1, const void* key
size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const {
// Allow zero-size reads.
if (size == 0) {
if (size == 0)
return size;
}
// Ensure buffer is valid.
// Ensure buffer is valid and we can only read at block aligned offsets.
ASSERT(buffer != nullptr);
// We can only read at block aligned offsets.
ASSERT(Common::IsAligned(offset, AesBlockSize));
ASSERT(Common::IsAligned(size, AesBlockSize));
// Read the data.
ASSERT(Common::IsAligned(offset, AesBlockSize) && Common::IsAligned(size, AesBlockSize));
m_base_storage->Read(buffer, size, offset);
// Setup the counter.
@ -60,25 +58,21 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const {
std::memcpy(ctr.data(), m_iv.data(), IvSize);
AddCounter(ctr.data(), IvSize, offset / m_block_size);
// Handle any unaligned data before the start.
// Handle any unaligned data before the start; then read said data into a local pooled
// buffer that resides on the stack, do not use the global memory allocator this is a
// very tiny (512 bytes) buffer so should be fine to keep on the stack (Nca::XtsBlockSize wide buffer)
size_t processed_size = 0;
if ((offset % m_block_size) != 0) {
// Decrypt into our pooled stack buffer (max bound = NCA::XtsBlockSize)
boost::container::static_vector<u8, NcaHeader::XtsBlockSize> tmp_buf;
// Determine the size of the pre-data read.
const size_t skip_size =
static_cast<size_t>(offset - Common::AlignDown(offset, m_block_size));
const size_t data_size = (std::min)(size, m_block_size - skip_size);
// Decrypt into a pooled buffer.
{
std::vector<char> tmp_buf(m_block_size, 0);
auto const skip_size = size_t(offset - Common::AlignDown(offset, m_block_size));
auto const data_size = (std::min)(size, m_block_size - skip_size);
std::fill_n(tmp_buf.begin(), skip_size, u8{0});
std::memcpy(tmp_buf.data() + skip_size, buffer, data_size);
m_cipher->SetIV(ctr);
m_cipher->Transcode(tmp_buf.data(), m_block_size, tmp_buf.data(),
Core::Crypto::Op::Decrypt);
m_cipher->Transcode(tmp_buf.data(), m_block_size, tmp_buf.data(), Core::Crypto::Op::Decrypt);
std::memcpy(buffer, tmp_buf.data() + skip_size, data_size);
}
AddCounter(ctr.data(), IvSize, 1);
processed_size += data_size;
@ -86,20 +80,16 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const {
}
// Decrypt aligned chunks.
char* cur = reinterpret_cast<char*>(buffer) + processed_size;
size_t remaining = size - processed_size;
while (remaining > 0) {
const size_t cur_size = (std::min)(m_block_size, remaining);
auto* cur = buffer + processed_size;
for (size_t remaining = size - processed_size; remaining > 0; ) {
auto const cur_size = (std::min)(m_block_size, remaining);
m_cipher->SetIV(ctr);
m_cipher->Transcode(cur, cur_size, cur, Core::Crypto::Op::Decrypt);
auto* char_cur = reinterpret_cast<char*>(cur); //same repr cur - diff signedness
m_cipher->Transcode(char_cur, cur_size, char_cur, Core::Crypto::Op::Decrypt);
remaining -= cur_size;
cur += cur_size;
AddCounter(ctr.data(), IvSize, 1);
}
return size;
}

View file

@ -13,6 +13,9 @@
"hash": "f943bac39c1879986decad7a442ff4288eaeca4a2907684c7914e115a55ecc43c2782ded85c0835763fe04e40d5c82220ce864423e489e648e408a84f54dc4f3",
"options": [
"MCL_INSTALL OFF"
],
"patches": [
"0001-assert-macro.patch"
]
},
"zycore": {

View file

@ -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) 2022 MerryMage
* SPDX-License-Identifier: 0BSD
@ -238,7 +241,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
#undef A32OPC
#undef A64OPC
default:
ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
ASSERT_FALSE("Invalid opcode: {:x}", std::size_t(inst->GetOpcode()));
break;
}

View file

@ -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) 2024 MerryMage
* SPDX-License-Identifier: 0BSD
@ -140,7 +143,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon
#undef A32OPC
#undef A64OPC
default:
ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
ASSERT_FALSE("Invalid opcode: {:x}", std::size_t(inst->GetOpcode()));
break;
}
}

View file

@ -145,7 +145,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
#undef OPCODE
#undef A32OPC
#undef A64OPC
default: [[unlikely]] ASSERT_FALSE("Invalid opcode: {}", inst->GetOpcode());
default: [[unlikely]] ASSERT_FALSE("Invalid opcode: {:x}", std::size_t(inst->GetOpcode()));
}
reg_alloc.EndOfAllocScope();
func(reg_alloc);

View file

@ -130,7 +130,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) noexcept {
#undef A32OPC
#undef A64OPC
default: [[unlikely]] {
ASSERT_MSG(false, "Invalid opcode: {}", opcode);
ASSERT_MSG(false, "Invalid opcode: {:x}", std::size_t(opcode));
goto finish_this_inst;
}
}

View file

@ -59,7 +59,7 @@ std::optional<EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescr
}
void EmitX64::EmitInvalid(EmitContext&, IR::Inst* inst) {
ASSERT_MSG(false, "Invalid opcode: {}", inst->GetOpcode());
ASSERT_MSG(false, "Invalid opcode: {:x}", std::size_t(inst->GetOpcode()));
}
void EmitX64::EmitVoid(EmitContext&, IR::Inst*) {

View file

@ -654,11 +654,3 @@ constexpr bool MayGetNZCVFromOp(const Opcode op) noexcept {
}
} // namespace Dynarmic::IR
template<>
struct fmt::formatter<Dynarmic::IR::Opcode> : fmt::formatter<std::string> {
template<typename FormatContext>
auto format(Dynarmic::IR::Opcode op, FormatContext& ctx) const {
return formatter<std::string>::format(Dynarmic::IR::GetNameOf(op), ctx);
}
};

View file

@ -14,6 +14,7 @@
#include <utility>
#include <vector>
#include <QString>
#include <QObject>
#include "common/common_types.h"
#include "common/settings_enums.h"

View file

@ -3,7 +3,7 @@
#pragma once
#include <QtVersionChecks>
#include <QtGlobal>
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
#define STATE_CHANGED stateChanged

View file

@ -82,16 +82,9 @@ bool compressSubDir(QuaZip *zip,
if (dir != origDir) {
QuaZipFile dirZipFile(zip);
std::unique_ptr<QuaZipNewInfo> qzni;
if (options.getDateTime().isNull()) {
qzni = std::make_unique<QuaZipNewInfo>(origDirectory.relativeFilePath(dir)
+ QLatin1String("/"),
dir);
} else {
qzni = std::make_unique<QuaZipNewInfo>(origDirectory.relativeFilePath(dir)
+ QLatin1String("/"),
dir,
options.getDateTime());
}
if (!dirZipFile.open(QIODevice::WriteOnly, *qzni, nullptr, 0, 0)) {
return false;
}
@ -156,7 +149,7 @@ bool compressFile(QuaZip *zip,
return false;
} else {
if (!outFile.open(QIODevice::WriteOnly,
QuaZipNewInfo(fileDest, fileName, options.getDateTime()),
QuaZipNewInfo(fileDest, fileName),
nullptr,
0,
options.getCompressionMethod(),

View file

@ -415,10 +415,8 @@ void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir,
QGuiApplication::processEvents();
auto progress_callback = [=](size_t total_size, size_t processed_size) {
QMetaObject::invokeMethod(progress,
&QtProgressDialog::setValue,
static_cast<int>((processed_size * 100) / total_size));
QMetaObject::invokeMethod(progress, "setValue", Qt::DirectConnection,
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
return !progress->wasCanceled();
};
@ -501,9 +499,8 @@ void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir,
QObject::connect(delete_watcher, &QFutureWatcher<bool>::finished, rootObject, [=]() {
auto progress_callback = [=](size_t total_size, size_t processed_size) {
QMetaObject::invokeMethod(progress,
&QtProgressDialog::setValue,
static_cast<int>((processed_size * 100) / total_size));
QMetaObject::invokeMethod(progress, "setValue", Qt::DirectConnection,
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
return !progress->wasCanceled();
};