Compare commits
18 Commits
descriptor
...
update-cpm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8656da2fa | ||
|
|
5f75aceace | ||
|
|
7bb30a1086 | ||
|
|
f532611a50 | ||
|
|
d754fca70f | ||
|
|
c5bd7dc047 | ||
|
|
557876b222 | ||
|
|
22dfc560e0 | ||
|
|
1d869e8495 | ||
|
|
959f72297d | ||
|
|
057d566ff4 | ||
|
|
be592f0ab3 | ||
|
|
bf68eede05 | ||
|
|
1eed7efd09 | ||
|
|
50f8d4130d | ||
|
|
e4dccd5a5c | ||
|
|
b9530ae80f | ||
|
|
5130185d12 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -37,6 +37,8 @@ CMakeLists.txt.user*
|
||||
# *nix related
|
||||
# Common convention for backup or temporary files
|
||||
*~
|
||||
*.core
|
||||
dtrace-out/
|
||||
|
||||
# Visual Studio CMake settings
|
||||
CMakeSettings.json
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
if (MSVC OR ANDROID)
|
||||
set(CPM_SOURCE_CACHE "${PROJECT_SOURCE_DIR}/.cache/cpm" CACHE STRING "" FORCE)
|
||||
|
||||
if(MSVC OR ANDROID)
|
||||
set(BUNDLED_DEFAULT ON)
|
||||
else()
|
||||
set(BUNDLED_DEFAULT OFF)
|
||||
@@ -19,7 +21,7 @@ include(CPM)
|
||||
# cpmfile parsing
|
||||
set(CPMUTIL_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json")
|
||||
|
||||
if (EXISTS ${CPMUTIL_JSON_FILE})
|
||||
if(EXISTS ${CPMUTIL_JSON_FILE})
|
||||
file(READ ${CPMUTIL_JSON_FILE} CPMFILE_CONTENT)
|
||||
else()
|
||||
message(WARNING "[CPMUtil] cpmfile ${CPMUTIL_JSON_FILE} does not exist, AddJsonPackage will be a no-op")
|
||||
@@ -45,14 +47,14 @@ endfunction()
|
||||
function(get_json_element object out member default)
|
||||
string(JSON out_type ERROR_VARIABLE err TYPE "${object}" ${member})
|
||||
|
||||
if (err)
|
||||
if(err)
|
||||
set("${out}" "${default}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(JSON outvar GET "${object}" ${member})
|
||||
|
||||
if (out_type STREQUAL "ARRAY")
|
||||
if(out_type STREQUAL "ARRAY")
|
||||
string(JSON _len LENGTH "${object}" ${member})
|
||||
# array_to_list("${outvar}" ${_len} outvar)
|
||||
set("${out}_LENGTH" "${_len}" PARENT_SCOPE)
|
||||
@@ -74,7 +76,7 @@ function(AddJsonPackage)
|
||||
set(multiValueArgs OPTIONS)
|
||||
|
||||
cmake_parse_arguments(JSON "" "${oneValueArgs}" "${multiValueArgs}"
|
||||
"${ARGN}")
|
||||
"${ARGN}")
|
||||
|
||||
list(LENGTH ARGN argnLength)
|
||||
|
||||
@@ -83,18 +85,18 @@ function(AddJsonPackage)
|
||||
set(JSON_NAME "${ARGV0}")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CPMFILE_CONTENT)
|
||||
if(NOT DEFINED CPMFILE_CONTENT)
|
||||
cpm_utils_message(WARNING ${name} "No cpmfile, AddJsonPackage is a no-op")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED JSON_NAME)
|
||||
if(NOT DEFINED JSON_NAME)
|
||||
cpm_utils_message(FATAL_ERROR "json package" "No name specified")
|
||||
endif()
|
||||
|
||||
string(JSON object ERROR_VARIABLE err GET "${CPMFILE_CONTENT}" "${JSON_NAME}")
|
||||
|
||||
if (err)
|
||||
if(err)
|
||||
cpm_utils_message(FATAL_ERROR ${JSON_NAME} "Not found in cpmfile")
|
||||
endif()
|
||||
|
||||
@@ -103,13 +105,13 @@ function(AddJsonPackage)
|
||||
get_json_element("${object}" ci ci OFF)
|
||||
get_json_element("${object}" version version "")
|
||||
|
||||
if (ci)
|
||||
if(ci)
|
||||
get_json_element("${object}" name name "${JSON_NAME}")
|
||||
get_json_element("${object}" extension extension "tar.zst")
|
||||
get_json_element("${object}" min_version min_version "")
|
||||
get_json_element("${object}" raw_disabled disabled_platforms "")
|
||||
|
||||
if (raw_disabled)
|
||||
if(raw_disabled)
|
||||
array_to_list("${raw_disabled}" ${raw_disabled_LENGTH} disabled_platforms)
|
||||
else()
|
||||
set(disabled_platforms "")
|
||||
@@ -154,31 +156,31 @@ function(AddJsonPackage)
|
||||
# first: tag gets %VERSION% replaced if applicable, with either git_version (preferred) or version
|
||||
# second: artifact gets %VERSION% and %TAG% replaced accordingly (same rules for VERSION)
|
||||
|
||||
if (git_version)
|
||||
if(git_version)
|
||||
set(version_replace ${git_version})
|
||||
else()
|
||||
set(version_replace ${version})
|
||||
endif()
|
||||
|
||||
# TODO(crueter): fmt module for cmake
|
||||
if (tag)
|
||||
if(tag)
|
||||
string(REPLACE "%VERSION%" "${version_replace}" tag ${tag})
|
||||
endif()
|
||||
|
||||
if (artifact)
|
||||
if(artifact)
|
||||
string(REPLACE "%VERSION%" "${version_replace}" artifact ${artifact})
|
||||
string(REPLACE "%TAG%" "${tag}" artifact ${artifact})
|
||||
endif()
|
||||
|
||||
# format patchdir
|
||||
if (raw_patches)
|
||||
if(raw_patches)
|
||||
math(EXPR range "${raw_patches_LENGTH} - 1")
|
||||
|
||||
foreach(IDX RANGE ${range})
|
||||
string(JSON _patch GET "${raw_patches}" "${IDX}")
|
||||
|
||||
set(full_patch "${CMAKE_SOURCE_DIR}/.patch/${JSON_NAME}/${_patch}")
|
||||
if (NOT EXISTS ${full_patch})
|
||||
if(NOT EXISTS ${full_patch})
|
||||
cpm_utils_message(FATAL_ERROR ${JSON_NAME} "specifies patch ${full_patch} which does not exist")
|
||||
endif()
|
||||
|
||||
@@ -190,7 +192,7 @@ function(AddJsonPackage)
|
||||
# options
|
||||
get_json_element("${object}" raw_options options "")
|
||||
|
||||
if (raw_options)
|
||||
if(raw_options)
|
||||
array_to_list("${raw_options}" ${raw_options_LENGTH} options)
|
||||
endif()
|
||||
|
||||
@@ -198,7 +200,7 @@ function(AddJsonPackage)
|
||||
# end options
|
||||
|
||||
# system/bundled
|
||||
if (bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE)
|
||||
if(bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE)
|
||||
set(bundled ${JSON_BUNDLED_PACKAGE})
|
||||
endif()
|
||||
|
||||
@@ -284,37 +286,37 @@ function(AddPackage)
|
||||
set(multiValueArgs OPTIONS PATCHES)
|
||||
|
||||
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}"
|
||||
"${ARGN}")
|
||||
"${ARGN}")
|
||||
|
||||
if (NOT DEFINED PKG_ARGS_NAME)
|
||||
if(NOT DEFINED PKG_ARGS_NAME)
|
||||
cpm_utils_message(FATAL_ERROR "package" "No package name defined")
|
||||
endif()
|
||||
|
||||
option(${PKG_ARGS_NAME}_FORCE_SYSTEM "Force the system package for ${PKG_ARGS_NAME}")
|
||||
option(${PKG_ARGS_NAME}_FORCE_BUNDLED "Force the bundled package for ${PKG_ARGS_NAME}")
|
||||
|
||||
if (NOT DEFINED PKG_ARGS_GIT_HOST)
|
||||
if(NOT DEFINED PKG_ARGS_GIT_HOST)
|
||||
set(git_host github.com)
|
||||
else()
|
||||
set(git_host ${PKG_ARGS_GIT_HOST})
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_URL)
|
||||
if(DEFINED PKG_ARGS_URL)
|
||||
set(pkg_url ${PKG_ARGS_URL})
|
||||
|
||||
if (DEFINED PKG_ARGS_REPO)
|
||||
if(DEFINED PKG_ARGS_REPO)
|
||||
set(pkg_git_url https://${git_host}/${PKG_ARGS_REPO})
|
||||
else()
|
||||
if (DEFINED PKG_ARGS_GIT_URL)
|
||||
if(DEFINED PKG_ARGS_GIT_URL)
|
||||
set(pkg_git_url ${PKG_ARGS_GIT_URL})
|
||||
else()
|
||||
set(pkg_git_url ${pkg_url})
|
||||
endif()
|
||||
endif()
|
||||
elseif (DEFINED PKG_ARGS_REPO)
|
||||
elseif(DEFINED PKG_ARGS_REPO)
|
||||
set(pkg_git_url https://${git_host}/${PKG_ARGS_REPO})
|
||||
|
||||
if (DEFINED PKG_ARGS_TAG)
|
||||
if(DEFINED PKG_ARGS_TAG)
|
||||
set(pkg_key ${PKG_ARGS_TAG})
|
||||
|
||||
if(DEFINED PKG_ARGS_ARTIFACT)
|
||||
@@ -324,14 +326,14 @@ function(AddPackage)
|
||||
set(pkg_url
|
||||
${pkg_git_url}/archive/refs/tags/${PKG_ARGS_TAG}.tar.gz)
|
||||
endif()
|
||||
elseif (DEFINED PKG_ARGS_SHA)
|
||||
elseif(DEFINED PKG_ARGS_SHA)
|
||||
set(pkg_url "${pkg_git_url}/archive/${PKG_ARGS_SHA}.tar.gz")
|
||||
else()
|
||||
if (DEFINED PKG_ARGS_BRANCH)
|
||||
if(DEFINED PKG_ARGS_BRANCH)
|
||||
set(PKG_BRANCH ${PKG_ARGS_BRANCH})
|
||||
else()
|
||||
cpm_utils_message(WARNING ${PKG_ARGS_NAME}
|
||||
"REPO defined but no TAG, SHA, BRANCH, or URL specified, defaulting to master")
|
||||
"REPO defined but no TAG, SHA, BRANCH, or URL specified, defaulting to master")
|
||||
set(PKG_BRANCH master)
|
||||
endif()
|
||||
|
||||
@@ -343,72 +345,72 @@ function(AddPackage)
|
||||
|
||||
cpm_utils_message(STATUS ${PKG_ARGS_NAME} "Download URL is ${pkg_url}")
|
||||
|
||||
if (NOT DEFINED PKG_ARGS_KEY)
|
||||
if (DEFINED PKG_ARGS_SHA)
|
||||
if(NOT DEFINED PKG_ARGS_KEY)
|
||||
if(DEFINED PKG_ARGS_SHA)
|
||||
string(SUBSTRING ${PKG_ARGS_SHA} 0 4 pkg_key)
|
||||
cpm_utils_message(DEBUG ${PKG_ARGS_NAME}
|
||||
"No custom key defined, using ${pkg_key} from sha")
|
||||
"No custom key defined, using ${pkg_key} from sha")
|
||||
elseif(DEFINED PKG_ARGS_GIT_VERSION)
|
||||
set(pkg_key ${PKG_ARGS_GIT_VERSION})
|
||||
cpm_utils_message(DEBUG ${PKG_ARGS_NAME}
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
elseif (DEFINED PKG_ARGS_TAG)
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
elseif(DEFINED PKG_ARGS_TAG)
|
||||
set(pkg_key ${PKG_ARGS_TAG})
|
||||
cpm_utils_message(DEBUG ${PKG_ARGS_NAME}
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
elseif (DEFINED PKG_ARGS_VERSION)
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
elseif(DEFINED PKG_ARGS_VERSION)
|
||||
set(pkg_key ${PKG_ARGS_VERSION})
|
||||
cpm_utils_message(DEBUG ${PKG_ARGS_NAME}
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
"No custom key defined, using ${pkg_key}")
|
||||
else()
|
||||
cpm_utils_message(WARNING ${PKG_ARGS_NAME}
|
||||
"Could not determine cache key, using CPM defaults")
|
||||
"Could not determine cache key, using CPM defaults")
|
||||
endif()
|
||||
else()
|
||||
set(pkg_key ${PKG_ARGS_KEY})
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_HASH_ALGO)
|
||||
if(DEFINED PKG_ARGS_HASH_ALGO)
|
||||
set(hash_algo ${PKG_ARGS_HASH_ALGO})
|
||||
else()
|
||||
set(hash_algo SHA512)
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_HASH)
|
||||
if(DEFINED PKG_ARGS_HASH)
|
||||
set(pkg_hash "${hash_algo}=${PKG_ARGS_HASH}")
|
||||
elseif (DEFINED PKG_ARGS_HASH_SUFFIX)
|
||||
elseif(DEFINED PKG_ARGS_HASH_SUFFIX)
|
||||
# funny sanity check
|
||||
string(TOLOWER ${hash_algo} hash_algo_lower)
|
||||
string(TOLOWER ${PKG_ARGS_HASH_SUFFIX} suffix_lower)
|
||||
if (NOT ${suffix_lower} MATCHES ${hash_algo_lower})
|
||||
if(NOT ${suffix_lower} MATCHES ${hash_algo_lower})
|
||||
cpm_utils_message(WARNING
|
||||
"Hash algorithm and hash suffix do not match, errors may occur")
|
||||
"Hash algorithm and hash suffix do not match, errors may occur")
|
||||
endif()
|
||||
|
||||
set(hash_url ${pkg_url}.${PKG_ARGS_HASH_SUFFIX})
|
||||
elseif (DEFINED PKG_ARGS_HASH_URL)
|
||||
elseif(DEFINED PKG_ARGS_HASH_URL)
|
||||
set(hash_url ${PKG_ARGS_HASH_URL})
|
||||
else()
|
||||
cpm_utils_message(WARNING ${PKG_ARGS_NAME}
|
||||
"No hash or hash URL found")
|
||||
"No hash or hash URL found")
|
||||
endif()
|
||||
|
||||
if (DEFINED hash_url)
|
||||
if(DEFINED hash_url)
|
||||
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/${PKG_ARGS_NAME}.hash)
|
||||
|
||||
# TODO(crueter): This is kind of a bad solution
|
||||
# because "technically" the hash is invalidated each week
|
||||
# but it works for now kjsdnfkjdnfjksdn
|
||||
string(TOLOWER ${PKG_ARGS_NAME} lowername)
|
||||
if (NOT EXISTS ${outfile} AND NOT EXISTS ${CPM_SOURCE_CACHE}/${lowername}/${pkg_key})
|
||||
if(NOT EXISTS ${outfile} AND NOT EXISTS ${CPM_SOURCE_CACHE}/${lowername}/${pkg_key})
|
||||
file(DOWNLOAD ${hash_url} ${outfile})
|
||||
endif()
|
||||
|
||||
if (EXISTS ${outfile})
|
||||
if(EXISTS ${outfile})
|
||||
file(READ ${outfile} pkg_hash_tmp)
|
||||
endif()
|
||||
|
||||
if (DEFINED ${pkg_hash_tmp})
|
||||
if(DEFINED ${pkg_hash_tmp})
|
||||
set(pkg_hash "${hash_algo}=${pkg_hash_tmp}")
|
||||
endif()
|
||||
endif()
|
||||
@@ -426,19 +428,19 @@ function(AddPackage)
|
||||
- CPMUTIL_FORCE_BUNDLED
|
||||
- BUNDLED_PACKAGE
|
||||
- default to allow local
|
||||
]]#
|
||||
if (PKG_ARGS_FORCE_BUNDLED_PACKAGE)
|
||||
]] #
|
||||
if(PKG_ARGS_FORCE_BUNDLED_PACKAGE)
|
||||
set_precedence(OFF OFF)
|
||||
elseif (${PKG_ARGS_NAME}_FORCE_SYSTEM)
|
||||
elseif(${PKG_ARGS_NAME}_FORCE_SYSTEM)
|
||||
set_precedence(ON ON)
|
||||
elseif (${PKG_ARGS_NAME}_FORCE_BUNDLED)
|
||||
elseif(${PKG_ARGS_NAME}_FORCE_BUNDLED)
|
||||
set_precedence(OFF OFF)
|
||||
elseif (CPMUTIL_FORCE_SYSTEM)
|
||||
elseif(CPMUTIL_FORCE_SYSTEM)
|
||||
set_precedence(ON ON)
|
||||
elseif(CPMUTIL_FORCE_BUNDLED)
|
||||
set_precedence(OFF OFF)
|
||||
elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE AND NOT PKG_ARGS_BUNDLED_PACKAGE STREQUAL "unset")
|
||||
if (PKG_ARGS_BUNDLED_PACKAGE)
|
||||
elseif(DEFINED PKG_ARGS_BUNDLED_PACKAGE AND NOT PKG_ARGS_BUNDLED_PACKAGE STREQUAL "unset")
|
||||
if(PKG_ARGS_BUNDLED_PACKAGE)
|
||||
set(local OFF)
|
||||
else()
|
||||
set(local ON)
|
||||
@@ -449,7 +451,7 @@ function(AddPackage)
|
||||
set_precedence(ON OFF)
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_VERSION)
|
||||
if(DEFINED PKG_ARGS_VERSION)
|
||||
list(APPEND EXTRA_ARGS
|
||||
VERSION ${PKG_ARGS_VERSION}
|
||||
)
|
||||
@@ -475,32 +477,32 @@ function(AddPackage)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${PKG_ARGS_NAME})
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS ${pkg_git_url})
|
||||
|
||||
if (${PKG_ARGS_NAME}_ADDED)
|
||||
if (DEFINED PKG_ARGS_SHA)
|
||||
if(${PKG_ARGS_NAME}_ADDED)
|
||||
if(DEFINED PKG_ARGS_SHA)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_SHA})
|
||||
elseif (DEFINED PKG_ARGS_GIT_VERSION)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_GIT_VERSION})
|
||||
elseif (DEFINED PKG_ARGS_TAG)
|
||||
${PKG_ARGS_SHA})
|
||||
elseif(DEFINED PKG_ARGS_GIT_VERSION)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_TAG})
|
||||
elseif(DEFINED PKG_ARGS_VERSION)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_VERSION})
|
||||
${PKG_ARGS_GIT_VERSION})
|
||||
elseif(DEFINED PKG_ARGS_TAG)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_TAG})
|
||||
elseif(DEFINED PKG_ARGS_VERSION)
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
${PKG_ARGS_VERSION})
|
||||
else()
|
||||
cpm_utils_message(WARNING ${PKG_ARGS_NAME}
|
||||
"Package has no specified sha, tag, or version")
|
||||
"Package has no specified sha, tag, or version")
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS "unknown")
|
||||
endif()
|
||||
else()
|
||||
if (DEFINED CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION AND NOT
|
||||
if(DEFINED CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION AND NOT
|
||||
"${CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION}" STREQUAL "")
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
"${CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION} (system)")
|
||||
"${CPM_PACKAGE_${PKG_ARGS_NAME}_VERSION} (system)")
|
||||
else()
|
||||
set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS
|
||||
"unknown (system)")
|
||||
"unknown (system)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -561,7 +563,7 @@ function(AddCIPackage)
|
||||
message(FATAL_ERROR "[CPMUtil] PACKAGE is required")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED PKG_ARGS_CMAKE_FILENAME)
|
||||
if(NOT DEFINED PKG_ARGS_CMAKE_FILENAME)
|
||||
set(ARTIFACT_CMAKE ${PKG_ARGS_NAME})
|
||||
else()
|
||||
set(ARTIFACT_CMAKE ${PKG_ARGS_CMAKE_FILENAME})
|
||||
@@ -573,11 +575,11 @@ function(AddCIPackage)
|
||||
set(ARTIFACT_EXT ${PKG_ARGS_EXTENSION})
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_MIN_VERSION)
|
||||
if(DEFINED PKG_ARGS_MIN_VERSION)
|
||||
set(ARTIFACT_MIN_VERSION ${PKG_ARGS_MIN_VERSION})
|
||||
endif()
|
||||
|
||||
if (DEFINED PKG_ARGS_DISABLED_PLATFORMS)
|
||||
if(DEFINED PKG_ARGS_DISABLED_PLATFORMS)
|
||||
set(DISABLED_PLATFORMS ${PKG_ARGS_DISABLED_PLATFORMS})
|
||||
endif()
|
||||
|
||||
@@ -587,19 +589,19 @@ function(AddCIPackage)
|
||||
set(ARTIFACT_REPO ${PKG_ARGS_REPO})
|
||||
set(ARTIFACT_PACKAGE ${PKG_ARGS_PACKAGE})
|
||||
|
||||
if ((MSVC AND ARCHITECTURE_x86_64) AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS)
|
||||
if((MSVC AND ARCHITECTURE_x86_64) AND NOT "windows-amd64" IN_LIST DISABLED_PLATFORMS)
|
||||
add_ci_package(windows-amd64)
|
||||
endif()
|
||||
|
||||
if ((MSVC AND ARCHITECTURE_arm64) AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS)
|
||||
if((MSVC AND ARCHITECTURE_arm64) AND NOT "windows-arm64" IN_LIST DISABLED_PLATFORMS)
|
||||
add_ci_package(windows-arm64)
|
||||
endif()
|
||||
|
||||
if ((MINGW AND ARCHITECTURE_x86_64) AND NOT "mingw-amd64" IN_LIST DISABLED_PLATFORMS)
|
||||
if((MINGW AND ARCHITECTURE_x86_64) AND NOT "mingw-amd64" IN_LIST DISABLED_PLATFORMS)
|
||||
add_ci_package(mingw-amd64)
|
||||
endif()
|
||||
|
||||
if ((MINGW AND ARCHITECTURE_arm64) AND NOT "mingw-arm64" IN_LIST DISABLED_PLATFORMS)
|
||||
if((MINGW AND ARCHITECTURE_arm64) AND NOT "mingw-arm64" IN_LIST DISABLED_PLATFORMS)
|
||||
add_ci_package(mingw-arm64)
|
||||
endif()
|
||||
|
||||
@@ -628,11 +630,11 @@ function(AddCIPackage)
|
||||
endif()
|
||||
|
||||
# TODO(crueter): macOS amd64/aarch64 split mayhaps
|
||||
if (APPLE AND NOT "macos-universal" IN_LIST DISABLED_PLATFORMS)
|
||||
if(APPLE AND NOT "macos-universal" IN_LIST DISABLED_PLATFORMS)
|
||||
add_ci_package(macos-universal)
|
||||
endif()
|
||||
|
||||
if (DEFINED ARTIFACT_DIR)
|
||||
if(DEFINED ARTIFACT_DIR)
|
||||
set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE)
|
||||
set(${ARTIFACT_PACKAGE}_SOURCE_DIR "${ARTIFACT_DIR}" PARENT_SCOPE)
|
||||
else()
|
||||
|
||||
10
README.md
10
README.md
@@ -25,9 +25,9 @@ It is written in C++ with portability in mind, and we actively maintain builds f
|
||||
<img src="https://img.shields.io/discord/1367654015269339267?color=5865F2&label=Eden&logo=discord&logoColor=white"
|
||||
alt="Discord">
|
||||
</a>
|
||||
<a href="https://rvlt.gg/qKgFEAbH">
|
||||
<img src="https://img.shields.io/revolt/invite/qKgFEAbH?color=d61f3a&label=Revolt"
|
||||
alt="Revolt">
|
||||
<a href="https://stt.gg/qKgFEAbH">
|
||||
<img src="https://img.shields.io/revolt/invite/qKgFEAbH?color=d61f3a&label=Stoat"
|
||||
alt="Stoat">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -52,10 +52,10 @@ Check out our [website](https://eden-emu.dev) for the latest news on exciting fe
|
||||
|
||||
## Development
|
||||
|
||||
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Revolt](https://rvlt.gg/qKgFEAbH).
|
||||
Most of the development happens on our Git server. It is also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussions, please join us on [Discord](https://discord.gg/HstXbPch7X) or [Stoat](https://stt.gg/qKgFEAbH).
|
||||
You can also follow us on [X (Twitter)](https://nitter.poast.org/edenemuofficial) for updates and announcements.
|
||||
|
||||
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Revolt to learn more about the current state of the emulator.
|
||||
If you would like to contribute, we are open to new developers and pull requests. Please ensure that your work is of a high standard and properly documented. You can also contact any of the developers on Discord or Stoat to learn more about the current state of the emulator.
|
||||
|
||||
See the [sign-up instructions](docs/SIGNUP.md) for information on registration.
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ If your initial configure failed:
|
||||
- Evaluate the error and find any related settings
|
||||
- See the [CPM docs](CPM.md) to see if you may need to forcefully bundle any packages
|
||||
|
||||
Otherwise, feel free to ask for help in Revolt or Discord.
|
||||
Otherwise, feel free to ask for help in Stoat or Discord.
|
||||
|
||||
## Caveats
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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`
|
||||
@@ -10,12 +10,13 @@ Global Options:
|
||||
|
||||
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 -->
|
||||
- [For Packagers](#for-packagers)
|
||||
- [Network Sandbox](#network-sandbox)
|
||||
- [Unsandboxed](#unsandboxed)
|
||||
|
||||
## AddPackage
|
||||
|
||||
@@ -43,4 +44,16 @@ For an example of how this might be implemented in an application, see Eden's im
|
||||
|
||||
- [`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)
|
||||
- [`deps_dialog.cpp`](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/src/yuzu/deps_dialog.cpp)
|
||||
|
||||
## For Packagers
|
||||
|
||||
If you are packaging a project that uses CPMUtil, read this!
|
||||
|
||||
### Network Sandbox
|
||||
|
||||
For sandboxed environments (e.g. Gentoo, nixOS) you must install all dependencies to the system beforehand and set `-DCPMUTIL_FORCE_SYSTEM=ON`. If a dependency is missing, get creating!
|
||||
|
||||
### Unsandboxed
|
||||
|
||||
For others (AUR, MPR, etc). CPMUtil will handle everything for you, including if some of the project's dependencies are missing from your distribution's repositories. That is pretty much half the reason I created this behemoth, after all.
|
||||
@@ -18,6 +18,7 @@ import android.content.IntentFilter
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Icon
|
||||
import android.hardware.input.InputManager
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
@@ -63,11 +64,12 @@ import kotlin.math.roundToInt
|
||||
import org.yuzu.yuzu_emu.utils.ForegroundService
|
||||
import androidx.core.os.BundleCompat
|
||||
|
||||
class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager.InputDeviceListener {
|
||||
private lateinit var binding: ActivityEmulationBinding
|
||||
|
||||
var isActivityRecreated = false
|
||||
private lateinit var nfcReader: NfcReader
|
||||
private lateinit var inputManager: InputManager
|
||||
|
||||
private var touchDownTime: Long = 0
|
||||
private val maxTapDuration = 500L
|
||||
@@ -140,6 +142,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
nfcReader = NfcReader(this)
|
||||
nfcReader.initialize()
|
||||
|
||||
inputManager = getSystemService(INPUT_SERVICE) as InputManager
|
||||
inputManager.registerInputDeviceListener(this, null)
|
||||
|
||||
foregroundService = Intent(this, ForegroundService::class.java)
|
||||
startForegroundService(foregroundService)
|
||||
|
||||
@@ -206,9 +211,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
inputManager.unregisterInputDeviceListener(this)
|
||||
stopForegroundService(this)
|
||||
NativeLibrary.playTimeManagerStop()
|
||||
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
@@ -244,8 +249,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
|
||||
event.device?.isVirtual == false
|
||||
|
||||
if (event.source and InputDevice.SOURCE_JOYSTICK != InputDevice.SOURCE_JOYSTICK &&
|
||||
event.source and InputDevice.SOURCE_GAMEPAD != InputDevice.SOURCE_GAMEPAD &&
|
||||
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
|
||||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
|
||||
|
||||
if (!isControllerInput &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
|
||||
!isPhysicalKeyboard
|
||||
) {
|
||||
@@ -256,12 +263,18 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
return super.dispatchKeyEvent(event)
|
||||
}
|
||||
|
||||
if (isControllerInput && event.action == KeyEvent.ACTION_DOWN) {
|
||||
notifyControllerInput()
|
||||
}
|
||||
|
||||
return InputHandler.dispatchKeyEvent(event)
|
||||
}
|
||||
|
||||
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 &&
|
||||
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
|
||||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
|
||||
|
||||
if (!isControllerInput &&
|
||||
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
|
||||
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE
|
||||
) {
|
||||
@@ -277,9 +290,54 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
return true
|
||||
}
|
||||
|
||||
if (isControllerInput) {
|
||||
notifyControllerInput()
|
||||
}
|
||||
|
||||
return InputHandler.dispatchGenericMotionEvent(event)
|
||||
}
|
||||
|
||||
private fun notifyControllerInput() {
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||
val emulationFragment =
|
||||
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
emulationFragment?.onControllerInputDetected()
|
||||
}
|
||||
|
||||
private fun isGameController(deviceId: Int): Boolean {
|
||||
val device = InputDevice.getDevice(deviceId) ?: return false
|
||||
val sources = device.sources
|
||||
return sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
|
||||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
|
||||
}
|
||||
|
||||
override fun onInputDeviceAdded(deviceId: Int) {
|
||||
if (isGameController(deviceId)) {
|
||||
InputHandler.updateControllerData()
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||
val emulationFragment =
|
||||
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
emulationFragment?.onControllerConnected()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInputDeviceRemoved(deviceId: Int) {
|
||||
InputHandler.updateControllerData()
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||
val emulationFragment =
|
||||
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
emulationFragment?.onControllerDisconnected()
|
||||
}
|
||||
|
||||
override fun onInputDeviceChanged(deviceId: Int) {
|
||||
if (isGameController(deviceId)) {
|
||||
InputHandler.updateControllerData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSensorChanged(event: SensorEvent) {
|
||||
val rotation = this.display?.rotation
|
||||
if (rotation == Surface.ROTATION_90) {
|
||||
@@ -519,8 +577,10 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
touchDownTime = System.currentTimeMillis()
|
||||
// show overlay immediately on touch and cancel timer
|
||||
if (!emulationViewModel.drawerOpen.value) {
|
||||
// show overlay immediately on touch and cancel timer when only auto-hide is enabled
|
||||
if (!emulationViewModel.drawerOpen.value &&
|
||||
BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.getBoolean() &&
|
||||
!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) {
|
||||
fragment.handler.removeCallbacksAndMessages(null)
|
||||
fragment.showOverlay()
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
||||
|
||||
SOC_OVERLAY_BACKGROUND("soc_overlay_background"),
|
||||
ENABLE_INPUT_OVERLAY_AUTO_HIDE("enable_input_overlay_auto_hide"),
|
||||
HIDE_OVERLAY_ON_CONTROLLER_INPUT("hide_overlay_on_controller_input"),
|
||||
|
||||
PERF_OVERLAY_BACKGROUND("perf_overlay_background"),
|
||||
SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"),
|
||||
|
||||
@@ -387,6 +387,13 @@ abstract class SettingsItem(
|
||||
valueHint = R.string.seconds
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT,
|
||||
titleId = R.string.hide_overlay_on_controller_input,
|
||||
descriptionId = R.string.hide_overlay_on_controller_input_description
|
||||
)
|
||||
)
|
||||
|
||||
put(
|
||||
SwitchSetting(
|
||||
|
||||
@@ -274,6 +274,7 @@ class SettingsFragmentPresenter(
|
||||
sl.apply {
|
||||
add(BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.key)
|
||||
add(IntSetting.INPUT_OVERLAY_AUTO_HIDE.key)
|
||||
add(BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ class AboutFragment : Fragment() {
|
||||
}
|
||||
|
||||
binding.buttonDiscord.setOnClickListener { openLink(getString(R.string.discord_link)) }
|
||||
binding.buttonRevolt.setOnClickListener { openLink(getString(R.string.revolt_link)) }
|
||||
binding.buttonStoat.setOnClickListener { openLink(getString(R.string.stoat_link)) }
|
||||
binding.buttonX.setOnClickListener { openLink(getString(R.string.x_link)) }
|
||||
binding.buttonWebsite.setOnClickListener { openLink(getString(R.string.website_link)) }
|
||||
binding.buttonGithub.setOnClickListener { openLink(getString(R.string.github_link)) }
|
||||
|
||||
@@ -93,7 +93,6 @@ import org.yuzu.yuzu_emu.utils.collect
|
||||
import org.yuzu.yuzu_emu.utils.CustomSettingsHandler
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import kotlin.coroutines.coroutineContext
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
@@ -106,6 +105,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
private var isOverlayVisible = true
|
||||
private var controllerInputReceived = false
|
||||
|
||||
private var _binding: FragmentEmulationBinding? = null
|
||||
|
||||
@@ -656,6 +656,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState)
|
||||
updateQuickOverlayMenuEntry(newState)
|
||||
binding.surfaceInputOverlay.refreshControls()
|
||||
// Sync view visibility with the setting
|
||||
if (newState) {
|
||||
showOverlay()
|
||||
} else {
|
||||
hideOverlay()
|
||||
}
|
||||
NativeConfig.saveGlobalConfig()
|
||||
true
|
||||
}
|
||||
@@ -1901,7 +1907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): AmiiboState =
|
||||
values().firstOrNull { it.value == value } ?: Disabled
|
||||
entries.firstOrNull { it.value == value } ?: Disabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1914,7 +1920,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): AmiiboLoadResult =
|
||||
values().firstOrNull { it.value == value } ?: Unknown
|
||||
entries.firstOrNull { it.value == value } ?: Unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1971,6 +1977,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
fun showOverlay() {
|
||||
if (!isOverlayVisible) {
|
||||
isOverlayVisible = true
|
||||
// Reset controller input flag so controller can hide overlay again
|
||||
controllerInputReceived = false
|
||||
ViewUtils.showView(binding.surfaceInputOverlay, 500)
|
||||
}
|
||||
}
|
||||
@@ -1978,7 +1986,26 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
private fun hideOverlay() {
|
||||
if (isOverlayVisible) {
|
||||
isOverlayVisible = false
|
||||
ViewUtils.hideView(binding.surfaceInputOverlay, 500)
|
||||
ViewUtils.hideView(binding.surfaceInputOverlay)
|
||||
}
|
||||
}
|
||||
|
||||
fun onControllerInputDetected() {
|
||||
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
|
||||
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
|
||||
if (controllerInputReceived) return
|
||||
controllerInputReceived = true
|
||||
hideOverlay()
|
||||
}
|
||||
|
||||
fun onControllerConnected() {
|
||||
controllerInputReceived = false
|
||||
}
|
||||
|
||||
fun onControllerDisconnected() {
|
||||
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
|
||||
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
|
||||
controllerInputReceived = false
|
||||
showOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@ namespace AndroidSettings {
|
||||
Settings::Setting<u32> input_overlay_auto_hide{linkage, 5, "input_overlay_auto_hide",
|
||||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Default, true, true, &enable_input_overlay_auto_hide};
|
||||
Settings::Setting<bool> hide_overlay_on_controller_input{linkage, false,
|
||||
"hide_overlay_on_controller_input",
|
||||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Default, true,
|
||||
true};
|
||||
Settings::Setting<bool> perf_overlay_background{linkage, false, "perf_overlay_background",
|
||||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Default, true,
|
||||
|
||||
@@ -220,12 +220,12 @@
|
||||
app:iconPadding="0dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_revolt"
|
||||
android:id="@+id/button_stoat"
|
||||
style="@style/EdenButton.Secondary"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
app:icon="@drawable/ic_revolt"
|
||||
app:icon="@drawable/ic_stoat"
|
||||
app:iconGravity="textStart"
|
||||
app:iconSize="24dp"
|
||||
app:iconPadding="0dp" />
|
||||
@@ -270,4 +270,4 @@
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -215,12 +215,12 @@
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/EdenButton.Secondary"
|
||||
android:id="@+id/button_revolt"
|
||||
android:id="@+id/button_stoat"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:icon="@drawable/ic_revolt"
|
||||
app:icon="@drawable/ic_stoat"
|
||||
app:iconSize="24dp"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp" />
|
||||
@@ -235,7 +235,7 @@
|
||||
app:icon="@drawable/ic_x"
|
||||
app:iconSize="24dp"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="0dp" />
|
||||
app:iconPadding="0dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/EdenButton.Secondary"
|
||||
@@ -267,4 +267,4 @@
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
<string name="overlay_auto_hide">Overlay Auto Hide</string>
|
||||
<string name="overlay_auto_hide_description">Automatically hide the touch controls overlay after the specified time of inactivity.</string>
|
||||
<string name="enable_input_overlay_auto_hide">Enable Overlay Auto Hide</string>
|
||||
<string name="hide_overlay_on_controller_input">Hide Overlay on Controller Input</string>
|
||||
<string name="hide_overlay_on_controller_input_description">Automatically hide the touch controls overlay when a physical controller is used. Overlay reappears when controller is disconnected.</string>
|
||||
|
||||
<string name="input_overlay_options">Input Overlay</string>
|
||||
<string name="input_overlay_options_description">Configure on-screen controls</string>
|
||||
@@ -445,7 +447,7 @@
|
||||
<string name="user_data_export_cancelled">Export cancelled</string>
|
||||
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
||||
<string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string>
|
||||
<string name="revolt_link" translatable="false">https://rvlt.gg/qKgFEAbH</string>
|
||||
<string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string>
|
||||
<string name="x_link" translatable="false">https://nitter.poast.org/edenemuofficial</string>
|
||||
<string name="website_link" translatable="false">https://eden-emu.dev</string>
|
||||
<string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string>
|
||||
|
||||
@@ -17,6 +17,8 @@ add_library(core STATIC
|
||||
constants.h
|
||||
core.cpp
|
||||
core.h
|
||||
game_settings.cpp
|
||||
game_settings.h
|
||||
core_timing.cpp
|
||||
core_timing.h
|
||||
cpu_manager.cpp
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "game_settings.h"
|
||||
#include "audio_core/audio_core.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -292,48 +293,6 @@ struct System::Impl {
|
||||
return SystemResultStatus::Success;
|
||||
}
|
||||
|
||||
|
||||
void LoadOverrides(u64 programId) const {
|
||||
std::string vendor = gpu_core->Renderer().GetDeviceVendor();
|
||||
LOG_INFO(Core, "GPU Vendor: {}", vendor);
|
||||
|
||||
// Reset all per-game flags
|
||||
Settings::values.use_squashed_iterated_blend = false;
|
||||
|
||||
// Insert PC overrides here
|
||||
|
||||
#ifdef ANDROID
|
||||
// Example on how to set a setting based on the program ID and vendor
|
||||
if (programId == 0x010028600EBDA000 && vendor == "Mali") { // Mario 3d World
|
||||
// Settings::values.example = true;
|
||||
}
|
||||
|
||||
// Example array of program IDs
|
||||
const std::array<u64, 10> example_array = {
|
||||
//0xprogramId
|
||||
0x0004000000033400, // Game 1
|
||||
0x0004000000033500 // Game 2
|
||||
// And so on
|
||||
};
|
||||
|
||||
for (auto id : example_array) {
|
||||
if (programId == id) {
|
||||
// Settings::values.example = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Ninja Gaiden Ragebound
|
||||
constexpr u64 ngr = 0x0100781020710000ULL;
|
||||
|
||||
if (programId == ngr) {
|
||||
LOG_INFO(Core, "Enabling game specifc override: use_squashed_iterated_blend");
|
||||
Settings::values.use_squashed_iterated_blend = true;
|
||||
}
|
||||
}
|
||||
|
||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath,
|
||||
Service::AM::FrontendAppletParameters& params) {
|
||||
@@ -419,7 +378,8 @@ struct System::Impl {
|
||||
LOG_ERROR(Core, "Failed to find program id for ROM");
|
||||
}
|
||||
|
||||
LoadOverrides(program_id);
|
||||
|
||||
GameSettings::LoadOverrides(program_id, gpu_core->Renderer());
|
||||
if (auto room_member = Network::GetRoomMember().lock()) {
|
||||
Network::GameInfo game_info;
|
||||
game_info.name = name;
|
||||
|
||||
140
src/core/game_settings.cpp
Normal file
140
src/core/game_settings.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "core/game_settings.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
namespace Core::GameSettings {
|
||||
|
||||
static GPUVendor GetGPU(const std::string& gpu_vendor_string) {
|
||||
struct Entry { const char* name; GPUVendor vendor; };
|
||||
static constexpr Entry GpuVendor[] = {
|
||||
// NVIDIA
|
||||
{"NVIDIA", GPUVendor::Nvidia},
|
||||
{"Nouveau", GPUVendor::Nvidia},
|
||||
{"NVK", GPUVendor::Nvidia},
|
||||
{"Tegra", GPUVendor::Nvidia},
|
||||
// AMD
|
||||
{"AMD", GPUVendor::AMD},
|
||||
{"RadeonSI", GPUVendor::AMD},
|
||||
{"RADV", GPUVendor::AMD},
|
||||
{"AMDVLK", GPUVendor::AMD},
|
||||
{"R600", GPUVendor::AMD},
|
||||
// Intel
|
||||
{"Intel", GPUVendor::Intel},
|
||||
{"ANV", GPUVendor::Intel},
|
||||
{"i965", GPUVendor::Intel},
|
||||
{"i915", GPUVendor::Intel},
|
||||
{"OpenSWR", GPUVendor::Intel},
|
||||
// Apple
|
||||
{"Apple", GPUVendor::Apple},
|
||||
{"MoltenVK", GPUVendor::Apple},
|
||||
// Qualcomm / Adreno
|
||||
{"Qualcomm", GPUVendor::Qualcomm},
|
||||
{"Turnip", GPUVendor::Qualcomm},
|
||||
// ARM / Mali
|
||||
{"Mali", GPUVendor::ARM},
|
||||
{"PanVK", GPUVendor::ARM},
|
||||
// Imagination / PowerVR
|
||||
{"PowerVR", GPUVendor::Imagination},
|
||||
{"PVR", GPUVendor::Imagination},
|
||||
// Microsoft / WARP / D3D12 GL
|
||||
{"D3D12", GPUVendor::Microsoft},
|
||||
{"Microsoft", GPUVendor::Microsoft},
|
||||
{"WARP", GPUVendor::Microsoft},
|
||||
};
|
||||
|
||||
for (const auto& entry : GpuVendor) {
|
||||
if (gpu_vendor_string == entry.name) {
|
||||
return entry.vendor;
|
||||
}
|
||||
}
|
||||
|
||||
// legacy (shouldn't be needed anymore, but just in case)
|
||||
std::string gpu = gpu_vendor_string;
|
||||
std::transform(gpu.begin(), gpu.end(), gpu.begin(), [](unsigned char c){ return (char)std::tolower(c); });
|
||||
if (gpu.find("geforce") != std::string::npos) {
|
||||
return GPUVendor::Nvidia;
|
||||
}
|
||||
if (gpu.find("radeon") != std::string::npos || gpu.find("ati") != std::string::npos) {
|
||||
return GPUVendor::AMD;
|
||||
}
|
||||
|
||||
return GPUVendor::Unknown;
|
||||
}
|
||||
|
||||
static OS DetectOS() {
|
||||
#if defined(_WIN32)
|
||||
return OS::Windows;
|
||||
#elif defined(__FIREOS__)
|
||||
return OS::FireOS;
|
||||
#elif defined(__ANDROID__)
|
||||
return OS::Android;
|
||||
#elif defined(__OHOS__)
|
||||
return OS::HarmonyOS;
|
||||
#elif defined(__HAIKU__)
|
||||
return OS::HaikuOS;
|
||||
#elif defined(__DragonFly__)
|
||||
return OS::DragonFlyBSD;
|
||||
#elif defined(__NetBSD__)
|
||||
return OS::NetBSD;
|
||||
#elif defined(__OpenBSD__)
|
||||
return OS::OpenBSD;
|
||||
#elif defined(_AIX)
|
||||
return OS::AIX;
|
||||
#elif defined(__managarm__)
|
||||
return OS::Managarm;
|
||||
#elif defined(__redox__)
|
||||
return OS::RedoxOS;
|
||||
#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
||||
return OS::IOS;
|
||||
#elif defined(__APPLE__)
|
||||
return OS::MacOS;
|
||||
#elif defined(__FreeBSD__)
|
||||
return OS::FreeBSD;
|
||||
#elif defined(__sun) && defined(__SVR4)
|
||||
return OS::Solaris;
|
||||
#elif defined(__linux__)
|
||||
return OS::Linux;
|
||||
#else
|
||||
return OS::Unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer) {
|
||||
EnvironmentInfo env{};
|
||||
env.os = DetectOS();
|
||||
env.vendor_string = renderer.GetDeviceVendor();
|
||||
env.vendor = GetGPU(env.vendor_string);
|
||||
return env;
|
||||
}
|
||||
|
||||
void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer) {
|
||||
const auto env = DetectEnvironment(renderer);
|
||||
|
||||
switch (static_cast<TitleID>(program_id)) {
|
||||
case TitleID::NinjaGaidenRagebound:
|
||||
Settings::values.use_squashed_iterated_blend = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_INFO(Core, "Applied game settings for title ID {:016X} on OS {}, GPU vendor {} ({})",
|
||||
program_id,
|
||||
static_cast<int>(env.os),
|
||||
static_cast<int>(env.vendor),
|
||||
env.vendor_string);
|
||||
}
|
||||
|
||||
} // namespace Core::GameSettings
|
||||
60
src/core/game_settings.h
Normal file
60
src/core/game_settings.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace VideoCore { class RendererBase; }
|
||||
|
||||
namespace Core::GameSettings {
|
||||
|
||||
enum class OS {
|
||||
Windows,
|
||||
Linux,
|
||||
MacOS,
|
||||
IOS,
|
||||
Android,
|
||||
FireOS,
|
||||
HarmonyOS,
|
||||
FreeBSD,
|
||||
DragonFlyBSD,
|
||||
NetBSD,
|
||||
OpenBSD,
|
||||
HaikuOS,
|
||||
AIX,
|
||||
Managarm,
|
||||
RedoxOS,
|
||||
Solaris,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
enum class GPUVendor {
|
||||
Nvidia,
|
||||
AMD,
|
||||
Intel,
|
||||
Apple,
|
||||
Qualcomm,
|
||||
ARM,
|
||||
Imagination,
|
||||
Microsoft,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
enum class TitleID : std::uint64_t {
|
||||
NinjaGaidenRagebound = 0x0100781020710000ULL
|
||||
};
|
||||
|
||||
struct EnvironmentInfo {
|
||||
OS os{OS::Unknown};
|
||||
GPUVendor vendor{GPUVendor::Unknown};
|
||||
std::string vendor_string; // raw string from driver
|
||||
};
|
||||
|
||||
EnvironmentInfo DetectEnvironment(const VideoCore::RendererBase& renderer);
|
||||
|
||||
void LoadOverrides(std::uint64_t program_id, const VideoCore::RendererBase& renderer);
|
||||
|
||||
} // namespace Core::GameSettings
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/expected.h"
|
||||
|
||||
// All the constants in this file come from http://switchbrew.org/index.php?title=Error_codes
|
||||
// All the constants in this file come from <http://switchbrew.org/index.php?title=Error_codes>
|
||||
|
||||
/**
|
||||
* Identifies the module which caused the error. Error codes can be propagated through a call
|
||||
@@ -87,6 +87,7 @@ enum class ErrorModule : u32 {
|
||||
AM = 128,
|
||||
PlayReport = 129,
|
||||
AHID = 130,
|
||||
APPLET = 131,
|
||||
Qlaunch = 132,
|
||||
PCV = 133,
|
||||
USBPD = 134,
|
||||
@@ -113,8 +114,8 @@ enum class ErrorModule : u32 {
|
||||
NPNSHTTPSTREAM = 155,
|
||||
IDLE = 156,
|
||||
ARP = 157,
|
||||
SWKBD = 158,
|
||||
BOOT = 159,
|
||||
UPDATER = 158,
|
||||
SWKBD = 159,
|
||||
NetDiag = 160,
|
||||
NFCMifare = 161,
|
||||
UserlandAssert = 162,
|
||||
@@ -125,7 +126,8 @@ enum class ErrorModule : u32 {
|
||||
BGTC = 167,
|
||||
UserlandCrash = 168,
|
||||
SASBUS = 169,
|
||||
PI = 170,
|
||||
PL = 170,
|
||||
CDMSC = 171,
|
||||
AudioCtrl = 172,
|
||||
LBL = 173,
|
||||
JIT = 175,
|
||||
@@ -137,23 +139,30 @@ enum class ErrorModule : u32 {
|
||||
Dauth = 181,
|
||||
STDFU = 182,
|
||||
DBG = 183,
|
||||
CDACM = 184,
|
||||
TCAP = 185,
|
||||
DHCPS = 186,
|
||||
SPI = 187,
|
||||
AVM = 188,
|
||||
PWM = 189,
|
||||
DNSServer = 190,
|
||||
RTC = 191,
|
||||
Regulator = 192,
|
||||
LED = 193,
|
||||
HTCTool = 194,
|
||||
SIO = 195,
|
||||
PCM = 196,
|
||||
CLKRST = 197,
|
||||
POWCTL = 198,
|
||||
HIDDriver = 199,
|
||||
DMA = 200,
|
||||
AudioOld = 201,
|
||||
HID = 202,
|
||||
LDN = 203,
|
||||
CS = 204,
|
||||
Irsensor = 205,
|
||||
Capture = 206,
|
||||
MM = 207,
|
||||
Manu = 208,
|
||||
ATK = 209,
|
||||
WEB = 210,
|
||||
@@ -166,19 +175,24 @@ enum class ErrorModule : u32 {
|
||||
MigrationLdcServ = 217,
|
||||
HIDBUS = 218,
|
||||
ENS = 219,
|
||||
ND = 220,
|
||||
NDD = 221,
|
||||
ToyCon = 222,
|
||||
WebSocket = 223,
|
||||
SocketIO = 224,
|
||||
DCDMTP = 227,
|
||||
PGL = 228,
|
||||
Notification = 229,
|
||||
INS = 230,
|
||||
LP2P = 231,
|
||||
RCD = 232,
|
||||
LCM40607 = 233,
|
||||
ICM40607 = 233,
|
||||
PRC = 235,
|
||||
TMAHTC = 237,
|
||||
ECTX = 238,
|
||||
BridgeCtrl = 237,
|
||||
ErrContext = 238,
|
||||
MNPP = 239,
|
||||
HSHL = 240,
|
||||
RINGCON = 241,
|
||||
CAPMTP = 242,
|
||||
DP2HDMI = 244,
|
||||
Cradle = 245,
|
||||
@@ -186,6 +200,8 @@ enum class ErrorModule : u32 {
|
||||
Icm42607p = 248,
|
||||
NDRM = 250,
|
||||
Fst2 = 251,
|
||||
TS = 253,
|
||||
SPLAY = 260,
|
||||
Nex = 306,
|
||||
NPLN = 321,
|
||||
TSPM = 499,
|
||||
|
||||
@@ -36,10 +36,6 @@ void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* pro
|
||||
m_buffer_sharing_enabled = false;
|
||||
m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
|
||||
mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
|
||||
|
||||
if (m_applet_id != AppletId::Application) {
|
||||
(void)this->IsSystemBufferSharingEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayLayerManager::Finalize() {
|
||||
@@ -80,11 +76,10 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
|
||||
if (m_applet_id != AppletId::Application) {
|
||||
(void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id);
|
||||
if (m_applet_id == AppletId::OverlayDisplay) {
|
||||
static constexpr s32 kOverlayBackgroundZ = -1;
|
||||
(void)m_manager_display_service->SetLayerZIndex(kOverlayBackgroundZ, *out_layer_id);
|
||||
(void)m_manager_display_service->SetLayerZIndex(-1, *out_layer_id);
|
||||
(void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true);
|
||||
} else {
|
||||
static constexpr s32 kOverlayZ = 3;
|
||||
(void)m_manager_display_service->SetLayerZIndex(kOverlayZ, *out_layer_id);
|
||||
(void)m_manager_display_service->SetLayerZIndex(1, *out_layer_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +126,7 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
|
||||
s32 initial_z = 1;
|
||||
if (m_applet_id == AppletId::OverlayDisplay) {
|
||||
initial_z = -1;
|
||||
(void)m_display_service->GetContainer()->SetLayerIsOverlay(m_system_shared_layer_id, true);
|
||||
}
|
||||
m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id);
|
||||
R_SUCCEED();
|
||||
|
||||
@@ -88,13 +88,13 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
|
||||
{181, nullptr, "UpgradeLaunchRequiredVersion"},
|
||||
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
|
||||
{200, nullptr, "GetLastApplicationExitReason"},
|
||||
{210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"}, // [20.0.0+]
|
||||
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"}, // [20.0.0+]
|
||||
{220, nullptr, "Unknown220"}, // [20.0.0+]
|
||||
{300, nullptr, "Unknown300"}, // [20.0.0+]
|
||||
{310, nullptr, "Unknown310"}, // [20.0.0+]
|
||||
{320, nullptr, "Unknown320"}, // [20.0.0+]
|
||||
{330, nullptr, "Unknown330"}, // [20.0.0+]
|
||||
{210, D<&IApplicationFunctions::GetLaunchRequiredVersionUpgrade>, "GetLaunchRequiredVersionUpgrade"}, //20.0.0+
|
||||
{211, nullptr, "GetLaunchRequiredVersionUpgradeStatus"}, //20.0.0+
|
||||
{220, nullptr, "Unknown220"}, //20.0.0+
|
||||
{300, nullptr, "CreateMovieWriter"}, //20.0.0+
|
||||
{310, nullptr, "Unknown310"}, //20.0.0+
|
||||
{320, nullptr, "Unknown320"}, //20.0.0+
|
||||
{330, nullptr, "Unknown330"}, //20.0.0+
|
||||
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
|
||||
{1000, nullptr, "CreateMovieMaker"},
|
||||
{1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
|
||||
|
||||
@@ -18,7 +18,7 @@ IAudioController::IAudioController(Core::System& system_)
|
||||
{2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
|
||||
{3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
|
||||
{4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
|
||||
{5, nullptr, "Unknown5"},
|
||||
{5, nullptr, "Unknown5"}, //20.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Service::AM {
|
||||
{20, D<&IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
|
||||
{21, nullptr, "SetHandlingTouchScreenInputEnabled"},
|
||||
{30, nullptr, "SetHealthWarningShowingState"},
|
||||
{31, nullptr, "IsHealthWarningRequired"},
|
||||
{31, D<&IOverlayFunctions::IsHealthWarningRequired>, "IsHealthWarningRequired"},
|
||||
{40, nullptr, "GetApplicationNintendoLogo"},
|
||||
{41, nullptr, "GetApplicationStartupMovie"},
|
||||
{50, nullptr, "SetGpuTimeSliceBoostForApplication"},
|
||||
@@ -69,12 +69,33 @@ namespace Service::AM {
|
||||
Result IOverlayFunctions::GetApplicationIdForLogo(Out<u64> out_application_id) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
// Prefer explicit application_id if available, else fall back to program_id
|
||||
std::shared_ptr<Applet> target_applet;
|
||||
|
||||
auto* window_system = system.GetAppletManager().GetWindowSystem();
|
||||
if (window_system) {
|
||||
target_applet = window_system->GetMainApplet();
|
||||
if (target_applet) {
|
||||
std::scoped_lock lk{target_applet->lock};
|
||||
LOG_DEBUG(Service_AM, "applet_id={}, program_id={:016X}, type={}",
|
||||
static_cast<u32>(target_applet->applet_id), target_applet->program_id,
|
||||
static_cast<u32>(target_applet->type));
|
||||
|
||||
u64 id = target_applet->screen_shot_identity.application_id;
|
||||
if (id == 0) {
|
||||
id = target_applet->program_id;
|
||||
}
|
||||
LOG_DEBUG(Service_AM, "application_id={:016X}", id);
|
||||
*out_application_id = id;
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
u64 id = m_applet->screen_shot_identity.application_id;
|
||||
if (id == 0) {
|
||||
id = m_applet->program_id;
|
||||
}
|
||||
LOG_DEBUG(Service_AM, "application_id={:016X} (fallback)", id);
|
||||
*out_application_id = id;
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -86,6 +107,13 @@ namespace Service::AM {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOverlayFunctions::IsHealthWarningRequired(Out<bool> is_required) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
*is_required = false;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled(bool enabled) {
|
||||
LOG_DEBUG(Service_AM, "called, enabled={}", enabled);
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Service::AM {
|
||||
Result EndToWatchShortHomeButtonMessage();
|
||||
Result GetApplicationIdForLogo(Out<u64> out_application_id);
|
||||
Result SetAutoSleepTimeAndDimmingTimeEnabled(bool enabled);
|
||||
Result IsHealthWarningRequired(Out<bool> is_required);
|
||||
Result SetHandlingHomeButtonShortPressedEnabled(bool enabled);
|
||||
Result Unknown70();
|
||||
|
||||
|
||||
@@ -186,8 +186,6 @@ void WindowSystem::OnSystemButtonPress(SystemButtonType type) {
|
||||
if (m_overlay_display) {
|
||||
std::scoped_lock lk_overlay{m_overlay_display->lock};
|
||||
m_overlay_display->overlay_in_foreground = !m_overlay_display->overlay_in_foreground;
|
||||
// Tie window visibility to foreground state so hidden when not active
|
||||
m_overlay_display->window_visible = m_overlay_display->overlay_in_foreground;
|
||||
LOG_INFO(Service_AM, "Overlay long-press toggle: overlay_in_foreground={} window_visible={}", m_overlay_display->overlay_in_foreground, m_overlay_display->window_visible);
|
||||
}
|
||||
SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingHomeButton);
|
||||
@@ -393,7 +391,7 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
|
||||
s32 z_index = 0;
|
||||
const bool now_foreground = inherited_foreground;
|
||||
if (applet->applet_id == AppletId::OverlayDisplay) {
|
||||
z_index = applet->overlay_in_foreground ? 100000 : -100000;
|
||||
z_index = applet->overlay_in_foreground ? 100000 : -1;
|
||||
} else if (now_foreground && !is_obscured) {
|
||||
z_index = 2;
|
||||
} else if (now_foreground) {
|
||||
|
||||
@@ -30,7 +30,7 @@ IAudioController::IAudioController(Core::System& system_)
|
||||
{3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
|
||||
{4, D<&IAudioController::IsTargetMute>, "IsTargetMute"},
|
||||
{5, D<&IAudioController::SetTargetMute>, "SetTargetMute"},
|
||||
{6, nullptr, "IsTargetConnected"},
|
||||
{6, nullptr, "IsTargetConnected"}, //20.0.0+
|
||||
{7, nullptr, "SetDefaultTarget"},
|
||||
{8, nullptr, "GetDefaultTarget"},
|
||||
{9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
|
||||
@@ -67,7 +67,8 @@ IAudioController::IAudioController(Core::System& system_)
|
||||
{40, nullptr, "GetSystemInformationForDebug"},
|
||||
{41, nullptr, "SetVolumeButtonLongPressTime"},
|
||||
{42, nullptr, "SetNativeVolumeForDebug"},
|
||||
{5000, D<&IAudioController::Unknown5000>, "Unknown5000"},
|
||||
{43, nullptr, "Unknown43"}, //21.0.0+
|
||||
{5000, D<&IAudioController::Unknown5000>, "Unknown5000"}, //19.0.0+
|
||||
{10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
|
||||
{10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
|
||||
{10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
|
||||
@@ -76,13 +77,13 @@ IAudioController::IAudioController(Core::System& system_)
|
||||
{10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
|
||||
{10103, nullptr, "GetAudioOutputTargetForPlayReport"},
|
||||
{10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
|
||||
{10200, nullptr, "Unknown10200"}, // [20.0.0+]
|
||||
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
|
||||
{50001, nullptr, "OverrideDefaultTargetForDebug"},
|
||||
{50003, nullptr, "SetForceOverrideExternalDeviceNameForDebug"},
|
||||
{50004, nullptr, "ClearForceOverrideExternalDeviceNameForDebug"}
|
||||
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, //14.0.0-19.0.1
|
||||
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, //14.0.0-19.0.1
|
||||
{10200, nullptr, "Unknown10200"}, //20.0.0+
|
||||
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, //15.0.0-18.1.0
|
||||
{50001, nullptr, "OverrideDefaultTargetForDebug"}, //19.0.0-19.0.1
|
||||
{50003, nullptr, "SetForceOverrideExternalDeviceNameForDebug"}, //19.0.0+
|
||||
{50004, nullptr, "ClearForceOverrideExternalDeviceNameForDebug"} //19.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -32,13 +32,13 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u
|
||||
{12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
|
||||
{13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
|
||||
{14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
|
||||
{15, nullptr, "AcquireAudioInputDeviceNotification"}, // 17.0.0+
|
||||
{16, nullptr, "ReleaseAudioInputDeviceNotification"}, // 17.0.0+
|
||||
{17, nullptr, "AcquireAudioOutputDeviceNotification"}, // 17.0.0+
|
||||
{18, nullptr, "ReleaseAudioOutputDeviceNotification"}, // 17.0.0+
|
||||
{19, nullptr, "SetAudioDeviceOutputVolumeAutoTuneEnabled"}, // 18.0.0+
|
||||
{20, nullptr, "IsAudioDeviceOutputVolumeAutoTuneEnabled"}, // 18.0.0+
|
||||
{21, nullptr, "IsActiveOutputDeviceEstimatedLowLatency"} // 21.0.0+
|
||||
{15, nullptr, "AcquireAudioInputDeviceNotification"}, //17.0.0+
|
||||
{16, nullptr, "ReleaseAudioInputDeviceNotification"}, //17.0.0+
|
||||
{17, nullptr, "AcquireAudioOutputDeviceNotification"}, //17.0.0+
|
||||
{18, nullptr, "ReleaseAudioOutputDeviceNotification"}, //17.0.0+
|
||||
{19, nullptr, "SetAudioDeviceOutputVolumeAutoTuneEnabled"}, //18.0.0+
|
||||
{20, nullptr, "IsAudioDeviceOutputVolumeAutoTuneEnabled"}, //18.0.0+
|
||||
{21, nullptr, "IsActiveOutputDeviceEstimatedLowLatency"} //21.0.0+
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
|
||||
@@ -43,21 +43,21 @@ IBcatService::IBcatService(Core::System& system_, BcatBackend& backend_)
|
||||
{20401, nullptr, "UnregisterSystemApplicationDeliveryTask"},
|
||||
{20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"},
|
||||
{30100, D<&IBcatService::SetPassphrase>, "SetPassphrase"},
|
||||
{30101, nullptr, "Unknown30101"},
|
||||
{30102, nullptr, "Unknown30102"},
|
||||
{30101, nullptr, "Unknown30101"}, //2.0.0-2.3.0
|
||||
{30102, nullptr, "Unknown30102"}, //2.0.0-2.3.0
|
||||
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
|
||||
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
|
||||
{30202, nullptr, "BlockDeliveryTask"},
|
||||
{30203, nullptr, "UnblockDeliveryTask"},
|
||||
{30210, nullptr, "SetDeliveryTaskTimer"},
|
||||
{30300, D<&IBcatService::RegisterSystemApplicationDeliveryTasks>, "RegisterSystemApplicationDeliveryTasks"},
|
||||
{90100, nullptr, "EnumerateBackgroundDeliveryTask"},
|
||||
{90101, nullptr, "Unknown90101"},
|
||||
{90100, nullptr, "GetDeliveryTaskList"},
|
||||
{90101, nullptr, "GetDeliveryTaskListForSystem"}, //11.0.0+
|
||||
{90200, nullptr, "GetDeliveryList"},
|
||||
{90201, D<&IBcatService::ClearDeliveryCacheStorage>, "ClearDeliveryCacheStorage"},
|
||||
{90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"},
|
||||
{90300, nullptr, "GetPushNotificationLog"},
|
||||
{90301, nullptr, "Unknown90301"},
|
||||
{90301, nullptr, "GetDeliveryCacheStorageUsage"}, //11.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -12,19 +15,19 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I
|
||||
{10100, D<&INewsService::PostLocalNews>, "PostLocalNews"},
|
||||
{20100, nullptr, "SetPassphrase"},
|
||||
{30100, D<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"},
|
||||
{30101, nullptr, "GetTopicList"},
|
||||
{30110, nullptr, "Unknown30110"},
|
||||
{30101, nullptr, "GetTopicList"}, //3.0.0+
|
||||
{30110, nullptr, "Unknown30110"}, //6.0.0+
|
||||
{30200, D<&INewsService::IsSystemUpdateRequired>, "IsSystemUpdateRequired"},
|
||||
{30201, nullptr, "Unknown30201"},
|
||||
{30210, nullptr, "Unknown30210"},
|
||||
{30201, nullptr, "Unknown30201"}, //8.0.0+
|
||||
{30210, nullptr, "Unknown30210"}, //10.0.0+
|
||||
{30300, nullptr, "RequestImmediateReception"},
|
||||
{30400, nullptr, "DecodeArchiveFile"},
|
||||
{30500, nullptr, "Unknown30500"},
|
||||
{30900, nullptr, "Unknown30900"},
|
||||
{30901, nullptr, "Unknown30901"},
|
||||
{30902, nullptr, "Unknown30902"},
|
||||
{30400, nullptr, "DecodeArchiveFile"}, //3.0.0-18.1.0
|
||||
{30500, nullptr, "Unknown30500"}, //8.0.0+
|
||||
{30900, nullptr, "Unknown30900"}, //1.0.0
|
||||
{30901, nullptr, "Unknown30901"}, //1.0.0
|
||||
{30902, nullptr, "Unknown30902"}, //1.0.0
|
||||
{40100, nullptr, "SetSubscriptionStatus"},
|
||||
{40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"},
|
||||
{40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"}, //3.0.0+
|
||||
{40200, nullptr, "ClearStorage"},
|
||||
{40201, nullptr, "ClearSubscriptionStatusAll"},
|
||||
{90100, nullptr, "GetNewsDatabaseDump"},
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -77,31 +80,33 @@ public:
|
||||
{57, nullptr, "RegisterAppletResourceUserId"},
|
||||
{58, nullptr, "UnregisterAppletResourceUserId"},
|
||||
{59, nullptr, "SetAppletResourceUserId"},
|
||||
{60, nullptr, "Unknown60"},
|
||||
{61, nullptr, "Unknown61"},
|
||||
{62, nullptr, "Unknown62"},
|
||||
{63, nullptr, "Unknown63"},
|
||||
{64, nullptr, "Unknown64"},
|
||||
{65, nullptr, "Unknown65"},
|
||||
{66, nullptr, "Unknown66"},
|
||||
{67, nullptr, "Unknown67"},
|
||||
{68, nullptr, "Unknown68"},
|
||||
{69, nullptr, "Unknown69"},
|
||||
{70, nullptr, "Unknown70"},
|
||||
{71, nullptr, "Unknown71"},
|
||||
{72, nullptr, "Unknown72"},
|
||||
{73, nullptr, "Unknown73"},
|
||||
{74, nullptr, "Unknown74"},
|
||||
{75, nullptr, "Unknown75"},
|
||||
{76, nullptr, "Unknown76"},
|
||||
{100, nullptr, "Unknown100"},
|
||||
{101, nullptr, "Unknown101"},
|
||||
{110, nullptr, "Unknown110"},
|
||||
{111, nullptr, "Unknown111"},
|
||||
{112, nullptr, "Unknown112"},
|
||||
{113, nullptr, "Unknown113"},
|
||||
{114, nullptr, "Unknown114"},
|
||||
{115, nullptr, "Unknown115"},
|
||||
{60, nullptr, "AcquireBleConnectionParameterUpdateEvent"}, //8.0.0+
|
||||
{61, nullptr, "SetCeLength"}, //8.0.0+
|
||||
{62, nullptr, "EnsureSlotExpansion"}, //9.0.0+
|
||||
{63, nullptr, "IsSlotExpansionEnsured"}, //9.0.0+
|
||||
{64, nullptr, "CancelConnectionTrigger"}, //10.0.0+
|
||||
{65, nullptr, "GetConnectionCapacity"}, //13.0.0+
|
||||
{66, nullptr, "GetWlanMode"}, //13.0.0+
|
||||
{67, nullptr, "IsSlotSavingEnabled"}, //13.0.0+
|
||||
{68, nullptr, "IsSlotSavingForPairingEnabled"}, //13.0.0+
|
||||
{69, nullptr, "AcquireAudioDeviceConnectionEvent"}, //13.0.0+
|
||||
{70, nullptr, "GetConnectedAudioDevices"}, //13.0.0+
|
||||
{71, nullptr, "SetAudioSourceVolume"}, //13.0.0+
|
||||
{72, nullptr, "GetAudioSourceVolume"}, //13.0.0+
|
||||
{73, nullptr, "RequestAudioDeviceConnectionRejection"}, //13.0.0+
|
||||
{74, nullptr, "CancelAudioDeviceConnectionRejection"}, //13.0.0+
|
||||
{75, nullptr, "GetPairedAudioDevices"}, //13.0.0+
|
||||
{76, nullptr, "SetWlanModeWithOption"}, //13.1.0+
|
||||
{100, nullptr, "AcquireConnectionDisallowedEvent"}, //13.0.0+
|
||||
{101, nullptr, "GetUsecaseViolationFactor"}, //13.0.0+
|
||||
{110, nullptr, "GetShortenedDeviceInfo"}, //13.0.0+
|
||||
{111, nullptr, "AcquirePairingCountUpdateEvent"},//13.0.0+
|
||||
{112, nullptr, "Unknown112"}, //14.0.0-14.1.2
|
||||
{113, nullptr, "Unknown113"}, //14.0.0-14.1.2
|
||||
{114, nullptr, "IsFirstAudioControlConnection"}, //14.0.0+
|
||||
{115, nullptr, "GetShortenedDeviceCondition"}, //14.0.0+
|
||||
{116, nullptr, "SetAudioSinkVolume"}, //15.0.0+
|
||||
{117, nullptr, "GetAudioSinkVolume"}, //15.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -17,11 +20,15 @@ IBtmDebug::IBtmDebug(Core::System& system_) : ServiceFramework{system_, "btm:dbg
|
||||
{6, nullptr, "SetTsiMode"},
|
||||
{7, nullptr, "GeneralTest"},
|
||||
{8, nullptr, "HidConnect"},
|
||||
{9, nullptr, "GeneralGet"},
|
||||
{10, nullptr, "GetGattClientDisconnectionReason"},
|
||||
{11, nullptr, "GetBleConnectionParameter"},
|
||||
{12, nullptr, "GetBleConnectionParameterRequest"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{9, nullptr, "GeneralGet"}, //5.0.0+
|
||||
{10, nullptr, "GetGattClientDisconnectionReason"}, //5.0.0+
|
||||
{11, nullptr, "GetBleConnectionParameter"}, //5.1.0+
|
||||
{12, nullptr, "GetBleConnectionParameterRequest"}, //5.1.0+
|
||||
{13, nullptr, "GetDiscoveredDevice"}, //12.0.0+
|
||||
{14, nullptr, "SleepAwakeLoopTest"}, //15.0.0+
|
||||
{15, nullptr, "SleepTest"}, //15.0.0+
|
||||
{16, nullptr, "MinimumAwakeTest"}, //15.0.0+
|
||||
{17, nullptr, "ForceEnableBtm"}, //15.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -60,6 +60,16 @@ public:
|
||||
{38, nullptr, "OwnTicket3"},
|
||||
{39, nullptr, "DeleteAllInactivePersonalizedTicket"},
|
||||
{40, nullptr, "DeletePrepurchaseRecordByNintendoAccountId"},
|
||||
{101, nullptr, "Unknown101"}, //18.0.0+
|
||||
{102, nullptr, "Unknown102"}, //18.0.0+
|
||||
{103, nullptr, "Unknown103"}, //18.0.0+
|
||||
{104, nullptr, "Unknown104"}, //18.0.0+
|
||||
{105, nullptr, "Unknown105"}, //20.0.0+
|
||||
{201, nullptr, "Unknown201"}, //18.0.0+
|
||||
{202, nullptr, "Unknown202"}, //18.0.0+
|
||||
{203, nullptr, "Unknown203"}, //18.0.0+
|
||||
{204, nullptr, "Unknown204"}, //18.0.0+
|
||||
{205, nullptr, "Unknown205"}, //18.0.0+
|
||||
{501, nullptr, "Unknown501"},
|
||||
{502, nullptr, "Unknown502"},
|
||||
{503, nullptr, "GetTitleKey"},
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -67,7 +70,7 @@ public:
|
||||
{20701, &IFriendService::GetPlayHistoryStatistics, "GetPlayHistoryStatistics"},
|
||||
{20800, &IFriendService::LoadUserSetting, "LoadUserSetting"},
|
||||
{20801, nullptr, "SyncUserSetting"},
|
||||
{20900, nullptr, "RequestListSummaryOverlayNotification"},
|
||||
{20900, &IFriendService::RequestListSummaryOverlayNotification, "RequestListSummaryOverlayNotification"},
|
||||
{21000, nullptr, "GetExternalApplicationCatalog"},
|
||||
{22000, nullptr, "GetReceivedFriendInvitationList"},
|
||||
{22001, nullptr, "GetReceivedFriendInvitationDetailedInfo"},
|
||||
@@ -317,6 +320,13 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void RequestListSummaryOverlayNotification(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_Friend, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetReceivedFriendInvitationCountCache(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Friend, "(STUBBED) called, check in out");
|
||||
|
||||
|
||||
@@ -125,13 +125,10 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
|
||||
{250, nullptr, "IsVirtual"},
|
||||
{251, nullptr, "GetAnalogStickModuleParam"},
|
||||
{253, nullptr, "ClearStorageForShipment"}, //19.0.0+
|
||||
{254, nullptr, "Unknown254"},
|
||||
{255, nullptr, "Unknown255"},
|
||||
{256, nullptr, "Unknown256"},
|
||||
{261, nullptr, "UpdateDesignInfo12"},
|
||||
{262, nullptr, "GetUniquePadButtonCount"},
|
||||
{267, nullptr, "Unknown267"},
|
||||
{268, nullptr, "Unknown268"},
|
||||
{261, nullptr, "UpdateDesignInfo12"}, //21.0.0+
|
||||
{262, nullptr, "GetUniquePadButtonCount"}, //21.0.0+
|
||||
{267, nullptr, "SetAnalogStickCalibration"}, //21.0.0+
|
||||
{268, nullptr, "ResetAnalogStickCalibration"}, //21.0.0+
|
||||
{301, nullptr, "GetAbstractedPadHandles"},
|
||||
{302, nullptr, "GetAbstractedPadState"},
|
||||
{303, nullptr, "GetAbstractedPadsState"},
|
||||
@@ -148,6 +145,8 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
|
||||
{331, nullptr, "DetachHdlsVirtualDevice"},
|
||||
{332, nullptr, "SetHdlsState"},
|
||||
{350, nullptr, "AddRegisteredDevice"},
|
||||
{351, nullptr, "GetRegisteredDevicesCountDebug"}, //17.0.0-18.1.0
|
||||
{352, nullptr, "DeleteRegisteredDevicesDebug"}, //17.0.0-18.1.0
|
||||
{400, nullptr, "DisableExternalMcuOnNxDevice"},
|
||||
{401, nullptr, "DisableRailDeviceFiltering"},
|
||||
{402, nullptr, "EnableWiredPairing"},
|
||||
@@ -159,14 +158,30 @@ IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<Resource
|
||||
{551, nullptr, "GetAnalogStickModelData"},
|
||||
{552, nullptr, "ResetAnalogStickModelData"},
|
||||
{600, nullptr, "ConvertPadState"},
|
||||
{601, nullptr, "IsButtonConfigSupported"}, //18.0.0+
|
||||
{602, nullptr, "IsButtonConfigEmbeddedSupported"}, //18.0.0+
|
||||
{603, nullptr, "DeleteButtonConfig"}, //18.0.0+
|
||||
{604, nullptr, "DeleteButtonConfigEmbedded"}, //18.0.0+
|
||||
{605, nullptr, "SetButtonConfigEnabled"}, //18.0.0+
|
||||
{606, nullptr, "SetButtonConfigEmbeddedEnabled"}, //18.0.0+
|
||||
{607, nullptr, "IsButtonConfigEnabled"}, //18.0.0+
|
||||
{608, nullptr, "IsButtonConfigEmbeddedEnabled"}, //18.0.0+
|
||||
{609, nullptr, "SetButtonConfigEmbedded"}, //18.0.0+
|
||||
{610, nullptr, "SetButtonConfigFull"}, //18.0.0+
|
||||
{611, nullptr, "SetButtonConfigLeft"}, //18.0.0+
|
||||
{612, nullptr, "SetButtonConfigRight"}, //18.0.0+
|
||||
{613, nullptr, "GetButtonConfigEmbedded"}, //18.0.0+
|
||||
{614, nullptr, "GetButtonConfigFull"}, //18.0.0+
|
||||
{615, nullptr, "GetButtonConfigLeft"}, //18.0.0+
|
||||
{616, nullptr, "GetButtonConfigRight"}, //18.0.0+
|
||||
{650, nullptr, "AddButtonPlayData"},
|
||||
{651, nullptr, "StartButtonPlayData"},
|
||||
{652, nullptr, "StopButtonPlayData"},
|
||||
{700, nullptr, "Unknown700"},
|
||||
{700, nullptr, "GetRailAttachEventCount"}, //21.0.0+
|
||||
{2000, nullptr, "DeactivateDigitizer"},
|
||||
{2001, nullptr, "SetDigitizerAutoPilotState"},
|
||||
{2002, nullptr, "UnsetDigitizerAutoPilotState"},
|
||||
{2002, nullptr, "ReloadFirmwareDebugSettings"},
|
||||
{3000, nullptr, "ReloadFirmwareDebugSettings"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -70,7 +70,9 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{328, nullptr, "AttachAbstractedPadToNpad"},
|
||||
{329, nullptr, "DetachAbstractedPadAll"},
|
||||
{330, nullptr, "CheckAbstractedPadConnection"},
|
||||
{500, nullptr, "SetAppletResourceUserId"},
|
||||
{332, nullptr, "ConvertAppletDetailedUiTypeFromPlayReportType"}, //19.0.0+
|
||||
{333, nullptr, "SetNpadUserSpgApplet"}, //20.0.0+
|
||||
{334, nullptr, "AcquireUniquePadButtonStateChangedEventHandle"}, //20.0.0+
|
||||
{501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"},
|
||||
{502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"},
|
||||
{503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"},
|
||||
@@ -99,7 +101,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{547, nullptr, "GetAllowedBluetoothLinksCount"},
|
||||
{548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
|
||||
{549, nullptr, "GetConnectableRegisteredDevices"},
|
||||
{551, nullptr, "GetRegisteredDevicesForControllerSupport"},
|
||||
{551, nullptr, "GetRegisteredDevicesForControllerSupport"}, //20.0.0+
|
||||
{700, nullptr, "ActivateUniquePad"},
|
||||
{702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
|
||||
{703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
|
||||
@@ -119,6 +121,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{810, nullptr, "GetUniquePadControllerNumber"},
|
||||
{811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
|
||||
{812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
|
||||
{813, nullptr, "GetDeviceType"},
|
||||
{821, nullptr, "StartAnalogStickManualCalibration"},
|
||||
{822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
|
||||
{823, nullptr, "CancelAnalogStickManualCalibration"},
|
||||
@@ -149,6 +152,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{1009, nullptr, "AcquireAudioControlEventHandle"},
|
||||
{1010, nullptr, "GetAudioControlStates"},
|
||||
{1011, nullptr, "DeactivateAudioControl"},
|
||||
{1012, nullptr, "GetFirmwareVersionStringForUserSupportPage"},
|
||||
{1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
|
||||
{1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
|
||||
{1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
|
||||
@@ -169,6 +173,8 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"},
|
||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
||||
{1157, nullptr, "CancelConnectionTrigger"},
|
||||
{1158, nullptr, "SetConnectionLimitForSplay"}, //20.1.0+
|
||||
{1159, nullptr, "ClearConnectionLimitForSplay"}, //20.1.0+
|
||||
{1200, nullptr, "IsButtonConfigSupported"},
|
||||
{1201, nullptr, "IsButtonConfigEmbeddedSupported"},
|
||||
{1202, nullptr, "DeleteButtonConfig"},
|
||||
@@ -227,16 +233,17 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
|
||||
{1289, nullptr, "SetButtonConfigStorageFull"},
|
||||
{1290, nullptr, "DeleteButtonConfigStorageRight"},
|
||||
{1291, nullptr, "DeleteButtonConfigStorageRight"},
|
||||
{1308, nullptr, "SetButtonConfigVisible"}, // 18.0.0+
|
||||
{1309, nullptr, "IsButtonConfigVisible"}, // 18.0.0+
|
||||
{1320, nullptr, "WakeTouchScreenUp"}, // 17.0.0+
|
||||
{1321, nullptr, "PutTouchScreenToSleep"}, // 17.0.0+
|
||||
{1322, nullptr, "AcquireTouchScreenAsyncWakeCompletedEvent"}, // 20.0.0+
|
||||
{1323, nullptr, "StartTouchScreenAutoTuneForSystemSettings"}, // 21.0.0+
|
||||
{1324, nullptr, "AcquireTouchScreenAutoTuneCompletedEvent"}, // 21.0.0+
|
||||
{1325, nullptr, "IsTouchScreenAutoTuneRequiredForRepairProviderReplacement"}, // 21.0.0+
|
||||
{1326, nullptr, "Unknown1326"}, // 21.0.0+
|
||||
{1420, nullptr, "GetAppletResourceProperty"}, // 19.0.0+
|
||||
{1308, nullptr, "SetButtonConfigVisible"}, //18.0.0+
|
||||
{1309, nullptr, "IsButtonConfigVisible"}, //18.0.0+
|
||||
{1320, nullptr, "WakeTouchScreenUp"}, //17.0.0+
|
||||
{1321, nullptr, "PutTouchScreenToSleep"}, //17.0.0+
|
||||
{1322, nullptr, "AcquireTouchScreenAsyncWakeCompletedEvent"}, //20.0.0+
|
||||
{1323, nullptr, "StartTouchScreenAutoTuneForSystemSettings"}, //21.0.0+
|
||||
{1324, nullptr, "AcquireTouchScreenAutoTuneCompletedEvent"}, //21.0.0+
|
||||
{1325, nullptr, "IsTouchScreenAutoTuneRequiredForRepairProviderReplacement"}, //21.0.0+
|
||||
{1326, nullptr, "SetTouchScreenOffset"}, //21.0.0+
|
||||
{1420, nullptr, "GetAppletResourceProperty"}, //19.0.0+
|
||||
{12010, nullptr, "SetButtonConfigLeft"} //11.0.0-17.0.1
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -14,17 +17,42 @@ public:
|
||||
explicit MIG_USR(Core::System& system_) : ServiceFramework{system_, "mig:usr"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Unknown0"}, //19.0.0+
|
||||
{1, nullptr, "Unknown1"}, //20.0.0+
|
||||
{2, nullptr, "Unknown2"}, //20.0.0+
|
||||
{10, nullptr, "TryGetLastMigrationInfo"},
|
||||
{100, nullptr, "CreateServer"},
|
||||
{101, nullptr, "ResumeServer"},
|
||||
{200, nullptr, "CreateClient"},
|
||||
{201, nullptr, "ResumeClient"},
|
||||
{1001, nullptr, "Unknown1001"},
|
||||
{1010, nullptr, "Unknown1010"},
|
||||
{1100, nullptr, "Unknown1100"},
|
||||
{1101, nullptr, "Unknown1101"},
|
||||
{1200, nullptr, "Unknown1200"},
|
||||
{1201, nullptr, "Unknown1201"}
|
||||
{11, nullptr, "Unknown11"}, //20.0.0+
|
||||
{100, nullptr, "CreateUserMigrationServer"}, //7.0.0+
|
||||
{101, nullptr, "ResumeUserMigrationServer"}, //7.0.0+
|
||||
{200, nullptr, "CreateUserMigrationClient"}, //7.0.0+
|
||||
{201, nullptr, "ResumeUserMigrationClient"}, //7.0.0+
|
||||
{1001, nullptr, "GetSaveDataMigrationPolicyInfoAsync"}, //8.0.0-20.5.0
|
||||
{1010, nullptr, "TryGetLastSaveDataMigrationInfo"}, //7.0.0+
|
||||
{1100, nullptr, "CreateSaveDataMigrationServer"}, //7.0.0-19.0.1
|
||||
{1101, nullptr, "ResumeSaveDataMigrationServer"}, //7.0.0+
|
||||
{1110, nullptr, "Unknown1101"}, //17.0.0+
|
||||
{1200, nullptr, "CreateSaveDataMigrationClient"}, //7.0.0+
|
||||
{1201, nullptr, "ResumeSaveDataMigrationClient"}, //7.0.0+
|
||||
{2001, nullptr, "Unknown2001"}, //20.0.0+
|
||||
{2010, nullptr, "Unknown2010"}, //20.0.0+
|
||||
{2100, nullptr, "Unknown2100"}, //20.0.0+
|
||||
{2110, nullptr, "Unknown2110"}, //20.0.0+
|
||||
{2200, nullptr, "Unknown2200"}, //20.0.0+
|
||||
{2210, nullptr, "Unknown2210"}, //20.0.0+
|
||||
{2220, nullptr, "Unknown2220"}, //20.0.0+
|
||||
{2230, nullptr, "Unknown2230"}, //20.0.0+
|
||||
{2231, nullptr, "Unknown2231"}, //20.0.0+
|
||||
{2232, nullptr, "Unknown2232"}, //20.0.0+
|
||||
{2233, nullptr, "Unknown2233"}, //20.0.0+
|
||||
{2234, nullptr, "Unknown2234"}, //20.0.0+
|
||||
{2250, nullptr, "Unknown2250"}, //20.0.0+
|
||||
{2260, nullptr, "Unknown2260"}, //20.0.0+
|
||||
{2270, nullptr, "Unknown2270"}, //20.0.0+
|
||||
{2280, nullptr, "Unknown2280"}, //20.0.0+
|
||||
{2300, nullptr, "Unknown2300"}, //20.0.0+
|
||||
{2310, nullptr, "Unknown2310"}, //20.0.0+
|
||||
{2400, nullptr, "Unknown2400"}, //20.0.0+
|
||||
{2420, nullptr, "Unknown2420"}, //20.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -167,57 +167,146 @@ public:
|
||||
{81, nullptr, "ListLocalCommunicationSendSystemUpdateTask"},
|
||||
{82, nullptr, "GetReceivedSystemDataPath"},
|
||||
{83, nullptr, "CalculateApplyDeltaTaskOccupiedSize"},
|
||||
{84, nullptr, "Unknown84"},
|
||||
{84, nullptr, "ReloadErrorSimulation"},
|
||||
{85, nullptr, "ListNetworkInstallTaskContentMetaFromInstallMeta"},
|
||||
{86, nullptr, "ListNetworkInstallTaskOccupiedSize"},
|
||||
{87, nullptr, "Unknown87"},
|
||||
{88, nullptr, "Unknown88"},
|
||||
{89, nullptr, "Unknown89"},
|
||||
{90, nullptr, "Unknown90"},
|
||||
{91, nullptr, "Unknown91"},
|
||||
{92, nullptr, "Unknown92"},
|
||||
{93, nullptr, "Unknown93"},
|
||||
{94, nullptr, "Unknown94"},
|
||||
{95, nullptr, "Unknown95"},
|
||||
{96, nullptr, "Unknown96"},
|
||||
{97, nullptr, "Unknown97"},
|
||||
{98, nullptr, "Unknown98"},
|
||||
{99, nullptr, "Unknown99"},
|
||||
{100, nullptr, "Unknown100"},
|
||||
{101, nullptr, "Unknown101"},
|
||||
{102, nullptr, "Unknown102"},
|
||||
{103, nullptr, "Unknown103"},
|
||||
{104, nullptr, "Unknown104"},
|
||||
{105, nullptr, "Unknown105"},
|
||||
{106, nullptr, "Unknown106"},
|
||||
{107, nullptr, "Unknown107"},
|
||||
{108, nullptr, "Unknown108"},
|
||||
{109, nullptr, "Unknown109"},
|
||||
{110, nullptr, "Unknown110"},
|
||||
{111, nullptr, "Unknown111"},
|
||||
{112, nullptr, "Unknown112"},
|
||||
{113, nullptr, "Unknown113"},
|
||||
{114, nullptr, "Unknown114"},
|
||||
{115, nullptr, "Unknown115"},
|
||||
{116, nullptr, "Unknown116"},
|
||||
{117, nullptr, "Unknown117"},
|
||||
{118, nullptr, "Unknown118"},
|
||||
{119, nullptr, "Unknown119"},
|
||||
{120, nullptr, "Unknown120"},
|
||||
{121, nullptr, "Unknown121"},
|
||||
{122, nullptr, "Unknown122"},
|
||||
{123, nullptr, "Unknown123"},
|
||||
{124, nullptr, "Unknown124"},
|
||||
{125, nullptr, "Unknown125"},
|
||||
{126, nullptr, "Unknown126"},
|
||||
{127, nullptr, "Unknown127"},
|
||||
{128, nullptr, "Unknown128"},
|
||||
{129, nullptr, "Unknown129"},
|
||||
{130, nullptr, "Unknown130"},
|
||||
{131, nullptr, "Unknown131"},
|
||||
{132, nullptr, "Unknown132"},
|
||||
{133, nullptr, "Unknown133"},
|
||||
{134, nullptr, "Unknown134"},
|
||||
{87, nullptr, "RequestQueryAvailableELicenses"},
|
||||
{88, nullptr, "RequestAssignELicenses"},
|
||||
{89, nullptr, "RequestExtendELicenses"},
|
||||
{90, nullptr, "RequestSyncELicenses"},
|
||||
{91, nullptr, "Unknown91"}, //6.0.0-14.1.2
|
||||
{92, nullptr, "Unknown92"}, //21.0.0+
|
||||
{93, nullptr, "RequestReportActiveELicenses"},
|
||||
{94, nullptr, "RequestReportActiveELicensesPassively"},
|
||||
{95, nullptr, "RequestRegisterDynamicRightsNotificationToken"},
|
||||
{96, nullptr, "RequestAssignAllDeviceLinkedELicenses"},
|
||||
{97, nullptr, "RequestRevokeAllELicenses"},
|
||||
{98, nullptr, "RequestPrefetchForDynamicRights"},
|
||||
{99, nullptr, "CreateNetworkInstallTask"},
|
||||
{100, nullptr, "ListNetworkInstallTaskRightsIds"},
|
||||
{101, nullptr, "RequestDownloadETickets"},
|
||||
{102, nullptr, "RequestQueryDownloadableContents"},
|
||||
{103, nullptr, "DeleteNetworkInstallTaskContentMeta"},
|
||||
{104, nullptr, "RequestIssueEdgeTokenForDebug"},
|
||||
{105, nullptr, "RequestQueryAvailableELicenses2"},
|
||||
{106, nullptr, "RequestAssignELicenses2"},
|
||||
{107, nullptr, "GetNetworkInstallTaskStateCounter"},
|
||||
{108, nullptr, "InvalidateDynamicRightsNaIdTokenCacheForDebug"},
|
||||
{109, nullptr, "ListNetworkInstallTaskPartialInstallContentMeta"},
|
||||
{110, nullptr, "ListNetworkInstallTaskRightsIdsFromIndex"},
|
||||
{111, nullptr, "AddNetworkInstallTaskContentMetaForUser"},
|
||||
{112, nullptr, "RequestAssignELicensesAndDownloadETickets"},
|
||||
{113, nullptr, "RequestQueryAvailableCommonELicenses"},
|
||||
{114, nullptr, "SetNetworkInstallTaskExtendedAttribute"},
|
||||
{115, nullptr, "GetNetworkInstallTaskExtendedAttribute"},
|
||||
{116, nullptr, "GetAllocatorInfo"},
|
||||
{117, nullptr, "RequestQueryDownloadableContentsByApplicationId"},
|
||||
{118, nullptr, "MarkNoDownloadRightsErrorResolved"},
|
||||
{119, nullptr, "GetApplyDeltaTaskAllAppliedContentMeta"},
|
||||
{120, nullptr, "PrioritizeNetworkInstallTask"},
|
||||
{121, nullptr, "RequestQueryAvailableCommonELicenses2"},
|
||||
{122, nullptr, "RequestAssignCommonELicenses"},
|
||||
{123, nullptr, "RequestAssignCommonELicenses2"},
|
||||
{124, nullptr, "IsNetworkInstallTaskFrontOfQueue"},
|
||||
{125, nullptr, "PrioritizeApplyDeltaTask"},
|
||||
{126, nullptr, "RerouteDownloadingPatch"},
|
||||
{127, nullptr, "UnmarkNoDownloadRightsErrorResolved"},
|
||||
{128, nullptr, "RequestContentsSize"},
|
||||
{129, nullptr, "RequestContentsAuthorizationToken"},
|
||||
{130, nullptr, "RequestCdnVendorDiscovery"},
|
||||
{131, nullptr, "RefreshDebugAvailability"},
|
||||
{132, nullptr, "ClearResponseSimulationEntry"},
|
||||
{133, nullptr, "RegisterResponseSimulationEntry"},
|
||||
{134, nullptr, "GetProcessedCdnVendors"},
|
||||
{135, nullptr, "RefreshRuntimeBehaviorsForDebug"},
|
||||
{136, nullptr, "RequestOnlineSubscriptionFreeTrialAvailability"},
|
||||
{137, nullptr, "GetNetworkInstallTaskContentMetaCount"},
|
||||
{138, nullptr, "RequestRevokeELicenses"},
|
||||
{139, nullptr, "EnableNetworkConnectionToUseApplicationCore"},
|
||||
{140, nullptr, "DisableNetworkConnectionToUseApplicationCore"},
|
||||
{141, nullptr, "IsNetworkConnectionEnabledToUseApplicationCore"},
|
||||
{142, nullptr, "RequestCheckSafeSystemVersion"},
|
||||
{143, nullptr, "RequestApplicationIcon"},
|
||||
{144, nullptr, "RequestDownloadIdbeIconFile"},
|
||||
{147, nullptr, "Unknown147"}, //18.0.0+
|
||||
{148, nullptr, "Unknown148"}, //18.0.0+
|
||||
{150, nullptr, "Unknown150"}, //19.0.0+
|
||||
{151, nullptr, "Unknown151"}, //20.0.0+
|
||||
{152, nullptr, "Unknown152"}, //20.0.0+
|
||||
{153, nullptr, "Unknown153"}, //20.0.0+
|
||||
{154, nullptr, "Unknown154"}, //20.0.0+
|
||||
{155, nullptr, "Unknown155"}, //20.0.0+
|
||||
{156, nullptr, "Unknown156"}, //20.0.0+
|
||||
{157, nullptr, "Unknown157"}, //20.0.0+
|
||||
{158, nullptr, "Unknown158"}, //20.0.0+
|
||||
{159, nullptr, "Unknown159"}, //20.0.0+
|
||||
{160, nullptr, "Unknown160"}, //20.0.0+
|
||||
{161, nullptr, "Unknown161"}, //20.0.0+
|
||||
{162, nullptr, "Unknown162"}, //20.0.0+
|
||||
{163, nullptr, "Unknown163"}, //20.0.0+
|
||||
{164, nullptr, "Unknown164"}, //20.0.0+
|
||||
{165, nullptr, "Unknown165"}, //20.0.0+
|
||||
{166, nullptr, "Unknown166"}, //20.0.0+
|
||||
{167, nullptr, "Unknown167"}, //20.0.0+
|
||||
{168, nullptr, "Unknown168"}, //20.0.0+
|
||||
{169, nullptr, "Unknown169"}, //20.0.0+
|
||||
{170, nullptr, "Unknown170"}, //20.0.0+
|
||||
{171, nullptr, "Unknown171"}, //20.0.0+
|
||||
{172, nullptr, "Unknown172"}, //20.0.0+
|
||||
{173, nullptr, "Unknown173"}, //20.0.0+
|
||||
{174, nullptr, "Unknown174"}, //20.0.0+
|
||||
{175, nullptr, "Unknown175"}, //20.0.0+
|
||||
{176, nullptr, "Unknown176"}, //20.0.0+
|
||||
{177, nullptr, "Unknown177"}, //20.0.0+
|
||||
{2000, nullptr, "Unknown2000"}, //20.0.0+
|
||||
{2001, nullptr, "Unknown2001"}, //20.0.0+
|
||||
{2002, nullptr, "Unknown2002"}, //20.0.0+
|
||||
{2003, nullptr, "Unknown2003"}, //20.0.0+
|
||||
{2004, nullptr, "Unknown2004"}, //20.0.0+
|
||||
{2007, nullptr, "Unknown2007"}, //20.0.0+
|
||||
{2011, nullptr, "Unknown2011"}, //20.0.0+
|
||||
{2012, nullptr, "Unknown2012"}, //20.0.0+
|
||||
{2013, nullptr, "Unknown2013"}, //20.0.0+
|
||||
{2014, nullptr, "Unknown2014"}, //20.0.0+
|
||||
{2015, nullptr, "Unknown2015"}, //20.0.0+
|
||||
{2016, nullptr, "Unknown2016"}, //20.0.0+
|
||||
{2017, nullptr, "Unknown2017"}, //20.0.0+
|
||||
{2018, nullptr, "Unknown2018"}, //20.0.0+
|
||||
{2019, nullptr, "Unknown2019"}, //20.0.0+
|
||||
{2020, nullptr, "Unknown2020"}, //20.0.0+
|
||||
{2021, nullptr, "Unknown2021"}, //20.0.0+
|
||||
{2022, nullptr, "Unknown2022"}, //20.0.0+
|
||||
{2023, nullptr, "Unknown2023"}, //20.0.0+
|
||||
{2024, nullptr, "Unknown2024"}, //20.0.0+
|
||||
{2025, nullptr, "Unknown2025"}, //20.0.0+
|
||||
{2026, nullptr, "Unknown2026"}, //20.0.0+
|
||||
{2027, nullptr, "Unknown2027"}, //20.0.0+
|
||||
{2028, nullptr, "Unknown2028"}, //20.0.0+
|
||||
{2029, nullptr, "Unknown2029"}, //20.0.0+
|
||||
{2030, nullptr, "Unknown2030"}, //20.0.0+
|
||||
{2031, nullptr, "Unknown2031"}, //20.0.0+
|
||||
{2032, nullptr, "Unknown2032"}, //20.0.0+
|
||||
{2033, nullptr, "Unknown2033"}, //20.0.0+
|
||||
{2034, nullptr, "Unknown2034"}, //20.0.0+
|
||||
{2035, nullptr, "Unknown2035"}, //20.0.0+
|
||||
{2036, nullptr, "Unknown2036"}, //20.0.0+
|
||||
{2037, nullptr, "Unknown2037"}, //20.0.0+
|
||||
{2038, nullptr, "Unknown2038"}, //20.0.0+
|
||||
{2039, nullptr, "Unknown2039"}, //20.0.0+
|
||||
{2040, nullptr, "Unknown2040"}, //20.0.0+
|
||||
{2041, nullptr, "Unknown2041"}, //20.0.0+
|
||||
{2042, nullptr, "Unknown2042"}, //20.0.0+
|
||||
{2043, nullptr, "Unknown2043"}, //20.0.0+
|
||||
{2044, nullptr, "Unknown2044"}, //20.0.0+
|
||||
{2045, nullptr, "Unknown2045"}, //20.0.0+
|
||||
{2046, nullptr, "Unknown2046"}, //20.0.0+
|
||||
{2047, nullptr, "Unknown2047"}, //20.0.0+
|
||||
{2048, nullptr, "Unknown2048"}, //20.0.0+
|
||||
{2049, nullptr, "Unknown2049"}, //20.0.0+
|
||||
{2050, nullptr, "Unknown2050"}, //20.0.0+
|
||||
{2051, nullptr, "Unknown2051"}, //20.0.0+
|
||||
{3000, nullptr, "RequestLatestApplicationIcon"}, //17.0.0+
|
||||
{3001, nullptr, "RequestDownloadIdbeLatestIconFile"}, //17.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/hle/service/ns/content_management_interface.h"
|
||||
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
@@ -54,7 +56,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{37, nullptr, "ListRequiredVersion"},
|
||||
{38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"},
|
||||
{39, nullptr, "CheckApplicationLaunchRights"},
|
||||
{40, nullptr, "GetApplicationLogoData"},
|
||||
{40, D<&IApplicationManagerInterface::GetApplicationLogoData>, "GetApplicationLogoData"},
|
||||
{41, nullptr, "CalculateApplicationDownloadRequiredSize"},
|
||||
{42, nullptr, "CleanupSdCard"},
|
||||
{43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
|
||||
@@ -132,7 +134,26 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, nullptr, "ListApplicationTitle"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{411, nullptr, "Unknown411"}, //19.0.0+
|
||||
{412, nullptr, "Unknown412"}, //19.0.0+
|
||||
{413, nullptr, "Unknown413"}, //19.0.0+
|
||||
{414, nullptr, "Unknown414"}, //19.0.0+
|
||||
{415, nullptr, "Unknown415"}, //19.0.0+
|
||||
{416, nullptr, "Unknown416"}, //19.0.0+
|
||||
{417, nullptr, "InvalidateAllApplicationControlCacheOfTheStage"}, //19.0.0+
|
||||
{418, nullptr, "InvalidateApplicationControlCacheOfTheStage"}, //19.0.0+
|
||||
{419, D<&IApplicationManagerInterface::RequestDownloadApplicationControlDataInBackground>, "RequestDownloadApplicationControlDataInBackground"},
|
||||
{420, nullptr, "CloneApplicationControlDataCacheForDebug"},
|
||||
{421, nullptr, "Unknown421"}, //20.0.0+
|
||||
{422, nullptr, "Unknown422"}, //20.0.0+
|
||||
{423, nullptr, "Unknown423"}, //20.0.0+
|
||||
{424, nullptr, "Unknown424"}, //20.0.0+
|
||||
{425, nullptr, "Unknown425"}, //20.0.0+
|
||||
{426, nullptr, "Unknown426"}, //20.0.0+
|
||||
{427, nullptr, "Unknown427"}, //20.0.0+
|
||||
{428, nullptr, "Unknown428"}, //21.0.0+
|
||||
{429, nullptr, "Unknown429"}, //21.0.0+
|
||||
{430, nullptr, "Unknown430"}, //21.0.0+
|
||||
{502, nullptr, "RequestCheckGameCardRegistration"},
|
||||
{503, nullptr, "RequestGameCardRegistrationGoldPoint"},
|
||||
{504, nullptr, "RequestRegisterGameCard"},
|
||||
@@ -144,6 +165,13 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{510, nullptr, "GetGameCardPlatformRegion"},
|
||||
{511, D<&IApplicationManagerInterface::GetGameCardWakenReadyEvent>, "GetGameCardWakenReadyEvent"},
|
||||
{512, D<&IApplicationManagerInterface::IsGameCardApplicationRunning>, "IsGameCardApplicationRunning"},
|
||||
{513, nullptr, "Unknown513"}, //20.0.0+
|
||||
{514, nullptr, "Unknown514"}, //20.0.0+
|
||||
{515, nullptr, "Unknown515"}, //20.0.0+
|
||||
{516, nullptr, "Unknown516"}, //21.0.0+
|
||||
{517, nullptr, "Unknown517"}, //21.0.0+
|
||||
{518, nullptr, "Unknown518"}, //21.0.0+
|
||||
{519, nullptr, "Unknown519"}, //21.0.0+
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{602, nullptr, "ListAvailableAddOnContent"},
|
||||
@@ -181,6 +209,22 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{914, nullptr, "HideApplicationRecord"},
|
||||
{915, nullptr, "ShowApplicationRecord"},
|
||||
{916, nullptr, "IsApplicationAutoDeleteDisabled"},
|
||||
{916, nullptr, "Unknown916"}, //20.0.0+
|
||||
{917, nullptr, "Unknown917"}, //20.0.0+
|
||||
{918, nullptr, "Unknown918"}, //20.0.0+
|
||||
{919, nullptr, "Unknown919"}, //20.0.0+
|
||||
{920, nullptr, "Unknown920"}, //20.0.0+
|
||||
{921, nullptr, "Unknown921"}, //20.0.0+
|
||||
{922, nullptr, "Unknown922"}, //20.0.0+
|
||||
{923, nullptr, "Unknown923"}, //20.0.0+
|
||||
{928, nullptr, "Unknown928"}, //20.0.0+
|
||||
{929, nullptr, "Unknown929"}, //20.0.0+
|
||||
{930, nullptr, "Unknown930"}, //20.0.0+
|
||||
{931, nullptr, "Unknown931"}, //20.0.0+
|
||||
{933, nullptr, "Unknown933"}, //20.0.0+
|
||||
{934, nullptr, "Unknown934"}, //20.0.0+
|
||||
{935, nullptr, "Unknown935"}, //20.0.0+
|
||||
{936, nullptr, "Unknown936"}, //20.0.0+
|
||||
{1000, nullptr, "RequestVerifyApplicationDeprecated"},
|
||||
{1001, nullptr, "CorruptApplicationForDebug"},
|
||||
{1002, nullptr, "RequestVerifyAddOnContentsRights"},
|
||||
@@ -209,6 +253,11 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{1504, nullptr, "InsertSdCard"},
|
||||
{1505, nullptr, "RemoveSdCard"},
|
||||
{1506, nullptr, "GetSdCardStartupStatus"},
|
||||
{1508, nullptr, "Unknown1508"}, //20.0.0+
|
||||
{1509, nullptr, "Unknown1509"}, //20.0.0+
|
||||
{1510, nullptr, "Unknown1510"}, //20.0.0+
|
||||
{1511, nullptr, "Unknown1511"}, //20.0.0+
|
||||
{1512, nullptr, "Unknown1512"}, //20.0.0+
|
||||
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
|
||||
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
|
||||
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
|
||||
@@ -245,8 +294,11 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{2016, nullptr, "ListNotCommittedContentMeta"},
|
||||
{2017, nullptr, "CreateDownloadTask"},
|
||||
{2018, nullptr, "GetApplicationDeliveryInfoHash"},
|
||||
{2019, nullptr, "Unknown2019"}, //20.0.0+
|
||||
{2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"},
|
||||
{2051, nullptr, "InvalidateRightsIdCache"},
|
||||
{2052, nullptr, "Unknown2052"}, //20.0.0+
|
||||
{2053, nullptr, "Unknown2053"}, //20.0.0+
|
||||
{2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"},
|
||||
{2101, nullptr, "GetRawApplicationTerminateResult"},
|
||||
{2150, nullptr, "CreateRightsEnvironment"},
|
||||
@@ -263,6 +315,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
|
||||
{2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
|
||||
{2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
|
||||
{2183, nullptr, "Unknown2183"}, //20.1.0+
|
||||
{2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
|
||||
{2199, nullptr, "GetRightsEnvironmentCountForDebug"},
|
||||
{2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
|
||||
@@ -279,6 +332,16 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{2357, nullptr, "EnableMultiCoreDownload"},
|
||||
{2358, nullptr, "DisableMultiCoreDownload"},
|
||||
{2359, nullptr, "IsMultiCoreDownloadEnabled"},
|
||||
{2360, nullptr, "GetApplicationDownloadTaskCount"}, //19.0.0+
|
||||
{2361, nullptr, "GetMaxApplicationDownloadTaskCount"}, //19.0.0+
|
||||
{2362, nullptr, "Unknown2362"}, //20.0.0+
|
||||
{2363, nullptr, "Unknown2363"}, //20.0.0+
|
||||
{2364, nullptr, "Unknown2364"}, //20.0.0+
|
||||
{2365, nullptr, "Unknown2365"}, //20.0.0+
|
||||
{2366, nullptr, "Unknown2366"}, //20.0.0+
|
||||
{2367, nullptr, "Unknown2367"}, //20.0.0+
|
||||
{2368, nullptr, "Unknown2368"}, //20.0.0+
|
||||
{2369, nullptr, "Unknown2369"}, //21.0.0+
|
||||
{2400, nullptr, "GetPromotionInfo"},
|
||||
{2401, nullptr, "CountPromotionInfo"},
|
||||
{2402, nullptr, "ListPromotionInfo"},
|
||||
@@ -297,6 +360,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
|
||||
{2521, nullptr, "GetRightsUserChangedEvent"},
|
||||
{2522, nullptr, "IsRomRedirectionAvailable"},
|
||||
{2523, nullptr, "GetProgramId"}, //17.0.0+
|
||||
{2524, nullptr, "Unknown2524"}, //19.0.0+
|
||||
{2525, nullptr, "Unknown2525"}, //20.0.0+
|
||||
{2800, nullptr, "GetApplicationIdOfPreomia"},
|
||||
{3000, nullptr, "RegisterDeviceLockKey"},
|
||||
{3001, nullptr, "UnregisterDeviceLockKey"},
|
||||
@@ -314,11 +380,99 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{3013, nullptr, "IsGameCardEnabled"},
|
||||
{3014, nullptr, "IsLocalContentShareEnabled"},
|
||||
{3050, nullptr, "ListAssignELicenseTaskResult"},
|
||||
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"},
|
||||
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"},
|
||||
{4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"},
|
||||
{4053, D<&IApplicationManagerInterface::Unknown4053>, "Unknown4053"},
|
||||
{9999, nullptr, "GetApplicationCertificate"},
|
||||
{3104, nullptr, "GetApplicationNintendoLogo"}, //18.0.0+
|
||||
{3105, nullptr, "GetApplicationStartupMovie"}, //18.0.0+
|
||||
{4000, nullptr, "Unknown4000"}, //20.0.0+
|
||||
{4004, nullptr, "Unknown4004"}, //20.0.0+
|
||||
{4006, nullptr, "Unknown4006"}, //20.0.0+
|
||||
{4007, nullptr, "Unknown4007"}, //20.0.0+
|
||||
{4008, nullptr, "Unknown4008"}, //20.0.0+
|
||||
{4009, nullptr, "Unknown4009"}, //20.0.0+
|
||||
{4010, nullptr, "Unknown4010"}, //20.0.0+
|
||||
{4011, nullptr, "Unknown4011"}, //20.0.0+
|
||||
{4012, nullptr, "Unknown4012"}, //20.0.0+
|
||||
{4013, nullptr, "Unknown4013"}, //20.0.0+
|
||||
{4015, nullptr, "Unknown4015"}, //20.0.0+
|
||||
{4017, nullptr, "Unknown4017"}, //20.0.0+
|
||||
{4019, nullptr, "Unknown4019"}, //20.0.0+
|
||||
{4020, nullptr, "Unknown4020"}, //20.0.0+
|
||||
{4021, nullptr, "Unknown4021"}, //20.0.0+
|
||||
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"}, //20.0.0+
|
||||
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"}, //20.0.0+
|
||||
{4024, nullptr, "Unknown4024"}, //20.0.0+
|
||||
{4025, nullptr, "Unknown4025"}, //20.0.0+
|
||||
{4026, nullptr, "Unknown4026"}, //20.0.0+
|
||||
{4027, nullptr, "Unknown4027"}, //20.0.0+
|
||||
{4028, nullptr, "Unknown4028"}, //20.0.0+
|
||||
{4029, nullptr, "Unknown4029"}, //20.0.0+
|
||||
{4030, nullptr, "Unknown4030"}, //20.0.0+
|
||||
{4031, nullptr, "Unknown4031"}, //20.0.0+
|
||||
{4032, nullptr, "Unknown4032"}, //20.0.0+
|
||||
{4033, nullptr, "Unknown4033"}, //20.0.0+
|
||||
{4034, nullptr, "Unknown4034"}, //20.0.0+
|
||||
{4035, nullptr, "Unknown4035"}, //20.0.0+
|
||||
{4037, nullptr, "Unknown4037"}, //20.0.0+
|
||||
{4038, nullptr, "Unknown4038"}, //20.0.0+
|
||||
{4039, nullptr, "Unknown4039"}, //20.0.0+
|
||||
{4040, nullptr, "Unknown4040"}, //20.0.0+
|
||||
{4041, nullptr, "Unknown4041"}, //20.0.0+
|
||||
{4042, nullptr, "Unknown4042"}, //20.0.0+
|
||||
{4043, nullptr, "Unknown4043"}, //20.0.0+
|
||||
{4044, nullptr, "Unknown4044"}, //20.0.0+
|
||||
{4045, nullptr, "Unknown4045"}, //20.0.0+
|
||||
{4046, nullptr, "Unknown4046"}, //20.0.0+
|
||||
{4049, nullptr, "Unknown4049"}, //20.0.0+
|
||||
{4050, nullptr, "Unknown4050"}, //20.0.0+
|
||||
{4051, nullptr, "Unknown4051"}, //20.0.0+
|
||||
{4052, nullptr, "Unknown4052"}, //20.0.0+
|
||||
{4053, D<&IApplicationManagerInterface::Unknown4053>, "Unknown4053"}, //20.0.0+
|
||||
{4054, nullptr, "Unknown4054"}, //20.0.0+
|
||||
{4055, nullptr, "Unknown4055"}, //20.0.0+
|
||||
{4056, nullptr, "Unknown4056"}, //20.0.0+
|
||||
{4057, nullptr, "Unknown4057"}, //20.0.0+
|
||||
{4058, nullptr, "Unknown4058"}, //20.0.0+
|
||||
{4059, nullptr, "Unknown4059"}, //20.0.0+
|
||||
{4060, nullptr, "Unknown4060"}, //20.0.0+
|
||||
{4061, nullptr, "Unknown4061"}, //20.0.0+
|
||||
{4062, nullptr, "Unknown4062"}, //20.0.0+
|
||||
{4063, nullptr, "Unknown4063"}, //20.0.0+
|
||||
{4064, nullptr, "Unknown4064"}, //20.0.0+
|
||||
{4065, nullptr, "Unknown4065"}, //20.0.0+
|
||||
{4066, nullptr, "Unknown4066"}, //20.0.0+
|
||||
{4067, nullptr, "Unknown4067"}, //20.0.0+
|
||||
{4068, nullptr, "Unknown4068"}, //20.0.0+
|
||||
{4069, nullptr, "Unknown4069"}, //20.0.0+
|
||||
{4070, nullptr, "Unknown4070"}, //20.0.0+
|
||||
{4071, nullptr, "Unknown4071"}, //20.0.0+
|
||||
{4072, nullptr, "Unknown4072"}, //20.0.0+
|
||||
{4073, nullptr, "Unknown4073"}, //20.0.0+
|
||||
{4074, nullptr, "Unknown4074"}, //20.0.0+
|
||||
{4075, nullptr, "Unknown4075"}, //20.0.0+
|
||||
{4076, nullptr, "Unknown4076"}, //20.0.0+
|
||||
{4077, nullptr, "Unknown4077"}, //20.0.0+
|
||||
{4078, nullptr, "Unknown4078"}, //20.0.0+
|
||||
{4079, nullptr, "Unknown4079"}, //20.0.0+
|
||||
{4080, nullptr, "Unknown4080"}, //20.0.0+
|
||||
{4081, nullptr, "Unknown4081"}, //20.0.0+
|
||||
{4083, nullptr, "Unknown4083"}, //20.0.0+
|
||||
{4084, nullptr, "Unknown4084"}, //20.0.0+
|
||||
{4085, nullptr, "Unknown4085"}, //20.0.0+
|
||||
{4086, nullptr, "Unknown4086"}, //20.0.0+
|
||||
{4087, nullptr, "Unknown4087"}, //20.0.0+
|
||||
{4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"}, //20.0.0+
|
||||
{4089, nullptr, "Unknown4089"}, //20.0.0+
|
||||
{4090, nullptr, "Unknown4090"}, //20.0.0+
|
||||
{4091, nullptr, "Unknown4091"}, //20.0.0+
|
||||
{4092, nullptr, "Unknown4092"}, //20.0.0+
|
||||
{4093, nullptr, "Unknown4093"}, //20.0.0+
|
||||
{4094, nullptr, "Unknown4094"}, //20.0.0+
|
||||
{4095, nullptr, "Unknown4095"}, //20.0.0+
|
||||
{4096, nullptr, "Unknown4096"}, //20.0.0+
|
||||
{4097, nullptr, "Unknown4097"}, //20.0.0+
|
||||
{4099, nullptr, "Unknown4099"}, //21.0.0+
|
||||
{5000, nullptr, "Unknown5000"}, //18.0.0+
|
||||
{5001, nullptr, "Unknown5001"}, //18.0.0+
|
||||
{9999, nullptr, "GetApplicationCertificate"}, //10.0.0-10.2.0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -331,6 +485,53 @@ Result IApplicationManagerInterface::UnregisterNetworkServiceAccountWithUserSave
|
||||
LOG_DEBUG(Service_NS, "called, user_id={}", user_id.FormattedString());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationLogoData(
|
||||
Out<s64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, u64 application_id,
|
||||
InBuffer<BufferAttr_HipcMapAlias> logo_path_buffer) {
|
||||
const std::string path_view{reinterpret_cast<const char*>(logo_path_buffer.data()),
|
||||
logo_path_buffer.size()};
|
||||
|
||||
// Find null terminator and trim the path
|
||||
auto null_pos = path_view.find('\0');
|
||||
std::string path = (null_pos != std::string::npos) ? path_view.substr(0, null_pos) : path_view;
|
||||
|
||||
LOG_DEBUG(Service_NS, "called, application_id={:016X}, logo_path={}", application_id, path);
|
||||
|
||||
auto& content_provider = system.GetContentProviderUnion();
|
||||
|
||||
auto program = content_provider.GetEntry(application_id, FileSys::ContentRecordType::Program);
|
||||
if (!program) {
|
||||
LOG_WARNING(Service_NS, "Application program not found for id={:016X}", application_id);
|
||||
R_RETURN(ResultUnknown);
|
||||
}
|
||||
|
||||
const auto logo_dir = program->GetLogoPartition();
|
||||
if (!logo_dir) {
|
||||
LOG_WARNING(Service_NS, "Logo partition not found for id={:016X}", application_id);
|
||||
R_RETURN(ResultUnknown);
|
||||
}
|
||||
|
||||
const auto file = logo_dir->GetFile(path);
|
||||
if (!file) {
|
||||
LOG_WARNING(Service_NS, "Logo path not found: {} for id={:016X}", path,
|
||||
application_id);
|
||||
R_RETURN(ResultUnknown);
|
||||
}
|
||||
|
||||
const auto data = file->ReadAllBytes();
|
||||
if (data.size() > out_buffer.size()) {
|
||||
LOG_WARNING(Service_NS, "Logo buffer too small: have={}, need={}", out_buffer.size(),
|
||||
data.size());
|
||||
R_RETURN(ResultUnknown);
|
||||
}
|
||||
|
||||
std::memcpy(out_buffer.data(), data.data(), data.size());
|
||||
*out_size = static_cast<s64>(data.size());
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationControlData(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||
ApplicationControlSource application_control_source, u64 application_id) {
|
||||
|
||||
@@ -60,6 +60,10 @@ public:
|
||||
u64 application_id);
|
||||
Result CheckApplicationLaunchVersion(u64 application_id);
|
||||
Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
|
||||
Result GetApplicationLogoData(Out<s64> out_size,
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
u64 application_id,
|
||||
InBuffer<BufferAttr_HipcMapAlias> logo_path_buffer);
|
||||
Result Unknown4022(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result Unknown4023(Out<u64> out_result);
|
||||
Result Unknown4053();
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -22,6 +25,7 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
{607, nullptr, "IsAnyApplicationRunning"},
|
||||
{608, nullptr, "Unknown608"}, //21.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -37,7 +37,11 @@ IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_)
|
||||
{23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
|
||||
{24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"},
|
||||
{25, nullptr, "RequestProceedDynamicRightsState"},
|
||||
{26, D<&IDynamicRightsInterface::HasAccountRestrictedRightsInRunningApplications>, "HasAccountRestrictedRightsInRunningApplications"}
|
||||
{26, D<&IDynamicRightsInterface::HasAccountRestrictedRightsInRunningApplications>, "HasAccountRestrictedRightsInRunningApplications"},
|
||||
{27, nullptr, "Unknown27"}, //20.0.0+
|
||||
{28, nullptr, "Unknown28"}, //20.0.0+
|
||||
{29, nullptr, "Unknown29"}, //21.0.0+
|
||||
{30, nullptr, "Unknown30"}, //21.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -179,4 +179,9 @@ struct ApplicationDisplayData {
|
||||
};
|
||||
static_assert(sizeof(ApplicationDisplayData) == 0x300, "ApplicationDisplayData has incorrect size.");
|
||||
|
||||
struct LogoPath {
|
||||
std::array<char, 0x300> path;
|
||||
};
|
||||
static_assert(std::is_trivially_copyable_v<LogoPath>, "LogoPath must be trivially copyable.");
|
||||
|
||||
} // namespace Service::NS
|
||||
|
||||
@@ -15,7 +15,7 @@ struct Layer {
|
||||
explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_,
|
||||
s32 consumer_id_)
|
||||
: buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_),
|
||||
blending(LayerBlending::None), visible(true), z_index(0) {}
|
||||
blending(LayerBlending::None), visible(true), z_index(0), is_overlay(false) {}
|
||||
~Layer() {
|
||||
buffer_item_consumer->Abandon();
|
||||
}
|
||||
@@ -25,6 +25,7 @@ struct Layer {
|
||||
LayerBlending blending;
|
||||
bool visible;
|
||||
s32 z_index;
|
||||
bool is_overlay;
|
||||
};
|
||||
|
||||
struct LayerStack {
|
||||
|
||||
@@ -78,8 +78,25 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
for (auto& layer : display.stack.layers) {
|
||||
auto consumer_id = layer->consumer_id;
|
||||
|
||||
bool should_try_acquire = true;
|
||||
if (!layer->is_overlay) {
|
||||
auto fb_it = m_framebuffers.find(consumer_id);
|
||||
if (fb_it != m_framebuffers.end() && fb_it->second.is_acquired) {
|
||||
const u64 frames_since_last_acquire = m_frame_number - fb_it->second.last_acquire_frame;
|
||||
const s32 expected_interval = NormalizeSwapInterval(nullptr, fb_it->second.item.swap_interval);
|
||||
|
||||
if (frames_since_last_acquire < static_cast<u64>(expected_interval)) {
|
||||
should_try_acquire = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to fetch the framebuffer (either new or stale).
|
||||
const auto result = this->CacheFramebufferLocked(*layer, consumer_id);
|
||||
const auto result = should_try_acquire
|
||||
? this->CacheFramebufferLocked(*layer, consumer_id)
|
||||
: (m_framebuffers.find(consumer_id) != m_framebuffers.end() && m_framebuffers[consumer_id].is_acquired
|
||||
? CacheStatus::CachedBufferReused
|
||||
: CacheStatus::NoBufferAvailable);
|
||||
|
||||
// If we failed, skip this layer.
|
||||
if (result == CacheStatus::NoBufferAvailable) {
|
||||
@@ -111,6 +128,12 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
});
|
||||
}
|
||||
|
||||
// Overlay layers run at their own framerate independently of the game.
|
||||
// Skip them when calculating the swap interval for the main game.
|
||||
if (layer->is_overlay) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We need to compose again either before this frame is supposed to
|
||||
// be released, or exactly on the vsync period it should be released.
|
||||
const s32 item_swap_interval = NormalizeSwapInterval(out_speed_scale, item.swap_interval);
|
||||
@@ -138,33 +161,44 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
// Batch framebuffer releases, instead of one-into-one.
|
||||
std::vector<std::pair<Layer*, Framebuffer*>> to_release;
|
||||
for (auto& [layer_id, framebuffer] : m_framebuffers) {
|
||||
if (framebuffer.release_frame_number > m_frame_number || !framebuffer.is_acquired)
|
||||
if (!framebuffer.is_acquired)
|
||||
continue;
|
||||
if (auto layer = display.stack.FindLayer(layer_id); layer)
|
||||
|
||||
auto layer = display.stack.FindLayer(layer_id);
|
||||
if (!layer)
|
||||
continue;
|
||||
|
||||
// Overlay layers always release after every compose
|
||||
// Non-overlay layers release based on their swap interval
|
||||
if (layer->is_overlay || framebuffer.release_frame_number <= m_frame_number) {
|
||||
to_release.emplace_back(layer.get(), &framebuffer);
|
||||
}
|
||||
}
|
||||
for (auto& [layer, framebuffer] : to_release) {
|
||||
layer->buffer_item_consumer->ReleaseBuffer(framebuffer->item, android::Fence::NoFence());
|
||||
framebuffer->is_acquired = false;
|
||||
}
|
||||
|
||||
// Advance by at least one frame.
|
||||
const u32 frame_advance = swap_interval.value_or(1);
|
||||
m_frame_number += frame_advance;
|
||||
// Advance by 1 frame (60 FPS compositing)
|
||||
m_frame_number += 1;
|
||||
|
||||
// Release any necessary framebuffers.
|
||||
// Release any necessary framebuffers (non-overlay layers only, as overlays are already released above).
|
||||
for (auto& [layer_id, framebuffer] : m_framebuffers) {
|
||||
if (framebuffer.release_frame_number > m_frame_number) {
|
||||
// Not yet ready to release this framebuffer.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!framebuffer.is_acquired) {
|
||||
// Already released.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (framebuffer.release_frame_number > m_frame_number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const auto layer = display.stack.FindLayer(layer_id); layer != nullptr) {
|
||||
// Skip overlay layers as they were already released above
|
||||
if (layer->is_overlay) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: support release fence
|
||||
// This is needed to prevent screen tearing
|
||||
layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
|
||||
@@ -172,7 +206,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
}
|
||||
}
|
||||
|
||||
return frame_advance;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) {
|
||||
@@ -200,8 +234,9 @@ bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& fr
|
||||
}
|
||||
|
||||
// We succeeded, so set the new release frame info.
|
||||
framebuffer.release_frame_number =
|
||||
NormalizeSwapInterval(nullptr, framebuffer.item.swap_interval);
|
||||
const s32 swap_interval = layer.is_overlay ? 1 : NormalizeSwapInterval(nullptr, framebuffer.item.swap_interval);
|
||||
framebuffer.release_frame_number = m_frame_number + swap_interval;
|
||||
framebuffer.last_acquire_frame = m_frame_number;
|
||||
framebuffer.is_acquired = true;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -34,6 +37,7 @@ private:
|
||||
struct Framebuffer {
|
||||
android::BufferItem item{};
|
||||
ReleaseFrameNumber release_frame_number{};
|
||||
u64 last_acquire_frame{0};
|
||||
bool is_acquired{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -101,6 +104,13 @@ void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blen
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay) {
|
||||
if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) {
|
||||
layer->is_overlay = is_overlay;
|
||||
LOG_DEBUG(Service_VI, "Layer {} marked as overlay: {}", consumer_binder_id, is_overlay);
|
||||
}
|
||||
}
|
||||
|
||||
Display* SurfaceFlinger::FindDisplay(u64 display_id) {
|
||||
for (auto& display : m_displays) {
|
||||
if (display.id == display_id) {
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
|
||||
void SetLayerVisibility(s32 consumer_binder_id, bool visible);
|
||||
void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending);
|
||||
void SetLayerIsOverlay(s32 consumer_binder_id, bool is_overlay);
|
||||
|
||||
std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id);
|
||||
|
||||
|
||||
@@ -16,64 +16,67 @@ IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_
|
||||
: ServiceFramework{system_, "olsc:s"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IOlscServiceForSystemService::OpenTransferTaskListController>, "OpenTransferTaskListController"},
|
||||
{1, D<&IOlscServiceForSystemService::OpenRemoteStorageController>, "OpenRemoteStorageController"},
|
||||
{2, D<&IOlscServiceForSystemService::OpenDaemonController>, "OpenDaemonController"},
|
||||
{10, nullptr, "Unknown10"},
|
||||
{11, nullptr, "Unknown11"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{0, D<&IOlscServiceForSystemService::GetTransferTaskListController>, "GetTransferTaskListController"},
|
||||
{1, D<&IOlscServiceForSystemService::GetRemoteStorageController>, "GetRemoteStorageController"},
|
||||
{2, D<&IOlscServiceForSystemService::GetDaemonController>, "GetDaemonController"},
|
||||
{10, nullptr, "PrepareDeleteUserProperty"},
|
||||
{11, nullptr, "DeleteUserSaveDataProperty"},
|
||||
{12, nullptr, "InvalidateMountCache"},
|
||||
{13, nullptr, "DeleteDeviceSaveDataProperty"},
|
||||
{100, nullptr, "ListLastTransferTaskErrorInfo"},
|
||||
{101, nullptr, "GetLastErrorInfoCount"},
|
||||
{102, nullptr, "RemoveLastErrorInfoOld"},
|
||||
{103, nullptr, "GetLastErrorInfo"},
|
||||
{104, nullptr, "GetLastErrorEventHolder"},
|
||||
{105, nullptr, "GetLastTransferTaskErrorInfo"},
|
||||
{200, D<&IOlscServiceForSystemService::GetDataTransferPolicyInfo>, "GetDataTransferPolicyInfo"},
|
||||
{201, nullptr, "RemoveDataTransferPolicyInfo"},
|
||||
{202, nullptr, "UpdateDataTransferPolicyOld"},
|
||||
{203, nullptr, "UpdateDataTransferPolicy"},
|
||||
{204, nullptr, "CleanupDataTransferPolicyInfo"},
|
||||
{205, nullptr, "RequestDataTransferPolicy"},
|
||||
{300, nullptr, "GetAutoTransferSeriesInfo"},
|
||||
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
|
||||
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
|
||||
{900, nullptr, "CleanupTransferTask"},
|
||||
{902, nullptr, "CleanupSeriesInfoType0"},
|
||||
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
|
||||
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
|
||||
{905, nullptr, "CleanupErrorHistory"},
|
||||
{906, nullptr, "SetLastError"},
|
||||
{907, nullptr, "AddSaveDataArchiveInfoType0"},
|
||||
{908, nullptr, "RemoveSeriesInfoType0"},
|
||||
{909, nullptr, "GetSeriesInfoType0"},
|
||||
{910, nullptr, "RemoveLastErrorInfo"},
|
||||
{911, nullptr, "CleanupSeriesInfoType1"},
|
||||
{912, nullptr, "RemoveSeriesInfoType1"},
|
||||
{913, nullptr, "GetSeriesInfoType1"},
|
||||
{200, D<&IOlscServiceForSystemService::GetDataTransferPolicy>, "GetDataTransferPolicy"},
|
||||
{201, nullptr, "DeleteDataTransferPolicyCache"},
|
||||
{202, nullptr, "Unknown202"},
|
||||
{203, nullptr, "RequestUpdateDataTransferPolicyCacheAsync"},
|
||||
{204, nullptr, "ClearDataTransferPolicyCache"},
|
||||
{205, nullptr, "RequestGetDataTransferPolicyAsync"},
|
||||
{206, nullptr, "Unknown206"}, //21.0.0+
|
||||
{300, nullptr, "GetUserSaveDataProperty"},
|
||||
{301, nullptr, "SetUserSaveDataProperty"},
|
||||
{302, nullptr, "Unknown302"}, //21.0.0+
|
||||
{400, nullptr, "CleanupSaveDataBackupContextForSpecificApplications"},
|
||||
{900, nullptr, "DeleteAllTransferTask"},
|
||||
{902, nullptr, "DeleteAllSeriesInfo"},
|
||||
{903, nullptr, "DeleteAllSdaInfoCache"},
|
||||
{904, nullptr, "DeleteAllApplicationSetting"},
|
||||
{905, nullptr, "DeleteAllTransferTaskErrorInfo"},
|
||||
{906, nullptr, "RegisterTransferTaskErrorInfo"},
|
||||
{907, nullptr, "AddSaveDataArchiveInfoCache"},
|
||||
{908, nullptr, "DeleteSeriesInfo"},
|
||||
{909, nullptr, "GetSeriesInfo"},
|
||||
{910, nullptr, "RemoveTransferTaskErrorInfo"},
|
||||
{911, nullptr, "DeleteAllSeriesInfoForSaveDataBackup"},
|
||||
{912, nullptr, "DeleteSeriesInfoForSaveDataBackup"},
|
||||
{913, nullptr, "GetSeriesInfoForSaveDataBackup"},
|
||||
{914, nullptr, "Unknown914"}, //20.2.0+
|
||||
{1000, nullptr, "UpdateIssueOld"},
|
||||
{1010, nullptr, "Unknown1010"},
|
||||
{1011, nullptr, "ListIssueInfoOld"},
|
||||
{1012, nullptr, "GetIssueOld"},
|
||||
{1013, nullptr, "GetIssue2Old"},
|
||||
{1014, nullptr, "GetIssue3Old"},
|
||||
{1020, nullptr, "RepairIssueOld"},
|
||||
{1021, nullptr, "RepairIssueWithUserIdOld"},
|
||||
{1022, nullptr, "RepairIssue2Old"},
|
||||
{1023, nullptr, "RepairIssue3Old"},
|
||||
{1011, nullptr, "Unknown1011"},
|
||||
{1012, nullptr, "Unknown1012"},
|
||||
{1013, nullptr, "Unkown1013"},
|
||||
{1014, nullptr, "Unknown1014"},
|
||||
{1020, nullptr, "Unknown1020"},
|
||||
{1021, nullptr, "Unknown1021"},
|
||||
{1022, nullptr, "Unknown1022"},
|
||||
{1023, nullptr, "Unknown1023"},
|
||||
{1024, nullptr, "Unknown1024"},
|
||||
{1100, nullptr, "UpdateIssue"},
|
||||
{1110, nullptr, "Unknown1110"},
|
||||
{1111, nullptr, "ListIssueInfo"},
|
||||
{1112, nullptr, "GetIssue"},
|
||||
{1113, nullptr, "GetIssue2"},
|
||||
{1114, nullptr, "GetIssue3"},
|
||||
{1120, nullptr, "RepairIssue"},
|
||||
{1121, nullptr, "RepairIssueWithUserId"},
|
||||
{1122, nullptr, "RepairIssue2"},
|
||||
{1123, nullptr, "RepairIssue3"},
|
||||
{1124, nullptr, "Unknown1124"},
|
||||
{10000, D<&IOlscServiceForSystemService::CloneService>, "CloneService"},
|
||||
{1100, nullptr, "RepairUpdateIssueInfoCacheAync"},
|
||||
{1110, nullptr, "RepairGetIssueInfo"},
|
||||
{1111, nullptr, "RepairListIssueInfo"},
|
||||
{1112, nullptr, "RepairListOperationPermissionInfo"},
|
||||
{1113, nullptr, "RepairListDataInfoForRepairedSaveDataDownload"},
|
||||
{1114, nullptr, "RepairListDataInfoForOriginalSaveDataDownload"},
|
||||
{1120, nullptr, "RepairUploadSaveDataAsync"},
|
||||
{1121, nullptr, "RepairUploadSaveDataAsync1"},
|
||||
{1122, nullptr, "RepairDownloadRepairedSaveDataAsync"},
|
||||
{1123, nullptr, "RepairDownloadOriginalSaveDataAsync"},
|
||||
{1124, nullptr, "RepairGetOperationProgressInfo"},
|
||||
{10000, D<&IOlscServiceForSystemService::GetOlscServiceForSystemService>, "GetOlscServiceForSystemService"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -82,38 +85,38 @@ IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_
|
||||
|
||||
IOlscServiceForSystemService::~IOlscServiceForSystemService() = default;
|
||||
|
||||
Result IOlscServiceForSystemService::OpenTransferTaskListController(
|
||||
Result IOlscServiceForSystemService::GetTransferTaskListController(
|
||||
Out<SharedPointer<ITransferTaskListController>> out_interface) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
*out_interface = std::make_shared<ITransferTaskListController>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOlscServiceForSystemService::OpenRemoteStorageController(
|
||||
Result IOlscServiceForSystemService::GetRemoteStorageController(
|
||||
Out<SharedPointer<IRemoteStorageController>> out_interface) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
*out_interface = std::make_shared<IRemoteStorageController>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOlscServiceForSystemService::OpenDaemonController(
|
||||
Result IOlscServiceForSystemService::GetDaemonController(
|
||||
Out<SharedPointer<IDaemonController>> out_interface) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
*out_interface = std::make_shared<IDaemonController>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(
|
||||
Out<DataTransferPolicy> out_policy_info, u64 application_id) {
|
||||
Result IOlscServiceForSystemService::GetDataTransferPolicy(
|
||||
Out<DataTransferPolicy> out_policy, u64 application_id) {
|
||||
LOG_WARNING(Service_OLSC, "(STUBBED) called");
|
||||
DataTransferPolicy policy{};
|
||||
policy.upload_policy = 0;
|
||||
policy.download_policy = 0;
|
||||
*out_policy_info = policy;
|
||||
*out_policy = policy;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IOlscServiceForSystemService::CloneService(
|
||||
Result IOlscServiceForSystemService::GetOlscServiceForSystemService(
|
||||
Out<SharedPointer<IOlscServiceForSystemService>> out_interface) {
|
||||
LOG_INFO(Service_OLSC, "called");
|
||||
*out_interface = std::static_pointer_cast<IOlscServiceForSystemService>(shared_from_this());
|
||||
|
||||
@@ -24,12 +24,12 @@ public:
|
||||
~IOlscServiceForSystemService() override;
|
||||
|
||||
private:
|
||||
Result OpenTransferTaskListController(
|
||||
Result GetTransferTaskListController(
|
||||
Out<SharedPointer<ITransferTaskListController>> out_interface);
|
||||
Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
|
||||
Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
|
||||
Result GetDataTransferPolicyInfo(Out<DataTransferPolicy> out_policy_info, u64 application_id);
|
||||
Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
|
||||
Result GetRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
|
||||
Result GetDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
|
||||
Result GetDataTransferPolicy(Out<DataTransferPolicy> out_policy, u64 application_id);
|
||||
Result GetOlscServiceForSystemService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
|
||||
};
|
||||
|
||||
} // namespace Service::OLSC
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -11,32 +14,37 @@ ITransferTaskListController::ITransferTaskListController(Core::System& system_)
|
||||
: ServiceFramework{system_, "ITransferTaskListController"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Unknown0"},
|
||||
{1, nullptr, "Unknown1"},
|
||||
{2, nullptr, "Unknown2"},
|
||||
{3, nullptr, "Unknown3"},
|
||||
{4, nullptr, "Unknown4"},
|
||||
{5, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder"},
|
||||
{6, nullptr, "Unknown6"},
|
||||
{7, nullptr, "Unknown7"},
|
||||
{8, nullptr, "GetRemoteStorageController"},
|
||||
{9, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder2"},
|
||||
{10, nullptr, "Unknown10"},
|
||||
{11, nullptr, "Unknown11"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "Unknown16"},
|
||||
{17, nullptr, "Unknown17"},
|
||||
{18, nullptr, "Unknown18"},
|
||||
{19, nullptr, "Unknown19"},
|
||||
{20, nullptr, "Unknown20"},
|
||||
{21, nullptr, "Unknown21"},
|
||||
{22, nullptr, "Unknown22"},
|
||||
{23, nullptr, "Unknown23"},
|
||||
{24, nullptr, "Unknown24"},
|
||||
{25, nullptr, "Unknown25"},
|
||||
{0, nullptr, "GetTransferTaskCountForOcean"},
|
||||
{1, nullptr, "GetTransferTaskInfoForOcean"},
|
||||
{2, nullptr, "ListTransferTaskInfoForOcean"},
|
||||
{3, nullptr, "DeleteTransferTaskForOcean"},
|
||||
{4, nullptr, "RaiseTransferTaskPriorityForOcean"},
|
||||
{5, D<&ITransferTaskListController::GetTransferTaskEndEventNativeHandleHolder>, "GetTransferTaskEndEventNativeHandleHolder"},
|
||||
{6, nullptr, "GetTransferTaskProgressForOcean"},
|
||||
{7, nullptr, "GetTransferTaskLastResultForOcean"},
|
||||
{8, nullptr, "StopNextTransferTaskExecution"},
|
||||
{9, D<&ITransferTaskListController::GetTransferTaskStartEventNativeHandleHolder>, "GetTransferTaskStartEventNativeHandleHolder"},
|
||||
{10, nullptr, "SuspendTransferTaskForOcean"},
|
||||
{11, nullptr, "GetCurrentTransferTaskInfoForOcean"},
|
||||
{12, nullptr, "FindTransferTaskInfoForOcean"},
|
||||
{13, nullptr, "CancelCurrentRepairTransferTask"},
|
||||
{14, nullptr, "GetRepairTransferTaskProgress"},
|
||||
{15, nullptr, "EnsureExecutableForRepairTransferTask"},
|
||||
{16, nullptr, "GetTransferTaskCount"},
|
||||
{17, nullptr, "GetTransferTaskInfo"},
|
||||
{18, nullptr, "ListTransferTaskInfo"},
|
||||
{19, nullptr, "DeleteTransferTask"},
|
||||
{20, nullptr, "RaiseTransferTaskPriority"},
|
||||
{21, nullptr, "GetTransferTaskProgress"},
|
||||
{22, nullptr, "GetTransferTaskLastResult"},
|
||||
{23, nullptr, "SuspendTransferTask"},
|
||||
{24, nullptr, "GetCurrentTransferTaskInfo"},
|
||||
{25, nullptr, "Unknown25"}, //20.1.0+
|
||||
{26, nullptr, "Unknown26"}, //20.1.0+
|
||||
{27, nullptr, "Unknown27"}, //20.1.0+
|
||||
{28, nullptr, "Unknown28"}, //20.1.0+
|
||||
{29, nullptr, "Unknown29"}, //20.1.0+
|
||||
{30, nullptr, "Unknown30"}, //20.1.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -45,7 +53,14 @@ ITransferTaskListController::ITransferTaskListController(Core::System& system_)
|
||||
|
||||
ITransferTaskListController::~ITransferTaskListController() = default;
|
||||
|
||||
Result ITransferTaskListController::GetNativeHandleHolder(
|
||||
Result ITransferTaskListController::GetTransferTaskEndEventNativeHandleHolder(
|
||||
Out<SharedPointer<INativeHandleHolder>> out_holder) {
|
||||
LOG_WARNING(Service_OLSC, "(STUBBED) called");
|
||||
*out_holder = std::make_shared<INativeHandleHolder>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ITransferTaskListController::GetTransferTaskStartEventNativeHandleHolder(
|
||||
Out<SharedPointer<INativeHandleHolder>> out_holder) {
|
||||
LOG_WARNING(Service_OLSC, "(STUBBED) called");
|
||||
*out_holder = std::make_shared<INativeHandleHolder>(system);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -14,7 +17,8 @@ public:
|
||||
~ITransferTaskListController() override;
|
||||
|
||||
private:
|
||||
Result GetNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
|
||||
Result GetTransferTaskEndEventNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
|
||||
Result GetTransferTaskStartEventNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
|
||||
};
|
||||
|
||||
} // namespace Service::OLSC
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -34,10 +37,10 @@ public:
|
||||
{17, nullptr, "AcquireIrq"},
|
||||
{18, nullptr, "ReleaseIrq"},
|
||||
{19, nullptr, "SetIrqEnable"},
|
||||
{20, nullptr, "SetAspmEnable"},
|
||||
{21, nullptr, "SetResetUponResumeEnable"},
|
||||
{22, nullptr, "ResetFunction"},
|
||||
{23, nullptr, "Unknown23"},
|
||||
{20, nullptr, "GetIrqEvent"},
|
||||
{21, nullptr, "SetAspmEnable"},
|
||||
{22, nullptr, "SetResetUponResumeEnable"},
|
||||
{23, nullptr, "ResetFunction"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
|
||||
{1017, D<&IParentalControlService::EndFreeCommunication>, "EndFreeCommunication"},
|
||||
{1018, D<&IParentalControlService::IsFreeCommunicationAvailable>, "IsFreeCommunicationAvailable"},
|
||||
{1019, D<&IParentalControlService::ConfirmLaunchApplicationPermission>, "ConfirmLaunchApplicationPermission"},
|
||||
{1020, nullptr, "ConfirmLaunchSharedApplicationPermission"}, //20.0.0+
|
||||
{1021, nullptr, "TryBeginFreeCommunicationForStreamPlay"}, //21.0.0+
|
||||
{1022, nullptr, "EndFreeCommunicationForStreamPlay"}, //21.0.0+
|
||||
{1031, D<&IParentalControlService::IsRestrictionEnabled>, "IsRestrictionEnabled"},
|
||||
{1032, D<&IParentalControlService::GetSafetyLevel>, "GetSafetyLevel"},
|
||||
{1033, nullptr, "SetSafetyLevel"},
|
||||
@@ -56,6 +59,8 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
|
||||
{1047, nullptr, "NotifyApplicationDownloadStarted"},
|
||||
{1048, nullptr, "NotifyNetworkProfileCreated"},
|
||||
{1049, nullptr, "ResetFreeCommunicationApplicationList"},
|
||||
{1050, nullptr, "AddToFreeCommunicationApplicationList"}, //20.0.0+
|
||||
{1051, nullptr, "NotifyApplicationDownloadStarted"}, //20.0.0+
|
||||
{1061, D<&IParentalControlService::ConfirmStereoVisionRestrictionConfigurable>, "ConfirmStereoVisionRestrictionConfigurable"},
|
||||
{1062, D<&IParentalControlService::GetStereoVisionRestriction>, "GetStereoVisionRestriction"},
|
||||
{1063, D<&IParentalControlService::SetStereoVisionRestriction>, "SetStereoVisionRestriction"},
|
||||
@@ -126,8 +131,17 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
|
||||
{2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
|
||||
{2014, nullptr, "FinishSynchronizeParentalControlSettings"},
|
||||
{2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
|
||||
{2016, nullptr, "RequestUpdateExemptionListAsync"},
|
||||
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"} // 18.0.0+
|
||||
{2016, nullptr, "RequestUpdateExemptionListAsync"}, //5.0.0+
|
||||
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"}, // 18.0.0+
|
||||
{2017, nullptr, "AuthorizePairingAsync"}, //19.0.0+
|
||||
{2019, nullptr, "RequestUpdateDeviceUsersBackground"}, //19.0.0+
|
||||
{2021, nullptr, "RequestCopyPairingAsync"}, //20.0.0+
|
||||
{2022, nullptr, "FinishRequestCopyPairing"}, //20.0.0+
|
||||
{2023, nullptr, "IsFromPairingActiveDevice"}, //20.0.0+
|
||||
{2024, nullptr, "RollbackCopyPairing"}, //21.0.0+
|
||||
{3001, nullptr, "GetErrorContextChangedEvent"}, //20.0.0+
|
||||
{145601, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"}, // 18.0.0+
|
||||
{195101, D<&IParentalControlService::SetPlayTimerSettings>, "SetPlayTimerSettingsForDebug"}, //18.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
@@ -393,16 +407,21 @@ Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restric
|
||||
}
|
||||
|
||||
Result IParentalControlService::GetPlayTimerSettingsOld(
|
||||
Out<PlayTimerSettings> out_play_timer_settings) {
|
||||
Out<PlayTimerSettingsOld> out_play_timer_settings) {
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called");
|
||||
*out_play_timer_settings = {};
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IParentalControlService::GetPlayTimerSettings(
|
||||
Out<PlayTimerSettings> out_play_timer_settings) {
|
||||
Result IParentalControlService::GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings) {
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called");
|
||||
*out_play_timer_settings = {};
|
||||
*out_play_timer_settings = raw_play_timer_settings;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IParentalControlService::SetPlayTimerSettings(PlayTimerSettings play_timer_settings) {
|
||||
LOG_WARNING(Service_PCTL, "(STUBBED) called");
|
||||
raw_play_timer_settings = play_timer_settings;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ private:
|
||||
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
|
||||
Result GetPlayTimerRemainingTime(Out<s32> out_remaining_time);
|
||||
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
|
||||
Result GetPlayTimerSettingsOld(Out<PlayTimerSettings> out_play_timer_settings);
|
||||
Result GetPlayTimerSettingsOld(Out<PlayTimerSettingsOld> out_play_timer_settings);
|
||||
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
|
||||
Result GetPlayTimerRemainingTimeDisplayInfo();
|
||||
@@ -60,6 +60,7 @@ private:
|
||||
Result SetStereoVisionRestriction(bool stereo_vision_restriction);
|
||||
Result ResetConfirmedStereoVisionPermission();
|
||||
Result GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings);
|
||||
Result SetPlayTimerSettings(PlayTimerSettings out_play_timer_settings);
|
||||
|
||||
struct States {
|
||||
u64 current_tid{};
|
||||
@@ -83,6 +84,8 @@ private:
|
||||
RestrictionSettings restriction_settings{};
|
||||
std::array<char, 8> pin_code{};
|
||||
Capability capability{};
|
||||
// TODO: this is RAW as fuck
|
||||
PlayTimerSettings raw_play_timer_settings{};
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Event synchronization_event;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -34,10 +37,16 @@ struct RestrictionSettings {
|
||||
};
|
||||
static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
|
||||
|
||||
// This is nn::pctl::PlayTimerSettings
|
||||
struct PlayTimerSettings {
|
||||
// This is nn::pctl::PlayTimerSettingsOld
|
||||
struct PlayTimerSettingsOld {
|
||||
std::array<u32, 13> settings;
|
||||
};
|
||||
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
|
||||
static_assert(sizeof(PlayTimerSettingsOld) == 0x34, "PlayTimerSettingsOld has incorrect size.");
|
||||
|
||||
// This is nn::pctl::PlayTimerSettings
|
||||
struct PlayTimerSettings {
|
||||
std::array<u32, 17> settings; //21.0.0+ now takes 0x44
|
||||
};
|
||||
static_assert(sizeof(PlayTimerSettings) == 0x44, "PlayTimerSettings has incorrect size.");
|
||||
|
||||
} // namespace Service::PCTL
|
||||
|
||||
@@ -34,9 +34,9 @@ public:
|
||||
{10300, &PlayReport::GetTransmissionStatus, "GetTransmissionStatus"},
|
||||
{10400, &PlayReport::GetSystemSessionId, "GetSystemSessionId"},
|
||||
{20100, &PlayReport::SaveSystemReportOld, "SaveSystemReport"},
|
||||
{20101, &PlayReport::SaveSystemReportWithUserOld, "SaveSystemReportWithUser"},
|
||||
{20102, &PlayReport::SaveSystemReport, "SaveSystemReport"},
|
||||
{20103, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"},
|
||||
{20101, &PlayReport::SaveSystemReportWithUserOld, "SaveSystemReportWithUser"},
|
||||
{20102, &PlayReport::SaveSystemReport, "SaveSystemReport"},
|
||||
{20103, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"},
|
||||
{20200, nullptr, "SetOperationMode"},
|
||||
{30100, nullptr, "ClearStorage"},
|
||||
{30200, nullptr, "ClearStatistics"},
|
||||
|
||||
@@ -18,49 +18,43 @@
|
||||
|
||||
namespace Service {
|
||||
|
||||
/**
|
||||
* Creates a function string for logging, complete with the name (or header code, depending
|
||||
* on what's passed in) the port name, and all the cmd_buff arguments.
|
||||
*/
|
||||
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name,
|
||||
std::string_view port_name,
|
||||
const u32* cmd_buff) {
|
||||
/// @brief Creates a function string for logging, complete with the name (or header code, depending
|
||||
/// on what's passed in) the port name, and all the cmd_buff arguments.
|
||||
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, std::string_view port_name, const u32* cmd_buff) {
|
||||
// Number of params == bits 0-5 + bits 6-11
|
||||
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
|
||||
|
||||
std::string function_string = fmt::format("function '{}': port={}", name, port_name);
|
||||
for (int i = 1; i <= num_params; ++i) {
|
||||
|
||||
for (int i = 1; i <= num_params; ++i)
|
||||
function_string += fmt::format(", cmd_buff[{}]={:#X}", i, cmd_buff[i]);
|
||||
}
|
||||
|
||||
return function_string;
|
||||
}
|
||||
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
||||
u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
|
||||
service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
|
||||
service_name{service_name_}, handler_invoker{handler_invoker_}, max_sessions{max_sessions_} {}
|
||||
|
||||
ServiceFrameworkBase::~ServiceFrameworkBase() {
|
||||
// Wait for other threads to release access before destroying
|
||||
const auto guard = LockService();
|
||||
const auto guard = ServiceFrameworkBase::LockService();
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
|
||||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
handlers.reserve(handlers.size() + n);
|
||||
for (std::size_t i = 0; i < n; ++i) {
|
||||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions,
|
||||
std::size_t n) {
|
||||
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) {
|
||||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
handlers_tipc.reserve(handlers_tipc.size() + n);
|
||||
for (std::size_t i = 0; i < n; ++i) {
|
||||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header,
|
||||
functions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
||||
@@ -69,15 +63,12 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
||||
std::string function_name = info == nullptr ? "<unknown>" : info->name;
|
||||
|
||||
fmt::memory_buffer buf;
|
||||
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}",
|
||||
ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
|
||||
for (int i = 1; i <= 8; ++i) {
|
||||
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
|
||||
for (int i = 1; i <= 8; ++i)
|
||||
fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]);
|
||||
}
|
||||
buf.push_back('}');
|
||||
|
||||
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name,
|
||||
service_name);
|
||||
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name);
|
||||
UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf));
|
||||
if (Settings::values.use_auto_stub) {
|
||||
LOG_WARNING(Service, "Using auto stub fallback!");
|
||||
@@ -87,25 +78,20 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) {
|
||||
auto itr = handlers.find(ctx.GetCommand());
|
||||
const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second;
|
||||
if (info == nullptr || info->handler_callback == nullptr) {
|
||||
auto it = handlers.find(ctx.GetCommand());
|
||||
FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second;
|
||||
if (info == nullptr || info->handler_callback == nullptr)
|
||||
return ReportUnimplementedFunction(ctx, info);
|
||||
}
|
||||
|
||||
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
|
||||
handler_invoker(this, info->handler_callback, ctx);
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) {
|
||||
boost::container::flat_map<u32, FunctionInfoBase>::iterator itr;
|
||||
|
||||
itr = handlers_tipc.find(ctx.GetCommand());
|
||||
|
||||
const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second;
|
||||
if (info == nullptr || info->handler_callback == nullptr) {
|
||||
auto it = handlers_tipc.find(ctx.GetCommand());
|
||||
FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : &it->second;
|
||||
if (info == nullptr || info->handler_callback == nullptr)
|
||||
return ReportUnimplementedFunction(ctx, info);
|
||||
}
|
||||
|
||||
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
|
||||
handler_invoker(this, info->handler_callback, ctx);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -47,25 +50,23 @@ static_assert(ServerSessionCountMax == 0x40,
|
||||
class ServiceFrameworkBase : public SessionRequestHandler {
|
||||
public:
|
||||
/// Returns the string identifier used to connect to the service.
|
||||
std::string GetServiceName() const {
|
||||
[[nodiscard]] std::string_view GetServiceName() const noexcept {
|
||||
return service_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of sessions that can be connected to this service at the same
|
||||
* time.
|
||||
*/
|
||||
u32 GetMaxSessions() const {
|
||||
/// @brief Returns the maximum number of sessions that can be connected to this service at the same
|
||||
/// time.
|
||||
u32 GetMaxSessions() const noexcept {
|
||||
return max_sessions;
|
||||
}
|
||||
|
||||
/// Invokes a service request routine using the HIPC protocol.
|
||||
/// @brief Invokes a service request routine using the HIPC protocol.
|
||||
void InvokeRequest(HLERequestContext& ctx);
|
||||
|
||||
/// Invokes a service request routine using the HIPC protocol.
|
||||
/// @brief Invokes a service request routine using the HIPC protocol.
|
||||
void InvokeRequestTipc(HLERequestContext& ctx);
|
||||
|
||||
/// Handles a synchronization request for the service.
|
||||
/// @brief Handles a synchronization request for the service.
|
||||
Result HandleSyncRequest(Kernel::KServerSession& session, HLERequestContext& context) override;
|
||||
|
||||
protected:
|
||||
@@ -74,7 +75,7 @@ protected:
|
||||
using HandlerFnP = void (Self::*)(HLERequestContext&);
|
||||
|
||||
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
|
||||
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() {
|
||||
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() noexcept {
|
||||
return std::unique_lock{lock_service};
|
||||
}
|
||||
|
||||
@@ -105,20 +106,19 @@ private:
|
||||
void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
|
||||
void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info);
|
||||
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers;
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
|
||||
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
|
||||
std::mutex lock_service;
|
||||
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
|
||||
InvokerFn* handler_invoker;
|
||||
|
||||
/// Maximum number of concurrent sessions that this service can handle.
|
||||
u32 max_sessions;
|
||||
|
||||
/// Flag to store if a port was already create/installed to detect multiple install attempts,
|
||||
/// which is not supported.
|
||||
bool service_registered = false;
|
||||
|
||||
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
|
||||
InvokerFn* handler_invoker;
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers;
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
|
||||
|
||||
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
|
||||
std::mutex lock_service;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -142,20 +142,12 @@ protected:
|
||||
// TODO(yuriks): This function could be constexpr, but clang is the only compiler that
|
||||
// doesn't emit an ICE or a wrong diagnostic because of the static_cast.
|
||||
|
||||
/**
|
||||
* Constructs a FunctionInfo for a function.
|
||||
*
|
||||
* @param expected_header_ request header in the command buffer which will trigger dispatch
|
||||
* to this handler
|
||||
* @param handler_callback_ member function in this service which will be called to handle
|
||||
* the request
|
||||
* @param name_ human-friendly name for the request. Used mostly for logging purposes.
|
||||
*/
|
||||
FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
|
||||
: FunctionInfoBase{
|
||||
expected_header_,
|
||||
// Type-erase member function pointer by casting it down to the base class.
|
||||
static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {}
|
||||
/// @brief Constructs a FunctionInfo for a function.
|
||||
/// @param expected_header_ request header in the command buffer which will trigger dispatch to this handler
|
||||
/// @param handler_callback_ member function in this service which will be called to handle the request
|
||||
/// @param name_ human-friendly name for the request. Used mostly for logging purposes.
|
||||
constexpr FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
|
||||
: FunctionInfoBase{expected_header_, HandlerFnP<ServiceFrameworkBase>(handler_callback_), name_} {}
|
||||
};
|
||||
using FunctionInfo = FunctionInfoTyped<Self>;
|
||||
|
||||
|
||||
@@ -36,6 +36,29 @@ struct SettingsHeader {
|
||||
u32 version;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
void SyncGlobalLanguageFromCode(LanguageCode language_code) {
|
||||
const auto it = std::find_if(available_language_codes.begin(), available_language_codes.end(),
|
||||
[language_code](LanguageCode code) { return code == language_code; });
|
||||
if (it == available_language_codes.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::size_t index = static_cast<std::size_t>(std::distance(available_language_codes.begin(), it));
|
||||
if (index >= static_cast<std::size_t>(Settings::values.language_index.GetValue())) {
|
||||
Settings::values.language_index.SetValue(static_cast<Settings::Language>(index));
|
||||
}
|
||||
}
|
||||
|
||||
void SyncGlobalRegionFromCode(SystemRegionCode region_code) {
|
||||
const auto region_index = static_cast<std::size_t>(region_code);
|
||||
if (region_index > static_cast<std::size_t>(Settings::Region::Taiwan)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings::values.region_index.SetValue(static_cast<Settings::Region>(region_index));
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
|
||||
@@ -457,6 +480,7 @@ Result ISystemSettingsServer::SetLanguageCode(LanguageCode language_code) {
|
||||
LOG_INFO(Service_SET, "called, language_code={}", language_code);
|
||||
|
||||
m_system_settings.language_code = language_code;
|
||||
SyncGlobalLanguageFromCode(language_code);
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -889,6 +913,7 @@ Result ISystemSettingsServer::SetRegionCode(SystemRegionCode region_code) {
|
||||
LOG_INFO(Service_SET, "called, region_code={}", region_code);
|
||||
|
||||
m_system_settings.region_code = region_code;
|
||||
SyncGlobalRegionFromCode(region_code);
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -1224,6 +1249,7 @@ Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout)
|
||||
LOG_INFO(Service_SET, "called, keyboard_layout={}", keyboard_layout);
|
||||
|
||||
m_system_settings.keyboard_layout = keyboard_layout;
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
@@ -578,7 +578,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
|
||||
}
|
||||
|
||||
std::vector<Network::PollFD> host_pollfds(fds.size());
|
||||
std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [this](PollFD pollfd) {
|
||||
std::transform(fds.begin(), fds.end(), host_pollfds.begin(), [](PollFD pollfd) {
|
||||
Network::PollFD result;
|
||||
result.socket = file_descriptors[pollfd.fd]->socket.get();
|
||||
result.events = Translate(pollfd.events);
|
||||
@@ -657,7 +657,11 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
|
||||
|
||||
const auto result = Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
|
||||
if (result != Errno::SUCCESS) {
|
||||
LOG_ERROR(Service, "Connect fd={} failed with errno={}", fd, static_cast<int>(result));
|
||||
if (result == Errno::INPROGRESS || result == Errno::AGAIN) {
|
||||
LOG_DEBUG(Service, "Connect fd={} in progress (non-blocking), errno={}", fd, static_cast<int>(result));
|
||||
} else {
|
||||
LOG_ERROR(Service, "Connect fd={} failed with errno={}", fd, static_cast<int>(result));
|
||||
}
|
||||
} else {
|
||||
LOG_INFO(Service, "Connect fd={} succeeded", fd);
|
||||
}
|
||||
@@ -967,7 +971,11 @@ Expected<s32, Errno> BSD::DuplicateSocketImpl(s32 fd) {
|
||||
return Unexpected(Errno::MFILE);
|
||||
}
|
||||
|
||||
file_descriptors[new_fd] = file_descriptors[fd];
|
||||
file_descriptors[new_fd] = FileDescriptor{
|
||||
.socket = file_descriptors[fd]->socket,
|
||||
.flags = file_descriptors[fd]->flags,
|
||||
.is_connection_based = file_descriptors[fd]->is_connection_based,
|
||||
};
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
@@ -1074,8 +1082,7 @@ BSD::~BSD() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> BSD::LockService() {
|
||||
// Do not lock socket IClient instances.
|
||||
std::unique_lock<std::mutex> BSD::LockService() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ private:
|
||||
|
||||
void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept;
|
||||
|
||||
std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors;
|
||||
static inline std::array<std::optional<FileDescriptor>, MAX_FD> file_descriptors{};
|
||||
|
||||
/// Callback to parse and handle a received wifi packet.
|
||||
void OnProxyPacketReceived(const Network::ProxyPacket& packet);
|
||||
@@ -188,7 +188,7 @@ private:
|
||||
Network::RoomMember::CallbackHandle<Network::ProxyPacket> proxy_packet_received;
|
||||
|
||||
protected:
|
||||
virtual std::unique_lock<std::mutex> LockService() override;
|
||||
std::unique_lock<std::mutex> LockService() noexcept override;
|
||||
};
|
||||
|
||||
class BSDCFG final : public ServiceFramework<BSDCFG> {
|
||||
|
||||
@@ -157,22 +157,24 @@ private:
|
||||
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
|
||||
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
|
||||
|
||||
// Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
|
||||
auto res = bsd->DuplicateSocketImpl(fd);
|
||||
if (!res.has_value()) {
|
||||
LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
|
||||
return ResultInvalidSocket;
|
||||
}
|
||||
|
||||
const s32 duplicated_fd = *res;
|
||||
|
||||
if (do_not_close_socket) {
|
||||
auto res = bsd->DuplicateSocketImpl(fd);
|
||||
if (!res.has_value()) {
|
||||
LOG_ERROR(Service_SSL, "Failed to duplicate socket with fd {}", fd);
|
||||
return ResultInvalidSocket;
|
||||
}
|
||||
fd = *res;
|
||||
fd_to_close = fd;
|
||||
*out_fd = fd;
|
||||
*out_fd = duplicated_fd;
|
||||
} else {
|
||||
*out_fd = -1;
|
||||
fd_to_close = duplicated_fd;
|
||||
}
|
||||
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd);
|
||||
|
||||
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(duplicated_fd);
|
||||
if (!sock.has_value()) {
|
||||
LOG_ERROR(Service_SSL, "invalid socket fd {}", fd);
|
||||
LOG_ERROR(Service_SSL, "invalid socket fd {} after duplication", duplicated_fd);
|
||||
return ResultInvalidSocket;
|
||||
}
|
||||
socket = std::move(*sock);
|
||||
@@ -325,7 +327,19 @@ private:
|
||||
res = backend->GetServerCerts(&certs);
|
||||
if (res == ResultSuccess) {
|
||||
const std::vector<u8> certs_buf = SerializeServerCerts(certs);
|
||||
ctx.WriteBuffer(certs_buf);
|
||||
if (ctx.CanWriteBuffer()) {
|
||||
const size_t buffer_size = ctx.GetWriteBufferSize();
|
||||
if (certs_buf.size() <= buffer_size) {
|
||||
ctx.WriteBuffer(certs_buf);
|
||||
} else {
|
||||
LOG_WARNING(Service_SSL, "Certificate buffer too small: {} bytes needed, {} bytes available",
|
||||
certs_buf.size(), buffer_size);
|
||||
ctx.WriteBuffer(std::span<const u8>(certs_buf.data(), buffer_size));
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG(Service_SSL, "No output buffer provided for certificates ({} bytes)", certs_buf.size());
|
||||
}
|
||||
|
||||
out.certs_count = static_cast<u32>(certs.size());
|
||||
out.certs_size = static_cast<u32>(certs_buf.size());
|
||||
}
|
||||
@@ -664,119 +678,119 @@ class ISslServiceForSystem final : public ServiceFramework<ISslServiceForSystem>
|
||||
{103, D<&ISslServiceForSystem::VerifySignature>, "VerifySignature"}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
RegisterHandlers(functions);
|
||||
};
|
||||
|
||||
|
||||
Result CreateContext() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result GetContextCount() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result GetCertificates() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result GetCertificateBufSize() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result DebugIoctl() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result SetInterfaceVersion() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result FlushSessionCache() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result SetDebugOption() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result GetDebugOption() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result ClearTls12FallbackFlag() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result CreateContextForSystem() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result SetThreadCoreMask() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result GetThreadCoreMask() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
|
||||
|
||||
Result VerifySignature() {
|
||||
LOG_DEBUG(Service_SSL, "(STUBBED) called.");
|
||||
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
|
||||
|
||||
return ResultSuccess;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
||||
@@ -166,6 +166,16 @@ Result Container::GetLayerZIndex(u64 layer_id, s32* out_z_index) {
|
||||
R_RETURN(VI::ResultNotFound);
|
||||
}
|
||||
|
||||
Result Container::SetLayerIsOverlay(u64 layer_id, bool is_overlay) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
|
||||
auto* const layer = m_layers.GetLayerById(layer_id);
|
||||
R_UNLESS(layer != nullptr, VI::ResultNotFound);
|
||||
|
||||
m_surface_flinger->SetLayerIsOverlay(layer->GetConsumerBinderId(), is_overlay);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void Container::LinkVsyncEvent(u64 display_id, Event* event) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
m_conductor->LinkVsyncEvent(display_id, event);
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
Result SetLayerBlending(u64 layer_id, bool enabled);
|
||||
Result SetLayerZIndex(u64 layer_id, s32 z_index);
|
||||
Result GetLayerZIndex(u64 layer_id, s32* out_z_index);
|
||||
Result SetLayerIsOverlay(u64 layer_id, bool is_overlay);
|
||||
|
||||
void LinkVsyncEvent(u64 display_id, Event* event);
|
||||
void UnlinkVsyncEvent(u64 display_id, Event* event);
|
||||
|
||||
@@ -46,8 +46,8 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_
|
||||
u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
|
||||
u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
|
||||
|
||||
for (; start < end; ++start) {
|
||||
*start = 0x00000000; // ARGB/RGBA with alpha=0
|
||||
for (; start < end; start++) {
|
||||
*start = 0xFF0000FF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,6 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
|
||||
|
||||
// Configure blending and z-index
|
||||
R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
|
||||
R_ASSERT(m_container.SetLayerZIndex(session.layer_id, 100000));
|
||||
|
||||
// Get the producer and set preallocated buffers.
|
||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||
@@ -374,11 +373,6 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
||||
android::Status::NoError,
|
||||
VI::ResultOperationFailed);
|
||||
|
||||
// Ensure the layer is visible when content is presented.
|
||||
// Re-assert overlay priority in case clients reset it.
|
||||
(void)m_container.SetLayerZIndex(layer_id, 100000);
|
||||
(void)m_container.SetLayerVisibility(layer_id, true);
|
||||
|
||||
// We succeeded.
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -415,51 +409,22 @@ Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32*
|
||||
// TODO: this could be optimized
|
||||
s64 e = -1280 * 768 * 4;
|
||||
for (auto& block : *m_buffer_page_group) {
|
||||
u8* const block_start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
|
||||
u8* ptr = block_start;
|
||||
u8* const block_end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
|
||||
u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
|
||||
u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
|
||||
|
||||
for (; ptr < block_end; ++ptr) {
|
||||
for (; start < end; start++) {
|
||||
*start = 0;
|
||||
if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
|
||||
*ptr = capture_buffer[static_cast<size_t>(e)];
|
||||
} else {
|
||||
*ptr = 0;
|
||||
*start = capture_buffer[e];
|
||||
}
|
||||
++e;
|
||||
e++;
|
||||
}
|
||||
|
||||
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(block_start, scratch, [&](DAddr addr) {
|
||||
m_system.GPU().InvalidateRegion(addr, block_end - block_start);
|
||||
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
|
||||
m_system.GPU().InvalidateRegion(addr, end - start);
|
||||
});
|
||||
}
|
||||
|
||||
// After writing, present a frame on each active shared layer so it becomes visible.
|
||||
for (auto& [aruid, session] : m_sessions) {
|
||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||
if (R_FAILED(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id))) {
|
||||
continue;
|
||||
}
|
||||
s32 slot = -1;
|
||||
android::Fence fence = android::Fence::NoFence();
|
||||
if (producer->DequeueBuffer(&slot, &fence, SharedBufferAsync != 0, SharedBufferWidth,
|
||||
SharedBufferHeight, SharedBufferBlockLinearFormat, 0) !=
|
||||
android::Status::NoError) {
|
||||
continue;
|
||||
}
|
||||
std::shared_ptr<android::GraphicBuffer> gb;
|
||||
if (producer->RequestBuffer(slot, &gb) != android::Status::NoError) {
|
||||
producer->CancelBuffer(slot, android::Fence::NoFence());
|
||||
continue;
|
||||
}
|
||||
android::QueueBufferInput qin{};
|
||||
android::QueueBufferOutput qout{};
|
||||
qin.crop = {0, 0, static_cast<s32>(SharedBufferWidth), static_cast<s32>(SharedBufferHeight)};
|
||||
qin.fence = android::Fence::NoFence();
|
||||
qin.transform = static_cast<android::NativeWindowTransform>(0);
|
||||
qin.swap_interval = 1;
|
||||
(void)producer->QueueBuffer(slot, qin, &qout);
|
||||
}
|
||||
|
||||
*out_was_written = true;
|
||||
*out_layer_index = 1;
|
||||
R_SUCCEED();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "common/assert.h"
|
||||
@@ -681,22 +682,17 @@ struct Memory::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, auto on_unmapped, auto on_rasterizer) const {
|
||||
template<typename F, typename G>
|
||||
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, F&& on_unmapped, G&& on_rasterizer) const {
|
||||
// AARCH64 masks the upper 16 bit of all memory accesses
|
||||
vaddr = vaddr & 0xffffffffffffULL;
|
||||
if (!AddressSpaceContains(*current_page_table, vaddr, 1)) [[unlikely]] {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
} else {
|
||||
vaddr &= 0xffffffffffffULL;
|
||||
if (AddressSpaceContains(*current_page_table, vaddr, 1)) [[likely]] {
|
||||
// Avoid adding any extra logic to this fast-path block
|
||||
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
|
||||
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
|
||||
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) [[likely]] {
|
||||
return reinterpret_cast<u8*>(pointer + vaddr);
|
||||
} else {
|
||||
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
||||
case Common::PageType::Unmapped:
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
case Common::PageType::Memory:
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
|
||||
return nullptr;
|
||||
@@ -707,11 +703,18 @@ struct Memory::Impl {
|
||||
on_rasterizer();
|
||||
return host_ptr;
|
||||
}
|
||||
case Common::PageType::Unmapped: [[unlikely]] {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,172 +732,38 @@ struct Memory::Impl {
|
||||
GetInteger(vaddr), []() {}, []() {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a particular data type out of memory at the given virtual address.
|
||||
*
|
||||
* @param vaddr The virtual address to read the data type from.
|
||||
*
|
||||
* @tparam T The data type to read out of memory. This type *must* be
|
||||
* trivially copyable, otherwise the behavior of this function
|
||||
* is undefined.
|
||||
*
|
||||
* @returns The instance of T read from the specified virtual address.
|
||||
*/
|
||||
/// @brief Reads a particular data type out of memory at the given virtual address.
|
||||
/// @param vaddr The virtual address to read the data type from.
|
||||
/// @tparam T The data type to read out of memory.
|
||||
/// @returns The instance of T read from the specified virtual address.
|
||||
template <typename T>
|
||||
T Read(Common::ProcessAddress vaddr) {
|
||||
// Fast path for aligned reads of common sizes
|
||||
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||
const u64 addr = GetInteger(vaddr);
|
||||
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
|
||||
// 8-bit reads are always aligned
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read8 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*ptr);
|
||||
}
|
||||
return 0;
|
||||
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
|
||||
// Check alignment for 16-bit reads
|
||||
if ((addr & 1) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read16 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u16*>(ptr));
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
|
||||
// Check alignment for 32-bit reads
|
||||
if ((addr & 3) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read32 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u32*>(ptr));
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
|
||||
// Check alignment for 64-bit reads
|
||||
if ((addr & 7) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read64 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u64*>(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the general case for other types or unaligned access
|
||||
T result = 0;
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
if (auto const ptr = GetPointerImpl(addr, [addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
|
||||
}, [&]() {
|
||||
HandleRasterizerDownload(addr, sizeof(T));
|
||||
}); ptr) [[likely]] {
|
||||
// It may be tempting to rewrite this particular section to use "reinterpret_cast";
|
||||
// afterall, it's trivially copyable so surely it can be copied ov- Alignment.
|
||||
// Remember, alignment. memcpy() will deal with all the alignment extremely fast.
|
||||
T result{};
|
||||
std::memcpy(&result, ptr, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
return T{};
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a particular data type to memory at the given virtual address.
|
||||
*
|
||||
* @param vaddr The virtual address to write the data type to.
|
||||
*
|
||||
* @tparam T The data type to write to memory. This type *must* be
|
||||
* trivially copyable, otherwise the behavior of this function
|
||||
* is undefined.
|
||||
*/
|
||||
/// @brief Writes a particular data type to memory at the given virtual address.
|
||||
/// @param vaddr The virtual address to write the data type to.
|
||||
/// @tparam T The data type to write to memory.
|
||||
template <typename T>
|
||||
void Write(Common::ProcessAddress vaddr, const T data) {
|
||||
// Fast path for aligned writes of common sizes
|
||||
inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||
const u64 addr = GetInteger(vaddr);
|
||||
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
|
||||
// 8-bit writes are always aligned
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write8 @ 0x{:016X} = 0x{:02X}", addr,
|
||||
static_cast<u8>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*ptr = static_cast<u8>(data);
|
||||
}
|
||||
return;
|
||||
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
|
||||
// Check alignment for 16-bit writes
|
||||
if ((addr & 1) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write16 @ 0x{:016X} = 0x{:04X}", addr,
|
||||
static_cast<u16>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u16*>(ptr) = static_cast<u16>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
|
||||
// Check alignment for 32-bit writes
|
||||
if ((addr & 3) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write32 @ 0x{:016X} = 0x{:08X}", addr,
|
||||
static_cast<u32>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u32*>(ptr) = static_cast<u32>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
|
||||
// Check alignment for 64-bit writes
|
||||
if ((addr & 7) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write64 @ 0x{:016X} = 0x{:016X}", addr,
|
||||
static_cast<u64>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u64*>(ptr) = static_cast<u64>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the general case for other types or unaligned access
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8,
|
||||
addr, static_cast<u64>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
if (auto const ptr = GetPointerImpl(addr, [addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, addr, u64(data));
|
||||
}, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]]
|
||||
std::memcpy(ptr, &data, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(dynarmic LANGUAGES C CXX ASM VERSION 6.7.0)
|
||||
|
||||
set(dynarmic_VERSION_MAJOR 7)
|
||||
set(dynarmic_VERSION_MINOR 0)
|
||||
set(dynarmic_VERSION_PATCH 0)
|
||||
|
||||
set(dynarmic_VERSION ${dynarmic_VERSION_MAJOR}.${dynarmic_VERSION_MINOR}.${dynarmic_VERSION_PATCH})
|
||||
|
||||
# Determine if we're built as a subproject (using add_subdirectory)
|
||||
# or if this is the master project.
|
||||
@@ -46,7 +51,7 @@ if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
# Add the module directory to the list of paths
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||
|
||||
# Compiler flags
|
||||
if (MSVC)
|
||||
|
||||
@@ -217,13 +217,13 @@ void A32EmitX64::ClearFastDispatchTable() {
|
||||
}
|
||||
|
||||
void A32EmitX64::GenTerminalHandlers() {
|
||||
// PC ends up in ebp, location_descriptor ends up in rbx
|
||||
// PC ends up in edi, location_descriptor ends up in rbx
|
||||
const auto calculate_location_descriptor = [this] {
|
||||
// This calculation has to match up with IREmitter::PushRSB
|
||||
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A32JitState, upper_location_descriptor)]);
|
||||
code.shl(rbx, 32);
|
||||
code.mov(ecx, MJitStateReg(A32::Reg::PC));
|
||||
code.mov(ebp, ecx);
|
||||
code.mov(edi, ecx);
|
||||
code.or_(rbx, rcx);
|
||||
};
|
||||
|
||||
@@ -238,7 +238,7 @@ void A32EmitX64::GenTerminalHandlers() {
|
||||
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax);
|
||||
code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
|
||||
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
|
||||
code.jne(rsb_cache_miss);
|
||||
code.jne(rsb_cache_miss, code.T_NEAR);
|
||||
} else {
|
||||
code.jne(code.GetReturnFromRunCodeAddress());
|
||||
}
|
||||
@@ -251,20 +251,21 @@ void A32EmitX64::GenTerminalHandlers() {
|
||||
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
|
||||
calculate_location_descriptor();
|
||||
code.L(rsb_cache_miss);
|
||||
code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
|
||||
code.mov(rbp, rbx);
|
||||
code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
|
||||
//code.mov(r12d, MJitStateReg(A32::Reg::PC));
|
||||
code.mov(r12, rbx);
|
||||
if (code.HasHostFeature(HostFeature::SSE42)) {
|
||||
code.crc32(rbp, r12);
|
||||
code.crc32(r12, r8);
|
||||
}
|
||||
code.and_(ebp, fast_dispatch_table_mask);
|
||||
code.lea(rbp, ptr[r12 + rbp]);
|
||||
code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
|
||||
code.jne(fast_dispatch_cache_miss);
|
||||
code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
|
||||
code.and_(r12d, fast_dispatch_table_mask);
|
||||
code.lea(r12, ptr[r8 + r12]);
|
||||
code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
|
||||
code.jne(fast_dispatch_cache_miss, code.T_NEAR);
|
||||
code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
|
||||
code.L(fast_dispatch_cache_miss);
|
||||
code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
|
||||
code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
|
||||
code.LookupBlock();
|
||||
code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
|
||||
code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
|
||||
code.jmp(rax);
|
||||
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a32_terminal_handler_fast_dispatch_hint");
|
||||
|
||||
|
||||
@@ -188,13 +188,14 @@ void A64EmitX64::ClearFastDispatchTable() {
|
||||
}
|
||||
|
||||
void A64EmitX64::GenTerminalHandlers() {
|
||||
// PC ends up in rbp, location_descriptor ends up in rbx
|
||||
// PC ends up in rcx, location_descriptor ends up in rbx
|
||||
static_assert(std::find(ABI_ALL_CALLEE_SAVE.begin(), ABI_ALL_CALLEE_SAVE.end(), HostLoc::R12) != ABI_ALL_CALLEE_SAVE.end());
|
||||
const auto calculate_location_descriptor = [this] {
|
||||
// This calculation has to match up with A64::LocationDescriptor::UniqueHash
|
||||
// TODO: Optimization is available here based on known state of fpcr.
|
||||
code.mov(rbp, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
|
||||
code.mov(rdi, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
|
||||
code.mov(rcx, A64::LocationDescriptor::pc_mask);
|
||||
code.and_(rcx, rbp);
|
||||
code.and_(rcx, rdi);
|
||||
code.mov(ebx, dword[code.ABI_JIT_PTR + offsetof(A64JitState, fpcr)]);
|
||||
code.and_(ebx, A64::LocationDescriptor::fpcr_mask);
|
||||
code.shl(rbx, A64::LocationDescriptor::fpcr_shift);
|
||||
@@ -226,20 +227,21 @@ void A64EmitX64::GenTerminalHandlers() {
|
||||
terminal_handler_fast_dispatch_hint = code.getCurr<const void*>();
|
||||
calculate_location_descriptor();
|
||||
code.L(rsb_cache_miss);
|
||||
code.mov(r12, reinterpret_cast<u64>(fast_dispatch_table.data()));
|
||||
code.mov(rbp, rbx);
|
||||
code.mov(r8, reinterpret_cast<u64>(fast_dispatch_table.data()));
|
||||
//code.mov(r12, qword[code.ABI_JIT_PTR + offsetof(A64JitState, pc)]);
|
||||
code.mov(r12, rbx);
|
||||
if (code.HasHostFeature(HostFeature::SSE42)) {
|
||||
code.crc32(rbp, r12);
|
||||
code.crc32(r12, r8);
|
||||
}
|
||||
code.and_(ebp, fast_dispatch_table_mask);
|
||||
code.lea(rbp, ptr[r12 + rbp]);
|
||||
code.cmp(rbx, qword[rbp + offsetof(FastDispatchEntry, location_descriptor)]);
|
||||
code.jne(fast_dispatch_cache_miss);
|
||||
code.jmp(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)]);
|
||||
code.and_(r12d, fast_dispatch_table_mask);
|
||||
code.lea(r12, ptr[r8 + r12]);
|
||||
code.cmp(rbx, qword[r12 + offsetof(FastDispatchEntry, location_descriptor)]);
|
||||
code.jne(fast_dispatch_cache_miss, code.T_NEAR);
|
||||
code.jmp(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)]);
|
||||
code.L(fast_dispatch_cache_miss);
|
||||
code.mov(qword[rbp + offsetof(FastDispatchEntry, location_descriptor)], rbx);
|
||||
code.mov(qword[r12 + offsetof(FastDispatchEntry, location_descriptor)], rbx);
|
||||
code.LookupBlock();
|
||||
code.mov(ptr[rbp + offsetof(FastDispatchEntry, code_ptr)], rax);
|
||||
code.mov(ptr[r12 + offsetof(FastDispatchEntry, code_ptr)], rax);
|
||||
code.jmp(rax);
|
||||
PerfMapRegister(terminal_handler_fast_dispatch_hint, code.getCurr(), "a64_terminal_handler_fast_dispatch_hint");
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
||||
|
||||
cmp(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], 0);
|
||||
jne(return_to_caller_mxcsr_already_exited, T_NEAR);
|
||||
lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], static_cast<u32>(HaltReason::Step));
|
||||
lock(); or_(dword[ABI_JIT_PTR + jsi.offsetof_halt_reason], u32(HaltReason::Step));
|
||||
|
||||
SwitchMxcsrOnEntry();
|
||||
jmp(ABI_PARAM2);
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/opt_passes.h"
|
||||
|
||||
#include "./A32/testenv.h"
|
||||
#include "./A64/testenv.h"
|
||||
|
||||
using namespace Dynarmic;
|
||||
|
||||
std::string_view GetNameOfA32Instruction(u32 instruction) {
|
||||
@@ -65,7 +68,10 @@ void PrintA32Instruction(u32 instruction) {
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
Optimization::Optimize(ir_block, A32::UserConfig{}, {});
|
||||
ArmTestEnv jit_env{};
|
||||
Dynarmic::A32::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
Optimization::Optimize(ir_block, jit_user_config, {});
|
||||
fmt::print("Optimized IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
@@ -80,7 +86,10 @@ void PrintA64Instruction(u32 instruction) {
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
Optimization::Optimize(ir_block, A64::UserConfig{}, {});
|
||||
A64TestEnv jit_env{};
|
||||
Dynarmic::A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
Optimization::Optimize(ir_block, jit_user_config, {});
|
||||
fmt::print("Optimized IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
@@ -98,7 +107,10 @@ void PrintThumbInstruction(u32 instruction) {
|
||||
fmt::print("should_continue: {}\n\n", should_continue);
|
||||
fmt::print("IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
Optimization::Optimize(ir_block, A32::UserConfig{}, {});
|
||||
ThumbTestEnv jit_env{};
|
||||
Dynarmic::A32::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
Optimization::Optimize(ir_block, jit_user_config, {});
|
||||
fmt::print("Optimized IR:\n");
|
||||
fmt::print("{}\n", IR::DumpBlock(ir_block));
|
||||
}
|
||||
@@ -219,7 +231,7 @@ void ExecuteA32Instruction(u32 instruction) {
|
||||
*(iter->second) = *value;
|
||||
fmt::print("> {} = 0x{:08x}\n", reg_name, *value);
|
||||
}
|
||||
} else if (reg_name == "mem" || reg_name == "memory") {
|
||||
} else if (reg_name.starts_with("m")) {
|
||||
fmt::print("address: ");
|
||||
if (const auto address = get_value()) {
|
||||
fmt::print("value: ");
|
||||
@@ -228,7 +240,7 @@ void ExecuteA32Instruction(u32 instruction) {
|
||||
fmt::print("> mem[0x{:08x}] = 0x{:08x}\n", *address, *value);
|
||||
}
|
||||
}
|
||||
} else if (reg_name == "end") {
|
||||
} else if (reg_name == "exit" || reg_name == "end" || reg_name.starts_with("q")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -244,6 +256,7 @@ void ExecuteA32Instruction(u32 instruction) {
|
||||
env.MemoryWrite32(initial_pc + 4, 0xEAFFFFFE); // B +0
|
||||
|
||||
cpu.Run();
|
||||
fmt::print("{}", fmt::join(cpu.Disassemble(), "\n"));
|
||||
|
||||
fmt::print("Registers modified:\n");
|
||||
for (size_t i = 0; i < regs.size(); ++i) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "input_common/drivers/mouse.h"
|
||||
|
||||
namespace InputCommon {
|
||||
constexpr int update_time = 250; // 4 TPS
|
||||
constexpr int update_time = 10;
|
||||
constexpr float default_panning_sensitivity = 0.0010f;
|
||||
constexpr float default_stick_sensitivity = 0.0006f;
|
||||
constexpr float default_deadzone_counterweight = 0.01f;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace Vulkan {
|
||||
|
||||
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines
|
||||
//constexpr size_t SETS_GROW_RATE = 32; //test difference between 16 and 32
|
||||
constexpr size_t SETS_GROW_RATE = 16;
|
||||
constexpr s32 SCORE_THRESHOLD = 3;
|
||||
|
||||
struct DescriptorBank {
|
||||
@@ -29,12 +29,9 @@ struct DescriptorBank {
|
||||
};
|
||||
|
||||
bool DescriptorBankInfo::IsSuperset(const DescriptorBankInfo& subset) const noexcept {
|
||||
return uniform_buffers >= subset.uniform_buffers &&
|
||||
storage_buffers >= subset.storage_buffers &&
|
||||
texture_buffers >= subset.texture_buffers &&
|
||||
image_buffers >= subset.image_buffers &&
|
||||
textures >= subset.textures &&
|
||||
images >= subset.images;
|
||||
return uniform_buffers >= subset.uniform_buffers && storage_buffers >= subset.storage_buffers &&
|
||||
texture_buffers >= subset.texture_buffers && image_buffers >= subset.image_buffers &&
|
||||
textures >= subset.textures && images >= subset.images;
|
||||
}
|
||||
|
||||
template <typename Descriptors>
|
||||
@@ -48,19 +45,6 @@ static u32 Accumulate(const Descriptors& descriptors) {
|
||||
|
||||
static DescriptorBankInfo MakeBankInfo(std::span<const Shader::Info> infos) {
|
||||
DescriptorBankInfo bank;
|
||||
if (infos.size() == 1) {
|
||||
const auto& info = infos.front();
|
||||
const auto acc = [](const auto& ds){ u32 c=0; for (const auto& d: ds) c+=d.count; return c; };
|
||||
bank.uniform_buffers += acc(info.constant_buffer_descriptors);
|
||||
bank.storage_buffers += acc(info.storage_buffers_descriptors);
|
||||
bank.texture_buffers += acc(info.texture_buffer_descriptors);
|
||||
bank.image_buffers += acc(info.image_buffer_descriptors);
|
||||
bank.textures += acc(info.texture_descriptors);
|
||||
bank.images += acc(info.image_descriptors);
|
||||
bank.score = bank.uniform_buffers + bank.storage_buffers + bank.texture_buffers +
|
||||
bank.image_buffers + bank.textures + bank.images;
|
||||
return bank;
|
||||
}
|
||||
for (const Shader::Info& info : infos) {
|
||||
bank.uniform_buffers += Accumulate(info.constant_buffer_descriptors);
|
||||
bank.storage_buffers += Accumulate(info.storage_buffers_descriptors);
|
||||
@@ -103,35 +87,14 @@ static void AllocatePool(const Device& device, DescriptorBank& bank) {
|
||||
}));
|
||||
}
|
||||
|
||||
static size_t GetGrowRate() {
|
||||
if (Settings::getDebugKnobAt(0))
|
||||
return 8;
|
||||
else if (Settings::getDebugKnobAt(1))
|
||||
return 16;
|
||||
else if (Settings::getDebugKnobAt(2))
|
||||
return 24;
|
||||
else if (Settings::getDebugKnobAt(3))
|
||||
return 32;
|
||||
else if (Settings::getDebugKnobAt(4))
|
||||
return 40;
|
||||
else if (Settings::getDebugKnobAt(5))
|
||||
return 48;
|
||||
else if (Settings::getDebugKnobAt(6))
|
||||
return 56;
|
||||
else if (Settings::getDebugKnobAt(7))
|
||||
return 64;
|
||||
else
|
||||
return 16;
|
||||
}
|
||||
|
||||
DescriptorAllocator::DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
|
||||
DescriptorBank& bank_, VkDescriptorSetLayout layout_)
|
||||
: ResourcePool(master_semaphore_, /*SETS_GROW_RATE*/ GetGrowRate()), device{&device_}, bank{&bank_},
|
||||
layout{layout_}, grow_rate{GetGrowRate()} {}
|
||||
: ResourcePool(master_semaphore_, SETS_GROW_RATE), device{&device_}, bank{&bank_},
|
||||
layout{layout_} {}
|
||||
|
||||
VkDescriptorSet DescriptorAllocator::Commit() {
|
||||
const size_t index = CommitResource();
|
||||
return sets[index / grow_rate][index % grow_rate];
|
||||
return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
|
||||
}
|
||||
|
||||
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
|
||||
@@ -139,22 +102,13 @@ void DescriptorAllocator::Allocate(size_t begin, size_t end) {
|
||||
}
|
||||
|
||||
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
|
||||
std::array<VkDescriptorSetLayout, 64> stack{};
|
||||
const VkDescriptorSetLayout* p_layouts = nullptr;
|
||||
std::vector<VkDescriptorSetLayout> heap;
|
||||
if (count <= stack.size()) {
|
||||
stack.fill(layout);
|
||||
p_layouts = stack.data();
|
||||
} else {
|
||||
heap.assign(count, layout);
|
||||
p_layouts = heap.data();
|
||||
}
|
||||
const std::vector<VkDescriptorSetLayout> layouts(count, layout);
|
||||
VkDescriptorSetAllocateInfo allocate_info{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.descriptorPool = *bank->pools.back(),
|
||||
.descriptorSetCount = static_cast<u32>(count),
|
||||
.pSetLayouts = p_layouts,
|
||||
.pSetLayouts = layouts.data(),
|
||||
};
|
||||
vk::DescriptorSets new_sets = bank->pools.back().Allocate(allocate_info);
|
||||
if (!new_sets.IsOutOfPoolMemory()) {
|
||||
@@ -192,58 +146,21 @@ DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
|
||||
}
|
||||
|
||||
DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) {
|
||||
{
|
||||
std::scoped_lock lk(cache_mutex);
|
||||
DescriptorBank* best = nullptr; u64 best_stamp = 0;
|
||||
for (const auto& e : cache_) {
|
||||
if (!e.bank) continue;
|
||||
if (std::abs(e.info.score - reqs.score) < SCORE_THRESHOLD && e.info.IsSuperset(reqs)) {
|
||||
if (e.stamp >= best_stamp) { best_stamp = e.stamp; best = e.bank; }
|
||||
}
|
||||
}
|
||||
if (best) return *best;
|
||||
}
|
||||
std::shared_lock read_lock{banks_mutex};
|
||||
const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
|
||||
return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);
|
||||
});
|
||||
if (it != bank_infos.end()) {
|
||||
DescriptorBank& found = *banks[std::distance(bank_infos.begin(), it)].get();
|
||||
read_lock.unlock();
|
||||
// update cache
|
||||
std::scoped_lock lk(cache_mutex);
|
||||
size_t victim = 0; u64 oldest = UINT64_MAX;
|
||||
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
|
||||
cache_[victim] = CacheEntry{found.info, &found, ++cache_tick_};
|
||||
return found;
|
||||
return *banks[std::distance(bank_infos.begin(), it)].get();
|
||||
}
|
||||
read_lock.unlock();
|
||||
|
||||
std::unique_lock write_lock{banks_mutex};
|
||||
auto it2 = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
|
||||
return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);
|
||||
});
|
||||
if (it2 != bank_infos.end()) {
|
||||
DescriptorBank& found = *banks[std::distance(bank_infos.begin(), it2)].get();
|
||||
// update cache
|
||||
std::scoped_lock lk(cache_mutex);
|
||||
size_t victim = 0; u64 oldest = UINT64_MAX;
|
||||
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
|
||||
cache_[victim] = CacheEntry{found.info, &found, ++cache_tick_};
|
||||
return found;
|
||||
}
|
||||
bank_infos.push_back(reqs);
|
||||
|
||||
auto& bank = *banks.emplace_back(std::make_unique<DescriptorBank>());
|
||||
bank.info = reqs;
|
||||
AllocatePool(device, bank);
|
||||
// update cache
|
||||
{
|
||||
std::scoped_lock lk(cache_mutex);
|
||||
size_t victim = 0; u64 oldest = UINT64_MAX;
|
||||
for (size_t i=0;i<cache_.size();++i) if (cache_[i].stamp < oldest) { oldest = cache_[i].stamp; victim = i; }
|
||||
cache_[victim] = CacheEntry{bank.info, &bank, ++cache_tick_};
|
||||
}
|
||||
return bank;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -9,8 +6,7 @@
|
||||
#include <shared_mutex>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <mutex>
|
||||
|
||||
#include "shader_recompiler/shader_info.h"
|
||||
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
@@ -62,7 +58,6 @@ private:
|
||||
VkDescriptorSetLayout layout{};
|
||||
|
||||
std::vector<vk::DescriptorSets> sets;
|
||||
size_t grow_rate = 32;
|
||||
};
|
||||
|
||||
class DescriptorPool {
|
||||
@@ -80,14 +75,6 @@ public:
|
||||
|
||||
private:
|
||||
DescriptorBank& Bank(const DescriptorBankInfo& reqs);
|
||||
struct CacheEntry {
|
||||
DescriptorBankInfo info{};
|
||||
DescriptorBank* bank{nullptr};
|
||||
u64 stamp{0};
|
||||
};
|
||||
std::mutex cache_mutex{};
|
||||
std::array<CacheEntry, 8> cache_{}; //test and then adjust
|
||||
u64 cache_tick_{0};
|
||||
|
||||
const Device& device;
|
||||
MasterSemaphore& master_semaphore;
|
||||
|
||||
@@ -146,7 +146,7 @@ PresentManager::PresentManager(const vk::Instance& instance_,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
|
||||
});
|
||||
free_queue.push(&frame);
|
||||
free_queue.push_back(&frame);
|
||||
}
|
||||
|
||||
if (use_present_thread) {
|
||||
@@ -164,7 +164,7 @@ Frame* PresentManager::GetRenderFrame() {
|
||||
|
||||
// Take the frame from the queue
|
||||
Frame* frame = free_queue.front();
|
||||
free_queue.pop();
|
||||
free_queue.pop_front();
|
||||
|
||||
// Wait for the presentation to be finished so all frame resources are free
|
||||
frame->present_done.Wait();
|
||||
@@ -174,18 +174,17 @@ Frame* PresentManager::GetRenderFrame() {
|
||||
}
|
||||
|
||||
void PresentManager::Present(Frame* frame) {
|
||||
if (!use_present_thread) {
|
||||
if (use_present_thread) {
|
||||
scheduler.Record([this, frame](vk::CommandBuffer) {
|
||||
std::unique_lock lock{queue_mutex};
|
||||
present_queue.push_back(frame);
|
||||
frame_cv.notify_one();
|
||||
});
|
||||
} else {
|
||||
scheduler.WaitWorker();
|
||||
CopyToSwapchain(frame);
|
||||
free_queue.push(frame);
|
||||
return;
|
||||
free_queue.push_back(frame);
|
||||
}
|
||||
|
||||
scheduler.Record([this, frame](vk::CommandBuffer) {
|
||||
std::unique_lock lock{queue_mutex};
|
||||
present_queue.push(frame);
|
||||
frame_cv.notify_one();
|
||||
});
|
||||
}
|
||||
|
||||
void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
|
||||
@@ -277,29 +276,25 @@ void PresentManager::PresentThread(std::stop_token token) {
|
||||
Common::SetCurrentThreadName("VulkanPresent");
|
||||
while (!token.stop_requested()) {
|
||||
std::unique_lock lock{queue_mutex};
|
||||
|
||||
// Wait for presentation frames
|
||||
frame_cv.wait(lock, token, [this] { return !present_queue.empty(); });
|
||||
if (token.stop_requested()) {
|
||||
return;
|
||||
if (!token.stop_requested()) {
|
||||
// Take the frame and notify anyone waiting
|
||||
Frame* frame = present_queue.front();
|
||||
present_queue.pop_front();
|
||||
frame_cv.notify_one();
|
||||
|
||||
// By exchanging the lock ownership we take the swapchain lock
|
||||
// before the queue lock goes out of scope. This way the swapchain
|
||||
// lock in WaitPresent is guaranteed to occur after here.
|
||||
std::exchange(lock, std::unique_lock{swapchain_mutex});
|
||||
CopyToSwapchain(frame);
|
||||
|
||||
// Free the frame for reuse
|
||||
std::scoped_lock fl{free_mutex};
|
||||
free_queue.push_back(frame);
|
||||
free_cv.notify_one();
|
||||
}
|
||||
|
||||
// Take the frame and notify anyone waiting
|
||||
Frame* frame = present_queue.front();
|
||||
present_queue.pop();
|
||||
frame_cv.notify_one();
|
||||
|
||||
// By exchanging the lock ownership we take the swapchain lock
|
||||
// before the queue lock goes out of scope. This way the swapchain
|
||||
// lock in WaitPresent is guaranteed to occur after here.
|
||||
std::exchange(lock, std::unique_lock{swapchain_mutex});
|
||||
|
||||
CopyToSwapchain(frame);
|
||||
|
||||
// Free the frame for reuse
|
||||
std::scoped_lock fl{free_mutex};
|
||||
free_queue.push(frame);
|
||||
free_cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -5,7 +8,7 @@
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <boost/container/deque.hpp>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
@@ -88,8 +91,8 @@ private:
|
||||
#endif
|
||||
vk::CommandPool cmdpool;
|
||||
std::vector<Frame> frames;
|
||||
std::queue<Frame*> present_queue;
|
||||
std::queue<Frame*> free_queue;
|
||||
boost::container::deque<Frame*> present_queue;
|
||||
boost::container::deque<Frame*> free_queue;
|
||||
std::condition_variable_any frame_cv;
|
||||
std::condition_variable free_cv;
|
||||
std::mutex swapchain_mutex;
|
||||
|
||||
@@ -20,18 +20,12 @@
|
||||
namespace Vulkan {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld,
|
||||
std::span<const char* const> extensions) {
|
||||
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
|
||||
if (!properties) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to query extension properties");
|
||||
return false;
|
||||
}
|
||||
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld, std::vector<VkExtensionProperties> const& properties, std::span<const char* const> extensions) {
|
||||
for (const char* extension : extensions) {
|
||||
const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) {
|
||||
const auto it = std::ranges::find_if(properties, [extension](const auto& prop) {
|
||||
return std::strcmp(extension, prop.extensionName) == 0;
|
||||
});
|
||||
if (it == properties->end()) {
|
||||
if (it == properties.end()) {
|
||||
LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension);
|
||||
return false;
|
||||
}
|
||||
@@ -78,14 +72,16 @@ namespace {
|
||||
if (window_type != Core::Frontend::WindowSystemType::Headless) {
|
||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
}
|
||||
if (auto const properties = vk::EnumerateInstanceExtensionProperties(dld); properties) {
|
||||
#ifdef __APPLE__
|
||||
if (AreExtensionsSupported(dld, std::array{VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME})) {
|
||||
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
}
|
||||
if (AreExtensionsSupported(dld, *properties, std::array{VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME}))
|
||||
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
#endif
|
||||
if (enable_validation &&
|
||||
AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME})) {
|
||||
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
if (enable_validation && AreExtensionsSupported(dld, *properties, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME}))
|
||||
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
// VK_EXT_surface_maintenance1 is required for VK_EXT_swapchain_maintenance1
|
||||
if (window_type != Core::Frontend::WindowSystemType::Headless && AreExtensionsSupported(dld, *properties, std::array{VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME}))
|
||||
extensions.push_back(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME);
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
@@ -133,11 +129,10 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD
|
||||
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers");
|
||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||
}
|
||||
const std::vector<const char*> extensions =
|
||||
RequiredExtensions(dld, window_type, enable_validation);
|
||||
if (!AreExtensionsSupported(dld, extensions)) {
|
||||
std::vector<const char*> const extensions = RequiredExtensions(dld, window_type, enable_validation);
|
||||
auto const properties = vk::EnumerateInstanceExtensionProperties(dld);
|
||||
if (!properties || !AreExtensionsSupported(dld, *properties, extensions))
|
||||
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT);
|
||||
}
|
||||
std::vector<const char*> layers = Layers(enable_validation);
|
||||
RemoveUnavailableLayers(dld, layers);
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ li.checked::marker { content: "\2612"; }
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLinks">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="https://eden-emulator.github.io/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.eden-emu.dev"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/activity/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://discord.gg/HstXbPch7X"><span style=" text-decoration: underline; color:#039be5;">Discord</span></a> | <a href="https://rvlt.gg/qKgFEAbH"><span style=" text-decoration: underline; color:#039be5;">Revolt</span></a> | <a href="https://nitter.poast.org/edenemuofficial"><span style=" text-decoration: underline; color:#039be5;">Twitter</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></string>
|
||||
<string><html><head/><body><p><a href="https://eden-emulator.github.io/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.eden-emu.dev"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/activity/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://discord.gg/HstXbPch7X"><span style=" text-decoration: underline; color:#039be5;">Discord</span></a> | <a href="https://stt.gg/qKgFEAbH"><span style=" text-decoration: underline; color:#039be5;">Stoat</span></a> | <a href="https://nitter.poast.org/edenemuofficial"><span style=" text-decoration: underline; color:#039be5;">Twitter</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -1900,7 +1900,7 @@ bool MainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPar
|
||||
tr("Error while loading ROM! %1", "%1 signifies a numeric error code.")
|
||||
.arg(QString::fromStdString(error_code));
|
||||
const auto description =
|
||||
tr("%1<br>Please redump your files or ask on Discord/Revolt for help.",
|
||||
tr("%1<br>Please redump your files or ask on Discord/Stoat for help.",
|
||||
"%1 signifies an error string.")
|
||||
.arg(QString::fromStdString(
|
||||
GetResultStatusString(static_cast<Loader::ResultStatus>(error_id))));
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
# provided for workflow compat
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
chmod +x tools/cpm/fetch.sh
|
||||
find tools/ -name '*.sh' -type f -exec chmod +x {} \;
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
tools/cpm/fetch.sh $LIBS
|
||||
tools/cpmutil.sh package fetch -a
|
||||
|
||||
@@ -1,79 +1,3 @@
|
||||
# CPMUtil Tools
|
||||
# CPMUtil Tooling
|
||||
|
||||
These are supplemental shell scripts for CPMUtil aiming to ease maintenance burden for sanity checking, updates, prefetching, formatting, and standard operations done by these shell scripts, all in one common place.
|
||||
|
||||
All scripts are POSIX-compliant. If something doesn't work on your shell, ensure it's POSIX-compliant.
|
||||
* If your shell doesn't support `$(...)` syntax, you've got bigger problems to worry about.
|
||||
<!-- TOC -->
|
||||
- [Meta](#meta)
|
||||
- [Simple Utilities](#simple-utilities)
|
||||
- [Functional Utilities](#functional-utilities)
|
||||
<!-- /TOC -->
|
||||
|
||||
## Meta
|
||||
|
||||
These scripts are generally reserved for internal use.
|
||||
|
||||
- `common.sh`: Grabs all available cpmfiles and aggregates them together.
|
||||
* Outputs:
|
||||
- `PACKAGES`: The aggregated cpmfile
|
||||
- `LIBS`: The list of individual libraries contained within each cpmfile
|
||||
- `value`: A function that grabs a key from the `JSON` variable (typically the package key)
|
||||
- `download.sh`: Utility script to handle downloading of regular and CI packages.
|
||||
* Generally only used by the fetch scripts.
|
||||
- `package.sh`: The actual package parser.
|
||||
* Inputs:
|
||||
- `PACKAGE`: The package key
|
||||
* Outputs:
|
||||
- Basically everything. You're best off reading the code rather than me poorly explaining it.
|
||||
- `which.sh`: Find which cpmfile a package is located in.
|
||||
* Inputs:
|
||||
- The package key
|
||||
- `replace.sh`: Replace a package's cpmfile definition.
|
||||
* Inputs:
|
||||
- `PACKAGE`: The package key
|
||||
- `NEW_JSON`: All keys to replace/add
|
||||
* Keys not found in the new json are not touched. Keys cannot currently be deleted.
|
||||
|
||||
## Simple Utilities
|
||||
|
||||
These scripts don't really have any functionality, they just help you out a bit yknow?
|
||||
|
||||
- `format.sh`: Format all cpmfiles (4-space indent is enforced)
|
||||
* In the future, these scripts will have options for spacing
|
||||
- `hash.sh`: Determine the hash of a specific package.
|
||||
* Inputs:
|
||||
- The repository (e.g. fmtlib/fmt)
|
||||
- The sha or tag (e.g. v1.0.1)
|
||||
- `-g <GIT_HOST>` or `--host <GIT_HOST>`: What git host to use (default github.com)
|
||||
- `-a <ARTIFACT>` or `--artifact <ARTIFACT>`: The artifact to download. Set to null or empty to use a source archive instead
|
||||
* Output: the SHA512 sum of the package
|
||||
- `url-hash.sh`: Determine the hash of a URL
|
||||
* Input: the URL
|
||||
* Output: the SHA512 sum of the URL
|
||||
|
||||
## Functional Utilities
|
||||
|
||||
These modify the CPM cache or cpmfiles. Each allows you to input all the packages to act on, as well as a `<scriptname>-all.sh` that acts upon all available packages.
|
||||
|
||||
Beware: if a hash is `cf83e1357...` that means you got a 404 error!
|
||||
|
||||
- `fetch.sh`: Prefetch a package according to its cpmfile definition
|
||||
* Packages are fetched to the `.cache/cpm` directory by default, following the CPMUtil default.
|
||||
* Already-fetched packages will be skipped. You can invalidate the entire cache with `rm -rf .cache/cpm`, or invalidate a specific package with e.g. `rm -rf .cache/cpm/packagename` to force a refetch.
|
||||
* In the future, a force option will be added
|
||||
* Note that full prefetching will take a long time depending on your internet, the amount of dependencies, and the size of each dependency.
|
||||
- `check-updates.sh`: Check a package for available updates
|
||||
* This only applies to packages that utilize tags.
|
||||
* If the tag is a format string, the `git_version` is acted upon instead.
|
||||
* Specifying `-f` or `--force` will forcefully update the package and its hash, even if it's on on the latest version.
|
||||
* Alternatively, only specify `-u` or `--update` to update packages that have new versions available.
|
||||
* This script generally runs fast.
|
||||
* Packages that should skip updates (e.g. older versions, OR packages with poorly-made tag structures... looking at you mbedtls) may specify `"skip_updates": true` in their cpmfile definition. This is unnecessary for untagged (e.g. sha or bare URL) packages.
|
||||
- `check-hashes.sh`: Check a package's hash
|
||||
* Specifying `-f` or `--force` will update the package's hash even if it's not mismatched.
|
||||
* Alternatively, specify `-u` or `--update` to only fix mismatched hashes.
|
||||
* This only applies to packages with hardcoded hashes, NOT ones that use hash URLs.
|
||||
* This script will take a long time. This is operationally equivalent to a prefetch, and thus checking all hashes will take a while--but it's worth it! Just make sure you're not using dial-up.
|
||||
|
||||
You are recommended to run sanity hash checking for every pull request and commit, and weekly update checks.
|
||||
CPMUtil's tooling entirely revolves around the `cpmutil.sh` script. It contains various functions to aid with package maintenance, such as sanity checks, updates, formatting, prefetching, adding/removing packages, and much more. These are now self-documenting, so view the scripts yourself or run the cpmutil script for help.
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
tools/cpm/check-hash.sh "$@" $LIBS
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
RETURN=0
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [uf] [PACKAGE]...
|
||||
Check the hash of a specific package or packages.
|
||||
If a hash mismatch occurs, this script will print the corrected hash of the package.
|
||||
|
||||
Options:
|
||||
-u, --update Correct the package's hash if it's a mismatch
|
||||
|
||||
-f, --force Update the package's hash anyways (implies -u)
|
||||
|
||||
Note that this procedure will usually take a long time
|
||||
depending on the number and size of dependencies.
|
||||
|
||||
This project has defined the following as valid cpmfiles:
|
||||
EOF
|
||||
|
||||
for file in $CPMFILES; do
|
||||
echo "- $file"
|
||||
done
|
||||
|
||||
exit $RETURN
|
||||
}
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
(-uf|-f|--force) UPDATE=true; FORCE=true; shift; continue ;;
|
||||
(-u|--update) UPDATE=true; shift; continue ;;
|
||||
(-h) usage ;;
|
||||
("$0") break ;;
|
||||
("") break ;;
|
||||
esac
|
||||
|
||||
PACKAGE="$1"
|
||||
|
||||
shift
|
||||
|
||||
export PACKAGE
|
||||
. tools/cpm/package.sh
|
||||
|
||||
if [ "$CI" != null ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
[ "$HASH_URL" != null ] && continue
|
||||
[ "$HASH_SUFFIX" != null ] && continue
|
||||
|
||||
echo "-- Package $PACKAGE"
|
||||
|
||||
[ "$HASH" = null ] && echo "-- * Warning: no hash specified" && continue
|
||||
|
||||
export USE_TAG=true
|
||||
ACTUAL=$(tools/cpm/url-hash.sh "$DOWNLOAD")
|
||||
|
||||
if [ "$ACTUAL" != "$HASH" ]; then
|
||||
echo "-- * Expected $HASH"
|
||||
echo "-- * Got $ACTUAL"
|
||||
[ "$UPDATE" != "true" ] && RETURN=1
|
||||
fi
|
||||
|
||||
if { [ "$UPDATE" = "true" ] && [ "$ACTUAL" != "$HASH" ]; } || [ "$FORCE" = "true" ]; then
|
||||
NEW_JSON=$(echo "$JSON" | jq ".hash = \"$ACTUAL\"")
|
||||
export NEW_JSON
|
||||
|
||||
tools/cpm/replace.sh
|
||||
fi
|
||||
done
|
||||
|
||||
exit $RETURN
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
tools/cpm/check-updates.sh "$@" $LIBS
|
||||
@@ -1,22 +1,24 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
##################################
|
||||
# CHANGE THESE FOR YOUR PROJECT! #
|
||||
##################################
|
||||
|
||||
# TODO: cache cpmfile defs
|
||||
|
||||
# How many levels to go (3 is 2 subdirs max)
|
||||
MAXDEPTH=3
|
||||
|
||||
# For your project you'll want to change this to define what dirs you have cpmfiles in
|
||||
# Remember to account for the MAXDEPTH variable!
|
||||
# Adding ./ before each will help to remove duplicates
|
||||
[ -z "$CPMFILES" ] && CPMFILES=$(find . ./src -maxdepth "$MAXDEPTH" -name cpmfile.json | sort | uniq)
|
||||
CPMFILES=$(find . -maxdepth "$MAXDEPTH" -name cpmfile.json | sort | uniq)
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
[ -z "$PACKAGES" ] && PACKAGES=$(echo "$CPMFILES" | xargs jq -s 'reduce .[] as $item ({}; . * $item)')
|
||||
PACKAGES=$(echo "$CPMFILES" | xargs jq -s 'reduce .[] as $item ({}; . * $item)')
|
||||
|
||||
LIBS=$(echo "$PACKAGES" | jq -j 'keys_unsorted | join(" ")')
|
||||
|
||||
@@ -25,7 +27,3 @@ export CPMFILES
|
||||
export LIBS
|
||||
export DIRS
|
||||
export MAXDEPTH
|
||||
|
||||
value() {
|
||||
echo "$JSON" | jq -r ".$1"
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
download_package() {
|
||||
FILENAME=$(basename "$DOWNLOAD")
|
||||
|
||||
OUTFILE="$TMP/$FILENAME"
|
||||
|
||||
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
|
||||
[ -d "$OUTDIR" ] && return
|
||||
|
||||
curl "$DOWNLOAD" -sS -L -o "$OUTFILE"
|
||||
|
||||
ACTUAL_HASH=$("${HASH_ALGO}"sum "$OUTFILE" | cut -d" " -f1)
|
||||
[ "$ACTUAL_HASH" != "$HASH" ] && echo "!! $FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" && exit 1
|
||||
|
||||
TMPDIR="$TMP/extracted"
|
||||
mkdir -p "$OUTDIR"
|
||||
mkdir -p "$TMPDIR"
|
||||
|
||||
PREVDIR="$PWD"
|
||||
mkdir -p "$TMPDIR"
|
||||
cd "$TMPDIR"
|
||||
|
||||
case "$FILENAME" in
|
||||
(*.7z)
|
||||
7z x "$OUTFILE" > /dev/null
|
||||
;;
|
||||
(*.tar*)
|
||||
tar xf "$OUTFILE" > /dev/null
|
||||
;;
|
||||
(*.zip)
|
||||
unzip "$OUTFILE" > /dev/null
|
||||
;;
|
||||
esac
|
||||
|
||||
# basically if only one real item exists at the top we just move everything from there
|
||||
# since github and some vendors hate me
|
||||
DIRS=$(find . -maxdepth 1 -type d -o -type f)
|
||||
|
||||
# thanks gnu
|
||||
if [ "$(echo "$DIRS" | wc -l)" -eq 2 ]; then
|
||||
SUBDIR=$(find . -maxdepth 1 -type d -not -name ".")
|
||||
mv "$SUBDIR"/* "$OUTDIR"
|
||||
mv "$SUBDIR"/.* "$OUTDIR" 2>/dev/null || true
|
||||
rmdir "$SUBDIR"
|
||||
else
|
||||
mv ./* "$OUTDIR"
|
||||
mv ./.* "$OUTDIR" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
cd "$OUTDIR"
|
||||
|
||||
if echo "$JSON" | grep -e "patches" > /dev/null; then
|
||||
PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")')
|
||||
for patch in $PATCHES; do
|
||||
# shellcheck disable=SC2154
|
||||
patch --binary -p1 < "$ROOTDIR/.patch/$PACKAGE/$patch"
|
||||
done
|
||||
fi
|
||||
|
||||
cd "$PREVDIR"
|
||||
}
|
||||
|
||||
ci_package() {
|
||||
[ "$REPO" = null ] && echo "-- ! No repo defined" && return
|
||||
|
||||
echo "-- CI package $PACKAGE_NAME"
|
||||
|
||||
for platform in windows-amd64 windows-arm64 \
|
||||
mingw-amd64 mingw-arm64 \
|
||||
android-aarch64 android-x86_64 \
|
||||
solaris-amd64 freebsd-amd64 openbsd-amd64 \
|
||||
linux-amd64 linux-aarch64 \
|
||||
macos-universal; do
|
||||
echo "-- * platform $platform"
|
||||
|
||||
case $DISABLED in
|
||||
(*"$platform"*)
|
||||
echo "-- * -- disabled"
|
||||
continue
|
||||
;;
|
||||
(*) ;;
|
||||
esac
|
||||
|
||||
FILENAME="${NAME}-${platform}-${VERSION}.${EXT}"
|
||||
DOWNLOAD="https://$GIT_HOST/${REPO}/releases/download/v${VERSION}/${FILENAME}"
|
||||
KEY=$platform
|
||||
|
||||
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
|
||||
[ -d "$OUTDIR" ] && continue
|
||||
|
||||
HASH_ALGO=$(value "hash_algo")
|
||||
[ "$HASH_ALGO" = null ] && HASH_ALGO=sha512
|
||||
|
||||
HASH_SUFFIX="${HASH_ALGO}sum"
|
||||
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
|
||||
|
||||
HASH=$(curl "$HASH_URL" -sS -q -L -o -)
|
||||
|
||||
download_package
|
||||
done
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
tools/cpm/fetch.sh "$@" $LIBS
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
[ -z "$CPM_SOURCE_CACHE" ] && CPM_SOURCE_CACHE=$PWD/.cache/cpm
|
||||
|
||||
mkdir -p "$CPM_SOURCE_CACHE"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/download.sh
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
ROOTDIR="$PWD"
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [PACKAGE]...
|
||||
Fetch the specified package or packages from their defined download locations.
|
||||
If the package is already cached, it will not be re-fetched.
|
||||
|
||||
This project has defined the following as valid cpmfiles:
|
||||
EOF
|
||||
|
||||
for file in $CPMFILES; do
|
||||
echo "- $file"
|
||||
done
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
(-h) usage ;;
|
||||
("$0") break ;;
|
||||
("") break ;;
|
||||
esac
|
||||
|
||||
PACKAGE="$1"
|
||||
|
||||
shift
|
||||
|
||||
export PACKAGE
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/package.sh
|
||||
|
||||
if [ "$CI" = "true" ]; then
|
||||
ci_package
|
||||
else
|
||||
echo "-- Downloading regular package $PACKAGE, with key $KEY, from $DOWNLOAD"
|
||||
download_package
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf "$TMP"
|
||||
@@ -1,12 +1,9 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
for file in $CPMFILES; do
|
||||
jq --indent 4 < "$file" > "$file".new
|
||||
mv "$file".new "$file"
|
||||
jq --indent 4 <"$file" >"$file".new
|
||||
mv "$file".new "$file"
|
||||
done
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# usage: hash.sh repo tag-or-sha
|
||||
# env vars: GIT_HOST, USE_TAG (use tag instead of sha), ARTIFACT (download artifact with that name instead of src archive)
|
||||
|
||||
RETURN=0
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [-a|--artifact ARTIFACT] [-g|--host GIT_HOST] [REPO] [REF]
|
||||
Get the hash of a package.
|
||||
|
||||
REPO must be in the form of OWNER/REPO, and REF must be a commit sha, branch, or tag.
|
||||
|
||||
Options:
|
||||
-g, --host <GIT_HOST> What Git host to use (defaults to github.com)
|
||||
|
||||
-a, --artifact <ARTIFACT> The artifact to download (implies -t)
|
||||
If -t is specified but not -a, fetches a tag archive.
|
||||
If ARTIFACT is specified but is null,
|
||||
|
||||
EOF
|
||||
exit "$RETURN"
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "$@" >&2
|
||||
RETURN=1 usage
|
||||
}
|
||||
|
||||
artifact() {
|
||||
if [ $# -lt 2 ]; then
|
||||
die "You must specify a valid artifact."
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
ARTIFACT="$1"
|
||||
}
|
||||
|
||||
host() {
|
||||
if [ $# -lt 2 ]; then
|
||||
die "You must specify a valid Git host."
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
GIT_HOST="$1"
|
||||
}
|
||||
|
||||
# this is a semi-hacky way to handle long/shortforms
|
||||
while true; do
|
||||
case "$1" in
|
||||
-[a-z]*)
|
||||
opt=$(echo "$1" | sed 's/^-//')
|
||||
while [ -n "$opt" ]; do
|
||||
# cut out first char from the optstring
|
||||
char=$(echo "$opt" | cut -c1)
|
||||
opt=$(echo "$opt" | cut -c2-)
|
||||
|
||||
case "$char" in
|
||||
a) artifact "$@" ;;
|
||||
g) host "$@" ;;
|
||||
h) usage ;;
|
||||
*) die "Invalid option -$char" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
;;
|
||||
--artifact) artifact "$@" ;;
|
||||
--host) host "$@" ;;
|
||||
--help) usage ;;
|
||||
--*) die "Invalid option $1" ;;
|
||||
"$0" | "") break ;;
|
||||
*)
|
||||
{ [ -z "$REPO" ] && REPO="$1"; } || REF="$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
[ -z "$REPO" ] && die "A valid repository must be provided."
|
||||
[ -z "$REF" ] && die "A valid reference must be provided."
|
||||
|
||||
GIT_HOST=${GIT_HOST:-github.com}
|
||||
GIT_URL="https://$GIT_HOST/$REPO"
|
||||
|
||||
if [ -z "$ARTIFACT" ] || [ "$ARTIFACT" = "null" ]; then
|
||||
URL="${GIT_URL}/archive/$REF.tar.gz"
|
||||
else
|
||||
URL="${GIT_URL}/releases/download/$REF/$ARTIFACT"
|
||||
fi
|
||||
|
||||
SUM=$(wget -q "$URL" -O - | sha512sum)
|
||||
echo "$SUM" | cut -d " " -f1
|
||||
47
tools/cpm/migrate.sh
Executable file
47
tools/cpm/migrate.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
SUBMODULES="$(git submodule status --recursive | cut -c2-)"
|
||||
|
||||
[ -z "$SUBMODULES" ] && echo "No submodules defined!" && exit 0
|
||||
|
||||
tmp=$(mktemp)
|
||||
printf '{}' >"$tmp"
|
||||
|
||||
IFS="
|
||||
"
|
||||
for i in $SUBMODULES; do
|
||||
sha=$(echo "$i" | cut -d" " -f1 | cut -c1-10)
|
||||
ver=$(echo "$i" | cut -d" " -f3 | tr -d '()')
|
||||
|
||||
path=$(echo "$i" | cut -d" " -f2)
|
||||
name=$(echo "$path" | awk -F/ '{print $NF}')
|
||||
|
||||
remote=$(git -C "$path" remote get-url origin)
|
||||
|
||||
host=$(echo "$remote" | cut -d"/" -f3)
|
||||
[ "$host" = github.com ] && host=
|
||||
|
||||
repo=$(echo "$remote" | cut -d"/" -f4-5 | cut -d'.' -f1)
|
||||
|
||||
entry=$(jq -n --arg name "$name" \
|
||||
--arg sha "$sha" \
|
||||
--arg ver "$ver" \
|
||||
--arg repo "$repo" \
|
||||
--arg host "$host" \
|
||||
'{
|
||||
($name): {
|
||||
sha: $sha,
|
||||
git_version: $ver,
|
||||
repo: $repo
|
||||
} + (if $host != "" then {git_host: $host} else {} end)
|
||||
}')
|
||||
|
||||
jq --argjson new "$entry" '. + $new' "$tmp" >"${tmp}.new"
|
||||
mv "$tmp.new" "$tmp"
|
||||
done
|
||||
|
||||
jq '.' "$tmp" >cpmfile.json
|
||||
rm -f "$tmp"
|
||||
@@ -1,200 +1,80 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 crueter
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. tools/cpm/common.sh
|
||||
RETURN=0
|
||||
|
||||
[ -z "$PACKAGE" ] && echo "Package was not specified" && exit 0
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: cpmutil.sh package [command]
|
||||
|
||||
# shellcheck disable=SC2153
|
||||
JSON=$(echo "$PACKAGES" | jq -r ".\"$PACKAGE\" | select( . != null )")
|
||||
Operate on a package or packages.
|
||||
|
||||
[ -z "$JSON" ] && echo "!! No cpmfile definition for $PACKAGE" >&2 && exit 1
|
||||
Commands:
|
||||
hash Verify the hash of a package, and update it if needed
|
||||
update Check for updates for a package
|
||||
fetch Fetch a package and place it in the cache
|
||||
add Add a new package
|
||||
rm Remove a package
|
||||
version Change the version of a package
|
||||
which Find which cpmfile a package is defined in
|
||||
download Get the download URL for a package
|
||||
|
||||
# unset stuff
|
||||
export PACKAGE_NAME="null"
|
||||
export REPO="null"
|
||||
export CI="null"
|
||||
export GIT_HOST="null"
|
||||
export EXT="null"
|
||||
export NAME="null"
|
||||
export DISABLED="null"
|
||||
export TAG="null"
|
||||
export ARTIFACT="null"
|
||||
export SHA="null"
|
||||
export VERSION="null"
|
||||
export GIT_VERSION="null"
|
||||
export DOWNLOAD="null"
|
||||
export URL="null"
|
||||
export KEY="null"
|
||||
export HASH="null"
|
||||
export ORIGINAL_TAG="null"
|
||||
export HAS_REPLACE="null"
|
||||
export VERSION_REPLACE="null"
|
||||
export HASH_URL="null"
|
||||
export HASH_SUFFIX="null"
|
||||
export HASH_ALGO="null"
|
||||
EOF
|
||||
|
||||
########
|
||||
# Meta #
|
||||
########
|
||||
exit $RETURN
|
||||
}
|
||||
|
||||
REPO=$(value "repo")
|
||||
CI=$(value "ci")
|
||||
SCRIPTS=$(CDPATH='' cd -- "$(dirname -- "$0")/package" && pwd)
|
||||
export SCRIPTS
|
||||
|
||||
PACKAGE_NAME=$(value "package")
|
||||
[ "$PACKAGE_NAME" = null ] && PACKAGE_NAME="$PACKAGE"
|
||||
while :; do
|
||||
case "$1" in
|
||||
hash)
|
||||
shift
|
||||
"$SCRIPTS"/hash.sh "$@"
|
||||
break
|
||||
;;
|
||||
update)
|
||||
shift
|
||||
"$SCRIPTS"/update.sh "$@"
|
||||
break
|
||||
;;
|
||||
fetch)
|
||||
shift
|
||||
"$SCRIPTS"/fetch.sh "$@"
|
||||
break
|
||||
;;
|
||||
add)
|
||||
shift
|
||||
"$SCRIPTS"/add.sh "$@"
|
||||
break
|
||||
;;
|
||||
rm)
|
||||
shift
|
||||
"$SCRIPTS"/rm.sh "$@"
|
||||
break
|
||||
;;
|
||||
version)
|
||||
shift
|
||||
"$SCRIPTS"/version.sh "$@"
|
||||
break
|
||||
;;
|
||||
which)
|
||||
shift
|
||||
"$SCRIPTS"/which.sh "$@"
|
||||
break
|
||||
;;
|
||||
download)
|
||||
shift
|
||||
"$SCRIPTS"/download.sh "$@"
|
||||
break
|
||||
;;
|
||||
-h | --help) usage ;;
|
||||
"") usage ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
GIT_HOST=$(value "git_host")
|
||||
[ "$GIT_HOST" = null ] && GIT_HOST=github.com
|
||||
|
||||
export PACKAGE_NAME
|
||||
export REPO
|
||||
export CI
|
||||
export GIT_HOST
|
||||
|
||||
######################
|
||||
# CI Package Parsing #
|
||||
######################
|
||||
|
||||
VERSION=$(value "version")
|
||||
|
||||
if [ "$CI" = "true" ]; then
|
||||
EXT=$(value "extension")
|
||||
[ "$EXT" = null ] && EXT="tar.zst"
|
||||
|
||||
NAME=$(value "name")
|
||||
DISABLED=$(echo "$JSON" | jq -j '.disabled_platforms')
|
||||
|
||||
[ "$NAME" = null ] && NAME="$PACKAGE_NAME"
|
||||
|
||||
export EXT
|
||||
export NAME
|
||||
export DISABLED
|
||||
export VERSION
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
##############
|
||||
# Versioning #
|
||||
##############
|
||||
|
||||
TAG=$(value "tag")
|
||||
ARTIFACT=$(value "artifact")
|
||||
SHA=$(value "sha")
|
||||
GIT_VERSION=$(value "git_version")
|
||||
|
||||
[ "$GIT_VERSION" = null ] && GIT_VERSION="$VERSION"
|
||||
|
||||
if [ "$GIT_VERSION" != null ]; then
|
||||
VERSION_REPLACE="$GIT_VERSION"
|
||||
else
|
||||
VERSION_REPLACE="$VERSION"
|
||||
fi
|
||||
|
||||
echo "$TAG" | grep -e "%VERSION%" > /dev/null && HAS_REPLACE=true || HAS_REPLACE=false
|
||||
ORIGINAL_TAG="$TAG"
|
||||
|
||||
TAG=$(echo "$TAG" | sed "s/%VERSION%/$VERSION_REPLACE/g")
|
||||
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%VERSION%/$VERSION_REPLACE/g")
|
||||
ARTIFACT=$(echo "$ARTIFACT" | sed "s/%TAG%/$TAG/g")
|
||||
|
||||
export TAG
|
||||
export ARTIFACT
|
||||
export SHA
|
||||
export VERSION
|
||||
export GIT_VERSION
|
||||
export ORIGINAL_TAG
|
||||
export HAS_REPLACE
|
||||
export VERSION_REPLACE
|
||||
|
||||
###############
|
||||
# URL Parsing #
|
||||
###############
|
||||
|
||||
URL=$(value "url")
|
||||
|
||||
if [ "$URL" != "null" ]; then
|
||||
DOWNLOAD="$URL"
|
||||
elif [ "$REPO" != "null" ]; then
|
||||
GIT_URL="https://$GIT_HOST/$REPO"
|
||||
|
||||
BRANCH=$(value "branch")
|
||||
|
||||
if [ "$TAG" != "null" ]; then
|
||||
if [ "$ARTIFACT" != "null" ]; then
|
||||
DOWNLOAD="${GIT_URL}/releases/download/${TAG}/${ARTIFACT}"
|
||||
else
|
||||
DOWNLOAD="${GIT_URL}/archive/refs/tags/${TAG}.tar.gz"
|
||||
fi
|
||||
elif [ "$SHA" != "null" ]; then
|
||||
DOWNLOAD="${GIT_URL}/archive/${SHA}.tar.gz"
|
||||
else
|
||||
if [ "$BRANCH" = null ]; then
|
||||
BRANCH=master
|
||||
fi
|
||||
|
||||
DOWNLOAD="${GIT_URL}/archive/refs/heads/${BRANCH}.tar.gz"
|
||||
fi
|
||||
else
|
||||
echo "!! No repo or URL defined for $PACKAGE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DOWNLOAD
|
||||
export URL
|
||||
|
||||
###############
|
||||
# Key Parsing #
|
||||
###############
|
||||
|
||||
KEY=$(value "key")
|
||||
|
||||
if [ "$KEY" = null ]; then
|
||||
if [ "$SHA" != null ]; then
|
||||
KEY=$(echo "$SHA" | cut -c1-4)
|
||||
elif [ "$GIT_VERSION" != null ]; then
|
||||
KEY="$GIT_VERSION"
|
||||
elif [ "$TAG" != null ]; then
|
||||
KEY="$TAG"
|
||||
elif [ "$VERSION" != null ]; then
|
||||
KEY="$VERSION"
|
||||
else
|
||||
echo "!! No valid key could be determined for $PACKAGE. Must define one of: key, sha, tag, version, git_version"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
export KEY
|
||||
|
||||
################
|
||||
# Hash Parsing #
|
||||
################
|
||||
|
||||
HASH_ALGO=$(value "hash_algo")
|
||||
[ "$HASH_ALGO" = null ] && HASH_ALGO=sha512
|
||||
|
||||
HASH=$(value "hash")
|
||||
|
||||
if [ "$HASH" = null ]; then
|
||||
HASH_SUFFIX="${HASH_ALGO}sum"
|
||||
HASH_URL=$(value "hash_url")
|
||||
|
||||
if [ "$HASH_URL" = null ]; then
|
||||
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
|
||||
fi
|
||||
|
||||
HASH=$(curl "$HASH_URL" -Ss -L -o -)
|
||||
else
|
||||
HASH_URL=null
|
||||
HASH_SUFFIX=null
|
||||
fi
|
||||
|
||||
export HASH_URL
|
||||
export HASH_SUFFIX
|
||||
export HASH
|
||||
export HASH_ALGO
|
||||
export JSON
|
||||
shift
|
||||
done
|
||||
|
||||
79
tools/cpm/package/add.sh
Executable file
79
tools/cpm/package/add.sh
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
RETURN=0
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: cpmutil.sh package add [-s|--sha] [-t|--tag]
|
||||
[-c|--cpmfile CPMFILE] [package name]
|
||||
|
||||
Add a new package to a cpmfile.
|
||||
|
||||
Options:
|
||||
-t, --tag Use tag versioning, instead of the default,
|
||||
commit sha versioning.
|
||||
-c, --cpmfile <CPMFILE> Use the specified cpmfile instead of the root cpmfile
|
||||
|
||||
Note that you are still responsible for integrating this into your CMake.
|
||||
|
||||
EOF
|
||||
|
||||
exit $RETURN
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "-- $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
_cpmfile() {
|
||||
[ -z "$1" ] && die "You must specify a valid cpmfile."
|
||||
CPMFILE="$1"
|
||||
}
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-[a-z]*)
|
||||
opt=$(printf '%s' "$1" | sed 's/^-//')
|
||||
while [ -n "$opt" ]; do
|
||||
# cut out first char from the optstring
|
||||
char=$(echo "$opt" | cut -c1)
|
||||
opt=$(echo "$opt" | cut -c2-)
|
||||
|
||||
case "$char" in
|
||||
t) TAG=1 ;;
|
||||
c)
|
||||
_cpmfile "$2"
|
||||
shift
|
||||
;;
|
||||
h) usage ;;
|
||||
*) die "Invalid option -$char" ;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
--tag) TAG=1 ;;
|
||||
--cpmfile)
|
||||
_cpmfile "$2"
|
||||
shift
|
||||
;;
|
||||
--help) usage ;;
|
||||
"$0") break ;;
|
||||
"") break ;;
|
||||
*) PKG="$1" ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
: "${CPMFILE:=$PWD/cpmfile.json}"
|
||||
|
||||
[ -z "$PKG" ] && die "You must specify a package name."
|
||||
|
||||
export PKG
|
||||
export CPMFILE
|
||||
export TAG
|
||||
|
||||
"$SCRIPTS"/util/interactive.sh
|
||||
46
tools/cpm/package/download.sh
Executable file
46
tools/cpm/package/download.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: cpmutil.sh package download [-a|--all] [PACKAGE]...
|
||||
|
||||
Get the download URL for the specified packages.
|
||||
|
||||
Options:
|
||||
-a, --all Operate on all packages in this project.
|
||||
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-a | --all) ALL=1 ;;
|
||||
-h | --help) usage ;;
|
||||
"$0") break ;;
|
||||
"") break ;;
|
||||
*) packages="$packages $1" ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
[ "$ALL" = 1 ] && packages="${LIBS:-$packages}"
|
||||
[ -z "$packages" ] && usage
|
||||
|
||||
for pkg in $packages; do
|
||||
PACKAGE="$pkg"
|
||||
export PACKAGE
|
||||
# shellcheck disable=SC1091
|
||||
. "$SCRIPTS"/vars.sh
|
||||
|
||||
if [ "$CI" = "true" ]; then
|
||||
echo "-- $PACKAGE: https://$GIT_HOST/$REPO"
|
||||
else
|
||||
echo -- "$PACKAGE: $DOWNLOAD"
|
||||
fi
|
||||
done
|
||||
156
tools/cpm/package/fetch.sh
Executable file
156
tools/cpm/package/fetch.sh
Executable file
@@ -0,0 +1,156 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
: "${CPM_SOURCE_CACHE:=$PWD/.cache/cpm}"
|
||||
|
||||
mkdir -p "$CPM_SOURCE_CACHE"
|
||||
|
||||
ROOTDIR="$PWD"
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
|
||||
download_package() {
|
||||
FILENAME=$(basename "$DOWNLOAD")
|
||||
|
||||
OUTFILE="$TMP/$FILENAME"
|
||||
|
||||
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
|
||||
[ -d "$OUTDIR" ] && return
|
||||
|
||||
curl "$DOWNLOAD" -sS -L -o "$OUTFILE"
|
||||
|
||||
ACTUAL_HASH=$("${HASH_ALGO}"sum "$OUTFILE" | cut -d" " -f1)
|
||||
[ "$ACTUAL_HASH" != "$HASH" ] && echo "!! $FILENAME did not match expected hash; expected $HASH but got $ACTUAL_HASH" && exit 1
|
||||
|
||||
TMPDIR="$TMP/extracted"
|
||||
mkdir -p "$OUTDIR"
|
||||
mkdir -p "$TMPDIR"
|
||||
|
||||
PREVDIR="$PWD"
|
||||
mkdir -p "$TMPDIR"
|
||||
cd "$TMPDIR"
|
||||
|
||||
case "$FILENAME" in
|
||||
*.7z)
|
||||
7z x "$OUTFILE" >/dev/null
|
||||
;;
|
||||
*.tar*)
|
||||
tar xf "$OUTFILE" >/dev/null
|
||||
;;
|
||||
*.zip)
|
||||
unzip "$OUTFILE" >/dev/null
|
||||
;;
|
||||
esac
|
||||
|
||||
# basically if only one real item exists at the top we just move everything from there
|
||||
# since github and some vendors hate me
|
||||
DIRS=$(find . -maxdepth 1 -type d -o -type f)
|
||||
|
||||
# thanks gnu
|
||||
if [ "$(echo "$DIRS" | wc -l)" -eq 2 ]; then
|
||||
SUBDIR=$(find . -maxdepth 1 -type d -not -name ".")
|
||||
mv "$SUBDIR"/* "$OUTDIR"
|
||||
mv "$SUBDIR"/.* "$OUTDIR" 2>/dev/null || true
|
||||
rmdir "$SUBDIR"
|
||||
else
|
||||
mv ./* "$OUTDIR"
|
||||
mv ./.* "$OUTDIR" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
cd "$OUTDIR"
|
||||
|
||||
if echo "$JSON" | grep -e "patches" >/dev/null; then
|
||||
PATCHES=$(echo "$JSON" | jq -r '.patches | join(" ")')
|
||||
for patch in $PATCHES; do
|
||||
patch --binary -p1 <"$ROOTDIR/.patch/$PACKAGE/$patch"
|
||||
done
|
||||
fi
|
||||
|
||||
cd "$PREVDIR"
|
||||
}
|
||||
|
||||
ci_package() {
|
||||
[ "$REPO" = null ] && echo "-- ! No repo defined" && return
|
||||
|
||||
echo "-- CI package $PACKAGE_NAME"
|
||||
|
||||
for platform in windows-amd64 windows-arm64 \
|
||||
mingw-amd64 mingw-arm64 \
|
||||
android-aarch64 android-x86_64 \
|
||||
solaris-amd64 freebsd-amd64 openbsd-amd64 \
|
||||
linux-amd64 linux-aarch64 \
|
||||
macos-universal; do
|
||||
echo "-- * platform $platform"
|
||||
|
||||
case $DISABLED in
|
||||
*"$platform"*)
|
||||
echo "-- * -- disabled"
|
||||
continue
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
FILENAME="${NAME}-${platform}-${VERSION}.${EXT}"
|
||||
DOWNLOAD="https://$GIT_HOST/${REPO}/releases/download/v${VERSION}/${FILENAME}"
|
||||
KEY="$platform-$VERSION"
|
||||
|
||||
LOWER_PACKAGE=$(echo "$PACKAGE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
OUTDIR="${CPM_SOURCE_CACHE}/${LOWER_PACKAGE}/${KEY}"
|
||||
[ -d "$OUTDIR" ] && continue
|
||||
|
||||
HASH_ALGO=$(echo "$JSON" | jq -r ".hash_algo")
|
||||
[ "$HASH_ALGO" = null ] && HASH_ALGO=sha512
|
||||
|
||||
HASH_SUFFIX="${HASH_ALGO}sum"
|
||||
HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}"
|
||||
|
||||
HASH=$(curl "$HASH_URL" -sS -q -L -o -)
|
||||
|
||||
download_package
|
||||
done
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: cpmutil.sh package fetch [a|--all] [PACKAGE]...
|
||||
|
||||
Fetch the specified package or packages from their defined download locations.
|
||||
If the package is already cached, it will not be re-fetched.
|
||||
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-h | --help) usage ;;
|
||||
-a | --all) ALL=1 ;;
|
||||
"$0") break ;;
|
||||
"") break ;;
|
||||
*) packages="$packages $1" ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
[ "$ALL" = 1 ] && packages="${LIBS:-$packages}"
|
||||
[ -z "$packages" ] && usage
|
||||
|
||||
for PACKAGE in $packages; do
|
||||
export PACKAGE
|
||||
# shellcheck disable=SC1091
|
||||
. "$SCRIPTS"/vars.sh
|
||||
|
||||
if [ "$CI" = "true" ]; then
|
||||
ci_package
|
||||
else
|
||||
echo "-- Downloading regular package $PACKAGE, with key $KEY, from $DOWNLOAD"
|
||||
download_package
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf "$TMP"
|
||||
66
tools/cpm/package/hash.sh
Executable file
66
tools/cpm/package/hash.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright 2025 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
RETURN=0
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: cpmutil.sh package hash [-n|--dry-run] [-a|--all] [PACKAGE]...
|
||||
|
||||
Check the hash of a specific package or packages.
|
||||
If a hash mismatch occurs, this script will update the package's hash.
|
||||
|
||||
Options:
|
||||
-n, --dry-run Don't update the package's hash if it's a mismatch
|
||||
-a, --all Operate on all packages in this project.
|
||||
|
||||
Note that this procedure will usually take a long time
|
||||
depending on the number and size of dependencies.
|
||||
|
||||
EOF
|
||||
|
||||
exit $RETURN
|
||||
}
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-[a-z]*)
|
||||
opt=$(printf '%s' "$1" | sed 's/^-//')
|
||||
while [ -n "$opt" ]; do
|
||||
# cut out first char from the optstring
|
||||
char=$(echo "$opt" | cut -c1)
|
||||
opt=$(echo "$opt" | cut -c2-)
|
||||
|
||||
case "$char" in
|
||||
a) ALL=1 ;;
|
||||
n) DRY=1 ;;
|
||||
h) usage ;;
|
||||
*) die "Invalid option -$char" ;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
--dry-run) DRY=1 ;;
|
||||
--all) ALL=1 ;;
|
||||
--help) usage ;;
|
||||
"$0") break ;;
|
||||
"") break ;;
|
||||
*) packages="$packages $1" ;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
[ "$ALL" = 1 ] && packages="${LIBS:-$packages}"
|
||||
[ "$DRY" = 1 ] && UPDATE=false || UPDATE=true
|
||||
[ -z "$packages" ] && usage
|
||||
|
||||
export UPDATE
|
||||
|
||||
for pkg in $packages; do
|
||||
echo "-- Package $pkg"
|
||||
"$SCRIPTS"/util/fix-hash.sh "$pkg" || RETURN=1
|
||||
done
|
||||
|
||||
exit $RETURN
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user