forked from eden-emu/eden
Compare commits
4 commits
master
...
Qlaunch-20
Author | SHA1 | Date | |
---|---|---|---|
![]() |
19387c61fc | ||
![]() |
7db430f794 | ||
![]() |
71297b6507 | ||
![]() |
eadefce244 |
127 changed files with 1066 additions and 3110 deletions
|
@ -1,8 +1,5 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
export NDK_CCACHE=$(which ccache)
|
||||
|
||||
# keystore & pass are stored locally
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
GITDATE="$(git show -s --date=short --format='%ad' | sed 's/-//g')"
|
||||
GITREV="$(git show -s --format='%h')"
|
||||
ARTIFACTS_DIR="$PWD/artifacts"
|
||||
mkdir -p "${ARTIFACTS_DIR}/"
|
||||
|
||||
REV_NAME="eden-android-${GITDATE}-${GITREV}"
|
||||
BUILD_FLAVOR="mainline"
|
||||
BUILD_TYPE_LOWER="release"
|
||||
BUILD_TYPE_UPPER="Release"
|
||||
|
||||
cp src/android/app/build/outputs/apk/"${BUILD_FLAVOR}/${BUILD_TYPE_LOWER}/app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.apk" \
|
||||
"${ARTIFACTS_DIR}/${REV_NAME}.apk" || echo "APK not found"
|
||||
|
||||
cp src/android/app/build/outputs/bundle/"${BUILD_FLAVOR}${BUILD_TYPE_UPPER}"/"app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.aab" \
|
||||
"${ARTIFACTS_DIR}/${REV_NAME}.aab" || echo "AAB not found"
|
||||
|
||||
ls -la "${ARTIFACTS_DIR}/"
|
0
.ci/windows/install-vulkan-sdk.ps1 → .ci/install-vulkan-sdk.ps1
Executable file → Normal file
0
.ci/windows/install-vulkan-sdk.ps1 → .ci/install-vulkan-sdk.ps1
Executable file → Normal file
|
@ -1,8 +1,5 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
export ARCH="$(uname -m)"
|
||||
|
||||
if [ "$ARCH" = 'x86_64' ]; then
|
|
@ -1,8 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This script assumes you're in the source directory
|
||||
set -ex
|
||||
|
||||
|
@ -116,7 +113,7 @@ echo "Generating AppImage..."
|
|||
./uruntime --appimage-mkdwarfs -f \
|
||||
--set-owner 0 --set-group 0 \
|
||||
--no-history --no-create-timestamp \
|
||||
--categorize=hotness --hotness-list=.ci/linux/eden.dwfsprof \
|
||||
--categorize=hotness --hotness-list=.ci/eden.dwfsprof \
|
||||
--compression zstd:level=22 -S26 -B32 \
|
||||
--header uruntime \
|
||||
-N 4 \
|
|
@ -1,27 +0,0 @@
|
|||
echo off
|
||||
|
||||
set chain=%1
|
||||
|
||||
if not defined DevEnvDir (
|
||||
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" %chain%
|
||||
)
|
||||
|
||||
mkdir build
|
||||
|
||||
cmake -S . -B build\%chain% ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DYUZU_USE_BUNDLED_QT=ON ^
|
||||
-DENABLE_QT_TRANSLATION=ON ^
|
||||
-DUSE_DISCORD_PRESENCE=ON ^
|
||||
-DYUZU_USE_BUNDLED_VCPKG=ON ^
|
||||
-DYUZU_USE_BUNDLED_SDL2=ON ^
|
||||
-G "Ninja" ^
|
||||
-DYUZU_TESTS=OFF ^
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache ^
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache ^
|
||||
-DCMAKE_TOOLCHAIN_FILE="%CD%\CMakeModules\MSVCCache.cmake" ^
|
||||
-DUSE_CCACHE=ON
|
||||
|
||||
cmake --build build\%chain%
|
||||
|
||||
ccache -s -v
|
|
@ -1,31 +0,0 @@
|
|||
echo off
|
||||
|
||||
set chain=%1
|
||||
set qt_ver=%2
|
||||
|
||||
if not defined DevEnvDir (
|
||||
CALL "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" %chain%
|
||||
)
|
||||
|
||||
CALL mkdir build
|
||||
|
||||
CALL cmake -S . -B build\%chain% ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DYUZU_USE_BUNDLED_QT=ON ^
|
||||
-DENABLE_QT_TRANSLATION=ON ^
|
||||
-DUSE_DISCORD_PRESENCE=ON ^
|
||||
-DYUZU_USE_BUNDLED_VCPKG=ON ^
|
||||
-DYUZU_USE_BUNDLED_SDL2=ON ^
|
||||
-G "Ninja" ^
|
||||
-DYUZU_TESTS=OFF ^
|
||||
-DUSE_BUNDLED_QT=OFF ^
|
||||
-DUSE_SYSTEM_QT=ON ^
|
||||
-DCMAKE_PREFIX_PATH=C:\Qt\%qt_ver%\msvc2022_64 ^
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache ^
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache ^
|
||||
-DCMAKE_TOOLCHAIN_FILE="%CD%\CMakeModules\MSVCCache.cmake" ^
|
||||
-DUSE_CCACHE=ON
|
||||
|
||||
CALL cmake --build build\%chain%
|
||||
|
||||
CALL ccache -s -v
|
|
@ -1,19 +0,0 @@
|
|||
echo off
|
||||
|
||||
call C:\tools\cygwin\cygwinsetup.exe -q -P autoconf,automake,libtool,make,pkg-config
|
||||
|
||||
REM Create wrapper batch files for Cygwin tools in a directory that will be in PATH
|
||||
REM uncomment this for first-run only
|
||||
REM call mkdir C:\cygwin-wrappers
|
||||
|
||||
REM Create autoconf.bat wrapper
|
||||
call echo @echo off > C:\cygwin-wrappers\autoconf.bat
|
||||
call echo C:\tools\cygwin\bin\bash.exe -l -c "autoconf %%*" >> C:\cygwin-wrappers\autoconf.bat
|
||||
|
||||
REM Add other wrappers if needed for other Cygwin tools
|
||||
call echo @echo off > C:\cygwin-wrappers\automake.bat
|
||||
call echo C:\tools\cygwin\bin\bash.exe -l -c "automake %%*" >> C:\cygwin-wrappers\automake.bat
|
||||
|
||||
REM Add the wrappers directory to PATH
|
||||
call echo C:\cygwin-wrappers>>"%GITHUB_PATH%"
|
||||
call echo C:\tools\cygwin\bin>>"%GITHUB_PATH%"
|
|
@ -1,41 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
$target=$args[0]
|
||||
$debug=$args[1]
|
||||
|
||||
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-", ""
|
||||
$GITREV = $(git show -s --format='%h')
|
||||
$RELEASE_DIST = "eden-windows-msvc"
|
||||
$ARTIFACTS_DIR = "artifacts"
|
||||
|
||||
New-Item -ItemType Directory -Path $ARTIFACTS_DIR -Force
|
||||
New-Item -ItemType Directory -Path $RELEASE_DIST -Force
|
||||
|
||||
if ($debug -eq "yes") {
|
||||
mkdir -p pdb
|
||||
$BUILD_PDB = "eden-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip"
|
||||
Get-ChildItem "build/$target/bin/" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb -ErrorAction SilentlyContinue
|
||||
|
||||
if (Test-Path -Path ".\pdb\*.pdb") {
|
||||
7z a -tzip $BUILD_PDB .\pdb\*.pdb
|
||||
Move-Item $BUILD_PDB $ARTIFACTS_DIR/ -ErrorAction SilentlyContinue
|
||||
}
|
||||
} else {
|
||||
Get-ChildItem "build/$target/bin/" -Recurse -Filter "*.pdb" | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Copy-Item "build/$target/bin/Release/*" -Destination "$RELEASE_DIST" -Recurse -ErrorAction SilentlyContinue
|
||||
if (-not $?) {
|
||||
# Try without Release subfolder if that doesn't exist
|
||||
Copy-Item "build/$target/bin/*" -Destination "$RELEASE_DIST" -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
|
||||
$BUILD_ZIP = "eden-windows-msvc-$GITDATE-$GITREV.zip"
|
||||
|
||||
7z a -tzip $BUILD_ZIP $RELEASE_DIST\*
|
||||
|
||||
Move-Item $BUILD_ZIP $ARTIFACTS_DIR/ -Force #-ErrorAction SilentlyContinue
|
||||
Copy-Item "LICENSE*" -Destination "$RELEASE_DIST" -ErrorAction SilentlyContinue
|
||||
Copy-Item "README*" -Destination "$RELEASE_DIST" -ErrorAction SilentlyContinue
|
115
.github/workflows/build.yml
vendored
115
.github/workflows/build.yml
vendored
|
@ -5,10 +5,10 @@ name: eden-build
|
|||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
tags: [ "*" ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
# TODO: combine build.yml into trigger_release.yml
|
||||
jobs:
|
||||
source:
|
||||
if: ${{ !github.head_ref }}
|
||||
|
@ -24,7 +24,6 @@ jobs:
|
|||
with:
|
||||
name: source.zip
|
||||
path: artifacts/
|
||||
|
||||
windows:
|
||||
runs-on: windows
|
||||
strategy:
|
||||
|
@ -44,7 +43,6 @@ jobs:
|
|||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up vcpkg cache
|
||||
uses: actions/cache@v4
|
||||
|
@ -61,25 +59,96 @@ jobs:
|
|||
uses: https://github.com/ilammy/msvc-dev-cmd@v1
|
||||
if: ${{ matrix.target == 'msvc' }}
|
||||
|
||||
# - name: Install extra tools
|
||||
# run: choco install ccache ninja wget cygwin
|
||||
# if: ${{ matrix.target == 'msvc' }}
|
||||
|
||||
# - name: Install vulkan-SDK
|
||||
# run: ./.ci/install-vulkan-sdk.ps1
|
||||
# shell: powershell
|
||||
|
||||
- name: Cygwin with autoconf # NEEDED FOR LIBUSB
|
||||
shell: cmd
|
||||
run: ./.ci/windows/cygwin.bat
|
||||
run: |
|
||||
C:\tools\cygwin\cygwinsetup.exe -q -P autoconf,automake,libtool,make,pkg-config
|
||||
|
||||
- name: Configure & Build
|
||||
REM Create wrapper batch files for Cygwin tools in a directory that will be in PATH
|
||||
REM mkdir C:\cygwin-wrappers
|
||||
|
||||
REM Create autoconf.bat wrapper
|
||||
echo @echo off > C:\cygwin-wrappers\autoconf.bat
|
||||
echo C:\tools\cygwin\bin\bash.exe -l -c "autoconf %%*" >> C:\cygwin-wrappers\autoconf.bat
|
||||
|
||||
REM Add other wrappers if needed for other Cygwin tools
|
||||
echo @echo off > C:\cygwin-wrappers\automake.bat
|
||||
echo C:\tools\cygwin\bin\bash.exe -l -c "automake %%*" >> C:\cygwin-wrappers\automake.bat
|
||||
|
||||
REM Add the wrappers directory to PATH
|
||||
echo C:\cygwin-wrappers>>"%GITHUB_PATH%"
|
||||
echo C:\tools\cygwin\bin>>"%GITHUB_PATH%"
|
||||
|
||||
- name: CMake Configure
|
||||
id: cmake
|
||||
shell: cmd
|
||||
run: ./.ci/windows/build-bqt.bat amd64 yes
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_TOOLCHAIN_FILE="%CD%\..\CMakeModules\MSVCCache.cmake" -DYUZU_USE_BUNDLED_QT=ON -DENABLE_QT_TRANSLATION=ON -DUSE_DISCORD_PRESENCE=ON -DYUZU_USE_BUNDLED_VCPKG=ON -DYUZU_USE_BUNDLED_SDL2=ON -DUSE_CCACHE=ON
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
shell: cmd
|
||||
run: |
|
||||
cd build
|
||||
ninja yuzu yuzu-cmd yuzu-room tests
|
||||
ccache -s -v
|
||||
|
||||
- name: Package artifacts
|
||||
if: steps.build.outcome == 'success'
|
||||
shell: powershell
|
||||
run: ./.ci/windows/package.ps1 amd64 yes
|
||||
run: |
|
||||
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-", ""
|
||||
$GITREV = $(git show -s --format='%h')
|
||||
$RELEASE_DIST = "eden-windows-msvc"
|
||||
$ARTIFACTS_DIR = "${{ github.workspace }}/artifacts"
|
||||
|
||||
mkdir -p $ARTIFACTS_DIR
|
||||
mkdir -p $RELEASE_DIST
|
||||
mkdir -p pdb
|
||||
|
||||
Copy-Item "build/bin/Release/*" -Destination "$RELEASE_DIST" -Recurse -ErrorAction SilentlyContinue
|
||||
if (-not $?) {
|
||||
# Try without Release subfolder if that doesn't exist
|
||||
Copy-Item "build/bin/*" -Destination "$RELEASE_DIST" -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Get-ChildItem "build/bin/" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb -ErrorAction SilentlyContinue
|
||||
|
||||
$BUILD_ZIP = "eden-windows-msvc-$GITDATE-$GITREV.zip"
|
||||
$BUILD_PDB = "eden-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip"
|
||||
$BUILD_7Z = "eden-windows-msvc-$GITDATE-$GITREV.7z"
|
||||
|
||||
7z a -tzip $BUILD_ZIP $RELEASE_DIST\*
|
||||
|
||||
if (Test-Path -Path ".\pdb\*.pdb") {
|
||||
7z a -tzip $BUILD_PDB .\pdb\*.pdb
|
||||
Move-Item $BUILD_PDB $ARTIFACTS_DIR/ -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
7z a $BUILD_7Z $RELEASE_DIST
|
||||
|
||||
Move-Item $BUILD_ZIP $ARTIFACTS_DIR/ -ErrorAction SilentlyContinue
|
||||
Move-Item $BUILD_7Z $ARTIFACTS_DIR/ -ErrorAction SilentlyContinue
|
||||
|
||||
Copy-Item "LICENSE*" -Destination "$RELEASE_DIST" -ErrorAction SilentlyContinue
|
||||
Copy-Item "README*" -Destination "$RELEASE_DIST" -ErrorAction SilentlyContinue
|
||||
|
||||
- name: Upload Windows artifacts
|
||||
if: steps.build.outcome == 'success'
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.target }}.zip
|
||||
path: artifacts/*
|
||||
|
||||
linux:
|
||||
runs-on: linux
|
||||
env:
|
||||
|
@ -92,14 +161,16 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-depth: 1
|
||||
fetch-tags: true
|
||||
|
||||
- name: Build
|
||||
run: ./.ci/linux/build.sh v3 8
|
||||
run: |
|
||||
./.ci/linux.sh v3 8
|
||||
|
||||
- name: Package AppImage
|
||||
run: ./.ci/linux/package.sh v3 &> /dev/null
|
||||
run: |
|
||||
./.ci/package-appimage.sh v3 &> /dev/null
|
||||
|
||||
- name: Upload Linux artifacts
|
||||
uses: forgejo/upload-artifact@v4
|
||||
|
@ -122,7 +193,6 @@ jobs:
|
|||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set tag name
|
||||
run: |
|
||||
|
@ -132,10 +202,27 @@ jobs:
|
|||
echo $GIT_TAG_NAME
|
||||
|
||||
- name: Build
|
||||
run: JAVA_HOME=$JAVA_HOME_21_X64 ./.ci/android/build.sh
|
||||
run: JAVA_HOME=$JAVA_HOME_21_X64 ./.ci/android.sh
|
||||
|
||||
- name: Package Android artifacts
|
||||
run: ./.ci/android/package.sh
|
||||
run: |
|
||||
GITDATE="$(git show -s --date=short --format='%ad' | sed 's/-//g')"
|
||||
GITREV="$(git show -s --format='%h')"
|
||||
ARTIFACTS_DIR="$PWD/artifacts"
|
||||
mkdir -p "${ARTIFACTS_DIR}/"
|
||||
|
||||
REV_NAME="eden-android-${GITDATE}-${GITREV}"
|
||||
BUILD_FLAVOR="mainline"
|
||||
BUILD_TYPE_LOWER="release"
|
||||
BUILD_TYPE_UPPER="Release"
|
||||
|
||||
cp src/android/app/build/outputs/apk/"${BUILD_FLAVOR}/${BUILD_TYPE_LOWER}/app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.apk" \
|
||||
"${ARTIFACTS_DIR}/${REV_NAME}.apk" || echo "APK not found"
|
||||
|
||||
cp src/android/app/build/outputs/bundle/"${BUILD_FLAVOR}${BUILD_TYPE_UPPER}"/"app-${BUILD_FLAVOR}-${BUILD_TYPE_LOWER}.aab" \
|
||||
"${ARTIFACTS_DIR}/${REV_NAME}.aab" || echo "AAB not found"
|
||||
|
||||
ls -la "${ARTIFACTS_DIR}/"
|
||||
|
||||
- name: Upload Android artifacts
|
||||
uses: forgejo/upload-artifact@v4
|
||||
|
|
193
.github/workflows/trigger_release.yml
vendored
193
.github/workflows/trigger_release.yml
vendored
|
@ -1,193 +0,0 @@
|
|||
name: Build Application and Make Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ "*" ]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
source:
|
||||
runs-on: linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Pack
|
||||
run: ./.ci/source.sh
|
||||
- name: Upload
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: source.zip
|
||||
path: artifacts/
|
||||
|
||||
windows:
|
||||
runs-on: windows
|
||||
strategy:
|
||||
matrix:
|
||||
target: ["msvc"] # TODO: Add msys2
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ (matrix.target == 'msys2' && 'msys2') || 'bash' }} {0}
|
||||
env:
|
||||
CCACHE_DIR: ${{ runner.workspace }}/.cache/.ccache
|
||||
CCACHE_COMPILERCHECK: content
|
||||
CCACHE_SLOPPINESS: time_macros
|
||||
OS: windows
|
||||
TARGET: ${{ matrix.target }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up vcpkg cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/build/vcpkg_installed
|
||||
${{ github.workspace }}/build/externals
|
||||
${{ github.workspace }}/.vcpkg
|
||||
key: ${{ runner.os }}-${{ matrix.target }}-vcpkg-${{ hashFiles('**/CMakeLists.txt', '**/vcpkg.json') }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.target }}-vcpkg-
|
||||
|
||||
- name: Set up MSVC
|
||||
uses: https://github.com/ilammy/msvc-dev-cmd@v1
|
||||
if: ${{ matrix.target == 'msvc' }}
|
||||
|
||||
- name: Cygwin with autoconf # NEEDED FOR LIBUSB
|
||||
shell: cmd
|
||||
run: ./.ci/windows/cygwin.bat
|
||||
|
||||
- name: Configure & Build
|
||||
id: cmake
|
||||
shell: cmd
|
||||
run: ./.ci/windows/build-bqt.bat amd64 no
|
||||
|
||||
- name: Package artifacts
|
||||
shell: powershell
|
||||
run: ./.ci/windows/package.ps1 amd64 no
|
||||
|
||||
- name: Upload Windows artifacts
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.target }}.zip
|
||||
path: artifacts/*
|
||||
|
||||
linux:
|
||||
runs-on: linux
|
||||
env:
|
||||
CCACHE_DIR: /home/runner/.cache/ccache
|
||||
CCACHE_COMPILERCHECK: content
|
||||
CCACHE_SLOPPINESS: time_macros
|
||||
OS: linux
|
||||
TARGET: fresh
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Build
|
||||
run: ./.ci/linux/build.sh v3 8
|
||||
|
||||
- name: Package AppImage
|
||||
run: ./.ci/linux/package.sh v3 &> /dev/null
|
||||
|
||||
- name: Upload Linux artifacts
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: linux.zip
|
||||
path: ./*.AppImage
|
||||
|
||||
android:
|
||||
runs-on: android
|
||||
|
||||
env:
|
||||
CCACHE_DIR: /home/runner/.cache/ccache
|
||||
CCACHE_COMPILERCHECK: content
|
||||
CCACHE_SLOPPINESS: time_macros
|
||||
OS: android
|
||||
TARGET: universal
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set tag name
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
|
||||
echo "GIT_TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
|
||||
fi
|
||||
echo $GIT_TAG_NAME
|
||||
|
||||
- name: Build
|
||||
run: JAVA_HOME=$JAVA_HOME_21_X64 ./.ci/android/build.sh
|
||||
|
||||
- name: Package Android artifacts
|
||||
run: ./.ci/android/package.sh
|
||||
|
||||
- name: Upload Android artifacts
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: android.zip
|
||||
path: artifacts/*
|
||||
|
||||
create_release:
|
||||
needs: [linux, windows, android]
|
||||
runs-on: linux
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
path: 'eden-source'
|
||||
|
||||
- name: Download artifacts
|
||||
uses: forgejo/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Grab and store version
|
||||
run: |
|
||||
cd eden-source
|
||||
tag_name=$(git describe --tags --abbrev=0)
|
||||
echo "VERSION=$tag_name" >> $GITHUB_ENV
|
||||
echo $tag_name
|
||||
|
||||
- name: Package artifacts properly
|
||||
shell: bash
|
||||
run: |
|
||||
set -ex
|
||||
mv ${{ github.workspace }}/eden-source eden-${{ env.VERSION }}
|
||||
cd artifacts
|
||||
ls *.zip
|
||||
|
||||
mkdir -p dist
|
||||
|
||||
cp linux.zip/Eden-*.AppImage dist/Eden-Linux-${{ env.VERSION }}-amd64.AppImage
|
||||
cp msvc.zip/eden-windows-msvc*.zip dist/Eden-Windows-MSVC-${{ env.VERSION }}-amd64.zip
|
||||
cp android.zip/eden-android*.apk dist/Eden-Android-${{ env.VERSION }}.apk
|
||||
cp android.zip/eden-android*.aab dist/Eden-Android-${{ env.VERSION }}.aab
|
||||
cp source.zip/eden-unified-source*.tar.xz dist/Eden-Source-${{ env.VERSION }}.tar.xz
|
||||
cp source.zip/eden-unified-source*.tar.xz.sha256sum dist/Eden-Source-${{ env.VERSION }}.tar.xz.sha256sum
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: actions/forgejo-release@v2.6.0
|
||||
with:
|
||||
direction: upload
|
||||
tag: ${{ env.VERSION }}
|
||||
title: Eden ${{ env.VERSION }}
|
||||
release-dir: artifacts/dist/
|
|
@ -73,6 +73,8 @@ option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF)
|
|||
|
||||
option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" OFF)
|
||||
|
||||
option(YUZU_LOG_BY_LINE "Flush log data by the line rather than 4KB buffers" OFF)
|
||||
|
||||
option(YUZU_ENABLE_PORTABLE "Allow yuzu to enable portable mode if a user folder is found in the CWD" ON)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
||||
|
@ -285,6 +287,10 @@ if (ARCHITECTURE_arm64 AND (ANDROID OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
|||
add_definitions(-DHAS_NCE=1)
|
||||
endif()
|
||||
|
||||
if (YUZU_LOG_BY_LINE)
|
||||
add_definitions(-DYUZU_LOG_BY_LINE=1)
|
||||
endif()
|
||||
|
||||
# Configure C++ standard
|
||||
# ===========================
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project
|
||||
# SPDX-FileCopyrightText: 2024 kleidis
|
||||
|
||||
function(copy_yuzu_Qt6_deps target_dir)
|
||||
|
@ -24,12 +25,12 @@ function(copy_yuzu_Qt6_deps target_dir)
|
|||
Qt6Widgets$<$<CONFIG:Debug>:d>.*
|
||||
Qt6Network$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
if (YUZU_USE_QT_MULTIMEDIA)
|
||||
if (CITRON_USE_QT_MULTIMEDIA)
|
||||
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
|
||||
Qt6Multimedia$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
endif()
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
if (CITRON_USE_QT_WEB_ENGINE)
|
||||
windows_copy_files(${target_dir} ${Qt6_DLL_DIR} ${DLL_DEST}
|
||||
Qt6WebEngineCore$<$<CONFIG:Debug>:d>.*
|
||||
Qt6WebEngineWidgets$<$<CONFIG:Debug>:d>.*
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2024 Citron HomeBrew Emulator Project
|
||||
# SPDX-FileCopyrightText: 2024 kleidis
|
||||
|
||||
[aqt]
|
||||
|
|
2
externals/ffmpeg/ffmpeg
vendored
2
externals/ffmpeg/ffmpeg
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 62e1c442633e8a09a1407a789cd2b50611850788
|
||||
Subproject commit 9c1294eaddb88cb0e044c675ccae059a85fc9c6c
|
|
@ -62,7 +62,7 @@ if (MSVC)
|
|||
|
||||
# Warnings
|
||||
/W4
|
||||
/WX-
|
||||
/WX
|
||||
|
||||
/we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
|
||||
/we4189 # 'identifier': local variable is initialized but not referenced
|
||||
|
|
|
@ -14,7 +14,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu
|
||||
|
||||
import android.content.DialogInterface
|
||||
|
@ -25,7 +21,6 @@ import org.yuzu.yuzu_emu.utils.Log
|
|||
import org.yuzu.yuzu_emu.model.InstallResult
|
||||
import org.yuzu.yuzu_emu.model.Patch
|
||||
import org.yuzu.yuzu_emu.model.GameVerificationResult
|
||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||
|
||||
/**
|
||||
* Class which contains methods that interact
|
||||
|
@ -247,27 +242,6 @@ object NativeLibrary {
|
|||
return coreErrorAlertResult
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun addNetPlayMessage(type: Int, message: String) {
|
||||
val emulationActivity = sEmulationActivity.get()
|
||||
if (emulationActivity != null) {
|
||||
emulationActivity.addNetPlayMessages(type, message)
|
||||
}
|
||||
else {
|
||||
NetPlayManager.addNetPlayMessage(type, message)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun clearChat() {
|
||||
NetPlayManager.clearChat()
|
||||
}
|
||||
|
||||
|
||||
external fun netPlayInit()
|
||||
|
||||
@Keep
|
||||
@JvmStatic
|
||||
fun exitEmulationActivity(resultCode: Int) {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
|
@ -43,14 +39,12 @@ import org.yuzu.yuzu_emu.NativeLibrary
|
|||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityEmulationBinding
|
||||
import org.yuzu.yuzu_emu.dialogs.NetPlayDialog
|
||||
import org.yuzu.yuzu_emu.features.input.NativeInput
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.model.EmulationViewModel
|
||||
import org.yuzu.yuzu_emu.model.Game
|
||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.MemoryUtil
|
||||
|
@ -411,16 +405,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
|
||||
fun displayMultiplayerDialog() {
|
||||
val dialog = NetPlayDialog(this)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun addNetPlayMessages(type: Int, msg: String) {
|
||||
NetPlayManager.addNetPlayMessage(type, msg)
|
||||
}
|
||||
|
||||
|
||||
private var pictureInPictureReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent) {
|
||||
if (intent.action == actionPlay) {
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.DialogChatBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ItemChatMessageBinding
|
||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class ChatMessage(
|
||||
val nickname: String, // This is the common name youll see on private servers
|
||||
val username: String, // Username is the community/forum username
|
||||
val message: String,
|
||||
val timestamp: String = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date())
|
||||
) {
|
||||
}
|
||||
|
||||
class ChatDialog(context: Context) : BottomSheetDialog(context) {
|
||||
private lateinit var binding: DialogChatBinding
|
||||
private lateinit var chatAdapter: ChatAdapter
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = DialogChatBinding.inflate(LayoutInflater.from(context))
|
||||
setContentView(binding.root)
|
||||
|
||||
NetPlayManager.setChatOpen(true)
|
||||
setupRecyclerView()
|
||||
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
|
||||
handler.post {
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
binding.chatRecyclerView.post {
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
NetPlayManager.setOnMessageReceivedListener { type, message ->
|
||||
handler.post {
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
binding.sendButton.setOnClickListener {
|
||||
val message = binding.chatInput.text.toString()
|
||||
if (message.isNotBlank()) {
|
||||
sendMessage(message)
|
||||
binding.chatInput.text?.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
NetPlayManager.setChatOpen(false)
|
||||
super.dismiss()
|
||||
}
|
||||
|
||||
private fun sendMessage(message: String) {
|
||||
val username = NetPlayManager.getUsername(context)
|
||||
NetPlayManager.netPlaySendMessage(message)
|
||||
|
||||
val chatMessage = ChatMessage(
|
||||
nickname = username,
|
||||
username = "",
|
||||
message = message,
|
||||
timestamp = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date())
|
||||
)
|
||||
|
||||
NetPlayManager.addChatMessage(chatMessage)
|
||||
chatAdapter.notifyDataSetChanged()
|
||||
scrollToBottom()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
chatAdapter = ChatAdapter(NetPlayManager.getChatMessages())
|
||||
binding.chatRecyclerView.layoutManager = LinearLayoutManager(context).apply {
|
||||
stackFromEnd = true
|
||||
}
|
||||
binding.chatRecyclerView.adapter = chatAdapter
|
||||
}
|
||||
|
||||
private fun scrollToBottom() {
|
||||
binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class ChatAdapter(private val messages: List<ChatMessage>) :
|
||||
RecyclerView.Adapter<ChatAdapter.ChatViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder {
|
||||
val binding = ItemChatMessageBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return ChatViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = messages.size
|
||||
|
||||
override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
|
||||
holder.bind(messages[position])
|
||||
}
|
||||
|
||||
inner class ChatViewHolder(private val binding: ItemChatMessageBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(message: ChatMessage) {
|
||||
binding.usernameText.text = message.nickname
|
||||
binding.messageText.text = message.message
|
||||
binding.userIcon.setImageResource(when (message.nickname) {
|
||||
"System" -> R.drawable.ic_system
|
||||
else -> R.drawable.ic_user
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,400 +0,0 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.databinding.DialogMultiplayerConnectBinding
|
||||
import org.yuzu.yuzu_emu.databinding.DialogMultiplayerLobbyBinding
|
||||
import org.yuzu.yuzu_emu.databinding.DialogMultiplayerRoomBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ItemBanListBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ItemButtonNetplayBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ItemTextNetplayBinding
|
||||
import org.yuzu.yuzu_emu.utils.CompatUtils
|
||||
import org.yuzu.yuzu_emu.network.NetPlayManager
|
||||
|
||||
class NetPlayDialog(context: Context) : BottomSheetDialog(context) {
|
||||
private lateinit var adapter: NetPlayAdapter
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
when {
|
||||
NetPlayManager.netPlayIsJoined() -> DialogMultiplayerLobbyBinding.inflate(layoutInflater)
|
||||
.apply {
|
||||
setContentView(root)
|
||||
adapter = NetPlayAdapter()
|
||||
listMultiplayer.layoutManager = LinearLayoutManager(context)
|
||||
listMultiplayer.adapter = adapter
|
||||
adapter.loadMultiplayerMenu()
|
||||
btnLeave.setOnClickListener {
|
||||
NetPlayManager.netPlayLeaveRoom()
|
||||
dismiss()
|
||||
}
|
||||
btnChat.setOnClickListener {
|
||||
ChatDialog(context).show()
|
||||
}
|
||||
|
||||
refreshAdapterItems()
|
||||
|
||||
btnModeration.visibility = if (NetPlayManager.netPlayIsModerator()) View.VISIBLE else View.GONE
|
||||
btnModeration.setOnClickListener {
|
||||
showModerationDialog()
|
||||
}
|
||||
|
||||
}
|
||||
else -> {
|
||||
DialogMultiplayerConnectBinding.inflate(layoutInflater).apply {
|
||||
setContentView(root)
|
||||
btnCreate.setOnClickListener {
|
||||
showNetPlayInputDialog(true)
|
||||
dismiss()
|
||||
}
|
||||
btnJoin.setOnClickListener {
|
||||
showNetPlayInputDialog(false)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class NetPlayItems(
|
||||
val option: Int,
|
||||
val name: String,
|
||||
val type: Int,
|
||||
val id: Int = 0
|
||||
) {
|
||||
companion object {
|
||||
const val MULTIPLAYER_ROOM_TEXT = 1
|
||||
const val MULTIPLAYER_ROOM_MEMBER = 2
|
||||
const val MULTIPLAYER_SEPARATOR = 3
|
||||
const val MULTIPLAYER_ROOM_COUNT = 4
|
||||
const val TYPE_BUTTON = 0
|
||||
const val TYPE_TEXT = 1
|
||||
const val TYPE_SEPARATOR = 2
|
||||
}
|
||||
}
|
||||
|
||||
inner class NetPlayAdapter : RecyclerView.Adapter<NetPlayAdapter.NetPlayViewHolder>() {
|
||||
val netPlayItems = mutableListOf<NetPlayItems>()
|
||||
|
||||
abstract inner class NetPlayViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
}
|
||||
abstract fun bind(item: NetPlayItems)
|
||||
}
|
||||
|
||||
inner class TextViewHolder(private val binding: ItemTextNetplayBinding) : NetPlayViewHolder(binding.root) {
|
||||
private lateinit var netPlayItem: NetPlayItems
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
override fun bind(item: NetPlayItems) {
|
||||
netPlayItem = item
|
||||
binding.itemTextNetplayName.text = item.name
|
||||
binding.itemIcon.apply {
|
||||
val iconRes = when (item.option) {
|
||||
NetPlayItems.MULTIPLAYER_ROOM_TEXT -> R.drawable.ic_system
|
||||
NetPlayItems.MULTIPLAYER_ROOM_COUNT -> R.drawable.ic_two_users
|
||||
else -> 0
|
||||
}
|
||||
visibility = if (iconRes != 0) {
|
||||
setImageResource(iconRes)
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ButtonViewHolder(private val binding: ItemButtonNetplayBinding) : NetPlayViewHolder(binding.root) {
|
||||
private lateinit var netPlayItems: NetPlayItems
|
||||
private val isModerator = NetPlayManager.netPlayIsModerator()
|
||||
|
||||
init {
|
||||
binding.itemButtonMore.apply {
|
||||
visibility = View.VISIBLE
|
||||
setOnClickListener { showPopupMenu(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
|
||||
private fun showPopupMenu(view: View) {
|
||||
PopupMenu(view.context, view).apply {
|
||||
menuInflater.inflate(R.menu.menu_netplay_member, menu)
|
||||
menu.findItem(R.id.action_kick).isEnabled = isModerator &&
|
||||
netPlayItems.name != NetPlayManager.getUsername(context)
|
||||
menu.findItem(R.id.action_ban).isEnabled = isModerator &&
|
||||
netPlayItems.name != NetPlayManager.getUsername(context)
|
||||
setOnMenuItemClickListener { item ->
|
||||
if (item.itemId == R.id.action_kick) {
|
||||
NetPlayManager.netPlayKickUser(netPlayItems.name)
|
||||
true
|
||||
} else if (item.itemId == R.id.action_ban) {
|
||||
NetPlayManager.netPlayBanUser(netPlayItems.name)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(item: NetPlayItems) {
|
||||
netPlayItems = item
|
||||
binding.itemButtonNetplayName.text = netPlayItems.name
|
||||
}
|
||||
}
|
||||
|
||||
fun loadMultiplayerMenu() {
|
||||
val infos = NetPlayManager.netPlayRoomInfo()
|
||||
if (infos.isNotEmpty()) {
|
||||
val roomInfo = infos[0].split("|")
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_TEXT, roomInfo[0], NetPlayItems.TYPE_TEXT))
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_COUNT, "${infos.size - 1}/${roomInfo[1]}", NetPlayItems.TYPE_TEXT))
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_SEPARATOR, "", NetPlayItems.TYPE_SEPARATOR))
|
||||
for (i in 1 until infos.size) {
|
||||
netPlayItems.add(NetPlayItems(NetPlayItems.MULTIPLAYER_ROOM_MEMBER, infos[i], NetPlayItems.TYPE_BUTTON))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int) = netPlayItems[position].type
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NetPlayViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (viewType) {
|
||||
NetPlayItems.TYPE_TEXT -> TextViewHolder(ItemTextNetplayBinding.inflate(inflater, parent, false))
|
||||
NetPlayItems.TYPE_BUTTON -> ButtonViewHolder(ItemButtonNetplayBinding.inflate(inflater, parent, false))
|
||||
NetPlayItems.TYPE_SEPARATOR -> object : NetPlayViewHolder(inflater.inflate(R.layout.item_separator_netplay, parent, false)) {
|
||||
override fun bind(item: NetPlayItems) {}
|
||||
override fun onClick(clicked: View) {}
|
||||
}
|
||||
else -> throw IllegalStateException("Unsupported view type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: NetPlayViewHolder, position: Int) {
|
||||
holder.bind(netPlayItems[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = netPlayItems.size
|
||||
}
|
||||
|
||||
fun refreshAdapterItems() {
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
NetPlayManager.setOnAdapterRefreshListener() { type, msg ->
|
||||
handler.post {
|
||||
adapter.netPlayItems.clear()
|
||||
adapter.loadMultiplayerMenu()
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNetPlayInputDialog(isCreateRoom: Boolean) {
|
||||
val activity = CompatUtils.findActivity(context)
|
||||
val dialog = BottomSheetDialog(activity)
|
||||
|
||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
dialog.behavior.skipCollapsed = context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
|
||||
val binding = DialogMultiplayerRoomBinding.inflate(LayoutInflater.from(activity))
|
||||
dialog.setContentView(binding.root)
|
||||
|
||||
binding.textTitle.text = activity.getString(
|
||||
if (isCreateRoom) R.string.multiplayer_create_room
|
||||
else R.string.multiplayer_join_room
|
||||
)
|
||||
|
||||
binding.ipAddress.setText(
|
||||
if (isCreateRoom) NetPlayManager.getIpAddressByWifi(activity)
|
||||
else NetPlayManager.getRoomAddress(activity)
|
||||
)
|
||||
binding.ipPort.setText(NetPlayManager.getRoomPort(activity))
|
||||
binding.username.setText(NetPlayManager.getUsername(activity))
|
||||
|
||||
binding.roomName.visibility = if (isCreateRoom) View.VISIBLE else View.GONE
|
||||
binding.maxPlayersContainer.visibility = if (isCreateRoom) View.VISIBLE else View.GONE
|
||||
binding.maxPlayersLabel.text = context.getString(R.string.multiplayer_max_players_value, binding.maxPlayers.value.toInt())
|
||||
|
||||
binding.maxPlayers.addOnChangeListener { _, value, _ ->
|
||||
binding.maxPlayersLabel.text = context.getString(R.string.multiplayer_max_players_value, value.toInt())
|
||||
}
|
||||
|
||||
binding.btnConfirm.setOnClickListener {
|
||||
binding.btnConfirm.isEnabled = false
|
||||
binding.btnConfirm.text = activity.getString(R.string.disabled_button_text)
|
||||
|
||||
val ipAddress = binding.ipAddress.text.toString()
|
||||
val username = binding.username.text.toString()
|
||||
val portStr = binding.ipPort.text.toString()
|
||||
val password = binding.password.text.toString()
|
||||
val port = portStr.toIntOrNull() ?: run {
|
||||
Toast.makeText(activity, R.string.multiplayer_port_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
return@setOnClickListener
|
||||
}
|
||||
val roomName = binding.roomName.text.toString()
|
||||
val maxPlayers = binding.maxPlayers.value.toInt()
|
||||
|
||||
if (isCreateRoom && (roomName.length !in 3..20)) {
|
||||
Toast.makeText(activity, R.string.multiplayer_room_name_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (ipAddress.length < 7 || username.length < 5) {
|
||||
Toast.makeText(activity, R.string.multiplayer_input_invalid, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
} else {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val result = if (isCreateRoom) {
|
||||
NetPlayManager.netPlayCreateRoom(ipAddress, port, username, password, roomName, maxPlayers)
|
||||
} else {
|
||||
NetPlayManager.netPlayJoinRoom(ipAddress, port, username, password)
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
NetPlayManager.setUsername(activity, username)
|
||||
NetPlayManager.setRoomPort(activity, portStr)
|
||||
if (!isCreateRoom) NetPlayManager.setRoomAddress(activity, ipAddress)
|
||||
Toast.makeText(
|
||||
YuzuApplication.appContext,
|
||||
if (isCreateRoom) R.string.multiplayer_create_room_success
|
||||
else R.string.multiplayer_join_room_success,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
dialog.dismiss()
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.multiplayer_could_not_connect, Toast.LENGTH_LONG).show()
|
||||
binding.btnConfirm.isEnabled = true
|
||||
binding.btnConfirm.text = activity.getString(R.string.original_button_text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun showModerationDialog() {
|
||||
val activity = CompatUtils.findActivity(context)
|
||||
val dialog = MaterialAlertDialogBuilder(activity)
|
||||
dialog.setTitle(R.string.multiplayer_moderation_title)
|
||||
|
||||
val banList = NetPlayManager.getBanList()
|
||||
if (banList.isEmpty()) {
|
||||
dialog.setMessage(R.string.multiplayer_no_bans)
|
||||
dialog.setPositiveButton(R.string.ok, null)
|
||||
dialog.show()
|
||||
return
|
||||
}
|
||||
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_ban_list, null)
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.ban_list_recycler)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
|
||||
lateinit var adapter: BanListAdapter
|
||||
|
||||
val onUnban: (String) -> Unit = { bannedItem ->
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.multiplayer_unban_title)
|
||||
.setMessage(activity.getString(R.string.multiplayer_unban_message, bannedItem))
|
||||
.setPositiveButton(R.string.multiplayer_unban) { _, _ ->
|
||||
NetPlayManager.netPlayUnbanUser(bannedItem)
|
||||
adapter.removeBan(bannedItem)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
adapter = BanListAdapter(banList, onUnban)
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
dialog.setView(view)
|
||||
dialog.setPositiveButton(R.string.ok, null)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private class BanListAdapter(
|
||||
banList: List<String>,
|
||||
private val onUnban: (String) -> Unit
|
||||
) : RecyclerView.Adapter<BanListAdapter.ViewHolder>() {
|
||||
|
||||
private val usernameBans = banList.filter { !it.contains(".") }.toMutableList()
|
||||
private val ipBans = banList.filter { it.contains(".") }.toMutableList()
|
||||
|
||||
class ViewHolder(val binding: ItemBanListBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding = ItemBanListBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val isUsername = position < usernameBans.size
|
||||
val item = if (isUsername) usernameBans[position] else ipBans[position - usernameBans.size]
|
||||
|
||||
holder.binding.apply {
|
||||
banText.text = item
|
||||
icon.setImageResource(if (isUsername) R.drawable.ic_user else R.drawable.ic_system)
|
||||
btnUnban.setOnClickListener { onUnban(item) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = usernameBans.size + ipBans.size
|
||||
|
||||
fun removeBan(bannedItem: String) {
|
||||
val position = if (bannedItem.contains(".")) {
|
||||
ipBans.indexOf(bannedItem).let { if (it >= 0) it + usernameBans.size else it }
|
||||
} else {
|
||||
usernameBans.indexOf(bannedItem)
|
||||
}
|
||||
|
||||
if (position >= 0) {
|
||||
if (bannedItem.contains(".")) {
|
||||
ipBans.remove(bannedItem)
|
||||
} else {
|
||||
usernameBans.remove(bannedItem)
|
||||
}
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -273,6 +273,13 @@ abstract class SettingsItem(
|
|||
descriptionId = R.string.use_docked_mode_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.USE_AUTO_STUB,
|
||||
titleId = R.string.use_auto_stub,
|
||||
descriptionId = R.string.use_auto_stub_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
syncCoreSpeedSetting,
|
||||
|
@ -317,7 +324,6 @@ abstract class SettingsItem(
|
|||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_SHADER_BACKEND,
|
||||
titleId = R.string.shader_backend,
|
||||
descriptionId = R.string.shader_backend_description,
|
||||
choicesId = R.array.rendererShaderNames,
|
||||
valuesId = R.array.rendererShaderValues
|
||||
)
|
||||
|
@ -350,7 +356,6 @@ abstract class SettingsItem(
|
|||
SingleChoiceSetting(
|
||||
IntSetting.RENDERER_VRAM_USAGE_MODE,
|
||||
titleId = R.string.vram_usage_mode,
|
||||
descriptionId = R.string.vram_usage_mode_description,
|
||||
choicesId = R.array.vramUsageMethodNames,
|
||||
valuesId = R.array.vramUsageMethodValues
|
||||
)
|
||||
|
@ -563,13 +568,6 @@ abstract class SettingsItem(
|
|||
descriptionId = R.string.renderer_debug_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.USE_AUTO_STUB,
|
||||
titleId = R.string.use_auto_stub,
|
||||
descriptionId = R.string.use_auto_stub_description
|
||||
)
|
||||
)
|
||||
put(
|
||||
SwitchSetting(
|
||||
BooleanSetting.CPU_DEBUG_MODE,
|
||||
|
|
|
@ -261,6 +261,7 @@ class SettingsFragmentPresenter(
|
|||
add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
|
||||
add(ShortSetting.RENDERER_SPEED_LIMIT.key)
|
||||
add(BooleanSetting.USE_DOCKED_MODE.key)
|
||||
add(BooleanSetting.USE_AUTO_STUB.key)
|
||||
add(IntSetting.REGION_INDEX.key)
|
||||
add(IntSetting.LANGUAGE_INDEX.key)
|
||||
add(BooleanSetting.USE_CUSTOM_RTC.key)
|
||||
|
@ -1197,7 +1198,6 @@ class SettingsFragmentPresenter(
|
|||
add(HeaderSetting(R.string.cpu))
|
||||
add(IntSetting.CPU_BACKEND.key)
|
||||
add(IntSetting.CPU_ACCURACY.key)
|
||||
add(BooleanSetting.USE_AUTO_STUB.key)
|
||||
add(BooleanSetting.CPU_DEBUG_MODE.key)
|
||||
add(SettingsItem.FASTMEM_COMBINED)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
|
@ -283,13 +279,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
true
|
||||
}
|
||||
|
||||
|
||||
R.id.menu_multiplayer -> {
|
||||
emulationActivity?.displayMultiplayerDialog()
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
R.id.menu_controls -> {
|
||||
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
|
||||
null,
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.Manifest
|
||||
|
@ -122,16 +118,6 @@ class HomeSettingsFragment : Fragment() {
|
|||
driverViewModel.selectedDriverTitle
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.multiplayer,
|
||||
R.string.multiplayer_description,
|
||||
R.drawable.ic_two_users,
|
||||
{
|
||||
val action = mainActivity.displayMultiplayerDialog()
|
||||
},
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.applets,
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.network
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.format.Formatter
|
||||
import android.widget.Toast
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.dialogs.ChatMessage
|
||||
|
||||
object NetPlayManager {
|
||||
external fun netPlayCreateRoom(ipAddress: String, port: Int, username: String, password: String, roomName: String, maxPlayers: Int): Int
|
||||
external fun netPlayJoinRoom(ipAddress: String, port: Int, username: String, password: String): Int
|
||||
external fun netPlayRoomInfo(): Array<String>
|
||||
external fun netPlayIsJoined(): Boolean
|
||||
external fun netPlayIsHostedRoom(): Boolean
|
||||
external fun netPlaySendMessage(msg: String)
|
||||
external fun netPlayKickUser(username: String)
|
||||
external fun netPlayLeaveRoom()
|
||||
external fun netPlayIsModerator(): Boolean
|
||||
external fun netPlayGetBanList(): Array<String>
|
||||
external fun netPlayBanUser(username: String)
|
||||
external fun netPlayUnbanUser(username: String)
|
||||
|
||||
private var messageListener: ((Int, String) -> Unit)? = null
|
||||
private var adapterRefreshListener: ((Int, String) -> Unit)? = null
|
||||
|
||||
fun setOnMessageReceivedListener(listener: (Int, String) -> Unit) {
|
||||
messageListener = listener
|
||||
}
|
||||
|
||||
fun setOnAdapterRefreshListener(listener: (Int, String) -> Unit) {
|
||||
adapterRefreshListener = listener
|
||||
}
|
||||
|
||||
fun getUsername(activity: Context): String { val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
val name = "Eden${(Math.random() * 100).toInt()}"
|
||||
return prefs.getString("NetPlayUsername", name) ?: name
|
||||
}
|
||||
|
||||
fun setUsername(activity: Activity, name: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayUsername", name).apply()
|
||||
}
|
||||
|
||||
fun getRoomAddress(activity: Activity): String {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
val address = getIpAddressByWifi(activity)
|
||||
return prefs.getString("NetPlayRoomAddress", address) ?: address
|
||||
}
|
||||
|
||||
fun setRoomAddress(activity: Activity, address: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayRoomAddress", address).apply()
|
||||
}
|
||||
|
||||
fun getRoomPort(activity: Activity): String {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
return prefs.getString("NetPlayRoomPort", "24872") ?: "24872"
|
||||
}
|
||||
|
||||
fun setRoomPort(activity: Activity, port: String) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
prefs.edit().putString("NetPlayRoomPort", port).apply()
|
||||
}
|
||||
|
||||
private val chatMessages = mutableListOf<ChatMessage>()
|
||||
private var isChatOpen = false
|
||||
|
||||
fun addChatMessage(message: ChatMessage) {
|
||||
chatMessages.add(message)
|
||||
}
|
||||
|
||||
fun getChatMessages(): List<ChatMessage> = chatMessages
|
||||
|
||||
fun clearChat() {
|
||||
chatMessages.clear()
|
||||
}
|
||||
|
||||
fun setChatOpen(isOpen: Boolean) {
|
||||
isChatOpen = isOpen
|
||||
}
|
||||
|
||||
fun addNetPlayMessage(type: Int, msg: String) {
|
||||
val context = YuzuApplication.appContext
|
||||
val message = formatNetPlayStatus(context, type, msg)
|
||||
|
||||
when (type) {
|
||||
NetPlayStatus.CHAT_MESSAGE -> {
|
||||
val parts = msg.split(":", limit = 2)
|
||||
if (parts.size == 2) {
|
||||
val nickname = parts[0].trim()
|
||||
val chatMessage = parts[1].trim()
|
||||
addChatMessage(ChatMessage(
|
||||
nickname = nickname,
|
||||
username = "",
|
||||
message = chatMessage
|
||||
))
|
||||
}
|
||||
}
|
||||
NetPlayStatus.MEMBER_JOIN,
|
||||
NetPlayStatus.MEMBER_LEAVE,
|
||||
NetPlayStatus.MEMBER_KICKED,
|
||||
NetPlayStatus.MEMBER_BANNED -> {
|
||||
addChatMessage(ChatMessage(
|
||||
nickname = "System",
|
||||
username = "",
|
||||
message = message
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
if (!isChatOpen) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
messageListener?.invoke(type, msg)
|
||||
adapterRefreshListener?.invoke(type, msg)
|
||||
}
|
||||
|
||||
private fun formatNetPlayStatus(context: Context, type: Int, msg: String): String {
|
||||
return when (type) {
|
||||
NetPlayStatus.NETWORK_ERROR -> context.getString(R.string.multiplayer_network_error)
|
||||
NetPlayStatus.LOST_CONNECTION -> context.getString(R.string.multiplayer_lost_connection)
|
||||
NetPlayStatus.NAME_COLLISION -> context.getString(R.string.multiplayer_name_collision)
|
||||
NetPlayStatus.MAC_COLLISION -> context.getString(R.string.multiplayer_mac_collision)
|
||||
NetPlayStatus.CONSOLE_ID_COLLISION -> context.getString(R.string.multiplayer_console_id_collision)
|
||||
NetPlayStatus.WRONG_VERSION -> context.getString(R.string.multiplayer_wrong_version)
|
||||
NetPlayStatus.WRONG_PASSWORD -> context.getString(R.string.multiplayer_wrong_password)
|
||||
NetPlayStatus.COULD_NOT_CONNECT -> context.getString(R.string.multiplayer_could_not_connect)
|
||||
NetPlayStatus.ROOM_IS_FULL -> context.getString(R.string.multiplayer_room_is_full)
|
||||
NetPlayStatus.HOST_BANNED -> context.getString(R.string.multiplayer_host_banned)
|
||||
NetPlayStatus.PERMISSION_DENIED -> context.getString(R.string.multiplayer_permission_denied)
|
||||
NetPlayStatus.NO_SUCH_USER -> context.getString(R.string.multiplayer_no_such_user)
|
||||
NetPlayStatus.ALREADY_IN_ROOM -> context.getString(R.string.multiplayer_already_in_room)
|
||||
NetPlayStatus.CREATE_ROOM_ERROR -> context.getString(R.string.multiplayer_create_room_error)
|
||||
NetPlayStatus.HOST_KICKED -> context.getString(R.string.multiplayer_host_kicked)
|
||||
NetPlayStatus.UNKNOWN_ERROR -> context.getString(R.string.multiplayer_unknown_error)
|
||||
NetPlayStatus.ROOM_UNINITIALIZED -> context.getString(R.string.multiplayer_room_uninitialized)
|
||||
NetPlayStatus.ROOM_IDLE -> context.getString(R.string.multiplayer_room_idle)
|
||||
NetPlayStatus.ROOM_JOINING -> context.getString(R.string.multiplayer_room_joining)
|
||||
NetPlayStatus.ROOM_JOINED -> context.getString(R.string.multiplayer_room_joined)
|
||||
NetPlayStatus.ROOM_MODERATOR -> context.getString(R.string.multiplayer_room_moderator)
|
||||
NetPlayStatus.MEMBER_JOIN -> context.getString(R.string.multiplayer_member_join, msg)
|
||||
NetPlayStatus.MEMBER_LEAVE -> context.getString(R.string.multiplayer_member_leave, msg)
|
||||
NetPlayStatus.MEMBER_KICKED -> context.getString(R.string.multiplayer_member_kicked, msg)
|
||||
NetPlayStatus.MEMBER_BANNED -> context.getString(R.string.multiplayer_member_banned, msg)
|
||||
NetPlayStatus.ADDRESS_UNBANNED -> context.getString(R.string.multiplayer_address_unbanned)
|
||||
NetPlayStatus.CHAT_MESSAGE -> msg
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun getIpAddressByWifi(activity: Activity): String {
|
||||
var ipAddress = 0
|
||||
val wifiManager = activity.getSystemService(WifiManager::class.java)
|
||||
val wifiInfo = wifiManager.connectionInfo
|
||||
if (wifiInfo != null) {
|
||||
ipAddress = wifiInfo.ipAddress
|
||||
}
|
||||
|
||||
if (ipAddress == 0) {
|
||||
val dhcpInfo = wifiManager.dhcpInfo
|
||||
if (dhcpInfo != null) {
|
||||
ipAddress = dhcpInfo.ipAddress
|
||||
}
|
||||
}
|
||||
|
||||
return if (ipAddress == 0) {
|
||||
"192.168.0.1"
|
||||
} else {
|
||||
Formatter.formatIpAddress(ipAddress)
|
||||
}
|
||||
}
|
||||
|
||||
fun getBanList(): List<String> {
|
||||
return netPlayGetBanList().toList()
|
||||
}
|
||||
|
||||
object NetPlayStatus {
|
||||
const val NO_ERROR = 0
|
||||
const val NETWORK_ERROR = 1
|
||||
const val LOST_CONNECTION = 2
|
||||
const val NAME_COLLISION = 3
|
||||
const val MAC_COLLISION = 4
|
||||
const val CONSOLE_ID_COLLISION = 5
|
||||
const val WRONG_VERSION = 6
|
||||
const val WRONG_PASSWORD = 7
|
||||
const val COULD_NOT_CONNECT = 8
|
||||
const val ROOM_IS_FULL = 9
|
||||
const val HOST_BANNED = 10
|
||||
const val PERMISSION_DENIED = 11
|
||||
const val NO_SUCH_USER = 12
|
||||
const val ALREADY_IN_ROOM = 13
|
||||
const val CREATE_ROOM_ERROR = 14
|
||||
const val HOST_KICKED = 15
|
||||
const val UNKNOWN_ERROR = 16
|
||||
const val ROOM_UNINITIALIZED = 17
|
||||
const val ROOM_IDLE = 18
|
||||
const val ROOM_JOINING = 19
|
||||
const val ROOM_JOINED = 20
|
||||
const val ROOM_MODERATOR = 21
|
||||
const val MEMBER_JOIN = 22
|
||||
const val MEMBER_LEAVE = 23
|
||||
const val MEMBER_KICKED = 24
|
||||
const val MEMBER_BANNED = 25
|
||||
const val ADDRESS_UNBANNED = 26
|
||||
const val CHAT_MESSAGE = 27
|
||||
}
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
package org.yuzu.yuzu_emu.ui.main
|
||||
|
||||
import android.content.Intent
|
||||
|
@ -35,7 +31,6 @@ import org.yuzu.yuzu_emu.HomeNavigationDirections
|
|||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
||||
import org.yuzu.yuzu_emu.dialogs.NetPlayDialog
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment
|
||||
import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment
|
||||
|
@ -75,7 +70,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||
|
||||
ThemeHelper.ThemeChangeListener(this)
|
||||
ThemeHelper.setTheme(this)
|
||||
NativeLibrary.netPlayInit()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
@ -168,10 +162,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
fun displayMultiplayerDialog() {
|
||||
val dialog = NetPlayDialog(this)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
|
||||
private fun checkKeys() {
|
||||
if (!NativeLibrary.areKeysPresent()) {
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
|
||||
object CompatUtils {
|
||||
fun findActivity(context: Context): Activity {
|
||||
return when (context) {
|
||||
is Activity -> context
|
||||
is ContextWrapper -> findActivity(context.baseContext)
|
||||
else -> throw IllegalArgumentException("Context is not an Activity")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
@ -24,7 +20,6 @@
|
|||
#include <frontend_common/content_manager.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "common/android/multiplayer/multiplayer.h"
|
||||
#include "common/android/android_common.h"
|
||||
#include "common/android/id_cache.h"
|
||||
#include "common/detached_tasks.h"
|
||||
|
@ -664,7 +659,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env
|
|||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv* env,
|
||||
jobject instance) {
|
||||
const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
|
||||
const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
|
||||
auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory(
|
||||
Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read);
|
||||
|
||||
|
@ -836,7 +831,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
|
|||
const auto user_id = manager.GetUser(static_cast<std::size_t>(0));
|
||||
ASSERT(user_id);
|
||||
|
||||
const auto nandDir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
|
||||
const auto nandDir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir);
|
||||
auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(nandDir),
|
||||
FileSys::OpenMode::Read);
|
||||
|
||||
|
@ -875,83 +870,4 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, jobje
|
|||
return ContentManager::AreKeysPresent();
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayCreateRoom(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
||||
jstring username, jstring password, jstring room_name, jint max_players) {
|
||||
return static_cast<jint>(
|
||||
NetPlayCreateRoom(Common::Android::GetJString(env, ipaddress), port,
|
||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password),
|
||||
Common::Android::GetJString(env, room_name), max_players));
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayJoinRoom(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring ipaddress, jint port,
|
||||
jstring username, jstring password) {
|
||||
return static_cast<jint>(
|
||||
NetPlayJoinRoom(Common::Android::GetJString(env, ipaddress), port,
|
||||
Common::Android::GetJString(env, username), Common::Android::GetJString(env, password)));
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayRoomInfo(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return Common::Android::ToJStringArray(env, NetPlayRoomInfo());
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsJoined(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsJoined();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsHostedRoom(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsHostedRoom();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlaySendMessage(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring msg) {
|
||||
NetPlaySendMessage(Common::Android::GetJString(env, msg));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayKickUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayKickUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayLeaveRoom(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
NetPlayLeaveRoom();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayIsModerator(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return NetPlayIsModerator();
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayGetBanList(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return Common::Android::ToJStringArray(env, NetPlayGetBanList());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayBanUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayBanUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_network_NetPlayManager_netPlayUnbanUser(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj, jstring username) {
|
||||
NetPlayUnbanUser(Common::Android::GetJString(env, username));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_yuzu_yuzu_1emu_NativeLibrary_netPlayInit(
|
||||
JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
NetworkInit(&EmulationSession::GetInstance().System().GetRoomNetwork());
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -44,7 +44,7 @@ bool IsProfileNameValid(std::string_view profile_name) {
|
|||
}
|
||||
|
||||
bool ProfileExistsInFilesystem(std::string_view profile_name) {
|
||||
return Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) / "input" /
|
||||
return Common::FS::Exists(Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "input" /
|
||||
fmt::format("{}.ini", profile_name));
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,7 @@ void Java_org_yuzu_yuzu_1emu_features_input_NativeInput_loadInputProfiles(JNIEnv
|
|||
jobject j_obj) {
|
||||
map_profiles.clear();
|
||||
const auto input_profile_loc =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) / "input";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "input";
|
||||
|
||||
if (Common::FS::IsDir(input_profile_loc)) {
|
||||
Common::FS::IterateDirEntries(
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||
</vector>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_icon_bg" />
|
||||
<foreground android:drawable="@drawable/ic_yuzu_icon" />
|
||||
<monochrome android:drawable="@drawable/ic_yuzu_icon" />
|
||||
<foreground android:drawable="@drawable/ic_yuzu" />
|
||||
<monochrome android:drawable="@drawable/ic_yuzu" />
|
||||
</adaptive-icon>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorPrimary"
|
||||
android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z"/>
|
||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"/>
|
||||
</vector>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
|
@ -1,39 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512dp"
|
||||
android:height="512dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:pathData="M304.46,255.4C304.89,255.4 305.31,255.4 306.14,255.43C308.29,255.44 310.04,255.44 311.78,255.43C329.71,255.44 347.63,255.44 365.56,255.47C369.95,255.48 374.33,255.62 378.72,255.58C380.38,255.57 381.19,255.99 381.06,257.81C380.9,260.05 380.89,262.29 380.92,264.53C380.95,266.66 380.25,267.51 377.87,267.5C351.65,267.41 325.42,267.46 299.2,267.47C287.33,267.47 275.46,267.47 263.59,267.47C262.69,267.47 261.79,267.47 260.68,267.47C260.68,268.76 260.68,269.87 260.68,271.29C300.35,271.29 340.05,271.29 380.4,271.29C379.57,275.72 378.85,279.75 378,283.75C377.91,284.18 377.1,284.62 376.56,284.76C375.85,284.93 375.07,284.81 374.33,284.81C337.48,284.81 300.63,284.81 263.78,284.81C262.8,284.81 261.82,284.81 260.65,284.81C260.65,286.05 260.65,287.08 260.65,288.4C299.24,288.4 337.78,288.4 376.97,288.4C376.11,291.32 375.42,293.81 374.62,296.27C373.14,300.86 373.12,300.85 368.42,300.85C333.56,300.85 298.7,300.86 263.85,300.83C262.02,300.83 260.52,300.96 261.29,303.33C261.48,303.9 262.3,304.41 262.94,304.66C263.52,304.89 264.25,304.71 264.91,304.71C299.19,304.71 333.46,304.71 367.74,304.71C368.79,304.71 369.85,304.71 371.59,304.71C369.69,308.63 368.15,312.08 366.31,315.36C365.96,315.98 364.4,316.14 363.39,316.14C348.37,316.19 333.35,316.17 318.33,316.17C301.32,316.17 284.3,316.17 267.29,316.17C265.89,316.17 264.49,316.1 262.71,316.16C261.04,316.25 259.75,316.25 258.46,316.25C258,312.48 257.23,308.71 257.15,304.93C256.85,291.18 256.73,277.42 256.69,263.66C256.69,261.04 257.35,258.42 258.05,255.65C259.59,255.49 260.8,255.48 262.24,255.51C274.31,255.52 286.16,255.5 298.23,255.48C300.45,255.45 302.46,255.42 304.46,255.4Z"
|
||||
android:fillColor="#BF42F6"/>
|
||||
<path
|
||||
android:pathData="M208.59,256.37C208.59,254.82 208.59,253.26 208.59,251.37C207.3,251.37 206.09,251.37 204.87,251.37C180.97,251.39 157.07,251.38 133.17,251.45C131.1,251.46 130.29,250.9 130.62,248.77C130.99,246.4 131.29,244 131.37,241.6C131.43,239.79 132.23,239.45 133.84,239.45C158.48,239.39 183.12,239.26 207.77,239.21C209.84,239.2 211.44,239.02 211,236.08C184.8,236.08 158.61,236.08 132.05,236.08C132.8,232.53 133.32,229.27 134.27,226.14C134.49,225.41 136.22,224.73 137.26,224.73C162.73,224.69 188.21,224.73 213.69,224.79C215.45,224.79 216.83,224.59 216.98,222.08C189.85,222.08 162.79,222.08 135.06,222.08C136.9,217.08 138.46,212.57 140.29,208.17C140.55,207.54 142.04,207.13 142.96,207.12C156.16,207.06 169.36,207.01 182.55,207.13C185.39,207.16 186.89,205.74 188.53,203.24C173.01,203.24 157.9,203.24 142.12,203.24C144.45,199.04 146.41,195.32 148.6,191.75C148.96,191.16 150.32,190.96 151.21,190.95C167.65,190.91 184.08,190.8 200.51,191.01C204.37,191.06 207.34,189.61 210.35,187.38C190.94,187.38 171.54,187.38 151.29,187.38C152.68,185.33 153.63,183.86 154.66,182.45C159.42,175.89 159.43,175.9 167.58,175.9C189.4,175.89 211.23,175.89 233.06,175.89C233.94,175.89 234.81,175.89 236.22,175.89C234.09,173.68 232.46,172.15 229.61,172.17C208.69,172.26 187.78,172.21 166.86,172.21C165.9,172.21 164.94,172.21 163.98,172.21C163.85,171.98 163.72,171.75 163.59,171.51C165.64,169.44 167.65,167.32 169.77,165.32C175.92,159.52 175.94,159.41 184.39,159.57C196.85,159.79 208.61,163.22 219.95,168.09C222.99,169.4 225.62,170.09 228.87,168.6C231.4,167.44 234.35,167.17 237.47,166.71C235.1,171.08 237.95,173.17 240.44,175.52C243.51,178.42 246.46,181.46 249.43,184.48C250.05,185.12 250.52,185.91 251.41,187.09C250.2,187.15 249.44,187.23 248.68,187.24C243.45,187.24 238.22,187.39 233,187.19C217.94,186.61 205.3,192.15 194.56,202.33C190.72,205.97 187.3,210.05 183.71,213.95C183.34,214.35 183.13,214.89 182.52,215.9C200.74,209.5 217.89,201.2 237.06,200.53C237.21,200.78 237.37,201.03 237.52,201.28C235.25,203.93 233.13,206.73 230.69,209.21C220.98,219.12 215.17,231.05 212.49,244.52C211.74,248.31 211.79,252.26 211.15,256.3C210.08,256.43 209.34,256.4 208.59,256.37ZM219.33,207.12C221.4,207.13 223.49,206.96 225.55,207.17C228.53,207.49 230.34,206 232.27,203.13C227.37,204.29 223.07,205.3 218.77,206.35C218.77,206.35 218.89,206.85 219.33,207.12Z"
|
||||
android:fillColor="#FF44C4"/>
|
||||
<path
|
||||
android:pathData="M208.38,256.38C209.34,256.4 210.08,256.43 211.05,256.48C211.35,258.14 211.43,259.79 211.51,261.44C211.81,261.54 212.1,261.64 212.39,261.75C213.62,259.93 214.86,258.11 216.4,256.13C217.71,255.93 218.73,255.87 219.92,255.81C220.68,255.74 221.25,255.63 221.82,255.62C228.3,255.53 234.79,255.46 241.52,255.42C243.38,255.48 244.99,255.51 246.61,255.53C246.01,259.12 245.37,262.7 244.81,266.29C242.28,282.55 241.91,298.87 243.1,315.49C241.78,315.89 240.68,316.05 239.58,316.21C209.45,316.2 179.32,316.14 149.2,316.25C146.34,316.26 144.74,315.41 143.73,312.8C142.73,310.21 141.43,307.74 140.02,304.71C143.48,304.71 146.35,304.71 149.23,304.71C178.19,304.71 207.16,304.72 236.12,304.69C237.21,304.69 238.73,305.34 238.98,303.29C239.23,301.22 238.3,300.81 236.42,300.82C215.59,300.87 194.75,300.85 173.92,300.85C162.97,300.85 152.01,300.82 141.06,300.92C139.16,300.94 138.18,300.36 137.66,298.55C136.78,295.46 135.74,292.42 134.51,288.53C169.6,288.39 204.12,288.52 238.88,288.45C238.95,287.2 239.01,286.17 239.08,284.95C238.06,284.89 237.26,284.82 236.45,284.81C205.16,284.8 173.88,284.78 142.59,284.78C140.18,284.78 137.78,284.93 135.37,284.87C134.76,284.85 133.72,284.39 133.63,283.97C132.73,279.8 131.99,275.6 131.15,271.1C135.68,271.1 139.63,271.09 143.59,271.11C144.67,271.12 145.74,271.33 146.81,271.33C176.85,271.34 206.9,271.34 236.94,271.34C240.2,271.34 240.33,271.2 240.3,267.48C204,267.48 167.69,267.48 130.92,267.48C130.76,263.91 130.53,260.64 130.6,257.37C130.61,256.95 132.18,256.22 133.03,256.21C141.16,256.1 149.3,256.11 157.43,256.11C166.89,256.1 176.35,256.07 185.81,256.11C193.26,256.15 200.71,256.3 208.38,256.38Z"
|
||||
android:fillColor="#BF43F5"/>
|
||||
<path
|
||||
android:pathData="M239.59,316.44C240.68,316.05 241.78,315.89 243.11,315.72C244.54,325.3 245.35,334.96 247.05,344.47C249.22,356.62 252.3,368.59 257.05,380.06C257.2,380.44 257.32,380.83 257.45,381.21C243.82,386.82 190.54,369.07 178.57,354.66C189.83,354.66 200.72,354.66 211.61,354.66C222.54,354.66 233.47,354.66 244.42,354.66C244.59,352.08 243.97,350.95 241.28,350.96C219.87,351.07 198.46,350.99 177.05,351.06C174.66,351.07 172.73,350.61 171.03,348.82C167.34,344.95 163.52,341.22 159.75,337.42C159.88,337.19 160,336.95 160.12,336.72C187.18,336.72 214.24,336.72 241.61,336.72C241.36,335.23 241.17,334.13 240.95,332.8C239.83,332.8 238.85,332.8 237.87,332.8C214.88,332.8 191.9,332.81 168.91,332.8C165.59,332.8 162.26,332.57 158.96,332.7C156.97,332.79 155.66,332.13 154.6,330.52C152.4,327.14 150.11,323.81 147.49,319.91C178.55,319.91 208.93,319.91 239.61,319.91C239.61,318.61 239.61,317.64 239.59,316.44Z"
|
||||
android:fillColor="#985DED"/>
|
||||
<path
|
||||
android:pathData="M258.44,316.48C259.75,316.25 261.04,316.25 262.54,316.24C262.8,317.31 262.85,318.38 262.92,319.73C296.42,319.73 329.83,319.73 364.01,319.73C362.33,322.39 361.03,324.54 359.64,326.62C355.54,332.81 355.53,332.8 348.25,332.8C321.86,332.8 295.46,332.8 269.07,332.8C268.09,332.8 267.11,332.8 266.16,332.8C265.84,336.39 266.08,336.68 269.29,336.68C295.68,336.68 322.08,336.68 348.47,336.68C349.44,336.68 350.4,336.68 352.17,336.68C350,339.11 348.17,340.87 346.68,342.88C341.82,349.43 335.64,351.54 327.37,351.23C309.64,350.55 291.86,351.02 274.09,351.02C273.11,351.02 272.13,351.02 271.17,351.02C271.02,354.12 271.48,354.66 274.17,354.66C292.68,354.66 311.19,354.66 329.7,354.66C330.65,354.66 331.6,354.66 332.54,354.66C332.62,354.89 332.7,355.12 332.78,355.35C330.9,356.75 329.07,358.22 327.14,359.56C314.53,368.29 300.74,374.45 285.87,378.18C284.11,378.62 282.23,378.92 280.46,378.76C279.45,378.68 278.23,377.74 277.63,376.83C272.53,369.18 269.33,360.66 266.33,352.02C262.35,340.53 260.11,328.68 258.44,316.48Z"
|
||||
android:fillColor="#985DED"/>
|
||||
<path
|
||||
android:pathData="M311.77,255.22C310.04,255.44 308.29,255.44 306.3,255.42C307.7,247.72 307.53,240.1 305.68,232.49C303.13,222.06 297.19,214.1 288.23,208.31C287.89,208.09 287.55,207.86 287.23,207.16C296.64,207.16 306.04,207.16 315.44,207.16C315.48,206.9 315.52,206.63 315.56,206.36C311.79,204.93 308.05,203.27 303.89,203.23C295.6,203.16 287.3,203.26 279,203.17C277.34,203.15 275.68,202.61 274.06,201.88C283.92,197.91 294.01,198.34 304.15,199.94C314.42,201.56 323.36,206.9 333.47,211.01C332.66,209.46 332.18,208.57 331.51,207.28C332.5,207.2 333.25,207.09 334.01,207.09C345.54,207.08 357.08,207.11 368.61,207.04C370.36,207.03 371.33,207.5 371.9,209.25C373.14,213.07 374.59,216.83 376.13,221.13C352.97,221.13 330.46,221.13 307.83,221.13C307.91,223.56 308.96,224.24 311,224.23C326.6,224.18 342.2,224.17 357.8,224.21C363.6,224.23 369.4,224.38 375.2,224.59C375.91,224.61 377.07,225.22 377.21,225.77C378.05,228.87 378.63,232.04 379.37,235.53C356.71,235.53 334.45,235.53 312.2,235.53C311.91,238.9 312.07,239.08 315,239.08C335.91,239.11 356.82,239.16 377.73,239.16C379.27,239.16 379.99,239.52 380.09,241.18C380.25,243.91 380.6,246.63 380.95,249.34C381.17,251.05 380.61,251.72 378.8,251.66C375.24,251.54 371.67,251.6 368.11,251.6C350.51,251.6 332.92,251.6 315.33,251.6C311.97,251.6 311.97,251.61 311.77,255.22Z"
|
||||
android:fillColor="#FF43C4"/>
|
||||
<path
|
||||
android:pathData="M233.67,133.02C256.13,129.25 277.19,131.88 288.96,135.95C287.31,139.82 285.66,143.69 284.01,147.55C283.13,149.6 282.1,151.61 281.39,153.73C280.81,155.48 279.79,155.91 278.06,155.9C266.2,155.83 254.34,155.87 241.85,155.87C243.96,158.04 245.54,159.78 248.45,159.75C257.41,159.67 266.37,159.72 275.33,159.73C276.24,159.73 277.14,159.73 278.95,159.73C276.99,163 275.7,166.08 273.6,168.43C270.3,172.11 266.39,175.23 262.88,178.73C261.53,180.08 260.9,180.03 259.6,178.61C254.3,172.8 248.97,167.01 243.39,161.48C237.24,155.37 229.44,152.84 220.98,151.86C213.46,150.99 206.32,152.38 199.27,154.82C197.58,155.4 195.74,155.75 193.96,155.82C190.07,155.97 186.17,155.86 182.15,155.55C197.45,143.96 214.61,136.59 233.67,133.02ZM262.52,174.52C263.06,173.88 263.6,173.24 264.46,172.22C262.24,172.22 260.62,172.22 258.52,172.22C259.34,173.38 259.78,174.29 260.48,174.87C260.83,175.15 261.67,174.84 262.52,174.52Z"
|
||||
android:fillColor="#FF42C3"/>
|
||||
<path
|
||||
android:pathData="M320.81,196.15C314.32,190.85 306.7,188.96 298.84,187.82C289.74,186.5 280.81,187.01 271.96,190.85C272.47,189.92 272.88,188.91 273.51,188.06C281.91,176.57 292.26,167.25 304.84,160.58C306.74,159.57 309.33,159.62 311.6,159.59C318.82,159.47 326.04,159.5 333.26,159.59C334.35,159.6 335.69,159.93 336.45,160.63C340.22,164 343.83,167.55 347.48,171.05C347.69,171.25 347.78,171.57 348.11,172.21C346.93,172.21 346.05,172.21 345.18,172.21C328.58,172.21 311.98,172.28 295.39,172.15C292.59,172.13 291.04,173.55 288.95,175.9C290.46,175.9 291.4,175.9 292.33,175.9C311.17,175.9 330.01,175.93 348.85,175.85C351,175.84 352.47,176.48 353.68,178.19C355.68,181.01 357.78,183.76 360.24,187.08C343.65,187.08 327.73,187.08 311.82,187.08C311.79,187.29 311.76,187.49 311.74,187.69C315.27,189 318.39,191.09 322.57,191.01C335.01,190.76 347.46,190.96 359.91,190.88C361.92,190.87 363.16,191.51 364.06,193.28C365.66,196.45 367.39,199.54 369.27,203.03C368.03,203.11 367.26,203.21 366.48,203.21C354.44,203.21 342.41,203.18 330.38,203.24C328.66,203.25 327.4,202.81 326.24,201.52C324.58,199.67 322.72,198.01 320.81,196.15Z"
|
||||
android:fillColor="#FF44C4"/>
|
||||
<path
|
||||
android:pathData="M262.01,255.48C260.8,255.48 259.59,255.49 258.15,255.49C259.26,241.21 260.47,226.92 264.71,213.11C265.34,211.06 266.03,210.16 268.06,211.62C270.08,213.06 272.41,214.16 274.15,215.88C286.01,227.55 297.17,239.78 304.4,255.23C302.46,255.42 300.45,255.45 298.21,255.28C297.55,252.82 296.4,251.87 293.9,251.91C284.4,252.06 274.9,251.97 265.39,251.98C264.34,251.98 263.3,251.98 262.01,251.98C262.01,253.37 262.01,254.43 262.01,255.48ZM263.18,238.86C271.2,238.86 279.22,238.86 287.25,238.86C287.34,238.56 287.43,238.26 287.52,237.96C286.55,237.47 285.57,236.58 284.58,236.57C277.89,236.44 271.2,236.51 264.5,236.49C262.98,236.48 262.3,237.02 263.18,238.86ZM268.75,222.05C266.99,221.93 265.42,222.05 265.71,224.51C268.73,224.51 271.68,224.51 274.73,224.51C273.54,221.78 271.35,221.98 268.75,222.05Z"
|
||||
android:fillColor="#FF44C4"/>
|
||||
<path
|
||||
android:pathData="M246.72,255.38C244.99,255.51 243.38,255.48 241.58,255.22C241.46,254.11 241.53,253.25 241.62,252.02C235.47,252.02 229.64,252.02 223.81,252.02C220.63,252.03 220.2,252.43 219.74,255.82C218.73,255.87 217.71,255.93 216.49,255.98C218.93,250.76 221.21,245.3 224.33,240.35C229.86,231.57 236.13,223.3 244.52,216.92C248.39,213.97 252.62,211.77 257.32,210.49C257.93,210.32 258.57,210.3 259.92,210.12C254.32,225.13 249.77,239.96 246.72,255.38ZM232.91,235.63C230.52,235.4 229.98,237.18 228.98,239.19C234.28,239.19 239.23,239.12 244.17,239.22C246.42,239.27 247.04,238.27 246.74,235.68C242.23,235.68 237.78,235.68 232.91,235.63ZM251.08,223.33C250.49,222.98 249.91,222.38 249.29,222.32C247.73,222.17 246.14,222.34 244.57,222.24C242.56,222.12 241.44,223.18 240.32,225.2C243.65,225.2 246.59,225.26 249.52,225.13C250.03,225.11 250.51,224.24 251.08,223.33Z"
|
||||
android:fillColor="#FF44C4"/>
|
||||
<path
|
||||
android:pathData="M302.88,140.38C312.51,144.32 321.39,149.16 329.57,155.7C313.1,154.61 297.42,157.52 282.02,164.18C282.47,161.67 283.3,160.12 285.45,159.45C288.6,158.48 291.72,157.43 294.83,155.97C292.13,155.97 289.42,155.97 285.99,155.97C289.14,149.79 291.98,144.13 294.96,138.55C295.17,138.15 296.47,138.03 297.12,138.23C299.02,138.8 300.85,139.61 302.88,140.38Z"
|
||||
android:fillColor="#FF44C4"/>
|
||||
</vector>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/ban_list_recycler"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"/>
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardCornerRadius="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="?colorSurface">
|
||||
|
||||
<View
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:backgroundTint="?colorSurfaceVariant" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
|
@ -1,55 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/chat"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/chat_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:transcriptMode="alwaysScroll" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/type_message">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/chat_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:imeOptions="actionSend" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/send_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_send"
|
||||
android:contentDescription="@string/send_message" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -1,72 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:text="@string/multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:src="@drawable/ic_network"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_join"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/multiplayer_join_room"
|
||||
app:icon="@drawable/ic_install"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_create"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/multiplayer_create_room"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -1,75 +0,0 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_title"
|
||||
android:text="@string/multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list_multiplayer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_chat"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="true"
|
||||
android:text="@string/multiplayer_chat"
|
||||
app:icon="@drawable/ic_chat"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_moderation"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:enabled="true"
|
||||
android:text="@string/multiplayer_moderation"
|
||||
app:cornerRadius="16dp"
|
||||
app:icon="@drawable/ic_user" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_leave"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:text="@string/multiplayer_exit_room"
|
||||
app:icon="@drawable/ic_exit"
|
||||
app:cornerRadius="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -1,119 +0,0 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"
|
||||
android:elevation="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="8dp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_ip_address"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/ip_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_ip_port"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/ip_port"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_username"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_password"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiplayer_room_name"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/room_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/max_players_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/max_players"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:value="8"
|
||||
android:valueFrom="2"
|
||||
android:valueTo="16"
|
||||
android:stepSize="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/max_players_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/multiplayer_max_players_value" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_confirm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@android:string/ok"
|
||||
android:layout_gravity="center" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_user"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ban_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_unban"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/multiplayer_unban"/>
|
||||
</LinearLayout>
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_button_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/item_button_more"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/multiplayer_more_options"
|
||||
android:src="@drawable/ic_more_vert"
|
||||
android:padding="12dp" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/user_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timestamp_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"/>
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text_netplay_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="8dp" />
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_text_netplay_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,7 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
tools:ignore="ExtraText">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_pause_emulation"
|
||||
|
@ -23,12 +21,6 @@
|
|||
android:icon="@drawable/ic_controller"
|
||||
android:title="@string/preferences_controls" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_multiplayer"
|
||||
android:icon="@drawable/ic_two_users"
|
||||
android:title="@string/multiplayer" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_overlay_controls"
|
||||
android:icon="@drawable/ic_overlay"
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/action_kick"
|
||||
android:title="@string/multiplayer_kick_member"
|
||||
android:enabled="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_ban"
|
||||
android:title="@string/multiplayer_ban"
|
||||
android:enabled="false" />
|
||||
|
||||
</menu>
|
|
@ -87,12 +87,14 @@
|
|||
|
||||
<string-array name="rendererShaderNames">
|
||||
<item>@string/shader_backend_glsl</item>
|
||||
<item>@string/shader_backend_glasm</item>
|
||||
<item>@string/shader_backend_spirv</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="rendererShaderValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<!-- VRAM USAGE MODE CHOICES -->
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
<string name="about_app_description">An open-source Switch emulator</string>
|
||||
<string name="contributors">Contributors</string>
|
||||
<string name="contributors_description">Contributors who made eden for Android possible</string>
|
||||
<string name="contributors_link">https://git.eden-emu.dev/eden-emu/eden/activity/contributors</string>
|
||||
<string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
|
||||
<string name="licenses_description">Projects that make eden for Android possible</string>
|
||||
<string name="build">Build</string>
|
||||
<string name="user_data">User data</string>
|
||||
|
@ -228,9 +228,9 @@
|
|||
<string name="user_data_import_success">User data imported successfully</string>
|
||||
<string name="user_data_export_cancelled">Export cancelled</string>
|
||||
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
||||
<string name="support_link">https://discord.gg/Xa3ssgxrY7</string>
|
||||
<string name="website_link">https://bixthefin.github.io//</string>
|
||||
<string name="github_link">https://git.eden-emu.dev/eden-emu</string>
|
||||
<string name="support_link">https://discord.gg/u77vRWY</string>
|
||||
<string name="website_link">https://yuzu-emu.org/</string>
|
||||
<string name="github_link">https://github.com/yuzu-emu</string>
|
||||
|
||||
<!-- Early access upgrade strings -->
|
||||
<string name="early_access">Early Access</string>
|
||||
|
@ -272,10 +272,10 @@
|
|||
<string name="set_custom_rtc">Set custom RTC</string>
|
||||
|
||||
<!-- Graphics settings strings -->
|
||||
<string name="frame_skipping">WIP: Frameskip</string>
|
||||
<string name="frame_skipping">Frame Skipping</string>
|
||||
<string name="frame_skipping_description">Toggle frame skipping to improve performance by reducing the number of rendered frames.</string>
|
||||
<string name="frame_interpolation">Enhanced Frame Pacing</string>
|
||||
<string name="frame_interpolation_description">Ensures smooth and consistent frame delivery by synchronizing the timing between frames, reducing stuttering and uneven animation. Ideal for games that experience frame timing instability or micro-stutter during gameplay</string>
|
||||
<string name="frame_interpolation">Frame Interpolation</string>
|
||||
<string name="frame_interpolation_description">Toggle frame interpolation to improve visual smoothness by generating intermediate frames.</string>
|
||||
<string name="renderer_accuracy">Accuracy level</string>
|
||||
<string name="renderer_resolution">Resolution (Handheld/Docked)</string>
|
||||
<string name="renderer_vsync">VSync mode</string>
|
||||
|
@ -297,12 +297,10 @@
|
|||
<string name="anisotropic_filtering">Anisotropic filtering</string>
|
||||
<string name="anisotropic_filtering_description">Improves the quality of textures when viewed at oblique angles</string>
|
||||
<string name="nvdec_emulation">NVDEC Emulation</string>
|
||||
<string name="nvdec_emulation_description">Select how video decoding (NVDEC) is handled during cutscenes and intros.</string>
|
||||
<string name="nvdec_emulation_description">Specifies how videos should be decoded. It can either use the CPU or the GPU for decoding, or perform no decoding at all (black screen on videos). In most cases, GPU decoding provides the best performance.</string>
|
||||
<string name="shader_backend">Shader Backend</string>
|
||||
<string name="shader_backend_description">Choose how shaders are compiled and translated for your GPU.</string>
|
||||
<string name="dyna_state">Extended Dynamic State</string>
|
||||
<string name="dyna_state_description">Enables Vulkan features to improve performance, rendering, and save resources on pipeline creation while maintaining lower CPU/GPU usage.
|
||||
These features may have repercussions on the device\'s temperature, some GPUs belonging to the older A6XX line may not react properly. Disabled by default to use Yuzu emulated formats, risk-free core functions 1 - 2, for higher-end devices select 3.</string>
|
||||
<string name="dyna_state_description">Enables the VkExtendedDynamicState* extensions.\nHigher dynamic states will generally improve performance, but may cause issues on certain games or devices.\nSet to 0 to disable.</string>
|
||||
|
||||
<!-- Debug settings strings -->
|
||||
<string name="cpu">CPU</string>
|
||||
|
@ -476,78 +474,6 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
<string name="preferences_debug">Debug</string>
|
||||
<string name="preferences_debug_description">CPU/GPU debugging, graphics API, fastmem</string>
|
||||
|
||||
|
||||
<!-- Multiplayer -->
|
||||
<string name="multiplayer">Multiplayer</string>
|
||||
<string name="multiplayer_description">Host your own game room or join an existing one to play with people</string>
|
||||
<string name="multiplayer_room_title">Room: %1$s</string>
|
||||
<string name="multiplayer_console_id">Console ID:%1$s</string>
|
||||
<string name="multiplayer_create_room">Create</string>
|
||||
<string name="multiplayer_join_room">Join</string>
|
||||
<string name="multiplayer_username">Username</string>
|
||||
<string name="multiplayer_ip_address">IP Address</string>
|
||||
<string name="multiplayer_ip_port">Port</string>
|
||||
<string name="multiplayer_create_room_success">Room created successfully!</string>
|
||||
<string name="multiplayer_join_room_success">Join the room successfully!</string>
|
||||
<string name="multiplayer_create_room_failed">Failed to create room!</string>
|
||||
<string name="multiplayer_join_room_failed">Failed to join room!</string>
|
||||
<string name="multiplayer_input_invalid">Invalid address or name is too short!</string>
|
||||
<string name="multiplayer_port_invalid">Invalid port!</string>
|
||||
<string name="multiplayer_exit_room">Exit Room</string>
|
||||
<string name="multiplayer_network_error">Network error</string>
|
||||
<string name="multiplayer_lost_connection">Lost connection</string>
|
||||
<string name="multiplayer_name_collision">Name collision</string>
|
||||
<string name="multiplayer_mac_collision">Mac collision</string>
|
||||
<string name="multiplayer_console_id_collision">Console ID collision</string>
|
||||
<string name="multiplayer_wrong_version">Wrong version</string>
|
||||
<string name="multiplayer_wrong_password">Wrong password</string>
|
||||
<string name="multiplayer_could_not_connect">Could not connect</string>
|
||||
<string name="multiplayer_room_is_full">Room is full</string>
|
||||
<string name="multiplayer_host_banned">Host banned</string>
|
||||
<string name="multiplayer_permission_denied">Permission denied</string>
|
||||
<string name="multiplayer_no_such_user">No such user</string>
|
||||
<string name="multiplayer_already_in_room">Already in room</string>
|
||||
<string name="multiplayer_create_room_error">Create room error</string>
|
||||
<string name="multiplayer_host_kicked">Host kicked</string>
|
||||
<string name="multiplayer_unknown_error">unknown error</string>
|
||||
<string name="multiplayer_room_uninitialized">Room uninitialized</string>
|
||||
<string name="multiplayer_room_idle">Room idle</string>
|
||||
<string name="multiplayer_room_joining">Room joining</string>
|
||||
<string name="multiplayer_room_joined">Room joined</string>
|
||||
<string name="multiplayer_room_moderator">Room moderator</string>
|
||||
<string name="multiplayer_member_join">%1$s joined</string>
|
||||
<string name="multiplayer_member_leave">%1$s left</string>
|
||||
<string name="multiplayer_member_kicked">%1$s kicked</string>
|
||||
<string name="multiplayer_member_banned">%1$s banned</string>
|
||||
<string name="multiplayer_address_unbanned">address unbanned</string>
|
||||
<string name="multiplayer_kick_member">Kick Out</string>
|
||||
<string name="multiplayer_chat_input_hint">Send messages……</string>
|
||||
<string name="multiplayer_password">Password</string>
|
||||
<string name="original_button_text">Join</string>
|
||||
<string name="disabled_button_text">Joining...</string>
|
||||
<string name="multiplayer_room_name">Room Name</string>
|
||||
<string name="multiplayer_room_name_invalid">Room name must be between 3 and 20 characters</string>
|
||||
<string name="multiplayer_max_players">Max Players (16)</string>
|
||||
<string name="multiplayer_max_players_value">Max Players: %d</string>
|
||||
<string name="multiplayer_chat">Chat</string>
|
||||
<string name="multiplayer_more_options">More Options</string>
|
||||
<string name="multiplayer_ip_copied">IP Address copied to clipboard</string>
|
||||
<string name="multiplayer_server_address">Server Address</string>
|
||||
<string name="chat">Chat</string>
|
||||
<string name="type_message">Type message……</string>
|
||||
<string name="send">Send</string>
|
||||
<string name="send_message">Send Message</string>
|
||||
<string name="multiplayer_moderation">Moderation</string>
|
||||
<string name="multiplayer_moderation_title">Ban List</string>
|
||||
<string name="multiplayer_no_bans">No banned users</string>
|
||||
<string name="multiplayer_unban_title">Unban User</string>
|
||||
<string name="multiplayer_unban">Unban</string>
|
||||
<string name="multiplayer_unban_message">Are you sure you want to unban %1$s?</string>
|
||||
<string name="multiplayer_ban">Ban User</string>
|
||||
<string name="emulation_multiplayer">Multiplayer</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="ok">Ok</string>
|
||||
|
||||
<!-- Game properties -->
|
||||
<string name="info">Info</string>
|
||||
<string name="info_description">Program ID, developer, version</string>
|
||||
|
@ -692,6 +618,7 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
|
||||
<!-- Shader Backend -->
|
||||
<string name="shader_backend_glsl">GLSL</string>
|
||||
<string name="shader_backend_glasm">GLASM</string>
|
||||
<string name="shader_backend_spirv">SPIR-V</string>
|
||||
|
||||
<!-- NVDEC Emulation -->
|
||||
|
@ -706,7 +633,7 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
|
||||
<!-- ASTC Decoding Method -->
|
||||
<string name="accelerate_astc">ASTC Decoding Method</string>
|
||||
<string name="accelerate_astc_description">Pick how ASTC-compressed textures are decoded for rendering.</string>
|
||||
<string name="accelerate_astc_description">Choose ASTC decoding method: CPU (slow but safe), GPU (fast, recommended), or Async CPU (no stutter but may glitch).</string>
|
||||
|
||||
<!-- ASTC Decoding Method Choices -->
|
||||
<string name="accelerate_astc_cpu">CPU</string>
|
||||
|
@ -715,7 +642,7 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
|
||||
<!-- ASTC Recompression Method -->
|
||||
<string name="astc_recompression">ASTC Recompression Method</string>
|
||||
<string name="astc_recompression_description">Choose how ASTC textures are recompressed to improve compatibility and performance.</string>
|
||||
<string name="astc_recompression_description">Low-end Android GPUs often lack ASTC support, forcing emulators to decompress textures to RGBA8. This option recompresses RGBA8 to BC1/BC3, saving VRAM but reducing quality.</string>
|
||||
|
||||
<!-- ASTC Recompression Method Choices -->
|
||||
<string name="astc_recompression_uncompressed">Uncompressed</string>
|
||||
|
@ -724,7 +651,6 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
|
||||
<!-- ASTC Recompression Method Choices -->
|
||||
<string name="vram_usage_mode">VRAM Usage Mode</string>
|
||||
<string name="vram_usage_mode_description">Control how aggressively the emulator allocates and frees GPU memory.</string>
|
||||
<string name="vram_usage_conservative">Conservative</string>
|
||||
<string name="vram_usage_aggressive">Aggressive</string>
|
||||
|
||||
|
@ -738,7 +664,7 @@ These features may have repercussions on the device\'s temperature, some GPUs be
|
|||
|
||||
<!-- LRU Cache -->
|
||||
<string name="use_lru_cache">Enable LRU Cache</string>
|
||||
<string name="use_lru_cache_description">Enable or disable the Least Recently Used (LRU) cache for improved performance, some games have issue with it, e.g TOTK 1.2.1</string>
|
||||
<string name="use_lru_cache_description">Enable or disable the Least Recently Used (LRU) cache for improved performance</string>
|
||||
|
||||
<!-- Renderer VSync -->
|
||||
<string name="renderer_vsync_immediate">Immediate (Off)</string>
|
||||
|
|
|
@ -187,8 +187,6 @@ if(ANDROID)
|
|||
android/android_common.h
|
||||
android/id_cache.cpp
|
||||
android/id_cache.h
|
||||
android/multiplayer/multiplayer.cpp
|
||||
android/multiplayer/multiplayer.h
|
||||
android/applets/software_keyboard.cpp
|
||||
android/applets/software_keyboard.h
|
||||
)
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "android_common.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -37,15 +34,6 @@ jstring ToJString(JNIEnv* env, std::string_view str) {
|
|||
static_cast<jint>(converted_string.size()));
|
||||
}
|
||||
|
||||
jobjectArray ToJStringArray(JNIEnv* env, const std::vector<std::string>& strs) {
|
||||
jobjectArray array =
|
||||
env->NewObjectArray(static_cast<jsize>(strs.size()), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
||||
for (std::size_t i = 0; i < strs.size(); ++i) {
|
||||
env->SetObjectArrayElement(array, static_cast<jsize>(i), ToJString(env, strs[i]));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
jstring ToJString(JNIEnv* env, std::u16string_view str) {
|
||||
return ToJString(env, Common::UTF16ToUTF8(str));
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
@ -22,7 +19,7 @@ jobject ToJDouble(JNIEnv* env, double value);
|
|||
|
||||
s32 GetJInteger(JNIEnv* env, jobject jinteger);
|
||||
jobject ToJInteger(JNIEnv* env, s32 value);
|
||||
jobjectArray ToJStringArray(JNIEnv* env, const std::vector<std::string>& strs);
|
||||
|
||||
bool GetJBoolean(JNIEnv* env, jobject jboolean);
|
||||
jobject ToJBoolean(JNIEnv* env, bool value);
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "applets/software_keyboard.h"
|
||||
|
@ -11,9 +8,6 @@
|
|||
#include "common/assert.h"
|
||||
#include "common/fs/fs_android.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
#include "common/android/multiplayer/multiplayer.h"
|
||||
#include <network/network.h>
|
||||
|
||||
|
||||
static JavaVM* s_java_vm;
|
||||
static jclass s_native_library_class;
|
||||
|
@ -94,9 +88,6 @@ static jmethodID s_yuzu_input_device_get_supports_vibration;
|
|||
static jmethodID s_yuzu_input_device_vibrate;
|
||||
static jmethodID s_yuzu_input_device_get_axes;
|
||||
static jmethodID s_yuzu_input_device_has_keys;
|
||||
static jmethodID s_add_netplay_message;
|
||||
static jmethodID s_clear_chat;
|
||||
|
||||
|
||||
static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
|
||||
|
||||
|
@ -397,15 +388,6 @@ jmethodID GetYuzuDeviceHasKeys() {
|
|||
return s_yuzu_input_device_has_keys;
|
||||
}
|
||||
|
||||
jmethodID GetAddNetPlayMessage() {
|
||||
return s_add_netplay_message;
|
||||
}
|
||||
|
||||
jmethodID ClearChat() {
|
||||
return s_clear_chat;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -565,10 +547,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||
s_yuzu_input_device_has_keys =
|
||||
env->GetMethodID(yuzu_input_device_interface, "hasKeys", "([I)[Z");
|
||||
env->DeleteLocalRef(yuzu_input_device_interface);
|
||||
s_add_netplay_message = env->GetStaticMethodID(s_native_library_class, "addNetPlayMessage",
|
||||
"(ILjava/lang/String;)V");
|
||||
s_clear_chat = env->GetStaticMethodID(s_native_library_class, "clearChat", "()V");
|
||||
|
||||
|
||||
// Initialize Android Storage
|
||||
Common::FS::Android::RegisterCallbacks(env, s_native_library_class);
|
||||
|
@ -604,8 +582,6 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
|
|||
|
||||
// UnInitialize applets
|
||||
SoftwareKeyboard::CleanupJNI(env);
|
||||
|
||||
NetworkShutdown();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <jni.h>
|
||||
#include <network/network.h>
|
||||
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
|
||||
|
@ -112,8 +108,5 @@ jmethodID GetYuzuDeviceGetSupportsVibration();
|
|||
jmethodID GetYuzuDeviceVibrate();
|
||||
jmethodID GetYuzuDeviceGetAxes();
|
||||
jmethodID GetYuzuDeviceHasKeys();
|
||||
jmethodID GetAddNetPlayMessage();
|
||||
jmethodID ClearChat();
|
||||
|
||||
|
||||
} // namespace Common::Android
|
||||
|
|
|
@ -1,353 +0,0 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "common/android/id_cache.h"
|
||||
#include "multiplayer.h"
|
||||
|
||||
#include "common/android/android_common.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "network/network.h"
|
||||
#include "android/log.h"
|
||||
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
namespace IDCache = Common::Android;
|
||||
Network::RoomNetwork* room_network;
|
||||
|
||||
void AddNetPlayMessage(jint type, jstring msg) {
|
||||
IDCache::GetEnvForThread()->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::GetAddNetPlayMessage(), type, msg);
|
||||
}
|
||||
|
||||
void AddNetPlayMessage(int type, const std::string& msg) {
|
||||
JNIEnv* env = IDCache::GetEnvForThread();
|
||||
AddNetPlayMessage(type, Common::Android::ToJString(env, msg));
|
||||
}
|
||||
|
||||
void ClearChat() {
|
||||
IDCache::GetEnvForThread()->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::ClearChat());
|
||||
}
|
||||
|
||||
|
||||
bool NetworkInit(Network::RoomNetwork* room_network_) {
|
||||
room_network = room_network_;
|
||||
bool result = room_network->Init();
|
||||
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto member = room_network->GetRoomMember().lock()) {
|
||||
// register the network structs to use in slots and signals
|
||||
member->BindOnStateChanged([](const Network::RoomMember::State& state) {
|
||||
if (state == Network::RoomMember::State::Joined ||
|
||||
state == Network::RoomMember::State::Moderator) {
|
||||
NetPlayStatus status;
|
||||
std::string msg;
|
||||
switch (state) {
|
||||
case Network::RoomMember::State::Joined:
|
||||
status = NetPlayStatus::ROOM_JOINED;
|
||||
break;
|
||||
case Network::RoomMember::State::Moderator:
|
||||
status = NetPlayStatus::ROOM_MODERATOR;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||
}
|
||||
});
|
||||
member->BindOnError([](const Network::RoomMember::Error& error) {
|
||||
NetPlayStatus status;
|
||||
std::string msg;
|
||||
switch (error) {
|
||||
case Network::RoomMember::Error::LostConnection:
|
||||
status = NetPlayStatus::LOST_CONNECTION;
|
||||
break;
|
||||
case Network::RoomMember::Error::HostKicked:
|
||||
status = NetPlayStatus::HOST_KICKED;
|
||||
break;
|
||||
case Network::RoomMember::Error::UnknownError:
|
||||
status = NetPlayStatus::UNKNOWN_ERROR;
|
||||
break;
|
||||
case Network::RoomMember::Error::NameCollision:
|
||||
status = NetPlayStatus::NAME_COLLISION;
|
||||
break;
|
||||
case Network::RoomMember::Error::IpCollision:
|
||||
status = NetPlayStatus::MAC_COLLISION;
|
||||
break;
|
||||
case Network::RoomMember::Error::WrongVersion:
|
||||
status = NetPlayStatus::WRONG_VERSION;
|
||||
break;
|
||||
case Network::RoomMember::Error::WrongPassword:
|
||||
status = NetPlayStatus::WRONG_PASSWORD;
|
||||
break;
|
||||
case Network::RoomMember::Error::CouldNotConnect:
|
||||
status = NetPlayStatus::COULD_NOT_CONNECT;
|
||||
break;
|
||||
case Network::RoomMember::Error::RoomIsFull:
|
||||
status = NetPlayStatus::ROOM_IS_FULL;
|
||||
break;
|
||||
case Network::RoomMember::Error::HostBanned:
|
||||
status = NetPlayStatus::HOST_BANNED;
|
||||
break;
|
||||
case Network::RoomMember::Error::PermissionDenied:
|
||||
status = NetPlayStatus::PERMISSION_DENIED;
|
||||
break;
|
||||
case Network::RoomMember::Error::NoSuchUser:
|
||||
status = NetPlayStatus::NO_SUCH_USER;
|
||||
break;
|
||||
}
|
||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||
});
|
||||
member->BindOnStatusMessageReceived([](const Network::StatusMessageEntry& status_message) {
|
||||
NetPlayStatus status = NetPlayStatus::NO_ERROR;
|
||||
std::string msg(status_message.nickname);
|
||||
switch (status_message.type) {
|
||||
case Network::IdMemberJoin:
|
||||
status = NetPlayStatus::MEMBER_JOIN;
|
||||
break;
|
||||
case Network::IdMemberLeave:
|
||||
status = NetPlayStatus::MEMBER_LEAVE;
|
||||
break;
|
||||
case Network::IdMemberKicked:
|
||||
status = NetPlayStatus::MEMBER_KICKED;
|
||||
break;
|
||||
case Network::IdMemberBanned:
|
||||
status = NetPlayStatus::MEMBER_BANNED;
|
||||
break;
|
||||
case Network::IdAddressUnbanned:
|
||||
status = NetPlayStatus::ADDRESS_UNBANNED;
|
||||
break;
|
||||
}
|
||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||
});
|
||||
member->BindOnChatMessageReceived([](const Network::ChatEntry& chat) {
|
||||
NetPlayStatus status = NetPlayStatus::CHAT_MESSAGE;
|
||||
std::string msg(chat.nickname);
|
||||
msg += ": ";
|
||||
msg += chat.message;
|
||||
AddNetPlayMessage(static_cast<int>(status), msg);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
NetPlayStatus NetPlayCreateRoom(const std::string& ipaddress, int port,
|
||||
const std::string& username, const std::string& password,
|
||||
const std::string& room_name, int max_players) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "NetPlay", "NetPlayCreateRoom called with ipaddress: %s, port: %d, username: %s, room_name: %s, max_players: %d", ipaddress.c_str(), port, username.c_str(), room_name.c_str(), max_players);
|
||||
|
||||
auto member = room_network->GetRoomMember().lock();
|
||||
if (!member) {
|
||||
return NetPlayStatus::NETWORK_ERROR;
|
||||
}
|
||||
|
||||
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
|
||||
return NetPlayStatus::ALREADY_IN_ROOM;
|
||||
}
|
||||
|
||||
auto room = room_network->GetRoom().lock();
|
||||
if (!room) {
|
||||
return NetPlayStatus::NETWORK_ERROR;
|
||||
}
|
||||
|
||||
if (room_name.length() < 3 || room_name.length() > 20) {
|
||||
return NetPlayStatus::CREATE_ROOM_ERROR;
|
||||
}
|
||||
|
||||
// Placeholder game info
|
||||
const AnnounceMultiplayerRoom::GameInfo game{
|
||||
.name = "Default Game",
|
||||
.id = 0, // Default program ID
|
||||
};
|
||||
|
||||
port = (port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
||||
|
||||
if (!room->Create(room_name, "", ipaddress, static_cast<u16>(port), password,
|
||||
static_cast<u32>(std::min(max_players, 16)), username, game, nullptr, {})) {
|
||||
return NetPlayStatus::CREATE_ROOM_ERROR;
|
||||
}
|
||||
|
||||
// Failsafe timer to avoid joining before creation
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
member->Join(username, ipaddress.c_str(), static_cast<u16>(port), 0, Network::NoPreferredIP, password, "");
|
||||
|
||||
// Failsafe timer to avoid joining before creation
|
||||
for (int i = 0; i < 5; i++) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
if (member->GetState() == Network::RoomMember::State::Joined ||
|
||||
member->GetState() == Network::RoomMember::State::Moderator) {
|
||||
return NetPlayStatus::NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// If join failed while room is created, clean up the room
|
||||
room->Destroy();
|
||||
return NetPlayStatus::CREATE_ROOM_ERROR;
|
||||
}
|
||||
|
||||
NetPlayStatus NetPlayJoinRoom(const std::string& ipaddress, int port,
|
||||
const std::string& username, const std::string& password) {
|
||||
auto member = room_network->GetRoomMember().lock();
|
||||
if (!member) {
|
||||
return NetPlayStatus::NETWORK_ERROR;
|
||||
}
|
||||
|
||||
port =
|
||||
(port == 0) ? Network::DefaultRoomPort : static_cast<u16>(port);
|
||||
|
||||
|
||||
if (member->GetState() == Network::RoomMember::State::Joining || member->IsConnected()) {
|
||||
return NetPlayStatus::ALREADY_IN_ROOM;
|
||||
}
|
||||
|
||||
member->Join(username, ipaddress.c_str(), static_cast<u16>(port), 0, Network::NoPreferredIP, password, "");
|
||||
|
||||
// Wait a bit for the connection and join process to complete
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
if (member->GetState() == Network::RoomMember::State::Joined ||
|
||||
member->GetState() == Network::RoomMember::State::Moderator) {
|
||||
return NetPlayStatus::NO_ERROR;
|
||||
}
|
||||
|
||||
if (!member->IsConnected()) {
|
||||
return NetPlayStatus::COULD_NOT_CONNECT;
|
||||
}
|
||||
|
||||
return NetPlayStatus::WRONG_PASSWORD;
|
||||
}
|
||||
|
||||
void NetPlaySendMessage(const std::string& msg) {
|
||||
if (auto room = room_network->GetRoomMember().lock()) {
|
||||
if (room->GetState() != Network::RoomMember::State::Joined &&
|
||||
room->GetState() != Network::RoomMember::State::Moderator) {
|
||||
|
||||
return;
|
||||
}
|
||||
room->SendChatMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlayKickUser(const std::string& username) {
|
||||
if (auto room = room_network->GetRoomMember().lock()) {
|
||||
auto members = room->GetMemberInformation();
|
||||
auto it = std::find_if(members.begin(), members.end(),
|
||||
[&username](const Network::RoomMember::MemberInformation& member) {
|
||||
return member.nickname == username;
|
||||
});
|
||||
if (it != members.end()) {
|
||||
room->SendModerationRequest(Network::RoomMessageTypes::IdModKick, username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlayBanUser(const std::string& username) {
|
||||
if (auto room = room_network->GetRoomMember().lock()) {
|
||||
auto members = room->GetMemberInformation();
|
||||
auto it = std::find_if(members.begin(), members.end(),
|
||||
[&username](const Network::RoomMember::MemberInformation& member) {
|
||||
return member.nickname == username;
|
||||
});
|
||||
if (it != members.end()) {
|
||||
room->SendModerationRequest(Network::RoomMessageTypes::IdModBan, username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlayUnbanUser(const std::string& username) {
|
||||
if (auto room = room_network->GetRoomMember().lock()) {
|
||||
room->SendModerationRequest(Network::RoomMessageTypes::IdModUnban, username);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> NetPlayRoomInfo() {
|
||||
std::vector<std::string> info_list;
|
||||
if (auto room = room_network->GetRoomMember().lock()) {
|
||||
auto members = room->GetMemberInformation();
|
||||
if (!members.empty()) {
|
||||
// name and max players
|
||||
auto room_info = room->GetRoomInformation();
|
||||
info_list.push_back(room_info.name + "|" + std::to_string(room_info.member_slots));
|
||||
// all members
|
||||
for (const auto& member : members) {
|
||||
info_list.push_back(member.nickname);
|
||||
}
|
||||
}
|
||||
}
|
||||
return info_list;
|
||||
}
|
||||
|
||||
bool NetPlayIsJoined() {
|
||||
auto member = room_network->GetRoomMember().lock();
|
||||
if (!member) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (member->GetState() == Network::RoomMember::State::Joined ||
|
||||
member->GetState() == Network::RoomMember::State::Moderator);
|
||||
}
|
||||
|
||||
bool NetPlayIsHostedRoom() {
|
||||
if (auto room = room_network->GetRoom().lock()) {
|
||||
return room->GetState() == Network::Room::State::Open;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetPlayLeaveRoom() {
|
||||
if (auto room = room_network->GetRoom().lock()) {
|
||||
// if you are in a room, leave it
|
||||
if (auto member = room_network->GetRoomMember().lock()) {
|
||||
member->Leave();
|
||||
}
|
||||
|
||||
ClearChat();
|
||||
|
||||
// if you are hosting a room, also stop hosting
|
||||
if (room->GetState() == Network::Room::State::Open) {
|
||||
room->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkShutdown() {
|
||||
room_network->Shutdown();
|
||||
}
|
||||
|
||||
bool NetPlayIsModerator() {
|
||||
auto member = room_network->GetRoomMember().lock();
|
||||
if (!member) {
|
||||
return false;
|
||||
}
|
||||
return member->GetState() == Network::RoomMember::State::Moderator;
|
||||
}
|
||||
|
||||
std::vector<std::string> NetPlayGetBanList() {
|
||||
std::vector<std::string> ban_list;
|
||||
if (auto room = room_network->GetRoom().lock()) {
|
||||
auto [username_bans, ip_bans] = room->GetBanList();
|
||||
|
||||
// Add username bans
|
||||
for (const auto& username : username_bans) {
|
||||
ban_list.push_back(username);
|
||||
}
|
||||
|
||||
// Add IP bans
|
||||
for (const auto& ip : ip_bans) {
|
||||
ban_list.push_back(ip);
|
||||
}
|
||||
}
|
||||
return ban_list;
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright 2024 Mandarine Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <common/common_types.h>
|
||||
#include <network/network.h>
|
||||
|
||||
enum class NetPlayStatus : s32 {
|
||||
NO_ERROR,
|
||||
|
||||
NETWORK_ERROR,
|
||||
LOST_CONNECTION,
|
||||
NAME_COLLISION,
|
||||
MAC_COLLISION,
|
||||
CONSOLE_ID_COLLISION,
|
||||
WRONG_VERSION,
|
||||
WRONG_PASSWORD,
|
||||
COULD_NOT_CONNECT,
|
||||
ROOM_IS_FULL,
|
||||
HOST_BANNED,
|
||||
PERMISSION_DENIED,
|
||||
NO_SUCH_USER,
|
||||
ALREADY_IN_ROOM,
|
||||
CREATE_ROOM_ERROR,
|
||||
HOST_KICKED,
|
||||
UNKNOWN_ERROR,
|
||||
|
||||
ROOM_UNINITIALIZED,
|
||||
ROOM_IDLE,
|
||||
ROOM_JOINING,
|
||||
ROOM_JOINED,
|
||||
ROOM_MODERATOR,
|
||||
|
||||
MEMBER_JOIN,
|
||||
MEMBER_LEAVE,
|
||||
MEMBER_KICKED,
|
||||
MEMBER_BANNED,
|
||||
ADDRESS_UNBANNED,
|
||||
|
||||
CHAT_MESSAGE,
|
||||
};
|
||||
|
||||
bool NetworkInit(Network::RoomNetwork* room_network);
|
||||
NetPlayStatus NetPlayCreateRoom(const std::string& ipaddress, int port,
|
||||
const std::string& username, const std::string& password,
|
||||
const std::string& room_name, int max_players);
|
||||
NetPlayStatus NetPlayJoinRoom(const std::string& ipaddress, int port,
|
||||
const std::string& username, const std::string& password);
|
||||
std::vector<std::string> NetPlayRoomInfo();
|
||||
bool NetPlayIsJoined();
|
||||
bool NetPlayIsHostedRoom();
|
||||
bool NetPlayIsModerator();
|
||||
void NetPlaySendMessage(const std::string& msg);
|
||||
void NetPlayKickUser(const std::string& username);
|
||||
void NetPlayBanUser(const std::string& username);
|
||||
void NetPlayLeaveRoom();
|
||||
std::string NetPlayGetConsoleId();
|
||||
void NetworkShutdown();
|
||||
std::vector<std::string> NetPlayGetBanList();
|
||||
void NetPlayUnbanUser(const std::string& username);
|
|
@ -1,9 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
@ -38,6 +35,7 @@ struct RoomInformation {
|
|||
u16 port; ///< The port of this room
|
||||
GameInfo preferred_game; ///< Game to advertise that you want to play
|
||||
std::string host_username; ///< Forum username of the host
|
||||
bool enable_yuzu_mods; ///< Allow yuzu Moderators to moderate on this room
|
||||
};
|
||||
|
||||
struct Room {
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
// yuzu data directories
|
||||
|
||||
#define EDEN_DIR "eden"
|
||||
#define YUZU_DIR "yuzu"
|
||||
#define PORTABLE_DIR "user"
|
||||
|
||||
// Sub-directories contained within a yuzu data directory
|
||||
|
@ -28,10 +25,6 @@
|
|||
#define SHADER_DIR "shader"
|
||||
#define TAS_DIR "tas"
|
||||
#define ICONS_DIR "icons"
|
||||
#define CITRON_DIR "citron"
|
||||
#define SUDACHI_DIR "sudachi"
|
||||
#define YUZU_DIR "yuzu"
|
||||
#define SUYU_DIR "suyu"
|
||||
|
||||
// yuzu-specific files
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
|
@ -60,10 +56,10 @@ namespace fs = std::filesystem;
|
|||
|
||||
/**
|
||||
* The PathManagerImpl is a singleton allowing to manage the mapping of
|
||||
* EdenPath enums to real filesystem paths.
|
||||
* This class provides 2 functions: GetEdenPathImpl and SetEdenPathImpl.
|
||||
* These are used by GetEdenPath and SetEdenPath respectively to get or modify
|
||||
* the path mapped by the EdenPath enum.
|
||||
* YuzuPath enums to real filesystem paths.
|
||||
* This class provides 2 functions: GetYuzuPathImpl and SetYuzuPathImpl.
|
||||
* These are used by GetYuzuPath and SetYuzuPath respectively to get or modify
|
||||
* the path mapped by the YuzuPath enum.
|
||||
*/
|
||||
class PathManagerImpl {
|
||||
public:
|
||||
|
@ -79,99 +75,62 @@ public:
|
|||
PathManagerImpl(PathManagerImpl&&) = delete;
|
||||
PathManagerImpl& operator=(PathManagerImpl&&) = delete;
|
||||
|
||||
[[nodiscard]] const fs::path& GetEdenPathImpl(EdenPath eden_path) {
|
||||
return eden_paths.at(eden_path);
|
||||
[[nodiscard]] const fs::path& GetYuzuPathImpl(YuzuPath yuzu_path) {
|
||||
return yuzu_paths.at(yuzu_path);
|
||||
}
|
||||
|
||||
[[nodiscard]] const fs::path& GetLegacyPathImpl(LegacyPath legacy_path) {
|
||||
return legacy_paths.at(legacy_path);
|
||||
void SetYuzuPathImpl(YuzuPath yuzu_path, const fs::path& new_path) {
|
||||
yuzu_paths.insert_or_assign(yuzu_path, new_path);
|
||||
}
|
||||
|
||||
void CreateEdenPaths() {
|
||||
std::for_each(eden_paths.begin(), eden_paths.end(), [](auto &path) {
|
||||
void(FS::CreateDir(path.second));
|
||||
});
|
||||
}
|
||||
|
||||
void SetEdenPathImpl(EdenPath eden_path, const fs::path& new_path) {
|
||||
eden_paths.insert_or_assign(eden_path, new_path);
|
||||
}
|
||||
|
||||
void SetLegacyPathImpl(LegacyPath legacy_path, const fs::path& new_path) {
|
||||
legacy_paths.insert_or_assign(legacy_path, new_path);
|
||||
}
|
||||
|
||||
void Reinitialize(fs::path eden_path = {}) {
|
||||
fs::path eden_path_cache;
|
||||
fs::path eden_path_config;
|
||||
void Reinitialize(fs::path yuzu_path = {}) {
|
||||
fs::path yuzu_path_cache;
|
||||
fs::path yuzu_path_config;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef YUZU_ENABLE_PORTABLE
|
||||
eden_path = GetExeDirectory() / PORTABLE_DIR;
|
||||
yuzu_path = GetExeDirectory() / PORTABLE_DIR;
|
||||
#endif
|
||||
if (!IsDir(eden_path)) {
|
||||
eden_path = GetAppDataRoamingDirectory() / EDEN_DIR;
|
||||
if (!IsDir(yuzu_path)) {
|
||||
yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR;
|
||||
}
|
||||
|
||||
eden_path_cache = eden_path / CACHE_DIR;
|
||||
eden_path_config = eden_path / CONFIG_DIR;
|
||||
|
||||
#define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetAppDataRoamingDirectory() / upperName##_DIR); \
|
||||
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetAppDataRoamingDirectory() / upperName##_DIR / CONFIG_DIR); \
|
||||
GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetAppDataRoamingDirectory() / upperName##_DIR / CACHE_DIR);
|
||||
|
||||
LEGACY_PATH(Citron, CITRON)
|
||||
LEGACY_PATH(Sudachi, SUDACHI)
|
||||
LEGACY_PATH(Yuzu, YUZU)
|
||||
LEGACY_PATH(Suyu, SUYU)
|
||||
#undef LEGACY_PATH
|
||||
|
||||
yuzu_path_cache = yuzu_path / CACHE_DIR;
|
||||
yuzu_path_config = yuzu_path / CONFIG_DIR;
|
||||
#elif ANDROID
|
||||
ASSERT(!eden_path.empty());
|
||||
eden_path_cache = eden_path / CACHE_DIR;
|
||||
eden_path_config = eden_path / CONFIG_DIR;
|
||||
ASSERT(!yuzu_path.empty());
|
||||
yuzu_path_cache = yuzu_path / CACHE_DIR;
|
||||
yuzu_path_config = yuzu_path / CONFIG_DIR;
|
||||
#else
|
||||
#ifdef YUZU_ENABLE_PORTABLE
|
||||
eden_path = GetCurrentDir() / PORTABLE_DIR;
|
||||
yuzu_path = GetCurrentDir() / PORTABLE_DIR;
|
||||
#endif
|
||||
if (Exists(eden_path) && IsDir(eden_path)) {
|
||||
eden_path_cache = eden_path / CACHE_DIR;
|
||||
eden_path_config = eden_path / CONFIG_DIR;
|
||||
if (Exists(yuzu_path) && IsDir(yuzu_path)) {
|
||||
yuzu_path_cache = yuzu_path / CACHE_DIR;
|
||||
yuzu_path_config = yuzu_path / CONFIG_DIR;
|
||||
} else {
|
||||
eden_path = GetDataDirectory("XDG_DATA_HOME") / EDEN_DIR;
|
||||
eden_path_cache = GetDataDirectory("XDG_CACHE_HOME") / EDEN_DIR;
|
||||
eden_path_config = GetDataDirectory("XDG_CONFIG_HOME") / EDEN_DIR;
|
||||
yuzu_path = GetDataDirectory("XDG_DATA_HOME") / YUZU_DIR;
|
||||
yuzu_path_cache = GetDataDirectory("XDG_CACHE_HOME") / YUZU_DIR;
|
||||
yuzu_path_config = GetDataDirectory("XDG_CONFIG_HOME") / YUZU_DIR;
|
||||
}
|
||||
|
||||
#define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetDataDirectory("XDG_DATA_HOME") / upperName##_DIR); \
|
||||
GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetDataDirectory("XDG_CONFIG_HOME") / upperName##_DIR); \
|
||||
GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetDataDirectory("XDG_CACHE_HOME") / upperName##_DIR);
|
||||
|
||||
LEGACY_PATH(Citron, CITRON)
|
||||
LEGACY_PATH(Sudachi, SUDACHI)
|
||||
LEGACY_PATH(Yuzu, YUZU)
|
||||
LEGACY_PATH(Suyu, SUYU)
|
||||
|
||||
#undef LEGACY_PATH
|
||||
|
||||
#endif
|
||||
|
||||
GenerateEdenPath(EdenPath::EdenDir, eden_path);
|
||||
GenerateEdenPath(EdenPath::AmiiboDir, eden_path / AMIIBO_DIR);
|
||||
GenerateEdenPath(EdenPath::CacheDir, eden_path_cache);
|
||||
GenerateEdenPath(EdenPath::ConfigDir, eden_path_config);
|
||||
GenerateEdenPath(EdenPath::CrashDumpsDir, eden_path / CRASH_DUMPS_DIR);
|
||||
GenerateEdenPath(EdenPath::DumpDir, eden_path / DUMP_DIR);
|
||||
GenerateEdenPath(EdenPath::KeysDir, eden_path / KEYS_DIR);
|
||||
GenerateEdenPath(EdenPath::LoadDir, eden_path / LOAD_DIR);
|
||||
GenerateEdenPath(EdenPath::LogDir, eden_path / LOG_DIR);
|
||||
GenerateEdenPath(EdenPath::NANDDir, eden_path / NAND_DIR);
|
||||
GenerateEdenPath(EdenPath::PlayTimeDir, eden_path / PLAY_TIME_DIR);
|
||||
GenerateEdenPath(EdenPath::ScreenshotsDir, eden_path / SCREENSHOTS_DIR);
|
||||
GenerateEdenPath(EdenPath::SDMCDir, eden_path / SDMC_DIR);
|
||||
GenerateEdenPath(EdenPath::ShaderDir, eden_path / SHADER_DIR);
|
||||
GenerateEdenPath(EdenPath::TASDir, eden_path / TAS_DIR);
|
||||
GenerateEdenPath(EdenPath::IconsDir, eden_path / ICONS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path);
|
||||
GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR);
|
||||
GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache);
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config);
|
||||
GenerateYuzuPath(YuzuPath::CrashDumpsDir, yuzu_path / CRASH_DUMPS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR);
|
||||
GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);
|
||||
GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR);
|
||||
GenerateYuzuPath(YuzuPath::NANDDir, yuzu_path / NAND_DIR);
|
||||
GenerateYuzuPath(YuzuPath::PlayTimeDir, yuzu_path / PLAY_TIME_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ScreenshotsDir, yuzu_path / SCREENSHOTS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR);
|
||||
GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -181,17 +140,13 @@ private:
|
|||
|
||||
~PathManagerImpl() = default;
|
||||
|
||||
void GenerateEdenPath(EdenPath eden_path, const fs::path& new_path) {
|
||||
// Defer path creation
|
||||
SetEdenPathImpl(eden_path, new_path);
|
||||
void GenerateYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
|
||||
void(FS::CreateDir(new_path));
|
||||
|
||||
SetYuzuPathImpl(yuzu_path, new_path);
|
||||
}
|
||||
|
||||
void GenerateLegacyPath(LegacyPath legacy_path, const fs::path& new_path) {
|
||||
SetLegacyPathImpl(legacy_path, new_path);
|
||||
}
|
||||
|
||||
std::unordered_map<EdenPath, fs::path> eden_paths;
|
||||
std::unordered_map<LegacyPath, fs::path> legacy_paths;
|
||||
std::unordered_map<YuzuPath, fs::path> yuzu_paths;
|
||||
};
|
||||
|
||||
bool ValidatePath(const fs::path& path) {
|
||||
|
@ -275,35 +230,22 @@ void SetAppDirectory(const std::string& app_directory) {
|
|||
PathManagerImpl::GetInstance().Reinitialize(app_directory);
|
||||
}
|
||||
|
||||
const fs::path& GetEdenPath(EdenPath eden_path) {
|
||||
return PathManagerImpl::GetInstance().GetEdenPathImpl(eden_path);
|
||||
const fs::path& GetYuzuPath(YuzuPath yuzu_path) {
|
||||
return PathManagerImpl::GetInstance().GetYuzuPathImpl(yuzu_path);
|
||||
}
|
||||
|
||||
const std::filesystem::path& GetLegacyPath(LegacyPath legacy_path) {
|
||||
return PathManagerImpl::GetInstance().GetLegacyPathImpl(legacy_path);
|
||||
std::string GetYuzuPathString(YuzuPath yuzu_path) {
|
||||
return PathToUTF8String(GetYuzuPath(yuzu_path));
|
||||
}
|
||||
|
||||
std::string GetEdenPathString(EdenPath eden_path) {
|
||||
return PathToUTF8String(GetEdenPath(eden_path));
|
||||
}
|
||||
|
||||
std::string GetLegacyPathString(LegacyPath legacy_path) {
|
||||
return PathToUTF8String(GetLegacyPath(legacy_path));
|
||||
}
|
||||
|
||||
void SetEdenPath(EdenPath eden_path, const fs::path& new_path) {
|
||||
void SetYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
|
||||
if (!FS::IsDir(new_path)) {
|
||||
LOG_ERROR(Common_Filesystem, "Filesystem object at new_path={} is not a directory",
|
||||
PathToUTF8String(new_path));
|
||||
return;
|
||||
}
|
||||
|
||||
PathManagerImpl::GetInstance().SetEdenPathImpl(eden_path, new_path);
|
||||
}
|
||||
|
||||
void CreateEdenPaths()
|
||||
{
|
||||
PathManagerImpl::GetInstance().CreateEdenPaths();
|
||||
PathManagerImpl::GetInstance().SetYuzuPathImpl(yuzu_path, new_path);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2025 eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
@ -13,8 +10,8 @@
|
|||
|
||||
namespace Common::FS {
|
||||
|
||||
enum class EdenPath {
|
||||
EdenDir, // Where yuzu stores its data.
|
||||
enum class YuzuPath {
|
||||
YuzuDir, // Where yuzu stores its data.
|
||||
AmiiboDir, // Where Amiibo backups are stored.
|
||||
CacheDir, // Where cached filesystem data is stored.
|
||||
ConfigDir, // Where config files are stored.
|
||||
|
@ -32,24 +29,6 @@ enum class EdenPath {
|
|||
IconsDir, // Where Icons for Windows shortcuts are stored.
|
||||
};
|
||||
|
||||
enum LegacyPath {
|
||||
CitronDir, // Citron Directories for migration
|
||||
CitronConfigDir,
|
||||
CitronCacheDir,
|
||||
|
||||
SudachiDir, // Sudachi Directories for migration
|
||||
SudachiConfigDir,
|
||||
SudachiCacheDir,
|
||||
|
||||
YuzuDir, // Yuzu Directories for migration
|
||||
YuzuConfigDir,
|
||||
YuzuCacheDir,
|
||||
|
||||
SuyuDir, // Suyu Directories for migration
|
||||
SuyuConfigDir,
|
||||
SuyuCacheDir,
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates a given path.
|
||||
*
|
||||
|
@ -214,62 +193,39 @@ template <typename Path>
|
|||
void SetAppDirectory(const std::string& app_directory);
|
||||
|
||||
/**
|
||||
* Gets the filesystem path associated with the EdenPath enum.
|
||||
* Gets the filesystem path associated with the YuzuPath enum.
|
||||
*
|
||||
* @param eden_path EdenPath enum
|
||||
* @param yuzu_path YuzuPath enum
|
||||
*
|
||||
* @returns The filesystem path associated with the EdenPath enum.
|
||||
* @returns The filesystem path associated with the YuzuPath enum.
|
||||
*/
|
||||
[[nodiscard]] const std::filesystem::path& GetEdenPath(EdenPath eden_path);
|
||||
[[nodiscard]] const std::filesystem::path& GetYuzuPath(YuzuPath yuzu_path);
|
||||
|
||||
/**
|
||||
* Gets the filesystem path associated with the LegacyPath enum.
|
||||
* Gets the filesystem path associated with the YuzuPath enum as a UTF-8 encoded std::string.
|
||||
*
|
||||
* @param legacy_path LegacyPath enum
|
||||
* @param yuzu_path YuzuPath enum
|
||||
*
|
||||
* @returns The filesystem path associated with the LegacyPath enum.
|
||||
* @returns The filesystem path associated with the YuzuPath enum as a UTF-8 encoded std::string.
|
||||
*/
|
||||
[[nodiscard]] const std::filesystem::path& GetLegacyPath(LegacyPath legacy_path);
|
||||
[[nodiscard]] std::string GetYuzuPathString(YuzuPath yuzu_path);
|
||||
|
||||
/**
|
||||
* Gets the filesystem path associated with the EdenPath enum as a UTF-8 encoded std::string.
|
||||
*
|
||||
* @param eden_path EdenPath enum
|
||||
*
|
||||
* @returns The filesystem path associated with the EdenPath enum as a UTF-8 encoded std::string.
|
||||
*/
|
||||
[[nodiscard]] std::string GetEdenPathString(EdenPath eden_path);
|
||||
|
||||
/**
|
||||
* Gets the filesystem path associated with the LegacyPath enum as a UTF-8 encoded std::string.
|
||||
*
|
||||
* @param legacy_path LegacyPath enum
|
||||
*
|
||||
* @returns The filesystem path associated with the LegacyPath enum as a UTF-8 encoded std::string.
|
||||
*/
|
||||
[[nodiscard]] std::string GetLegacyPathString(LegacyPath legacy_path);
|
||||
|
||||
/**
|
||||
* Sets a new filesystem path associated with the EdenPath enum.
|
||||
* Sets a new filesystem path associated with the YuzuPath enum.
|
||||
* If the filesystem object at new_path is not a directory, this function will not do anything.
|
||||
*
|
||||
* @param eden_path EdenPath enum
|
||||
* @param yuzu_path YuzuPath enum
|
||||
* @param new_path New filesystem path
|
||||
*/
|
||||
void SetEdenPath(EdenPath eden_path, const std::filesystem::path& new_path);
|
||||
|
||||
/**
|
||||
* Creates all necessary Eden paths in the filesystem.
|
||||
*/
|
||||
void CreateEdenPaths();
|
||||
void SetYuzuPath(YuzuPath yuzu_path, const std::filesystem::path& new_path);
|
||||
|
||||
#ifdef _WIN32
|
||||
template <typename Path>
|
||||
void SetEdenPath(EdenPath eden_path, const Path& new_path) {
|
||||
void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
|
||||
if constexpr (IsChar<typename Path::value_type>) {
|
||||
SetEdenPath(eden_path, ToU8String(new_path));
|
||||
SetYuzuPath(yuzu_path, ToU8String(new_path));
|
||||
} else {
|
||||
SetEdenPath(eden_path, std::filesystem::path{new_path});
|
||||
SetYuzuPath(yuzu_path, std::filesystem::path{new_path});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -88,8 +88,8 @@ public:
|
|||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
static_cast<void>(FS::RemoveFile(old_filename));
|
||||
static_cast<void>(FS::RenameFile(filename, old_filename));
|
||||
|
||||
|
@ -106,10 +106,10 @@ public:
|
|||
|
||||
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
|
||||
|
||||
// Option to log each line rather than 4k buffers
|
||||
if (Settings::values.log_flush_lines.GetValue()) {
|
||||
file->Flush();
|
||||
}
|
||||
// Option to log each line rather than 4k buffers
|
||||
#ifdef YUZU_LOG_BY_LINE
|
||||
file->Flush();
|
||||
#endif
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
|
@ -200,7 +200,7 @@ public:
|
|||
return;
|
||||
}
|
||||
using namespace Common::FS;
|
||||
const auto& log_dir = GetEdenPath(EdenPath::LogDir);
|
||||
const auto& log_dir = GetYuzuPath(YuzuPath::LogDir);
|
||||
void(CreateDir(log_dir));
|
||||
Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Common {
|
|||
void ConfigureNvidiaEnvironmentFlags() {
|
||||
#ifdef _WIN32
|
||||
const auto nvidia_shader_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir) / "nvidia";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir) / "nvidia";
|
||||
|
||||
if (!Common::FS::CreateDirs(nvidia_shader_dir)) {
|
||||
return;
|
||||
|
|
|
@ -131,11 +131,11 @@ void LogSettings() {
|
|||
log_setting(name, setting->Canonicalize());
|
||||
}
|
||||
}
|
||||
log_path("DataStorage_CacheDir", Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir));
|
||||
log_path("DataStorage_ConfigDir", Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir));
|
||||
log_path("DataStorage_LoadDir", Common::FS::GetEdenPath(Common::FS::EdenPath::LoadDir));
|
||||
log_path("DataStorage_NANDDir", Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir));
|
||||
log_path("DataStorage_SDMCDir", Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir));
|
||||
log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir));
|
||||
log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir));
|
||||
log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir));
|
||||
log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir));
|
||||
log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir));
|
||||
}
|
||||
|
||||
void UpdateGPUAccuracy() {
|
||||
|
|
|
@ -198,9 +198,7 @@ struct Values {
|
|||
MemoryLayout::Memory_4Gb,
|
||||
MemoryLayout::Memory_8Gb,
|
||||
"memory_layout_mode",
|
||||
Category::Core,
|
||||
Specialization::Default,
|
||||
false};
|
||||
Category::Core};
|
||||
SwitchableSetting<bool> use_speed_limit{
|
||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true};
|
||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||
|
@ -214,11 +212,13 @@ struct Values {
|
|||
true,
|
||||
&use_speed_limit};
|
||||
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default};
|
||||
//SwitchableSetting<bool> use_nce{linkage, true, "use_nce", Category::Core};
|
||||
SwitchableSetting<bool> use_nce{linkage, true, "Use Native Code Execution", Category::Core};
|
||||
|
||||
// Memory
|
||||
#ifdef ANDROID
|
||||
SwitchableSetting<bool> use_gpu_memory_manager{linkage, false, "Use GPU Memory Manager", Category::Core};
|
||||
SwitchableSetting<bool> enable_memory_snapshots{linkage, false, "Enable Memory Snapshots", Category::Core};
|
||||
SwitchableSetting<bool> lru_cache_enabled{linkage, true, "use_lru_cache", Category::System};
|
||||
#endif
|
||||
|
||||
// Cpu
|
||||
SwitchableSetting<CpuBackend, true> cpu_backend{linkage,
|
||||
|
@ -629,9 +629,7 @@ struct Values {
|
|||
|
||||
// Miscellaneous
|
||||
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
||||
Setting<bool> log_flush_lines{linkage, false, "flush_lines", Category::Miscellaneous};
|
||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
|
||||
Setting<bool> first_launch{linkage, true, "first_launch", Category::Miscellaneous};
|
||||
|
||||
// Network
|
||||
Setting<std::string> network_interface{linkage, std::string(), "network_interface",
|
||||
|
|
|
@ -372,7 +372,7 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source)
|
|||
|
||||
std::optional<Key128> DeriveSDSeed() {
|
||||
const auto system_save_43_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000043";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000043";
|
||||
const Common::FS::IOFile save_43{system_save_43_path, Common::FS::FileAccessMode::Read,
|
||||
Common::FS::FileType::BinaryFile};
|
||||
|
||||
|
@ -381,7 +381,7 @@ std::optional<Key128> DeriveSDSeed() {
|
|||
}
|
||||
|
||||
const auto sd_private_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir) / "Nintendo/Contents/private";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "Nintendo/Contents/private";
|
||||
|
||||
const Common::FS::IOFile sd_private{sd_private_path, Common::FS::FileAccessMode::Read,
|
||||
Common::FS::FileType::BinaryFile};
|
||||
|
@ -640,7 +640,7 @@ KeyManager::KeyManager() {
|
|||
|
||||
void KeyManager::ReloadKeys() {
|
||||
// Initialize keys
|
||||
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||
|
||||
if (!Common::FS::CreateDir(yuzu_keys_dir)) {
|
||||
LOG_ERROR(Core, "Failed to create the keys directory.");
|
||||
|
@ -847,7 +847,7 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const {
|
|||
template <size_t Size>
|
||||
void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
|
||||
const std::array<u8, Size>& key) {
|
||||
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||
|
||||
std::string filename = "title.keys_autogenerated";
|
||||
|
||||
|
@ -947,7 +947,7 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
|
|||
}
|
||||
|
||||
bool KeyManager::KeyFileExists(bool title) {
|
||||
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||
|
||||
if (title) {
|
||||
return Common::FS::Exists(yuzu_keys_dir / "title.keys");
|
||||
|
@ -1197,7 +1197,7 @@ void KeyManager::PopulateTickets() {
|
|||
std::vector<Ticket> tickets;
|
||||
|
||||
const auto system_save_e1_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e1";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e1";
|
||||
if (Common::FS::Exists(system_save_e1_path)) {
|
||||
const Common::FS::IOFile save_e1{system_save_e1_path, Common::FS::FileAccessMode::Read,
|
||||
Common::FS::FileType::BinaryFile};
|
||||
|
@ -1206,7 +1206,7 @@ void KeyManager::PopulateTickets() {
|
|||
}
|
||||
|
||||
const auto system_save_e2_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/80000000000000e2";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/80000000000000e2";
|
||||
if (Common::FS::Exists(system_save_e2_path)) {
|
||||
const Common::FS::IOFile save_e2{system_save_e2_path, Common::FS::FileAccessMode::Read,
|
||||
Common::FS::FileType::BinaryFile};
|
||||
|
|
|
@ -83,7 +83,7 @@ VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
|
|||
VirtualFilesystem file_system) const {
|
||||
auto& keys = Core::Crypto::KeyManager::Instance();
|
||||
Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
|
||||
Common::FS::GetEdenPathString(Common::FS::EdenPath::NANDDir), OpenMode::Read)};
|
||||
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir), OpenMode::Read)};
|
||||
keys.PopulateFromPartitionData(pdm);
|
||||
|
||||
switch (id) {
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Service::Account {
|
|||
constexpr std::size_t THUMBNAIL_SIZE = 0x24000;
|
||||
|
||||
static std::filesystem::path GetImagePath(const Common::UUID& uuid) {
|
||||
return Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) /
|
||||
return Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) /
|
||||
fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());
|
||||
}
|
||||
|
||||
|
|
|
@ -377,7 +377,7 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase&
|
|||
}
|
||||
|
||||
void ProfileManager::ParseUserSaveFile() {
|
||||
const auto save_path(FS::GetEdenPath(FS::EdenPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
|
||||
const auto save_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
|
||||
"profiles.dat");
|
||||
const FS::IOFile save(save_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
|
||||
|
||||
|
@ -429,12 +429,12 @@ void ProfileManager::WriteUserSaveFile() {
|
|||
};
|
||||
}
|
||||
|
||||
const auto raw_path(FS::GetEdenPath(FS::EdenPath::NANDDir) / "system/save/8000000000000010");
|
||||
const auto raw_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / "system/save/8000000000000010");
|
||||
if (FS::IsFile(raw_path) && !FS::RemoveFile(raw_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto save_path(FS::GetEdenPath(FS::EdenPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
|
||||
const auto save_path(FS::GetYuzuPath(FS::YuzuPath::NANDDir) / ACC_SAVE_AVATORS_BASE_PATH /
|
||||
"profiles.dat");
|
||||
|
||||
if (!FS::CreateParentDirs(save_path)) {
|
||||
|
|
|
@ -155,7 +155,7 @@ void ExtractSharedFonts(Core::System& system) {
|
|||
"FontNintendoExtended2.ttf",
|
||||
};
|
||||
|
||||
const auto fonts_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "fonts";
|
||||
const auto fonts_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "fonts";
|
||||
|
||||
for (std::size_t i = 0; i < NS::SHARED_FONTS.size(); ++i) {
|
||||
const auto font_file_path = fonts_dir / DECRYPTED_SHARED_FONTS[i];
|
||||
|
@ -415,7 +415,7 @@ void WebBrowser::InitializeOffline() {
|
|||
"system_data",
|
||||
};
|
||||
|
||||
offline_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) /
|
||||
offline_cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
|
||||
fmt::format("offline_web_applet_{}/{:016X}",
|
||||
RESOURCE_TYPES[static_cast<u32>(document_kind) - 1], title_id);
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
|
|||
out_control = nacp.GetRawBytes();
|
||||
} else {
|
||||
out_control.resize(sizeof(FileSys::RawNACP));
|
||||
std::fill(out_control.begin(), out_control.end(), (u8) 0);
|
||||
std::fill(out_control.begin(), out_control.end(), 0);
|
||||
}
|
||||
|
||||
auto& storage = system.GetContentProviderUnion();
|
||||
|
|
|
@ -303,7 +303,7 @@ void AlbumManager::FindScreenshots() {
|
|||
album_files.clear();
|
||||
|
||||
// TODO: Swap this with a blocking operation.
|
||||
const auto screenshots_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ScreenshotsDir);
|
||||
const auto screenshots_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ScreenshotsDir);
|
||||
Common::FS::IterateDirEntries(
|
||||
screenshots_dir,
|
||||
[this](const std::filesystem::path& full_path) {
|
||||
|
@ -438,7 +438,7 @@ static void PNGToMemory(void* context, void* data, int len) {
|
|||
Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image,
|
||||
u64 title_id, const AlbumFileDateTime& date) const {
|
||||
const auto screenshot_path =
|
||||
Common::FS::GetEdenPathString(Common::FS::EdenPath::ScreenshotsDir);
|
||||
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir);
|
||||
const std::string formatted_date =
|
||||
fmt::format("{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{:03}", date.year, date.month, date.day,
|
||||
date.hour, date.minute, date.second, 0);
|
||||
|
|
|
@ -346,12 +346,12 @@ std::shared_ptr<SaveDataController> FileSystemController::OpenSaveDataController
|
|||
|
||||
std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory(
|
||||
ProgramId program_id) {
|
||||
using EdenPath = Common::FS::EdenPath;
|
||||
using YuzuPath = Common::FS::YuzuPath;
|
||||
const auto rw_mode = FileSys::OpenMode::ReadWrite;
|
||||
|
||||
auto vfs = system.GetFilesystem();
|
||||
const auto nand_directory =
|
||||
vfs->OpenDirectory(Common::FS::GetEdenPathString(EdenPath::NANDDir), rw_mode);
|
||||
vfs->OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode);
|
||||
return std::make_shared<FileSys::SaveDataFactory>(system, program_id,
|
||||
std::move(nand_directory));
|
||||
}
|
||||
|
@ -683,20 +683,20 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
|
|||
sdmc_factory = nullptr;
|
||||
}
|
||||
|
||||
using EdenPath = Common::FS::EdenPath;
|
||||
const auto sdmc_dir_path = Common::FS::GetEdenPath(EdenPath::SDMCDir);
|
||||
using YuzuPath = Common::FS::YuzuPath;
|
||||
const auto sdmc_dir_path = Common::FS::GetYuzuPath(YuzuPath::SDMCDir);
|
||||
const auto sdmc_load_dir_path = sdmc_dir_path / "atmosphere/contents";
|
||||
const auto rw_mode = FileSys::OpenMode::ReadWrite;
|
||||
|
||||
auto nand_directory =
|
||||
vfs.OpenDirectory(Common::FS::GetEdenPathString(EdenPath::NANDDir), rw_mode);
|
||||
vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode);
|
||||
auto sd_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_dir_path), rw_mode);
|
||||
auto load_directory = vfs.OpenDirectory(Common::FS::GetEdenPathString(EdenPath::LoadDir),
|
||||
auto load_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir),
|
||||
FileSys::OpenMode::Read);
|
||||
auto sd_load_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path),
|
||||
FileSys::OpenMode::Read);
|
||||
auto dump_directory =
|
||||
vfs.OpenDirectory(Common::FS::GetEdenPathString(EdenPath::DumpDir), rw_mode);
|
||||
vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode);
|
||||
|
||||
if (bis_factory == nullptr) {
|
||||
bis_factory = std::make_unique<FileSys::BISFactory>(
|
||||
|
|
|
@ -22,9 +22,9 @@ DatabaseManager::DatabaseManager() {}
|
|||
Result DatabaseManager::MountSaveData() {
|
||||
if (!is_save_data_mounted) {
|
||||
system_save_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000030";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000030";
|
||||
if (is_test_db) {
|
||||
system_save_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) /
|
||||
system_save_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) /
|
||||
"system/save/8000000000000031";
|
||||
}
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou
|
|||
}
|
||||
|
||||
bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) {
|
||||
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||
|
||||
const Common::FS::IOFile keys_file{yuzu_keys_dir / "key_retail.bin",
|
||||
Common::FS::FileAccessMode::Read,
|
||||
|
@ -295,7 +295,7 @@ bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) {
|
|||
}
|
||||
|
||||
bool IsKeyAvailable() {
|
||||
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||
return Common::FS::Exists(yuzu_keys_dir / "key_retail.bin");
|
||||
}
|
||||
|
||||
|
|
|
@ -1261,7 +1261,7 @@ Result NfcDevice::BreakTag(NFP::BreakType break_type) {
|
|||
Result NfcDevice::HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const {
|
||||
ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
|
||||
constexpr auto backup_dir = "backup";
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::AmiiboDir);
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
|
||||
const auto file_name =
|
||||
fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
|
||||
|
||||
|
@ -1282,7 +1282,7 @@ Result NfcDevice::ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid
|
|||
std::span<u8> data) const {
|
||||
ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
|
||||
constexpr auto backup_dir = "backup";
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::AmiiboDir);
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
|
||||
const auto file_name =
|
||||
fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
|
||||
|
||||
|
@ -1313,7 +1313,7 @@ Result NfcDevice::WriteBackupData(const UniqueSerialNumber& uid, std::size_t uui
|
|||
std::span<const u8> data) {
|
||||
ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
|
||||
constexpr auto backup_dir = "backup";
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::AmiiboDir);
|
||||
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
|
||||
const auto file_name =
|
||||
fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
|
||||
|
||||
|
|
|
@ -1330,25 +1330,25 @@ Result ISystemSettingsServer::SetPanelCrcMode(s32 panel_crc_mode) {
|
|||
|
||||
void ISystemSettingsServer::SetupSettings() {
|
||||
auto system_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
|
||||
if (!LoadSettingsFile(system_dir, []() { return DefaultSystemSettings(); })) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
auto private_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000052";
|
||||
if (!LoadSettingsFile(private_dir, []() { return DefaultPrivateSettings(); })) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
auto device_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000053";
|
||||
if (!LoadSettingsFile(device_dir, []() { return DefaultDeviceSettings(); })) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
auto appln_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000054";
|
||||
if (!LoadSettingsFile(appln_dir, []() { return DefaultApplnSettings(); })) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
@ -1356,25 +1356,25 @@ void ISystemSettingsServer::SetupSettings() {
|
|||
|
||||
void ISystemSettingsServer::StoreSettings() {
|
||||
auto system_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000050";
|
||||
if (!StoreSettingsFile(system_dir, m_system_settings)) {
|
||||
LOG_ERROR(Service_SET, "Failed to store System settings");
|
||||
}
|
||||
|
||||
auto private_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000052";
|
||||
if (!StoreSettingsFile(private_dir, m_private_settings)) {
|
||||
LOG_ERROR(Service_SET, "Failed to store Private settings");
|
||||
}
|
||||
|
||||
auto device_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000053";
|
||||
if (!StoreSettingsFile(device_dir, m_device_settings)) {
|
||||
LOG_ERROR(Service_SET, "Failed to store Device settings");
|
||||
}
|
||||
|
||||
auto appln_dir =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / "system/save/8000000000000054";
|
||||
if (!StoreSettingsFile(appln_dir, m_appln_settings)) {
|
||||
LOG_ERROR(Service_SET, "Failed to store ApplLn settings");
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ PerfStats::~PerfStats() {
|
|||
std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index,
|
||||
std::ostream_iterator<double>(stream, "\n"));
|
||||
|
||||
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::LogDir);
|
||||
const auto path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir);
|
||||
// %F Date format expanded is "%Y-%m-%d"
|
||||
const auto filename = fmt::format("{:%F-%H-%M}_{:016X}.csv", *std::localtime(&t), title_id);
|
||||
const auto filepath = path / filename;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
namespace {
|
||||
|
||||
std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_view timestamp) {
|
||||
return Common::FS::GetEdenPath(Common::FS::EdenPath::LogDir) / type /
|
||||
return Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / type /
|
||||
fmt::format("{:016X}_{}.json", title_id, timestamp);
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ void Reporter::SaveErrorReport(u64 title_id, Result result,
|
|||
|
||||
void Reporter::SaveFSAccessLog(std::string_view log_message) const {
|
||||
const auto access_log_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir) / "FsAccessLog.txt";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "FsAccessLog.txt";
|
||||
|
||||
void(Common::FS::AppendStringToFile(access_log_path, Common::FS::FileType::TextFile,
|
||||
log_message));
|
||||
|
@ -352,7 +352,7 @@ void Reporter::SaveUserReport() const {
|
|||
|
||||
void Reporter::ClearFSAccessLog() const {
|
||||
const auto access_log_path =
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::SDMCDir) / "FsAccessLog.txt";
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "FsAccessLog.txt";
|
||||
|
||||
Common::FS::IOFile access_log_file{access_log_path, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::FileType::TextFile};
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
@ -204,6 +200,7 @@ int main(int argc, char** argv) {
|
|||
u64 preferred_game_id = 0;
|
||||
u32 port = Network::DefaultRoomPort;
|
||||
u32 max_members = 16;
|
||||
bool enable_yuzu_mods = false;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"room-name", required_argument, 0, 'n'},
|
||||
|
@ -271,6 +268,9 @@ int main(int argc, char** argv) {
|
|||
case 'l':
|
||||
log_file.assign(optarg);
|
||||
break;
|
||||
case 'e':
|
||||
enable_yuzu_mods = true;
|
||||
break;
|
||||
case 'h':
|
||||
PrintHelp(argv[0]);
|
||||
return 0;
|
||||
|
@ -338,6 +338,10 @@ int main(int argc, char** argv) {
|
|||
Settings::values.yuzu_token = token;
|
||||
}
|
||||
}
|
||||
if (!announce && enable_yuzu_mods) {
|
||||
enable_yuzu_mods = false;
|
||||
LOG_INFO(Network, "Can not enable yuzu Moderators for private rooms");
|
||||
}
|
||||
|
||||
// Load the ban list
|
||||
Network::Room::BanList ban_list;
|
||||
|
@ -366,7 +370,7 @@ int main(int argc, char** argv) {
|
|||
.id = preferred_game_id};
|
||||
if (!room->Create(room_name, room_description, bind_address, static_cast<u16>(port),
|
||||
password, max_members, username, preferred_game_info,
|
||||
std::move(verify_backend), ban_list)) {
|
||||
std::move(verify_backend), ban_list, enable_yuzu_mods)) {
|
||||
LOG_INFO(Network, "Failed to create room: ");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ Config::Config(const ConfigType config_type)
|
|||
: type(config_type), global{config_type == ConfigType::GlobalConfig} {}
|
||||
|
||||
void Config::Initialize(const std::string& config_name) {
|
||||
const std::filesystem::path fs_config_loc = FS::GetEdenPath(FS::EdenPath::ConfigDir);
|
||||
const std::filesystem::path fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir);
|
||||
const auto config_file = fmt::format("{}.ini", config_name);
|
||||
|
||||
switch (type) {
|
||||
|
@ -51,7 +51,7 @@ void Config::Initialize(const std::string& config_name) {
|
|||
|
||||
void Config::Initialize(const std::optional<std::string> config_path) {
|
||||
const std::filesystem::path default_sdl_config_path =
|
||||
FS::GetEdenPath(FS::EdenPath::ConfigDir) / "sdl2-config.ini";
|
||||
FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
|
||||
config_loc = config_path.value_or(FS::PathToUTF8String(default_sdl_config_path));
|
||||
void(FS::CreateParentDir(config_loc));
|
||||
SetUpIni();
|
||||
|
@ -275,11 +275,11 @@ void Config::ReadCoreValues() {
|
|||
void Config::ReadDataStorageValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||
|
||||
FS::SetEdenPath(FS::EdenPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
|
||||
FS::SetEdenPath(FS::EdenPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
|
||||
FS::SetEdenPath(FS::EdenPath::LoadDir, ReadStringSetting(std::string("load_directory")));
|
||||
FS::SetEdenPath(FS::EdenPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
|
||||
FS::SetEdenPath(FS::EdenPath::TASDir, ReadStringSetting(std::string("tas_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::LoadDir, ReadStringSetting(std::string("load_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
|
||||
FS::SetYuzuPath(FS::YuzuPath::TASDir, ReadStringSetting(std::string("tas_directory")));
|
||||
|
||||
ReadCategory(Settings::Category::DataStorage);
|
||||
|
||||
|
@ -372,7 +372,7 @@ void Config::ReadScreenshotValues() {
|
|||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
||||
|
||||
ReadCategory(Settings::Category::Screenshots);
|
||||
FS::SetEdenPath(FS::EdenPath::ScreenshotsDir,
|
||||
FS::SetYuzuPath(FS::YuzuPath::ScreenshotsDir,
|
||||
ReadStringSetting(std::string("screenshot_path")));
|
||||
|
||||
EndGroup();
|
||||
|
@ -578,16 +578,16 @@ void Config::SaveCoreValues() {
|
|||
void Config::SaveDataStorageValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||
|
||||
WriteStringSetting(std::string("nand_directory"), FS::GetEdenPathString(FS::EdenPath::NANDDir),
|
||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::NANDDir)));
|
||||
WriteStringSetting(std::string("sdmc_directory"), FS::GetEdenPathString(FS::EdenPath::SDMCDir),
|
||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::SDMCDir)));
|
||||
WriteStringSetting(std::string("load_directory"), FS::GetEdenPathString(FS::EdenPath::LoadDir),
|
||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::LoadDir)));
|
||||
WriteStringSetting(std::string("dump_directory"), FS::GetEdenPathString(FS::EdenPath::DumpDir),
|
||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::DumpDir)));
|
||||
WriteStringSetting(std::string("tas_directory"), FS::GetEdenPathString(FS::EdenPath::TASDir),
|
||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::TASDir)));
|
||||
WriteStringSetting(std::string("nand_directory"), FS::GetYuzuPathString(FS::YuzuPath::NANDDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)));
|
||||
WriteStringSetting(std::string("sdmc_directory"), FS::GetYuzuPathString(FS::YuzuPath::SDMCDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)));
|
||||
WriteStringSetting(std::string("load_directory"), FS::GetYuzuPathString(FS::YuzuPath::LoadDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)));
|
||||
WriteStringSetting(std::string("dump_directory"), FS::GetYuzuPathString(FS::YuzuPath::DumpDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)));
|
||||
WriteStringSetting(std::string("tas_directory"), FS::GetYuzuPathString(FS::YuzuPath::TASDir),
|
||||
std::make_optional(FS::GetYuzuPathString(FS::YuzuPath::TASDir)));
|
||||
|
||||
WriteCategory(Settings::Category::DataStorage);
|
||||
|
||||
|
@ -681,7 +681,7 @@ void Config::SaveScreenshotValues() {
|
|||
BeginGroup(Settings::TranslateCategory(Settings::Category::Screenshots));
|
||||
|
||||
WriteStringSetting(std::string("screenshot_path"),
|
||||
FS::GetEdenPathString(FS::EdenPath::ScreenshotsDir));
|
||||
FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir));
|
||||
WriteCategory(Settings::Category::Screenshots);
|
||||
|
||||
EndGroup();
|
||||
|
|
|
@ -82,7 +82,7 @@ void Tas::LoadTasFile(size_t player_index, size_t file_index) {
|
|||
commands[player_index].clear();
|
||||
|
||||
std::string file = Common::FS::ReadStringFromFile(
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::TASDir) /
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) /
|
||||
fmt::format("script{}-{}.txt", file_index, player_index + 1),
|
||||
Common::FS::FileType::BinaryFile);
|
||||
std::istringstream command_line(file);
|
||||
|
@ -137,7 +137,7 @@ void Tas::WriteTasFile(std::u8string_view file_name) {
|
|||
WriteCommandAxis(line.l_axis), WriteCommandAxis(line.r_axis));
|
||||
}
|
||||
|
||||
const auto tas_file_name = Common::FS::GetEdenPath(Common::FS::EdenPath::TASDir) / file_name;
|
||||
const auto tas_file_name = Common::FS::GetYuzuPath(Common::FS::YuzuPath::TASDir) / file_name;
|
||||
const auto bytes_written =
|
||||
Common::FS::WriteStringToFile(tas_file_name, Common::FS::FileType::TextFile, output_text);
|
||||
if (bytes_written == output_text.size()) {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <iomanip>
|
||||
|
@ -359,14 +355,7 @@ void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
|
|||
std::lock_guard lock(verify_uid_mutex);
|
||||
uid = verify_uid;
|
||||
}
|
||||
|
||||
if (verify_backend != nullptr)
|
||||
member.user_data = verify_backend->LoadUserData(uid, token);
|
||||
|
||||
if (nickname == room_information.host_username) {
|
||||
member.user_data.moderator = true;
|
||||
LOG_INFO(Network, "User {} is a moderator", std::string(room_information.host_username));
|
||||
}
|
||||
member.user_data = verify_backend->LoadUserData(uid, token);
|
||||
|
||||
std::string ip;
|
||||
{
|
||||
|
@ -585,7 +574,8 @@ bool Room::RoomImpl::HasModPermission(const ENetPeer* client) const {
|
|||
if (sending_member == members.end()) {
|
||||
return false;
|
||||
}
|
||||
if (sending_member->user_data.moderator) { // Community moderator
|
||||
if (room_information.enable_yuzu_mods &&
|
||||
sending_member->user_data.moderator) { // Community moderator
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1057,7 +1047,7 @@ bool Room::Create(const std::string& name, const std::string& description,
|
|||
const u32 max_connections, const std::string& host_username,
|
||||
const GameInfo preferred_game,
|
||||
std::unique_ptr<VerifyUser::Backend> verify_backend,
|
||||
const Room::BanList& ban_list) {
|
||||
const Room::BanList& ban_list, bool enable_yuzu_mods) {
|
||||
ENetAddress address;
|
||||
address.host = ENET_HOST_ANY;
|
||||
if (!server_address.empty()) {
|
||||
|
@ -1079,6 +1069,7 @@ bool Room::Create(const std::string& name, const std::string& description,
|
|||
room_impl->room_information.port = server_port;
|
||||
room_impl->room_information.preferred_game = preferred_game;
|
||||
room_impl->room_information.host_username = host_username;
|
||||
room_impl->room_information.enable_yuzu_mods = enable_yuzu_mods;
|
||||
room_impl->password = password;
|
||||
room_impl->verify_backend = std::move(verify_backend);
|
||||
room_impl->username_ban_list = ban_list.first;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
@ -127,7 +123,7 @@ public:
|
|||
const u32 max_connections = MaxConcurrentConnections,
|
||||
const std::string& host_username = "", const GameInfo = {},
|
||||
std::unique_ptr<VerifyUser::Backend> verify_backend = nullptr,
|
||||
const BanList& ban_list = {});
|
||||
const BanList& ban_list = {}, bool enable_yuzu_mods = false);
|
||||
|
||||
/**
|
||||
* Sets the verification GUID of the room.
|
||||
|
|
|
@ -304,6 +304,8 @@ add_library(video_core STATIC
|
|||
vulkan_common/vulkan_library.h
|
||||
vulkan_common/vulkan_memory_allocator.cpp
|
||||
vulkan_common/vulkan_memory_allocator.h
|
||||
vulkan_common/hybrid_memory.cpp
|
||||
vulkan_common/hybrid_memory.h
|
||||
vulkan_common/vulkan_surface.cpp
|
||||
vulkan_common/vulkan_surface.h
|
||||
vulkan_common/vulkan_wrapper.cpp
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#version 450
|
||||
|
|
|
@ -28,7 +28,7 @@ MICROPROFILE_DEFINE(MacroHLE, "GPU", "Execute macro HLE", MP_RGB(128, 192, 192))
|
|||
namespace Tegra {
|
||||
|
||||
static void Dump(u64 hash, std::span<const u32> code, bool decompiled = false) {
|
||||
const auto base_dir{Common::FS::GetEdenPath(Common::FS::EdenPath::DumpDir)};
|
||||
const auto base_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)};
|
||||
const auto macro_dir{base_dir / "macros"};
|
||||
if (!Common::FS::CreateDir(base_dir) || !Common::FS::CreateDir(macro_dir)) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create macro dump directories");
|
||||
|
|
|
@ -260,7 +260,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
|||
if (title_id == 0) {
|
||||
return;
|
||||
}
|
||||
const auto shader_dir{Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir)};
|
||||
const auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir)};
|
||||
const auto base_dir{shader_dir / fmt::format("{:016x}", title_id)};
|
||||
if (!Common::FS::CreateDir(shader_dir) || !Common::FS::CreateDir(base_dir)) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create shader cache directories");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
|
@ -33,6 +35,7 @@
|
|||
#include "video_core/vulkan_common/vulkan_instance.h"
|
||||
#include "video_core/vulkan_common/vulkan_library.h"
|
||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||
#include "video_core/vulkan_common/hybrid_memory.h"
|
||||
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
#ifdef __ANDROID__
|
||||
|
@ -132,6 +135,7 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window,
|
|||
PresentFiltersForAppletCapture),
|
||||
rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker,
|
||||
scheduler),
|
||||
hybrid_memory(std::make_unique<HybridMemory>(device, memory_allocator)),
|
||||
applet_frame() {
|
||||
|
||||
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
|
||||
|
@ -146,6 +150,49 @@ RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& emu_window,
|
|||
debug_messenger.release();
|
||||
}
|
||||
|
||||
// Initialize HybridMemory system
|
||||
if (Settings::values.use_gpu_memory_manager.GetValue()) {
|
||||
#if defined(__linux__) || defined(__ANDROID__) || defined(_WIN32)
|
||||
try {
|
||||
// Define memory size with explicit types to avoid conversion warnings
|
||||
constexpr size_t memory_size_mb = 64;
|
||||
constexpr size_t memory_size_bytes = memory_size_mb * 1024 * 1024;
|
||||
|
||||
void* guest_memory_base = nullptr;
|
||||
#if defined(_WIN32)
|
||||
// On Windows, use VirtualAlloc to reserve (but not commit) memory
|
||||
const SIZE_T win_size = static_cast<SIZE_T>(memory_size_bytes);
|
||||
LPVOID result = VirtualAlloc(nullptr, win_size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (result != nullptr) {
|
||||
guest_memory_base = result;
|
||||
}
|
||||
#else
|
||||
// On Linux/Android, use aligned_alloc
|
||||
guest_memory_base = std::aligned_alloc(4096, memory_size_bytes);
|
||||
#endif
|
||||
if (guest_memory_base != nullptr) {
|
||||
try {
|
||||
hybrid_memory->InitializeGuestMemory(guest_memory_base, memory_size_bytes);
|
||||
LOG_INFO(Render_Vulkan, "HybridMemory initialized with {} MB of fault-managed memory", memory_size_mb);
|
||||
} catch (const std::exception&) {
|
||||
#if defined(_WIN32)
|
||||
if (guest_memory_base != nullptr) {
|
||||
const LPVOID win_ptr = static_cast<LPVOID>(guest_memory_base);
|
||||
VirtualFree(win_ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
#else
|
||||
std::free(guest_memory_base);
|
||||
#endif
|
||||
throw;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to initialize HybridMemory: {}", e.what());
|
||||
}
|
||||
#else
|
||||
LOG_INFO(Render_Vulkan, "Fault-managed memory not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
Report();
|
||||
} catch (const vk::Exception& exception) {
|
||||
LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
|
||||
|
@ -371,6 +418,35 @@ void RendererVulkan::RenderScreenshot(std::span<const Tegra::FramebufferConfig>
|
|||
return;
|
||||
}
|
||||
|
||||
// If memory snapshots are enabled, take a snapshot with the screenshot
|
||||
if (Settings::values.enable_memory_snapshots.GetValue() && hybrid_memory) {
|
||||
try {
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto now_time_t = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm local_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&local_tm, &now_time_t);
|
||||
#else
|
||||
localtime_r(&now_time_t, &local_tm);
|
||||
#endif
|
||||
char time_str[128];
|
||||
std::strftime(time_str, sizeof(time_str), "%Y%m%d_%H%M%S", &local_tm);
|
||||
|
||||
std::string snapshot_path = fmt::format("snapshots/memory_snapshot_{}.bin", time_str);
|
||||
hybrid_memory->SaveSnapshot(snapshot_path);
|
||||
|
||||
// Also save a differential snapshot if there's been a previous snapshot
|
||||
if (Settings::values.use_gpu_memory_manager.GetValue()) {
|
||||
std::string diff_path = fmt::format("snapshots/diff_snapshot_{}.bin", time_str);
|
||||
hybrid_memory->SaveDifferentialSnapshot(diff_path);
|
||||
hybrid_memory->ResetDirtyTracking();
|
||||
LOG_INFO(Render_Vulkan, "Memory snapshots saved with screenshot");
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to save memory snapshot: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
const auto& layout{renderer_settings.screenshot_framebuffer_layout};
|
||||
const auto dst_buffer = RenderToBuffer(framebuffers, layout, VK_FORMAT_B8G8R8A8_UNORM,
|
||||
layout.width * layout.height * 4);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "video_core/renderer_vulkan/vk_turbo_mode.h"
|
||||
#include "video_core/vulkan_common/vulkan_device.h"
|
||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||
#include "video_core/vulkan_common/hybrid_memory.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
#include "video_core/vulkan_common/vulkan_raii.h"
|
||||
|
||||
|
@ -101,6 +102,9 @@ private:
|
|||
RasterizerVulkan rasterizer;
|
||||
std::optional<TurboMode> turbo_mode;
|
||||
|
||||
// HybridMemory for advanced memory management
|
||||
std::unique_ptr<HybridMemory> hybrid_memory;
|
||||
|
||||
Frame applet_frame;
|
||||
};
|
||||
|
||||
|
|
|
@ -472,7 +472,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
|
|||
if (title_id == 0) {
|
||||
return;
|
||||
}
|
||||
const auto shader_dir{Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir)};
|
||||
const auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::ShaderDir)};
|
||||
const auto base_dir{shader_dir / fmt::format("{:016x}", title_id)};
|
||||
if (!Common::FS::CreateDir(shader_dir) || !Common::FS::CreateDir(base_dir)) {
|
||||
LOG_ERROR(Common_Filesystem, "Failed to create pipeline cache directories");
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue