early-access version 3927
This commit is contained in:
		| @@ -53,7 +53,7 @@ option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" | ||||
|  | ||||
| CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Compile LDN room server" ON "NOT ANDROID" OFF) | ||||
|  | ||||
| CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF) | ||||
| CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) | ||||
|  | ||||
| option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}") | ||||
|  | ||||
| @@ -179,9 +179,6 @@ if (YUZU_USE_BUNDLED_VCPKG) | ||||
|     if (YUZU_TESTS) | ||||
|         list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests") | ||||
|     endif() | ||||
|     if (YUZU_CRASH_DUMPS) | ||||
|         list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp") | ||||
|     endif() | ||||
|     if (ENABLE_WEB_SERVICE) | ||||
|         list(APPEND VCPKG_MANIFEST_FEATURES "web-service") | ||||
|     endif() | ||||
| @@ -587,6 +584,18 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG) | ||||
|     find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) | ||||
| endif() | ||||
|  | ||||
| if (WIN32 AND YUZU_CRASH_DUMPS) | ||||
|     set(BREAKPAD_VER "breakpad-c89f9dd") | ||||
|     download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX) | ||||
|  | ||||
|     set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include") | ||||
|     set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib") | ||||
|  | ||||
|     add_library(libbreakpad_client INTERFACE IMPORTED) | ||||
|     target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}") | ||||
|     target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}") | ||||
| endif() | ||||
|  | ||||
| # Prefer the -pthread flag on Linux. | ||||
| set(THREADS_PREFER_PTHREAD_FLAG ON) | ||||
| find_package(Threads REQUIRED) | ||||
| @@ -606,13 +615,6 @@ elseif (WIN32) | ||||
|         # PSAPI is the Process Status API | ||||
|         set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version) | ||||
|     endif() | ||||
|  | ||||
|     if (YUZU_CRASH_DUMPS) | ||||
|         find_library(DBGHELP_LIBRARY dbghelp) | ||||
|         if ("${DBGHELP_LIBRARY}" STREQUAL "DBGHELP_LIBRARY-NOTFOUND") | ||||
|             message(FATAL_ERROR "YUZU_CRASH_DUMPS enabled but dbghelp library not found") | ||||
|         endif() | ||||
|     endif() | ||||
| elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$") | ||||
|     set(PLATFORM_LIBRARIES rt) | ||||
| endif() | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| yuzu emulator early access | ||||
| ============= | ||||
|  | ||||
| This is the source code for early-access 3926. | ||||
| This is the source code for early-access 3927. | ||||
|  | ||||
| ## Legal Notice | ||||
|  | ||||
|   | ||||
							
								
								
									
										102
									
								
								externals/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								externals/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -185,3 +185,105 @@ if (ANDROID) | ||||
|        add_subdirectory(libadrenotools) | ||||
|    endif() | ||||
| endif() | ||||
|  | ||||
| # Breakpad | ||||
| # https://github.com/microsoft/vcpkg/blob/master/ports/breakpad/CMakeLists.txt | ||||
| if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client) | ||||
|     set(BREAKPAD_WIN32_DEFINES | ||||
|         NOMINMAX | ||||
|         UNICODE | ||||
|         WIN32_LEAN_AND_MEAN | ||||
|         _CRT_SECURE_NO_WARNINGS | ||||
|         _CRT_SECURE_NO_DEPRECATE | ||||
|         _CRT_NONSTDC_NO_DEPRECATE | ||||
|     ) | ||||
|  | ||||
|     # libbreakpad | ||||
|     add_library(libbreakpad STATIC) | ||||
|     file(GLOB_RECURSE LIBBREAKPAD_SOURCES breakpad/src/processor/*.cc) | ||||
|     file(GLOB_RECURSE LIBDISASM_SOURCES breakpad/src/third_party/libdisasm/*.c) | ||||
|     list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "_unittest|_selftest|synth_minidump|/tests|/testdata|/solaris|microdump_stackwalk|minidump_dump|minidump_stackwalk") | ||||
|     if (WIN32) | ||||
|         list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/mac|/android") | ||||
|         target_compile_definitions(libbreakpad PRIVATE ${BREAKPAD_WIN32_DEFINES}) | ||||
|         target_include_directories(libbreakpad PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include") | ||||
|     elseif (APPLE) | ||||
|         list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/linux|/windows|/android") | ||||
|     else() | ||||
|         list(FILTER LIBBREAKPAD_SOURCES EXCLUDE REGEX "/mac|/windows|/android") | ||||
|     endif() | ||||
|     target_sources(libbreakpad PRIVATE ${LIBBREAKPAD_SOURCES} ${LIBDISASM_SOURCES}) | ||||
|     target_include_directories(libbreakpad | ||||
|         PUBLIC | ||||
|             ${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src | ||||
|             ${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src/third_party/libdisasm | ||||
|     ) | ||||
|  | ||||
|     # libbreakpad_client | ||||
|     add_library(libbreakpad_client STATIC) | ||||
|     file(GLOB LIBBREAKPAD_COMMON_SOURCES breakpad/src/common/*.cc breakpad/src/common/*.c breakpad/src/client/*.cc) | ||||
|  | ||||
|     if (WIN32) | ||||
|         file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/windows/*.cc breakpad/src/common/windows/*.cc) | ||||
|         list(FILTER LIBBREAKPAD_COMMON_SOURCES EXCLUDE REGEX "language.cc|path_helper.cc|stabs_to_module.cc|stabs_reader.cc|minidump_file_writer.cc") | ||||
|         target_include_directories(libbreakpad_client PRIVATE "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/include") | ||||
|         target_compile_definitions(libbreakpad_client PRIVATE ${BREAKPAD_WIN32_DEFINES}) | ||||
|     elseif (APPLE) | ||||
|         target_compile_definitions(libbreakpad_client PRIVATE HAVE_MACH_O_NLIST_H) | ||||
|         file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/mac/*.cc breakpad/src/common/mac/*.cc) | ||||
|         list(APPEND LIBBREAKPAD_CLIENT_SOURCES breakpad/src/common/mac/MachIPC.mm) | ||||
|     else() | ||||
|         target_compile_definitions(libbreakpad_client PUBLIC -DHAVE_A_OUT_H) | ||||
|         file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES breakpad/src/client/linux/*.cc breakpad/src/common/linux/*.cc) | ||||
|     endif() | ||||
|     list(APPEND LIBBREAKPAD_CLIENT_SOURCES ${LIBBREAKPAD_COMMON_SOURCES}) | ||||
|     list(FILTER LIBBREAKPAD_CLIENT_SOURCES EXCLUDE REGEX "/sender|/tests|/unittests|/testcases|_unittest|_test") | ||||
|     target_sources(libbreakpad_client PRIVATE ${LIBBREAKPAD_CLIENT_SOURCES}) | ||||
|     target_include_directories(libbreakpad_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/breakpad/src) | ||||
|  | ||||
|     if (WIN32) | ||||
|         target_link_libraries(libbreakpad_client PRIVATE wininet.lib) | ||||
|     elseif (APPLE) | ||||
|         find_library(CoreFoundation_FRAMEWORK CoreFoundation) | ||||
|         target_link_libraries(libbreakpad_client PRIVATE ${CoreFoundation_FRAMEWORK}) | ||||
|     else() | ||||
|         find_library(PTHREAD_LIBRARIES pthread) | ||||
|         target_compile_definitions(libbreakpad_client PRIVATE HAVE_GETCONTEXT=1) | ||||
|         if (PTHREAD_LIBRARIES) | ||||
|             target_link_libraries(libbreakpad_client PRIVATE ${PTHREAD_LIBRARIES}) | ||||
|         endif() | ||||
|     endif() | ||||
|  | ||||
|     # Host tools for symbol processing | ||||
|     if (LINUX) | ||||
|         find_package(ZLIB REQUIRED) | ||||
|  | ||||
|         add_executable(minidump_stackwalk breakpad/src/processor/minidump_stackwalk.cc) | ||||
|         target_link_libraries(minidump_stackwalk PRIVATE libbreakpad libbreakpad_client) | ||||
|  | ||||
|         add_executable(dump_syms | ||||
|             breakpad/src/common/dwarf_cfi_to_module.cc | ||||
|             breakpad/src/common/dwarf_cu_to_module.cc | ||||
|             breakpad/src/common/dwarf_line_to_module.cc | ||||
|             breakpad/src/common/dwarf_range_list_handler.cc | ||||
|             breakpad/src/common/language.cc | ||||
|             breakpad/src/common/module.cc | ||||
|             breakpad/src/common/path_helper.cc | ||||
|             breakpad/src/common/stabs_reader.cc | ||||
|             breakpad/src/common/stabs_to_module.cc | ||||
|             breakpad/src/common/dwarf/bytereader.cc | ||||
|             breakpad/src/common/dwarf/dwarf2diehandler.cc | ||||
|             breakpad/src/common/dwarf/dwarf2reader.cc | ||||
|             breakpad/src/common/dwarf/elf_reader.cc | ||||
|             breakpad/src/common/linux/crc32.cc | ||||
|             breakpad/src/common/linux/dump_symbols.cc | ||||
|             breakpad/src/common/linux/elf_symbols_to_module.cc | ||||
|             breakpad/src/common/linux/elfutils.cc | ||||
|             breakpad/src/common/linux/file_id.cc | ||||
|             breakpad/src/common/linux/linux_libc_support.cc | ||||
|             breakpad/src/common/linux/memory_mapped_file.cc | ||||
|             breakpad/src/common/linux/safe_readlink.cc | ||||
|             breakpad/src/tools/linux/dump_syms/dump_syms.cc) | ||||
|         target_link_libraries(dump_syms PRIVATE libbreakpad_client ZLIB::ZLIB) | ||||
|     endif() | ||||
| endif() | ||||
|   | ||||
| @@ -39,8 +39,12 @@ | ||||
| #define Crash() exit(1) | ||||
| #endif | ||||
|  | ||||
| #define LTO_NOINLINE __attribute__((noinline)) | ||||
|  | ||||
| #else // _MSC_VER | ||||
|  | ||||
| #define LTO_NOINLINE | ||||
|  | ||||
| // Locale Cross-Compatibility | ||||
| #define locale_t _locale_t | ||||
|  | ||||
|   | ||||
| @@ -211,6 +211,11 @@ struct Elf64_Rela { | ||||
|     Elf64_Sxword r_addend; /* Addend */ | ||||
| }; | ||||
|  | ||||
| /* RELR relocation table entry */ | ||||
|  | ||||
| using Elf32_Relr = Elf32_Word; | ||||
| using Elf64_Relr = Elf64_Xword; | ||||
|  | ||||
| /* How to extract and insert information held in the r_info field.  */ | ||||
|  | ||||
| static inline u32 Elf32RelSymIndex(Elf32_Word r_info) { | ||||
| @@ -328,6 +333,9 @@ constexpr u32 ElfDtFiniArray = 26;   /* Array with addresses of fini fct */ | ||||
| constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */ | ||||
| constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */ | ||||
| constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */ | ||||
| constexpr u32 ElfDtRelrsz = 35;      /* Size of RELR relative relocations */ | ||||
| constexpr u32 ElfDtRelr = 36;        /* Address of RELR relative relocations */ | ||||
| constexpr u32 ElfDtRelrent = 37;     /* Size of one RELR relative relocation */ | ||||
|  | ||||
| } // namespace ELF | ||||
| } // namespace Common | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #define AMIIBO_DIR "amiibo" | ||||
| #define CACHE_DIR "cache" | ||||
| #define CONFIG_DIR "config" | ||||
| #define CRASH_DUMPS_DIR "crash_dumps" | ||||
| #define DUMP_DIR "dump" | ||||
| #define KEYS_DIR "keys" | ||||
| #define LOAD_DIR "load" | ||||
|   | ||||
| @@ -119,6 +119,7 @@ public: | ||||
|         GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR); | ||||
|         GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); | ||||
|         GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); | ||||
|         GenerateYuzuPath(YuzuPath::CrashDumpsDir, yuzu_path / CRASH_DUMPS_DIR); | ||||
|         GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); | ||||
|         GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR); | ||||
|         GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); | ||||
|   | ||||
| @@ -15,6 +15,7 @@ enum class YuzuPath { | ||||
|     AmiiboDir,      // Where Amiibo backups are stored. | ||||
|     CacheDir,       // Where cached filesystem data is stored. | ||||
|     ConfigDir,      // Where config files are stored. | ||||
|     CrashDumpsDir,  // Where crash dumps are stored. | ||||
|     DumpDir,        // Where dumped data is stored. | ||||
|     KeysDir,        // Where key files are stored. | ||||
|     LoadDir,        // Where cheat/mod files are stored. | ||||
|   | ||||
| @@ -502,7 +502,6 @@ struct Values { | ||||
|         linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false}; | ||||
|     Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers", | ||||
|                                          Category::Debugging}; | ||||
|     Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging}; | ||||
|     Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging}; | ||||
|  | ||||
|     // Miscellaneous | ||||
|   | ||||
| @@ -373,7 +373,7 @@ struct KernelCore::Impl { | ||||
|     static inline thread_local u8 host_thread_id = UINT8_MAX; | ||||
|  | ||||
|     /// Sets the host thread ID for the caller. | ||||
|     u32 SetHostThreadId(std::size_t core_id) { | ||||
|     LTO_NOINLINE u32 SetHostThreadId(std::size_t core_id) { | ||||
|         // This should only be called during core init. | ||||
|         ASSERT(host_thread_id == UINT8_MAX); | ||||
|  | ||||
| @@ -384,13 +384,13 @@ struct KernelCore::Impl { | ||||
|     } | ||||
|  | ||||
|     /// Gets the host thread ID for the caller | ||||
|     u32 GetHostThreadId() const { | ||||
|     LTO_NOINLINE u32 GetHostThreadId() const { | ||||
|         return host_thread_id; | ||||
|     } | ||||
|  | ||||
|     // Gets the dummy KThread for the caller, allocating a new one if this is the first time | ||||
|     KThread* GetHostDummyThread(KThread* existing_thread) { | ||||
|         const auto initialize{[](KThread* thread) { | ||||
|     LTO_NOINLINE KThread* GetHostDummyThread(KThread* existing_thread) { | ||||
|         const auto initialize{[](KThread* thread) LTO_NOINLINE { | ||||
|             ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); | ||||
|             return thread; | ||||
|         }}; | ||||
| @@ -424,11 +424,11 @@ struct KernelCore::Impl { | ||||
|  | ||||
|     static inline thread_local bool is_phantom_mode_for_singlecore{false}; | ||||
|  | ||||
|     bool IsPhantomModeForSingleCore() const { | ||||
|     LTO_NOINLINE bool IsPhantomModeForSingleCore() const { | ||||
|         return is_phantom_mode_for_singlecore; | ||||
|     } | ||||
|  | ||||
|     void SetIsPhantomModeForSingleCore(bool value) { | ||||
|     LTO_NOINLINE void SetIsPhantomModeForSingleCore(bool value) { | ||||
|         ASSERT(!is_multicore); | ||||
|         is_phantom_mode_for_singlecore = value; | ||||
|     } | ||||
| @@ -439,14 +439,14 @@ struct KernelCore::Impl { | ||||
|  | ||||
|     static inline thread_local KThread* current_thread{nullptr}; | ||||
|  | ||||
|     KThread* GetCurrentEmuThread() { | ||||
|     LTO_NOINLINE KThread* GetCurrentEmuThread() { | ||||
|         if (!current_thread) { | ||||
|             current_thread = GetHostDummyThread(nullptr); | ||||
|         } | ||||
|         return current_thread; | ||||
|     } | ||||
|  | ||||
|     void SetCurrentEmuThread(KThread* thread) { | ||||
|     LTO_NOINLINE void SetCurrentEmuThread(KThread* thread) { | ||||
|         current_thread = thread; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -87,7 +87,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu | ||||
|  | ||||
| Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, | ||||
|                                       ContentType contex_type, s64 start_posix_time, | ||||
|                                       s64 end_posix_time, u64 aruid) { | ||||
|                                       s64 end_posix_time, u64 aruid) const { | ||||
|     if (!is_mounted) { | ||||
|         return ResultIsNotMounted; | ||||
|     } | ||||
| @@ -115,7 +115,7 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& ou | ||||
|  | ||||
| Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, | ||||
|                                       ContentType contex_type, AlbumFileDateTime start_date, | ||||
|                                       AlbumFileDateTime end_date, u64 aruid) { | ||||
|                                       AlbumFileDateTime end_date, u64 aruid) const { | ||||
|     if (!is_mounted) { | ||||
|         return ResultIsNotMounted; | ||||
|     } | ||||
|   | ||||
| @@ -46,10 +46,10 @@ public: | ||||
|                             u8 flags) const; | ||||
|     Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries, | ||||
|                             ContentType contex_type, s64 start_posix_time, s64 end_posix_time, | ||||
|                             u64 aruid); | ||||
|                             u64 aruid) const; | ||||
|     Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries, | ||||
|                             ContentType contex_type, AlbumFileDateTime start_date, | ||||
|                             AlbumFileDateTime end_date, u64 aruid); | ||||
|                             AlbumFileDateTime end_date, u64 aruid) const; | ||||
|     Result GetAutoSavingStorage(bool& out_is_autosaving) const; | ||||
|     Result LoadAlbumScreenShotImage(LoadAlbumScreenShotImageOutput& out_image_output, | ||||
|                                     std::vector<u8>& out_image, const AlbumFileId& file_id, | ||||
|   | ||||
| @@ -156,6 +156,8 @@ public: | ||||
|  | ||||
|     bool LoadNRO(std::span<const u8> data) { | ||||
|         local_memory.clear(); | ||||
|  | ||||
|         relocbase = local_memory.size(); | ||||
|         local_memory.insert(local_memory.end(), data.begin(), data.end()); | ||||
|  | ||||
|         if (FixupRelocations()) { | ||||
| @@ -181,8 +183,8 @@ public: | ||||
|         // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html | ||||
|         // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html | ||||
|         VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; | ||||
|         VAddr rela_dyn = 0; | ||||
|         size_t num_rela = 0; | ||||
|         VAddr rela_dyn = 0, relr_dyn = 0; | ||||
|         size_t num_rela = 0, num_relr = 0; | ||||
|         while (true) { | ||||
|             const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)}; | ||||
|             dynamic_offset += sizeof(Elf64_Dyn); | ||||
| @@ -196,6 +198,12 @@ public: | ||||
|             if (dyn.d_tag == ElfDtRelasz) { | ||||
|                 num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela); | ||||
|             } | ||||
|             if (dyn.d_tag == ElfDtRelr) { | ||||
|                 relr_dyn = dyn.d_un.d_ptr; | ||||
|             } | ||||
|             if (dyn.d_tag == ElfDtRelrsz) { | ||||
|                 num_relr = dyn.d_un.d_val / sizeof(Elf64_Relr); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (size_t i = 0; i < num_rela; i++) { | ||||
| @@ -207,6 +215,29 @@ public: | ||||
|             callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend); | ||||
|         } | ||||
|  | ||||
|         VAddr relr_where = 0; | ||||
|         for (size_t i = 0; i < num_relr; i++) { | ||||
|             const auto relr{callbacks->ReadMemory<Elf64_Relr>(relr_dyn + i * sizeof(Elf64_Relr))}; | ||||
|             const auto incr{[&](VAddr where) { | ||||
|                 callbacks->MemoryWrite64(where, callbacks->MemoryRead64(where) + relocbase); | ||||
|             }}; | ||||
|  | ||||
|             if ((relr & 1) == 0) { | ||||
|                 // where pointer | ||||
|                 relr_where = relocbase + relr; | ||||
|                 incr(relr_where); | ||||
|                 relr_where += sizeof(Elf64_Addr); | ||||
|             } else { | ||||
|                 // bitmap | ||||
|                 for (int bit = 1; bit < 64; bit++) { | ||||
|                     if ((relr & (1ULL << bit)) != 0) { | ||||
|                         incr(relr_where + i * sizeof(Elf64_Addr)); | ||||
|                     } | ||||
|                 } | ||||
|                 relr_where += 63 * sizeof(Elf64_Addr); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -313,6 +344,7 @@ public: | ||||
|     Core::Memory::Memory& memory; | ||||
|     VAddr top_of_stack; | ||||
|     VAddr heap_pointer; | ||||
|     VAddr relocbase; | ||||
| }; | ||||
|  | ||||
| void DynarmicCallbacks64::CallSVC(u32 swi) { | ||||
|   | ||||
| @@ -62,7 +62,11 @@ using BufferId = SlotId; | ||||
| using VideoCore::Surface::PixelFormat; | ||||
| using namespace Common::Literals; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
| constexpr u32 NUM_VERTEX_BUFFERS = 16; | ||||
| #else | ||||
| constexpr u32 NUM_VERTEX_BUFFERS = 32; | ||||
| #endif | ||||
| constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; | ||||
| constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; | ||||
| constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; | ||||
|   | ||||
| @@ -3,16 +3,16 @@ | ||||
|  | ||||
| #version 450 | ||||
|  | ||||
| precision mediump int; | ||||
| precision highp float; | ||||
|  | ||||
| layout(binding = 0) uniform sampler2D depth_tex; | ||||
| layout(binding = 1) uniform isampler2D stencil_tex; | ||||
| layout(binding = 1) uniform usampler2D stencil_tex; | ||||
|  | ||||
| layout(location = 0) out vec4 color; | ||||
|  | ||||
| void main() { | ||||
|     ivec2 coord = ivec2(gl_FragCoord.xy); | ||||
|     uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||||
|     uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||||
|  | ||||
|     highp uint depth_val = | ||||
|         uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0)); | ||||
|     lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r; | ||||
|   | ||||
| @@ -3,16 +3,16 @@ | ||||
|  | ||||
| #version 450 | ||||
|  | ||||
| precision mediump int; | ||||
| precision highp float; | ||||
|  | ||||
| layout(binding = 0) uniform sampler2D depth_tex; | ||||
| layout(binding = 1) uniform isampler2D stencil_tex; | ||||
| layout(binding = 1) uniform usampler2D stencil_tex; | ||||
|  | ||||
| layout(location = 0) out vec4 color; | ||||
|  | ||||
| void main() { | ||||
|     ivec2 coord = ivec2(gl_FragCoord.xy); | ||||
|     uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f)); | ||||
|     uint stencil = uint(textureLod(stencil_tex, coord, 0).r); | ||||
|  | ||||
|     highp uint depth_val = | ||||
|         uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0)); | ||||
|     lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r; | ||||
|   | ||||
| @@ -1436,6 +1436,7 @@ void QueryCacheRuntime::Barriers(bool is_prebarrier) { | ||||
|         .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|         .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, | ||||
|     }; | ||||
|     impl->scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     if (is_prebarrier) { | ||||
|         impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { | ||||
|             cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||||
|   | ||||
| @@ -975,6 +975,19 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs | ||||
|     if (!state_tracker.TouchScissors()) { | ||||
|         return; | ||||
|     } | ||||
|     if (!regs.viewport_scale_offset_enabled) { | ||||
|         const auto x = static_cast<float>(regs.surface_clip.x); | ||||
|         const auto y = static_cast<float>(regs.surface_clip.y); | ||||
|         const auto width = static_cast<float>(regs.surface_clip.width); | ||||
|         const auto height = static_cast<float>(regs.surface_clip.height); | ||||
|         VkRect2D scissor; | ||||
|         scissor.offset.x = static_cast<u32>(x); | ||||
|         scissor.offset.y = static_cast<u32>(y); | ||||
|         scissor.extent.width = static_cast<u32>(width != 0.0f ? width : 1.0f); | ||||
|         scissor.extent.height = static_cast<u32>(height != 0.0f ? height : 1.0f); | ||||
|         scheduler.Record([scissor](vk::CommandBuffer cmdbuf) { cmdbuf.SetScissor(0, scissor); }); | ||||
|         return; | ||||
|     } | ||||
|     u32 up_scale = 1; | ||||
|     u32 down_shift = 0; | ||||
|     if (texture_cache.IsRescaling()) { | ||||
|   | ||||
| @@ -19,7 +19,7 @@ VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat | ||||
|                                               VkSampleCountFlagBits samples) { | ||||
|     using MaxwellToVK::SurfaceFormat; | ||||
|     return { | ||||
|         .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT, | ||||
|         .flags = {}, | ||||
|         .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, | ||||
|         .samples = samples, | ||||
|         .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, | ||||
|   | ||||
| @@ -10,19 +10,23 @@ | ||||
| #include "video_core/texture_cache/image_info.h" | ||||
| #include "video_core/texture_cache/image_view_base.h" | ||||
| #include "video_core/texture_cache/render_targets.h" | ||||
| #include "video_core/texture_cache/samples_helper.h" | ||||
|  | ||||
| namespace VideoCommon { | ||||
|  | ||||
| std::string Name(const ImageBase& image) { | ||||
|     const GPUVAddr gpu_addr = image.gpu_addr; | ||||
|     const ImageInfo& info = image.info; | ||||
|     const u32 width = info.size.width; | ||||
|     const u32 height = info.size.height; | ||||
|     u32 width = info.size.width; | ||||
|     u32 height = info.size.height; | ||||
|     const u32 depth = info.size.depth; | ||||
|     const u32 num_layers = image.info.resources.layers; | ||||
|     const u32 num_levels = image.info.resources.levels; | ||||
|     std::string resource; | ||||
|     if (image.info.num_samples > 1) { | ||||
|         const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(image.info.num_samples); | ||||
|         width >>= samples_x; | ||||
|         height >>= samples_y; | ||||
|         resource += fmt::format(":{}xMSAA", image.info.num_samples); | ||||
|     } | ||||
|     if (num_layers > 1) { | ||||
|   | ||||
| @@ -24,7 +24,7 @@ namespace VideoCommon { | ||||
|         return {2, 2}; | ||||
|     } | ||||
|     ASSERT_MSG(false, "Invalid number of samples={}", num_samples); | ||||
|     return {1, 1}; | ||||
|     return {0, 0}; | ||||
| } | ||||
|  | ||||
| [[nodiscard]] inline int NumSamples(Tegra::Texture::MsaaMode msaa_mode) { | ||||
|   | ||||
| @@ -68,7 +68,6 @@ struct LevelInfo { | ||||
|     Extent2D tile_size; | ||||
|     u32 bpp_log2; | ||||
|     u32 tile_width_spacing; | ||||
|     u32 num_levels; | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] constexpr u32 AdjustTileSize(u32 shift, u32 unit_factor, u32 dimension) { | ||||
| @@ -119,11 +118,11 @@ template <u32 GOB_EXTENT> | ||||
| } | ||||
|  | ||||
| [[nodiscard]] constexpr Extent3D AdjustMipBlockSize(Extent3D num_tiles, Extent3D block_size, | ||||
|                                                     u32 level, u32 num_levels) { | ||||
|                                                     u32 level) { | ||||
|     return { | ||||
|         .width = AdjustMipBlockSize<GOB_SIZE_X>(num_tiles.width, block_size.width, level), | ||||
|         .height = AdjustMipBlockSize<GOB_SIZE_Y>(num_tiles.height, block_size.height, level), | ||||
|         .depth = level == 0 && num_levels == 1 | ||||
|         .depth = level == 0 | ||||
|                      ? block_size.depth | ||||
|                      : AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level), | ||||
|     }; | ||||
| @@ -167,6 +166,13 @@ template <u32 GOB_EXTENT> | ||||
| } | ||||
|  | ||||
| [[nodiscard]] constexpr Extent3D TileShift(const LevelInfo& info, u32 level) { | ||||
|     if (level == 0) { | ||||
|         return Extent3D{ | ||||
|             .width = info.block.width, | ||||
|             .height = info.block.height, | ||||
|             .depth = info.block.depth, | ||||
|         }; | ||||
|     } | ||||
|     const Extent3D blocks = NumLevelBlocks(info, level); | ||||
|     return Extent3D{ | ||||
|         .width = AdjustTileSize(info.block.width, GOB_SIZE_X, blocks.width), | ||||
| @@ -251,7 +257,7 @@ template <u32 GOB_EXTENT> | ||||
| } | ||||
|  | ||||
| [[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block, | ||||
|                                                 u32 tile_width_spacing, u32 num_levels) { | ||||
|                                                 u32 tile_width_spacing) { | ||||
|     const u32 bytes_per_block = BytesPerBlock(format); | ||||
|     return { | ||||
|         .size = | ||||
| @@ -264,18 +270,16 @@ template <u32 GOB_EXTENT> | ||||
|         .tile_size = DefaultBlockSize(format), | ||||
|         .bpp_log2 = BytesPerBlockLog2(bytes_per_block), | ||||
|         .tile_width_spacing = tile_width_spacing, | ||||
|         .num_levels = num_levels, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| [[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) { | ||||
|     return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing, | ||||
|                          info.resources.levels); | ||||
|     return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block, | ||||
|                                                  u32 tile_width_spacing, u32 level) { | ||||
|     const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing, level); | ||||
|     const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing); | ||||
|     u32 offset = 0; | ||||
|     for (u32 current_level = 0; current_level < level; ++current_level) { | ||||
|         offset += CalculateLevelSize(info, current_level); | ||||
| @@ -462,7 +466,7 @@ template <u32 GOB_EXTENT> | ||||
|     }; | ||||
|     const u32 bpp_log2 = BytesPerBlockLog2(info.format); | ||||
|     const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing); | ||||
|     const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0, info.resources.levels); | ||||
|     const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0); | ||||
|     return Extent3D{ | ||||
|         .width = Common::AlignUpLog2(num_tiles.width, alignment), | ||||
|         .height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height), | ||||
| @@ -529,8 +533,7 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr | ||||
|     UNIMPLEMENTED_IF(copy.image_extent != level_size); | ||||
|  | ||||
|     const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); | ||||
|     const Extent3D block = | ||||
|         AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); | ||||
|     const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level); | ||||
|  | ||||
|     size_t host_offset = copy.buffer_offset; | ||||
|  | ||||
| @@ -695,7 +698,7 @@ u32 CalculateLevelStrideAlignment(const ImageInfo& info, u32 level) { | ||||
|     const Extent2D tile_size = DefaultBlockSize(info.format); | ||||
|     const Extent3D level_size = AdjustMipSize(info.size, level); | ||||
|     const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); | ||||
|     const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level, info.resources.levels); | ||||
|     const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level); | ||||
|     const u32 bpp_log2 = BytesPerBlockLog2(info.format); | ||||
|     return StrideAlignment(num_tiles, block, bpp_log2, info.tile_width_spacing); | ||||
| } | ||||
| @@ -884,8 +887,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory | ||||
|             .image_extent = level_size, | ||||
|         }; | ||||
|         const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); | ||||
|         const Extent3D block = | ||||
|             AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); | ||||
|         const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level); | ||||
|         const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2); | ||||
|         size_t guest_layer_offset = 0; | ||||
|  | ||||
| @@ -1039,7 +1041,7 @@ Extent3D MipBlockSize(const ImageInfo& info, u32 level) { | ||||
|     const Extent2D tile_size = DefaultBlockSize(info.format); | ||||
|     const Extent3D level_size = AdjustMipSize(info.size, level); | ||||
|     const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); | ||||
|     return AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); | ||||
|     return AdjustMipBlockSize(num_tiles, level_info.block, level); | ||||
| } | ||||
|  | ||||
| boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const ImageInfo& info) { | ||||
| @@ -1061,8 +1063,7 @@ boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const I | ||||
|     for (s32 level = 0; level < num_levels; ++level) { | ||||
|         const Extent3D level_size = AdjustMipSize(size, level); | ||||
|         const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); | ||||
|         const Extent3D block = | ||||
|             AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); | ||||
|         const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level); | ||||
|         params[level] = SwizzleParameters{ | ||||
|             .num_tiles = num_tiles, | ||||
|             .block = block, | ||||
| @@ -1291,11 +1292,11 @@ u32 MapSizeBytes(const ImageBase& image) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0, 1}, 0) == | ||||
| static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0}, 0) == | ||||
|               0x7f8000); | ||||
| static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0, 1}, 0) == 0x4000); | ||||
| static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x40000); | ||||
|  | ||||
| static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0, 1}, 0) == 0x4000); | ||||
| static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0}, 0) == 0x40000); | ||||
|  | ||||
| static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) == | ||||
|               0x2afc00); | ||||
|   | ||||
| @@ -227,14 +227,14 @@ add_executable(yuzu | ||||
|     yuzu.rc | ||||
| ) | ||||
|  | ||||
| if (WIN32 AND YUZU_CRASH_DUMPS) | ||||
| if (YUZU_CRASH_DUMPS) | ||||
|     target_sources(yuzu PRIVATE | ||||
|         mini_dump.cpp | ||||
|         mini_dump.h | ||||
|         breakpad.cpp | ||||
|         breakpad.h | ||||
|     ) | ||||
|  | ||||
|     target_link_libraries(yuzu PRIVATE ${DBGHELP_LIBRARY}) | ||||
|     target_compile_definitions(yuzu PRIVATE -DYUZU_DBGHELP) | ||||
|     target_link_libraries(yuzu PRIVATE libbreakpad_client) | ||||
|     target_compile_definitions(yuzu PRIVATE YUZU_CRASH_DUMPS) | ||||
| endif() | ||||
|  | ||||
| if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | ||||
|   | ||||
							
								
								
									
										77
									
								
								src/yuzu/breakpad.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								src/yuzu/breakpad.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <ranges> | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #include <client/windows/handler/exception_handler.h> | ||||
