early-access version 3932
This commit is contained in:
parent
f851294b1d
commit
4d49e282ae
17 changed files with 116 additions and 163 deletions
|
@ -11,7 +11,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
|
||||||
include(DownloadExternals)
|
include(DownloadExternals)
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
# Set bundled sdl2/qt as dependent options.
|
# Set bundled sdl2/qt as dependent options.
|
||||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||||
|
@ -99,47 +98,8 @@ if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
||||||
DESTINATION "${vvl_lib_path}")
|
DESTINATION "${vvl_lib_path}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# On Android, fetch and compile libcxx before doing anything else
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set(CMAKE_SKIP_INSTALL_RULES ON)
|
set(CMAKE_SKIP_INSTALL_RULES ON)
|
||||||
set(LLVM_VERSION "15.0.6")
|
|
||||||
|
|
||||||
# Note: even though libcxx and libcxxabi have separate releases on the project page,
|
|
||||||
# the separated releases cannot be compiled. Only in-tree builds work. Therefore we
|
|
||||||
# must fetch the source release for the entire llvm tree.
|
|
||||||
FetchContent_Declare(llvm
|
|
||||||
URL "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-project-${LLVM_VERSION}.src.tar.xz"
|
|
||||||
URL_HASH SHA256=9d53ad04dc60cb7b30e810faf64c5ab8157dadef46c8766f67f286238256ff92
|
|
||||||
TLS_VERIFY TRUE
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(llvm)
|
|
||||||
|
|
||||||
# libcxx has support for most of the range library, but it's gated behind a flag:
|
|
||||||
add_compile_definitions(_LIBCPP_ENABLE_EXPERIMENTAL)
|
|
||||||
|
|
||||||
# Disable standard header inclusion
|
|
||||||
set(ANDROID_STL "none")
|
|
||||||
|
|
||||||
# libcxxabi
|
|
||||||
set(LIBCXXABI_INCLUDE_TESTS OFF)
|
|
||||||
set(LIBCXXABI_ENABLE_SHARED FALSE)
|
|
||||||
set(LIBCXXABI_ENABLE_STATIC TRUE)
|
|
||||||
set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXX_TARGET_INCLUDE_DIRECTORY}" CACHE STRING "" FORCE)
|
|
||||||
add_subdirectory("${llvm_SOURCE_DIR}/libcxxabi" "${llvm_BINARY_DIR}/libcxxabi")
|
|
||||||
link_libraries(cxxabi_static)
|
|
||||||
|
|
||||||
# libcxx
|
|
||||||
set(LIBCXX_ABI_NAMESPACE "__ndk1" CACHE STRING "" FORCE)
|
|
||||||
set(LIBCXX_CXX_ABI "libcxxabi")
|
|
||||||
set(LIBCXX_INCLUDE_TESTS OFF)
|
|
||||||
set(LIBCXX_INCLUDE_BENCHMARKS OFF)
|
|
||||||
set(LIBCXX_INCLUDE_DOCS OFF)
|
|
||||||
set(LIBCXX_ENABLE_SHARED FALSE)
|
|
||||||
set(LIBCXX_ENABLE_STATIC TRUE)
|
|
||||||
set(LIBCXX_ENABLE_ASSERTIONS FALSE)
|
|
||||||
add_subdirectory("${llvm_SOURCE_DIR}/libcxx" "${llvm_BINARY_DIR}/libcxx")
|
|
||||||
set_target_properties(cxx-headers PROPERTIES INTERFACE_COMPILE_OPTIONS "-isystem${CMAKE_BINARY_DIR}/${LIBCXX_INSTALL_INCLUDE_DIR}")
|
|
||||||
link_libraries(cxx_static cxx-headers)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (YUZU_USE_BUNDLED_VCPKG)
|
if (YUZU_USE_BUNDLED_VCPKG)
|
||||||
|
@ -326,7 +286,7 @@ find_package(Boost 1.79.0 REQUIRED context)
|
||||||
find_package(enet 1.3 MODULE)
|
find_package(enet 1.3 MODULE)
|
||||||
find_package(fmt 9 REQUIRED)
|
find_package(fmt 9 REQUIRED)
|
||||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||||
find_package(LLVM 17 MODULE COMPONENTS Demangle)
|
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
||||||
find_package(lz4 REQUIRED)
|
find_package(lz4 REQUIRED)
|
||||||
find_package(nlohmann_json 3.8 REQUIRED)
|
find_package(nlohmann_json 3.8 REQUIRED)
|
||||||
find_package(Opus 1.3 MODULE)
|
find_package(Opus 1.3 MODULE)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3931.
|
This is the source code for early-access 3932.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ android {
|
||||||
namespace = "org.yuzu.yuzu_emu"
|
namespace = "org.yuzu.yuzu_emu"
|
||||||
|
|
||||||
compileSdkVersion = "android-34"
|
compileSdkVersion = "android-34"
|
||||||
ndkVersion = "25.2.9519653"
|
ndkVersion = "26.1.10909125"
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
|
@ -203,23 +203,23 @@ ktlint {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.10.1")
|
implementation("androidx.core:core-ktx:1.12.0")
|
||||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
implementation("androidx.recyclerview:recyclerview:1.3.0")
|
implementation("androidx.recyclerview:recyclerview:1.3.1")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.fragment:fragment-ktx:1.6.0")
|
implementation("androidx.fragment:fragment-ktx:1.6.1")
|
||||||
implementation("androidx.documentfile:documentfile:1.0.1")
|
implementation("androidx.documentfile:documentfile:1.0.1")
|
||||||
implementation("com.google.android.material:material:1.9.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
implementation("androidx.preference:preference:1.2.0")
|
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
|
||||||
implementation("io.coil-kt:coil:2.2.2")
|
implementation("io.coil-kt:coil:2.2.2")
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.window:window:1.2.0-beta03")
|
implementation("androidx.window:window:1.2.0-beta03")
|
||||||
implementation("org.ini4j:ini4j:0.5.4")
|
implementation("org.ini4j:ini4j:0.5.4")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
|
||||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
android:localeConfig="@xml/locales_config"
|
android:localeConfig="@xml/locales_config"
|
||||||
android:banner="@drawable/tv_banner"
|
android:banner="@drawable/tv_banner"
|
||||||
android:extractNativeLibs="true"
|
|
||||||
android:fullBackupContent="@xml/data_extraction_rules"
|
android:fullBackupContent="@xml/data_extraction_rules"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
|
||||||
android:enableOnBackInvokedCallback="true">
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.utils.FileUtil
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class DriverManagerFragment : Fragment() {
|
class DriverManagerFragment : Fragment() {
|
||||||
|
@ -154,29 +155,29 @@ class DriverManagerFragment : Fragment() {
|
||||||
R.string.installing_driver,
|
R.string.installing_driver,
|
||||||
false
|
false
|
||||||
) {
|
) {
|
||||||
|
val driverPath =
|
||||||
|
"${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}"
|
||||||
|
val driverFile = File(driverPath)
|
||||||
|
|
||||||
// Ignore file exceptions when a user selects an invalid zip
|
// Ignore file exceptions when a user selects an invalid zip
|
||||||
try {
|
try {
|
||||||
GpuDriverHelper.copyDriverToInternalStorage(result)
|
if (!GpuDriverHelper.copyDriverToInternalStorage(result)) {
|
||||||
|
throw IOException("Driver failed validation!")
|
||||||
|
}
|
||||||
} catch (_: IOException) {
|
} catch (_: IOException) {
|
||||||
|
if (driverFile.exists()) {
|
||||||
|
driverFile.delete()
|
||||||
|
}
|
||||||
return@newInstance getString(R.string.select_gpu_driver_error)
|
return@newInstance getString(R.string.select_gpu_driver_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
val driverData = GpuDriverHelper.customDriverData
|
val driverData = GpuDriverHelper.getMetadataFromZip(driverFile)
|
||||||
if (driverData.name == null) {
|
|
||||||
return@newInstance getString(R.string.select_gpu_driver_error)
|
|
||||||
}
|
|
||||||
|
|
||||||
val driverInList =
|
val driverInList =
|
||||||
driverViewModel.driverList.value.firstOrNull { it.second == driverData }
|
driverViewModel.driverList.value.firstOrNull { it.second == driverData }
|
||||||
if (driverInList != null) {
|
if (driverInList != null) {
|
||||||
return@newInstance getString(R.string.driver_already_installed)
|
return@newInstance getString(R.string.driver_already_installed)
|
||||||
} else {
|
} else {
|
||||||
driverViewModel.addDriver(
|
driverViewModel.addDriver(Pair(driverPath, driverData))
|
||||||
Pair(
|
|
||||||
"${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}",
|
|
||||||
driverData
|
|
||||||
)
|
|
||||||
)
|
|
||||||
driverViewModel.setNewDriverInstalled(true)
|
driverViewModel.setNewDriverInstalled(true)
|
||||||
}
|
}
|
||||||
return@newInstance Any()
|
return@newInstance Any()
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.0.2" apply false
|
id("com.android.application") version "8.1.2" apply false
|
||||||
id("com.android.library") version "8.0.2" apply false
|
id("com.android.library") version "8.1.2" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.21" apply false
|
id("org.jetbrains.kotlin.android") version "1.8.21" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <stop_token>
|
#include <stop_token>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
template <typename Condvar, typename Lock, typename Pred>
|
template <typename Condvar, typename Lock, typename Pred>
|
||||||
void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) {
|
void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token, Pred&& pred) {
|
||||||
cv.wait(lk, token, std::move(pred));
|
cv.wait(lk, token, std::forward<Pred>(pred));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Rep, typename Period>
|
template <typename Rep, typename Period>
|
||||||
|
@ -109,7 +110,7 @@ public:
|
||||||
|
|
||||||
// Insert the callback.
|
// Insert the callback.
|
||||||
stop_state_callback ret = ++m_next_callback;
|
stop_state_callback ret = ++m_next_callback;
|
||||||
m_callbacks.emplace(ret, move(f));
|
m_callbacks.emplace(ret, std::move(f));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ private:
|
||||||
friend class stop_source;
|
friend class stop_source;
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
friend class stop_callback;
|
friend class stop_callback;
|
||||||
stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {}
|
stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(std::move(stop_state)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||||
|
@ -198,7 +199,7 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class jthread;
|
friend class jthread;
|
||||||
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
|
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
|
||||||
: m_stop_state(move(stop_state)) {}
|
: m_stop_state(std::move(stop_state)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||||
|
@ -218,16 +219,16 @@ public:
|
||||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||||
: m_stop_state(st.m_stop_state) {
|
: m_stop_state(st.m_stop_state) {
|
||||||
if (m_stop_state) {
|
if (m_stop_state) {
|
||||||
m_callback = m_stop_state->insert_callback(move(cb));
|
m_callback = m_stop_state->insert_callback(std::move(cb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename C>
|
template <typename C>
|
||||||
requires constructible_from<Callback, C>
|
requires constructible_from<Callback, C>
|
||||||
explicit stop_callback(stop_token&& st,
|
explicit stop_callback(stop_token&& st,
|
||||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||||
: m_stop_state(move(st.m_stop_state)) {
|
: m_stop_state(std::move(st.m_stop_state)) {
|
||||||
if (m_stop_state) {
|
if (m_stop_state) {
|
||||||
m_callback = m_stop_state->insert_callback(move(cb));
|
m_callback = m_stop_state->insert_callback(std::move(cb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~stop_callback() {
|
~stop_callback() {
|
||||||
|
@ -260,7 +261,7 @@ public:
|
||||||
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
|
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
|
||||||
explicit jthread(F&& f, Args&&... args)
|
explicit jthread(F&& f, Args&&... args)
|
||||||
: m_stop_state(make_shared<polyfill::stop_state>()),
|
: m_stop_state(make_shared<polyfill::stop_state>()),
|
||||||
m_thread(make_thread(move(f), move(args)...)) {}
|
m_thread(make_thread(std::forward<F>(f), std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
~jthread() {
|
~jthread() {
|
||||||
if (joinable()) {
|
if (joinable()) {
|
||||||
|
@ -317,9 +318,9 @@ private:
|
||||||
template <typename F, typename... Args>
|
template <typename F, typename... Args>
|
||||||
thread make_thread(F&& f, Args&&... args) {
|
thread make_thread(F&& f, Args&&... args) {
|
||||||
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
|
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
|
||||||
return thread(move(f), get_stop_token(), move(args)...);
|
return thread(std::forward<F>(f), get_stop_token(), std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
return thread(move(f), move(args)...);
|
return thread(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,11 +116,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (concat.empty()) {
|
return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(dir->GetName(),
|
||||||
return nullptr;
|
std::move(concat));
|
||||||
}
|
|
||||||
|
|
||||||
return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Common::FS::IsDir(path)) {
|
if (Common::FS::IsDir(path)) {
|
||||||
|
|
|
@ -107,62 +107,56 @@ static u64 romfs_get_hash_table_count(u64 num_entries) {
|
||||||
|
|
||||||
void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir,
|
void RomFSBuildContext::VisitDirectory(VirtualDir romfs_dir, VirtualDir ext_dir,
|
||||||
std::shared_ptr<RomFSBuildDirectoryContext> parent) {
|
std::shared_ptr<RomFSBuildDirectoryContext> parent) {
|
||||||
std::vector<std::shared_ptr<RomFSBuildDirectoryContext>> child_dirs;
|
for (auto& child_romfs_file : romfs_dir->GetFiles()) {
|
||||||
|
const auto name = child_romfs_file->GetName();
|
||||||
|
const auto child = std::make_shared<RomFSBuildFileContext>();
|
||||||
|
// Set child's path.
|
||||||
|
child->cur_path_ofs = parent->path_len + 1;
|
||||||
|
child->path_len = child->cur_path_ofs + static_cast<u32>(name.size());
|
||||||
|
child->path = parent->path + "/" + name;
|
||||||
|
|
||||||
const auto entries = romfs_dir->GetEntries();
|
if (ext_dir != nullptr && ext_dir->GetFile(name + ".stub") != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& kv : entries) {
|
// Sanity check on path_len
|
||||||
if (kv.second == VfsEntryType::Directory) {
|
ASSERT(child->path_len < FS_MAX_PATH);
|
||||||
const auto child = std::make_shared<RomFSBuildDirectoryContext>();
|
|
||||||
// Set child's path.
|
|
||||||
child->cur_path_ofs = parent->path_len + 1;
|
|
||||||
child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size());
|
|
||||||
child->path = parent->path + "/" + kv.first;
|
|
||||||
|
|
||||||
if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) {
|
child->source = std::move(child_romfs_file);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check on path_len
|
if (ext_dir != nullptr) {
|
||||||
ASSERT(child->path_len < FS_MAX_PATH);
|
if (const auto ips = ext_dir->GetFile(name + ".ips")) {
|
||||||
|
if (auto patched = PatchIPS(child->source, ips)) {
|
||||||
if (AddDirectory(parent, child)) {
|
child->source = std::move(patched);
|
||||||
child_dirs.push_back(child);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto child = std::make_shared<RomFSBuildFileContext>();
|
|
||||||
// Set child's path.
|
|
||||||
child->cur_path_ofs = parent->path_len + 1;
|
|
||||||
child->path_len = child->cur_path_ofs + static_cast<u32>(kv.first.size());
|
|
||||||
child->path = parent->path + "/" + kv.first;
|
|
||||||
|
|
||||||
if (ext_dir != nullptr && ext_dir->GetFile(kv.first + ".stub") != nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check on path_len
|
|
||||||
ASSERT(child->path_len < FS_MAX_PATH);
|
|
||||||
|
|
||||||
child->source = romfs_dir->GetFile(kv.first);
|
|
||||||
|
|
||||||
if (ext_dir != nullptr) {
|
|
||||||
if (const auto ips = ext_dir->GetFile(kv.first + ".ips")) {
|
|
||||||
if (auto patched = PatchIPS(child->source, ips)) {
|
|
||||||
child->source = std::move(patched);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child->size = child->source->GetSize();
|
|
||||||
|
|
||||||
AddFile(parent, child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
child->size = child->source->GetSize();
|
||||||
|
|
||||||
|
AddFile(parent, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& child : child_dirs) {
|
for (auto& child_romfs_dir : romfs_dir->GetSubdirectories()) {
|
||||||
auto subdir_name = std::string_view(child->path).substr(child->cur_path_ofs);
|
const auto name = child_romfs_dir->GetName();
|
||||||
auto child_romfs_dir = romfs_dir->GetSubdirectory(subdir_name);
|
const auto child = std::make_shared<RomFSBuildDirectoryContext>();
|
||||||
auto child_ext_dir = ext_dir != nullptr ? ext_dir->GetSubdirectory(subdir_name) : nullptr;
|
// Set child's path.
|
||||||
|
child->cur_path_ofs = parent->path_len + 1;
|
||||||
|
child->path_len = child->cur_path_ofs + static_cast<u32>(name.size());
|
||||||
|
child->path = parent->path + "/" + name;
|
||||||
|
|
||||||
|
if (ext_dir != nullptr && ext_dir->GetFile(name + ".stub") != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check on path_len
|
||||||
|
ASSERT(child->path_len < FS_MAX_PATH);
|
||||||
|
|
||||||
|
if (!AddDirectory(parent, child)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto child_ext_dir = ext_dir != nullptr ? ext_dir->GetSubdirectory(name) : nullptr;
|
||||||
this->VisitDirectory(child_romfs_dir, child_ext_dir, child);
|
this->VisitDirectory(child_romfs_dir, child_ext_dir, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,7 +287,7 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
|
||||||
|
|
||||||
cur_entry.name_size = name_size;
|
cur_entry.name_size = name_size;
|
||||||
|
|
||||||
out.emplace(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->source);
|
out.emplace(cur_file->offset + ROMFS_FILEPARTITION_OFS, std::move(cur_file->source));
|
||||||
std::memcpy(file_table.data() + cur_file->entry_offset, &cur_entry, sizeof(RomFSFileEntry));
|
std::memcpy(file_table.data() + cur_file->entry_offset, &cur_entry, sizeof(RomFSFileEntry));
|
||||||
std::memset(file_table.data() + cur_file->entry_offset + sizeof(RomFSFileEntry), 0,
|
std::memset(file_table.data() + cur_file->entry_offset + sizeof(RomFSFileEntry), 0,
|
||||||
Common::AlignUp(cur_entry.name_size, 4));
|
Common::AlignUp(cur_entry.name_size, 4));
|
||||||
|
|
|
@ -377,16 +377,16 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
|
||||||
|
|
||||||
auto romfs_dir = FindSubdirectoryCaseless(subdir, "romfs");
|
auto romfs_dir = FindSubdirectoryCaseless(subdir, "romfs");
|
||||||
if (romfs_dir != nullptr)
|
if (romfs_dir != nullptr)
|
||||||
layers.push_back(std::make_shared<CachedVfsDirectory>(romfs_dir));
|
layers.emplace_back(std::make_shared<CachedVfsDirectory>(std::move(romfs_dir)));
|
||||||
|
|
||||||
auto ext_dir = FindSubdirectoryCaseless(subdir, "romfs_ext");
|
auto ext_dir = FindSubdirectoryCaseless(subdir, "romfs_ext");
|
||||||
if (ext_dir != nullptr)
|
if (ext_dir != nullptr)
|
||||||
layers_ext.push_back(std::make_shared<CachedVfsDirectory>(ext_dir));
|
layers_ext.emplace_back(std::make_shared<CachedVfsDirectory>(std::move(ext_dir)));
|
||||||
|
|
||||||
if (type == ContentRecordType::HtmlDocument) {
|
if (type == ContentRecordType::HtmlDocument) {
|
||||||
auto manual_dir = FindSubdirectoryCaseless(subdir, "manual_html");
|
auto manual_dir = FindSubdirectoryCaseless(subdir, "manual_html");
|
||||||
if (manual_dir != nullptr)
|
if (manual_dir != nullptr)
|
||||||
layers.push_back(std::make_shared<CachedVfsDirectory>(manual_dir));
|
layers.emplace_back(std::make_shared<CachedVfsDirectory>(std::move(manual_dir)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
layers.push_back(std::move(extracted));
|
layers.emplace_back(std::move(extracted));
|
||||||
|
|
||||||
auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers));
|
auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers));
|
||||||
if (layered == nullptr) {
|
if (layered == nullptr) {
|
||||||
|
|
|
@ -322,7 +322,8 @@ VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& open_di
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConcatenatedVfsFile::MakeConcatenatedFile(concat, concat.front()->GetName());
|
auto name = concat.front()->GetName();
|
||||||
|
return ConcatenatedVfsFile::MakeConcatenatedFile(std::move(name), std::move(concat));
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
|
VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
|
||||||
|
|
|
@ -133,7 +133,7 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
|
||||||
out = out->GetSubdirectories().front();
|
out = out->GetSubdirectories().front();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<CachedVfsDirectory>(out);
|
return std::make_shared<CachedVfsDirectory>(std::move(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
|
VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
|
||||||
|
@ -141,8 +141,7 @@ VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
RomFSBuildContext ctx{dir, ext};
|
RomFSBuildContext ctx{dir, ext};
|
||||||
auto file_map = ctx.Build();
|
return ConcatenatedVfsFile::MakeConcatenatedFile(0, dir->GetName(), ctx.Build());
|
||||||
return ConcatenatedVfsFile::MakeConcatenatedFile(0, file_map, dir->GetName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
CachedVfsDirectory::CachedVfsDirectory(VirtualDir& source_dir)
|
CachedVfsDirectory::CachedVfsDirectory(VirtualDir&& source_dir)
|
||||||
: name(source_dir->GetName()), parent(source_dir->GetParentDirectory()) {
|
: name(source_dir->GetName()), parent(source_dir->GetParentDirectory()) {
|
||||||
for (auto& dir : source_dir->GetSubdirectories()) {
|
for (auto& dir : source_dir->GetSubdirectories()) {
|
||||||
dirs.emplace(dir->GetName(), std::make_shared<CachedVfsDirectory>(dir));
|
dirs.emplace(dir->GetName(), std::make_shared<CachedVfsDirectory>(std::move(dir)));
|
||||||
}
|
}
|
||||||
for (auto& file : source_dir->GetFiles()) {
|
for (auto& file : source_dir->GetFiles()) {
|
||||||
files.emplace(file->GetName(), file);
|
files.emplace(file->GetName(), std::move(file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace FileSys {
|
||||||
|
|
||||||
class CachedVfsDirectory : public ReadOnlyVfsDirectory {
|
class CachedVfsDirectory : public ReadOnlyVfsDirectory {
|
||||||
public:
|
public:
|
||||||
CachedVfsDirectory(VirtualDir& source_directory);
|
CachedVfsDirectory(VirtualDir&& source_directory);
|
||||||
|
|
||||||
~CachedVfsDirectory() override;
|
~CachedVfsDirectory() override;
|
||||||
VirtualFile GetFile(std::string_view file_name) const override;
|
VirtualFile GetFile(std::string_view file_name) const override;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
ConcatenatedVfsFile::ConcatenatedVfsFile(ConcatenationMap&& concatenation_map_, std::string&& name_)
|
ConcatenatedVfsFile::ConcatenatedVfsFile(std::string&& name_, ConcatenationMap&& concatenation_map_)
|
||||||
: concatenation_map(std::move(concatenation_map_)), name(std::move(name_)) {
|
: concatenation_map(std::move(concatenation_map_)), name(std::move(name_)) {
|
||||||
DEBUG_ASSERT(this->VerifyContinuity());
|
DEBUG_ASSERT(this->VerifyContinuity());
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ bool ConcatenatedVfsFile::VerifyContinuity() const {
|
||||||
|
|
||||||
ConcatenatedVfsFile::~ConcatenatedVfsFile() = default;
|
ConcatenatedVfsFile::~ConcatenatedVfsFile() = default;
|
||||||
|
|
||||||
VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(const std::vector<VirtualFile>& files,
|
VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(std::string&& name,
|
||||||
std::string&& name) {
|
std::vector<VirtualFile>&& files) {
|
||||||
// Fold trivial cases.
|
// Fold trivial cases.
|
||||||
if (files.empty()) {
|
if (files.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -46,20 +46,21 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(const std::vector<VirtualF
|
||||||
u64 last_offset = 0;
|
u64 last_offset = 0;
|
||||||
|
|
||||||
for (auto& file : files) {
|
for (auto& file : files) {
|
||||||
|
const auto size = file->GetSize();
|
||||||
|
|
||||||
concatenation_map.emplace_back(ConcatenationEntry{
|
concatenation_map.emplace_back(ConcatenationEntry{
|
||||||
.offset = last_offset,
|
.offset = last_offset,
|
||||||
.file = file,
|
.file = std::move(file),
|
||||||
});
|
});
|
||||||
|
|
||||||
last_offset += file->GetSize();
|
last_offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VirtualFile(new ConcatenatedVfsFile(std::move(concatenation_map), std::move(name)));
|
return VirtualFile(new ConcatenatedVfsFile(std::move(name), std::move(concatenation_map)));
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
|
VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte, std::string&& name,
|
||||||
const std::multimap<u64, VirtualFile>& files,
|
std::multimap<u64, VirtualFile>&& files) {
|
||||||
std::string&& name) {
|
|
||||||
// Fold trivial cases.
|
// Fold trivial cases.
|
||||||
if (files.empty()) {
|
if (files.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -76,6 +77,8 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
|
||||||
|
|
||||||
// Iteration of a multimap is ordered, so offset will be strictly non-decreasing.
|
// Iteration of a multimap is ordered, so offset will be strictly non-decreasing.
|
||||||
for (auto& [offset, file] : files) {
|
for (auto& [offset, file] : files) {
|
||||||
|
const auto size = file->GetSize();
|
||||||
|
|
||||||
if (offset > last_offset) {
|
if (offset > last_offset) {
|
||||||
concatenation_map.emplace_back(ConcatenationEntry{
|
concatenation_map.emplace_back(ConcatenationEntry{
|
||||||
.offset = last_offset,
|
.offset = last_offset,
|
||||||
|
@ -85,13 +88,13 @@ VirtualFile ConcatenatedVfsFile::MakeConcatenatedFile(u8 filler_byte,
|
||||||
|
|
||||||
concatenation_map.emplace_back(ConcatenationEntry{
|
concatenation_map.emplace_back(ConcatenationEntry{
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.file = file,
|
.file = std::move(file),
|
||||||
});
|
});
|
||||||
|
|
||||||
last_offset = offset + file->GetSize();
|
last_offset = offset + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VirtualFile(new ConcatenatedVfsFile(std::move(concatenation_map), std::move(name)));
|
return VirtualFile(new ConcatenatedVfsFile(std::move(name), std::move(concatenation_map)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConcatenatedVfsFile::GetName() const {
|
std::string ConcatenatedVfsFile::GetName() const {
|
||||||
|
|
|
@ -24,22 +24,20 @@ private:
|
||||||
};
|
};
|
||||||
using ConcatenationMap = std::vector<ConcatenationEntry>;
|
using ConcatenationMap = std::vector<ConcatenationEntry>;
|
||||||
|
|
||||||
explicit ConcatenatedVfsFile(std::vector<ConcatenationEntry>&& concatenation_map,
|
explicit ConcatenatedVfsFile(std::string&& name,
|
||||||
std::string&& name);
|
std::vector<ConcatenationEntry>&& concatenation_map);
|
||||||
bool VerifyContinuity() const;
|
bool VerifyContinuity() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ConcatenatedVfsFile() override;
|
~ConcatenatedVfsFile() override;
|
||||||
|
|
||||||
/// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases.
|
/// Wrapper function to allow for more efficient handling of files.size() == 0, 1 cases.
|
||||||
static VirtualFile MakeConcatenatedFile(const std::vector<VirtualFile>& files,
|
static VirtualFile MakeConcatenatedFile(std::string&& name, std::vector<VirtualFile>&& files);
|
||||||
std::string&& name);
|
|
||||||
|
|
||||||
/// Convenience function that turns a map of offsets to files into a concatenated file, filling
|
/// Convenience function that turns a map of offsets to files into a concatenated file, filling
|
||||||
/// gaps with a given filler byte.
|
/// gaps with a given filler byte.
|
||||||
static VirtualFile MakeConcatenatedFile(u8 filler_byte,
|
static VirtualFile MakeConcatenatedFile(u8 filler_byte, std::string&& name,
|
||||||
const std::multimap<u64, VirtualFile>& files,
|
std::multimap<u64, VirtualFile>&& files);
|
||||||
std::string&& name);
|
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
std::size_t GetSize() const override;
|
std::size_t GetSize() const override;
|
||||||
|
|
|
@ -38,7 +38,7 @@ VirtualDir LayeredVfsDirectory::GetDirectoryRelative(std::string_view path) cons
|
||||||
for (const auto& layer : dirs) {
|
for (const auto& layer : dirs) {
|
||||||
auto dir = layer->GetDirectoryRelative(path);
|
auto dir = layer->GetDirectoryRelative(path);
|
||||||
if (dir != nullptr) {
|
if (dir != nullptr) {
|
||||||
out.push_back(std::move(dir));
|
out.emplace_back(std::move(dir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,11 +62,11 @@ std::vector<VirtualFile> LayeredVfsDirectory::GetFiles() const {
|
||||||
std::set<std::string, std::less<>> out_names;
|
std::set<std::string, std::less<>> out_names;
|
||||||
|
|
||||||
for (const auto& layer : dirs) {
|
for (const auto& layer : dirs) {
|
||||||
for (const auto& file : layer->GetFiles()) {
|
for (auto& file : layer->GetFiles()) {
|
||||||
auto file_name = file->GetName();
|
auto file_name = file->GetName();
|
||||||
if (!out_names.contains(file_name)) {
|
if (!out_names.contains(file_name)) {
|
||||||
out_names.emplace(std::move(file_name));
|
out_names.emplace(std::move(file_name));
|
||||||
out.push_back(file);
|
out.emplace_back(std::move(file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ std::vector<VirtualDir> LayeredVfsDirectory::GetSubdirectories() const {
|
||||||
std::vector<VirtualDir> out;
|
std::vector<VirtualDir> out;
|
||||||
out.reserve(names.size());
|
out.reserve(names.size());
|
||||||
for (const auto& subdir : names)
|
for (const auto& subdir : names)
|
||||||
out.push_back(GetSubdirectory(subdir));
|
out.emplace_back(GetSubdirectory(subdir));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue