mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-06-06 01:13:45 -04:00
Compare commits
14 commits
6f4ca0d457
...
acb23d7dea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acb23d7dea | ||
|
|
82bd9242b7 | ||
|
|
54bb22f364 | ||
|
|
4996f8913c | ||
|
|
c7afb87a0c | ||
|
|
a8047d3b12 | ||
|
|
cc8451f764 | ||
|
|
27189f39d2 | ||
|
|
683e6249c3 | ||
|
|
eaece15dbd | ||
|
|
8e5419209c | ||
|
|
8fac95dcc0 | ||
|
|
706a3d0764 | ||
|
|
3d19743d95 |
99 changed files with 5622 additions and 1336 deletions
214
.patch/openssl-cmake/0001-cpmutil-compat.patch
Normal file
214
.patch/openssl-cmake/0001-cpmutil-compat.patch
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
From ec4c1fdf526cb9ad045abf59b29ee495bbf5023a Mon Sep 17 00:00:00 2001
|
||||||
|
From: crueter <crueter@eden-emu.dev>
|
||||||
|
Date: Sat, 30 May 2026 20:56:35 -0400
|
||||||
|
Subject: [PATCH] cpmutil compat
|
||||||
|
|
||||||
|
---
|
||||||
|
CMakeLists.txt | 31 ++++++++-----------
|
||||||
|
cmake/FetchOpenSSL.cmake | 64 ----------------------------------------
|
||||||
|
cmake/GetCPM.cmake | 5 ----
|
||||||
|
3 files changed, 13 insertions(+), 87 deletions(-)
|
||||||
|
delete mode 100644 cmake/FetchOpenSSL.cmake
|
||||||
|
delete mode 100644 cmake/GetCPM.cmake
|
||||||
|
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 5420ecc..9ffd5a0 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -19,9 +19,7 @@ include(FetchContent)
|
||||||
|
include(ProcessorCount)
|
||||||
|
include(cmake/ConfigureOpenSSL.cmake)
|
||||||
|
include(cmake/DetectTargetPlatform.cmake)
|
||||||
|
-include(cmake/FetchOpenSSL.cmake)
|
||||||
|
include(cmake/FindVcvarsall.cmake)
|
||||||
|
-include(cmake/GetCPM.cmake)
|
||||||
|
|
||||||
|
# Custom options
|
||||||
|
option(OPENSSL_BUILD_VERBOSE "Enable verbose output from build" OFF)
|
||||||
|
@@ -47,9 +45,6 @@ if("${OPENSSL_TARGET_PLATFORM}" STREQUAL "")
|
||||||
|
detect_target_platform(OPENSSL_TARGET_PLATFORM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
-# Fetch OpenSSL source
|
||||||
|
-fetch_openssl()
|
||||||
|
-
|
||||||
|
# Apply patches
|
||||||
|
foreach(patch IN LISTS OPENSSL_PATCH)
|
||||||
|
if(EXISTS "${patch}" AND NOT IS_DIRECTORY "${patch}")
|
||||||
|
@@ -59,13 +54,13 @@ foreach(patch IN LISTS OPENSSL_PATCH)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND git init
|
||||||
|
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
|
||||||
|
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND git apply ${patch}
|
||||||
|
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
|
||||||
|
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
@@ -161,8 +156,8 @@ list(PREPEND OPENSSL_CONFIGURE_OPTIONS ${OPENSSL_TARGET_PLATFORM})
|
||||||
|
# Configure OpenSSL
|
||||||
|
configure_openssl(
|
||||||
|
COMMAND ${VCVARSALL_COMMAND}
|
||||||
|
- FILE ${openssl_SOURCE_DIR}/Configure
|
||||||
|
- BUILD_DIR ${openssl_BINARY_DIR}
|
||||||
|
+ FILE ${OpenSSL_SOURCE_DIR}/Configure
|
||||||
|
+ BUILD_DIR ${OpenSSL_BINARY_DIR}
|
||||||
|
OPTIONS ${OPENSSL_CONFIGURE_OPTIONS}
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -203,8 +198,8 @@ endif()
|
||||||
|
# Parse Makefile
|
||||||
|
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_LIBS" OPENSSL_STATIC_LIBS)
|
||||||
|
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_SHLIBS" OPENSSL_SHARED_LIBS)
|
||||||
|
-list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${openssl_BINARY_DIR}/")
|
||||||
|
-list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${openssl_BINARY_DIR}/")
|
||||||
|
+list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
|
||||||
|
+list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
|
||||||
|
|
||||||
|
foreach(LIBRARY IN LISTS OPENSSL_STATIC_LIBS)
|
||||||
|
if(LIBRARY MATCHES "crypto")
|
||||||
|
@@ -239,14 +234,14 @@ endif()
|
||||||
|
|
||||||
|
# Provide same targets and variables as FindOpenSSL module
|
||||||
|
set(OPENSSL_FOUND ON CACHE BOOL "Override FindOpenSSL variables" FORCE)
|
||||||
|
-set(OPENSSL_INCLUDE_DIR ${openssl_SOURCE_DIR}/include ${openssl_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
+set(OPENSSL_INCLUDE_DIR ${OpenSSL_SOURCE_DIR}/include ${OpenSSL_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_CRYPTO_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_SSL_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_SSL_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
set(OPENSSL_VERSION ${OPENSSL_CONFIGURED_VERSION} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
-set(OPENSSL_APPLINK_SOURCE ${openssl_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
+set(OPENSSL_APPLINK_SOURCE ${OpenSSL_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||||
|
|
||||||
|
add_library(OpenSSL::Crypto ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
|
||||||
|
add_library(OpenSSL::SSL ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
|
||||||
|
@@ -308,8 +303,8 @@ if(ANDROID)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB_RECURSE OPENSSL_SOURCES
|
||||||
|
- ${openssl_SOURCE_DIR}/*.[ch]
|
||||||
|
- ${openssl_SOURCE_DIR}/*.[ch].in
|
||||||
|
+ ${OpenSSL_SOURCE_DIR}/*.[ch]
|
||||||
|
+ ${OpenSSL_SOURCE_DIR}/*.[ch].in
|
||||||
|
)
|
||||||
|
|
||||||
|
set(OPENSSL_BUILD_OUTPUT
|
||||||
|
@@ -322,7 +317,7 @@ add_custom_command(
|
||||||
|
OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||||
|
COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||||
|
DEPENDS ${OPENSSL_SOURCES}
|
||||||
|
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
|
||||||
|
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -341,7 +336,7 @@ if(OPENSSL_TEST AND NOT CMAKE_CROSSCOMPILING)
|
||||||
|
add_test(
|
||||||
|
NAME openssl-test
|
||||||
|
COMMAND ${OPENSSL_BUILD_TOOL} test VERBOSE_FAILURE=yes HARNESS_JOBS=${NUMBER_OF_THREADS}
|
||||||
|
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
|
||||||
|
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
@@ -356,7 +351,7 @@ if(OPENSSL_INSTALL)
|
||||||
|
install(CODE
|
||||||
|
"execute_process(
|
||||||
|
COMMAND ${OPENSSL_INSTALL_COMMAND}
|
||||||
|
- WORKING_DIRECTORY \"${openssl_BINARY_DIR}\"
|
||||||
|
+ WORKING_DIRECTORY \"${OpenSSL_BINARY_DIR}\"
|
||||||
|
)"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
diff --git a/cmake/FetchOpenSSL.cmake b/cmake/FetchOpenSSL.cmake
|
||||||
|
deleted file mode 100644
|
||||||
|
index a43505d..0000000
|
||||||
|
--- a/cmake/FetchOpenSSL.cmake
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,64 +0,0 @@
|
||||||
|
-function(fetch_openssl)
|
||||||
|
- if(EXISTS "${OPENSSL_SOURCE}" AND IS_DIRECTORY "${OPENSSL_SOURCE}")
|
||||||
|
- # Fetch the local OpenSSL source
|
||||||
|
- if(NOT IS_ABSOLUTE "${OPENSSL_SOURCE}")
|
||||||
|
- string(PREPEND OPENSSL_SOURCE ${CMAKE_SOURCE_DIR}/)
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- string(REPLACE "\\" "/" openssl-source_SOURCE_DIR "${OPENSSL_SOURCE}")
|
||||||
|
- set(openssl-source_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-source-build)
|
||||||
|
- else()
|
||||||
|
- set(CPM_OPTIONS
|
||||||
|
- NAME openssl-source
|
||||||
|
- DOWNLOAD_ONLY ON
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- if(NOT OPENSSL_CONFIGURE_VERBOSE)
|
||||||
|
- list(APPEND CPM_OPTIONS QUIET)
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- if("${OPENSSL_SOURCE}" MATCHES "^http")
|
||||||
|
- # Download OpenSSL source from the internet
|
||||||
|
- list(APPEND CPM_OPTIONS URL ${OPENSSL_SOURCE})
|
||||||
|
- else()
|
||||||
|
- # Download OpenSSL source from the official website
|
||||||
|
- if("${OPENSSL_TARGET_VERSION}" STREQUAL "")
|
||||||
|
- set(OPENSSL_TARGET_VERSION ${PROJECT_VERSION})
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- if(OPENSSL_TARGET_VERSION VERSION_EQUAL PROJECT_VERSION)
|
||||||
|
- list(APPEND CPM_OPTIONS URL_HASH SHA256=aaf51a1fe064384f811daeaeb4ec4dce7340ec8bd893027eee676af31e83a04f)
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- if(OPENSSL_TARGET_VERSION MATCHES "^1\.1\.1[a-w]$")
|
||||||
|
- string(REPLACE "." "_" OPENSSL_TAGGED_VERSION ${OPENSSL_TARGET_VERSION})
|
||||||
|
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/OpenSSL_${OPENSSL_TAGGED_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
|
||||||
|
- else()
|
||||||
|
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_TARGET_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
|
||||||
|
- endif()
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- CPMAddPackage(${CPM_OPTIONS})
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- # Clean build directory if source directory has changed
|
||||||
|
- if(DEFINED CACHE{openssl-source_SOURCE_DIR_OLD} AND NOT openssl-source_SOURCE_DIR STREQUAL openssl-source_SOURCE_DIR_OLD)
|
||||||
|
- set(openssl-source_SOURCE_DIR_OLD ${openssl-source_SOURCE_DIR} CACHE INTERNAL "Previously fetched OpenSSL source")
|
||||||
|
-
|
||||||
|
- if(IS_DIRECTORY ${openssl-source_BINARY_DIR})
|
||||||
|
- file(REMOVE_RECURSE ${openssl-source_BINARY_DIR})
|
||||||
|
- file(MAKE_DIRECTORY ${openssl-source_BINARY_DIR})
|
||||||
|
- endif()
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
- # Override the FindOpenSSL module
|
||||||
|
- FetchContent_Declare(
|
||||||
|
- OpenSSL
|
||||||
|
- SOURCE_DIR ${openssl-source_SOURCE_DIR}
|
||||||
|
- BINARY_DIR ${openssl-source_BINARY_DIR}
|
||||||
|
- OVERRIDE_FIND_PACKAGE
|
||||||
|
- )
|
||||||
|
- FetchContent_MakeAvailable(OpenSSL)
|
||||||
|
-
|
||||||
|
- return(PROPAGATE openssl_SOURCE_DIR openssl_BINARY_DIR)
|
||||||
|
-endfunction()
|
||||||
|
diff --git a/cmake/GetCPM.cmake b/cmake/GetCPM.cmake
|
||||||
|
deleted file mode 100644
|
||||||
|
index bfc50f5..0000000
|
||||||
|
--- a/cmake/GetCPM.cmake
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,5 +0,0 @@
|
||||||
|
-file(
|
||||||
|
- DOWNLOAD https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
|
||||||
|
- ${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake
|
||||||
|
-)
|
||||||
|
-include(${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake)
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
54
.patch/openssl-cmake/0002-use-ccache.patch
Normal file
54
.patch/openssl-cmake/0002-use-ccache.patch
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
From d46675fbb61eb6d51e478023ce4075e545ad4cfd Mon Sep 17 00:00:00 2001
|
||||||
|
From: crueter <crueter@eden-emu.dev>
|
||||||
|
Date: Sat, 30 May 2026 21:11:55 -0400
|
||||||
|
Subject: [PATCH] use ccache
|
||||||
|
|
||||||
|
---
|
||||||
|
CMakeLists.txt | 1 -
|
||||||
|
cmake/ConfigureOpenSSL.cmake | 12 +++---------
|
||||||
|
2 files changed, 3 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 9ffd5a0..9ff14c8 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -28,7 +28,6 @@ option(OPENSSL_ENABLE_PARALLEL "Build and test in parallel if possible" ON)
|
||||||
|
option(OPENSSL_INSTALL "Install OpenSSL components to the <prefix> directory" OFF)
|
||||||
|
option(OPENSSL_INSTALL_CERT "Install cert.pem to the <openssldir> directory" OFF)
|
||||||
|
option(OPENSSL_TEST "Enable testing and build OpenSSL self tests" OFF)
|
||||||
|
-option(OPENSSL_USE_CCACHE "Use ccache if available" ON)
|
||||||
|
|
||||||
|
if("${OPENSSL_BUILD_TARGET}" STREQUAL "")
|
||||||
|
# Makefile target for build
|
||||||
|
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
|
||||||
|
index 211c18b..3d8cbed 100644
|
||||||
|
--- a/cmake/ConfigureOpenSSL.cmake
|
||||||
|
+++ b/cmake/ConfigureOpenSSL.cmake
|
||||||
|
@@ -69,15 +69,9 @@ function(apply_ccache FILE)
|
||||||
|
message(FATAL_ERROR "Couldn't find Makefile")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
- if(OPENSSL_USE_CCACHE)
|
||||||
|
- find_program(CCACHE ccache)
|
||||||
|
-
|
||||||
|
- if(NOT CCACHE)
|
||||||
|
- return()
|
||||||
|
- endif()
|
||||||
|
-
|
||||||
|
+ if(USE_CCACHE)
|
||||||
|
file(READ ${FILE} MAKEFILE)
|
||||||
|
- string(REPLACE "\nCC=" "\nCC=ccache " MAKEFILE "${MAKEFILE}")
|
||||||
|
+ string(REPLACE "\nCC=" "\nCC=${CCACHE_BINARY} " MAKEFILE "${MAKEFILE}")
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
string(REPLACE "/Zi /Fdossl_static.pdb " "" MAKEFILE "${MAKEFILE}")
|
||||||
|
@@ -171,4 +165,4 @@ function(configure_openssl)
|
||||||
|
string(REPLACE "/W3" "/W0" MAKEFILE "${MAKEFILE}")
|
||||||
|
file(WRITE ${OPENSSL_MAKEFILE} "${MAKEFILE}")
|
||||||
|
endif()
|
||||||
|
-endfunction()
|
||||||
|
\ No newline at end of file
|
||||||
|
+endfunction()
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
28
.patch/openssl-cmake/0003-use-cmake-compiler-flags.patch
Normal file
28
.patch/openssl-cmake/0003-use-cmake-compiler-flags.patch
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
From 4a3cc92a7abad403529ed1cb4255ca63d9252de4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: crueter <crueter@eden-emu.dev>
|
||||||
|
Date: Sat, 30 May 2026 21:48:42 -0400
|
||||||
|
Subject: [PATCH 2/2] use cmake compiler flags
|
||||||
|
|
||||||
|
---
|
||||||
|
cmake/ConfigureOpenSSL.cmake | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
|
||||||
|
index 3d8cbed..3012e05 100644
|
||||||
|
--- a/cmake/ConfigureOpenSSL.cmake
|
||||||
|
+++ b/cmake/ConfigureOpenSSL.cmake
|
||||||
|
@@ -135,7 +135,10 @@ function(configure_openssl)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
- COMMAND ${CONFIGURE_COMMAND}
|
||||||
|
+ COMMAND ${CMAKE_COMMAND} -E env
|
||||||
|
+ "CFLAGS=${CMAKE_C_FLAGS}"
|
||||||
|
+ "CXXFLAGS=${CMAKE_CXX_FLAGS}"
|
||||||
|
+ ${CONFIGURE_COMMAND}
|
||||||
|
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
|
||||||
|
${VERBOSE_OPTION}
|
||||||
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
39
.patch/openssl-cmake/0004-use-shell-wrapper.patch
Normal file
39
.patch/openssl-cmake/0004-use-shell-wrapper.patch
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
--- a/CMakeLists.txt 2026-06-01 23:53:16.498043856 -0400
|
||||||
|
+++ b/CMakeLists.txt 2026-06-01 23:53:23.910543615 -0400
|
||||||
|
@@ -312,13 +312,29 @@
|
||||||
|
${OPENSSL_SHARED_CRYPTO_LIBRARY}
|
||||||
|
${OPENSSL_SHARED_SSL_LIBRARY}
|
||||||
|
)
|
||||||
|
-add_custom_command(
|
||||||
|
- OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||||
|
- COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||||
|
- DEPENDS ${OPENSSL_SOURCES}
|
||||||
|
- WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||||
|
- VERBATIM
|
||||||
|
-)
|
||||||
|
+if (WIN32)
|
||||||
|
+ add_custom_command(
|
||||||
|
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||||
|
+ COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||||
|
+ DEPENDS ${OPENSSL_SOURCES}
|
||||||
|
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||||
|
+ VERBATIM)
|
||||||
|
+else()
|
||||||
|
+ set(_openssl_build_script "${CMAKE_CURRENT_BINARY_DIR}/BuildOpenSSL.cmake")
|
||||||
|
+ file(WRITE ${_openssl_build_script}
|
||||||
|
+ "execute_process(\n"
|
||||||
|
+ " COMMAND ${OPENSSL_BUILD_COMMAND}\n"
|
||||||
|
+ " WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}\n"
|
||||||
|
+ " RESULT_VARIABLE _r)\n"
|
||||||
|
+ "if(_r)\n"
|
||||||
|
+ " message(FATAL_ERROR \"OpenSSL build failed: \${_r}\")\n"
|
||||||
|
+ "endif()\n")
|
||||||
|
+ add_custom_command(
|
||||||
|
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||||
|
+ COMMAND ${CMAKE_COMMAND} -P ${_openssl_build_script}
|
||||||
|
+ DEPENDS ${OPENSSL_SOURCES}
|
||||||
|
+ VERBATIM)
|
||||||
|
+endif()
|
||||||
|
|
||||||
|
if(PROJECT_IS_TOP_LEVEL)
|
||||||
|
add_custom_target(openssl-build ALL DEPENDS ${OPENSSL_BUILD_OUTPUT})
|
||||||
3665
.patch/openssl/0001-add-bundled-cert.patch
Normal file
3665
.patch/openssl/0001-add-bundled-cert.patch
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -306,7 +306,7 @@ if (YUZU_ROOM)
|
||||||
add_compile_definitions(YUZU_ROOM)
|
add_compile_definitions(YUZU_ROOM)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ((ANDROID OR APPLE OR UNIX) AND (NOT PLATFORM_LINUX OR ANDROID) AND NOT WIN32)
|
if (UNIX AND NOT (PLATFORM_LINUX OR WIN32))
|
||||||
if(CXX_APPLE OR CXX_CLANG)
|
if(CXX_APPLE OR CXX_CLANG)
|
||||||
# libc++ has stop_token and jthread as experimental
|
# libc++ has stop_token and jthread as experimental
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||||
|
|
@ -383,13 +383,20 @@ find_package(RenderDoc MODULE)
|
||||||
# openssl funniness
|
# openssl funniness
|
||||||
if (YUZU_USE_BUNDLED_OPENSSL)
|
if (YUZU_USE_BUNDLED_OPENSSL)
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
AddJsonPackage(openssl-ci)
|
||||||
|
else()
|
||||||
AddJsonPackage(openssl)
|
AddJsonPackage(openssl)
|
||||||
|
set(OPENSSL_BUILD_VERBOSE ON)
|
||||||
|
set(OPENSSL_CONFIGURE_VERBOSE ON)
|
||||||
|
|
||||||
if (OpenSSL_ADDED)
|
if (OpenSSL_ADDED)
|
||||||
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
AddJsonPackage(openssl-cmake)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(OpenSSL 3 REQUIRED)
|
if (OpenSSL_ADDED)
|
||||||
|
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
||||||
|
endif()
|
||||||
|
|
||||||
message(STATUS "Fetching needed dependencies with CPM")
|
message(STATUS "Fetching needed dependencies with CPM")
|
||||||
|
|
||||||
|
|
@ -517,6 +524,8 @@ elseif (WIN32)
|
||||||
# PSAPI is the Process Status API
|
# PSAPI is the Process Status API
|
||||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
|
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
|
||||||
endif()
|
endif()
|
||||||
|
elseif (PLATFORM_MANAGARM)
|
||||||
|
set(PLATFORM_LIBRARIES iconv intl)
|
||||||
elseif (PLATFORM_HAIKU)
|
elseif (PLATFORM_HAIKU)
|
||||||
# Haiku is so special :)
|
# Haiku is so special :)
|
||||||
set(PLATFORM_LIBRARIES bsd /boot/system/lib/libnetwork.so)
|
set(PLATFORM_LIBRARIES bsd /boot/system/lib/libnetwork.so)
|
||||||
|
|
|
||||||
30
cpmfile.json
30
cpmfile.json
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"openssl": {
|
"openssl-ci": {
|
||||||
"ci": true,
|
"ci": true,
|
||||||
"package": "OpenSSL",
|
"package": "OpenSSL",
|
||||||
"name": "openssl",
|
"name": "openssl",
|
||||||
|
|
@ -7,6 +7,34 @@
|
||||||
"version": "3.6.0-1cb0d36b39",
|
"version": "3.6.0-1cb0d36b39",
|
||||||
"min_version": "3"
|
"min_version": "3"
|
||||||
},
|
},
|
||||||
|
"openssl-cmake": {
|
||||||
|
"repo": "jimmy-park/openssl-cmake",
|
||||||
|
"hash": "2cc185c924fd70e7d886257ca0caa42b3b8f7f712f2052b4f94dde74759e27022de76178460e18c9bdfc57c366583999e198fbb6052d4e7d91c099d15a0ca63e",
|
||||||
|
"git_version": "3.6.2",
|
||||||
|
"tag": "%VERSION%",
|
||||||
|
"bundled": true,
|
||||||
|
"options": [
|
||||||
|
"OPENSSL_CONFIGURE_OPTIONS threads"
|
||||||
|
],
|
||||||
|
"patches": [
|
||||||
|
"0001-cpmutil-compat.patch",
|
||||||
|
"0002-use-ccache.patch",
|
||||||
|
"0003-use-cmake-compiler-flags.patch",
|
||||||
|
"0004-use-shell-wrapper.patch"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"openssl": {
|
||||||
|
"repo": "openssl/openssl",
|
||||||
|
"package": "OpenSSL",
|
||||||
|
"min_version": "3",
|
||||||
|
"version": "3",
|
||||||
|
"hash": "29002ce50cb95a4f4f1d0e9d3f684401fbd4eac34203dc2eef3b6334af5d44aa46bf788b63a6f5c139c383eafb7269ae87a58a9a3ad5912903b9773e545ccc0a",
|
||||||
|
"git_version": "3.6.2",
|
||||||
|
"tag": "openssl-%VERSION%",
|
||||||
|
"patches": [
|
||||||
|
"0001-add-bundled-cert.patch"
|
||||||
|
]
|
||||||
|
},
|
||||||
"boost": {
|
"boost": {
|
||||||
"package": "Boost",
|
"package": "Boost",
|
||||||
"repo": "boostorg/boost",
|
"repo": "boostorg/boost",
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
|
|
@ -101,7 +100,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
private var romSwapGeneration = 0
|
private var romSwapGeneration = 0
|
||||||
private var hasEmulationSession = processHasEmulationSession
|
private var hasEmulationSession = processHasEmulationSession
|
||||||
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
|
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
|
||||||
private val pictureInPictureFailureActions: MutableSet<String> = mutableSetOf()
|
|
||||||
|
|
||||||
private fun onRomSwapStopTimeout() {
|
private fun onRomSwapStopTimeout() {
|
||||||
if (!isWaitingForRomSwapStop) {
|
if (!isWaitingForRomSwapStop) {
|
||||||
|
|
@ -270,18 +268,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUserLeaveHint() {
|
override fun onUserLeaveHint() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||||
!isPictureInPictureSupported() ||
|
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
|
||||||
!BooleanSetting.PICTURE_IN_PICTURE.getBoolean() ||
|
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||||
isInPictureInPictureMode
|
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||||
) {
|
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
|
||||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
|
||||||
runPictureInPictureAction("enter picture-in-picture mode") {
|
|
||||||
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -661,29 +653,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
return this.apply { setActions(pictureInPictureActions) }
|
return this.apply { setActions(pictureInPictureActions) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isPictureInPictureSupported() =
|
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
|
||||||
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
|
|
||||||
|
|
||||||
private fun runPictureInPictureAction(actionName: String, action: () -> Unit) {
|
|
||||||
try {
|
|
||||||
action()
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
if (pictureInPictureFailureActions.add(actionName)) {
|
|
||||||
Log.warning("[PiP] Failed to $actionName: ${e.message}")
|
|
||||||
}
|
|
||||||
} catch (e: UnsupportedOperationException) {
|
|
||||||
if (pictureInPictureFailureActions.add(actionName)) {
|
|
||||||
Log.warning("[PiP] Failed to $actionName: ${e.message}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildPictureInPictureParams() {
|
fun buildPictureInPictureParams() {
|
||||||
if (!isPictureInPictureSupported()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
|
@ -693,9 +663,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||||
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
|
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
runPictureInPictureAction("set picture-in-picture params") {
|
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun displayMultiplayerDialog() {
|
fun displayMultiplayerDialog() {
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ namespace {
|
||||||
}
|
}
|
||||||
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
|
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
|
||||||
u64 cntfrq_el0 = 0;
|
u64 cntfrq_el0 = 0;
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
std::string_view board{""};
|
std::string_view board{""};
|
||||||
char buffer[PROP_VALUE_MAX];
|
char buffer[PROP_VALUE_MAX];
|
||||||
int len{__system_property_get("ro.product.board", buffer)};
|
int len{__system_property_get("ro.product.board", buffer)};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
@ -30,7 +33,7 @@ std::string NativeErrorToString(int e) {
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
char err_str[255];
|
char err_str[255];
|
||||||
#if defined(ANDROID) || \
|
#if defined(__ANDROID__) || \
|
||||||
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
|
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
|
||||||
// Thread safe (GNU-specific)
|
// Thread safe (GNU-specific)
|
||||||
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/fs/file.h"
|
#include "common/fs/file.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
|
@ -259,7 +259,7 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
||||||
} else {
|
} else {
|
||||||
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
||||||
}
|
}
|
||||||
#elif ANDROID
|
#elif __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
|
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
|
||||||
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read);
|
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read);
|
||||||
|
|
@ -396,7 +396,7 @@ u64 IOFile::GetSize() const {
|
||||||
// Flush any unwritten buffered data into the file prior to retrieving the file size.
|
// Flush any unwritten buffered data into the file prior to retrieving the file size.
|
||||||
std::fflush(file);
|
std::fflush(file);
|
||||||
|
|
||||||
#if ANDROID
|
#ifdef __ANDROID__
|
||||||
u64 file_size = 0;
|
u64 file_size = 0;
|
||||||
if (Android::IsContentUri(file_path)) {
|
if (Android::IsContentUri(file_path)) {
|
||||||
file_size = Android::GetSize(file_path);
|
file_size = Android::GetSize(file_path);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "common/fs/file.h"
|
#include "common/fs/file.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
|
@ -532,7 +532,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
|
||||||
|
|
||||||
bool Exists(const fs::path& path) {
|
bool Exists(const fs::path& path) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
return Android::Exists(path);
|
return Android::Exists(path);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -545,7 +545,7 @@ bool Exists(const fs::path& path) {
|
||||||
|
|
||||||
bool IsFile(const fs::path& path) {
|
bool IsFile(const fs::path& path) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
return !Android::IsDirectory(path);
|
return !Android::IsDirectory(path);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -558,7 +558,7 @@ bool IsFile(const fs::path& path) {
|
||||||
|
|
||||||
bool IsDir(const fs::path& path) {
|
bool IsDir(const fs::path& path) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
return Android::IsDirectory(path);
|
return Android::IsDirectory(path);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -611,7 +611,7 @@ fs::file_type GetEntryType(const fs::path& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetSize(const fs::path& path) {
|
u64 GetSize(const fs::path& path) {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
return Android::GetSize(path);
|
return Android::GetSize(path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/fs/fs_paths.h"
|
#include "common/fs/fs_paths.h"
|
||||||
|
|
@ -126,7 +126,7 @@ public:
|
||||||
LEGACY_PATH(Yuzu, YUZU)
|
LEGACY_PATH(Yuzu, YUZU)
|
||||||
LEGACY_PATH(Suyu, SUYU)
|
LEGACY_PATH(Suyu, SUYU)
|
||||||
#undef LEGACY_PATH
|
#undef LEGACY_PATH
|
||||||
#elif ANDROID
|
#elif __ANDROID__
|
||||||
ASSERT(!eden_path.empty());
|
ASSERT(!eden_path.empty());
|
||||||
eden_path_cache = eden_path / CACHE_DIR;
|
eden_path_cache = eden_path / CACHE_DIR;
|
||||||
eden_path_config = eden_path / CONFIG_DIR;
|
eden_path_config = eden_path / CONFIG_DIR;
|
||||||
|
|
@ -447,11 +447,11 @@ std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) {
|
||||||
|
|
||||||
std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
|
std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
|
||||||
std::string path(path_);
|
std::string path(path_);
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
#endif // ANDROID
|
#endif // __ANDROID__
|
||||||
|
|
||||||
char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\';
|
char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\';
|
||||||
char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/';
|
char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/';
|
||||||
|
|
@ -482,7 +482,7 @@ std::string GetParentPath(std::string_view path) {
|
||||||
return std::string(path);
|
return std::string(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (path[0] != '/') {
|
if (path[0] != '/') {
|
||||||
std::string path_string{path};
|
std::string path_string{path};
|
||||||
return FS::Android::GetParentDirectory(path_string);
|
return FS::Android::GetParentDirectory(path_string);
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ struct DebuggerBackend final : public Backend {
|
||||||
void Flush() noexcept override {}
|
void Flush() noexcept override {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
/// @brief Backend that writes to the Android logcat
|
/// @brief Backend that writes to the Android logcat
|
||||||
struct LogcatBackend : public Backend {
|
struct LogcatBackend : public Backend {
|
||||||
explicit LogcatBackend() noexcept = default;
|
explicit LogcatBackend() noexcept = default;
|
||||||
|
|
@ -359,7 +359,7 @@ struct Impl {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
lambda(static_cast<Backend&>(debugger_backend));
|
lambda(static_cast<Backend&>(debugger_backend));
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
lambda(static_cast<Backend&>(lc_backend));
|
lambda(static_cast<Backend&>(lc_backend));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +372,7 @@ struct Impl {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DebuggerBackend debugger_backend{};
|
DebuggerBackend debugger_backend{};
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
LogcatBackend lc_backend{};
|
LogcatBackend lc_backend{};
|
||||||
#endif
|
#endif
|
||||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
0,
|
0,
|
||||||
#else
|
#else
|
||||||
25,
|
25,
|
||||||
|
|
@ -417,7 +417,7 @@ struct Values {
|
||||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||||
|
|
||||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
GpuAccuracy::Low,
|
GpuAccuracy::Low,
|
||||||
#else
|
#else
|
||||||
GpuAccuracy::Medium,
|
GpuAccuracy::Medium,
|
||||||
|
|
@ -447,7 +447,7 @@ struct Values {
|
||||||
"nvdec_emulation", Category::RendererAdvanced};
|
"nvdec_emulation", Category::RendererAdvanced};
|
||||||
|
|
||||||
SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
|
SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
AnisotropyMode::Default,
|
AnisotropyMode::Default,
|
||||||
#else
|
#else
|
||||||
AnisotropyMode::Automatic,
|
AnisotropyMode::Automatic,
|
||||||
|
|
@ -500,7 +500,7 @@ struct Values {
|
||||||
Category::RendererAdvanced};
|
Category::RendererAdvanced};
|
||||||
|
|
||||||
SwitchableSetting<bool> use_reactive_flushing{linkage,
|
SwitchableSetting<bool> use_reactive_flushing{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
false,
|
false,
|
||||||
#else
|
#else
|
||||||
true,
|
true,
|
||||||
|
|
@ -519,7 +519,7 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
SwitchableSetting<bool> use_optimized_vertex_buffers{linkage,
|
SwitchableSetting<bool> use_optimized_vertex_buffers{linkage,
|
||||||
false,
|
false,
|
||||||
"use_optimized_vertex_buffers",
|
"use_optimized_vertex_buffers",
|
||||||
|
|
@ -553,7 +553,7 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
SwitchableSetting<bool> async_presentation{linkage,
|
SwitchableSetting<bool> async_presentation{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
false,
|
false,
|
||||||
#else
|
#else
|
||||||
false,
|
false,
|
||||||
|
|
@ -599,7 +599,7 @@ struct Values {
|
||||||
Category::RendererHacks};
|
Category::RendererHacks};
|
||||||
|
|
||||||
SwitchableSetting<ExtendedDynamicState> dyna_state{linkage,
|
SwitchableSetting<ExtendedDynamicState> dyna_state{linkage,
|
||||||
#if defined(ANDROID)
|
#if defined(__ANDROID__)
|
||||||
ExtendedDynamicState::Disabled,
|
ExtendedDynamicState::Disabled,
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
ExtendedDynamicState::Disabled,
|
ExtendedDynamicState::Disabled,
|
||||||
|
|
@ -618,7 +618,7 @@ struct Values {
|
||||||
Specialization::Scalar};
|
Specialization::Scalar};
|
||||||
|
|
||||||
SwitchableSetting<bool> vertex_input_dynamic_state{linkage,
|
SwitchableSetting<bool> vertex_input_dynamic_state{linkage,
|
||||||
#if defined (ANDROID)
|
#ifdef __ANDROID__
|
||||||
false,
|
false,
|
||||||
#else
|
#else
|
||||||
true,
|
true,
|
||||||
|
|
@ -634,7 +634,7 @@ struct Values {
|
||||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||||
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
// Debug override for automatic BCn patching detection
|
// Debug override for automatic BCn patching detection
|
||||||
Setting<bool> patch_old_qcom_drivers{linkage, false, "patch_old_qcom_drivers",
|
Setting<bool> patch_old_qcom_drivers{linkage, false, "patch_old_qcom_drivers",
|
||||||
Category::RendererDebug};
|
Category::RendererDebug};
|
||||||
|
|
@ -679,7 +679,7 @@ struct Values {
|
||||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||||
|
|
||||||
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
ConsoleMode::Handheld,
|
ConsoleMode::Handheld,
|
||||||
#else
|
#else
|
||||||
ConsoleMode::Docked,
|
ConsoleMode::Docked,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include <common/fs/fs_android.h>
|
#include <common/fs/fs_android.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
|
||||||
if (full_path.empty())
|
if (full_path.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (full_path[0] != '/') {
|
if (full_path[0] != '/') {
|
||||||
*_pPath = Common::FS::Android::GetParentDirectory(full_path);
|
*_pPath = Common::FS::Android::GetParentDirectory(full_path);
|
||||||
*_pFilename = Common::FS::Android::GetFilename(full_path);
|
*_pFilename = Common::FS::Android::GetFilename(full_path);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2012 PPSSPP Project
|
// SPDX-FileCopyrightText: 2012 PPSSPP Project
|
||||||
|
|
@ -10,12 +10,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#endif
|
|
||||||
#include <bit>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <bit>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
|
||||||
|
|
@ -1200,7 +1200,7 @@ else()
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type>
|
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type>
|
||||||
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>)
|
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>)
|
||||||
# pre-clang19 will spam with "OH DID YOU MEAN THIS?" otherwise...
|
# pre-clang19 will spam with "OH DID YOU MEAN THIS?" otherwise...
|
||||||
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19)
|
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
|
||||||
target_compile_options(core PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>)
|
target_compile_options(core PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
#if BOOST_VERSION > 108400 && (!defined(_WINDOWS) && !defined(ANDROID)) || defined(YUZU_BOOST_v1)
|
#if BOOST_VERSION > 108400 && (!defined(_WINDOWS) && !defined(__ANDROID__)) || defined(YUZU_BOOST_v1)
|
||||||
#define USE_BOOST_v1
|
#define USE_BOOST_v1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
#define stat _stat64
|
#define stat _stat64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -288,7 +288,7 @@ RealVfsFile::~RealVfsFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RealVfsFile::GetName() const {
|
std::string RealVfsFile::GetName() const {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (path[0] != '/') {
|
if (path[0] != '/') {
|
||||||
return FS::Android::GetFilename(path);
|
return FS::Android::GetFilename(path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -12,8 +15,8 @@ Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t pro
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
|
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
|
||||||
UNIMPLEMENTED();
|
LOG_WARNING(Service, "(STUBBED) called");
|
||||||
R_THROW(ResultNotImplemented);
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {
|
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ RenderdocAPI::RenderdocAPI() {
|
||||||
#elif defined(__HAIKU__)
|
#elif defined(__HAIKU__)
|
||||||
// no rtld on haiku
|
// no rtld on haiku
|
||||||
#else
|
#else
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so";
|
static constexpr const char RENDERDOC_LIB[] = "libVkLayer_GLES_RenderDoc.so";
|
||||||
#else
|
#else
|
||||||
static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so";
|
static constexpr const char RENDERDOC_LIB[] = "librenderdoc.so";
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ ArgCallback DevirtualizeItanium(mcl::class_type<decltype(mfp)>* this_) {
|
||||||
|
|
||||||
template<auto mfp>
|
template<auto mfp>
|
||||||
ArgCallback Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
|
ArgCallback Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
|
||||||
#if defined(__APPLE__) || defined(linux) || defined(__linux) || defined(__linux__)
|
#if defined(__APPLE__) || defined(__linux__)
|
||||||
return DevirtualizeItanium<mfp>(this_);
|
return DevirtualizeItanium<mfp>(this_);
|
||||||
#elif defined(__MINGW64__)
|
#elif defined(__MINGW64__)
|
||||||
return DevirtualizeItanium<mfp>(this_);
|
return DevirtualizeItanium<mfp>(this_);
|
||||||
|
|
|
||||||
|
|
@ -1009,7 +1009,7 @@ std::string Config::AdjustOutputString(const std::string& string) {
|
||||||
|
|
||||||
// Windows requires that two forward slashes are used at the start of a path for unmapped
|
// Windows requires that two forward slashes are used at the start of a path for unmapped
|
||||||
// network drives so we have to watch for that here
|
// network drives so we have to watch for that here
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
if (string.substr(0, 2) == "//") {
|
if (string.substr(0, 2) == "//") {
|
||||||
boost::replace_all(adjusted_string, "//", "/");
|
boost::replace_all(adjusted_string, "//", "/");
|
||||||
adjusted_string.insert(0, "/");
|
adjusted_string.insert(0, "/");
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef DATA_MANAGER_H
|
#pragma once
|
||||||
#define DATA_MANAGER_H
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -21,5 +20,3 @@ std::string ReadableBytesSize(u64 size) noexcept;
|
||||||
u64 DataDirSize(DataDir dir);
|
u64 DataDirSize(DataDir dir);
|
||||||
|
|
||||||
}; // namespace FrontendCommon::DataManager
|
}; // namespace FrontendCommon::DataManager
|
||||||
|
|
||||||
#endif // DATA_MANAGER_H
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "frontend_common/content_manager.h"
|
#include "frontend_common/content_manager.h"
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <common/android/id_cache.h>
|
#include <common/android/id_cache.h>
|
||||||
#include <common/android/android_common.h>
|
#include <common/android/android_common.h>
|
||||||
|
|
@ -25,7 +25,7 @@ FirmwareManager::InstallKeys(std::string location, std::string extension) {
|
||||||
|
|
||||||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
JNIEnv *env = Common::Android::GetEnvForThread();
|
JNIEnv *env = Common::Android::GetEnvForThread();
|
||||||
|
|
||||||
jstring jsrc = Common::Android::ToJString(env, location);
|
jstring jsrc = Common::Android::ToJString(env, location);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef FIRMWARE_MANAGER_H
|
#pragma once
|
||||||
#define FIRMWARE_MANAGER_H
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
|
@ -107,5 +106,3 @@ inline std::pair<Service::Set::FirmwareVersionFormat, Result> GetFirmwareVersion
|
||||||
|
|
||||||
// TODO(crueter): GET AS STRING
|
// TODO(crueter): GET AS STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/fs_types.h"
|
#include "common/fs/fs_types.h"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace FrontendCommon {
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ void EmulatedController::LoadDevices() {
|
||||||
if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) {
|
if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) {
|
||||||
camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
|
camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
|
||||||
nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
|
nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
|
ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
|
||||||
#else
|
#else
|
||||||
android_params = Common::ParamPackage{"engine:android,port:100"};
|
android_params = Common::ParamPackage{"engine:android,port:100"};
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
#include "input_common/drivers/sdl_driver.h"
|
#include "input_common/drivers/sdl_driver.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "input_common/drivers/android.h"
|
#include "input_common/drivers/android.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ struct InputSubsystem::Impl {
|
||||||
RegisterEngine("cemuhookudp", udp_client);
|
RegisterEngine("cemuhookudp", udp_client);
|
||||||
RegisterEngine("tas", tas_input);
|
RegisterEngine("tas", tas_input);
|
||||||
RegisterEngine("camera", camera);
|
RegisterEngine("camera", camera);
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
RegisterEngine("android", android);
|
RegisterEngine("android", android);
|
||||||
#endif
|
#endif
|
||||||
RegisterEngine("virtual_amiibo", virtual_amiibo);
|
RegisterEngine("virtual_amiibo", virtual_amiibo);
|
||||||
|
|
@ -119,7 +119,7 @@ struct InputSubsystem::Impl {
|
||||||
UnregisterEngine(udp_client);
|
UnregisterEngine(udp_client);
|
||||||
UnregisterEngine(tas_input);
|
UnregisterEngine(tas_input);
|
||||||
UnregisterEngine(camera);
|
UnregisterEngine(camera);
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
UnregisterEngine(android);
|
UnregisterEngine(android);
|
||||||
#endif
|
#endif
|
||||||
UnregisterEngine(virtual_amiibo);
|
UnregisterEngine(virtual_amiibo);
|
||||||
|
|
@ -138,13 +138,13 @@ struct InputSubsystem::Impl {
|
||||||
Common::ParamPackage{{"display", "Any"}, {"engine", "any"}},
|
Common::ParamPackage{{"display", "Any"}, {"engine", "any"}},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
auto keyboard_devices = keyboard->GetInputDevices();
|
auto keyboard_devices = keyboard->GetInputDevices();
|
||||||
devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end());
|
devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end());
|
||||||
auto mouse_devices = mouse->GetInputDevices();
|
auto mouse_devices = mouse->GetInputDevices();
|
||||||
devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
|
devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
auto android_devices = android->GetInputDevices();
|
auto android_devices = android->GetInputDevices();
|
||||||
devices.insert(devices.end(), android_devices.begin(), android_devices.end());
|
devices.insert(devices.end(), android_devices.begin(), android_devices.end());
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -176,7 +176,7 @@ struct InputSubsystem::Impl {
|
||||||
if (engine == mouse->GetEngineName()) {
|
if (engine == mouse->GetEngineName()) {
|
||||||
return mouse;
|
return mouse;
|
||||||
}
|
}
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (engine == android->GetEngineName()) {
|
if (engine == android->GetEngineName()) {
|
||||||
return android;
|
return android;
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ struct InputSubsystem::Impl {
|
||||||
if (engine == mouse->GetEngineName()) {
|
if (engine == mouse->GetEngineName()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (engine == android->GetEngineName()) {
|
if (engine == android->GetEngineName()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +294,7 @@ struct InputSubsystem::Impl {
|
||||||
void BeginConfiguration() {
|
void BeginConfiguration() {
|
||||||
keyboard->BeginConfiguration();
|
keyboard->BeginConfiguration();
|
||||||
mouse->BeginConfiguration();
|
mouse->BeginConfiguration();
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
android->BeginConfiguration();
|
android->BeginConfiguration();
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_LIBUSB
|
#ifdef ENABLE_LIBUSB
|
||||||
|
|
@ -310,7 +310,7 @@ struct InputSubsystem::Impl {
|
||||||
void EndConfiguration() {
|
void EndConfiguration() {
|
||||||
keyboard->EndConfiguration();
|
keyboard->EndConfiguration();
|
||||||
mouse->EndConfiguration();
|
mouse->EndConfiguration();
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
android->EndConfiguration();
|
android->EndConfiguration();
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_LIBUSB
|
#ifdef ENABLE_LIBUSB
|
||||||
|
|
@ -355,7 +355,7 @@ struct InputSubsystem::Impl {
|
||||||
std::shared_ptr<Joycons> joycon;
|
std::shared_ptr<Joycons> joycon;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
std::shared_ptr<Android> android;
|
std::shared_ptr<Android> android;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
@ -412,7 +412,7 @@ const Camera* InputSubsystem::GetCamera() const {
|
||||||
return impl->camera.get();
|
return impl->camera.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
Android* InputSubsystem::GetAndroid() {
|
Android* InputSubsystem::GetAndroid() {
|
||||||
return impl->android.get();
|
return impl->android.get();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ add_library(qt_common STATIC
|
||||||
abstract/frontend.h abstract/frontend.cpp
|
abstract/frontend.h abstract/frontend.cpp
|
||||||
abstract/progress.h abstract/progress.cpp
|
abstract/progress.h abstract/progress.cpp
|
||||||
|
|
||||||
|
game_list/model.h game_list/model.cpp
|
||||||
|
game_list/worker.h game_list/worker.cpp
|
||||||
|
game_list/game_list_p.h
|
||||||
|
|
||||||
qt_string_lookup.h
|
qt_string_lookup.h
|
||||||
qt_compat.h
|
qt_compat.h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef FRONTEND_H
|
#pragma once
|
||||||
#define FRONTEND_H
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
|
|
@ -114,4 +113,3 @@ const QString GetTextInput(const QString& title = QString(), const QString& capt
|
||||||
const QString& defaultText = QString());
|
const QString& defaultText = QString());
|
||||||
|
|
||||||
} // namespace QtCommon::Frontend
|
} // namespace QtCommon::Frontend
|
||||||
#endif // FRONTEND_H
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,13 @@
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QStandardItem>
|
#include <QStandardItem>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "frontend_common/play_time_manager.h"
|
#include "frontend_common/play_time_manager.h"
|
||||||
#include "qt_common/config/uisettings.h"
|
#include "qt_common/config/uisettings.h"
|
||||||
#include "yuzu/util/util.h"
|
#include "qt_common/qt_common.h"
|
||||||
|
|
||||||
enum class GameListItemType {
|
enum class GameListItemType {
|
||||||
Game = QStandardItem::UserType + 1,
|
Game = QStandardItem::UserType + 1,
|
||||||
|
|
@ -204,7 +203,7 @@ public:
|
||||||
setData(compatibility, CompatNumberRole);
|
setData(compatibility, CompatNumberRole);
|
||||||
setText(tr(status.text));
|
setText(tr(status.text));
|
||||||
setToolTip(tr(status.tooltip));
|
setToolTip(tr(status.tooltip));
|
||||||
setData(CreateCirclePixmapFromColor(status.color), Qt::DecorationRole);
|
setData(QtCommon::CreateCirclePixmapFromColor(status.color), Qt::DecorationRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
int type() const override {
|
int type() const override {
|
||||||
|
|
@ -237,7 +236,7 @@ public:
|
||||||
// representations of the data are always accurate and in the correct format.
|
// representations of the data are always accurate and in the correct format.
|
||||||
if (role == SizeRole) {
|
if (role == SizeRole) {
|
||||||
qulonglong size_bytes = value.toULongLong();
|
qulonglong size_bytes = value.toULongLong();
|
||||||
GameListItem::setData(ReadableByteSize(size_bytes), Qt::DisplayRole);
|
GameListItem::setData(QtCommon::ReadableByteSize(size_bytes), Qt::DisplayRole);
|
||||||
GameListItem::setData(value, SizeRole);
|
GameListItem::setData(value, SizeRole);
|
||||||
} else {
|
} else {
|
||||||
GameListItem::setData(value, role);
|
GameListItem::setData(value, role);
|
||||||
|
|
@ -398,49 +397,3 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameList;
|
|
||||||
class QHBoxLayout;
|
|
||||||
class QTreeView;
|
|
||||||
class QLabel;
|
|
||||||
class QLineEdit;
|
|
||||||
class QToolButton;
|
|
||||||
|
|
||||||
class GameListSearchField : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GameListSearchField(GameList* parent = nullptr);
|
|
||||||
|
|
||||||
QString filterText() const;
|
|
||||||
void setFilterResult(int visible_, int total_);
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
void setFocus();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void changeEvent(QEvent*) override;
|
|
||||||
void RetranslateUI();
|
|
||||||
|
|
||||||
class KeyReleaseEater : public QObject {
|
|
||||||
public:
|
|
||||||
explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GameList* gamelist = nullptr;
|
|
||||||
QString edit_filter_text_old;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// EventFilter in order to process systemkeys while editing the searchfield
|
|
||||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
|
||||||
};
|
|
||||||
int visible;
|
|
||||||
int total;
|
|
||||||
|
|
||||||
QHBoxLayout* layout_filter = nullptr;
|
|
||||||
QTreeView* tree_view = nullptr;
|
|
||||||
QLabel* label_filter = nullptr;
|
|
||||||
QLineEdit* edit_filter = nullptr;
|
|
||||||
QLabel* label_filter_result = nullptr;
|
|
||||||
QToolButton* button_filter_close = nullptr;
|
|
||||||
};
|
|
||||||
303
src/qt_common/game_list/model.cpp
Normal file
303
src/qt_common/game_list/model.cpp
Normal file
|
|
@ -0,0 +1,303 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QThreadPool>
|
||||||
|
|
||||||
|
#include "common/logging.h"
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "qt_common/config/uisettings.h"
|
||||||
|
#include "qt_common/qt_common.h"
|
||||||
|
#include "qt_common/util/game.h"
|
||||||
|
|
||||||
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
|
#include "qt_common/game_list/worker.h"
|
||||||
|
#include "qt_common/game_list/model.h"
|
||||||
|
|
||||||
|
GameListModel::GameListModel(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
|
||||||
|
FileSys::ManualContentProvider* provider_,
|
||||||
|
const PlayTime::PlayTimeManager& play_time_manager_,
|
||||||
|
Core::System& system_, QObject* parent)
|
||||||
|
: QStandardItemModel{parent}, vfs{std::move(vfs_)}, provider{provider_},
|
||||||
|
play_time_manager{play_time_manager_}, system{system_} {
|
||||||
|
watcher = new QFileSystemWatcher(this);
|
||||||
|
external_watcher = new QFileSystemWatcher(this);
|
||||||
|
|
||||||
|
connect(watcher, &QFileSystemWatcher::directoryChanged, this,
|
||||||
|
&GameListModel::RefreshGameDirectory);
|
||||||
|
connect(external_watcher, &QFileSystemWatcher::directoryChanged, this,
|
||||||
|
&GameListModel::RefreshExternalContent);
|
||||||
|
|
||||||
|
insertColumns(0, COLUMN_COUNT);
|
||||||
|
RetranslateUI();
|
||||||
|
|
||||||
|
setSortRole(GameListItemPath::SortRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameListModel::~GameListModel() = default;
|
||||||
|
|
||||||
|
void GameListModel::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
|
||||||
|
current_worker.reset();
|
||||||
|
removeRows(0, rowCount());
|
||||||
|
|
||||||
|
current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, compatibility_list,
|
||||||
|
play_time_manager, system);
|
||||||
|
|
||||||
|
connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameListModel::WorkerEvent,
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
|
QThreadPool::globalInstance()->start(current_worker.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::WorkerEvent() {
|
||||||
|
current_worker->ProcessEvents(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::AddDirEntry(GameListDir* entry_items) {
|
||||||
|
if (m_flat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
invisibleRootItem()->appendRow(entry_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent) {
|
||||||
|
if (m_flat) {
|
||||||
|
invisibleRootItem()->appendRow(entry_items);
|
||||||
|
} else {
|
||||||
|
parent->appendRow(entry_items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::DonePopulating(const QStringList& watch_list) {
|
||||||
|
emit ShowList(!IsEmpty());
|
||||||
|
|
||||||
|
if (!m_flat) {
|
||||||
|
invisibleRootItem()->appendRow(new GameListAddDir());
|
||||||
|
invisibleRootItem()->insertRow(0, new GameListFavorites());
|
||||||
|
|
||||||
|
for (const auto id : std::as_const(UISettings::values.favorited_ids)) {
|
||||||
|
AddFavorite(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit PopulatingCompleted(watch_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameListModel::IsEmpty() const {
|
||||||
|
for (int i = 0; i < rowCount(); i++) {
|
||||||
|
const QStandardItem* child = invisibleRootItem()->child(i);
|
||||||
|
const auto type = static_cast<GameListItemType>(child->type());
|
||||||
|
|
||||||
|
if (!child->hasChildren() &&
|
||||||
|
(type == GameListItemType::SdmcDir || type == GameListItemType::UserNandDir ||
|
||||||
|
type == GameListItemType::SysNandDir)) {
|
||||||
|
invisibleRootItem()->removeRow(child->row());
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !invisibleRootItem()->hasChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::ToggleFavorite(u64 program_id) {
|
||||||
|
if (!UISettings::values.favorited_ids.contains(program_id)) {
|
||||||
|
UISettings::values.favorited_ids.append(program_id);
|
||||||
|
AddFavorite(program_id);
|
||||||
|
} else {
|
||||||
|
UISettings::values.favorited_ids.removeOne(program_id);
|
||||||
|
RemoveFavorite(program_id);
|
||||||
|
}
|
||||||
|
emit SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::AddFavorite(u64 program_id) {
|
||||||
|
auto* favorites_row = item(0);
|
||||||
|
|
||||||
|
for (int i = 1; i < rowCount() - 1; i++) {
|
||||||
|
const auto* folder = item(i);
|
||||||
|
for (int j = 0; j < folder->rowCount(); j++) {
|
||||||
|
if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() ==
|
||||||
|
program_id) {
|
||||||
|
QList<QStandardItem*> list;
|
||||||
|
for (int k = 0; k < COLUMN_COUNT; k++) {
|
||||||
|
list.append(folder->child(j, k)->clone());
|
||||||
|
}
|
||||||
|
list[0]->setData(folder->child(j)->data(GameListItem::SortRole),
|
||||||
|
GameListItem::SortRole);
|
||||||
|
list[0]->setText(folder->child(j)->data(Qt::DisplayRole).toString());
|
||||||
|
|
||||||
|
favorites_row->appendRow(list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::RemoveFavorite(u64 program_id) {
|
||||||
|
auto* favorites_row = item(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < favorites_row->rowCount(); i++) {
|
||||||
|
const auto* game = favorites_row->child(i);
|
||||||
|
if (game->data(GameListItemPath::ProgramIdRole).toULongLong() == program_id) {
|
||||||
|
favorites_row->removeRow(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::LoadCompatibilityList() {
|
||||||
|
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
|
||||||
|
|
||||||
|
if (!compat_list.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
|
LOG_ERROR(Frontend, "Unable to open game compatibility list");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compat_list.size() == 0) {
|
||||||
|
LOG_WARNING(Frontend, "Game compatibility list is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray content = compat_list.readAll();
|
||||||
|
if (content.isEmpty()) {
|
||||||
|
LOG_ERROR(Frontend, "Unable to completely read game compatibility list");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QJsonDocument json = QJsonDocument::fromJson(content);
|
||||||
|
const QJsonArray arr = json.array();
|
||||||
|
|
||||||
|
for (const QJsonValue& value : arr) {
|
||||||
|
const QJsonObject game = value.toObject();
|
||||||
|
const QString compatibility_key = QStringLiteral("compatibility");
|
||||||
|
|
||||||
|
if (!game.contains(compatibility_key) || !game[compatibility_key].isDouble()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int compatibility = game[compatibility_key].toInt();
|
||||||
|
const QString directory = game[QStringLiteral("directory")].toString();
|
||||||
|
const QJsonArray ids = game[QStringLiteral("releases")].toArray();
|
||||||
|
|
||||||
|
for (const QJsonValue& id_ref : ids) {
|
||||||
|
const QJsonObject id_object = id_ref.toObject();
|
||||||
|
const QString id = id_object[QStringLiteral("id")].toString();
|
||||||
|
|
||||||
|
compatibility_list.emplace(id.toUpper().toStdString(),
|
||||||
|
std::make_pair(QString::number(compatibility), directory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::RefreshGameDirectory() {
|
||||||
|
ResetExternalWatcher();
|
||||||
|
|
||||||
|
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
|
||||||
|
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
||||||
|
QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
|
||||||
|
PopulateAsync(UISettings::values.game_dirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::RefreshExternalContent() {
|
||||||
|
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
|
||||||
|
LOG_INFO(Frontend, "External content directory changed. Clearing metadata cache.");
|
||||||
|
QtCommon::Game::ResetMetadata(false);
|
||||||
|
QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
|
||||||
|
PopulateAsync(UISettings::values.game_dirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::ResetExternalWatcher() {
|
||||||
|
auto watch_dirs = external_watcher->directories();
|
||||||
|
if (!watch_dirs.isEmpty()) {
|
||||||
|
external_watcher->removePaths(watch_dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::string& dir : Settings::values.external_content_dirs) {
|
||||||
|
external_watcher->addPath(QString::fromStdString(dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::OnUpdateThemedIcons() {
|
||||||
|
for (int i = 0; i < invisibleRootItem()->rowCount(); i++) {
|
||||||
|
QStandardItem* child = invisibleRootItem()->child(i);
|
||||||
|
|
||||||
|
const int icon_size = UISettings::values.folder_icon_size.GetValue();
|
||||||
|
|
||||||
|
switch (child->data(GameListItem::TypeRole).value<GameListItemType>()) {
|
||||||
|
case GameListItemType::SdmcDir:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("sd_card"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
|
case GameListItemType::UserNandDir:
|
||||||
|
case GameListItemType::SysNandDir:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("chip"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
|
case GameListItemType::CustomDir: {
|
||||||
|
const UISettings::GameDir& game_dir =
|
||||||
|
UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()];
|
||||||
|
const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path))
|
||||||
|
? QStringLiteral("folder")
|
||||||
|
: QStringLiteral("bad_folder");
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
|
||||||
|
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GameListItemType::AddDir:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("list-add"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
|
case GameListItemType::Favorites:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("star"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::RetranslateUI() {
|
||||||
|
setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
|
||||||
|
setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
|
||||||
|
setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
|
||||||
|
setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
|
||||||
|
setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
|
||||||
|
setHeaderData(COLUMN_PLAY_TIME, Qt::Horizontal, tr("Play time"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileSystemWatcher* GameListModel::GetWatcher() const {
|
||||||
|
return watcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CompatibilityList& GameListModel::GetCompatibilityList() const {
|
||||||
|
return compatibility_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::SetFlat(bool flat) {
|
||||||
|
m_flat = flat;
|
||||||
|
}
|
||||||
98
src/qt_common/game_list/model.h
Normal file
98
src/qt_common/game_list/model.h
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "frontend_common/play_time_manager.h"
|
||||||
|
#include "qt_common/config/uisettings.h"
|
||||||
|
#include "yuzu/compatibility_list.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GameListDir;
|
||||||
|
class GameListWorker;
|
||||||
|
class QStandardItem;
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
class ManualContentProvider;
|
||||||
|
class VfsFilesystem;
|
||||||
|
} // namespace FileSys
|
||||||
|
|
||||||
|
class GameListModel : public QStandardItemModel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column {
|
||||||
|
COLUMN_NAME,
|
||||||
|
COLUMN_FILE_TYPE,
|
||||||
|
COLUMN_SIZE,
|
||||||
|
COLUMN_PLAY_TIME,
|
||||||
|
COLUMN_ADD_ONS,
|
||||||
|
COLUMN_COMPATIBILITY,
|
||||||
|
COLUMN_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit GameListModel(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
|
||||||
|
FileSys::ManualContentProvider* provider_,
|
||||||
|
const PlayTime::PlayTimeManager& play_time_manager_,
|
||||||
|
Core::System& system_, QObject* parent = nullptr);
|
||||||
|
~GameListModel() override;
|
||||||
|
|
||||||
|
void AddDirEntry(GameListDir* entry_items);
|
||||||
|
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
|
||||||
|
void DonePopulating(const QStringList& watch_list);
|
||||||
|
|
||||||
|
void PopulateAsync(QVector<UISettings::GameDir>& game_dirs);
|
||||||
|
void WorkerEvent();
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
void ToggleFavorite(u64 program_id);
|
||||||
|
|
||||||
|
void RefreshGameDirectory();
|
||||||
|
void RefreshExternalContent();
|
||||||
|
void ResetExternalWatcher();
|
||||||
|
|
||||||
|
void LoadCompatibilityList();
|
||||||
|
|
||||||
|
void OnUpdateThemedIcons();
|
||||||
|
void RetranslateUI();
|
||||||
|
|
||||||
|
QFileSystemWatcher* GetWatcher() const;
|
||||||
|
|
||||||
|
const CompatibilityList& GetCompatibilityList() const;
|
||||||
|
|
||||||
|
void SetFlat(bool flat);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void ShowList(bool show);
|
||||||
|
void PopulatingCompleted(const QStringList& watch_list);
|
||||||
|
void SaveConfig();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class GameListWorker;
|
||||||
|
|
||||||
|
void AddFavorite(u64 program_id);
|
||||||
|
void RemoveFavorite(u64 program_id);
|
||||||
|
|
||||||
|
bool m_flat = false;
|
||||||
|
|
||||||
|
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
||||||
|
FileSys::ManualContentProvider* provider;
|
||||||
|
CompatibilityList compatibility_list;
|
||||||
|
const PlayTime::PlayTimeManager& play_time_manager;
|
||||||
|
Core::System& system;
|
||||||
|
|
||||||
|
std::unique_ptr<GameListWorker> current_worker;
|
||||||
|
QFileSystemWatcher* watcher = nullptr;
|
||||||
|
QFileSystemWatcher* external_watcher = nullptr;
|
||||||
|
};
|
||||||
|
|
@ -33,9 +33,10 @@
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
|
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/game/game_list.h"
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
#include "yuzu/game/game_list_p.h"
|
|
||||||
#include "yuzu/game/game_list_worker.h"
|
#include "qt_common/game_list/worker.h"
|
||||||
|
#include "qt_common/game_list/model.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
@ -250,9 +251,9 @@ GameListWorker::~GameListWorker() {
|
||||||
processing_completed.Wait();
|
processing_completed.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameListWorker::ProcessEvents(GameList* game_list) {
|
void GameListWorker::ProcessEvents(GameListModel* model) {
|
||||||
while (true) {
|
while (true) {
|
||||||
std::function<void(GameList*)> func;
|
std::function<void(GameListModel*)> func;
|
||||||
{
|
{
|
||||||
// Lock queue to protect concurrent modification.
|
// Lock queue to protect concurrent modification.
|
||||||
std::scoped_lock lk(lock);
|
std::scoped_lock lk(lock);
|
||||||
|
|
@ -268,7 +269,7 @@ void GameListWorker::ProcessEvents(GameList* game_list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the function.
|
// Run the function.
|
||||||
func(game_list);
|
func(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +336,7 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
||||||
|
|
||||||
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
|
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
|
||||||
program_id, compatibility_list, play_time_manager, patch);
|
program_id, compatibility_list, play_time_manager, patch);
|
||||||
RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
RecordEvent([=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,7 +418,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
||||||
id, compatibility_list, play_time_manager, patch);
|
id, compatibility_list, play_time_manager, patch);
|
||||||
|
|
||||||
RecordEvent(
|
RecordEvent(
|
||||||
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::vector<u8> icon;
|
std::vector<u8> icon;
|
||||||
|
|
@ -434,7 +435,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
|
||||||
program_id, compatibility_list, play_time_manager, patch);
|
program_id, compatibility_list, play_time_manager, patch);
|
||||||
|
|
||||||
RecordEvent(
|
RecordEvent(
|
||||||
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
|
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (is_dir) {
|
} else if (is_dir) {
|
||||||
|
|
@ -457,7 +458,7 @@ void GameListWorker::run() {
|
||||||
provider->ClearAllEntries();
|
provider->ClearAllEntries();
|
||||||
|
|
||||||
const auto DirEntryReady = [&](GameListDir* game_list_dir) {
|
const auto DirEntryReady = [&](GameListDir* game_list_dir) {
|
||||||
RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); });
|
RecordEvent([=](GameListModel* model) { model->AddDirEntry(game_list_dir); });
|
||||||
};
|
};
|
||||||
|
|
||||||
for (UISettings::GameDir& game_dir : game_dirs) {
|
for (UISettings::GameDir& game_dir : game_dirs) {
|
||||||
|
|
@ -491,6 +492,6 @@ void GameListWorker::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordEvent([this](GameList* game_list) { game_list->DonePopulating(watch_list); });
|
RecordEvent([this](GameListModel* model) { model->DonePopulating(watch_list); });
|
||||||
processing_completed.Set();
|
processing_completed.Set();
|
||||||
}
|
}
|
||||||
|
|
@ -26,8 +26,8 @@ namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameList;
|
|
||||||
class GameListDir;
|
class GameListDir;
|
||||||
|
class GameListModel;
|
||||||
class QStandardItem;
|
class QStandardItem;
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
@ -58,11 +58,11 @@ public:
|
||||||
/**
|
/**
|
||||||
* Synchronously processes any events queued by the worker.
|
* Synchronously processes any events queued by the worker.
|
||||||
*
|
*
|
||||||
* AddDirEntry is called on the game list for every discovered directory.
|
* AddDirEntry is called on the model for every discovered directory.
|
||||||
* AddEntry is called on the game list for every discovered program.
|
* AddEntry is called on the model for every discovered program.
|
||||||
* DonePopulating is called on the game list when processing completes.
|
* DonePopulating is called on the model when processing completes.
|
||||||
*/
|
*/
|
||||||
void ProcessEvents(GameList* game_list);
|
void ProcessEvents(GameListModel* model);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void DataAvailable();
|
void DataAvailable();
|
||||||
|
|
@ -92,7 +92,7 @@ private:
|
||||||
|
|
||||||
std::mutex lock;
|
std::mutex lock;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::deque<std::function<void(GameList*)>> queued_events;
|
std::deque<std::function<void(GameListModel*)>> queued_events;
|
||||||
std::atomic_bool stop_requested = false;
|
std::atomic_bool stop_requested = false;
|
||||||
Common::Event processing_completed;
|
Common::Event processing_completed;
|
||||||
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "common/memory_detect.h"
|
#include "common/memory_detect.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "frontend_common/data_manager.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "qt_common.h"
|
#include "qt_common.h"
|
||||||
|
|
@ -27,6 +28,7 @@
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <JlCompress.h>
|
#include <JlCompress.h>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
#if !defined(WIN32) && !defined(__APPLE__)
|
#if !defined(WIN32) && !defined(__APPLE__)
|
||||||
#include <qpa/qplatformnativeinterface.h>
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
|
@ -307,4 +309,19 @@ void SetupHID() {
|
||||||
system->HIDCore().ReloadInputDevices();
|
system->HIDCore().ReloadInputDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ReadableByteSize(qulonglong size) {
|
||||||
|
return QString::fromStdString(FrontendCommon::DataManager::ReadableBytesSize(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap CreateCirclePixmapFromColor(const QColor& color) {
|
||||||
|
QPixmap circle_pixmap(16, 16);
|
||||||
|
circle_pixmap.fill(Qt::transparent);
|
||||||
|
QPainter painter(&circle_pixmap);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
painter.setPen(color);
|
||||||
|
painter.setBrush(color);
|
||||||
|
painter.drawEllipse({circle_pixmap.width() / 2.0, circle_pixmap.height() / 2.0}, 7.0, 7.0);
|
||||||
|
return circle_pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QtCommon
|
} // namespace QtCommon
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_COMMON_H
|
#pragma once
|
||||||
#define QT_COMMON_H
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
@ -46,6 +45,19 @@ void SetupHID();
|
||||||
const QString tr(const char* str);
|
const QString tr(const char* str);
|
||||||
const QString tr(const std::string& str);
|
const QString tr(const std::string& str);
|
||||||
|
|
||||||
|
// TODO: Find a better place for these
|
||||||
|
|
||||||
|
/// Convert a size in bytes into a readable format (KiB, MiB, etc.)
|
||||||
|
[[nodiscard]] QString ReadableByteSize(qulonglong size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a circle pixmap from a specified color
|
||||||
|
* @param color The color the pixmap shall have
|
||||||
|
* @return QPixmap circle pixmap
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::filesystem::path GetEdenCommand();
|
std::filesystem::path GetEdenCommand();
|
||||||
} // namespace QtCommon
|
} // namespace QtCommon
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_APPLET_UTIL_H
|
#pragma once
|
||||||
#define QT_APPLET_UTIL_H
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
namespace QtCommon::Applets {}
|
namespace QtCommon::Applets {}
|
||||||
#endif // QT_APPLET_UTIL_H
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_CONTENT_UTIL_H
|
#pragma once
|
||||||
#define QT_CONTENT_UTIL_H
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
@ -63,4 +62,3 @@ void configureFilesystemProvider(const std::string& filepath);
|
||||||
// Profiles //
|
// Profiles //
|
||||||
void FixProfiles();
|
void FixProfiles();
|
||||||
} // namespace QtCommon::Content
|
} // namespace QtCommon::Content
|
||||||
#endif // QT_CONTENT_UTIL_H
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace QtCommon::FS {
|
namespace QtCommon::FS {
|
||||||
|
|
||||||
void LinkRyujinx(std::filesystem::path& from, std::filesystem::path& to);
|
void LinkRyujinx(std::filesystem::path& from, std::filesystem::path& to);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_GAME_UTIL_H
|
#pragma once
|
||||||
#define QT_GAME_UTIL_H
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
@ -78,5 +77,3 @@ void CreateHomeMenuShortcut(ShortcutTarget target);
|
||||||
[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image);
|
[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image);
|
||||||
|
|
||||||
} // namespace QtCommon::Game
|
} // namespace QtCommon::Game
|
||||||
|
|
||||||
#endif // QT_GAME_UTIL_H
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_META_H
|
#pragma once
|
||||||
#define QT_META_H
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
|
@ -12,4 +11,3 @@ namespace QtCommon::Meta {
|
||||||
void RegisterMetaTypes();
|
void RegisterMetaTypes();
|
||||||
|
|
||||||
} // namespace QtCommon::Meta
|
} // namespace QtCommon::Meta
|
||||||
#endif // QT_META_H
|
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,13 @@ QStringList GetModFolders(const QString& root, const QString& fallbackName) {
|
||||||
std_path = paths[0];
|
std_path = paths[0];
|
||||||
|
|
||||||
QString default_name;
|
QString default_name;
|
||||||
if (!fallbackName.isEmpty())
|
|
||||||
default_name = fallbackName;
|
// If this is an atmosphere-packed mod, the default name will end up as the game's title ID.
|
||||||
else if (!paths.empty())
|
// So in this case ignore it and use the zip name instead
|
||||||
|
if (!paths.empty() && std_path.string().find("atmosphere") == std::string::npos)
|
||||||
default_name = QString::fromStdString(std_path.filename().string());
|
default_name = QString::fromStdString(std_path.filename().string());
|
||||||
|
else if (!fallbackName.isEmpty())
|
||||||
|
default_name = fallbackName;
|
||||||
else
|
else
|
||||||
default_name = root.split(QLatin1Char('/')).last();
|
default_name = root.split(QLatin1Char('/')).last();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_PATH_UTIL_H
|
#pragma once
|
||||||
#define QT_PATH_UTIL_H
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
@ -10,5 +9,3 @@
|
||||||
namespace QtCommon::Path {
|
namespace QtCommon::Path {
|
||||||
bool OpenShaderCache(u64 program_id, QObject* parent);
|
bool OpenShaderCache(u64 program_id, QObject* parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QT_PATH_UTIL_H
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef QT_ROM_UTIL_H
|
#pragma once
|
||||||
#define QT_ROM_UTIL_H
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
|
|
||||||
namespace QtCommon::ROM {
|
namespace QtCommon::ROM {
|
||||||
|
bool RomFSRawCopy(size_t total_size, size_t& read_size, QtProgressCallback callback, const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, bool full);
|
||||||
bool RomFSRawCopy(size_t total_size, size_t& read_size, QtProgressCallback callback,
|
|
||||||
const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, bool full);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // QT_ROM_UTIL_H
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ Id EmitConvertU32U64(EmitContext& ctx, Id value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitConvertF16F32(EmitContext& ctx, Id value) {
|
Id EmitConvertF16F32(EmitContext& ctx, Id value) {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
return ctx.OpFConvert(ctx.F16[1], value);
|
return ctx.OpFConvert(ctx.F16[1], value);
|
||||||
#else
|
#else
|
||||||
const auto result = ctx.OpFConvert(ctx.F16[1], value);
|
const auto result = ctx.OpFConvert(ctx.F16[1], value);
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value&
|
||||||
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
||||||
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
|
||||||
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
if (Settings::values.fix_bloom_effects.GetValue()) {
|
if (Settings::values.fix_bloom_effects.GetValue()) {
|
||||||
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f));
|
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
#include "shader_recompiler/environment.h"
|
#include "shader_recompiler/environment.h"
|
||||||
#include "shader_recompiler/frontend/ir/basic_block.h"
|
#include "shader_recompiler/frontend/ir/basic_block.h"
|
||||||
#include "shader_recompiler/frontend/ir/breadth_first_search.h"
|
#include "shader_recompiler/frontend/ir/breadth_first_search.h"
|
||||||
|
|
@ -820,8 +821,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
||||||
const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)};
|
const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)};
|
||||||
IR::IREmitter ir{*texture_inst.block, insert_point};
|
IR::IREmitter ir{*texture_inst.block, insert_point};
|
||||||
const IR::U32 shift{ir.Imm32(size_shift)};
|
const IR::U32 shift{ir.Imm32(size_shift)};
|
||||||
inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift),
|
inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), ir.Imm32(count - 1)));
|
||||||
ir.Imm32(count - 1)));
|
|
||||||
} else {
|
} else {
|
||||||
inst->SetArg(0, IR::Value{});
|
inst->SetArg(0, IR::Value{});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -801,7 +801,7 @@ void BufferCache<P>::UpdateVertexBufferSlot(u32 index, const Binding& binding) {
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindHostVertexBuffers() {
|
void BufferCache<P>::BindHostVertexBuffers() {
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
const bool use_optimized_vertex_buffers = Settings::values.use_optimized_vertex_buffers.GetValue();
|
const bool use_optimized_vertex_buffers = Settings::values.use_optimized_vertex_buffers.GetValue();
|
||||||
#else
|
#else
|
||||||
constexpr bool use_optimized_vertex_buffers = true;
|
constexpr bool use_optimized_vertex_buffers = true;
|
||||||
|
|
@ -1893,23 +1893,17 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
|
||||||
return NULL_BINDING;
|
return NULL_BINDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// xbzk: New size logic. Fixes MCI.
|
|
||||||
// If ever the * comment below prove wrong, the 'if' block may be removed.
|
|
||||||
const auto size = [&]() {
|
const auto size = [&]() {
|
||||||
const bool is_nvn_cbuf = cbuf_index == 0;
|
const u32 memory_layout_size =
|
||||||
if (is_nvn_cbuf) {
|
static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
|
||||||
// * The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
|
const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
|
||||||
const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
|
const u32 packed_size = static_cast<u32>(next_qword);
|
||||||
const u32 upper_32 = static_cast<u32>(next_qword >> 32);
|
const bool next_qword_is_size = static_cast<u32>(next_qword >> 32) == 0 &&
|
||||||
// Hardware-based detection: GPU addresses have non-zero upper bits
|
packed_size != 0 &&
|
||||||
if (upper_32 == 0) {
|
packed_size <= memory_layout_size;
|
||||||
// This is a size field, not a GPU address
|
if (next_qword_is_size) {
|
||||||
return static_cast<u32>(next_qword); // Return lower_32
|
return packed_size;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Fall through: either not NVN cbuf (Doom Eternal & +), or NVN but ssbo_addr+8 is a GPU address (MCI)
|
|
||||||
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
|
|
||||||
// Cap at 8MB to prevent allocator overflow from misinterpreted addresses
|
|
||||||
return (std::min)(memory_layout_size, static_cast<u32>(8_MiB));
|
return (std::min)(memory_layout_size, static_cast<u32>(8_MiB));
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
#include "video_core/gpu_logging/freedreno_debug.h"
|
#include "video_core/gpu_logging/freedreno_debug.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
|
@ -49,4 +49,4 @@ std::string FreedrenoDebugger::GetBreadcrumbs() {
|
||||||
|
|
||||||
} // namespace GPU::Logging::Freedreno
|
} // namespace GPU::Logging::Freedreno
|
||||||
|
|
||||||
#endif // ANDROID
|
#endif // __ANDROID__
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -29,4 +29,4 @@ private:
|
||||||
|
|
||||||
} // namespace GPU::Logging::Freedreno
|
} // namespace GPU::Logging::Freedreno
|
||||||
|
|
||||||
#endif // ANDROID
|
#endif // __ANDROID__
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace {
|
||||||
constexpr AVPixelFormat PreferredGpuFormat = AV_PIX_FMT_NV12;
|
constexpr AVPixelFormat PreferredGpuFormat = AV_PIX_FMT_NV12;
|
||||||
constexpr AVPixelFormat PreferredCpuFormat = AV_PIX_FMT_YUV420P;
|
constexpr AVPixelFormat PreferredCpuFormat = AV_PIX_FMT_YUV420P;
|
||||||
constexpr std::array PreferredGpuDecoders = {
|
constexpr std::array PreferredGpuDecoders = {
|
||||||
#if defined (_WIN32)
|
#if defined(_WIN32)
|
||||||
AV_HWDEVICE_TYPE_CUDA,
|
AV_HWDEVICE_TYPE_CUDA,
|
||||||
AV_HWDEVICE_TYPE_D3D11VA,
|
AV_HWDEVICE_TYPE_D3D11VA,
|
||||||
AV_HWDEVICE_TYPE_DXVA2,
|
AV_HWDEVICE_TYPE_DXVA2,
|
||||||
|
|
@ -39,7 +39,7 @@ constexpr std::array PreferredGpuDecoders = {
|
||||||
AV_HWDEVICE_TYPE_DRM,
|
AV_HWDEVICE_TYPE_DRM,
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
|
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
|
||||||
#elif defined(ANDROID)
|
#elif defined(__ANDROID__)
|
||||||
AV_HWDEVICE_TYPE_MEDIACODEC,
|
AV_HWDEVICE_TYPE_MEDIACODEC,
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
AV_HWDEVICE_TYPE_CUDA,
|
AV_HWDEVICE_TYPE_CUDA,
|
||||||
|
|
|
||||||
|
|
@ -436,7 +436,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, barrier);
|
0, barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, barrier);
|
0, barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,10 +171,10 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
|
||||||
.imageOffset{.x = 0, .y = 0, .z = 0},
|
.imageOffset{.x = 0, .y = 0, .z = 0},
|
||||||
.imageExtent{extent},
|
.imageExtent{extent},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||||
read_barrier);
|
read_barrier);
|
||||||
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy);
|
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0,
|
||||||
memory_write_barrier, nullptr, image_write_barrier);
|
memory_write_barrier, nullptr, image_write_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -172,11 +171,7 @@ try
|
||||||
|
|
||||||
RendererVulkan::~RendererVulkan() {
|
RendererVulkan::~RendererVulkan() {
|
||||||
scheduler.RegisterOnSubmit([] {});
|
scheduler.RegisterOnSubmit([] {});
|
||||||
scheduler.Finish();
|
void(device.GetLogical().WaitIdle());
|
||||||
{
|
|
||||||
std::scoped_lock lock{scheduler.submit_mutex};
|
|
||||||
void(device.GetLogical().WaitIdle());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
|
void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
#include <mutex>
|
|
||||||
#include "video_core/framebuffer_config.h"
|
#include "video_core/framebuffer_config.h"
|
||||||
#include "video_core/present.h"
|
#include "video_core/present.h"
|
||||||
#include "video_core/renderer_vulkan/present/filters.h"
|
#include "video_core/renderer_vulkan/present/filters.h"
|
||||||
|
|
@ -32,10 +31,7 @@ BlitScreen::~BlitScreen() = default;
|
||||||
void BlitScreen::WaitIdle() {
|
void BlitScreen::WaitIdle() {
|
||||||
present_manager.WaitPresent();
|
present_manager.WaitPresent();
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
{
|
device.GetLogical().WaitIdle();
|
||||||
std::scoped_lock lock{scheduler.submit_mutex};
|
|
||||||
device.GetLogical().WaitIdle();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::SetWindowAdaptPass() {
|
void BlitScreen::SetWindowAdaptPass() {
|
||||||
|
|
|
||||||
|
|
@ -437,13 +437,13 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
|
||||||
if (barrier) {
|
if (barrier) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
||||||
}
|
}
|
||||||
cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies));
|
cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies));
|
||||||
if (barrier) {
|
if (barrier) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +457,7 @@ void BufferCacheRuntime::PreCopyBarrier() {
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, READ_BARRIER);
|
0, READ_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -471,7 +471,7 @@ void BufferCacheRuntime::PostCopyBarrier() {
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, WRITE_BARRIER);
|
0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -495,10 +495,10 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
|
||||||
|
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, READ_BARRIER);
|
0, READ_BARRIER);
|
||||||
cmdbuf.FillBuffer(dest_buffer, offset, size, value);
|
cmdbuf.FillBuffer(dest_buffer, offset, size, value);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, WRITE_BARRIER);
|
0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -454,8 +454,8 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
|
||||||
const VkDescriptorSet set = descriptor_allocator.Commit();
|
const VkDescriptorSet set = descriptor_allocator.Commit();
|
||||||
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
|
||||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
|
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
|
||||||
|
|
@ -537,7 +537,7 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe
|
||||||
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
|
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
|
||||||
cmdbuf.Dispatch(1, 1, 1);
|
cmdbuf.Dispatch(1, 1, 1);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -589,9 +589,9 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
cmdbuf.PipelineBarrier(is_initialized ? vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER
|
||||||
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
: VkPipelineStageFlags(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT),
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
||||||
});
|
});
|
||||||
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
|
||||||
|
|
@ -648,7 +648,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, image_barrier);
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier);
|
||||||
});
|
});
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
#include "video_core/gpu_logging/gpu_logging.h"
|
#include "video_core/gpu_logging/gpu_logging.h"
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#include "../../android/app/src/main/jni/android_settings.h"
|
#include "../../android/app/src/main/jni/android_settings.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
|
||||||
size_t GetTotalPipelineWorkers() {
|
size_t GetTotalPipelineWorkers() {
|
||||||
const size_t max_core_threads =
|
const size_t max_core_threads =
|
||||||
std::max<size_t>(static_cast<size_t>(std::thread::hardware_concurrency()), 2ULL) - 1ULL;
|
std::max<size_t>(static_cast<size_t>(std::thread::hardware_concurrency()), 2ULL) - 1ULL;
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
const int configured = AndroidSettings::values.pipeline_worker_count.GetValue();
|
const int configured = AndroidSettings::values.pipeline_worker_count.GetValue();
|
||||||
const int clamped = std::clamp(configured, 4, 8);
|
const int clamped = std::clamp(configured, 4, 8);
|
||||||
const size_t desired = static_cast<size_t>(clamped);
|
const size_t desired = static_cast<size_t>(clamped);
|
||||||
|
|
@ -492,8 +492,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
device.IsExtExtendedDynamicState3BlendingSupported();
|
device.IsExtExtendedDynamicState3BlendingSupported();
|
||||||
dynamic_features.has_extended_dynamic_state_3_enables =
|
dynamic_features.has_extended_dynamic_state_3_enables =
|
||||||
device.IsExtExtendedDynamicState3EnablesSupported();
|
device.IsExtExtendedDynamicState3EnablesSupported();
|
||||||
dynamic_features.has_dynamic_state3_depth_clamp_enable =
|
dynamic_features.has_dynamic_state3_depth_clamp_enable = false;
|
||||||
device.SupportsDynamicState3DepthClampEnable();
|
|
||||||
dynamic_features.has_dynamic_state3_logic_op_enable =
|
dynamic_features.has_dynamic_state3_logic_op_enable =
|
||||||
device.SupportsDynamicState3LogicOpEnable();
|
device.SupportsDynamicState3LogicOpEnable();
|
||||||
dynamic_features.has_dynamic_state3_line_stipple_enable =
|
dynamic_features.has_dynamic_state3_line_stipple_enable =
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
|
||||||
try {
|
try {
|
||||||
// Recreate surface and swapchain if needed.
|
// Recreate surface and swapchain if needed.
|
||||||
if (requires_recreation) {
|
if (requires_recreation) {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
surface = CreateSurface(instance, render_window.GetWindowInfo());
|
surface = CreateSurface(instance, render_window.GetWindowInfo());
|
||||||
#endif
|
#endif
|
||||||
RecreateSwapchain(frame);
|
RecreateSwapchain(frame);
|
||||||
|
|
@ -429,7 +429,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, {},
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, {},
|
||||||
{}, {}, pre_barriers);
|
{}, {}, pre_barriers);
|
||||||
|
|
||||||
if (blit_supported) {
|
if (blit_supported) {
|
||||||
|
|
|
||||||
|
|
@ -157,9 +157,8 @@ public:
|
||||||
ReserveHostQuery();
|
ReserveHostQuery();
|
||||||
|
|
||||||
scheduler.Record([query_pool = current_query_pool,
|
scheduler.Record([query_pool = current_query_pool,
|
||||||
query_index = current_bank_slot](vk::CommandBuffer cmdbuf) {
|
query_index = current_bank_slot](vk::CommandBuffer cmdbuf) {
|
||||||
const bool use_precise = Settings::IsGPULevelHigh();
|
const bool use_precise = Settings::IsGPULevelHigh();
|
||||||
cmdbuf.ResetQueryPool(query_pool, static_cast<u32>(query_index), 1);
|
|
||||||
cmdbuf.BeginQuery(query_pool, static_cast<u32>(query_index),
|
cmdbuf.BeginQuery(query_pool, static_cast<u32>(query_index),
|
||||||
use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
|
use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
|
||||||
});
|
});
|
||||||
|
|
@ -221,7 +220,8 @@ public:
|
||||||
}
|
}
|
||||||
PauseCounter();
|
PauseCounter();
|
||||||
const auto driver_id = device.GetDriverID();
|
const auto driver_id = device.GetDriverID();
|
||||||
if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
|
if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
|
||||||
|
driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
|
||||||
pending_sync.clear();
|
pending_sync.clear();
|
||||||
sync_values_stash.clear();
|
sync_values_stash.clear();
|
||||||
return;
|
return;
|
||||||
|
|
@ -846,7 +846,7 @@ public:
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
vk::PIPELINE_STAGE_HOST, 0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::scoped_lock lk(flush_guard);
|
std::scoped_lock lk(flush_guard);
|
||||||
|
|
@ -1587,13 +1587,13 @@ void QueryCacheRuntime::Barriers(bool is_prebarrier) {
|
||||||
impl->scheduler.RequestOutsideRenderPassOperationContext();
|
impl->scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
if (is_prebarrier) {
|
if (is_prebarrier) {
|
||||||
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST, 0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -580,7 +580,7 @@ void RasterizerVulkan::DispatchCompute() {
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
};
|
};
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
0, READ_BARRIER); });
|
0, READ_BARRIER); });
|
||||||
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
||||||
|
|
||||||
|
|
@ -928,13 +928,13 @@ void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_load
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::FlushWork() {
|
void RasterizerVulkan::FlushWork() {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
static constexpr u32 DRAWS_TO_DISPATCH = 512;
|
static constexpr u32 DRAWS_TO_DISPATCH = 512;
|
||||||
static constexpr u32 CHECK_MASK = 3;
|
static constexpr u32 CHECK_MASK = 3;
|
||||||
#else
|
#else
|
||||||
static constexpr u32 DRAWS_TO_DISPATCH = 4096;
|
static constexpr u32 DRAWS_TO_DISPATCH = 4096;
|
||||||
static constexpr u32 CHECK_MASK = 7;
|
static constexpr u32 CHECK_MASK = 7;
|
||||||
#endif // ANDROID
|
#endif // __ANDROID__
|
||||||
|
|
||||||
static_assert(DRAWS_TO_DISPATCH % (CHECK_MASK + 1) == 0);
|
static_assert(DRAWS_TO_DISPATCH % (CHECK_MASK + 1) == 0);
|
||||||
if ((++draw_counter & CHECK_MASK) != CHECK_MASK) {
|
if ((++draw_counter & CHECK_MASK) != CHECK_MASK) {
|
||||||
|
|
|
||||||
|
|
@ -267,8 +267,7 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
};
|
};
|
||||||
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
||||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, WRITE_BARRIER);
|
|
||||||
upload_cmdbuf.End();
|
upload_cmdbuf.End();
|
||||||
cmdbuf.End();
|
cmdbuf.End();
|
||||||
|
|
||||||
|
|
@ -372,7 +371,7 @@ void Scheduler::EndRenderPass()
|
||||||
}
|
}
|
||||||
cmdbuf.EndRenderPass();
|
cmdbuf.EndRenderPass();
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, nullptr, nullptr, vk::Span(barriers.data(), num_images));
|
0, nullptr, nullptr, vk::Span(barriers.data(), num_images));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
|
||||||
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.queueFamilyIndexCount = 0,
|
.queueFamilyIndexCount = 0,
|
||||||
.pQueueFamilyIndices = nullptr,
|
.pQueueFamilyIndices = nullptr,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
// On Android, do not allow surface rotation to deviate from the frontend.
|
// On Android, do not allow surface rotation to deviate from the frontend.
|
||||||
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
||||||
#else
|
#else
|
||||||
|
|
@ -313,7 +313,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
|
||||||
swapchain_ci.imageFormat, // Base format MUST be first
|
swapchain_ci.imageFormat, // Base format MUST be first
|
||||||
VK_FORMAT_B8G8R8A8_UNORM,
|
VK_FORMAT_B8G8R8A8_UNORM,
|
||||||
VK_FORMAT_B8G8R8A8_SRGB,
|
VK_FORMAT_B8G8R8A8_SRGB,
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
VK_FORMAT_R8G8B8A8_UNORM, // Android may use RGBA
|
VK_FORMAT_R8G8B8A8_UNORM, // Android may use RGBA
|
||||||
VK_FORMAT_R8G8B8A8_SRGB,
|
VK_FORMAT_R8G8B8A8_SRGB,
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -338,7 +338,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
|
||||||
|
|
||||||
images = swapchain.GetImages();
|
images = swapchain.GetImages();
|
||||||
image_count = static_cast<u32>(images.size());
|
image_count = static_cast<u32>(images.size());
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
// Android is already ordered the same as Switch.
|
// Android is already ordered the same as Switch.
|
||||||
image_view_format = VK_FORMAT_R8G8B8A8_UNORM;
|
image_view_format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -860,12 +860,12 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
|
||||||
.subresourceRange = subresource_range,
|
.subresourceRange = subresource_range,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, nullptr, nullptr, read_barriers);
|
0, nullptr, nullptr, read_barriers);
|
||||||
cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
|
cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter);
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, nullptr, nullptr, write_barriers);
|
0, nullptr, nullptr, write_barriers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
@ -1123,19 +1123,19 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
|
||||||
.subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
|
.subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, {}, {}, pre_barriers);
|
0, {}, {}, pre_barriers);
|
||||||
|
|
||||||
cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
|
cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
|
||||||
vk_in_copies);
|
vk_in_copies);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, WRITE_BARRIER, nullptr, middle_in_barrier);
|
0, WRITE_BARRIER, nullptr, middle_in_barrier);
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, READ_BARRIER, {}, middle_out_barrier);
|
0, READ_BARRIER, {}, middle_out_barrier);
|
||||||
cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
|
cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, {}, {}, post_barriers);
|
0, {}, {}, post_barriers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1261,8 +1261,8 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, nullptr, nullptr, read_barriers);
|
0, nullptr, nullptr, read_barriers);
|
||||||
if (is_resolve) {
|
if (is_resolve) {
|
||||||
cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image,
|
cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
|
@ -1274,8 +1274,8 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||||
src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
MakeImageBlit(dst_region, src_region, dst_layers, src_layers), vk_filter);
|
MakeImageBlit(dst_region, src_region, dst_layers, src_layers), vk_filter);
|
||||||
}
|
}
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, write_barrier);
|
0, write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1852,7 +1852,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, read_barrier);
|
0, read_barrier);
|
||||||
|
|
||||||
for (size_t index = 0; index < buffers.size(); index++) {
|
for (size_t index = 0; index < buffers.size(); index++) {
|
||||||
|
|
@ -1884,7 +1884,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, memory_write_barrier, nullptr, image_write_barrier);
|
0, memory_write_barrier, nullptr, image_write_barrier);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
@ -1919,7 +1919,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, read_barrier);
|
0, read_barrier);
|
||||||
|
|
||||||
for (size_t index = 0; index < buffers.size(); index++) {
|
for (size_t index = 0; index < buffers.size(); index++) {
|
||||||
|
|
@ -1951,7 +1951,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
0, memory_write_barrier, nullptr, image_write_barrier);
|
0, memory_write_barrier, nullptr, image_write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -2524,8 +2524,8 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) {
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([barrier](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([barrier](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier);
|
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
#include <adrenotools/driver.h>
|
#include <adrenotools/driver.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Vulkan {
|
||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
|
|
||||||
TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld)
|
TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld)
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
: m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device}
|
: m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
@ -40,7 +40,7 @@ void TurboMode::QueueSubmitted() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TurboMode::Run(std::stop_token stop_token) {
|
void TurboMode::Run(std::stop_token stop_token) {
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
auto& dld = m_device.GetLogical();
|
auto& dld = m_device.GetLogical();
|
||||||
|
|
||||||
// Allocate buffer. 2MiB should be sufficient.
|
// Allocate buffer. 2MiB should be sufficient.
|
||||||
|
|
@ -154,7 +154,7 @@ void TurboMode::Run(std::stop_token stop_token) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
adrenotools_set_turbo(true);
|
adrenotools_set_turbo(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -232,7 +232,7 @@ void TurboMode::Run(std::stop_token stop_token) {
|
||||||
std::chrono::milliseconds{100};
|
std::chrono::milliseconds{100};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
adrenotools_set_turbo(false);
|
adrenotools_set_turbo(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -23,7 +26,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void Run(std::stop_token stop_token);
|
void Run(std::stop_token stop_token);
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
Device m_device;
|
Device m_device;
|
||||||
MemoryAllocator m_allocator;
|
MemoryAllocator m_allocator;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Jorge Jimenez (jorge@iryoku.com)
|
// SPDX-FileCopyrightText: 2013 Jorge Jimenez (jorge@iryoku.com)
|
||||||
// SPDX-FileCopyrightText: 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
// SPDX-FileCopyrightText: 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
||||||
// SPDX-FileCopyrightText: 2013 Belen Masia (bmasia@unizar.es)
|
// SPDX-FileCopyrightText: 2013 Belen Masia (bmasia@unizar.es)
|
||||||
|
|
@ -5,8 +8,7 @@
|
||||||
// SPDX-FileCopyrightText: 2013 Diego Gutierrez (diegog@unizar.es)
|
// SPDX-FileCopyrightText: 2013 Diego Gutierrez (diegog@unizar.es)
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#ifndef AREATEX_H
|
#pragma once
|
||||||
#define AREATEX_H
|
|
||||||
|
|
||||||
#define AREATEX_WIDTH 160
|
#define AREATEX_WIDTH 160
|
||||||
#define AREATEX_HEIGHT 560
|
#define AREATEX_HEIGHT 560
|
||||||
|
|
@ -11219,5 +11221,3 @@ static const unsigned char areaTexBytes[] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Jorge Jimenez (jorge@iryoku.com)
|
// SPDX-FileCopyrightText: 2013 Jorge Jimenez (jorge@iryoku.com)
|
||||||
// SPDX-FileCopyrightText: 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
// SPDX-FileCopyrightText: 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
||||||
// SPDX-FileCopyrightText: 2013 Belen Masia (bmasia@unizar.es)
|
// SPDX-FileCopyrightText: 2013 Belen Masia (bmasia@unizar.es)
|
||||||
|
|
@ -5,8 +8,7 @@
|
||||||
// SPDX-FileCopyrightText: 2013 Diego Gutierrez (diegog@unizar.es)
|
// SPDX-FileCopyrightText: 2013 Diego Gutierrez (diegog@unizar.es)
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#ifndef SEARCHTEX_H
|
#pragma once
|
||||||
#define SEARCHTEX_H
|
|
||||||
|
|
||||||
#define SEARCHTEX_WIDTH 64
|
#define SEARCHTEX_WIDTH 64
|
||||||
#define SEARCHTEX_HEIGHT 16
|
#define SEARCHTEX_HEIGHT 16
|
||||||
|
|
@ -84,5 +86,3 @@ static const unsigned char searchTexBytes[] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||||
[[maybe_unused]] void* user_data) {
|
[[maybe_unused]] void* user_data) {
|
||||||
// Skip logging known false-positive validation errors
|
// Skip logging known false-positive validation errors
|
||||||
switch (static_cast<u32>(data->messageIdNumber)) {
|
switch (static_cast<u32>(data->messageIdNumber)) {
|
||||||
#ifdef ANDROID
|
#ifdef __ANDROID__
|
||||||
case 0xbf9cf353u: // VUID-vkCmdBindVertexBuffers2-pBuffers-04111
|
case 0xbf9cf353u: // VUID-vkCmdBindVertexBuffers2-pBuffers-04111
|
||||||
// The below are due to incorrect reporting of extendedDynamicState
|
// The below are due to incorrect reporting of extendedDynamicState
|
||||||
case 0x1093bebbu: // VUID-vkCmdSetCullMode-None-03384
|
case 0x1093bebbu: // VUID-vkCmdSetCullMode-None-03384
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
#include "video_core/gpu_logging/gpu_logging.h"
|
#include "video_core/gpu_logging/gpu_logging.h"
|
||||||
|
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
#include <adrenotools/bcenabler.h>
|
#include <adrenotools/bcenabler.h>
|
||||||
#include <android/api-level.h>
|
#include <android/api-level.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -294,7 +294,7 @@ ankerl::unordered_dense::map<VkFormat, VkFormatProperties> GetFormatProperties(v
|
||||||
return format_properties;
|
return format_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
void OverrideBcnFormats(ankerl::unordered_dense::map<VkFormat, VkFormatProperties>& format_properties) {
|
void OverrideBcnFormats(ankerl::unordered_dense::map<VkFormat, VkFormatProperties>& format_properties) {
|
||||||
// These properties are extracted from Adreno driver 512.687.0
|
// These properties are extracted from Adreno driver 512.687.0
|
||||||
constexpr VkFormatFeatureFlags tiling_features{VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
constexpr VkFormatFeatureFlags tiling_features{VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
||||||
|
|
@ -486,11 +486,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
CollectToolingInfo();
|
CollectToolingInfo();
|
||||||
|
|
||||||
if (is_qualcomm) {
|
if (is_qualcomm) {
|
||||||
// Qualcomm Adreno GPUs doesn't handle scaled vertex attributes; keep emulation enabled
|
LOG_WARNING(Render_Vulkan,
|
||||||
|
"Qualcomm drivers require scaled vertex format emulation");
|
||||||
must_emulate_scaled_formats = true;
|
must_emulate_scaled_formats = true;
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"Qualcomm drivers require scaled vertex format emulation; forcing fallback");
|
"Qualcomm drivers have broken provoking vertex");
|
||||||
|
RemoveExtension(extensions.provoking_vertex, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||||
|
LOG_WARNING(Render_Vulkan,
|
||||||
|
"Qualcomm drivers have slow push descriptor implementation");
|
||||||
|
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"Disabling shader float controls and 64-bit integer features on Qualcomm proprietary drivers");
|
"Disabling shader float controls and 64-bit integer features on Qualcomm proprietary drivers");
|
||||||
RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
RemoveExtension(extensions.shader_float_controls, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
|
||||||
|
|
@ -500,7 +504,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
features.shader_atomic_int64.shaderSharedInt64Atomics = false;
|
features.shader_atomic_int64.shaderSharedInt64Atomics = false;
|
||||||
features.features.shaderInt64 = false;
|
features.features.shaderInt64 = false;
|
||||||
|
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
// BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load.
|
// BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load.
|
||||||
const auto major = (properties.properties.driverVersion >> 24) << 2;
|
const auto major = (properties.properties.driverVersion >> 24) << 2;
|
||||||
const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU;
|
const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Vulkan {
|
||||||
std::shared_ptr<Common::DynamicLibrary> OpenLibrary(
|
std::shared_ptr<Common::DynamicLibrary> OpenLibrary(
|
||||||
[[maybe_unused]] Core::Frontend::GraphicsContext* context) {
|
[[maybe_unused]] Core::Frontend::GraphicsContext* context) {
|
||||||
LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library");
|
LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library");
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
// Android manages its Vulkan driver from the frontend.
|
// Android manages its Vulkan driver from the frontend.
|
||||||
return context->GetDriverLibrary();
|
return context->GetDriverLibrary();
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||||
X(vkCmdEndDebugUtilsLabelEXT);
|
X(vkCmdEndDebugUtilsLabelEXT);
|
||||||
X(vkCmdFillBuffer);
|
X(vkCmdFillBuffer);
|
||||||
X(vkCmdPipelineBarrier);
|
X(vkCmdPipelineBarrier);
|
||||||
X(vkCmdResetQueryPool);
|
|
||||||
X(vkCmdPushConstants);
|
X(vkCmdPushConstants);
|
||||||
X(vkCmdPushDescriptorSetWithTemplateKHR);
|
X(vkCmdPushDescriptorSetWithTemplateKHR);
|
||||||
X(vkCmdSetBlendConstants);
|
X(vkCmdSetBlendConstants);
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,18 @@ inline VkResult Filter(VkResult result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE =
|
||||||
|
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
|
||||||
|
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER =
|
||||||
|
PIPELINE_STAGE_GRAPHICS_COMPUTE | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
|
||||||
|
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST =
|
||||||
|
PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER | VK_PIPELINE_STAGE_HOST_BIT;
|
||||||
|
|
||||||
|
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_HOST = VK_PIPELINE_STAGE_HOST_BIT;
|
||||||
|
|
||||||
|
|
||||||
/// Table holding Vulkan instance function pointers.
|
/// Table holding Vulkan instance function pointers.
|
||||||
struct InstanceDispatch {
|
struct InstanceDispatch {
|
||||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};
|
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{};
|
||||||
|
|
@ -225,7 +237,6 @@ struct DeviceDispatch : InstanceDispatch {
|
||||||
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
|
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
|
||||||
PFN_vkCmdFillBuffer vkCmdFillBuffer{};
|
PFN_vkCmdFillBuffer vkCmdFillBuffer{};
|
||||||
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
|
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
|
||||||
PFN_vkCmdResetQueryPool vkCmdResetQueryPool{};
|
|
||||||
PFN_vkCmdPushConstants vkCmdPushConstants{};
|
PFN_vkCmdPushConstants vkCmdPushConstants{};
|
||||||
PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{};
|
PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{};
|
||||||
PFN_vkCmdResolveImage vkCmdResolveImage{};
|
PFN_vkCmdResolveImage vkCmdResolveImage{};
|
||||||
|
|
@ -442,7 +453,7 @@ public:
|
||||||
return handle != Type{};
|
return handle != Type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
/**
|
/**
|
||||||
* Releases ownership of the managed handle.
|
* Releases ownership of the managed handle.
|
||||||
* The caller is responsible for managing the lifetime of the returned handle.
|
* The caller is responsible for managing the lifetime of the returned handle.
|
||||||
|
|
@ -524,7 +535,7 @@ public:
|
||||||
return handle != Type{};
|
return handle != Type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef __ANDROID__
|
||||||
/**
|
/**
|
||||||
* Releases ownership of the managed handle.
|
* Releases ownership of the managed handle.
|
||||||
* The caller is responsible for managing the lifetime of the returned handle.
|
* The caller is responsible for managing the lifetime of the returned handle.
|
||||||
|
|
@ -1169,10 +1180,6 @@ public:
|
||||||
dld->vkCmdEndQuery(handle, query_pool, query);
|
dld->vkCmdEndQuery(handle, query_pool, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetQueryPool(VkQueryPool query_pool, u32 first_query, u32 query_count) const noexcept {
|
|
||||||
dld->vkCmdResetQueryPool(handle, query_pool, first_query, query_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first,
|
void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first,
|
||||||
Span<VkDescriptorSet> sets, Span<u32> dynamic_offsets) const noexcept {
|
Span<VkDescriptorSet> sets, Span<u32> dynamic_offsets) const noexcept {
|
||||||
dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),
|
dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),
|
||||||
|
|
|
||||||
|
|
@ -156,13 +156,12 @@ add_executable(yuzu
|
||||||
debugger/controller.cpp
|
debugger/controller.cpp
|
||||||
debugger/controller.h
|
debugger/controller.h
|
||||||
|
|
||||||
game/game_list.cpp
|
game/game_list.cpp game/game_list.h
|
||||||
game/game_list.h
|
game/game_grid.cpp game/game_grid.h
|
||||||
game/game_list_p.h
|
|
||||||
game/game_list_worker.cpp
|
game/game_tree.h game/game_tree.cpp
|
||||||
game/game_list_worker.h
|
game/game_card.h game/game_card.cpp
|
||||||
game/game_card.h
|
game/search_field.h game/search_field.cpp
|
||||||
game/game_card.cpp
|
|
||||||
|
|
||||||
hotkeys.cpp
|
hotkeys.cpp
|
||||||
hotkeys.h
|
hotkeys.h
|
||||||
|
|
@ -219,18 +218,16 @@ add_executable(yuzu
|
||||||
util/util.h
|
util/util.h
|
||||||
compatdb.cpp
|
compatdb.cpp
|
||||||
compatdb.h
|
compatdb.h
|
||||||
user_data_migration.cpp
|
|
||||||
user_data_migration.h
|
user_data_migration.h user_data_migration.cpp
|
||||||
|
|
||||||
yuzu.qrc
|
yuzu.qrc
|
||||||
yuzu.rc
|
yuzu.rc
|
||||||
migration_dialog.h migration_dialog.cpp
|
migration_dialog.h migration_dialog.cpp
|
||||||
migration_worker.h
|
migration_worker.h migration_worker.cpp
|
||||||
migration_worker.cpp
|
libqt_common.h libqt_common.cpp
|
||||||
|
|
||||||
deps_dialog.cpp
|
deps_dialog.cpp deps_dialog.h deps_dialog.ui
|
||||||
deps_dialog.h
|
|
||||||
deps_dialog.ui
|
|
||||||
|
|
||||||
data_dialog.h data_dialog.cpp data_dialog.ui
|
data_dialog.h data_dialog.cpp data_dialog.ui
|
||||||
data_widget.ui
|
data_widget.ui
|
||||||
|
|
@ -242,7 +239,6 @@ add_executable(yuzu
|
||||||
configuration/addon/mod_select_dialog.h configuration/addon/mod_select_dialog.cpp configuration/addon/mod_select_dialog.ui
|
configuration/addon/mod_select_dialog.h configuration/addon/mod_select_dialog.cpp configuration/addon/mod_select_dialog.ui
|
||||||
|
|
||||||
render/performance_overlay.h render/performance_overlay.cpp render/performance_overlay.ui
|
render/performance_overlay.h render/performance_overlay.cpp render/performance_overlay.ui
|
||||||
libqt_common.h libqt_common.cpp
|
|
||||||
updater/update_dialog.h updater/update_dialog.cpp updater/update_dialog.ui)
|
updater/update_dialog.h updater/update_dialog.cpp updater/update_dialog.ui)
|
||||||
|
|
||||||
set_target_properties(yuzu PROPERTIES OUTPUT_NAME "eden")
|
set_target_properties(yuzu PROPERTIES OUTPUT_NAME "eden")
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
#include "qt_common/config/uisettings.h"
|
#include "qt_common/config/uisettings.h"
|
||||||
|
#include "qt_common/qt_common.h"
|
||||||
#include "qt_common/util/vk.h"
|
#include "qt_common/util/vk.h"
|
||||||
#include "ui_configure_per_game.h"
|
#include "ui_configure_per_game.h"
|
||||||
#include "yuzu/configuration/configuration_shared.h"
|
#include "yuzu/configuration/configuration_shared.h"
|
||||||
|
|
@ -205,6 +206,6 @@ void ConfigurePerGame::LoadConfiguration() {
|
||||||
ui->display_format->setText(
|
ui->display_format->setText(
|
||||||
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())));
|
QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())));
|
||||||
|
|
||||||
const auto valueText = ReadableByteSize(file->GetSize());
|
const auto valueText = QtCommon::ReadableByteSize(file->GetSize());
|
||||||
ui->display_size->setText(valueText);
|
ui->display_size->setText(valueText);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef DATA_DIALOG_H
|
#pragma once
|
||||||
#define DATA_DIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "frontend_common/data_manager.h"
|
#include "frontend_common/data_manager.h"
|
||||||
|
|
@ -47,5 +46,3 @@ private:
|
||||||
|
|
||||||
std::optional<std::string> selectProfile();
|
std::optional<std::string> selectProfile();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DATA_DIALOG_H
|
|
||||||
|
|
|
||||||
|
|
@ -18,34 +18,27 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setRenderHint(QPainter::Antialiasing);
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
// Padding, dimensions, alignment...
|
constexpr int cardMargin = 8;
|
||||||
|
constexpr int cardCornerRadius = 10;
|
||||||
|
|
||||||
const int column = index.row() % m_columns;
|
const int column = index.row() % m_columns;
|
||||||
const int cell_width = option.rect.width();
|
const int cell_width = option.rect.width();
|
||||||
const int fixed_card_width = cell_width - m_padding;
|
const int card_width = cell_width - m_padding;
|
||||||
const int margins = 8;
|
|
||||||
|
|
||||||
// The gist of it is that this anchors the left and right sides to the edges,
|
const int row_width = m_columns * cell_width;
|
||||||
// while maintaining an even gap between each card.
|
const int total_gap = row_width - cardMargin * 2 - m_columns * card_width;
|
||||||
// I just smashed random keys into my keyboard until something worked.
|
const int gap = (m_columns > 1) ? (total_gap / (m_columns - 1)) : 0;
|
||||||
// Don't even bother trying to figure out what the hell this is doing.
|
|
||||||
const auto total_row_width = m_columns * cell_width;
|
|
||||||
const auto total_gap_space = total_row_width - (margins * 2) - (m_columns * fixed_card_width);
|
|
||||||
const auto gap = (m_columns > 1) ? (total_gap_space / (m_columns - 1)) : 0;
|
|
||||||
|
|
||||||
const auto relative_x = margins + (column * (fixed_card_width + gap));
|
const int card_left = option.rect.left() - column * cell_width + cardMargin + column * (card_width + gap) + 4;
|
||||||
const auto x_pos = option.rect.left() - (column * cell_width) + static_cast<int>(relative_x);
|
const QRect cardRect(card_left, option.rect.top() + 4, card_width - 8,
|
||||||
|
option.rect.height() - cardMargin);
|
||||||
|
|
||||||
// also, add some additional padding here to prevent card overlap
|
|
||||||
QRect cardRect(x_pos + 4, option.rect.top() + 4, fixed_card_width - 8,
|
|
||||||
option.rect.height() - margins);
|
|
||||||
|
|
||||||
// colors
|
|
||||||
QPalette palette = option.palette;
|
QPalette palette = option.palette;
|
||||||
QColor backgroundColor = palette.window().color();
|
QColor backgroundColor = palette.window().color();
|
||||||
QColor borderColor = palette.dark().color();
|
QColor borderColor = palette.dark().color();
|
||||||
QColor textColor = palette.text().color();
|
QColor textColor = palette.text().color();
|
||||||
|
|
||||||
// if it's selected add a blue background
|
// highlight blue on select
|
||||||
if (option.state & QStyle::State_Selected) {
|
if (option.state & QStyle::State_Selected) {
|
||||||
backgroundColor = palette.highlight().color();
|
backgroundColor = palette.highlight().color();
|
||||||
borderColor = palette.highlight().color().lighter(150);
|
borderColor = palette.highlight().color().lighter(150);
|
||||||
|
|
@ -54,63 +47,45 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
|
||||||
backgroundColor = backgroundColor.lighter(120);
|
backgroundColor = backgroundColor.lighter(120);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bg
|
|
||||||
painter->setBrush(backgroundColor);
|
painter->setBrush(backgroundColor);
|
||||||
painter->setPen(QPen(borderColor, 1));
|
painter->setPen(QPen(borderColor, 1));
|
||||||
painter->drawRoundedRect(cardRect, 10, 10);
|
painter->drawRoundedRect(cardRect, cardCornerRadius, cardCornerRadius);
|
||||||
|
|
||||||
// icon
|
const u32 icon_size = UISettings::values.game_icon_size.GetValue();
|
||||||
int _iconsize = UISettings::values.game_icon_size.GetValue();
|
QPixmap icon_pixmap = index.data(Qt::DecorationRole).value<QPixmap>();
|
||||||
QSize iconSize(_iconsize, _iconsize);
|
|
||||||
QPixmap iconPixmap = index.data(Qt::DecorationRole).value<QPixmap>();
|
|
||||||
|
|
||||||
QRect iconRect;
|
QRect iconRect;
|
||||||
if (!iconPixmap.isNull()) {
|
if (!icon_pixmap.isNull()) {
|
||||||
QSize scaledSize = iconPixmap.size();
|
QSize scaled = icon_pixmap.size();
|
||||||
scaledSize.scale(iconSize, Qt::KeepAspectRatio);
|
scaled.scale(icon_size, icon_size, Qt::KeepAspectRatio);
|
||||||
|
|
||||||
int x = cardRect.left() + (cardRect.width() - scaledSize.width()) / 2;
|
iconRect = {cardRect.left() + (cardRect.width() - scaled.width()) / 2,
|
||||||
int y = cardRect.top() + margins;
|
cardRect.top() + cardMargin, scaled.width(), scaled.height()};
|
||||||
|
|
||||||
iconRect = QRect(x, y, scaledSize.width(), scaledSize.height());
|
|
||||||
|
|
||||||
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
|
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||||
|
|
||||||
// Put this in a separate thing on the painter stack to prevent clipping the text.
|
|
||||||
painter->save();
|
painter->save();
|
||||||
|
QPainterPath clip_path;
|
||||||
// round image edges
|
clip_path.addRoundedRect(iconRect, cardCornerRadius, cardCornerRadius);
|
||||||
QPainterPath path;
|
painter->setClipPath(clip_path);
|
||||||
path.addRoundedRect(iconRect, 10, 10);
|
painter->drawPixmap(iconRect, icon_pixmap);
|
||||||
painter->setClipPath(path);
|
|
||||||
|
|
||||||
painter->drawPixmap(iconRect, iconPixmap);
|
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
} else {
|
} else {
|
||||||
// if there is no icon just draw a blank rect
|
iconRect = {cardRect.left() + cardMargin, cardRect.top() + cardMargin,
|
||||||
iconRect = QRect(cardRect.left() + margins, cardRect.top() + margins, _iconsize, _iconsize);
|
static_cast<int>(icon_size), static_cast<int>(icon_size)};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UISettings::values.show_game_name.GetValue()) {
|
if (UISettings::values.show_game_name.GetValue()) {
|
||||||
// padding + text
|
|
||||||
QRect textRect = cardRect;
|
QRect textRect = cardRect;
|
||||||
textRect.setTop(iconRect.bottom() + margins);
|
textRect.setTop(iconRect.bottom() + cardMargin);
|
||||||
textRect.adjust(margins, 0, -margins, -margins);
|
textRect.adjust(cardMargin, 0, -cardMargin, -cardMargin);
|
||||||
|
|
||||||
// We are already crammed on space, ignore the row 2
|
QString title = index.data(Qt::DisplayRole).toString().split(QLatin1Char('\n')).first();
|
||||||
QString title = index.data(Qt::DisplayRole).toString();
|
|
||||||
title = title.split(QLatin1Char('\n')).first();
|
|
||||||
|
|
||||||
// now draw text
|
|
||||||
painter->setPen(textColor);
|
painter->setPen(textColor);
|
||||||
QFont font = option.font;
|
QFont font = option.font;
|
||||||
font.setBold(true);
|
font.setBold(true);
|
||||||
|
font.setPixelSize(std::max(11.0, std::sqrt(static_cast<double>(icon_size))));
|
||||||
// TODO(crueter): fix this abysmal scaling
|
|
||||||
font.setPixelSize(1.5 + std::max(10.0, std::sqrt(_iconsize)));
|
|
||||||
|
|
||||||
// TODO(crueter): elide mode
|
|
||||||
painter->setFont(font);
|
painter->setFont(font);
|
||||||
|
|
||||||
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, title);
|
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, title);
|
||||||
|
|
|
||||||
118
src/yuzu/game/game_grid.cpp
Normal file
118
src/yuzu/game/game_grid.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <QScroller>
|
||||||
|
#include <QScrollerProperties>
|
||||||
|
|
||||||
|
#include "qt_common/config/uisettings.h"
|
||||||
|
#include "yuzu/game/game_card.h"
|
||||||
|
#include "yuzu/game/game_grid.h"
|
||||||
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
|
#include "qt_common/game_list/model.h"
|
||||||
|
|
||||||
|
GameGrid::GameGrid(QWidget* parent) : QListView{parent} {
|
||||||
|
m_gameCard = new GameCard(this);
|
||||||
|
setItemDelegate(m_gameCard);
|
||||||
|
|
||||||
|
setViewMode(QListView::ListMode);
|
||||||
|
setResizeMode(QListView::Fixed);
|
||||||
|
setUniformItemSizes(true);
|
||||||
|
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
|
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
|
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
|
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
setGridSize(QSize(140, 160));
|
||||||
|
m_gameCard->setSize(gridSize(), 0, 4);
|
||||||
|
|
||||||
|
setSpacing(10);
|
||||||
|
setWordWrap(true);
|
||||||
|
setTextElideMode(Qt::ElideRight);
|
||||||
|
setFlow(QListView::LeftToRight);
|
||||||
|
setWrapping(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameGrid::SetModel(GameListModel* model) {
|
||||||
|
QListView::setModel(model);
|
||||||
|
UpdateIconSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameGrid::ApplyFilter(const QString& edit_filter_text, GameListModel* model) {
|
||||||
|
int row_count = model->rowCount();
|
||||||
|
|
||||||
|
auto ContainsAllWords = [](const QString& haystack, const QString& userinput) {
|
||||||
|
const QStringList userinput_split =
|
||||||
|
userinput.split(QLatin1Char{' '}, Qt::SkipEmptyParts);
|
||||||
|
return std::all_of(userinput_split.begin(), userinput_split.end(),
|
||||||
|
[&haystack](const QString& s) { return haystack.contains(s); });
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < row_count; ++i) {
|
||||||
|
QStandardItem* item = model->item(i, 0);
|
||||||
|
if (!item)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const QString file_path =
|
||||||
|
item->data(GameListItemPath::FullPathRole).toString().toLower();
|
||||||
|
const QString file_title =
|
||||||
|
item->data(GameListItemPath::TitleRole).toString().toLower();
|
||||||
|
const QString file_name = file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) +
|
||||||
|
QLatin1Char{' '} + file_title;
|
||||||
|
|
||||||
|
if (edit_filter_text.isEmpty() || ContainsAllWords(file_name, edit_filter_text)) {
|
||||||
|
setRowHidden(i, false);
|
||||||
|
} else {
|
||||||
|
setRowHidden(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameGrid::UpdateIconSize() {
|
||||||
|
const u32 icon_size = UISettings::values.game_icon_size.GetValue();
|
||||||
|
|
||||||
|
int heightMargin = 0;
|
||||||
|
int widthMargin = 80;
|
||||||
|
|
||||||
|
if (UISettings::values.show_game_name) {
|
||||||
|
switch (icon_size) {
|
||||||
|
case 128:
|
||||||
|
heightMargin = 65;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
widthMargin = 120;
|
||||||
|
heightMargin = 120;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
heightMargin = 77;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
case 256:
|
||||||
|
heightMargin = 81;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
widthMargin = 24;
|
||||||
|
heightMargin = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int view_width = viewport()->width();
|
||||||
|
|
||||||
|
const double spacing = 0.01;
|
||||||
|
const int min_item_width = icon_size + widthMargin;
|
||||||
|
|
||||||
|
int columns = std::max(1, (view_width - 16) / min_item_width);
|
||||||
|
int stretched_width = ((view_width) - (spacing * (columns - 1))) / columns;
|
||||||
|
|
||||||
|
QSize grid_size(stretched_width, icon_size + heightMargin);
|
||||||
|
if (gridSize() != grid_size) {
|
||||||
|
setUpdatesEnabled(false);
|
||||||
|
|
||||||
|
setGridSize(grid_size);
|
||||||
|
m_gameCard->setSize(grid_size, stretched_width - min_item_width, columns);
|
||||||
|
|
||||||
|
setUpdatesEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/yuzu/game/game_grid.h
Normal file
26
src/yuzu/game/game_grid.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QListView>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
class GameCard;
|
||||||
|
class GameListModel;
|
||||||
|
|
||||||
|
class GameGrid : public QListView {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameGrid(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void SetModel(GameListModel* model);
|
||||||
|
void ApplyFilter(const QString& edit_filter_text, GameListModel* model);
|
||||||
|
void UpdateIconSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameCard* m_gameCard = nullptr;
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,14 +6,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTreeView>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
@ -28,21 +26,22 @@
|
||||||
|
|
||||||
class QVariantAnimation;
|
class QVariantAnimation;
|
||||||
|
|
||||||
class QListView;
|
|
||||||
|
|
||||||
class GameCard;
|
class GameCard;
|
||||||
namespace Core {
|
class GameListModel;
|
||||||
class System;
|
class GameTree;
|
||||||
}
|
class GameGrid;
|
||||||
|
class GameListSearchField;
|
||||||
class ControllerNavigation;
|
class ControllerNavigation;
|
||||||
class GameListWorker;
|
class GameListWorker;
|
||||||
class GameListSearchField;
|
|
||||||
class GameListDir;
|
class GameListDir;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
enum class AmLaunchType;
|
enum class AmLaunchType;
|
||||||
enum class StartGameType;
|
enum class StartGameType;
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
class ManualContentProvider;
|
class ManualContentProvider;
|
||||||
class VfsFilesystem;
|
class VfsFilesystem;
|
||||||
|
|
@ -62,16 +61,6 @@ class GameList : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
|
||||||
COLUMN_NAME,
|
|
||||||
COLUMN_FILE_TYPE,
|
|
||||||
COLUMN_SIZE,
|
|
||||||
COLUMN_PLAY_TIME,
|
|
||||||
COLUMN_ADD_ONS,
|
|
||||||
COLUMN_COMPATIBILITY,
|
|
||||||
COLUMN_COUNT, // Number of columns
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
|
explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
|
||||||
FileSys::ManualContentProvider* provider_,
|
FileSys::ManualContentProvider* provider_,
|
||||||
PlayTime::PlayTimeManager& play_time_manager_, Core::System& system_,
|
PlayTime::PlayTimeManager& play_time_manager_, Core::System& system_,
|
||||||
|
|
@ -95,13 +84,11 @@ public:
|
||||||
/// Disables events from the emulated controller
|
/// Disables events from the emulated controller
|
||||||
void UnloadController();
|
void UnloadController();
|
||||||
|
|
||||||
bool IsTreeMode();
|
|
||||||
void ResetViewMode();
|
void ResetViewMode();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void RefreshGameDirectory();
|
void RefreshGameDirectory();
|
||||||
void RefreshExternalContent();
|
void RefreshExternalContent();
|
||||||
void ResetExternalWatcher();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void BootGame(const QString& game_path, StartGameType type);
|
void BootGame(const QString& game_path, StartGameType type);
|
||||||
|
|
@ -130,27 +117,20 @@ signals:
|
||||||
void SaveConfig();
|
void SaveConfig();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void OnItemExpanded(const QModelIndex& item);
|
|
||||||
void OnTextChanged(const QString& new_text);
|
void OnTextChanged(const QString& new_text);
|
||||||
void OnFilterCloseClicked();
|
void OnFilterCloseClicked();
|
||||||
void OnUpdateThemedIcons();
|
void OnUpdateThemedIcons();
|
||||||
|
void OnPopulatingCompleted(const QStringList& watch_list);
|
||||||
void UpdateIconSize();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GameListWorker;
|
void SetupViews();
|
||||||
void WorkerEvent();
|
void SetupScrollAnimation();
|
||||||
|
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||||
|
void changeEvent(QEvent*) override;
|
||||||
|
|
||||||
void AddDirEntry(GameListDir* entry_items);
|
|
||||||
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
|
|
||||||
void DonePopulating(const QStringList& watch_list);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ValidateEntry(const QModelIndex& item);
|
void ValidateEntry(const QModelIndex& item);
|
||||||
|
|
||||||
void ToggleFavorite(u64 program_id);
|
void ToggleFavorite(u64 program_id);
|
||||||
void AddFavorite(u64 program_id);
|
|
||||||
void RemoveFavorite(u64 program_id);
|
|
||||||
|
|
||||||
void PopupContextMenu(const QPoint& menu_location);
|
void PopupContextMenu(const QPoint& menu_location);
|
||||||
void AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path);
|
void AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path);
|
||||||
|
|
@ -158,41 +138,32 @@ private:
|
||||||
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
||||||
void AddFavoritesPopup(QMenu& context_menu);
|
void AddFavoritesPopup(QMenu& context_menu);
|
||||||
|
|
||||||
void changeEvent(QEvent*) override;
|
|
||||||
void RetranslateUI();
|
void RetranslateUI();
|
||||||
|
|
||||||
|
friend class GameListSearchField;
|
||||||
|
|
||||||
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
||||||
FileSys::ManualContentProvider* provider;
|
FileSys::ManualContentProvider* provider;
|
||||||
GameListSearchField* search_field;
|
GameListSearchField* search_field = nullptr;
|
||||||
MainWindow* main_window = nullptr;
|
MainWindow* main_window = nullptr;
|
||||||
QVBoxLayout* layout = nullptr;
|
QVBoxLayout* layout = nullptr;
|
||||||
|
|
||||||
QTreeView* tree_view = nullptr;
|
GameTree* tree_view = nullptr;
|
||||||
QListView* list_view = nullptr;
|
GameGrid* grid_view = nullptr;
|
||||||
GameCard* m_gameCard = nullptr;
|
GameListModel* item_model = nullptr;
|
||||||
|
|
||||||
QStandardItemModel* item_model = nullptr;
|
|
||||||
std::unique_ptr<GameListWorker> current_worker;
|
|
||||||
QFileSystemWatcher* watcher = nullptr;
|
|
||||||
QFileSystemWatcher* external_watcher = nullptr;
|
|
||||||
ControllerNavigation* controller_navigation = nullptr;
|
ControllerNavigation* controller_navigation = nullptr;
|
||||||
CompatibilityList compatibility_list;
|
|
||||||
|
|
||||||
QVariantAnimation* vertical_scroll = nullptr;
|
QVariantAnimation* vertical_scroll = nullptr;
|
||||||
QVariantAnimation* horizontal_scroll = nullptr;
|
QVariantAnimation* horizontal_scroll = nullptr;
|
||||||
int vertical_scroll_target = 0;
|
int vertical_scroll_target = 0;
|
||||||
int horizontal_scroll_target = 0;
|
int horizontal_scroll_target = 0;
|
||||||
|
|
||||||
void SetupScrollAnimation();
|
|
||||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
|
||||||
|
|
||||||
friend class GameListSearchField;
|
|
||||||
|
|
||||||
const PlayTime::PlayTimeManager& play_time_manager;
|
const PlayTime::PlayTimeManager& play_time_manager;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
bool m_isTreeMode = true;
|
bool m_isTreeMode = true;
|
||||||
QAbstractItemView* m_currentView = tree_view;
|
QAbstractItemView* m_currentView = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameListPlaceholder : public QWidget {
|
class GameListPlaceholder : public QWidget {
|
||||||
|
|
|
||||||
173
src/yuzu/game/game_tree.cpp
Normal file
173
src/yuzu/game/game_tree.cpp
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QScroller>
|
||||||
|
#include <QScrollerProperties>
|
||||||
|
|
||||||
|
#include "qt_common/config/uisettings.h"
|
||||||
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
|
#include "yuzu/game/game_tree.h"
|
||||||
|
#include "qt_common/game_list/model.h"
|
||||||
|
|
||||||
|
GameTree::GameTree(QWidget* parent) : QTreeView{parent} {
|
||||||
|
setAlternatingRowColors(true);
|
||||||
|
setSelectionMode(QHeaderView::SingleSelection);
|
||||||
|
setSelectionBehavior(QHeaderView::SelectRows);
|
||||||
|
setVerticalScrollMode(QHeaderView::ScrollPerPixel);
|
||||||
|
setHorizontalScrollMode(QHeaderView::ScrollPerPixel);
|
||||||
|
setSortingEnabled(true);
|
||||||
|
setEditTriggers(QHeaderView::NoEditTriggers);
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
setAttribute(Qt::WA_AcceptTouchEvents, true);
|
||||||
|
setStyleSheet(QStringLiteral("QTreeView{ border: none; }"));
|
||||||
|
|
||||||
|
connect(this, &QTreeView::expanded, this, &GameTree::OnItemExpanded);
|
||||||
|
connect(this, &QTreeView::collapsed, this, &GameTree::OnItemExpanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::SetModel(GameListModel* model) {
|
||||||
|
QTreeView::setModel(model);
|
||||||
|
LoadInterfaceLayout();
|
||||||
|
UpdateColumnVisibility(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::OnItemExpanded(const QModelIndex& item) {
|
||||||
|
const auto type = item.data(GameListItem::TypeRole).value<GameListItemType>();
|
||||||
|
const bool is_dir = type == GameListItemType::CustomDir || type == GameListItemType::SdmcDir ||
|
||||||
|
type == GameListItemType::UserNandDir ||
|
||||||
|
type == GameListItemType::SysNandDir;
|
||||||
|
const bool is_fave = type == GameListItemType::Favorites;
|
||||||
|
if (!is_dir && !is_fave) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bool is_expanded = isExpanded(item);
|
||||||
|
if (is_fave) {
|
||||||
|
UISettings::values.favorites_expanded = is_expanded;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int item_dir_index = item.data(GameListDir::GameDirRole).toInt();
|
||||||
|
UISettings::values.game_dirs[item_dir_index].expanded = is_expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::SaveInterfaceLayout() {
|
||||||
|
UISettings::values.gamelist_header_state = header()->saveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::LoadInterfaceLayout() {
|
||||||
|
auto* hdr = header();
|
||||||
|
|
||||||
|
if (hdr->restoreState(UISettings::values.gamelist_header_state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hdr->resizeSection(GameListModel::COLUMN_NAME, 840);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::UpdateColumnVisibility(GameListModel* model) {
|
||||||
|
Q_UNUSED(model)
|
||||||
|
setColumnHidden(GameListModel::COLUMN_ADD_ONS, !UISettings::values.show_add_ons);
|
||||||
|
setColumnHidden(GameListModel::COLUMN_COMPATIBILITY, !UISettings::values.show_compat);
|
||||||
|
setColumnHidden(GameListModel::COLUMN_FILE_TYPE, !UISettings::values.show_types);
|
||||||
|
setColumnHidden(GameListModel::COLUMN_SIZE, !UISettings::values.show_size);
|
||||||
|
setColumnHidden(GameListModel::COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameTree::GetLastFilterResultItem() const {
|
||||||
|
QString file_path;
|
||||||
|
|
||||||
|
auto* model = qobject_cast<GameListModel*>(QTreeView::model());
|
||||||
|
if (!model)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
for (int i = 1; i < model->rowCount() - 1; ++i) {
|
||||||
|
const QStandardItem* folder = model->item(i, 0);
|
||||||
|
const QModelIndex folder_index = folder->index();
|
||||||
|
const int children_count = folder->rowCount();
|
||||||
|
|
||||||
|
for (int j = 0; j < children_count; ++j) {
|
||||||
|
if (isRowHidden(j, folder_index)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStandardItem* child = folder->child(j, 0);
|
||||||
|
file_path = child->data(GameListItemPath::FullPathRole).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameTree::FilterClosedResultCount(GameListModel* model) {
|
||||||
|
int children_total = 0;
|
||||||
|
|
||||||
|
auto hide_favorites_row = UISettings::values.favorited_ids.size() == 0;
|
||||||
|
setRowHidden(0, model->invisibleRootItem()->index(), hide_favorites_row);
|
||||||
|
|
||||||
|
for (int i = 1; i < model->rowCount() - 1; ++i) {
|
||||||
|
auto* folder = model->item(i, 0);
|
||||||
|
const QModelIndex folder_index = folder->index();
|
||||||
|
const int children_count = folder->rowCount();
|
||||||
|
for (int j = 0; j < children_count; ++j) {
|
||||||
|
++children_total;
|
||||||
|
setRowHidden(j, folder_index, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return children_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTree::ApplyFilter(const QString& edit_filter_text, GameListModel* model) {
|
||||||
|
int children_total = 0;
|
||||||
|
int result_count = 0;
|
||||||
|
|
||||||
|
if (edit_filter_text.isEmpty()) {
|
||||||
|
children_total = FilterClosedResultCount(model);
|
||||||
|
emit FilterResultReady(children_total, children_total);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRowHidden(0, model->invisibleRootItem()->index(), true);
|
||||||
|
|
||||||
|
for (int i = 1; i < model->rowCount() - 1; ++i) {
|
||||||
|
auto* folder = model->item(i, 0);
|
||||||
|
const QModelIndex folder_index = folder->index();
|
||||||
|
const int children_count = folder->rowCount();
|
||||||
|
|
||||||
|
for (int j = 0; j < children_count; ++j) {
|
||||||
|
++children_total;
|
||||||
|
|
||||||
|
const QStandardItem* child = folder->child(j, 0);
|
||||||
|
|
||||||
|
const auto program_id = child->data(GameListItemPath::ProgramIdRole).toULongLong();
|
||||||
|
|
||||||
|
const QString file_path =
|
||||||
|
child->data(GameListItemPath::FullPathRole).toString().toLower();
|
||||||
|
const QString file_title =
|
||||||
|
child->data(GameListItemPath::TitleRole).toString().toLower();
|
||||||
|
const QString file_program_id =
|
||||||
|
QStringLiteral("%1").arg(program_id, 16, 16, QLatin1Char{'0'});
|
||||||
|
|
||||||
|
const QString file_name =
|
||||||
|
file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} +
|
||||||
|
file_title;
|
||||||
|
|
||||||
|
auto ContainsAllWords = [](const QString& haystack, const QString& userinput) {
|
||||||
|
const QStringList userinput_split =
|
||||||
|
userinput.split(QLatin1Char{' '}, Qt::SkipEmptyParts);
|
||||||
|
return std::all_of(userinput_split.begin(), userinput_split.end(),
|
||||||
|
[&haystack](const QString& s) { return haystack.contains(s); });
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ContainsAllWords(file_name, edit_filter_text) ||
|
||||||
|
(file_program_id.size() == 16 && file_program_id.contains(edit_filter_text))) {
|
||||||
|
setRowHidden(j, folder_index, false);
|
||||||
|
++result_count;
|
||||||
|
} else {
|
||||||
|
setRowHidden(j, folder_index, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit FilterResultReady(result_count, children_total);
|
||||||
|
}
|
||||||
35
src/yuzu/game/game_tree.h
Normal file
35
src/yuzu/game/game_tree.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
class GameListModel;
|
||||||
|
|
||||||
|
class GameTree : public QTreeView {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameTree(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void SetModel(GameListModel* model);
|
||||||
|
|
||||||
|
QString GetLastFilterResultItem() const;
|
||||||
|
int FilterClosedResultCount(GameListModel* model);
|
||||||
|
void ApplyFilter(const QString& edit_filter_text, GameListModel* model);
|
||||||
|
|
||||||
|
void SaveInterfaceLayout();
|
||||||
|
void LoadInterfaceLayout();
|
||||||
|
|
||||||
|
void UpdateColumnVisibility(GameListModel* model);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void ItemExpandedChanged(const QModelIndex& item);
|
||||||
|
void FilterResultReady(int visible, int total);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void OnItemExpanded(const QModelIndex& item);
|
||||||
|
};
|
||||||
124
src/yuzu/game/search_field.cpp
Normal file
124
src/yuzu/game/search_field.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "game/game_list.h"
|
||||||
|
#include "game/search_field.h"
|
||||||
|
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
// TODO: Remove GameList dependence?
|
||||||
|
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
|
||||||
|
: QObject(parent), gamelist{gamelist_} {}
|
||||||
|
|
||||||
|
// EventFilter in order to process systemkeys while editing the searchfield
|
||||||
|
bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) {
|
||||||
|
// If it isn't a KeyRelease event then continue with standard event processing
|
||||||
|
if (event->type() != QEvent::KeyRelease)
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
|
||||||
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
|
QString edit_filter_text = gamelist->search_field->edit_filter->text().toLower();
|
||||||
|
|
||||||
|
// If the searchfield's text hasn't changed special function keys get checked
|
||||||
|
// If no function key changes the searchfield's text the filter doesn't need to get reloaded
|
||||||
|
if (edit_filter_text == edit_filter_text_old) {
|
||||||
|
switch (keyEvent->key()) {
|
||||||
|
// Escape: Resets the searchfield
|
||||||
|
case Qt::Key_Escape: {
|
||||||
|
if (edit_filter_text_old.isEmpty()) {
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
} else {
|
||||||
|
gamelist->search_field->edit_filter->clear();
|
||||||
|
edit_filter_text.clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Return and Enter
|
||||||
|
// If the enter key gets pressed first checks how many and which entry is visible
|
||||||
|
// If there is only one result launch this game
|
||||||
|
case Qt::Key_Return:
|
||||||
|
case Qt::Key_Enter: {
|
||||||
|
if (gamelist->search_field->visible == 1) {
|
||||||
|
const QString file_path = gamelist->GetLastFilterResultItem();
|
||||||
|
|
||||||
|
// To avoid loading error dialog loops while confirming them using enter
|
||||||
|
// Also users usually want to run a different game after closing one
|
||||||
|
gamelist->search_field->edit_filter->clear();
|
||||||
|
edit_filter_text.clear();
|
||||||
|
emit gamelist->GameChosen(file_path);
|
||||||
|
} else {
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edit_filter_text_old = edit_filter_text;
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListSearchField::setFilterResult(int visible_, int total_) {
|
||||||
|
visible = visible_;
|
||||||
|
total = total_;
|
||||||
|
|
||||||
|
label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameListSearchField::filterText() const {
|
||||||
|
return edit_filter->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListSearchField::clear() {
|
||||||
|
edit_filter->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListSearchField::setFocus() {
|
||||||
|
if (edit_filter->isVisible()) {
|
||||||
|
edit_filter->setFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {
|
||||||
|
auto* const key_release_eater = new KeyReleaseEater(parent, this);
|
||||||
|
layout_filter = new QHBoxLayout;
|
||||||
|
layout_filter->setContentsMargins(8, 8, 8, 8);
|
||||||
|
label_filter = new QLabel;
|
||||||
|
edit_filter = new QLineEdit;
|
||||||
|
edit_filter->clear();
|
||||||
|
edit_filter->installEventFilter(key_release_eater);
|
||||||
|
edit_filter->setClearButtonEnabled(true);
|
||||||
|
connect(edit_filter, &QLineEdit::textChanged, parent, &GameList::OnTextChanged);
|
||||||
|
label_filter_result = new QLabel;
|
||||||
|
button_filter_close = new QToolButton(this);
|
||||||
|
button_filter_close->setText(QStringLiteral("X"));
|
||||||
|
button_filter_close->setCursor(Qt::ArrowCursor);
|
||||||
|
button_filter_close->setStyleSheet(
|
||||||
|
QStringLiteral("QToolButton{ border: none; padding: 0px; color: "
|
||||||
|
"#000000; font-weight: bold; background: #F0F0F0; }"
|
||||||
|
"QToolButton:hover{ border: none; padding: 0px; color: "
|
||||||
|
"#EEEEEE; font-weight: bold; background: #E81123}"));
|
||||||
|
connect(button_filter_close, &QToolButton::clicked, parent, &GameList::OnFilterCloseClicked);
|
||||||
|
layout_filter->setSpacing(10);
|
||||||
|
layout_filter->addWidget(label_filter);
|
||||||
|
layout_filter->addWidget(edit_filter);
|
||||||
|
layout_filter->addWidget(label_filter_result);
|
||||||
|
layout_filter->addWidget(button_filter_close);
|
||||||
|
setLayout(layout_filter);
|
||||||
|
RetranslateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListSearchField::changeEvent(QEvent* event) {
|
||||||
|
if (event->type() == QEvent::LanguageChange) {
|
||||||
|
RetranslateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget::changeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListSearchField::RetranslateUI() {
|
||||||
|
label_filter->setText(tr("Filter:"));
|
||||||
|
edit_filter->setPlaceholderText(tr("Enter pattern to filter"));
|
||||||
|
}
|
||||||
52
src/yuzu/game/search_field.h
Normal file
52
src/yuzu/game/search_field.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class GameList;
|
||||||
|
class QHBoxLayout;
|
||||||
|
class QTreeView;
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QToolButton;
|
||||||
|
|
||||||
|
class GameListSearchField : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameListSearchField(GameList* parent = nullptr);
|
||||||
|
|
||||||
|
QString filterText() const;
|
||||||
|
void setFilterResult(int visible_, int total_);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void setFocus();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void changeEvent(QEvent*) override;
|
||||||
|
void RetranslateUI();
|
||||||
|
|
||||||
|
class KeyReleaseEater : public QObject {
|
||||||
|
public:
|
||||||
|
explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameList* gamelist = nullptr;
|
||||||
|
QString edit_filter_text_old;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// EventFilter in order to process systemkeys while editing the searchfield
|
||||||
|
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||||
|
};
|
||||||
|
int visible;
|
||||||
|
int total;
|
||||||
|
|
||||||
|
QHBoxLayout* layout_filter = nullptr;
|
||||||
|
QTreeView* tree_view = nullptr;
|
||||||
|
QLabel* label_filter = nullptr;
|
||||||
|
QLineEdit* edit_filter = nullptr;
|
||||||
|
QLabel* label_filter_result = nullptr;
|
||||||
|
QToolButton* button_filter_close = nullptr;
|
||||||
|
};
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef MIGRATION_DIALOG_H
|
#pragma once
|
||||||
#define MIGRATION_DIALOG_H
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
@ -29,5 +28,3 @@ private:
|
||||||
|
|
||||||
QAbstractButton* m_clickedButton;
|
QAbstractButton* m_clickedButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MIGRATION_DIALOG_H
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef MIGRATION_WORKER_H
|
#pragma once
|
||||||
#define MIGRATION_WORKER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
|
@ -73,5 +72,3 @@ private:
|
||||||
MigrationStrategy strategy;
|
MigrationStrategy strategy;
|
||||||
QString success_text = tr("Data was migrated successfully.");
|
QString success_text = tr("Data was migrated successfully.");
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MIGRATION_WORKER_H
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "network/announce_multiplayer_session.h"
|
#include "network/announce_multiplayer_session.h"
|
||||||
#include "ui_chat_room.h"
|
#include "ui_chat_room.h"
|
||||||
#include "yuzu/game/game_list_p.h"
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
#include "yuzu/multiplayer/chat_room.h"
|
#include "yuzu/multiplayer/chat_room.h"
|
||||||
#include "yuzu/multiplayer/message.h"
|
#include "yuzu/multiplayer/message.h"
|
||||||
#ifdef ENABLE_WEB_SERVICE
|
#ifdef ENABLE_WEB_SERVICE
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "network/announce_multiplayer_session.h"
|
#include "network/announce_multiplayer_session.h"
|
||||||
#include "ui_client_room.h"
|
#include "ui_client_room.h"
|
||||||
#include "yuzu/game/game_list_p.h"
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
#include "yuzu/multiplayer/client_room.h"
|
#include "yuzu/multiplayer/client_room.h"
|
||||||
#include "yuzu/multiplayer/message.h"
|
#include "yuzu/multiplayer/message.h"
|
||||||
#include "yuzu/multiplayer/moderation_dialog.h"
|
#include "yuzu/multiplayer/moderation_dialog.h"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "network/announce_multiplayer_session.h"
|
#include "network/announce_multiplayer_session.h"
|
||||||
#include "qt_common/config/uisettings.h"
|
#include "qt_common/config/uisettings.h"
|
||||||
#include "ui_host_room.h"
|
#include "ui_host_room.h"
|
||||||
#include "yuzu/game/game_list_p.h"
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
#include "yuzu/main_window.h"
|
#include "yuzu/main_window.h"
|
||||||
#include "yuzu/multiplayer/host_room.h"
|
#include "yuzu/multiplayer/host_room.h"
|
||||||
#include "yuzu/multiplayer/message.h"
|
#include "yuzu/multiplayer/message.h"
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "qt_common/config/uisettings.h"
|
#include "qt_common/config/uisettings.h"
|
||||||
#include "ui_lobby.h"
|
#include "ui_lobby.h"
|
||||||
#include "yuzu/game/game_list_p.h"
|
#include "qt_common/game_list/game_list_p.h"
|
||||||
#include "yuzu/main_window.h"
|
#include "yuzu/main_window.h"
|
||||||
#include "yuzu/multiplayer/client_room.h"
|
#include "yuzu/multiplayer/client_room.h"
|
||||||
#include "yuzu/multiplayer/lobby.h"
|
#include "yuzu/multiplayer/lobby.h"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#ifndef RYUJINX_DIALOG_H
|
#pragma once
|
||||||
#define RYUJINX_DIALOG_H
|
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
@ -28,5 +27,3 @@ private:
|
||||||
std::filesystem::path m_eden;
|
std::filesystem::path m_eden;
|
||||||
std::filesystem::path m_ryu;
|
std::filesystem::path m_ryu;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RYUJINX_DIALOG_H
|
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,11 @@
|
||||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
#include "applets/qt_profile_select.h"
|
#include "applets/qt_profile_select.h"
|
||||||
#include "common/logging.h"
|
|
||||||
#include "core/frontend/applets/profile_select.h"
|
#include "core/frontend/applets/profile_select.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "frontend_common/data_manager.h"
|
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
#include "yuzu/util/util.h"
|
#include "yuzu/util/util.h"
|
||||||
|
|
||||||
|
|
@ -28,21 +25,6 @@ QFont GetMonospaceFont() {
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ReadableByteSize(qulonglong size) {
|
|
||||||
return QString::fromStdString(FrontendCommon::DataManager::ReadableBytesSize(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap CreateCirclePixmapFromColor(const QColor& color) {
|
|
||||||
QPixmap circle_pixmap(16, 16);
|
|
||||||
circle_pixmap.fill(Qt::transparent);
|
|
||||||
QPainter painter(&circle_pixmap);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.setPen(color);
|
|
||||||
painter.setBrush(color);
|
|
||||||
painter.drawEllipse({circle_pixmap.width() / 2.0, circle_pixmap.height() / 2.0}, 7.0, 7.0);
|
|
||||||
return circle_pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::optional<Common::UUID> GetProfileID() {
|
const std::optional<Common::UUID> GetProfileID() {
|
||||||
// if there's only a single profile, the user probably wants to use that... right?
|
// if there's only a single profile, the user probably wants to use that... right?
|
||||||
const auto& profiles = QtCommon::system->GetProfileManager().FindExistingProfileUUIDs();
|
const auto& profiles = QtCommon::system->GetProfileManager().FindExistingProfileUUIDs();
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,6 @@
|
||||||
/// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc.
|
/// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc.
|
||||||
[[nodiscard]] QFont GetMonospaceFont();
|
[[nodiscard]] QFont GetMonospaceFont();
|
||||||
|
|
||||||
/// Convert a size in bytes into a readable format (KiB, MiB, etc.)
|
|
||||||
[[nodiscard]] QString ReadableByteSize(qulonglong size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a circle pixmap from a specified color
|
|
||||||
* @param color The color the pixmap shall have
|
|
||||||
* @return QPixmap circle pixmap
|
|
||||||
*/
|
|
||||||
[[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompt the user for a profile ID. If there is only one valid profile, returns that profile.
|
* Prompt the user for a profile ID. If there is only one valid profile, returns that profile.
|
||||||
* @return The selected profile, or an std::nullopt if none were selected
|
* @return The selected profile, or an std::nullopt if none were selected
|
||||||
|
|
|
||||||
55
tools/cpp-lint.sh
Executable file
55
tools/cpp-lint.sh
Executable file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/sh -ex
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# tools/../
|
||||||
|
ROOTDIR=$(CDPATH='' cd -- "$(dirname -- "$0")/../" && pwd)
|
||||||
|
BUILD_DIR="$ROOTDIR"/build
|
||||||
|
SRC_DIR="$ROOTDIR"/src
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "-- $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [command]
|
||||||
|
|
||||||
|
Dumb script that serves as a ad-hoc cpp-linter
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
once Check for #pragma once prescence in header files
|
||||||
|
osdef Finds OS defines that are not recommended to use.
|
||||||
|
inchk Check includes being valid/toolchain not being stupid
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case "$1" in
|
||||||
|
once)
|
||||||
|
find "$SRC_DIR" -type f -name "*.h" -exec grep -L "#pragma once" {} +
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
osdef)
|
||||||
|
# not recommended macros
|
||||||
|
PATTERN="ANDROID\|_WIN64\|__linux\|__unix\|APPLE\|__APPLE"
|
||||||
|
strings=("ANDROID" "_WIN64" "__linux" "__unix" "APPLE" "__APPLE" "linux" "unix")
|
||||||
|
for item in "${strings[@]}"; do
|
||||||
|
PATTERN="$PATTERN\|ifdef $item\|($item)"
|
||||||
|
done
|
||||||
|
# if statements for macros that shouldn't be if
|
||||||
|
strings=("_WIN32" "_AIX" "__managarm__" "__unix__" "__linux__" "__FreeBSD__" "__NetBSD__" \
|
||||||
|
"__OpenBSD__" "__DragonFly__" "__redox__" "__HAIKU__" "__OHOS__" "__FIREOS__")
|
||||||
|
for item in "${strings[@]}"; do
|
||||||
|
PATTERN="$PATTERN\|if $item"
|
||||||
|
done
|
||||||
|
find "$SRC_DIR" -type f -name "*.h" -exec grep -nw "$PATTERN" {} + || echo
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*) usage ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
Loading…
Add table
Reference in a new issue