Compare commits
31 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8212828221 | ||
|
|
ec73ccd582 | ||
|
|
11115d36e2 | ||
|
|
f1dd8f59a1 | ||
|
|
66a6014855 | ||
|
|
573061ed5a | ||
|
|
432afa1a52 | ||
|
|
96836e2710 | ||
|
|
9e6bd15bc9 | ||
|
|
9dc9aaf4af | ||
|
|
5eec980a2d | ||
|
|
aded28f276 | ||
|
|
80c4743754 | ||
|
|
498159d719 | ||
|
|
91ad6b7098 | ||
|
|
df49795bcb | ||
|
|
337e37f91d | ||
|
|
992ca8c358 | ||
|
|
7dddf5cb3c | ||
|
|
b8f66c9412 | ||
|
|
fd29227bc4 | ||
|
|
e21f96ffde | ||
|
|
1d11fe00a3 | ||
|
|
7c1cb5e8c9 | ||
|
|
ac11f6e4c5 | ||
|
|
40644d43f7 | ||
|
|
dfa56765d6 | ||
|
|
dee792937f | ||
|
|
75c5be55af | ||
|
|
735612c9b3 | ||
|
|
7d34800531 |
2
.github/workflows/android-build.yml
vendored
2
.github/workflows/android-build.yml
vendored
@@ -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'
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
119
.github/workflows/verify.yml
vendored
119
.github/workflows/verify.yml
vendored
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
4
externals/CMakeLists.txt
vendored
4
externals/CMakeLists.txt
vendored
@@ -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
11
externals/gamemode/CMakeLists.txt
vendored
Normal 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)
|
||||
379
externals/gamemode/include/gamemode_client.h
vendored
Normal file
379
externals/gamemode/include/gamemode_client.h
vendored
Normal 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
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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>()
|
||||
|
||||
215
src/android/app/src/main/jni/prod.keys
Normal file
215
src/android/app/src/main/jni/prod.keys
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -541,7 +541,7 @@ public:
|
||||
if (write) {
|
||||
flags |= PROT_WRITE;
|
||||
}
|
||||
#ifdef ARCHITECTURE_arm64
|
||||
#ifdef HAS_NCE
|
||||
if (execute) {
|
||||
flags |= PROT_EXEC;
|
||||
}
|
||||
|
||||
40
src/common/linux/gamemode.cpp
Normal file
40
src/common/linux/gamemode.cpp
Normal 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
|
||||
24
src/common/linux/gamemode.h
Normal file
24
src/common/linux/gamemode.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ enum class Category : u32 {
|
||||
Multiplayer,
|
||||
Services,
|
||||
Paths,
|
||||
Linux,
|
||||
MaxEnum,
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
} {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="coreGroup">
|
||||
<property name="title">
|
||||
<string>Core</string>
|
||||
</property>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -340,6 +340,7 @@ private:
|
||||
void SetupSigInterrupts();
|
||||
static void HandleSigInterrupt(int);
|
||||
void OnSigInterruptNotifierActivated();
|
||||
void SetGamemodeEnabled(bool state);
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user