Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f34a385166 | |||
| e367bdf3cc | |||
| 226160f639 | |||
| 0eeeee515e | |||
| 54d6283ac3 | |||
| 2e9dbe3f1d | |||
| d7cd7c6313 | |||
| df653d6ca4 | |||
| a53823646c | |||
| b330117a14 | |||
| d24db9c3cb | |||
| f55e560ac5 | |||
| 84ab54c4bc | |||
| 9333393a7b | |||
| cb83a258db | |||
| 6bdf479488 | |||
| 9c7ed0f59d | |||
| de46b8e817 | |||
| 3e8fe622a7 | |||
| 1c90b099d3 | |||
| e2a8f3154f | |||
| c0fb872d1a | |||
| 171a1d23e4 | |||
| 3d6a784e62 | |||
| 440ee4916d | |||
| 551f244dfd | |||
| ef14303c48 | |||
| b7021afff6 | |||
| bfc10723bc | |||
| 30482692c7 | |||
| 31463142e1 | |||
| bb836ed6c2 | |||
| f273ac446b | |||
| 3f725c979d | |||
| 2a5e6f98b6 | |||
| fff8e2026f | |||
| 5f9dba40a0 | |||
| 0a54ac63f0 | |||
| 94ca83a6ca | |||
| 2f88463203 | |||
| 11200714e8 | |||
| ac59b6eae5 | |||
| b389a72697 | |||
| b3f28d29c0 | |||
| 053f4e95d4 | |||
| 8ae7cfe96a | |||
| e157b3fa96 | |||
| 56e2dbc619 | |||
| a3ef2cc183 | |||
| 1e1b8ad33f | |||
| 91493fa39b | |||
| 973a65c4c5 | |||
| 8a017951aa | |||
| 776958c79d | |||
| 3656253262 | |||
| b6241e4148 | |||
| bfffafe68b | |||
| 3c6ef765af |
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
license_header = <<~EOF
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
EOF
|
||||
|
||||
print 'Getting branch changes...'
|
||||
branch_name = `git rev-parse --abbrev-ref HEAD`.chomp
|
||||
branch_commits = `git log #{branch_name} --not master --pretty=format:"%h"`.split("\n")
|
||||
branch_commit_range = "#{branch_commits[-1]}^..#{branch_commits[0]}"
|
||||
branch_changed_files = `git diff-tree --no-commit-id --name-only #{branch_commit_range} -r`.split("\n")
|
||||
puts 'done'
|
||||
|
||||
print 'Checking files...'
|
||||
issue_files = []
|
||||
branch_changed_files.each do |file_name|
|
||||
if file_name.end_with?('.cpp', '.h', '.kt', '.kts') and File.file?(file_name)
|
||||
file_content = File.read(file_name)
|
||||
if not file_content.start_with?(license_header)
|
||||
issue_files.push(file_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
puts 'done'
|
||||
|
||||
if issue_files.empty?
|
||||
puts "\nAll changed files have correct headers"
|
||||
exit 0
|
||||
end
|
||||
|
||||
puts <<-EOF
|
||||
|
||||
The following #{issue_files.length} files have incorrect license headers:
|
||||
#{issue_files.join("\n")}
|
||||
|
||||
The following license header should be added to the start of all offending files:
|
||||
=== BEGIN ===
|
||||
#{license_header}
|
||||
=== END ===
|
||||
|
||||
If some of the code in this PR is not being contributed by the original author, the files which have been exclusively changed by that code can be ignored.
|
||||
If this happens, this PR requirement can be bypassed once all other files are addressed.
|
||||
EOF
|
||||
|
||||
exit 1
|
||||
@@ -1,74 +1,152 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
HEADER="$(cat "$PWD/.ci/license/header.txt")"
|
||||
HEADER_HASH="$(cat "$PWD/.ci/license/header-hash.txt")"
|
||||
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
echo "Getting branch changes"
|
||||
# specify full path if dupes may exist
|
||||
EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake sse2neon.h renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder"
|
||||
|
||||
# BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||
# COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"`
|
||||
# RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}"
|
||||
# FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r`
|
||||
# license header constants, please change when needed :))))
|
||||
YEAR=2025
|
||||
HOLDER="Eden Emulator Project"
|
||||
LICENSE="GPL-3.0-or-later"
|
||||
|
||||
BASE=`git merge-base master HEAD`
|
||||
FILES=`git diff --name-only $BASE`
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [uc]
|
||||
Compares the current HEAD to the master branch to check for license
|
||||
header discrepancies. Each file changed in a branch MUST have a
|
||||
license header, and this script attempts to enforce that.
|
||||
|
||||
#FILES=$(git diff --name-only master)
|
||||
Options:
|
||||
-u, --update Fix license headers, if applicable;
|
||||
if the license header exists but has the incorrect
|
||||
year or is otherwise malformed, it will be fixed.
|
||||
|
||||
echo "Done"
|
||||
-c, --commit Commit changes to Git (requires --update)
|
||||
|
||||
Copyright $YEAR $HOLDER
|
||||
Licensed under $LICENSE
|
||||
|
||||
The following files/directories are marked as external
|
||||
and thus will not have license headers asserted:
|
||||
EOF
|
||||
|
||||
for file in $EXCLUDE_FILES; do
|
||||
echo "- $file"
|
||||
done
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
(-uc) UPDATE=true; COMMIT=true ;;
|
||||
(-u|--update) UPDATE=true ;;
|
||||
(-c|--commit) COMMIT=true ;;
|
||||
("$0") break ;;
|
||||
("") break ;;
|
||||
(*) usage ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# human-readable header string
|
||||
header() {
|
||||
header_line1 "$1"
|
||||
header_line2 "$1"
|
||||
}
|
||||
|
||||
header_line1() {
|
||||
echo "$1 SPDX-FileCopyrightText: Copyright $YEAR $HOLDER"
|
||||
}
|
||||
|
||||
header_line2() {
|
||||
echo "$1 SPDX-License-Identifier: $LICENSE"
|
||||
}
|
||||
|
||||
# PCRE header string
|
||||
pcre_header() {
|
||||
begin="$1"
|
||||
echo "(?s)$(header_line1 "$begin").*$(header_line2 "$begin")"
|
||||
}
|
||||
|
||||
check_header() {
|
||||
CONTENT="`head -n3 < $1`"
|
||||
case "$CONTENT" in
|
||||
"$HEADER"*) ;;
|
||||
*) BAD_FILES="$BAD_FILES $1" ;;
|
||||
esac
|
||||
begin="$1"
|
||||
file="$2"
|
||||
content="$(head -n5 < "$2")"
|
||||
|
||||
header="$(pcre_header "$begin")"
|
||||
|
||||
if ! echo "$content" | grep -Pzo "$header" > /dev/null; then
|
||||
# SRC_FILES is Kotlin/C++
|
||||
# OTHER_FILES is sh, CMake
|
||||
case "$begin" in
|
||||
"//")
|
||||
SRC_FILES="$SRC_FILES $file"
|
||||
;;
|
||||
"#")
|
||||
OTHER_FILES="$OTHER_FILES $file"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
check_cmake_header() {
|
||||
CONTENT="`head -n3 < $1`"
|
||||
BASE=$(git merge-base master HEAD)
|
||||
FILES=$(git diff --name-only "$BASE")
|
||||
|
||||
case "$CONTENT" in
|
||||
"$HEADER_HASH"*) ;;
|
||||
*)
|
||||
BAD_CMAKE="$BAD_CMAKE $1" ;;
|
||||
esac
|
||||
}
|
||||
for file in $FILES; do
|
||||
[ -f "$file" ] || continue
|
||||
|
||||
if [ `basename -- "$file"` = "CMakeLists.txt" ]; then
|
||||
check_cmake_header "$file"
|
||||
continue
|
||||
fi
|
||||
# skip files that are third party (crueter's CMake modules, sse2neon, etc)
|
||||
for pattern in $EXCLUDE_FILES; do
|
||||
case "$file" in
|
||||
*"$pattern"*)
|
||||
excluded=true
|
||||
break
|
||||
;;
|
||||
*)
|
||||
excluded=false
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
EXTENSION="${file##*.}"
|
||||
case "$EXTENSION" in
|
||||
kts|kt|cpp|h)
|
||||
check_header "$file"
|
||||
;;
|
||||
cmake)
|
||||
check_cmake_header "$file"
|
||||
;;
|
||||
[ "$excluded" = "true" ] && continue
|
||||
|
||||
case "$file" in
|
||||
*.cmake|*.sh|CMakeLists.txt)
|
||||
begin="#"
|
||||
;;
|
||||
*.kt*|*.cpp|*.h)
|
||||
begin="//"
|
||||
;;
|
||||
*)
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
check_header "$begin" "$file"
|
||||
done
|
||||
|
||||
if [ "$BAD_FILES" = "" ] && [ "$BAD_CMAKE" = "" ]; then
|
||||
echo
|
||||
echo "All good."
|
||||
if [ -z "$SRC_FILES" ] && [ -z "$OTHER_FILES" ]; then
|
||||
echo "-- All good."
|
||||
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$BAD_FILES" != "" ]; then
|
||||
echo "The following source files have incorrect license headers:"
|
||||
echo
|
||||
echo
|
||||
|
||||
for file in $BAD_FILES; do echo $file; done
|
||||
if [ "$SRC_FILES" != "" ]; then
|
||||
echo "-- The following source files have incorrect license headers:"
|
||||
|
||||
HEADER=$(header "//")
|
||||
|
||||
for file in $SRC_FILES; do echo "-- * $file"; done
|
||||
|
||||
cat << EOF
|
||||
|
||||
The following license header should be added to the start of all offending SOURCE files:
|
||||
-- The following license header should be added to the start of these offending files:
|
||||
|
||||
=== BEGIN ===
|
||||
$HEADER
|
||||
@@ -78,18 +156,19 @@ EOF
|
||||
|
||||
fi
|
||||
|
||||
if [ "$BAD_CMAKE" != "" ]; then
|
||||
echo "The following CMake files have incorrect license headers:"
|
||||
echo
|
||||
if [ "$OTHER_FILES" != "" ]; then
|
||||
echo "-- The following CMake and shell scripts have incorrect license headers:"
|
||||
|
||||
for file in $BAD_CMAKE; do echo $file; done
|
||||
HEADER=$(header "#")
|
||||
|
||||
for file in $OTHER_FILES; do echo "-- * $file"; done
|
||||
|
||||
cat << EOF
|
||||
|
||||
The following license header should be added to the start of all offending CMake files:
|
||||
-- The following license header should be added to the start of these offending files:
|
||||
|
||||
=== BEGIN ===
|
||||
$HEADER_HASH
|
||||
$HEADER
|
||||
=== END ===
|
||||
|
||||
EOF
|
||||
@@ -97,50 +176,76 @@ EOF
|
||||
fi
|
||||
|
||||
cat << EOF
|
||||
If some of the code in this PR is not being contributed by the original author,
|
||||
the files which have been exclusively changed by that code can be ignored.
|
||||
If this happens, this PR requirement can be bypassed once all other files are addressed.
|
||||
If some of the code in this PR is not being contributed by the original author,
|
||||
the files which have been exclusively changed by that code can be ignored.
|
||||
If this happens, this PR requirement can be bypassed once all other files are addressed.
|
||||
|
||||
EOF
|
||||
|
||||
if [ "$FIX" = "true" ]; then
|
||||
echo
|
||||
echo "FIX set to true. Fixing headers."
|
||||
echo
|
||||
if [ "$UPDATE" = "true" ]; then
|
||||
TMP_DIR=$(mktemp -d)
|
||||
echo "-- Fixing headers..."
|
||||
|
||||
for file in $BAD_FILES; do
|
||||
cat $file > $file.bak
|
||||
for file in $SRC_FILES $OTHER_FILES; do
|
||||
case $(basename -- "$file") in
|
||||
*.cmake|CMakeLists.txt)
|
||||
begin="#"
|
||||
shell="false"
|
||||
;;
|
||||
*.sh)
|
||||
begin="#"
|
||||
shell=true
|
||||
;;
|
||||
*.kt*|*.cpp|*.h)
|
||||
begin="//"
|
||||
shell="false"
|
||||
;;
|
||||
esac
|
||||
|
||||
cat .ci/license/header.txt > $file
|
||||
echo >> $file
|
||||
cat $file.bak >> $file
|
||||
# This is fun
|
||||
match="$begin SPDX-FileCopyrightText.*$HOLDER"
|
||||
|
||||
rm $file.bak
|
||||
# basically if the copyright holder is already defined we can just replace the year
|
||||
if head -n5 < "$file" | grep -e "$match" >/dev/null; then
|
||||
replace=$(header_line1 "$begin")
|
||||
sed "s|$match|$replace|" "$file" > "$file".bak
|
||||
mv "$file".bak "$file"
|
||||
else
|
||||
header "$begin" > "$TMP_DIR"/header
|
||||
|
||||
git add $file
|
||||
done
|
||||
if [ "$shell" = "true" ]; then
|
||||
# grab shebang
|
||||
head -n1 "$file" > "$TMP_DIR/shebang"
|
||||
echo >> "$TMP_DIR/shebang"
|
||||
|
||||
for file in $BAD_CMAKE; do
|
||||
cat $file > $file.bak
|
||||
# remove shebang
|
||||
sed '1d' "$file" > "$file".bak
|
||||
mv "$file".bak "$file"
|
||||
|
||||
cat .ci/license/header-hash.txt > $file
|
||||
echo >> $file
|
||||
cat $file.bak >> $file
|
||||
# add to header
|
||||
cat "$TMP_DIR"/shebang "$TMP_DIR"/header > "$TMP_DIR"/new-header
|
||||
mv "$TMP_DIR"/new-header "$TMP_DIR"/header
|
||||
else
|
||||
echo >> "$TMP_DIR/header"
|
||||
fi
|
||||
|
||||
rm $file.bak
|
||||
cat "$TMP_DIR"/header "$file" > "$file".bak
|
||||
mv "$file".bak "$file"
|
||||
fi
|
||||
|
||||
git add $file
|
||||
done
|
||||
echo "License headers fixed."
|
||||
[ "$shell" = "true" ] && chmod a+x "$file"
|
||||
[ "$COMMIT" = "true" ] && git add "$file"
|
||||
done
|
||||
|
||||
if [ "$COMMIT" = "true" ]; then
|
||||
echo
|
||||
echo "COMMIT set to true. Committing changes."
|
||||
echo
|
||||
|
||||
git commit -m "Fix license headers"
|
||||
|
||||
echo "Changes committed. You may now push."
|
||||
fi
|
||||
else
|
||||
exit 1
|
||||
echo "-- Done"
|
||||
fi
|
||||
|
||||
if [ "$COMMIT" = "true" ]; then
|
||||
echo "-- Committing changes"
|
||||
|
||||
git commit -m "Fix license headers"
|
||||
|
||||
echo "-- Changes committed. You may now push."
|
||||
fi
|
||||
|
||||
[ -d "$TMP_DIR" ] && rm -rf "$TMP_DIR"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -1,2 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -10,6 +10,12 @@ doc-build/
|
||||
AppDir/
|
||||
uruntime
|
||||
|
||||
# dtrace and ktrace stuffs
|
||||
[dk]trace-out/
|
||||
[dk]trace.out
|
||||
*.core
|
||||
log.txt
|
||||
|
||||
# Generated source files
|
||||
src/common/scm_rev.cpp
|
||||
dist/english_plurals/generated_en.ts
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/src/catch2/matchers/catch_matchers_floating_point.cpp b/src/catch2/matchers/catch_matchers_floating_point.cpp
|
||||
index fc7b444..0e1a3c2 100644
|
||||
--- a/src/catch2/matchers/catch_matchers_floating_point.cpp
|
||||
+++ b/src/catch2/matchers/catch_matchers_floating_point.cpp
|
||||
@@ -5,6 +5,7 @@
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
+#include <catch2/internal/catch_polyfills.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
#include <catch2/internal/catch_enforce.hpp>
|
||||
#include <catch2/internal/catch_polyfills.hpp>
|
||||
@@ -0,0 +1,25 @@
|
||||
diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
|
||||
index a9a50b2..56e681b 100644
|
||||
--- a/libusb/os/netbsd_usb.c
|
||||
+++ b/libusb/os/netbsd_usb.c
|
||||
@@ -580,6 +580,20 @@ _access_endpoint(struct libusb_transfer *transfer)
|
||||
return hpriv->endpoints[endpt];
|
||||
}
|
||||
|
||||
+void usbi_get_monotonic_time(struct timespec *tp) {
|
||||
+ struct timeval tv;
|
||||
+ gettimeofday(&tv, NULL);
|
||||
+ tp->tv_sec = tv.tv_sec;
|
||||
+ tp->tv_nsec = tv.tv_usec * 1000ull;
|
||||
+}
|
||||
+
|
||||
+void usbi_get_real_time(struct timespec *tp) {
|
||||
+ struct timeval tv;
|
||||
+ gettimeofday(&tv, NULL);
|
||||
+ tp->tv_sec = tv.tv_sec;
|
||||
+ tp->tv_nsec = tv.tv_usec * 1000ull;
|
||||
+}
|
||||
+
|
||||
int
|
||||
_sync_gen_transfer(struct usbi_transfer *itransfer)
|
||||
{
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/library/aesni.h b/library/aesni.h
|
||||
index 754c984c79..59e27afd3e 100644
|
||||
--- a/library/aesni.h
|
||||
+++ b/library/aesni.h
|
||||
@@ -35,7 +35,7 @@
|
||||
/* GCC-like compilers: currently, we only support intrinsics if the requisite
|
||||
* target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
|
||||
* or `clang -maes -mpclmul`). */
|
||||
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)
|
||||
+#if defined(__GNUC__) || defined(__clang__)
|
||||
#define MBEDTLS_AESNI_HAVE_INTRINSICS
|
||||
#endif
|
||||
/* For 32-bit, we only support intrinsics */
|
||||
@@ -0,0 +1,22 @@
|
||||
diff --git a/library/aesni.c b/library/aesni.c
|
||||
index 2857068..3e104ab 100644
|
||||
--- a/library/aesni.c
|
||||
+++ b/library/aesni.c
|
||||
@@ -31,16 +31,14 @@
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
-#if defined(MBEDTLS_ARCH_IS_X86)
|
||||
#if defined(MBEDTLS_COMPILER_IS_GCC)
|
||||
#pragma GCC push_options
|
||||
#pragma GCC target ("pclmul,sse2,aes")
|
||||
#define MBEDTLS_POP_TARGET_PRAGMA
|
||||
-#elif defined(__clang__) && (__clang_major__ >= 5)
|
||||
+#elif defined(__clang__)
|
||||
#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function)
|
||||
#define MBEDTLS_POP_TARGET_PRAGMA
|
||||
#endif
|
||||
-#endif
|
||||
|
||||
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
|
||||
/*
|
||||
@@ -0,0 +1,55 @@
|
||||
diff --git a/include/mcl/assert.hpp b/include/mcl/assert.hpp
|
||||
index f77dbe7..9ec0b9c 100644
|
||||
--- a/include/mcl/assert.hpp
|
||||
+++ b/include/mcl/assert.hpp
|
||||
@@ -23,8 +23,11 @@ template<typename... Ts>
|
||||
|
||||
} // namespace mcl::detail
|
||||
|
||||
+#ifndef UNREACHABLE
|
||||
#define UNREACHABLE() ASSERT_FALSE("Unreachable code!")
|
||||
+#endif
|
||||
|
||||
+#ifndef ASSERT
|
||||
#define ASSERT(expr) \
|
||||
[&] { \
|
||||
if (std::is_constant_evaluated()) { \
|
||||
@@ -37,7 +40,9 @@ template<typename... Ts>
|
||||
} \
|
||||
} \
|
||||
}()
|
||||
+#endif
|
||||
|
||||
+#ifndef ASSERT_MSG
|
||||
#define ASSERT_MSG(expr, ...) \
|
||||
[&] { \
|
||||
if (std::is_constant_evaluated()) { \
|
||||
@@ -50,13 +55,24 @@ template<typename... Ts>
|
||||
} \
|
||||
} \
|
||||
}()
|
||||
+#endif
|
||||
|
||||
+#ifndef ASSERT_FALSE
|
||||
#define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false", __VA_ARGS__)
|
||||
+#endif
|
||||
|
||||
#if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS)
|
||||
-# define DEBUG_ASSERT(expr) ASSUME(expr)
|
||||
-# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
|
||||
+# ifndef DEBUG_ASSERT
|
||||
+# define DEBUG_ASSERT(expr) ASSUME(expr)
|
||||
+# endif
|
||||
+# ifndef DEBUG_ASSERT_MSG
|
||||
+# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr)
|
||||
+# endif
|
||||
#else
|
||||
-# define DEBUG_ASSERT(expr) ASSERT(expr)
|
||||
-# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
|
||||
+# ifndef DEBUG_ASSERT
|
||||
+# define DEBUG_ASSERT(expr) ASSERT(expr)
|
||||
+# endif
|
||||
+# ifndef DEBUG_ASSERT_MSG
|
||||
+# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__)
|
||||
+# endif
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
|
||||
index eb4e69e..3155805 100644
|
||||
--- a/external/CMakeLists.txt
|
||||
+++ b/external/CMakeLists.txt
|
||||
@@ -72,7 +72,8 @@ if (SPIRV_TOOLS_USE_MIMALLOC)
|
||||
pop_variable(MI_BUILD_TESTS)
|
||||
endif()
|
||||
|
||||
-if (DEFINED SPIRV-Headers_SOURCE_DIR)
|
||||
+# NetBSD doesn't have SPIRV-Headers readily available on system
|
||||
+if (DEFINED SPIRV-Headers_SOURCE_DIR AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
|
||||
# This allows flexible position of the SPIRV-Headers repo.
|
||||
set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
|
||||
else()
|
||||
@@ -13,12 +13,13 @@ Copyright: yuzu Emulator Project
|
||||
License: GPL-2.0-or-later
|
||||
|
||||
Files: dist/qt_themes/default/icons/256x256/eden.png
|
||||
dist/qt_themes/default/icons/256x256/eden_named.png
|
||||
dist/yuzu.bmp
|
||||
dist/yuzu.icns
|
||||
dist/eden.icns
|
||||
dist/eden.ico
|
||||
dist/eden.svg
|
||||
Copyright: yuzu Emulator Project
|
||||
License: GPL-2.0-or-later
|
||||
dist/dev.eden_emu.eden.svg
|
||||
Copyright: 2025 Eden Emulator Project
|
||||
License: GPL-3.0-or-later
|
||||
|
||||
Files: dist/qt_themes/qdarkstyle*/LICENSE.*
|
||||
dist/qt_themes/qdarkstyle*/style.qrc
|
||||
@@ -155,3 +156,39 @@ License: BSD-3-Clause
|
||||
Files: src/android/app/debug.keystore
|
||||
Copyright: 2023 yuzu Emulator Project
|
||||
License: GPL-3.0-or-later
|
||||
|
||||
Files: dist/qt_themes/colorful/icons/48x48/user-trash.png
|
||||
dist/qt_themes/colorful/icons/48x48/upload.png
|
||||
dist/qt_themes/colorful/icons/48x48/download.png
|
||||
Copyright: 2014 Uri Herrera
|
||||
1996-2025 KDE Software Foundation
|
||||
License: LGPL-2.0-or-later
|
||||
|
||||
Files: dist/qt_themes/default/icons/48x48/user-trash.png
|
||||
dist/qt_themes/default/icons/48x48/upload.png
|
||||
dist/qt_themes/default/icons/48x48/download.png
|
||||
dist/qt_themes/default_dark/icons/48x48/user-trash.png
|
||||
dist/qt_themes/default_dark/icons/48x48/upload.png
|
||||
dist/qt_themes/default_dark/icons/48x48/download.png
|
||||
Copyright: 2025 Fonticons, Inc.
|
||||
License: CC-BY-4.0
|
||||
Comment: All of these icons have been modified by crueter <crueter@crueter.xyz>
|
||||
|
||||
Files: CMakeModules/CPM.cmake
|
||||
Copyright: 2019-2023 Lars Melchior
|
||||
License: MIT
|
||||
|
||||
Files: CMakeModules/CPMUtil.cmake
|
||||
CMakeModules/CPM.cmake
|
||||
CMakeModules/GetSCMRev.cmake
|
||||
CMakeModules/DetectArchitecture.cmake
|
||||
tools/cpm/*
|
||||
tools/update-cpm.sh
|
||||
tools/shellcheck.sh
|
||||
docs/CPMUtil.md
|
||||
**cpmfile.json
|
||||
Copyright: 2025 crueter <crueter@crueter.xyz>
|
||||
License: GPL-3.0-or-later
|
||||
Comment: CPM.cmake has had additional modifications from crueter to better work with CPMUtil
|
||||
https://git.crueter.xyz/CMake/CPMUtil
|
||||
https://git.crueter.xyz/CMake/Modules
|
||||
|
||||
@@ -11,6 +11,8 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
set(PLATFORM_FREEBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set(PLATFORM_OPENBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
|
||||
set(PLATFORM_NETBSD ON)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(PLATFORM_LINUX ON)
|
||||
endif()
|
||||
@@ -41,8 +43,7 @@ if (PLATFORM_SUN)
|
||||
list(APPEND CMAKE_PREFIX_PATH "/usr/lib/qt/6.6/lib/amd64/cmake")
|
||||
list(APPEND CMAKE_MODULE_PATH "/usr/lib/qt/6.6/lib/amd64/cmake")
|
||||
|
||||
# amazing
|
||||
# absolutely incredible
|
||||
# Amazing - absolutely incredible
|
||||
list(APPEND CMAKE_PREFIX_PATH "/usr/lib/amd64/cmake")
|
||||
list(APPEND CMAKE_MODULE_PATH "/usr/lib/amd64/cmake")
|
||||
|
||||
@@ -52,6 +53,10 @@ if (PLATFORM_SUN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
|
||||
endif()
|
||||
if (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Needed for FFmpeg w/ VAAPI and DRM
|
||||
@@ -59,6 +64,15 @@ if (PLATFORM_OPENBSD)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/X11R6/include")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/X11R6/include")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/X11R6/lib")
|
||||
elseif (PLATFORM_NETBSD)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/X11R7/include")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/X11R7/include")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/X11R7/lib")
|
||||
endif()
|
||||
|
||||
# NetBSD: Fun for the whole family!
|
||||
if (PLATFORM_NETBSD)
|
||||
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:/usr/pkg/lib/ffmpeg7/pkgconfig")
|
||||
endif()
|
||||
|
||||
# Detect current compilation architecture and create standard definitions
|
||||
@@ -145,6 +159,7 @@ endif()
|
||||
|
||||
if (PLATFORM_FREEBSD)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
|
||||
|
||||
endif()
|
||||
|
||||
# Set bundled sdl2/qt as dependent options.
|
||||
@@ -260,7 +275,11 @@ if (ENABLE_WEB_SERVICE)
|
||||
endif()
|
||||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
||||
if (ENABLE_OPENSSL)
|
||||
cmake_dependent_option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON)
|
||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
||||
if (EXT_DEFAULT OR PLATFORM_SUN)
|
||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
||||
endif()
|
||||
option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL})
|
||||
endif()
|
||||
|
||||
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
||||
@@ -347,7 +366,7 @@ if (YUZU_ROOM)
|
||||
add_compile_definitions(YUZU_ROOM)
|
||||
endif()
|
||||
|
||||
if (ANDROID OR PLATFORM_FREEBSD OR PLATFORM_OPENBSD OR PLATFORM_SUN OR APPLE)
|
||||
if ((ANDROID OR APPLE OR UNIX) AND (NOT PLATFORM_LINUX OR ANDROID) AND NOT WIN32)
|
||||
if(CXX_APPLE OR CXX_CLANG)
|
||||
# libc++ has stop_token and jthread as experimental
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||
@@ -573,11 +592,12 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(httplib)
|
||||
if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER)
|
||||
# Workaround: httplib will kill itself if you attempt to do a find_package propagation
|
||||
# find_package(httplib CONFIG)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER)
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(cpp-jwt)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This is a slightly modified version of CPM.cmake
|
||||
|
||||
# CPM.cmake - CMake's missing package manager
|
||||
# ===========================================
|
||||
# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.
|
||||
|
||||
@@ -325,7 +325,7 @@ function(AddPackage)
|
||||
${pkg_git_url}/archive/refs/tags/${PKG_ARGS_TAG}.tar.gz)
|
||||
endif()
|
||||
elseif (DEFINED PKG_ARGS_SHA)
|
||||
set(pkg_url "${pkg_git_url}/archive/${PKG_ARGS_SHA}.zip")
|
||||
set(pkg_url "${pkg_git_url}/archive/${PKG_ARGS_SHA}.tar.gz")
|
||||
else()
|
||||
if (DEFINED PKG_ARGS_BRANCH)
|
||||
set(PKG_BRANCH ${PKG_ARGS_BRANCH})
|
||||
@@ -335,7 +335,7 @@ function(AddPackage)
|
||||
set(PKG_BRANCH master)
|
||||
endif()
|
||||
|
||||
set(pkg_url ${pkg_git_url}/archive/refs/heads/${PKG_BRANCH}.zip)
|
||||
set(pkg_url ${pkg_git_url}/archive/refs/heads/${PKG_BRANCH}.tar.gz)
|
||||
endif()
|
||||
else()
|
||||
cpm_utils_message(FATAL_ERROR ${PKG_ARGS_NAME} "No URL or repository defined")
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
|
||||
find_package(DiscordRPC CONFIG QUIET)
|
||||
|
||||
find_library(DiscordRPC_LIBRARY discord-rpc)
|
||||
if (NOT DiscordRPC_FOUND)
|
||||
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
|
||||
find_library(DiscordRPC_LIBRARY discord-rpc)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DiscordRPC
|
||||
REQUIRED_VARS
|
||||
DiscordRPC_LIBRARY
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DiscordRPC
|
||||
REQUIRED_VARS
|
||||
DiscordRPC_LIBRARY
|
||||
DiscordRPC_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
|
||||
add_library(DiscordRPC::discord-rpc UNKNOWN IMPORTED)
|
||||
set_target_properties(DiscordRPC::discord-rpc PROPERTIES
|
||||
IMPORTED_LOCATION "${DiscordRPC_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${DiscordRPC_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
DiscordRPC_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
|
||||
add_library(DiscordRPC::discord-rpc UNKNOWN IMPORTED)
|
||||
set_target_properties(DiscordRPC::discord-rpc PROPERTIES
|
||||
IMPORTED_LOCATION "${DiscordRPC_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${DiscordRPC_INCLUDE_DIR}"
|
||||
DiscordRPC_LIBRARY
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
DiscordRPC_INCLUDE_DIR
|
||||
DiscordRPC_LIBRARY
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"name": "lz4",
|
||||
"repo": "lz4/lz4",
|
||||
"sha": "ebb370ca83",
|
||||
"hash": "43600e87b35256005c0f2498fa56a77de6783937ba4cfce38c099f27c03188d097863e8a50c5779ca0a7c63c29c4f7ed0ae526ec798c1fd2e3736861b62e0a37",
|
||||
"hash": "35c21a5d9cfb5bbf314a5321d02b36819491d2ee3cf8007030ca09d13ca4dae672247b7aeab553e973093604fc48221cb03dc92197c6efe8fc3746891363fdab",
|
||||
"source_subdir": "build/cmake"
|
||||
},
|
||||
"nlohmann": {
|
||||
@@ -62,7 +62,7 @@
|
||||
"zstd": {
|
||||
"repo": "facebook/zstd",
|
||||
"sha": "b8d6101fba",
|
||||
"hash": "a6c8e5272214fd3e65e03ae4fc375f452bd2f646623886664ee23e239e35751cfc842db4d34a84a8039d89fc8f76556121f2a4ae350d017bdff5e22150f9c3de",
|
||||
"hash": "cc5ad4b119a9c2ea57f0b71eeff01113bb506e0d17000159c5409cb8236d22e38c52d5e9e97e7947a4bf1b2dfc44b6c503ab2d9aedbd59458435c6a2849cb029",
|
||||
"version": "1.5",
|
||||
"source_subdir": "build/cmake",
|
||||
"find_args": "MODULE",
|
||||
@@ -74,7 +74,7 @@
|
||||
"package": "Opus",
|
||||
"repo": "crueter/opus",
|
||||
"sha": "ab19c44fad",
|
||||
"hash": "79d0d015b19e74ce6076197fc32b86fe91d724a0b5a79e86adfc4bdcb946ece384e252adbbf742b74d03040913b70bb0e9556eafa59ef20e42d2f3f4d6f2859a",
|
||||
"hash": "d632e8f83c5d3245db404bcb637113f9860bf16331498ba2c8e77979d1febee6b52d8b1da448e7d54eeac373e912cd55e3e300fc6c242244923323280dc43fbe",
|
||||
"version": "1.3",
|
||||
"find_args": "MODULE",
|
||||
"options": [
|
||||
@@ -84,7 +84,7 @@
|
||||
"boost_headers": {
|
||||
"repo": "boostorg/headers",
|
||||
"sha": "95930ca8f5",
|
||||
"hash": "d1dece16f3b209109de02123c537bfe1adf07a62b16c166367e7e5d62e0f7c323bf804c89b3192dd6871bc58a9d879d25a1cc3f7b9da0e497cf266f165816e2a",
|
||||
"hash": "8a07d7a6f0065587d3005a83481a794704ae22e773b9f336fbd89ed230aaa7b4c86c03edcbae30bba8b3e20839c3131eaa2dceac037ef811533ef4eadc53b15b",
|
||||
"bundled": true
|
||||
},
|
||||
"llvm-mingw": {
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@@ -18,6 +18,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
|
||||
@@ -11,6 +11,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../colorful/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../colorful/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../colorful/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
||||
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
|
||||
|
||||
@@ -14,6 +14,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 853 B |
|
After Width: | Height: | Size: 820 B |
|
After Width: | Height: | Size: 584 B |
@@ -2,6 +2,12 @@ QAbstractSpinBox {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QComboBox {
|
||||
padding: 0px 4px 0px 4px;
|
||||
min-width: 60px;
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
color: #959595;
|
||||
border: 1px solid transparent;
|
||||
|
||||
@@ -13,6 +13,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../colorful/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../colorful/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../colorful/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
||||
|
||||
@@ -6,6 +6,12 @@ QAbstractSpinBox {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QComboBox {
|
||||
padding: 0px 4px 0px 4px;
|
||||
min-width: 60px;
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
color: #959595;
|
||||
border: 1px solid transparent;
|
||||
|
||||
|
After Width: | Height: | Size: 883 B |
|
After Width: | Height: | Size: 853 B |
|
After Width: | Height: | Size: 584 B |
@@ -9,6 +9,9 @@
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<file alias="48x48/bad_folder.png">../qdarkstyle/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../qdarkstyle/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../qdarkstyle/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../qdarkstyle/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../qdarkstyle/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../qdarkstyle/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">../qdarkstyle/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../qdarkstyle/icons/48x48/sd_card.png</file>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# CPMUtil
|
||||
|
||||
CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful utility functions to make dependency management a piece of cake.
|
||||
|
||||
See more in [its repository](https://git.crueter.xyz/CMake/CPMUtil)
|
||||
|
||||
Eden-specific options:
|
||||
|
||||
- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing
|
||||
* If this is `OFF`, required system dependencies will be searched via `find_package`, although most externals use CPM regardless.
|
||||
|
||||
## Tooling
|
||||
|
||||
See the [tooling docs](../tools/cpm)
|
||||
@@ -0,0 +1,17 @@
|
||||
# AddPackage
|
||||
|
||||
- `VERSION` (required): The version to get (the tag will be `v${VERSION}`)
|
||||
- `NAME` (required): Name used within the artifacts
|
||||
- `REPO` (required): CI repository, e.g. `crueter-ci/OpenSSL`
|
||||
- `PACKAGE` (required): `find_package` package name
|
||||
- `EXTENSION`: Artifact extension (default `tar.zst`)
|
||||
- `MIN_VERSION`: Minimum version for `find_package`. Only used if platform does not support this package as a bundled artifact
|
||||
- `DISABLED_PLATFORMS`: List of platforms that lack artifacts for this package. Options:
|
||||
* `windows-amd64`
|
||||
* `windows-arm64`
|
||||
* `android`
|
||||
* `solaris-amd64`
|
||||
* `freebsd-amd64`
|
||||
* `linux-amd64`
|
||||
* `linux-aarch64`
|
||||
* `macos-universal`
|
||||
@@ -0,0 +1,17 @@
|
||||
# AddPackage
|
||||
|
||||
- `VERSION` (required): The version to get (the tag will be `v${VERSION}`)
|
||||
- `NAME` (required): Name used within the artifacts
|
||||
- `REPO` (required): CI repository, e.g. `crueter-ci/OpenSSL`
|
||||
- `PACKAGE` (required): `find_package` package name
|
||||
- `EXTENSION`: Artifact extension (default `tar.zst`)
|
||||
- `MIN_VERSION`: Minimum version for `find_package`. Only used if platform does not support this package as a bundled artifact
|
||||
- `DISABLED_PLATFORMS`: List of platforms that lack artifacts for this package. Options:
|
||||
* `windows-amd64`
|
||||
* `windows-arm64`
|
||||
* `android`
|
||||
* `solaris-amd64`
|
||||
* `freebsd-amd64`
|
||||
* `linux-amd64`
|
||||
* `linux-aarch64`
|
||||
* `macos-universal`
|
||||
@@ -0,0 +1,104 @@
|
||||
# AddJsonPackage
|
||||
|
||||
In each directory that utilizes `CPMUtil`, there must be a `cpmfile.json` that defines dependencies in a similar manner to the individual calls.
|
||||
|
||||
The cpmfile is an object of objects, with each sub-object being named according to the package's identifier, e.g. `openssl`, which can then be fetched with `AddJsonPackage(<identifier>)`. Options are designed to map closely to the argument names, and are always strings unless otherwise specified.
|
||||
<!-- TOC -->
|
||||
- [Options](#options)
|
||||
- [Examples](#examples)
|
||||
<!-- /TOC -->
|
||||
|
||||
## Options
|
||||
|
||||
- `package` -> `NAME` (`PACKAGE` for CI), defaults to the object key
|
||||
- `repo` -> `REPO`
|
||||
- `version` -> `VERSION`
|
||||
- `ci` (bool)
|
||||
|
||||
If `ci` is `false`:
|
||||
|
||||
- `hash` -> `HASH`
|
||||
- `hash_suffix` -> `HASH_SUFFIX`
|
||||
- `sha` -> `SHA`
|
||||
- `key` -> `KEY`
|
||||
- `tag` -> `TAG`
|
||||
* If the tag contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified
|
||||
- `url` -> `URL`
|
||||
- `artifact` -> `ARTIFACT`
|
||||
* If the artifact contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified
|
||||
* If the artifact contains `%TAG%`, that part will be replaced by the `tag` (with its replacement already done)
|
||||
- `git_version` -> `GIT_VERSION`
|
||||
- `git_host` -> `GIT_HOST`
|
||||
- `source_subdir` -> `SOURCE_SUBDIR`
|
||||
- `bundled` -> `BUNDLED_PACKAGE`
|
||||
- `find_args` -> `FIND_PACKAGE_ARGUMENTS`
|
||||
- `download_only` -> `DOWNLOAD_ONLY`
|
||||
- `patches` -> `PATCHES` (array)
|
||||
- `options` -> `OPTIONS` (array)
|
||||
- `skip_updates`: Tells `check-updates.sh` to not check for new updates on this package.
|
||||
|
||||
Other arguments aren't currently supported. If you wish to add them, see the `AddJsonPackage` function in `CMakeModules/CPMUtil.cmake`.
|
||||
|
||||
If `ci` is `true`:
|
||||
|
||||
- `name` -> `NAME`, defaults to the object key
|
||||
- `extension` -> `EXTENSION`, defaults to `tar.zst`
|
||||
- `min_version` -> `MIN_VERSION`
|
||||
- `extension` -> `EXTENSION`
|
||||
- `disabled_platforms` -> `DISABLED_PLATFORMS` (array)
|
||||
|
||||
## Examples
|
||||
|
||||
In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discord-rpc (sha + options + patches).
|
||||
|
||||
```json
|
||||
{
|
||||
"openssl": {
|
||||
"ci": true,
|
||||
"package": "OpenSSL",
|
||||
"name": "openssl",
|
||||
"repo": "crueter-ci/OpenSSL",
|
||||
"version": "3.6.0",
|
||||
"min_version": "1.1.1",
|
||||
"disabled_platforms": [
|
||||
"macos-universal"
|
||||
]
|
||||
},
|
||||
"boost": {
|
||||
"package": "Boost",
|
||||
"repo": "boostorg/boost",
|
||||
"tag": "boost-%VERSION%",
|
||||
"artifact": "%TAG%-cmake.7z",
|
||||
"hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01",
|
||||
"git_version": "1.88.0",
|
||||
"version": "1.57"
|
||||
},
|
||||
"opus": {
|
||||
"package": "Opus",
|
||||
"repo": "xiph/opus",
|
||||
"sha": "5ded705cf4",
|
||||
"hash": "0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203",
|
||||
"version": "1.3",
|
||||
"find_args": "MODULE",
|
||||
"options": [
|
||||
"OPUS_BUILD_TESTING OFF",
|
||||
"OPUS_BUILD_PROGRAMS OFF",
|
||||
"OPUS_INSTALL_PKG_CONFIG_MODULE OFF",
|
||||
"OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF"
|
||||
]
|
||||
},
|
||||
"discord-rpc": {
|
||||
"repo": "discord/discord-rpc",
|
||||
"sha": "963aa9f3e5",
|
||||
"hash": "386e1344e9a666d730f2d335ee3aef1fd05b1039febefd51aa751b705009cc764411397f3ca08dffd46205c72f75b235c870c737b2091a4ed0c3b061f5919bde",
|
||||
"options": [
|
||||
"BUILD_EXAMPLES OFF"
|
||||
],
|
||||
"patches": [
|
||||
"0001-cmake-version.patch",
|
||||
"0002-no-clang-format.patch",
|
||||
"0003-fix-cpp17.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,116 @@
|
||||
# `AddPackage`
|
||||
|
||||
<!-- TOC -->
|
||||
- [Identification/Fetching](#identificationfetching)
|
||||
- [Hashing](#hashing)
|
||||
- [Other Options](#other-options)
|
||||
- [Extra Variables](#extra-variables)
|
||||
- [System/Bundled Packages](#systembundled-packages)
|
||||
- [Identification](#identification)
|
||||
<!-- /TOC -->
|
||||
|
||||
## Identification/Fetching
|
||||
|
||||
- `NAME` (required): The package name (must be the same as the `find_package` name if applicable)
|
||||
- `VERSION`: The minimum version of this package that can be used on the system
|
||||
- `GIT_VERSION`: The "version" found within git
|
||||
- `URL`: The URL to fetch.
|
||||
- `REPO`: The repo to use (`owner/repo`).
|
||||
- `GIT_HOST`: The Git host to use
|
||||
* Defaults to `github.com`. Do not include the protocol, as HTTPS is enforced.
|
||||
- `TAG`: The tag to fetch, if applicable.
|
||||
- `ARTIFACT`: The name of the artifact, if applicable.
|
||||
- `SHA`: Commit sha to fetch, if applicable.
|
||||
- `BRANCH`: Branch to fetch, if applicable.
|
||||
|
||||
The following configurations are supported, in descending order of precedence:
|
||||
|
||||
- `URL`: Bare URL download, useful for custom artifacts
|
||||
* If this is set, `GIT_URL` or `REPO` should be set to allow the dependency viewer to link to the project's Git repository.
|
||||
* If this is NOT set, `REPO` must be defined.
|
||||
- `REPO + TAG + ARTIFACT`: GitHub release artifact
|
||||
* The final download URL will be `https://github.com/${REPO}/releases/download/${TAG}/${ARTIFACT}`
|
||||
* Useful for prebuilt libraries and prefetched archives
|
||||
- `REPO + TAG`: GitHub tag archive
|
||||
* The final download URL will be `https://github.com/${REPO}/archive/refs/tags/${TAG}.tar.gz`
|
||||
* Useful for pinning to a specific tag, better for build identification
|
||||
- `REPO + SHA`: GitHub commit archive
|
||||
* The final download URL will be `https://github.com/${REPO}/archive/${SHA}.zip`
|
||||
* Useful for pinning to a specific commit
|
||||
- `REPO + BRANCH`: GitHub branch archive
|
||||
* The final download URL will be `https://github.com/${REPO}/archive/refs/heads/${BRANCH}.zip`
|
||||
* Generally not recommended unless the branch is frozen
|
||||
- `REPO`: GitHub master archive
|
||||
* The final download URL will be `https://github.com/${REPO}/archive/refs/heads/master.zip`
|
||||
* Generally not recommended unless the project is dead
|
||||
|
||||
## Hashing
|
||||
|
||||
Hashing is used for verifying downloads. It's highly recommended to use these.
|
||||
|
||||
- `HASH_ALGO` (default `SHA512`): Hash algorithm to use
|
||||
|
||||
Hashing strategies, descending order of precedence:
|
||||
|
||||
- `HASH`: Bare hash verification, useful for static downloads e.g. commit archives
|
||||
- `HASH_SUFFIX`: Download the hash as `${DOWNLOAD_URL}.${HASH_SUFFIX}`
|
||||
* The downloaded hash *must* match the hash algorithm and contain nothing but the hash; no filenames or extra content.
|
||||
- `HASH_URL`: Download the hash from a separate URL
|
||||
|
||||
## Other Options
|
||||
|
||||
- `KEY`: Custom cache key to use (stored as `.cache/cpm/${packagename_lower}/${key}`)
|
||||
* Default is based on, in descending order of precedence:
|
||||
- First 4 characters of the sha
|
||||
- `GIT_VERSION`
|
||||
- Tag
|
||||
- `VERSION`
|
||||
- Otherwise, CPM defaults will be used. This is not recommended as it doesn't produce reproducible caches
|
||||
- `DOWNLOAD_ONLY`: Whether or not to configure the downloaded package via CMake
|
||||
* Useful to turn `OFF` if the project doesn't use CMake
|
||||
- `SOURCE_SUBDIR`: Subdirectory of the project containing a CMakeLists.txt file
|
||||
- `FIND_PACKAGE_ARGUMENTS`: Arguments to pass to the `find_package` call
|
||||
- `BUNDLED_PACKAGE`: Set to `ON` to default to the bundled package
|
||||
- `FORCE_BUNDLED_PACKAGE`: Set to `ON` to force the usage of the bundled package, regardless of CPMUTIL_FORCE_SYSTEM or `<package>_FORCE_SYSTEM`
|
||||
- `OPTIONS`: Options to pass to the configuration of the package
|
||||
- `PATCHES`: Patches to apply to the package, stored in `.patch/${packagename_lower}/0001-patch-name.patch` and so on
|
||||
- Other arguments can be passed to CPM as well
|
||||
|
||||
## Extra Variables
|
||||
|
||||
For each added package, users may additionally force usage of the system/bundled package.
|
||||
|
||||
- `${package}_FORCE_SYSTEM`: Require the package to be installed on the system
|
||||
- `${package}_FORCE_BUNDLED`: Force the package to be fetched and use the bundled version
|
||||
|
||||
## System/Bundled Packages
|
||||
|
||||
Descending order of precedence:
|
||||
- If `${package}_FORCE_SYSTEM` is true, requires the package to be on the system
|
||||
- If `${package}_FORCE_BUNDLED` is true, forcefully uses the bundled package
|
||||
- If `CPMUTIL_FORCE_SYSTEM` is true, requires the package to be on the system
|
||||
- If `CPMUTIL_FORCE_BUNDLED` is true, forcefully uses the bundled package
|
||||
- If the `BUNDLED_PACKAGE` argument is true, forcefully uses the bundled package
|
||||
- Otherwise, CPM will search for the package first, and if not found, will use the bundled package
|
||||
|
||||
## Identification
|
||||
|
||||
All dependencies must be identifiable in some way for usage in the dependency viewer. Lists are provided in descending order of precedence.
|
||||
|
||||
URLs:
|
||||
|
||||
- `GIT_URL`
|
||||
- `REPO` as a Git repository
|
||||
* You may optionally specify `GIT_HOST` to use a custom host, e.g. `GIT_HOST git.crueter.xyz`. Note that the git host MUST be GitHub-like in its artifact/archive downloads, e.g. Forgejo
|
||||
* If `GIT_HOST` is unspecified, defaults to `github.com`
|
||||
- `URL`
|
||||
|
||||
Versions (bundled):
|
||||
|
||||
- `SHA`
|
||||
- `GIT_VERSION`
|
||||
- `VERSION`
|
||||
- `TAG`
|
||||
- "unknown"
|
||||
|
||||
If the package is a system package, AddPackage will attempt to determine the package version and append ` (system)` to the identifier. Otherwise, it will be marked as `unknown (system)`
|
||||
@@ -0,0 +1,46 @@
|
||||
# CPMUtil
|
||||
|
||||
CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful utility functions to make dependency management a piece of cake.
|
||||
|
||||
Global Options:
|
||||
|
||||
- `CPMUTIL_FORCE_SYSTEM` (default `OFF`): Require all CPM dependencies to use system packages. NOT RECOMMENDED!
|
||||
* You may optionally override this (section)
|
||||
- `CPMUTIL_FORCE_BUNDLED` (default `ON` on MSVC and Android, `OFF` elsewhere): Require all CPM dependencies to use bundled packages.
|
||||
|
||||
You are highly encouraged to read AddPackage first, even if you plan to only interact with CPMUtil via `AddJsonPackage`.
|
||||
|
||||
<!-- TOC -->
|
||||
- [AddPackage](#addpackage)
|
||||
- [AddCIPackage](#addcipackage)
|
||||
- [AddJsonPackage](#addjsonpackage)
|
||||
- [Lists](#lists)
|
||||
<!-- /TOC -->
|
||||
|
||||
## AddPackage
|
||||
|
||||
The core of CPMUtil is the [`AddPackage`](./AddPackage.md) function. [`AddPackage`](./AddPackage.md) itself is fully CMake-based, and largely serves as an interface between CPM and the rest of CPMUtil.
|
||||
|
||||
## AddCIPackage
|
||||
|
||||
[`AddCIPackage`](./AddCIPackage.md) adds a package that follows [crueter's CI repository spec](https://github.com/crueter-ci).
|
||||
|
||||
## AddJsonPackage
|
||||
|
||||
[`AddJsonPackage`](./AddJsonPackage.md) is the recommended method of usage for CPMUtil.
|
||||
|
||||
## Lists
|
||||
|
||||
CPMUtil will create three lists of dependencies where `AddPackage` or similar was used. Each is in order of addition.
|
||||
|
||||
- `CPM_PACKAGE_NAMES`: The names of packages included by CPMUtil
|
||||
- `CPM_PACKAGE_URLS`: The URLs to project/repo pages of packages
|
||||
- `CPM_PACKAGE_SHAS`: Short version identifiers for each package
|
||||
* If the package was included as a system package, ` (system)` is appended thereafter
|
||||
* Packages whose versions can't be deduced will be left as `unknown`.
|
||||
|
||||
For an example of how this might be implemented in an application, see Eden's implementation:
|
||||
|
||||
- [`dep_hashes.h.in`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/src/dep_hashes.h.in)
|
||||
- [`GenerateDepHashes.cmake`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CMakeModules/GenerateDepHashes.cmake)
|
||||
- [`deps_dialog.cpp`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/src/yuzu/deps_dialog.cpp)
|
||||
@@ -45,8 +45,18 @@ export LIBGL_ALWAYS_SOFTWARE=1
|
||||
|
||||
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
|
||||
|
||||
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`.
|
||||
|
||||
If clang has errors, try using `g++-11`.
|
||||
|
||||
## FreeBSD
|
||||
|
||||
Eden is not currently available as a port on FreeBSD, though it is in the works. For now, the recommended method of usage is to compile it yourself.
|
||||
|
||||
The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_BUNDLED_OPENSSL=ON` to your CMake configure command.
|
||||
The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_BUNDLED_OPENSSL=ON` to your CMake configure command.
|
||||
|
||||
## NetBSD
|
||||
|
||||
System provides a default `g++-10` which doesn't support the current C++ codebase; install `clang-19` with `pkgin install clang-19`. Then build with `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -B build`.
|
||||
|
||||
Make may error out when generating C++ headers of SPIRV shaders, hence it's recommended to use `gmake` over the default system one.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Cross Compile
|
||||
|
||||
## ARM64
|
||||
|
||||
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
|
||||
|
||||
- Install QEMU: `sudo pkg install qemu`
|
||||
- Download Debian 13: `wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso`
|
||||
- Create a system disk: `qemu-img create -f qcow2 debian-13-arm64-ci.qcow2 30G`
|
||||
- Run the VM: `qemu-system-aarch64 -M virt -m 2G -cpu max -bios /usr/local/share/qemu/edk2-aarch64-code.fd -drive if=none,file=debian-13.0.0-arm64-netinst.iso,format=raw,id=cdrom -device scsi-cd,drive=cdrom -drive if=none,file=debian-13-arm64-ci.qcow2,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 -device virtio-gpu-pci -device usb-ehci -device usb-kbd -device intel-hda -device hda-output -nic user,model=virtio-net-pci`
|
||||
@@ -0,0 +1,68 @@
|
||||
# Debug Guidelines
|
||||
|
||||
## Debugging (host code)
|
||||
|
||||
Ignoring SIGSEGV when debugging in host:
|
||||
|
||||
- **gdb**: `handle all nostop pass`.
|
||||
- **lldb**: `pro hand -p true -s false -n false SIGSEGV`.
|
||||
|
||||
## Debugging (guest code)
|
||||
|
||||
### gdb
|
||||
|
||||
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run eden normally to see where it is)> -d -g <path to game>`
|
||||
|
||||
Then hook up an aarch64-gdb (use `yay aarch64-gdb` or `sudo pkg in arch64-gdb` to install)
|
||||
Then type `target remote localhost:1234` and type `c` (for continue) - and then if it crashes just do a `bt` (backtrace) and `layout asm`.
|
||||
|
||||
### gdb cheatsheet
|
||||
|
||||
- `mo <cmd>`: Monitor commands, `get info`, `get fastmem` and `get mappings` are available. Type `mo help` for more info.
|
||||
- `detach`: Detach from remote (i.e restarting the emulator).
|
||||
- `c`: Continue
|
||||
- `p <expr>`: Print variable, `p/x <expr>` for hexadecimal.
|
||||
- `r`: Run
|
||||
- `bt`: Print backtrace
|
||||
- `info threads`: Print all active threads
|
||||
- `thread <number>`: Switch to the given thread (see `info threads`)
|
||||
- `layout asm`: Display in assembly mode (TUI)
|
||||
- `si`: Step assembly instruction
|
||||
- `s` or `step`: Step over LINE OF CODE (not assembly)
|
||||
- `display <expr>`: Display variable each step.
|
||||
- `n`: Next (skips over call frame of a function)
|
||||
- `frame <number>`: Switches to the given frame (from `bt`)
|
||||
- `br <expr>`: Set breakpoint at `<expr>`.
|
||||
- `delete`: Deletes all breakpoints.
|
||||
- `catch throw`: Breakpoint at throw. Can also use `br __cxa_throw`
|
||||
- `br _mesa_error`: Break on mesa errors (set environment variable `MESA_DEBUG=1` beforehand), see [MESA_DEBUG](https://mesa-docs.readthedocs.io/en/latest/debugging.html).
|
||||
|
||||
Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference of a pointer) or `*(1 + var)` (computed expression).
|
||||
|
||||
For more information type `info gdb` and read [the man page](https://man7.org/linux/man-pages/man1/gdb.1.html).
|
||||
|
||||
## Simple checklist for debugging black screens using Renderdoc
|
||||
|
||||
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it [here](https://renderdoc.org).
|
||||
|
||||
Before using renderdoc to diagnose issues, it is always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, renderdoc can help debug validation errors if you do have them.
|
||||
|
||||
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
|
||||
Here is a short checklist of items to look at to make sure are appropriate:
|
||||
* Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
|
||||
* Vertex buffers are bound
|
||||
* vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
|
||||
* Any bound push constants and descriptors have the right data - including:
|
||||
* Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
|
||||
* Pipeline state is correct
|
||||
* viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
|
||||
* Fill mode matches expected - usually solid
|
||||
* Culling mode makes sense - commonly back or none
|
||||
* The winding direction is correct - typically CCW (counter clockwise)
|
||||
* Scissor region is correct - usually same as viewport's x,y,width, &height
|
||||
* Blend state is correct
|
||||
* Depth state is correct - typically enabled with Function set to Less than or Equal
|
||||
* Swapchain images are bound when rendering to the swapchain
|
||||
* Image being rendered to is the same as the one being presented when rendering to the swapchain
|
||||
|
||||
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.
|
||||
@@ -102,7 +102,7 @@ sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glsl
|
||||
<summary>Ubuntu, Debian, Mint Linux</summary>
|
||||
|
||||
```sh
|
||||
sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2t64 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev vulkan-utility-libraries-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev
|
||||
sudo apt-get install autoconf cmake g++ gcc git glslang-tools libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev libboost-dev libboost-fiber-dev libboost-context-dev libsdl2-dev libopus-dev libasound2t64 vulkan-utility-libraries-dev
|
||||
```
|
||||
|
||||
* Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
|
||||
@@ -110,18 +110,28 @@ sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2t64 libb
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Fedora Linux</summary>
|
||||
<summary>AlmaLinux, Fedora, Red Hat Linux</summary>
|
||||
|
||||
Fedora:
|
||||
```sh
|
||||
sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel
|
||||
sudo dnf install autoconf cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel boost jq
|
||||
```
|
||||
|
||||
* Force system libraries via CMake arguments:
|
||||
* SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF`
|
||||
* FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF`
|
||||
* [RPM Fusion](https://rpmfusion.org/) is required for `ffmpeg-devel`
|
||||
AlmaLinux (use `YUZU_USE_CPM=ON`):
|
||||
```sh
|
||||
# vvv - Only if RPMfusion is not installed or EPEL isn't either
|
||||
sudo dnf install epel-release dnf-utils
|
||||
# (run rpmfusion installation afterwards)
|
||||
# vvv - This will work for most systems
|
||||
sudo dnf install autoconf cmake libtool libudev cmake gcc gcc-c++ qt6-qtbase-devel zlib-devel openssl-devel boost SDL2 ffmpeg-devel libdrm glslang jq patch
|
||||
# Qt6 private GUI must be taken from CRB repos
|
||||
sudo dnf config-manager --enable crb
|
||||
sudo dnf install qt6-qtbase-private-devel
|
||||
```
|
||||
|
||||
* [RPM Fusion](https://rpmfusion.org/Configuration) is required for `ffmpeg-devel`
|
||||
* Fedora 32 or later is required.
|
||||
* Fedora 36+ users with GCC 12 need Clang and should configure CMake with:
|
||||
* Fedora 36+ users with GCC 12 need Clang and should configure CMake with: `cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -B build`
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -145,44 +155,43 @@ brew install molten-vk vulkan-loader
|
||||
<details>
|
||||
<summary>FreeBSD</summary>
|
||||
|
||||
```
|
||||
devel/cmake
|
||||
devel/sdl20
|
||||
devel/boost-libs
|
||||
devel/catch2
|
||||
devel/libfmt
|
||||
devel/nlohmann-json
|
||||
devel/ninja
|
||||
devel/nasm
|
||||
devel/autoconf
|
||||
devel/pkgconf
|
||||
devel/qt6-base
|
||||
|
||||
net/enet
|
||||
|
||||
multimedia/ffnvcodec-headers
|
||||
multimedia/ffmpeg
|
||||
|
||||
audio/opus
|
||||
|
||||
archivers/liblz4
|
||||
|
||||
lang/gcc12
|
||||
|
||||
graphics/glslang
|
||||
graphics/vulkan-utility-libraries
|
||||
```
|
||||
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/jwt-cpp devel/unordered-dense devel/zydis`
|
||||
|
||||
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>NetBSD</summary>
|
||||
|
||||
Install `pkgin` if not already `pkg_add pkgin`, see also the general [pkgsrc guide](https://www.netbsd.org/docs/pkgsrc/using.html). For NetBSD 10.1 provide `cat 'PKG_PATH="https://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/x86_64/10.0_2025Q3/All/"' >/etc/pkg_install.conf`. If `pkgin` is taking too much time consider adding the following to `/etc/rc.conf`:
|
||||
```
|
||||
ip6addrctl=YES
|
||||
ip6addrctl_policy=ipv4_prefer
|
||||
```
|
||||
|
||||
For NetBSD +10.1: `pkgin install git cmake boost fmtlib SDL2 catch2 libjwt spirv-headers ffmpeg7 libva nlohmann-json jq libopus qt6 mbedtls3 cpp-httplib lz4 vulkan-headers nasm autoconf enet pkg-config libusb1`.
|
||||
|
||||
glslang is not available on NetBSD, to circumvent this simply build glslang by yourself:
|
||||
```sh
|
||||
pkgin python313
|
||||
git clone https://github.com/KhronosGroup/glslang.git
|
||||
cd glslang
|
||||
python3.13 ./update_glslang_sources.py
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -- -j`nproc`
|
||||
cmake --install build
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>OpenBSD</summary>
|
||||
|
||||
```sh
|
||||
pkg_add -u
|
||||
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1.1.0.27
|
||||
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1-1.0.27
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -210,6 +219,16 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l
|
||||
* `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc`
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>RedoxOS</summary>
|
||||
|
||||
```sh
|
||||
sudo pkg update && sudo pkg install git cmake
|
||||
sudo pkg install ffmpeg6 sdl2 zlib llvm18
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## All Done
|
||||
|
||||
You may now return to the **[root build guide](Build.md)**.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Guidelines
|
||||
# Development guidelines
|
||||
|
||||
## License Headers
|
||||
All commits must have proper license header accreditation.
|
||||
@@ -6,19 +6,21 @@ All commits must have proper license header accreditation.
|
||||
You can easily add all necessary license headers by running:
|
||||
```sh
|
||||
git fetch origin master:master
|
||||
FIX=true COMMIT=true .ci/license-header.sh
|
||||
.ci/license-header.sh -u -c
|
||||
git push
|
||||
```
|
||||
|
||||
Alternatively, you may omit `COMMIT=true` and do an amend commit:
|
||||
Alternatively, you may omit `-c` and do an amend commit:
|
||||
```sh
|
||||
git fetch origin master:master
|
||||
FIX=true .ci/license-header.sh
|
||||
.ci/license-header.sh
|
||||
git commit --amend -a --no-edit
|
||||
```
|
||||
|
||||
If the work is licensed/vendored from other people or projects, you may omit the license headers. Additionally, if you wish to retain authorship over a piece of code, you may attribute it to yourself; however, the code may be changed at any given point and brought under the attribution of Eden.
|
||||
|
||||
For more information on the license header script, run `.ci/license-header.sh -h`.
|
||||
|
||||
## Pull Requests
|
||||
Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed:
|
||||
```
|
||||
@@ -101,49 +103,6 @@ May not be used but worth mentioning nonethless:
|
||||
- OGG files: Use [OptiVorbis](https://github.com/OptiVorbis/OptiVorbis).
|
||||
- Video files: Use ffmpeg, preferably re-encode as AV1.
|
||||
|
||||
# Debugging
|
||||
|
||||
## Debugging (host code)
|
||||
|
||||
Ignoring SIGSEGV when debugging in host:
|
||||
|
||||
- **gdb**: `handle all nostop pass`.
|
||||
- **lldb**: `pro hand -p true -s false -n false SIGSEGV`.
|
||||
|
||||
## Debugging (guest code)
|
||||
|
||||
### gdb
|
||||
|
||||
Run `./build/bin/eden-cli -c <path to your config file (see logs where you run eden normally to see where it is)> -d -g <path to game>`
|
||||
|
||||
Then hook up an aarch64-gdb (use `yay aarch64-gdb` or `sudo pkg in arch64-gdb` to install)
|
||||
Then type `target remote localhost:1234` and type `c` (for continue) - and then if it crashes just do a `bt` (backtrace) and `layout asm`.
|
||||
|
||||
### gdb cheatsheet
|
||||
|
||||
- `mo <cmd>`: Monitor commands, `get info`, `get fastmem` and `get mappings` are available. Type `mo help` for more info.
|
||||
- `detach`: Detach from remote (i.e restarting the emulator).
|
||||
- `c`: Continue
|
||||
- `p <expr>`: Print variable, `p/x <expr>` for hexadecimal.
|
||||
- `r`: Run
|
||||
- `bt`: Print backtrace
|
||||
- `info threads`: Print all active threads
|
||||
- `thread <number>`: Switch to the given thread (see `info threads`)
|
||||
- `layout asm`: Display in assembly mode (TUI)
|
||||
- `si`: Step assembly instruction
|
||||
- `s` or `step`: Step over LINE OF CODE (not assembly)
|
||||
- `display <expr>`: Display variable each step.
|
||||
- `n`: Next (skips over call frame of a function)
|
||||
- `frame <number>`: Switches to the given frame (from `bt`)
|
||||
- `br <expr>`: Set breakpoint at `<expr>`.
|
||||
- `delete`: Deletes all breakpoints.
|
||||
- `catch throw`: Breakpoint at throw. Can also use `br __cxa_throw`
|
||||
- `br _mesa_error`: Break on mesa errors (set environment variable `MESA_DEBUG=1` beforehand), see [MESA_DEBUG](https://mesa-docs.readthedocs.io/en/latest/debugging.html).
|
||||
|
||||
Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference of a pointer) or `*(1 + var)` (computed expression).
|
||||
|
||||
For more information type `info gdb` and read [the man page](https://man7.org/linux/man-pages/man1/gdb.1.html).
|
||||
|
||||
# Bisecting older commits
|
||||
|
||||
Since going into the past can be tricky (especially due to the dependencies from the project being lost thru time). This should "restore" the URLs for the respective submodules.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Eden Build Documentation
|
||||
|
||||
This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](CPM.md), and more.
|
||||
This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](./CPMUtil), and more.
|
||||
|
||||
- **[General Build Instructions](Build.md)**
|
||||
- **[Cross Compiling](CrossCompile.md)**
|
||||
- **[Development Guidelines](Development.md)**
|
||||
- **[Dependencies](Deps.md)**
|
||||
- **[Debug Guidelines](./Debug.md)**
|
||||
- **[CPM - CMake Package Manager](CPMUtil.md)**
|
||||
- **[Platform-Specific Caveats](Caveats.md)**
|
||||
- **[User Handbook](User.md)**
|
||||
- **[User Handbook](User.md)**
|
||||
|
||||
@@ -8,3 +8,4 @@ This handbook is primarily aimed at the end-user - baking useful knowledge for e
|
||||
- **[Audio](user/Audio.md)**
|
||||
- **[Graphics](user/Graphics.md)**
|
||||
- **[Platforms and Architectures](user/Architectures.md)**
|
||||
- **[Testing](user/Testing.md)**
|
||||
|
||||
@@ -35,6 +35,8 @@ Eden by default will be cloned into -
|
||||
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
|
||||
7. You can pass extra variables to cmake via `-PYUZU_ANDROID_ARGS="-D..."`
|
||||
|
||||
Remember to have a Java SDK installed if not already, on Debian and similar this is done with `sudo apt install openjdk-17-jdk`.
|
||||
|
||||
### Script
|
||||
A convenience script for building is provided in `.ci/android/build.sh`. The built APK can be put into an `artifacts` directory via `.ci/android/package.sh`. On Windows, these must be done in the Git Bash or MinGW terminal.
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ The vast majority of Eden's testing is done on Windows, Linux, and Android. Howe
|
||||
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- OpenIndiana (Solaris)
|
||||
- macOS
|
||||
|
||||
@@ -127,6 +128,6 @@ AMD GPU support on these platforms is limited or nonexistent.
|
||||
|
||||
## VMs
|
||||
|
||||
Eden "can" run in a VM, but only with the software renderer, *unless* you create a hardware-accelerated KVM with GPU passthrough. If you *really* want to do this and don't have a spare GPU lying around, RX 570 and 580 GPUs are extremely cheap on the black market and are powerful enough to run most commercial games at 60fps.
|
||||
Eden "can" run in a VM, but only with the software renderer, *unless* you create a hardware-accelerated KVM with GPU passthrough. If you *really* want to do this and don't have a spare GPU lying around, RX 570 and 580 GPUs are extremely cheap on the black market and are powerful enough to run most commercial games at 60 FPS.
|
||||
|
||||
Some users and developers have had success using a pure OpenGL-accelerated KVM on Linux with a Windows VM, but this is ridiculously tedious to set up. You're probably better off dual-booting.
|
||||
@@ -0,0 +1,32 @@
|
||||
# User Handbook - Testing
|
||||
|
||||
While this is mainly aimed for testers - normal users can benefit from these guidelines to make their life easier when trying to outline and/or report an issue.
|
||||
|
||||
## How to Test a PR Against the Based Master When Issues Arise
|
||||
|
||||
When you're testing a pull request (PR) and encounter unexpected behavior, it's important to determine whether the issue was introduced by the PR or if it already exists in the base code. To do this, compare the behavior against the based master branch.
|
||||
|
||||
Even before an issue occurs, it is best practice to keep the same settings and delete the shader cache. Using an already made shader cache can make the PR look like it is having a regression in some rare cases.
|
||||
|
||||
### What to Do When Something Seems Off
|
||||
If you notice something odd during testing:
|
||||
- Reproduce the issue using the based master branch.
|
||||
- Observe whether the same behavior occurs.
|
||||
|
||||
### Two Possible Outcomes
|
||||
- If the issue exists in the based master: This means the problem was already present before the PR. The PR most likely did not introduce the regression.
|
||||
- If the issue does not exist in the based master: This suggests the PR most likely introduced the regression and needs further investigation.
|
||||
|
||||
### Report your findings
|
||||
When you report your results:
|
||||
- Clearly state whether the behavior was observed in the based master.
|
||||
- Indicate whether the result is good (expected behavior) or bad (unexpected or broken behavior). Without mentioning if your post/report/log is good or bad it may confuse the Developer of the PR.
|
||||
- Example:
|
||||
```
|
||||
1. "Tested on based master — issue not present. Bad result for PR, likely regression introduced."
|
||||
2. "Tested on based master — issue already present. Good result for PR, not a regression."
|
||||
```
|
||||
|
||||
This approach helps maintain clarity and accountability in the testing process and ensures regressions are caught and addressed efficiently. If the behavior seems normal for a certain game/feature then it may not be always required to check against the based master.
|
||||
|
||||
If a master build for the PR' based master does not exist. It will be helpful to just test past and future builds nearby. That would help with gathering more information about the problem.
|
||||
@@ -0,0 +1,8 @@
|
||||
# User Handbook - Third party tools and extras
|
||||
|
||||
The Eden emulator by itself lacks some functionality - or otherwise requires external files (such as packaging) to operate correctly in a given OS. Addendum to that some repositories provide nightly or specialised builds of the emulator.
|
||||
|
||||
While most of the links mentioned in this guide are relatively "safe"; we urge users to use their due diligence and appropriatedly verify the integrity of all files downloaded and ensure they're not compromised.
|
||||
|
||||
- [Nightly Eden builds](https://github.com/pflyly/eden-nightly)
|
||||
- [NixOS Eden Flake](https://github.com/Grantimatter/eden-flake)
|
||||
@@ -29,13 +29,14 @@
|
||||
"repo": "yhirose/cpp-httplib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "b364500f76e2ecb0fe21b032d831272e3f1dfeea71af74e325f8fc4ce9dcdb3c941b97a5b422bdeafb9facd058597b90f8bfc284fb9afe3c33fefa15dd5a010b",
|
||||
"git_version": "0.26.0"
|
||||
"git_version": "0.26.0",
|
||||
"find_args": "MODULE GLOBAL"
|
||||
},
|
||||
"cpp-jwt": {
|
||||
"version": "1.4",
|
||||
"repo": "crueter/cpp-jwt",
|
||||
"sha": "9eaea6328f",
|
||||
"hash": "e237d92c59ebbf0dc8ac0bae3bc80340e1e9cf430e1c1c9638443001118e16de2b3e9036ac4b98105427667b0386d97831415170b68c432438dcad9ef8052de7",
|
||||
"hash": "35b0b2bfb143585c7b2bd6dc6ca7df5ae5c6e2681000b2ebca077b0ac4bc1e6b6afbe1ce8e47f6d2edad12fcc6404f677acc2ad205661d819b8821ce6f4823fd",
|
||||
"find_args": "CONFIG",
|
||||
"options": [
|
||||
"CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF"
|
||||
@@ -45,9 +46,10 @@
|
||||
"package": "xbyak",
|
||||
"repo": "herumi/xbyak",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "e84992c65ad62c577e2746ec5180132fd2875166d1e6b1521a0ff619787e1645792fe5f6a858fe94ed66f297912b6a6b89a509b5d5f5e81a2db1dd7e6790b1f5",
|
||||
"hash": "b40dade90fb0e46a2bd52934f7ce461e37be931b571e58cbe2203bc08ed5b54c7ff1a29026c74c7f9805e4e3f6c9636deca528e6b4a8093ce7eae145218599f1",
|
||||
"git_version": "7.29",
|
||||
"bundled": true,
|
||||
"git_version": "7.30"
|
||||
"skip_updates": true
|
||||
},
|
||||
"xbyak": {
|
||||
"package": "xbyak",
|
||||
@@ -68,7 +70,7 @@
|
||||
"libadrenotools": {
|
||||
"repo": "bylaws/libadrenotools",
|
||||
"sha": "8fae8ce254",
|
||||
"hash": "c74fa855f0edebbf25c9bce40b00966daa2447bfc5e15f0cf1a95f86cbf70fc6b02590707edbde16328a0a2a4fb9a1fc419d2dfc22a4a4150971be91892d4edb",
|
||||
"hash": "db4a74ce15559c75e01d1868a90701519b655d77f2a343bbee283a42f8332dc9046960fb022dc969f205e457348a3f99cb8be6e1cd91264d2ae1235294b9f9b2",
|
||||
"patches": [
|
||||
"0001-linkerns-cpm.patch"
|
||||
]
|
||||
@@ -96,7 +98,11 @@
|
||||
"version": "3",
|
||||
"git_version": "3.6.4",
|
||||
"artifact": "%TAG%.tar.bz2",
|
||||
"skip_updates": true
|
||||
"skip_updates": true,
|
||||
"patches": [
|
||||
"0002-aesni-fix.patch",
|
||||
"0003-aesni-fix.patch"
|
||||
]
|
||||
},
|
||||
"enet": {
|
||||
"repo": "lsalzman/enet",
|
||||
@@ -119,17 +125,20 @@
|
||||
"package": "SPIRV-Tools",
|
||||
"repo": "crueter/SPIRV-Tools",
|
||||
"sha": "2fa2d44485",
|
||||
"hash": "45b198be1d09974ccb2438e8bfa5683f23a0421b058297c28eacfd77e454ec2cf87e77850eddd202efff34b004d8d6b4d12e9615e59bd72be904c196f5eb2169",
|
||||
"hash": "3124bbddf7bd44f11445edeca6786b5bba9fb314f27dc087d0bbd9951b0936884ece2b9b40b75cfc8e31ab10ba55854e73aa63df835c40423b1c81dd47b1437d",
|
||||
"git_version": "2025.4",
|
||||
"options": [
|
||||
"SPIRV_SKIP_EXECUTABLES ON"
|
||||
],
|
||||
"patches": [
|
||||
"0001-netbsd-fix.patch"
|
||||
]
|
||||
},
|
||||
"spirv-headers": {
|
||||
"package": "SPIRV-Headers",
|
||||
"repo": "KhronosGroup/SPIRV-Headers",
|
||||
"sha": "01e0577914",
|
||||
"hash": "d0f905311faf7d743de686fdf241dc4cb0a4f08e2184f5a3b3b2946e680db3cd89eeb72954eafe6fa457f93550e27d516575c8709cb134d8aecc0b43064636ce",
|
||||
"hash": "e2b90e95b6f492e640cd27c090d7072f0d03c8fc7382be67cbe176fc8f3fdd78b59f5f0b906198e09808fde645427f409cb9ab8fe4843de7f7dc5b510d454a0a",
|
||||
"options": [
|
||||
"SPIRV_WERROR OFF"
|
||||
]
|
||||
@@ -137,7 +146,7 @@
|
||||
"cubeb": {
|
||||
"repo": "mozilla/cubeb",
|
||||
"sha": "fa02160712",
|
||||
"hash": "82d808356752e4064de48c8fecbe7856715ade1e76b53937116bf07129fc1cc5b3de5e4b408de3cd000187ba8dc32ca4109661cb7e0355a52e54bd81b9be1c61",
|
||||
"hash": "8a4bcb2f83ba590f52c66626e895304a73eb61928dbc57777e1822e55378e3568366f17f9da4b80036cc2ef4ea9723c32abf6e7d9bbe00fb03654f0991596ab0",
|
||||
"find_args": "CONFIG",
|
||||
"options": [
|
||||
"USE_SANITIZERS OFF",
|
||||
@@ -163,13 +172,16 @@
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "a95495142f915d6e9c2a23e80fe360343e9097680066a2f9d3037a070ba5f81ee5559a0407cc9e972dc2afae325873f1fc7ea07a64012c0f01aac6e549f03e3f",
|
||||
"version": "3.0.1",
|
||||
"git_version": "3.11.0"
|
||||
"git_version": "3.11.0",
|
||||
"patches": [
|
||||
"0001-solaris-isnan-fix.patch"
|
||||
]
|
||||
},
|
||||
"discord-rpc": {
|
||||
"package": "DiscordRPC",
|
||||
"repo": "eden-emulator/discord-rpc",
|
||||
"sha": "1cf7772bb6",
|
||||
"hash": "e9b35e6f2c075823257bcd59f06fe7bb2ccce1976f44818d2e28810435ef79c712a3c4f20f40da41f691342a4058cf86b078eb7f9d9e4dae83c0547c21ec4f97",
|
||||
"hash": "9a6c35887dcacceb4ba1bf3141edb73b05b2abc719a8d81dad9cb9dd5b039ce203946787335d9d738af669c10cf2534638b645635a22096fc28dcae2475e0cbe",
|
||||
"find_args": "MODULE"
|
||||
},
|
||||
"simpleini": {
|
||||
@@ -194,7 +206,7 @@
|
||||
"package": "SDL2",
|
||||
"repo": "libsdl-org/SDL",
|
||||
"sha": "cc016b0046",
|
||||
"hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b",
|
||||
"hash": "b8d9873446cdb922387471df9968e078714683046674ef0d0edddf8e25da65a539a3bae83d635496b970237f90b07b36a69f8d7855d450de59311d6d6e8c3dbc",
|
||||
"key": "steamdeck",
|
||||
"bundled": true,
|
||||
"skip_updates": "true"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"ffmpeg": {
|
||||
"repo": "FFmpeg/FFmpeg",
|
||||
"sha": "c2184b65d2",
|
||||
"hash": "2a89d664119debbb3c006ab1c48d5d7f26e889f4a65ad2e25c8b0503308295123d5a9c5c78bf683aef5ff09acef8c3fc2837f22d3e8c611528b933bf03bcdd97",
|
||||
"hash": "007b1ccdd4d3ea3324835258d9a255103253bd66edb442b12d9c60dca85149cad52136a3b3120e5094115b6a3d9e80eeacbf9c07e5ffafc9ac459614d5fa3b22",
|
||||
"bundled": true
|
||||
},
|
||||
"ffmpeg-ci": {
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "98c5f7940ff06b25c9aa65aa98e23de4c79a4c1067595f4c73cc145af23a1c286639e1ba11185cd91bab702081f307b973f08a4c9746576dc8d01b3620a3aeb5",
|
||||
"find_args": "MODULE",
|
||||
"git_version": "1.0.29"
|
||||
"git_version": "1.0.29",
|
||||
"patches": [
|
||||
"0001-netbsd-gettime.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,17 +35,14 @@ endif()
|
||||
|
||||
if(NOT YUZU_TZDB_PATH STREQUAL "")
|
||||
set(NX_TZDB_BASE_DIR "${YUZU_TZDB_PATH}")
|
||||
set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo")
|
||||
elseif (MSVC)
|
||||
# TODO(crueter): This is a terrible solution, but MSVC fails to link without it
|
||||
# Need to investigate further but I still can't reproduce...
|
||||
elseif (MSVC AND NOT CXX_CLANG AND YUZU_ENABLE_LTO)
|
||||
# TODO(crueter): boot up the windows vm
|
||||
set(NX_TZDB_VERSION "250725")
|
||||
set(NX_TZDB_ARCHIVE "${CPM_SOURCE_CACHE}/nx_tzdb/${NX_TZDB_VERSION}.zip")
|
||||
|
||||
set(NX_TZDB_BASE_DIR "${CPM_SOURCE_CACHE}/nx_tzdb/tz")
|
||||
set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo")
|
||||
|
||||
set(NX_TZDB_DOWNLOAD_URL "https://github.com/crueter/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
||||
set(NX_TZDB_DOWNLOAD_URL "https://git.crueter.xyz/misc/tzdb_to_nx/releases/download/${NX_TZDB_VERSION}/${NX_TZDB_VERSION}.zip")
|
||||
|
||||
message(STATUS "Downloading time zone data from ${NX_TZDB_DOWNLOAD_URL}...")
|
||||
file(DOWNLOAD ${NX_TZDB_DOWNLOAD_URL} ${NX_TZDB_ARCHIVE}
|
||||
@@ -65,14 +62,11 @@ else()
|
||||
message(STATUS "Downloading time zone data...")
|
||||
AddJsonPackage(tzdb)
|
||||
|
||||
target_include_directories(nx_tzdb
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
INTERFACE ${NX_TZDB_INCLUDE_DIR})
|
||||
|
||||
set(NX_TZDB_BASE_DIR "${CPM_SOURCE_CACHE}/nx_tzdb")
|
||||
set(NX_TZDB_TZ_DIR "${nx_tzdb_SOURCE_DIR}")
|
||||
set(NX_TZDB_BASE_DIR "${nx_tzdb_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo")
|
||||
|
||||
target_include_directories(nx_tzdb
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
INTERFACE ${NX_TZDB_INCLUDE_DIR})
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"package": "nx_tzdb",
|
||||
"repo": "misc/tzdb_to_nx",
|
||||
"git_host": "git.crueter.xyz",
|
||||
"artifact": "%VERSION%.zip",
|
||||
"artifact": "%VERSION%.tar.gz",
|
||||
"tag": "%VERSION%",
|
||||
"hash": "8f60b4b29f285e39c0443f3d5572a73780f3dbfcfd5b35004451fadad77f3a215b2e2aa8d0fffe7e348e2a7b0660882b35228b6178dda8804a14ce44509fd2ca",
|
||||
"version": "250725"
|
||||
"hash": "87abb2aeca716d5d77b05317086dbc2f8acfc2f3f76ce4778345ee3df19973e6cd8ecbf16cfab5ad94c9636a6c44fd3588f9aadd3cba89403cfd56c8bec645c5",
|
||||
"version": "091025"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#define RENDERDOC_CC __cdecl
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__)
|
||||
#define RENDERDOC_CC
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#define RENDERDOC_CC
|
||||
#else
|
||||
#error "Unknown platform"
|
||||
|
||||
@@ -58,8 +58,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "dev.eden.eden_emulator"
|
||||
|
||||
minSdk = 28
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionName = getGitVersion()
|
||||
|
||||
|
||||
@@ -206,6 +206,17 @@ object NativeLibrary {
|
||||
ErrorUnknown
|
||||
}
|
||||
|
||||
/**
|
||||
* playtime tracking
|
||||
*/
|
||||
external fun playTimeManagerInit()
|
||||
external fun playTimeManagerStart()
|
||||
external fun playTimeManagerStop()
|
||||
external fun playTimeManagerGetPlayTime(programId: String): Long
|
||||
external fun playTimeManagerGetCurrentTitleId(): Long
|
||||
external fun playTimeManagerResetProgramPlayTime(programId: String)
|
||||
external fun playTimeManagerSetPlayTime(programId: String, playTimeSeconds: Long)
|
||||
|
||||
var coreErrorAlertResult = false
|
||||
val coreErrorAlertLock = Object()
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ class YuzuApplication : Application() {
|
||||
application = this
|
||||
documentsTree = DocumentsTree()
|
||||
DirectoryInitialization.start()
|
||||
NativeLibrary.playTimeManagerInit()
|
||||
GpuDriverHelper.initializeDriverParameters()
|
||||
NativeInput.reloadInputDevices()
|
||||
NativeLibrary.logDeviceInfo()
|
||||
|
||||
@@ -61,6 +61,7 @@ import org.yuzu.yuzu_emu.utils.ThemeHelper
|
||||
import java.text.NumberFormat
|
||||
import kotlin.math.roundToInt
|
||||
import org.yuzu.yuzu_emu.utils.ForegroundService
|
||||
import androidx.core.os.BundleCompat
|
||||
|
||||
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
private lateinit var binding: ActivityEmulationBinding
|
||||
@@ -202,6 +203,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
stopForegroundService(this)
|
||||
NativeLibrary.playTimeManagerStop()
|
||||
|
||||
}
|
||||
|
||||
@@ -230,7 +232,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
||||
) {
|
||||
return super.dispatchKeyEvent(event)
|
||||
}
|
||||
@@ -244,7 +248,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
||||
) {
|
||||
return super.dispatchGenericMotionEvent(event)
|
||||
}
|
||||
@@ -526,6 +532,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
fun onEmulationStarted() {
|
||||
emulationViewModel.setEmulationStarted(true)
|
||||
NativeLibrary.playTimeManagerStart()
|
||||
|
||||
}
|
||||
|
||||
fun onEmulationStopped(status: Int) {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -83,6 +86,34 @@ class GamePropertiesAdapter(
|
||||
} else {
|
||||
binding.details.setVisible(false)
|
||||
}
|
||||
|
||||
|
||||
val hasVisibleActions = submenuProperty.secondaryActions?.any { it.isShown } == true
|
||||
|
||||
if (hasVisibleActions) {
|
||||
binding.dividerSecondaryActions.setVisible(true)
|
||||
binding.layoutSecondaryActions.setVisible(true)
|
||||
|
||||
submenuProperty.secondaryActions!!.forEach { secondaryAction ->
|
||||
if (secondaryAction.isShown) {
|
||||
val button = com.google.android.material.button.MaterialButton(
|
||||
binding.root.context,
|
||||
null,
|
||||
com.google.android.material.R.attr.materialButtonOutlinedStyle
|
||||
).apply {
|
||||
setIconResource(secondaryAction.iconId)
|
||||
iconSize = (18 * binding.root.context.resources.displayMetrics.density).toInt()
|
||||
text = binding.root.context.getString(secondaryAction.descriptionId)
|
||||
contentDescription = binding.root.context.getString(secondaryAction.descriptionId)
|
||||
setOnClickListener { secondaryAction.action.invoke() }
|
||||
}
|
||||
binding.layoutSecondaryActions.addView(button)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.dividerSecondaryActions.setVisible(false)
|
||||
binding.layoutSecondaryActions.setVisible(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
|
||||
enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
AUDIO_MUTED("audio_muted"),
|
||||
CPU_DEBUG_MODE("cpu_debug_mode"),
|
||||
FASTMEM("cpuopt_fastmem"),
|
||||
FASTMEM_EXCLUSIVES("cpuopt_fastmem_exclusives"),
|
||||
CORE_SYNC_CORE_SPEED("sync_core_speed"),
|
||||
|
||||
@@ -764,13 +764,6 @@ abstract class SettingsItem(
|
||||
descriptionId = R.string.use_auto_stub_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.CPU_DEBUG_MODE,
|
||||
titleId = R.string.cpu_debug_mode,
|
||||
descriptionId = R.string.cpu_debug_mode_description
|
||||
)
|
||||
)
|
||||
|
||||
val fastmem = object : AbstractBooleanSetting {
|
||||
override fun getBoolean(needsGlobal: Boolean): Boolean =
|
||||
@@ -784,7 +777,6 @@ abstract class SettingsItem(
|
||||
|
||||
override val key: String = FASTMEM_COMBINED
|
||||
override val isRuntimeModifiable: Boolean = false
|
||||
override val pairedSettingKey = BooleanSetting.CPU_DEBUG_MODE.key
|
||||
override val defaultValue: Boolean = true
|
||||
override val isSwitchable: Boolean = true
|
||||
override var global: Boolean
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -149,7 +152,9 @@ class InputDialogFragment : DialogFragment() {
|
||||
|
||||
private fun onKeyEvent(event: KeyEvent): Boolean {
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
||||
) {
|
||||
return false
|
||||
}
|
||||
@@ -173,7 +178,9 @@ class InputDialogFragment : DialogFragment() {
|
||||
|
||||
private fun onMotionEvent(event: MotionEvent): Boolean {
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1158,7 +1158,6 @@ class SettingsFragmentPresenter(
|
||||
add(IntSetting.CPU_BACKEND.key)
|
||||
add(IntSetting.CPU_ACCURACY.key)
|
||||
add(BooleanSetting.USE_AUTO_STUB.key)
|
||||
add(BooleanSetting.CPU_DEBUG_MODE.key)
|
||||
add(SettingsItem.FASTMEM_COMBINED)
|
||||
|
||||
add(HeaderSetting(R.string.log))
|
||||
|
||||
@@ -1635,6 +1635,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
Log.debug("[EmulationFragment] Pausing emulation.")
|
||||
|
||||
NativeLibrary.pauseEmulation()
|
||||
NativeLibrary.playTimeManagerStop()
|
||||
|
||||
state = State.PAUSED
|
||||
} else {
|
||||
@@ -1725,6 +1726,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
State.PAUSED -> {
|
||||
Log.debug("[EmulationFragment] Resuming emulation.")
|
||||
NativeLibrary.unpauseEmulation()
|
||||
NativeLibrary.playTimeManagerStart()
|
||||
}
|
||||
|
||||
else -> Log.debug("[EmulationFragment] Bug, run called while already running.")
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.os.Bundle
|
||||
import android.provider.DocumentsContract
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -14,27 +16,31 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.adapters.GamePropertiesAdapter
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentGamePropertiesBinding
|
||||
import org.yuzu.yuzu_emu.features.DocumentProvider
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||
import org.yuzu.yuzu_emu.model.GameProperty
|
||||
import org.yuzu.yuzu_emu.model.GamesViewModel
|
||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||
import org.yuzu.yuzu_emu.model.InstallableProperty
|
||||
import org.yuzu.yuzu_emu.model.SubMenuPropertySecondaryAction
|
||||
import org.yuzu.yuzu_emu.model.SubmenuProperty
|
||||
import org.yuzu.yuzu_emu.model.TaskState
|
||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||
@@ -104,6 +110,8 @@ class GamePropertiesFragment : Fragment() {
|
||||
binding.title.text = args.game.title
|
||||
binding.title.marquee()
|
||||
|
||||
getPlayTime()
|
||||
|
||||
binding.buttonStart.setOnClickListener {
|
||||
LaunchGameDialogFragment.newInstance(args.game)
|
||||
.show(childFragmentManager, LaunchGameDialogFragment.TAG)
|
||||
@@ -128,6 +136,110 @@ class GamePropertiesFragment : Fragment() {
|
||||
gamesViewModel.reloadGames(true)
|
||||
}
|
||||
|
||||
private fun getPlayTime() {
|
||||
binding.playtime.text = buildString {
|
||||
val playTimeSeconds = NativeLibrary.playTimeManagerGetPlayTime(args.game.programId)
|
||||
|
||||
val hours = playTimeSeconds / 3600
|
||||
val minutes = (playTimeSeconds % 3600) / 60
|
||||
val seconds = playTimeSeconds % 60
|
||||
|
||||
val readablePlayTime = when {
|
||||
hours > 0 -> "${hours}h ${minutes}m ${seconds}s"
|
||||
minutes > 0 -> "${minutes}m ${seconds}s"
|
||||
else -> "${seconds}s"
|
||||
}
|
||||
|
||||
append(getString(R.string.playtime))
|
||||
append(readablePlayTime)
|
||||
}
|
||||
|
||||
binding.playtime.setOnClickListener {
|
||||
showEditPlaytimeDialog()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showEditPlaytimeDialog() {
|
||||
val dialogView = layoutInflater.inflate(R.layout.dialog_edit_playtime, null)
|
||||
val hoursLayout =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputLayout>(R.id.layout_hours)
|
||||
val minutesLayout =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputLayout>(R.id.layout_minutes)
|
||||
val secondsLayout =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputLayout>(R.id.layout_seconds)
|
||||
val hoursInput =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.input_hours)
|
||||
val minutesInput =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.input_minutes)
|
||||
val secondsInput =
|
||||
dialogView.findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.input_seconds)
|
||||
|
||||
val playTimeSeconds = NativeLibrary.playTimeManagerGetPlayTime(args.game.programId)
|
||||
val hours = playTimeSeconds / 3600
|
||||
val minutes = (playTimeSeconds % 3600) / 60
|
||||
val seconds = playTimeSeconds % 60
|
||||
|
||||
hoursInput.setText(hours.toString())
|
||||
minutesInput.setText(minutes.toString())
|
||||
secondsInput.setText(seconds.toString())
|
||||
|
||||
val dialog = com.google.android.material.dialog.MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.edit_playtime)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
|
||||
dialog.setOnShowListener {
|
||||
val positiveButton = dialog.getButton(android.app.AlertDialog.BUTTON_POSITIVE)
|
||||
positiveButton.setOnClickListener {
|
||||
hoursLayout.error = null
|
||||
minutesLayout.error = null
|
||||
secondsLayout.error = null
|
||||
|
||||
val hoursText = hoursInput.text.toString()
|
||||
val minutesText = minutesInput.text.toString()
|
||||
val secondsText = secondsInput.text.toString()
|
||||
|
||||
val hoursValue = hoursText.toLongOrNull() ?: 0
|
||||
val minutesValue = minutesText.toLongOrNull() ?: 0
|
||||
val secondsValue = secondsText.toLongOrNull() ?: 0
|
||||
|
||||
var hasError = false
|
||||
|
||||
// normally cant be above 9999
|
||||
if (hoursValue < 0 || hoursValue > 9999) {
|
||||
hoursLayout.error = getString(R.string.hours_must_be_between_0_and_9999)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
if (minutesValue < 0 || minutesValue > 59) {
|
||||
minutesLayout.error = getString(R.string.minutes_must_be_between_0_and_59)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
if (secondsValue < 0 || secondsValue > 59) {
|
||||
secondsLayout.error = getString(R.string.seconds_must_be_between_0_and_59)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
if (!hasError) {
|
||||
val totalSeconds = hoursValue * 3600 + minutesValue * 60 + secondsValue
|
||||
NativeLibrary.playTimeManagerSetPlayTime(args.game.programId, totalSeconds)
|
||||
getPlayTime()
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
R.string.playtime_updated_successfully,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun reloadList() {
|
||||
_binding ?: return
|
||||
|
||||
@@ -137,25 +249,66 @@ class GamePropertiesFragment : Fragment() {
|
||||
SubmenuProperty(
|
||||
R.string.info,
|
||||
R.string.info_description,
|
||||
R.drawable.ic_info_outline
|
||||
) {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToGameInfoFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
R.drawable.ic_info_outline,
|
||||
action = {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToGameInfoFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
SubmenuProperty(
|
||||
R.string.preferences_settings,
|
||||
R.string.per_game_settings_description,
|
||||
R.drawable.ic_settings
|
||||
) {
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||
args.game,
|
||||
Settings.MenuTag.SECTION_ROOT
|
||||
)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
R.drawable.ic_settings,
|
||||
action = {
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||
args.game,
|
||||
Settings.MenuTag.SECTION_ROOT
|
||||
)
|
||||
binding.root.findNavController().navigate(action)
|
||||
},
|
||||
secondaryActions = buildList {
|
||||
val configExists = File(
|
||||
DirectoryInitialization.userDirectory +
|
||||
"/config/custom/" + args.game.settingsName + ".ini"
|
||||
).exists()
|
||||
|
||||
add(SubMenuPropertySecondaryAction(
|
||||
isShown = configExists,
|
||||
descriptionId = R.string.import_config,
|
||||
iconId = R.drawable.ic_import,
|
||||
action = {
|
||||
importConfig.launch(arrayOf("text/ini", "application/octet-stream"))
|
||||
}
|
||||
))
|
||||
|
||||
add(SubMenuPropertySecondaryAction(
|
||||
isShown = configExists,
|
||||
descriptionId = R.string.export_config,
|
||||
iconId = R.drawable.ic_export,
|
||||
action = {
|
||||
exportConfig.launch(args.game.settingsName + ".ini")
|
||||
}
|
||||
))
|
||||
|
||||
add(SubMenuPropertySecondaryAction(
|
||||
isShown = configExists,
|
||||
descriptionId = R.string.share_game_settings,
|
||||
iconId = R.drawable.ic_share,
|
||||
action = {
|
||||
val configFile = File(
|
||||
DirectoryInitialization.userDirectory +
|
||||
"/config/custom/" + args.game.settingsName + ".ini"
|
||||
)
|
||||
if (configFile.exists()) {
|
||||
shareConfigFile(configFile)
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if (GpuDriverHelper.supportsCustomDriverLoading()) {
|
||||
@@ -164,12 +317,13 @@ class GamePropertiesFragment : Fragment() {
|
||||
R.string.gpu_driver_manager,
|
||||
R.string.install_gpu_driver_description,
|
||||
R.drawable.ic_build,
|
||||
detailsFlow = driverViewModel.selectedDriverTitle
|
||||
) {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToDriverManagerFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
detailsFlow = driverViewModel.selectedDriverTitle,
|
||||
action = {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToDriverManagerFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -178,12 +332,13 @@ class GamePropertiesFragment : Fragment() {
|
||||
SubmenuProperty(
|
||||
R.string.add_ons,
|
||||
R.string.add_ons_description,
|
||||
R.drawable.ic_edit
|
||||
) {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToAddonsFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
R.drawable.ic_edit,
|
||||
action = {
|
||||
val action = GamePropertiesFragmentDirections
|
||||
.actionPerGamePropertiesFragmentToAddonsFragment(args.game)
|
||||
binding.root.findNavController().navigate(action)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
InstallableProperty(
|
||||
@@ -245,7 +400,7 @@ class GamePropertiesFragment : Fragment() {
|
||||
R.string.clear_shader_cache,
|
||||
R.string.clear_shader_cache_description,
|
||||
R.drawable.ic_delete,
|
||||
{
|
||||
details = {
|
||||
if (shaderCacheDir.exists()) {
|
||||
val bytes = shaderCacheDir.walkTopDown().filter { it.isFile }
|
||||
.map { it.length() }.sum()
|
||||
@@ -253,30 +408,63 @@ class GamePropertiesFragment : Fragment() {
|
||||
} else {
|
||||
MemoryUtil.bytesToSizeUnit(0f)
|
||||
}
|
||||
},
|
||||
action = {
|
||||
MessageDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
titleId = R.string.clear_shader_cache,
|
||||
descriptionId = R.string.clear_shader_cache_warning_description,
|
||||
positiveAction = {
|
||||
shaderCacheDir.deleteRecursively()
|
||||
Toast.makeText(
|
||||
YuzuApplication.appContext,
|
||||
R.string.cleared_shaders_successfully,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
homeViewModel.reloadPropertiesList(true)
|
||||
}
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
) {
|
||||
MessageDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
titleId = R.string.clear_shader_cache,
|
||||
descriptionId = R.string.clear_shader_cache_warning_description,
|
||||
positiveAction = {
|
||||
shaderCacheDir.deleteRecursively()
|
||||
Toast.makeText(
|
||||
YuzuApplication.appContext,
|
||||
R.string.cleared_shaders_successfully,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
homeViewModel.reloadPropertiesList(true)
|
||||
}
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
if (NativeLibrary.playTimeManagerGetPlayTime(args.game.programId) > 0) {
|
||||
add(
|
||||
SubmenuProperty(
|
||||
R.string.reset_playtime,
|
||||
R.string.reset_playtime_description,
|
||||
R.drawable.ic_delete,
|
||||
action = {
|
||||
MessageDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
titleId = R.string.reset_playtime,
|
||||
descriptionId = R.string.reset_playtime_warning_description,
|
||||
positiveAction = {
|
||||
NativeLibrary.playTimeManagerResetProgramPlayTime(args.game.programId)
|
||||
Toast.makeText(
|
||||
YuzuApplication.appContext,
|
||||
R.string.playtime_reset_successfully,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
getPlayTime()
|
||||
homeViewModel.reloadPropertiesList(true)
|
||||
}
|
||||
).show(parentFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.listProperties.apply {
|
||||
layoutManager =
|
||||
GridLayoutManager(requireContext(), resources.getInteger(R.integer.grid_columns))
|
||||
val spanCount = resources.getInteger(R.integer.grid_columns)
|
||||
val staggered = StaggeredGridLayoutManager(
|
||||
spanCount,
|
||||
StaggeredGridLayoutManager.VERTICAL
|
||||
).apply {
|
||||
gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
|
||||
}
|
||||
layoutManager = staggered
|
||||
adapter = GamePropertiesAdapter(viewLifecycleOwner, properties)
|
||||
}
|
||||
}
|
||||
@@ -284,6 +472,8 @@ class GamePropertiesFragment : Fragment() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
driverViewModel.updateDriverNameForGame(args.game)
|
||||
getPlayTime()
|
||||
reloadList()
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
@@ -420,4 +610,89 @@ class GamePropertiesFragment : Fragment() {
|
||||
}
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports an ini file from external storage to internal app directory and override per-game config
|
||||
*/
|
||||
private val importConfig = registerForActivityResult(
|
||||
ActivityResultContracts.OpenDocument()
|
||||
) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
val iniResult = FileUtil.copyUriToInternalStorage(
|
||||
sourceUri = result,
|
||||
destinationParentPath =
|
||||
DirectoryInitialization.userDirectory + "/config/custom/",
|
||||
destinationFilename = args.game.settingsName + ".ini"
|
||||
)
|
||||
if (iniResult?.exists() == true) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getString(R.string.import_success),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
homeViewModel.reloadPropertiesList(true)
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getString(R.string.import_failed),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports game's config ini to the specified location in external storage
|
||||
*/
|
||||
private val exportConfig = registerForActivityResult(
|
||||
ActivityResultContracts.CreateDocument("text/ini")
|
||||
) { result ->
|
||||
if (result == null) {
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
ProgressDialogFragment.newInstance(
|
||||
requireActivity(),
|
||||
R.string.save_files_exporting,
|
||||
false
|
||||
) { _, _ ->
|
||||
val configLocation = DirectoryInitialization.userDirectory +
|
||||
"/config/custom/" + args.game.settingsName + ".ini"
|
||||
|
||||
val iniResult = FileUtil.copyToExternalStorage(
|
||||
sourcePath = configLocation,
|
||||
destUri = result
|
||||
)
|
||||
return@newInstance when (iniResult) {
|
||||
TaskState.Completed -> getString(R.string.export_success)
|
||||
TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed)
|
||||
}
|
||||
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
|
||||
}
|
||||
|
||||
private fun shareConfigFile(configFile: File) {
|
||||
val file = DocumentFile.fromSingleUri(
|
||||
requireContext(),
|
||||
DocumentsContract.buildDocumentUri(
|
||||
DocumentProvider.AUTHORITY,
|
||||
"${DocumentProvider.ROOT_ID}/${configFile}"
|
||||
)
|
||||
)!!
|
||||
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
.setDataAndType(file.uri, FileUtil.TEXT_PLAIN)
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
if (file.exists()) {
|
||||
intent.putExtra(Intent.EXTRA_STREAM, file.uri)
|
||||
startActivity(Intent.createChooser(intent, getText(R.string.share_game_settings)))
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getText(R.string.share_config_failed),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -24,9 +27,17 @@ data class SubmenuProperty(
|
||||
override val iconId: Int,
|
||||
val details: (() -> String)? = null,
|
||||
val detailsFlow: StateFlow<String>? = null,
|
||||
val action: () -> Unit
|
||||
val action: () -> Unit,
|
||||
val secondaryActions: List<SubMenuPropertySecondaryAction>? = null
|
||||
) : GameProperty
|
||||
|
||||
data class SubMenuPropertySecondaryAction(
|
||||
val isShown : Boolean,
|
||||
val descriptionId: Int,
|
||||
val iconId: Int,
|
||||
val action: () -> Unit
|
||||
)
|
||||
|
||||
data class InstallableProperty(
|
||||
override val titleId: Int,
|
||||
override val descriptionId: Int,
|
||||
|
||||
@@ -1039,7 +1039,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
scale /= 100f
|
||||
|
||||
// Apply individual scale
|
||||
scale *= overlayControlData.individualScale
|
||||
scale *= overlayControlData.individualScale.let { if (it > 0f) it else 1f }
|
||||
|
||||
// Initialize the InputOverlayDrawableButton.
|
||||
val defaultStateBitmap = getBitmap(context, defaultResId, scale)
|
||||
@@ -1114,7 +1114,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
|
||||
// Apply individual scale
|
||||
if (dpadData != null) {
|
||||
scale *= dpadData.individualScale
|
||||
scale *= dpadData.individualScale.let { if (it > 0f) it else 1f }
|
||||
}
|
||||
|
||||
// Initialize the InputOverlayDrawableDpad.
|
||||
@@ -1191,7 +1191,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
scale /= 100f
|
||||
|
||||
// Apply individual scale
|
||||
scale *= overlayControlData.individualScale
|
||||
scale *= overlayControlData.individualScale.let { if (it > 0f) it else 1f }
|
||||
|
||||
// Initialize the InputOverlayDrawableJoystick.
|
||||
val bitmapOuter = getBitmap(context, resOuter, scale)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
object AddonUtil {
|
||||
val validAddonDirectories = listOf("cheats", "exefs", "romfs")
|
||||
val validAddonDirectories = listOf("cheats", "exefs", "romfs", "romfslite")
|
||||
}
|
||||
|
||||