forked from eden-emu/eden
Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
440ee4916d | |||
551f244dfd |
23 changed files with 308 additions and 185 deletions
13
.patch/mbedtls/0002-aesni-fix.patch
Normal file
13
.patch/mbedtls/0002-aesni-fix.patch
Normal 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 */
|
22
.patch/mbedtls/0003-aesni-fix.patch
Normal file
22
.patch/mbedtls/0003-aesni-fix.patch
Normal 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)
|
||||
/*
|
55
.patch/mcl/0001-assert-macro.patch
Normal file
55
.patch/mcl/0001-assert-macro.patch
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
6
externals/cpmfile.json
vendored
6
externals/cpmfile.json
vendored
|
@ -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",
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
3
src/dynarmic/externals/cpmfile.json
vendored
3
src/dynarmic/externals/cpmfile.json
vendored
|
@ -13,6 +13,9 @@
|
|||
"hash": "f943bac39c1879986decad7a442ff4288eaeca4a2907684c7914e115a55ecc43c2782ded85c0835763fe04e40d5c82220ce864423e489e648e408a84f54dc4f3",
|
||||
"options": [
|
||||
"MCL_INSTALL OFF"
|
||||
],
|
||||
"patches": [
|
||||
"0001-assert-macro.patch"
|
||||
]
|
||||
},
|
||||
"zycore": {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include "common/common_types.h"
|
||||
#include "common/settings_enums.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QtVersionChecks>
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
|
||||
#define STATE_CHANGED stateChanged
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue