Compare commits

..

31 Commits

Author SHA1 Message Date
isyvdshvsy
8212828221 Update verify.yml 2023-12-01 01:51:52 +08:00
isyvdshvsy
ec73ccd582 Add files via upload 2023-11-30 22:24:51 +08:00
isyvdshvsy
11115d36e2 Update MainActivity.kt 2023-11-30 22:13:10 +08:00
isyvdshvsy
f1dd8f59a1 Merge pull request #3 from isyvdshvsy/isyvdshvsy-patch-4
Update MainActivity.kt
2023-11-30 21:42:09 +08:00
isyvdshvsy
66a6014855 Update MainActivity.kt 2023-11-30 21:41:41 +08:00
isyvdshvsy
573061ed5a Merge pull request #2 from isyvdshvsy/isyvdshvsy-patch-3
Update MainActivity.kt
2023-11-30 21:02:47 +08:00
isyvdshvsy
432afa1a52 Update MainActivity.kt 2023-11-30 21:02:25 +08:00
yuzubot
96836e2710 Android #146 2023-11-30 00:57:34 +00:00
yuzubot
9e6bd15bc9 Merge PR 12074 2023-11-30 00:57:33 +00:00
Narr the Reg
9dc9aaf4af Merge pull request #12223 from liamwhite/fruit-company
general: conditionally compile gamemode on linux only
2023-11-29 14:28:37 -06:00
Liam
5eec980a2d general: conditionally compile gamemode on linux only 2023-11-29 14:26:11 -05:00
liamwhite
aded28f276 Merge pull request #12204 from t895/config-migration
android: Multi directory UI
2023-11-29 12:34:09 -05:00
liamwhite
80c4743754 Merge pull request #12203 from liamwhite/crash-fix
set: don't load version nca with null romfs
2023-11-29 12:34:02 -05:00
liamwhite
498159d719 Merge pull request #12201 from Macj0rdan/controller-applet-fix
Fixed controller applet crashing when on FW17+
2023-11-29 12:33:50 -05:00
liamwhite
91ad6b7098 Merge pull request #12194 from liamwhite/fruit-company
video_core: fix mac compile
2023-11-29 12:33:41 -05:00
liamwhite
df49795bcb Merge pull request #12154 from liamwhite/more-drivers
vulkan_device: add names for more driverID enumeration values
2023-11-29 12:33:34 -05:00
liamwhite
337e37f91d Merge pull request #11946 from flodavid/gamemode
Enable (Feral Interactive) Gamemode on Linux
2023-11-29 12:33:09 -05:00
liamwhite
992ca8c358 Merge pull request #11902 from ameerj/ssbo-align
shader_recompiler: Align SSBO offsets to meet host requirements
2023-11-29 12:32:52 -05:00
t895
7dddf5cb3c android: Save global settings in onStop 2023-11-27 23:46:30 -05:00
t895
b8f66c9412 android: Multi directory UI 2023-11-27 23:46:29 -05:00
Liam
fd29227bc4 set: don't load version nca with null romfs 2023-11-27 15:20:18 -05:00
FrozenAra
e21f96ffde Fixed controller applet crashing when on FW17+ 2023-11-27 20:01:30 +01:00
Ameer J
1d11fe00a3 Merge branch 'master' into ssbo-align 2023-11-26 21:08:53 -05:00
Liam
7c1cb5e8c9 video_core: fix mac compile 2023-11-26 20:04:06 -05:00
flodavid
ac11f6e4c5 cmake: move gamemode target include into its file 2023-11-25 19:30:45 +01:00
flodavid
40644d43f7 yuzu: create linux group in general settings
- Create files dedicated to starting and stopping gamemode functions
  - Use them in yuzu and yuzu_cmd modules
2023-11-25 19:30:37 +01:00
xcfrg
dfa56765d6 yuzu: integrate gamemode support on linux 2023-11-25 19:30:29 +01:00
Liam
dee792937f vulkan_device: add names for more driverID enumeration values 2023-11-24 12:00:41 -05:00
Ameer J
75c5be55af shader_recompiler: Align SSBO offsets in GlobalMemory functions 2023-10-31 20:14:18 -04:00
Ameer J
735612c9b3 buffer_cache: Apply storage buffer alignment only to the offset 2023-10-31 20:10:54 -04:00
Ameer J
7d34800531 shader_recompiler: Align SSBO offsets to meet host requirements
Co-Authored-By: Billy Laws <blaws05@gmail.com>
2023-10-31 20:10:54 -04:00
54 changed files with 966 additions and 212 deletions

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
name: 'yuzu-android-build'

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-FileCopyrightText: 2021 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
name: yuzu-ci

View File

@@ -6,129 +6,10 @@ name: 'yuzu verify'
on:
pull_request:
branches: [ master ]
env:
PR_NUMBER: pr${{ github.event.number }}
jobs:
format:
name: 'verify format'
runs-on: ubuntu-latest
container:
image: yuzuemu/build-environments:linux-clang-format
options: -u 1001
steps:
- uses: actions/checkout@v3
with:
submodules: false
- name: 'Verify Formatting'
run: bash -ex ./.ci/scripts/format/script.sh
build:
name: 'test build'
needs: format
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- type: clang
image: linux-fresh
- type: linux
image: linux-fresh
- type: windows
image: linux-mingw
container:
image: yuzuemu/build-environments:${{ matrix.image }}
options: -u 1001
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
- name: Set up cache
uses: actions/cache@v3
id: ccache-restore
with:
path: ~/.ccache
key: ${{ runner.os }}-${{ matrix.type }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-${{ matrix.type }}-
- name: Create ccache directory
if: steps.ccache-restore.outputs.cache-hit != 'true'
run: mkdir -p ~/.ccache
- name: Build
run: ./.ci/scripts/${{ matrix.type }}/docker.sh
env:
ENABLE_COMPATIBILITY_REPORTING: "ON"
- name: Pack
run: ./.ci/scripts/${{ matrix.type }}/upload.sh
env:
NO_SOURCE_PACK: "YES"
- name: Upload
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.type }}
path: artifacts/
build-msvc:
name: 'test build (windows, msvc)'
needs: format
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
- name: Set up cache
uses: actions/cache@v3
with:
path: ~/.buildcache
key: ${{ runner.os }}-msvc-${{ github.sha }}
restore-keys: |
${{ runner.os }}-msvc-
- name: Install dependencies
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$BuildCacheVer = "v0.28.4"
$File = "buildcache-windows.zip"
$Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File"
$WebClient = New-Object System.Net.WebClient
$WebClient.DownloadFile($Uri, $File)
7z x $File
$CurrentDir = Convert-Path .
echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install Vulkan SDK
shell: pwsh
run: .\.ci\scripts\windows\install-vulkan-sdk.ps1
- name: Set up MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Configure
env:
CC: cl.exe
CXX: cl.exe
run: |
glslangValidator --version
mkdir build
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DYUZU_CRASH_DUMPS=ON
- name: Build
run: cmake --build build
- name: Cache Summary
run: buildcache -s
- name: Pack
shell: pwsh
run: .\.ci\scripts\windows\upload.ps1
- name: Upload
uses: actions/upload-artifact@v3
with:
name: msvc
path: artifacts/
- name: Upload EXE
uses: actions/upload-artifact@v3
with:
name: ${{ env.INDIVIDUAL_EXE }}
path: ${{ env.INDIVIDUAL_EXE }}
android:
runs-on: ubuntu-latest
needs: format
steps:
- uses: actions/checkout@v3
with:

View File

@@ -1,7 +1,6 @@
| Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----|
| [12074](https://github.com/yuzu-emu/yuzu//pull/12074) | [`a76a8fb5f`](https://github.com/yuzu-emu/yuzu//pull/12074/files) | Implement Native Code Execution (NCE) | [GPUCode](https://github.com/GPUCode/) | Yes |
| [12204](https://github.com/yuzu-emu/yuzu//pull/12204) | [`caa83609f`](https://github.com/yuzu-emu/yuzu//pull/12204/files) | android: Multi directory UI | [t895](https://github.com/t895/) | Yes |
| [12074](https://github.com/yuzu-emu/yuzu//pull/12074) | [`4a3abba16`](https://github.com/yuzu-emu/yuzu//pull/12074/files) | Implement Native Code Execution (NCE) | [GPUCode](https://github.com/GPUCode/) | Yes |
End of merge log. You can find the original README.md below the break.

View File

@@ -193,6 +193,10 @@ if (ANDROID)
endif()
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_subdirectory(gamemode)
endif()
# Breakpad
# https://github.com/microsoft/vcpkg/blob/master/ports/breakpad/CMakeLists.txt
if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)

11
externals/gamemode/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
project(gamemode LANGUAGES CXX C)
add_library(gamemode include/gamemode_client.h)
target_link_libraries(gamemode PRIVATE common)
target_include_directories(gamemode PUBLIC include)
set_target_properties(gamemode PROPERTIES LINKER_LANGUAGE C)

View File

@@ -0,0 +1,379 @@
// SPDX-FileCopyrightText: Copyright 2017-2019 Feral Interactive
// SPDX-License-Identifier: BSD-3-Clause
/*
Copyright (c) 2017-2019, Feral Interactive
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Feral Interactive nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CLIENT_GAMEMODE_H
#define CLIENT_GAMEMODE_H
/*
* GameMode supports the following client functions
* Requests are refcounted in the daemon
*
* int gamemode_request_start() - Request gamemode starts
* 0 if the request was sent successfully
* -1 if the request failed
*
* int gamemode_request_end() - Request gamemode ends
* 0 if the request was sent successfully
* -1 if the request failed
*
* GAMEMODE_AUTO can be defined to make the above two functions apply during static init and
* destruction, as appropriate. In this configuration, errors will be printed to stderr
*
* int gamemode_query_status() - Query the current status of gamemode
* 0 if gamemode is inactive
* 1 if gamemode is active
* 2 if gamemode is active and this client is registered
* -1 if the query failed
*
* int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
* 0 if the request was sent successfully
* -1 if the request failed
* -2 if the request was rejected
*
* int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
* 0 if the request was sent successfully
* -1 if the request failed
* -2 if the request was rejected
*
* int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process
* 0 if gamemode is inactive
* 1 if gamemode is active
* 2 if gamemode is active and this client is registered
* -1 if the query failed
*
* const char* gamemode_error_string() - Get an error string
* returns a string describing any of the above errors
*
* Note: All the above requests can be blocking - dbus requests can and will block while the daemon
* handles the request. It is not recommended to make these calls in performance critical code
*/
#include <stdbool.h>
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
static char internal_gamemode_client_error_string[512] = { 0 };
/**
* Load libgamemode dynamically to dislodge us from most dependencies.
* This allows clients to link and/or use this regardless of runtime.
* See SDL2 for an example of the reasoning behind this in terms of
* dynamic versioning as well.
*/
static volatile int internal_libgamemode_loaded = 1;
/* Typedefs for the functions to load */
typedef int (*api_call_return_int)(void);
typedef const char *(*api_call_return_cstring)(void);
typedef int (*api_call_pid_return_int)(pid_t);
/* Storage for functors */
static api_call_return_int REAL_internal_gamemode_request_start = NULL;
static api_call_return_int REAL_internal_gamemode_request_end = NULL;
static api_call_return_int REAL_internal_gamemode_query_status = NULL;
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
/**
* Internal helper to perform the symbol binding safely.
*
* Returns 0 on success and -1 on failure
*/
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
void *handle, const char *name, void **out_func, size_t func_size, bool required)
{
void *symbol_lookup = NULL;
char *dl_error = NULL;
/* Safely look up the symbol */
symbol_lookup = dlsym(handle, name);
dl_error = dlerror();
if (required && (dl_error || !symbol_lookup)) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"dlsym failed - %s",
dl_error);
return -1;
}
/* Have the symbol correctly, copy it to make it usable */
memcpy(out_func, &symbol_lookup, func_size);
return 0;
}
/**
* Loads libgamemode and needed functions
*
* Returns 0 on success and -1 on failure
*/
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
{
/* We start at 1, 0 is a success and -1 is a fail */
if (internal_libgamemode_loaded != 1) {
return internal_libgamemode_loaded;
}
/* Anonymous struct type to define our bindings */
struct binding {
const char *name;
void **functor;
size_t func_size;
bool required;
} bindings[] = {
{ "real_gamemode_request_start",
(void **)&REAL_internal_gamemode_request_start,
sizeof(REAL_internal_gamemode_request_start),
true },
{ "real_gamemode_request_end",
(void **)&REAL_internal_gamemode_request_end,
sizeof(REAL_internal_gamemode_request_end),
true },
{ "real_gamemode_query_status",
(void **)&REAL_internal_gamemode_query_status,
sizeof(REAL_internal_gamemode_query_status),
false },
{ "real_gamemode_error_string",
(void **)&REAL_internal_gamemode_error_string,
sizeof(REAL_internal_gamemode_error_string),
true },
{ "real_gamemode_request_start_for",
(void **)&REAL_internal_gamemode_request_start_for,
sizeof(REAL_internal_gamemode_request_start_for),
false },
{ "real_gamemode_request_end_for",
(void **)&REAL_internal_gamemode_request_end_for,
sizeof(REAL_internal_gamemode_request_end_for),
false },
{ "real_gamemode_query_status_for",
(void **)&REAL_internal_gamemode_query_status_for,
sizeof(REAL_internal_gamemode_query_status_for),
false },
};
void *libgamemode = NULL;
/* Try and load libgamemode */
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
if (!libgamemode) {
/* Attempt to load unversioned library for compatibility with older
* versions (as of writing, there are no ABI changes between the two -
* this may need to change if ever ABI-breaking changes are made) */
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
if (!libgamemode) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"dlopen failed - %s",
dlerror());
internal_libgamemode_loaded = -1;
return -1;
}
}
/* Attempt to bind all symbols */
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
struct binding *binder = &bindings[i];
if (internal_bind_libgamemode_symbol(libgamemode,
binder->name,
binder->functor,
binder->func_size,
binder->required)) {
internal_libgamemode_loaded = -1;
return -1;
};
}
/* Success */
internal_libgamemode_loaded = 0;
return 0;
}
/**
* Redirect to the real libgamemode
*/
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
{
/* If we fail to load the system gamemode, or we have an error string already, return our error
* string instead of diverting to the system version */
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
return internal_gamemode_client_error_string;
}
/* Assert for static analyser that the function is not NULL */
assert(REAL_internal_gamemode_error_string != NULL);
return REAL_internal_gamemode_error_string();
}
/**
* Redirect to the real libgamemode
* Allow automatically requesting game mode
* Also prints errors as they happen.
*/
#ifdef GAMEMODE_AUTO
__attribute__((constructor))
#else
__attribute__((always_inline)) static inline
#endif
int gamemode_request_start(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
/* Assert for static analyser that the function is not NULL */
assert(REAL_internal_gamemode_request_start != NULL);
if (REAL_internal_gamemode_request_start() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
return 0;
}
/* Redirect to the real libgamemode */
#ifdef GAMEMODE_AUTO
__attribute__((destructor))
#else
__attribute__((always_inline)) static inline
#endif
int gamemode_request_end(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
/* Assert for static analyser that the function is not NULL */
assert(REAL_internal_gamemode_request_end != NULL);
if (REAL_internal_gamemode_request_end() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
return 0;
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_query_status(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_query_status == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_query_status missing (older host?)");
return -1;
}
return REAL_internal_gamemode_query_status();
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_request_start_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_request_start_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_request_start_for(pid);
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_request_end_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_request_end_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_request_end_for(pid);
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_query_status_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_query_status_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_query_status_for(pid);
}
#endif // CLIENT_GAMEMODE_H

View File

@@ -31,6 +31,8 @@ import com.google.android.material.navigation.NavigationBarView
import kotlinx.coroutines.CoroutineScope
import java.io.File
import java.io.FilenameFilter
import java.io.FileOutputStream
import java.io.IOException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -70,45 +72,28 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
val savesFolderRoot get() = File(savesFolder).listFiles()?.firstOrNull()?.canonicalPath ?: ""
override fun onCreate(savedInstanceState: Bundle?) {
// 定义一个变量keysDirPath,其值是应用程序文件目录下"keys"子目录的绝对路径
val keysDirPath = applicationContext.filesDir.absolutePath + "/keys/"
// 创建一个File对象代表keysDirPath所指示的文件或目录
val keysDir = File(keysDirPath)
// 检查"keys"目录是否存在,如果不存在则创建它
if (!keysDir.exists()) {
keysDir.mkdir()
// 尝试打开assets目录下的"keys.txt"文件并创建一个输入流inputStream
try {
val inputStream = applicationContext.assets.open("prod.keys")
// 创建一个输出流outputStream用于将数据写入到keys目录下的"prod.keys"文件
val outputStream = FileOutputStream(keysDirPath + "prod.keys")
// 使用缓冲区来提高读写效率创建输入缓冲流bufferedInputStream和输出缓冲流bufferedOutputStream
val bufferedInputStream = BufferedInputStream(inputStream)
val bufferedOutputStream = BufferedOutputStream(outputStream)
// 创建一个大小为1024字节的字节数组buffer用于在输入输出流之间传递数据
val buffer = ByteArray(1024)
var length: Int
// 从输入流读取数据,并将其写入输出流中,直到读取完所有数据为止
while (bufferedInputStream.read(buffer).also { length = it } != -1) {
bufferedOutputStream.write(buffer, 0, length)
val keysDirPath = applicationContext.filesDir.absolutePath + "/keys/"
val keysDir = File(keysDirPath)
if (!keysDir.exists()) {
keysDir.mkdir()
try {
val inputStream = applicationContext.assets.open("prod.keys")
val outputStream = FileOutputStream(keysDirPath + "prod.keys")
val bufferedInputStream = BufferedInputStream(inputStream)
val bufferedOutputStream = BufferedOutputStream(outputStream)
val buffer = ByteArray(1024)
var length: Int
while (bufferedInputStream.read(buffer).also { length = it } != -1) {
bufferedOutputStream.write(buffer, 0, length)
}
bufferedInputStream.close()
bufferedOutputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
} else {
println("Keys directory already exists.")
}
// 关闭输入流和输出流,释放资源
bufferedInputStream.close()
bufferedOutputStream.close()
} catch (e: IOException) {
// 如果在上述过程中发生异常,打印异常的堆栈跟踪信息,帮助定位问题原因
e.printStackTrace()
}
} else {
// 如果"keys"目录已经存在,打印一条消息提示用户目录已经存在,避免重复操作
println("Keys directory already exists.")
}
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }

View File

@@ -58,8 +58,8 @@ object GameHelper {
gameDirs.removeAt(it - offset)
offset++
}
NativeConfig.setGameDirs(gameDirs.toTypedArray())
}
NativeConfig.setGameDirs(gameDirs.toTypedArray())
// Cache list of games found on disk
val serializedGames = mutableSetOf<String>()

View File

@@ -0,0 +1,215 @@
aes_kek_generation_source = 4d870986c45d20722fba1053da92e8a9
aes_key_generation_source = 89615ee05c31b6805fe58f3da24f7aa8
bis_kek_source = 34c1a0c48258f8b4fa9e5e6adafc7e4f
bis_key_00 = 2b8bb16cfc902cadb2e04b63cb5ea0ec33cc49b3d74b1866090e06617fb2ad08
bis_key_01 = ae9cc3d720c0894fa9ed293ea0349c46a526dc11281200b8d853d2a25ab2a9fe
bis_key_02 = 0569dfd9e2f8d2d06235dba3b442a2450be9d10d22a7d9b0626bb43570cd9ebb
bis_key_03 = 0569dfd9e2f8d2d06235dba3b442a2450be9d10d22a7d9b0626bb43570cd9ebb
bis_key_source_00 = f83f386e2cd2ca32a89ab9aa29bfc7487d92b03aa8bfdee1a74c3b6e35cb7106
bis_key_source_01 = 41003049ddccc065647a7eb41eed9c5f44424edab49dfcd98777249adc9f7ca4
bis_key_source_02 = 52c2e9eb09e3ee2932a10c1fb6a0926c4d12e14b2a474c1c09cb0359f015f4e4
device_key = e6b9dc43da7e4d15f60443133f9c5c9f
device_key_4x = e2f0bcbf3a84a72dc9866aad9d3555bc
eticket_rsa_kek = 19c8b441d318802bad63a5beda283a84
eticket_rsa_kek_source = dba451124ca0a9836814f5ed95e3125b
eticket_rsa_kekek_source = 466e57b74a447f02f321cde58f2f5535
eticket_rsa_keypair = a1c4013b6b5d6965147020e80e5c917b06ad609d6681751ef9bbca91015b7f59a5d84902af4aae63a900f75ea1e8dcff633bdfefa70befbacc5dbd0dd138ab2f7781f8df3851aff9678b40af7f075780c1633727ee8d2d9e8a8925d36c07cd59a8cfa15cfff71f80c51399a8ab4b53010e2ce7e99ea7a83339d5ba272a2ae97b470adc0f64fb02c8d08d1cdf9e8a63b30c27f85bee9bc0faded0a27dfda73fe90a3e9afc9a9ab24e1519f5c222a0d7062771fc508c07cd8b99efe8e3ff9c76c36b8450ae5a3274f2da3e1ae964d9f67e5574b570c6352c0e13195684e50222b2ca57e9a9bbefec09578d9fd114882fb01c56b6014c8cd4aa57cf70bb105a94b1d30fd325ba4dc1c607ea7fd7cb6d57386b6ffcf4cb14ecafaec12e6f05e24d0665ad0ae95cd5ebd45ed1cbe9416818c00a16613d68873c687ad9a152f92c4fc068a122780f7f870b3d9476be4dceec41a5eefaf33762846d6f1d0ff9bb025224bf3ab6950cea5108e1935089828b0bb6bce8a3494026d9adaba053cff388c25c30f2c4ffe545663ab2a754d0e57a6d50c29e4c2a9f9788cbd903b051f2fc65ee998db48c703d4d89246b96001c6c99dd80d09be60de6c9829ae8cad18b5d8de02991834bab3e1ea7f9b2c731b89253b2873527c0103959ddc8e633f71fe320921349f7b80efa77a6e27e409eaf50e75a06f20288073b5d8955c35662c7b979af00010001000000000000000000000000
header_kek_source = 1f12913a4acbf00d4cde3af6d523882a
header_key = aeaab1ca08adf9bef12991f369e3c567d6881e4e4a6a47a51f6e4877062d542d
header_key_source = 5a3ed84fdec0d82631f7e25d197bf5d01c9b7bfaf628183d71f64d73f150b9d2
key_area_key_application_00 = ef979e289a132c23d39c4ec5a0bba969
key_area_key_application_01 = cdedbab97b69729073dfb2440bff2c13
key_area_key_application_02 = 75716ed3b524a01dfe21456ce26c7270
key_area_key_application_03 = f428306544cf5707c25eaa8bc0583fd1
key_area_key_application_04 = 798844ec099eb6a04b26c7c728a35a4d
key_area_key_application_05 = a57c6eecc5410ada22712eb3ccbf45f1
key_area_key_application_06 = 2a60f6c4275df1770651d5891b8e73ec
key_area_key_application_07 = 32221bd6ed19b938bec06b9d36ed9e51
key_area_key_application_08 = fb20aa9e3dbf67350e86479eb431a0b3
key_area_key_application_09 = ce8d5fa79e220d5f48470e9f21be018b
key_area_key_application_0a = 38b865725adcf568a81d2db3ceaa5bcc
key_area_key_application_0b = bbddfd40a59d0ff555c0954239972213
key_area_key_application_0c = 3fee7204e21c6b0ff1373226c0c3e055
key_area_key_application_0d = 7b05d214fa554bc3e91b044fb412fc0d
key_area_key_application_0e = 061667d7668b76a423e3f1aea52a8baa
key_area_key_application_0f = 7ee19b046987ba2588e852cc24bc2953
key_area_key_application_10 = fd8a4be923d9a464793cd2f3a27557ee
key_area_key_application_source = 7f59971e629f36a13098066f2144c30d
key_area_key_ocean_00 = b33813e4c9c4399c75fabc673ab4947b
key_area_key_ocean_01 = c54166efa8c9c0f6511fa8b580191677
key_area_key_ocean_02 = 3061ce73461e0b0409d6a33da85843c8
key_area_key_ocean_03 = 06f170025a64921c849df168e74d37f2
key_area_key_ocean_04 = dc857fd6dc1c6213076ec7b902ec5bb6
key_area_key_ocean_05 = 131d76b70bd8a60036d8218c15cb610f
key_area_key_ocean_06 = 17d565492ba819b0c19bed1b4297b659
key_area_key_ocean_07 = 37255186f7678324bf2b2d773ea2c412
key_area_key_ocean_08 = 4115c119b7bd8522ad63c831b6c816a6
key_area_key_ocean_09 = 792bfc652870cca7491d1685384be147
key_area_key_ocean_0a = dfcc9e87e61c9fba54a9b1c262d41e4d
key_area_key_ocean_0b = 66fe3107f5a6a8d8eda2459d920b07a1
key_area_key_ocean_0c = b79b6bf3d6cdc5ec10277fc07a4fec93
key_area_key_ocean_0d = 9a20ffbdcb03cfc5b8e88b058d27ae6c
key_area_key_ocean_0e = 1e8bba40c91ca4d55163cdfb779a2f4e
key_area_key_ocean_0f = 2a51262c614e175f22cb0bf7907418b0
key_area_key_ocean_10 = 97b66913f9683a9e7b733b96a35cabf3
key_area_key_ocean_source = 327d36085ad1758dab4e6fbaa555d882
key_area_key_system_00 = 6dd02aa15b440d6231236b6677de86bc
key_area_key_system_01 = 4ab155e7f29a292037fd147592770b12
key_area_key_system_02 = b7a74adeaf89c2a198c327bdff322d7d
key_area_key_system_03 = d5aab1acd23a8aec284a316df859d377
key_area_key_system_04 = 9b44b45b37de9d14754b1d22c2ca742c
key_area_key_system_05 = 0012e957530d3dc7af34fbbe6fd44559
key_area_key_system_06 = 01744e3b0818445cd54ee9f89da43192
key_area_key_system_07 = d0d30e46f5695b875f11522c375c5a80
key_area_key_system_08 = bd06cb1b86bd5c433667470a09eb63de
key_area_key_system_09 = e19f788f658eda8bbf34a1dd2a9503a9
key_area_key_system_0a = 7070e7ff5cfe448630143a9874903c38
key_area_key_system_0b = 3fa471d4483e58b8f7756fcb64f63890
key_area_key_system_0c = 7bfd381df3369407ab1c6bdd9fabf522
key_area_key_system_0d = 53ed531cd657edf443b551a964f44ecc
key_area_key_system_0e = fa9d4958e8f8f2c8c8ae33b1034a0a02
key_area_key_system_0f = 91eae4eeb5335cc5a706c4fe81d8d8af
key_area_key_system_10 = ae11fa6821b123419e0a54f3a89d9a8b
key_area_key_system_source = 8745f1bba6be79647d048ba67b5fda4a
keyblob_00 = f759024f8199101dddc1ef91e6eecf37e24b95ac9272f7ae441d5d8060c843a48322d21cdd06d4fc958c68d3800eb4db939ffbec930177f77d136144ff615aa8835e811bb958deda218f8486b5a10f531b30cb9d269645ac9fc25c53fc80525e56bd3602988a9fcf06bbf99ca910ad6530791d512c9d57e17abf49220de6419bf4eca1685c1e4df77f19db7b44a985ca
keyblob_01 = bd27264ae07e979756411d0c66e679e3c50851f3e902d9c2cd1a438b948159a517ec1566c10570326ea2697ee62da46f14bb5d581bfc06fd0c9387ea33d2d4dc63e7809ba90f03dd2c7112ffbfa548951b9b8c688b5e4f2951d24a73da29c668154a5d4838dba71ee068ace83fe720e8c2a495c596f73525dc3c05994b40ad27f8c60322f75cd548b821af9162e16f76
keyblob_02 = a3d4a8e153b8e6ae6e6aef3e8f219cb4b7790f47856accc76268f9afa99a1ff8b1a72f63d1f99f480a3c1532078bb59abdd25203cfb12a38b33e9ba6a09afb6f24283b3ba76a0161230a73669ddf5493c2b7919d094fd795b484794854f71e4f4c672245d7770e29397722444d111b4229cdbf35707b70634ea8f140766e884cc580cb1e2d9aa9866ffef920010fc409
keyblob_03 = 1558f525ae8c5be9243fb6d8a8b0a8ee0e886a59035668740a936619b7a5c83e821198b171d18e51445054df68688e45703b936818a827d8e540dd6bef2e11ec9ddc6cfe5fc736dd769b9f6e0a23a62e2e5f49e86143646a04ec3a23f828373a336a5c224a91f8a0c6c6a7b5844dd6415804209f83c943aeca9cfd856db6bd4ec32009c8cb268ed053052c9237dfd8bc
keyblob_04 = 9fbeb1957fc1629e08b753a9086d6e01ffb4f11466b7417e3fa7f5f1efb754406704fd75afaf91a408a0b524c1fc80d36c2046fa4757412efe4c11e382f72e8a10d90ed580017d9deb87af2549b6b02661af48ff94f6072c0fef7fc2833b8bdae503898e2e927ac0663e8b6391dd4f1d685313935e2c48ece7d177c88bc9c883ede36c3677495784b838d7265c6ba7a1
keyblob_05 = 94a92da1d73c2b3e165c891ced5607fc6628ca2a0654f3fbc05711c063377c6e9c96a9d0192e530dd510e4fd41aa62ef4213c5f6e059e7e21db098a9b22d1e6c29bee148aaef15c52549d9165de96e85b0d029ecdc5843e2f32cb18be707eec61909cf3385d45bc2a4c8d76e9bfad5a40c4b92dcb982aa50d474897ac9ebb5351a7015dcc277a08f1214ad41384d7941
keyblob_key_00 = d621a08fba5e3a11e5c8ae37560b8d01
keyblob_key_01 = 84e3303b6e4acd083fd73ca75be0d4a2
keyblob_key_02 = a7bf0d1e44d6f3f7cb010a35654e84b4
keyblob_key_03 = 4f11fd1e2ed8cc2ab8fe5c4f8adecfee
keyblob_key_04 = 59b204d1cc932c23e5a473bf0fa8af15
keyblob_key_05 = a9984e8f0ef40cd0ca9b86ab74188cf9
keyblob_key_source_00 = df206f594454efdc7074483b0ded9fd3
keyblob_key_source_01 = 0c25615d684ceb421c2379ea822512ac
keyblob_key_source_02 = 337685ee884aae0ac28afd7d63c0433b
keyblob_key_source_03 = 2d1f4880edeced3e3cf248b5657df7be
keyblob_key_source_04 = bb5a01f988aff5fc6cff079e133c3980
keyblob_key_source_05 = d8cce1266a353fcc20f32d3b517de9c0
keyblob_mac_key_00 = 782b915ab93552634fa142f8220e3cb5
keyblob_mac_key_01 = bdcaccca7c0f2ea5f9a0f6e065fa66f6
keyblob_mac_key_02 = 3e097bf16b5c24a8748c0498e998368e
keyblob_mac_key_03 = b48f35cb5b99f22315c69612c788b5f2
keyblob_mac_key_04 = 33e8ac5201ca946da82e5d5bf34d3c2f
keyblob_mac_key_05 = 7faed890e924d08d594636dd017086b6
keyblob_mac_key_source = 59c7fb6fbe9bbe87656b15c0537336a5
mariko_master_kek_source_05 = 77605ad2ee6ef83c3f72e2599dac5e56
mariko_master_kek_source_06 = 1e80b8173ec060aa11be1a4aa66fe4ae
mariko_master_kek_source_07 = 940867bd0a00388411d31adbdd8df18a
mariko_master_kek_source_08 = 5c24e3b8b4f700c23cfd0ace13c3dc23
mariko_master_kek_source_09 = 8669f00987c805aeb57b4874de62a613
mariko_master_kek_source_0a = 0e440cedb436c03faa1daebf62b10982
mariko_master_kek_source_0b = e541acecd1a7d1abed0377f127caf8f1
mariko_master_kek_source_0c = 52719bdfa78b61d8d58511e48e4f74c6
mariko_master_kek_source_0d = d268c6539d94f9a8a5a8a7c88f534b7a
mariko_master_kek_source_0e = ec61bc821e0f5ac32b643f9dd619222d
mariko_master_kek_source_0f = a5ec16391a3016082ecf096f5e7ceea9
mariko_master_kek_source_10 = 8dee9e11363a9b0a6ac7bbe9d103f780
master_kek_00 = f759024f8199101dddc1ef91e6eecf37
master_kek_01 = bd27264ae07e979756411d0c66e679e3
master_kek_02 = a3d4a8e153b8e6ae6e6aef3e8f219cb4
master_kek_03 = 1558f525ae8c5be9243fb6d8a8b0a8ee
master_kek_04 = 9fbeb1957fc1629e08b753a9086d6e01
master_kek_05 = 94a92da1d73c2b3e165c891ced5607fc
master_kek_08 = e42f1ec8002043d746575ae6dd9f283f
master_kek_09 = cec2885fbeef5f6a989db84a4cc4b393
master_kek_0a = dd1a730232522b5cb4590cd43869ab6a
master_kek_0b = fc6f0c891d42710180724ed9e112e72a
master_kek_0c = 43f7fc20fcec22a5b2a744790371b094
master_kek_0d = 8dc9a8223671daa73ccd8b93cdaaed9f
master_kek_0e = f3f857257c3f63ca63b9c9710b8f673e
master_kek_0f = 1e8f01c4927a76a66097df44c3bad27d
master_kek_10 = 8b523b9d476508daadc2036582ce5aa8
master_kek_source_06 = 374b772959b4043081f6e58c6d36179a
master_kek_source_07 = 9a3ea9abfd56461c9bf6487f5cfa095c
master_kek_source_08 = dedce339308816f8ae97adec642d4141
master_kek_source_09 = 1aec11822b32387a2bedba01477e3b67
master_kek_source_0a = 303f027ed838ecd7932534b530ebca7a
master_kek_source_0b = 8467b67f1311aee6589b19af136c807a
master_kek_source_0c = 683bca54b86f9248c305768788707923
master_kek_source_0d = f013379ad56351c3b49635bc9ce87681
master_kek_source_0e = 6e7786ac830a8d3e7db766a022b76e67
master_kek_source_0f = 99220957a7f95e94fe787f41d6e756e6
master_kek_source_10 = 71b9a6c0ff976b0cb440b9d5815d8190
master_key_00 = c2caaff089b9aed55694876055271c7d
master_key_01 = 54e1b8e999c2fd16cd07b66109acaaa6
master_key_02 = 4f6b10d33072af2f250562bff06b6da3
master_key_03 = 84e04ec20b9373818c540829cf147f3d
master_key_04 = cfa2176790a53ff74974bff2af180921
master_key_05 = c1dbedcebf0dd6956079e506cfa1af6e
master_key_06 = 0aa90e6330cdc12d819b3254d11a4e1e
master_key_07 = 929f86fbfe4ef7732892bf3462511b0e
master_key_08 = 23cfb792c3cb50cd715da0f84880c877
master_key_09 = 75c93b716255319b8e03e14c19dea64e
master_key_0a = 73767484c73088f629b0eeb605f64aa6
master_key_0b = 8500b14bf4766b855a26ffc614097a8f
master_key_0c = b3c503709135d4b35de31be4b0b9c0f7
master_key_0d = 6d2b26416ab030dc504cbfd6bb2977b7
master_key_0e = 3b995e3bf23207c3cacb07f8c57415e6
master_key_0f = ff22454d86237004c750e2dcb4b16c80
master_key_10 = 252c7d95f296d07f2369bdba6d42c615
master_key_source = d8a2410ac6c59001c61d6a267c513f3c
package1_key_00 = f4eca1685c1e4df77f19db7b44a985ca
package1_key_01 = f8c60322f75cd548b821af9162e16f76
package1_key_02 = c580cb1e2d9aa9866ffef920010fc409
package1_key_03 = c32009c8cb268ed053052c9237dfd8bc
package1_key_04 = ede36c3677495784b838d7265c6ba7a1
package1_key_05 = 1a7015dcc277a08f1214ad41384d7941
package2_key_00 = a35a19cb14404b2f4460d343d178638d
package2_key_01 = a0dd1eacd438610c85a191f02c1db8a8
package2_key_02 = 7e5ba2aafd57d47a85fd4a57f2076679
package2_key_03 = bf03e9889fa18f0d7a55e8e9f684323d
package2_key_04 = 09df6e361e28eb9c96c9fa0bfc897179
package2_key_05 = 444b1a4f9035178b9b1fe262462acb8e
package2_key_06 = 442cd9c21cfb8914587dc12e8e7ed608
package2_key_07 = 70c821e7d6716feb124acbac09f7b863
package2_key_08 = 8accebcc3d15a328a48365503f8369b6
package2_key_09 = f562a7c6c42e3d4d3d13ffd504d77346
package2_key_0a = 0803167ec7fc0bc753d8330e5592a289
package2_key_0b = 341db6796aa7bdb8092f7aae6554900a
package2_key_0c = 4e97dc4225d00c6ae33d49bddd17637d
package2_key_0d = db13c2de2c313540b18a32b4f106d4a1
package2_key_0e = 254d393b26e6d98963c1c8c4fa6d11e2
package2_key_0f = 1c87f9650cca54af03df3590021e457d
package2_key_10 = 2d64ee13cece88746b375f1a43b9fdf6
package2_key_source = fb8b6a9c7900c849efd24d854d30a0c7
per_console_key_source = 4f025f0eb66d110edc327d4186c2f478
retail_specific_aes_key_source = e2d6b87a119cb880e822888a46fba195
save_mac_kek_source = d89c236ec9124e43c82b038743f9cf1b
save_mac_key = f33d6c1a8b26c7f6ff96f3b3a7dcf5db
save_mac_key_source = e4cd3d4ad50f742845a487e5a063ea1f
save_mac_sd_card_kek_source = 0489ef5d326e1a59c4b7ab8c367aab17
save_mac_sd_card_key_source = 6f645947c56146f9ffa045d595332918
sd_card_custom_storage_key_source = 370c345e12e4cefe21b58e64db52af354f2ca5a3fc999a47c03ee004485b2fd0
sd_card_kek_source = 88358d9c629ba1a00147dbe0621b5432
sd_card_nca_key_source = 5841a284935b56278b8e1fc518e99f2b67c793f0f24fded075495dca006d99c2
sd_card_save_key_source = 2449b722726703a81965e6e3ea582fdd9a951517b16e8f7f1f68263152ea296a
sd_seed = a1bdc735db732a90004f7eb2c2f4c6f7
secure_boot_key = 461720644b2df9fd1b109745000af741
ssl_rsa_kek = b011100660d1dccbad1b1b733afa9f95
ssl_rsa_kek_source = 9a383bf431d0bd8132534ba964397de3
ssl_rsa_kekek_source = 7f5bb0847b25aa67fac84be23d7b6903
ssl_rsa_key = 6af57e8a0b394231df2fe6ec3dfff06d1c35119c3c9e58ed6ef452415a1d9d331422112a776f4c67ce8e00d3a4469ea62e8cf7f4b38285daed8e700b3af301a44d64740f34631549ee2645194cf47c4efae44e287abb80a2c99910c6309c7cba3be49ae46488d889987240ed36c54f294cb85e0b9a81cb79a3c2c1bf1b2beef3f5553d06dc6c2101e330e974052cf8fa55433f1a4f4468368961f4bc22dbee595ef6ec28f1dc1f2ddd33a8d49b24852d2ca1f80878c2f107d7542d96237a127cb15fecf64c93abb7b68d85315ff72319332b7d2fd61e772458e451b8901ab38b7027f4b045b6147c4bad806bb0fa1ec4649bc2b51c433081b75617c4ca234fb9
titlekek_00 = 62a24d6e6d0d0e0abf3554d259be3dc9
titlekek_01 = 8821f642176969b1a18021d2665c0111
titlekek_02 = 5d15b9b95a5739a0ac9b20f600283962
titlekek_03 = 1b3f63bcb67d4b06da5badc7d89acce1
titlekek_04 = e45c1789a69c7afbbf1a1e61f2499459
titlekek_05 = ddc67f7189f4527a37b519cb051eee21
titlekek_06 = b1532b9d38ab036068f074c0d78706ac
titlekek_07 = 81dc1b1783df268789a6a0edbf058343
titlekek_08 = 47dfe4bf0eeda88b17136b8005ab08ea
titlekek_09 = adaa785d90e1a9c182ac07bc276bf600
titlekek_0a = 42daa957c128f75bb1fda56a8387e17b
titlekek_0b = d08903363f2c8655d3de3ccf85d79406
titlekek_0c = be2682599db34caa9bc7ebb2cc7c654c
titlekek_0d = 41071f95beddc4114a03e0072e6ccab7
titlekek_0e = e342365a0fa0fa4a28a7bc00e45b3f68
titlekek_0f = 105999eaf8b71d199bf201f525b2c68d
titlekek_10 = 3796fcdb27351d58cc3f3379dda04202
titlekek_source = 1edc7b3b60e6b4d878b81715985e629b
tsec_key = fdb46027e6576babf0caf127980f4cae
tsec_root_key_02 = 4b4fbcf58e23cf4902d478b76c8048ec

View File

@@ -182,6 +182,15 @@ if(ANDROID)
)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_sources(common PRIVATE
linux/gamemode.cpp
linux/gamemode.h
)
target_link_libraries(common PRIVATE gamemode)
endif()
if(ARCHITECTURE_x86_64)
target_sources(common
PRIVATE

View File

@@ -541,7 +541,7 @@ public:
if (write) {
flags |= PROT_WRITE;
}
#ifdef ARCHITECTURE_arm64
#ifdef HAS_NCE
if (execute) {
flags |= PROT_EXEC;
}

View File

@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <gamemode_client.h>
#include "common/linux/gamemode.h"
#include "common/logging/log.h"
#include "common/settings.h"
namespace Common::Linux {
void StartGamemode() {
if (Settings::values.enable_gamemode) {
if (gamemode_request_start() < 0) {
LOG_WARNING(Frontend, "Failed to start gamemode: {}", gamemode_error_string());
} else {
LOG_INFO(Frontend, "Started gamemode");
}
}
}
void StopGamemode() {
if (Settings::values.enable_gamemode) {
if (gamemode_request_end() < 0) {
LOG_WARNING(Frontend, "Failed to stop gamemode: {}", gamemode_error_string());
} else {
LOG_INFO(Frontend, "Stopped gamemode");
}
}
}
void SetGamemodeState(bool state) {
if (state) {
StartGamemode();
} else {
StopGamemode();
}
}
} // namespace Common::Linux

View File

@@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace Common::Linux {
/**
* Start the (Feral Interactive) Linux gamemode if it is installed and it is activated
*/
void StartGamemode();
/**
* Stop the (Feral Interactive) Linux gamemode if it is installed and it is activated
*/
void StopGamemode();
/**
* Start or stop the (Feral Interactive) Linux gamemode if it is installed and it is activated
* @param state The new state the gamemode should have
*/
void SetGamemodeState(bool state);
} // namespace Common::Linux

View File

@@ -236,6 +236,8 @@ const char* TranslateCategory(Category category) {
return "Services";
case Category::Paths:
return "Paths";
case Category::Linux:
return "Linux";
case Category::MaxEnum:
break;
}

View File

@@ -438,6 +438,9 @@ struct Values {
true,
true};
// Linux
SwitchableSetting<bool> enable_gamemode{linkage, true, "enable_gamemode", Category::Linux};
// Controls
InputSetting<std::array<PlayerInput, 10>> players;

View File

@@ -41,6 +41,7 @@ enum class Category : u32 {
Multiplayer,
Services,
Paths,
Linux,
MaxEnum,
};

View File

@@ -935,8 +935,8 @@ if (HAS_NCE)
arm/nce/arm_nce.h
arm/nce/arm_nce.s
arm/nce/guest_context.h
arm/nce/patch.cpp
arm/nce/patch.h
arm/nce/patcher.cpp
arm/nce/patcher.h
arm/nce/instructions.h
)
target_link_libraries(core PRIVATE merry::oaknut)

View File

@@ -6,7 +6,7 @@
#include "common/signal_chain.h"
#include "core/arm/nce/arm_nce.h"
#include "core/arm/nce/patch.h"
#include "core/arm/nce/patcher.h"
#include "core/core.h"
#include "core/memory.h"

View File

@@ -7,7 +7,7 @@
#include "core/arm/nce/arm_nce.h"
#include "core/arm/nce/guest_context.h"
#include "core/arm/nce/instructions.h"
#include "core/arm/nce/patch.h"
#include "core/arm/nce/patcher.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/svc.h"

View File

@@ -16,7 +16,8 @@ namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
: ControllerBase{hid_core_}, touchscreen_width(Layout::ScreenUndocked::Width),
touchscreen_height(Layout::ScreenUndocked::Height) {
static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
"TouchSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
@@ -95,8 +96,8 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (id < active_fingers_count) {
const auto& [active_x, active_y] = active_fingers[id].position;
touch_entry.position = {
.x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width),
.y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height),
.x = static_cast<u16>(active_x * static_cast<float>(touchscreen_width)),
.y = static_cast<u16>(active_y * static_cast<float>(touchscreen_height)),
};
touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
@@ -120,4 +121,9 @@ void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
}
void TouchScreen::SetTouchscreenDimensions(u32 width, u32 height) {
touchscreen_width = width;
touchscreen_height = height;
}
} // namespace Service::HID

View File

@@ -28,6 +28,8 @@ public:
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
void SetTouchscreenDimensions(u32 width, u32 height);
private:
static constexpr std::size_t MAX_FINGERS = 16;
@@ -53,5 +55,7 @@ private:
Core::HID::EmulatedConsole* console = nullptr;
std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
u32 touchscreen_width;
u32 touchscreen_height;
};
} // namespace Service::HID

View File

@@ -208,6 +208,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
{1001, &IHidServer::GetNpadCommunicationMode, "GetNpadCommunicationMode"},
{1002, &IHidServer::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"},
{1003, &IHidServer::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},
{1004, &IHidServer::SetTouchScreenResolution, "SetTouchScreenResolution"},
{2000, nullptr, "ActivateDigitizer"},
};
// clang-format on
@@ -2363,6 +2364,21 @@ void IHidServer::IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx) {
rb.Push(false);
}
void IHidServer::SetTouchScreenResolution(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto width{rp.Pop<u32>()};
const auto height{rp.Pop<u32>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
GetResourceManager()->GetTouchScreen()->SetTouchscreenDimensions(width, height);
LOG_INFO(Service_HID, "called, width={}, height={}, applet_resource_user_id={}", width, height,
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
std::shared_ptr<ResourceManager> IHidServer::GetResourceManager() {
resource_manager->Initialize();
return resource_manager;

View File

@@ -141,6 +141,7 @@ private:
void GetNpadCommunicationMode(HLERequestContext& ctx);
void SetTouchScreenConfiguration(HLERequestContext& ctx);
void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
void SetTouchScreenResolution(HLERequestContext& ctx);
std::shared_ptr<ResourceManager> resource_manager;
std::shared_ptr<HidFirmwareSettings> firmware_settings;

View File

@@ -34,7 +34,9 @@ Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System&
nca = bis_system->GetEntry(FirmwareVersionSystemDataId, FileSys::ContentRecordType::Data);
}
if (nca) {
romfs = FileSys::ExtractRomFS(nca->GetRomFS());
if (auto nca_romfs = nca->GetRomFS(); nca_romfs) {
romfs = FileSys::ExtractRomFS(nca_romfs);
}
}
if (!romfs) {
romfs = FileSys::ExtractRomFS(

View File

@@ -16,7 +16,7 @@
#include "core/loader/nso.h"
#ifdef HAS_NCE
#include "core/arm/nce/patch.h"
#include "core/arm/nce/patcher.h"
#endif
namespace Loader {

View File

@@ -23,7 +23,7 @@
#include "core/memory.h"
#ifdef HAS_NCE
#include "core/arm/nce/patch.h"
#include "core/arm/nce/patcher.h"
#endif
namespace Loader {

View File

@@ -21,7 +21,7 @@
#include "core/memory.h"
#ifdef HAS_NCE
#include "core/arm/nce/patch.h"
#include "core/arm/nce/patcher.h"
#endif
namespace Loader {

View File

@@ -5,6 +5,7 @@
#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
#include "shader_recompiler/frontend/ir/program.h"
#include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/profile.h"
#include "shader_recompiler/runtime_info.h"
namespace Shader::Backend::GLASM {
@@ -35,7 +36,9 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std
continue;
}
const auto& ssbo{ctx.info.storage_buffers_descriptors[index]};
ctx.Add("LDC.U64 DC.x,c{}[{}];" // ssbo_addr
const u64 ssbo_align_mask{~(ctx.profile.min_ssbo_alignment - 1U)};
ctx.Add("LDC.U64 DC.x,c{}[{}];" // unaligned_ssbo_addr
"AND.U64 DC.x,DC.x,{};" // ssbo_addr = unaligned_ssbo_addr & ssbo_align_mask
"LDC.U32 RC.x,c{}[{}];" // ssbo_size_u32
"CVT.U64.U32 DC.y,RC.x;" // ssbo_size = ssbo_size_u32
"ADD.U64 DC.y,DC.y,DC.x;" // ssbo_end = ssbo_addr + ssbo_size
@@ -44,8 +47,8 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std
"AND.U.CC RC.x,RC.x,RC.y;" // cond = a && b
"IF NE.x;" // if cond
"SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr
ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address,
address, address);
ssbo.cbuf_index, ssbo.cbuf_offset, ssbo_align_mask, ssbo.cbuf_index,
ssbo.cbuf_offset + 8, address, address, address);
if (pointer_based) {
ctx.Add("PK64.U DC.y,c[{}];" // host_ssbo = cbuf
"ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset

View File

@@ -601,7 +601,10 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
addr_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, addr_loc / 16, Swizzle(addr_loc));
size_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, size_loc / 16, Swizzle(size_loc));
}
const auto addr_pack{fmt::format("packUint2x32(uvec2({},{}))", addr_xy[0], addr_xy[1])};
const u32 ssbo_align_mask{~(static_cast<u32>(profile.min_ssbo_alignment) - 1U)};
const auto aligned_low_addr{fmt::format("{}&{}", addr_xy[0], ssbo_align_mask)};
const auto aligned_addr{fmt::format("uvec2({},{})", aligned_low_addr, addr_xy[1])};
const auto addr_pack{fmt::format("packUint2x32({})", aligned_addr)};
const auto addr_statment{fmt::format("uint64_t {}={};", ssbo_addr, addr_pack)};
func += addr_statment;

View File

@@ -891,7 +891,9 @@ void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
const Id ssbo_size_pointer{OpAccessChain(uniform_types.U32, cbufs[ssbo.cbuf_index].U32,
zero, ssbo_size_cbuf_offset)};
const Id ssbo_addr{OpBitcast(U64, OpLoad(U32[2], ssbo_addr_pointer))};
const u64 ssbo_align_mask{~(profile.min_ssbo_alignment - 1U)};
const Id unaligned_addr{OpBitcast(U64, OpLoad(U32[2], ssbo_addr_pointer))};
const Id ssbo_addr{OpBitwiseAnd(U64, unaligned_addr, Constant(U64, ssbo_align_mask))};
const Id ssbo_size{OpUConvert(U64, OpLoad(U32[1], ssbo_size_pointer))};
const Id ssbo_end{OpIAdd(U64, ssbo_addr, ssbo_size)};
const Id cond{OpLogicalAnd(U1, OpUGreaterThanEqual(U1, addr, ssbo_addr),

View File

@@ -298,7 +298,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
Optimization::PositionPass(env, program);
Optimization::GlobalMemoryToStorageBufferPass(program);
Optimization::GlobalMemoryToStorageBufferPass(program, host_info);
Optimization::TexturePass(env, program, host_info);
if (Settings::values.resolution_info.active) {

View File

@@ -16,6 +16,7 @@ struct HostTranslateInfo {
bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered
bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers
bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS
u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs
bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry
///< passthrough shaders
bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional

View File

@@ -11,6 +11,7 @@
#include "shader_recompiler/frontend/ir/breadth_first_search.h"
#include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/host_translate_info.h"
#include "shader_recompiler/ir_opt/passes.h"
namespace Shader::Optimization {
@@ -408,7 +409,7 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageInfo& info)
}
/// Returns the offset in indices (not bytes) for an equivalent storage instruction
IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer) {
IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer, u32 alignment) {
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
IR::U32 offset;
if (const std::optional<LowAddrInfo> low_addr{TrackLowAddress(&inst)}) {
@@ -421,7 +422,10 @@ IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer
}
// Subtract the least significant 32 bits from the guest offset. The result is the storage
// buffer offset in bytes.
const IR::U32 low_cbuf{ir.GetCbuf(ir.Imm32(buffer.index), ir.Imm32(buffer.offset))};
IR::U32 low_cbuf{ir.GetCbuf(ir.Imm32(buffer.index), ir.Imm32(buffer.offset))};
// Align the offset base to match the host alignment requirements
low_cbuf = ir.BitwiseAnd(low_cbuf, ir.Imm32(~(alignment - 1U)));
return ir.ISub(offset, low_cbuf);
}
@@ -516,7 +520,7 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
}
} // Anonymous namespace
void GlobalMemoryToStorageBufferPass(IR::Program& program) {
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info) {
StorageInfo info;
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
@@ -540,7 +544,8 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) {
const IR::U32 index{IR::Value{static_cast<u32>(info.set.index_of(it))}};
IR::Block* const block{storage_inst.block};
IR::Inst* const inst{storage_inst.inst};
const IR::U32 offset{StorageOffset(*block, *inst, storage_buffer)};
const IR::U32 offset{
StorageOffset(*block, *inst, storage_buffer, host_info.min_ssbo_alignment)};
Replace(*block, *inst, index, offset);
}
}

View File

@@ -16,7 +16,7 @@ void CollectShaderInfoPass(Environment& env, IR::Program& program);
void ConditionalBarrierPass(IR::Program& program);
void ConstantPropagationPass(Environment& env, IR::Program& program);
void DeadCodeEliminationPass(IR::Program& program);
void GlobalMemoryToStorageBufferPass(IR::Program& program);
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info);
void IdentityRemovalPass(IR::Program& program);
void LowerFp64ToFp32(IR::Program& program);
void LowerFp16ToFp32(IR::Program& program);

View File

@@ -85,6 +85,8 @@ struct Profile {
/// Maxwell and earlier nVidia architectures have broken robust support
bool has_broken_robust{};
u64 min_ssbo_alignment{};
};
} // namespace Shader

View File

@@ -1753,15 +1753,25 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
return std::min(memory_layout_size, static_cast<u32>(8_MiB));
}();
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
if (!cpu_addr || size == 0) {
// Alignment only applies to the offset of the buffer
const u32 alignment = runtime.GetStorageBufferAlignment();
const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);
const u32 aligned_size = static_cast<u32>(gpu_addr - aligned_gpu_addr) + size;
const std::optional<VAddr> aligned_cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr);
if (!aligned_cpu_addr || size == 0) {
LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index);
return NULL_BINDING;
}
const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, YUZU_PAGESIZE);
const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
ASSERT_MSG(cpu_addr, "Unaligned storage buffer address not found for cbuf index {}",
cbuf_index);
// The end address used for size calculation does not need to be aligned
const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, Core::Memory::YUZU_PAGESIZE);
const Binding binding{
.cpu_addr = *cpu_addr,
.size = is_written ? size : static_cast<u32>(cpu_end - *cpu_addr),
.cpu_addr = *aligned_cpu_addr,
.size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_cpu_addr),
.buffer_id = BufferId{},
};
return binding;

View File

@@ -58,7 +58,7 @@ private:
void TrackPage(u64 page, u64 offset, u64 size) noexcept {
const size_t offset_in_page = offset % PAGE_BYTES;
const size_t first_bit = offset_in_page >> BYTES_PER_BIT_SHIFT;
const size_t num_bits = std::min(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
const size_t num_bits = std::min<size_t>(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
const size_t mask = ~u64{0} >> (64 - num_bits);
pages[page] |= (~u64{0} & mask) << first_bit;
}
@@ -66,7 +66,7 @@ private:
bool IsPageUsed(u64 page, u64 offset, u64 size) const noexcept {
const size_t offset_in_page = offset % PAGE_BYTES;
const size_t first_bit = offset_in_page >> BYTES_PER_BIT_SHIFT;
const size_t num_bits = std::min(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
const size_t num_bits = std::min<size_t>(size, PAGE_BYTES) >> BYTES_PER_BIT_SHIFT;
const size_t mask = ~u64{0} >> (64 - num_bits);
const size_t mask2 = (~u64{0} & mask) << first_bit;
return (pages[page] & mask2) != 0;

View File

@@ -191,6 +191,10 @@ public:
return device.CanReportMemoryUsage();
}
u32 GetStorageBufferAlignment() const {
return static_cast<u32>(device.GetShaderStorageBufferAlignment());
}
private:
static constexpr std::array PABO_LUT{
GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV,

View File

@@ -265,33 +265,33 @@ std::string Device::GetVendorName() const {
if (vendor_name == "Intel") {
// For Mesa, `Intel` is an overloaded vendor string that could mean crocus or iris.
// Simply return `INTEL` for those as well as the Windows driver.
return "INTEL";
return "Intel";
}
if (vendor_name == "Intel Open Source Technology Center") {
return "I965";
return "i965";
}
if (vendor_name == "Mesa Project") {
return "I915";
return "i915";
}
if (vendor_name == "Mesa/X.org") {
// This vendor string is overloaded between llvmpipe, softpipe, and virgl, so just return
// MESA instead of one of those driver names.
return "MESA";
return "Mesa";
}
if (vendor_name == "AMD") {
return "RADEONSI";
return "RadeonSI";
}
if (vendor_name == "nouveau") {
return "NOUVEAU";
return "Nouveau";
}
if (vendor_name == "X.Org") {
return "R600";
}
if (vendor_name == "Collabora Ltd") {
return "ZINK";
return "Zink";
}
if (vendor_name == "Intel Corporation") {
return "OPENSWR";
return "OpenSWR";
}
if (vendor_name == "Microsoft Corporation") {
return "D3D12";
@@ -300,7 +300,7 @@ std::string Device::GetVendorName() const {
// Mesa's tegra driver reports `NVIDIA`. Only present in this list because the default
// strategy would have returned `NVIDIA` here for this driver, the same result as the
// proprietary driver.
return "TEGRA";
return "Tegra";
}
return vendor_name;
}

View File

@@ -232,6 +232,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.has_gl_bool_ref_bug = device.HasBoolRefBug(),
.ignore_nan_fp_comparisons = true,
.gl_max_compute_smem_size = device.GetMaxComputeSharedMemorySize(),
.min_ssbo_alignment = device.GetShaderStorageBufferAlignment(),
},
host_info{
.support_float64 = true,
@@ -240,6 +241,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.needs_demote_reorder = device.IsAmd(),
.support_snorm_render_buffer = false,
.support_viewport_index_layer = device.HasVertexViewportLayer(),
.min_ssbo_alignment = static_cast<u32>(device.GetShaderStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
.support_conditional_barrier = device.SupportsConditionalBarriers(),
} {

View File

@@ -355,6 +355,10 @@ bool BufferCacheRuntime::CanReportMemoryUsage() const {
return device.CanReportMemoryUsage();
}
u32 BufferCacheRuntime::GetStorageBufferAlignment() const {
return static_cast<u32>(device.GetStorageBufferAlignment());
}
void BufferCacheRuntime::TickFrame(VideoCommon::SlotVector<Buffer>& slot_buffers) noexcept {
for (auto it = slot_buffers.begin(); it != slot_buffers.end(); it++) {
it->ResetUsageTracking();

View File

@@ -91,6 +91,8 @@ public:
bool CanReportMemoryUsage() const;
u32 GetStorageBufferAlignment() const;
[[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size, bool deferred = false);

View File

@@ -373,6 +373,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
.has_broken_robust =
device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal,
.min_ssbo_alignment = device.GetStorageBufferAlignment(),
};
host_info = Shader::HostTranslateInfo{
@@ -383,6 +384,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE,
.support_snorm_render_buffer = true,
.support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(),
.min_ssbo_alignment = static_cast<u32>(device.GetStorageBufferAlignment()),
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
.support_conditional_barrier = device.SupportsConditionalBarriers(),
};

View File

@@ -847,11 +847,41 @@ std::string Device::GetDriverName() const {
case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
return "NVIDIA";
case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS:
return "INTEL";
return "Intel";
case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA:
return "ANV";
case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
return "PowerVR";
case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
return "Qualcomm";
case VK_DRIVER_ID_ARM_PROPRIETARY:
return "Mali";
case VK_DRIVER_ID_GOOGLE_SWIFTSHADER:
return "SwiftShader";
case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
return "Broadcom";
case VK_DRIVER_ID_MESA_LLVMPIPE:
return "LAVAPIPE";
return "Lavapipe";
case VK_DRIVER_ID_MOLTENVK:
return "MoltenVK";
case VK_DRIVER_ID_VERISILICON_PROPRIETARY:
return "Vivante";
case VK_DRIVER_ID_MESA_TURNIP:
return "Turnip";
case VK_DRIVER_ID_MESA_V3DV:
return "V3DV";
case VK_DRIVER_ID_MESA_PANVK:
return "PanVK";
case VK_DRIVER_ID_MESA_VENUS:
return "Venus";
case VK_DRIVER_ID_MESA_DOZEN:
return "Dozen";
case VK_DRIVER_ID_MESA_NVK:
return "NVK";
case VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA:
return "PVR";
// case VK_DRIVER_ID_MESA_AGXV:
// return "Asahi";
default:
return properties.driver.driverName;
}

View File

@@ -386,7 +386,7 @@ if (NOT WIN32)
target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS})
endif()
if (UNIX AND NOT APPLE)
target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus)
target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus gamemode)
endif()
target_compile_definitions(yuzu PRIVATE

View File

@@ -36,12 +36,29 @@ ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::SetConfiguration() {}
void ConfigureGeneral::Setup(const ConfigurationShared::Builder& builder) {
QLayout& layout = *ui->general_widget->layout();
QLayout& general_layout = *ui->general_widget->layout();
QLayout& linux_layout = *ui->linux_widget->layout();
std::map<u32, QWidget*> hold{};
std::map<u32, QWidget*> general_hold{};
std::map<u32, QWidget*> linux_hold{};
for (const auto setting :
UISettings::values.linkage.by_category[Settings::Category::UiGeneral]) {
std::vector<Settings::BasicSetting*> settings;
auto push = [&settings](auto& list) {
for (auto setting : list) {
settings.push_back(setting);
}
};
push(UISettings::values.linkage.by_category[Settings::Category::UiGeneral]);
push(Settings::values.linkage.by_category[Settings::Category::Linux]);
// Only show Linux group on Unix
#ifndef __unix__
ui->LinuxGroupBox->setVisible(false);
#endif
for (const auto setting : settings) {
auto* widget = builder.BuildWidget(setting, apply_funcs);
if (widget == nullptr) {
@@ -52,11 +69,23 @@ void ConfigureGeneral::Setup(const ConfigurationShared::Builder& builder) {
continue;
}
hold.emplace(setting->Id(), widget);
switch (setting->GetCategory()) {
case Settings::Category::UiGeneral:
general_hold.emplace(setting->Id(), widget);
break;
case Settings::Category::Linux:
linux_hold.emplace(setting->Id(), widget);
break;
default:
widget->deleteLater();
}
}
for (const auto& [id, widget] : hold) {
layout.addWidget(widget);
for (const auto& [id, widget] : general_hold) {
general_layout.addWidget(widget);
}
for (const auto& [id, widget] : linux_hold) {
linux_layout.addWidget(widget);
}
}

View File

@@ -46,6 +46,33 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="LinuxGroupBox">
<property name="title">
<string>Linux</string>
</property>
<layout class="QVBoxLayout" name="LinuxVerticalLayout_1">
<item>
<widget class="QWidget" name="linux_widget" native="true">
<layout class="QVBoxLayout" name="LinuxVerticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@@ -57,7 +57,7 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="coreGroup">
<property name="title">
<string>Core</string>
</property>

View File

@@ -177,6 +177,9 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
INSERT(UISettings, controller_applet_disabled, tr("Disable controller applet"),
QStringLiteral());
// Linux
INSERT(Settings, enable_gamemode, tr("Enable Gamemode"), QStringLiteral());
// Ui Debugging
// Ui Multiplayer

View File

@@ -17,6 +17,7 @@
#ifdef __unix__
#include <csignal>
#include <sys/socket.h>
#include "common/linux/gamemode.h"
#endif
#include <boost/container/flat_set.hpp>
@@ -319,6 +320,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
provider{std::make_unique<FileSys::ManualContentProvider>()} {
#ifdef __unix__
SetupSigInterrupts();
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
#endif
system->Initialize();
@@ -2120,6 +2122,10 @@ void GMainWindow::OnEmulationStopped() {
discord_rpc->Update();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
// The emulation is stopped, so closing the window or not does not matter anymore
disconnect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
@@ -3502,6 +3508,10 @@ void GMainWindow::OnStartGame() {
play_time_manager->Start();
discord_rpc->Update();
#ifdef __unix__
Common::Linux::StartGamemode();
#endif
}
void GMainWindow::OnRestartGame() {
@@ -3522,6 +3532,10 @@ void GMainWindow::OnPauseGame() {
play_time_manager->Stop();
UpdateMenuState();
AllowOSSleep();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
}
void GMainWindow::OnPauseContinueGame() {
@@ -3803,6 +3817,9 @@ void GMainWindow::OnConfigure() {
const auto old_theme = UISettings::values.theme;
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
const auto old_language_index = Settings::values.language_index.GetValue();
#ifdef __unix__
const bool old_gamemode = Settings::values.enable_gamemode.GetValue();
#endif
Settings::SetConfiguringGlobal(true);
ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(),
@@ -3864,6 +3881,11 @@ void GMainWindow::OnConfigure() {
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) {
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
}
#ifdef __unix__
if (Settings::values.enable_gamemode.GetValue() != old_gamemode) {
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
}
#endif
if (!multiplayer_state->IsHostingPublicRoom()) {
multiplayer_state->UpdateCredentials();
@@ -5172,6 +5194,14 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
discord_rpc->Update();
}
#ifdef __unix__
void GMainWindow::SetGamemodeEnabled(bool state) {
if (emulation_running) {
Common::Linux::SetGamemodeState(state);
}
}
#endif
void GMainWindow::changeEvent(QEvent* event) {
#ifdef __unix__
// PaletteChange event appears to only reach so far into the GUI, explicitly asking to

View File

@@ -340,6 +340,7 @@ private:
void SetupSigInterrupts();
static void HandleSigInterrupt(int);
void OnSigInterruptNotifierActivated();
void SetGamemodeEnabled(bool state);
#endif
private slots:

View File

@@ -63,6 +63,10 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif
#ifdef __unix__
#include "common/linux/gamemode.h"
#endif
static void PrintHelp(const char* argv0) {
std::cout << "Usage: " << argv0
<< " [options] <filename>\n"
@@ -425,6 +429,10 @@ int main(int argc, char** argv) {
exit(0);
});
#ifdef __unix__
Common::Linux::StartGamemode();
#endif
void(system.Run());
if (system.DebuggerEnabled()) {
system.InitializeDebugger();
@@ -436,6 +444,10 @@ int main(int argc, char** argv) {
void(system.Pause());
system.ShutdownMainProcess();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
detached_tasks.WaitForAllTasks();
return 0;
}