| #elif defined(__linux__) | ||||
| #include <client/linux/handler/exception_handler.h> | ||||
| #else | ||||
| #error Minidump creation not supported on this platform | ||||
| #endif | ||||
|  | ||||
| #include "common/fs/fs_paths.h" | ||||
| #include "common/fs/path_util.h" | ||||
| #include "yuzu/breakpad.h" | ||||
|  | ||||
| namespace Breakpad { | ||||
|  | ||||
| static void PruneDumpDirectory(const std::filesystem::path& dump_path) { | ||||
|     // Code in this function should be exception-safe. | ||||
|     struct Entry { | ||||
|         std::filesystem::path path; | ||||
|         std::filesystem::file_time_type last_write_time; | ||||
|     }; | ||||
|     std::vector<Entry> existing_dumps; | ||||
|  | ||||
|     // Get existing entries. | ||||
|     std::error_code ec; | ||||
|     std::filesystem::directory_iterator dir(dump_path, ec); | ||||
|     for (auto& entry : dir) { | ||||
|         if (entry.is_regular_file()) { | ||||
|             existing_dumps.push_back(Entry{ | ||||
|                 .path = entry.path(), | ||||
|                 .last_write_time = entry.last_write_time(ec), | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Sort descending by creation date. | ||||
|     std::ranges::stable_sort(existing_dumps, [](const auto& a, const auto& b) { | ||||
|         return a.last_write_time > b.last_write_time; | ||||
|     }); | ||||
|  | ||||
|     // Delete older dumps. | ||||
|     for (size_t i = 5; i < existing_dumps.size(); i++) { | ||||
|         std::filesystem::remove(existing_dumps[i].path, ec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #if defined(__linux__) | ||||
| [[noreturn]] bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, | ||||
|                                bool succeeded) { | ||||
|     // Prevent time- and space-consuming core dumps from being generated, as we have | ||||
|     // already generated a minidump and a core file will not be useful anyway. | ||||
|     _exit(1); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void InstallCrashHandler() { | ||||
|     // Write crash dumps to profile directory. | ||||
|     const auto dump_path = GetYuzuPath(Common::FS::YuzuPath::CrashDumpsDir); | ||||
|     PruneDumpDirectory(dump_path); | ||||
|  | ||||
| #if defined(_WIN32) | ||||
|     // TODO: If we switch to MinGW builds for Windows, this needs to be wrapped in a C API. | ||||
|     static google_breakpad::ExceptionHandler eh{dump_path, nullptr, nullptr, nullptr, | ||||
|                                                 google_breakpad::ExceptionHandler::HANDLER_ALL}; | ||||
| #elif defined(__linux__) | ||||
|     static google_breakpad::MinidumpDescriptor descriptor{dump_path}; | ||||
|     static google_breakpad::ExceptionHandler eh{descriptor, nullptr, DumpCallback, | ||||
|                                                 nullptr,    true,    -1}; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| } // namespace Breakpad | ||||
							
								
								
									
										10
									
								
								src/yuzu/breakpad.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								src/yuzu/breakpad.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| namespace Breakpad { | ||||
|  | ||||
| void InstallCrashHandler(); | ||||
|  | ||||
| } | ||||
| @@ -27,16 +27,6 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent) | ||||
|  | ||||
|     connect(ui->toggle_gdbstub, &QCheckBox::toggled, | ||||
|             [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); }); | ||||
|  | ||||
|     connect(ui->create_crash_dumps, &QCheckBox::stateChanged, [&](int) { | ||||
|         if (crash_dump_warning_shown) { | ||||
|             return; | ||||
|         } | ||||
|         QMessageBox::warning(this, tr("Restart Required"), | ||||
|                              tr("yuzu is required to restart in order to apply this setting."), | ||||
|                              QMessageBox::Ok, QMessageBox::Ok); | ||||
|         crash_dump_warning_shown = true; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| ConfigureDebug::~ConfigureDebug() = default; | ||||
| @@ -91,13 +81,6 @@ void ConfigureDebug::SetConfiguration() { | ||||
|     ui->disable_web_applet->setEnabled(false); | ||||
|     ui->disable_web_applet->setText(tr("Web applet not compiled")); | ||||
| #endif | ||||
|  | ||||
| #ifdef YUZU_DBGHELP | ||||
|     ui->create_crash_dumps->setChecked(Settings::values.create_crash_dumps.GetValue()); | ||||
| #else | ||||
|     ui->create_crash_dumps->setEnabled(false); | ||||
|     ui->create_crash_dumps->setText(tr("MiniDump creation not compiled")); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void ConfigureDebug::ApplyConfiguration() { | ||||
| @@ -109,7 +92,6 @@ void ConfigureDebug::ApplyConfiguration() { | ||||
|     Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked(); | ||||
|     Settings::values.reporting_services = ui->reporting_services->isChecked(); | ||||
|     Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked(); | ||||
|     Settings::values.create_crash_dumps = ui->create_crash_dumps->isChecked(); | ||||
|     Settings::values.quest_flag = ui->quest_flag->isChecked(); | ||||
|     Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); | ||||
|     Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); | ||||
|   | ||||
| @@ -481,13 +481,6 @@ | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="4" column="0"> | ||||
|           <widget class="QCheckBox" name="create_crash_dumps"> | ||||
|            <property name="text"> | ||||
|             <string>Create Minidump After Crash</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item row="3" column="0"> | ||||
|           <widget class="QCheckBox" name="dump_audio_commands"> | ||||
|            <property name="toolTip"> | ||||
|   | ||||
| @@ -157,8 +157,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | ||||
| #include "yuzu/util/clickable_label.h" | ||||
| #include "yuzu/vk_device_info.h" | ||||
|  | ||||
| #ifdef YUZU_DBGHELP | ||||
| #include "yuzu/mini_dump.h" | ||||
| #ifdef YUZU_CRASH_DUMPS | ||||
| #include "yuzu/breakpad.h" | ||||
| #endif | ||||
|  | ||||
| using namespace Common::Literals; | ||||
| @@ -5146,22 +5146,15 @@ int main(int argc, char* argv[]) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| #ifdef YUZU_DBGHELP | ||||
|     PROCESS_INFORMATION pi; | ||||
|     if (!is_child && Settings::values.create_crash_dumps.GetValue() && | ||||
|         MiniDump::SpawnDebuggee(argv[0], pi)) { | ||||
|         // Delete the config object so that it doesn't save when the program exits | ||||
|         config.reset(nullptr); | ||||
|         MiniDump::DebugDebuggee(pi); | ||||
|         return 0; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     if (StartupChecks(argv[0], &has_broken_vulkan, | ||||
|                       Settings::values.perform_vulkan_check.GetValue())) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| #ifdef YUZU_CRASH_DUMPS | ||||
|     Breakpad::InstallCrashHandler(); | ||||
| #endif | ||||
|  | ||||
|     Common::DetachedTasks detached_tasks; | ||||
|     MicroProfileOnThreadCreate("Frontend"); | ||||
|     SCOPE_EXIT({ MicroProfileShutdown(); }); | ||||
|   | ||||
| @@ -33,10 +33,6 @@ | ||||
|             "description": "Compile tests", | ||||
|             "dependencies": [ "catch2" ] | ||||
|         }, | ||||
|         "dbghelp": { | ||||
|             "description": "Compile Windows crash dump (Minidump) support", | ||||
|             "dependencies": [ "dbghelp" ] | ||||
|         }, | ||||
|         "web-service": { | ||||
|             "description": "Enable web services (telemetry, etc.)", | ||||
|             "dependencies": [ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user