mirror of
https://github.com/Vita3K/Vita3K-Android.git
synced 2025-02-11 07:45:35 +00:00
android: V12 Update
This commit is contained in:
parent
fab31c81b2
commit
a62e232024
466
.github/workflows/c-cpp.yml
vendored
466
.github/workflows/c-cpp.yml
vendored
@ -1,234 +1,234 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
format-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Format check
|
||||
run: .github/format-check.sh
|
||||
|
||||
build:
|
||||
needs: [format-check]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
config: [Release]
|
||||
version: [zip, appimage]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
version: appimage
|
||||
cache_path: ~/.ccache
|
||||
extra_cmake_args: -DLINUXDEPLOY_COMMAND=/usr/local/bin/linuxdeploy-x86_64.AppImage
|
||||
cmake_preset: linux-ninja-clang15-appimage
|
||||
- os: ubuntu-latest
|
||||
version: zip
|
||||
cache_path: ~/.ccache
|
||||
extra_cmake_args:
|
||||
cmake_preset: linux-ninja-clang15
|
||||
- os: windows-latest
|
||||
version: zip
|
||||
cache_path: |
|
||||
C:\vcpkg\installed
|
||||
C:\vcpkg\packages
|
||||
C:\Users\runneradmin\AppData\Local\ccache
|
||||
extra_cmake_args: -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
|
||||
cmake_preset: windows-ninja
|
||||
- os: macos-latest
|
||||
version: zip
|
||||
cache_path: ~/Library/Caches/ccache
|
||||
extra_cmake_args: -DCMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
cmake_preset: macos-ninja
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
version: appimage
|
||||
- os: windows-latest
|
||||
version: appimage
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up build environment (macos-latest)
|
||||
run: |
|
||||
brew install ccache ninja create-dmg
|
||||
brew fetch --force --bottle-tag=x86_64_monterey boost openssl@3 molten-vk
|
||||
brew install $(brew --cache --bottle-tag=x86_64_monterey boost)
|
||||
brew install $(brew --cache --bottle-tag=x86_64_monterey molten-vk)
|
||||
brew reinstall $(brew --cache --bottle-tag=x86_64_monterey openssl@3)
|
||||
echo "$(brew --prefix ccache)/libexec" >> $GITHUB_PATH
|
||||
ccache --set-config=compiler_check=content
|
||||
if: matrix.os == 'macos-latest'
|
||||
|
||||
- name: Set up build environment (ubuntu-latest)
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:mhier/libboost-latest
|
||||
sudo add-apt-repository universe
|
||||
sudo apt update
|
||||
sudo apt -y install ccache libboost-filesystem1.83-dev libboost-program-options1.83-dev libboost-system1.83-dev libgtk-3-dev libsdl2-dev ninja-build libfuse2
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ matrix.cache_path }}
|
||||
key: cache-${{ matrix.os }}-${{ matrix.config }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
cache-${{ matrix.os }}-${{ matrix.config }}-
|
||||
|
||||
- name: Set up build environment (windows-latest)
|
||||
run: |
|
||||
vcpkg install zlib:x64-windows-static-md boost-system:x64-windows-static-md boost-filesystem:x64-windows-static-md boost-program-options:x64-windows-static-md boost-icl:x64-windows-static-md boost-variant:x64-windows-static-md curl:x64-windows-static-md openssl:x64-windows-static-md
|
||||
choco install ccache
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- name: Set up SDL 2.28.3 (ubuntu-latest)
|
||||
run: |
|
||||
SDL2VER=2.28.3
|
||||
if [[ ! -e ~/.ccache ]]; then
|
||||
mkdir ~/.ccache
|
||||
fi
|
||||
cd ~/.ccache
|
||||
if [[ ! -e SDL2-${SDL2VER} ]]; then
|
||||
curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz
|
||||
tar -xzf SDL2-${SDL2VER}.tar.gz
|
||||
cd SDL2-${SDL2VER}
|
||||
./configure --prefix=/usr/local
|
||||
make && cd ../
|
||||
rm SDL2-${SDL2VER}.tar.gz
|
||||
fi
|
||||
sudo make -C SDL2-${SDL2VER} install
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- name: Set up linuxdeploy (ubuntu-latest, appimage)
|
||||
run: |
|
||||
if [[ ! -e linuxdeploy-x86_64.AppImage ]]; then
|
||||
curl -sLO https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-x86_64.AppImage
|
||||
fi
|
||||
sudo cp -f linuxdeploy-x86_64.AppImage /usr/local/bin/
|
||||
sudo chmod +x /usr/local/bin/linuxdeploy-x86_64.AppImage
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.version == 'appimage'
|
||||
|
||||
- name: Ccache setup
|
||||
run: ccache -z
|
||||
|
||||
- name: CMake
|
||||
run: |
|
||||
cmake ${{ matrix.extra_cmake_args }} --preset ${{ matrix.cmake_preset }}
|
||||
cmake --build build/${{ matrix.cmake_preset }} --config ${{ matrix.config }}
|
||||
|
||||
- name: CTest
|
||||
working-directory: build/${{ matrix.cmake_preset }}
|
||||
run: ctest --build-config ${{ matrix.config }} --output-on-failure
|
||||
|
||||
- name: Compute git short sha
|
||||
shell: bash
|
||||
run: echo "git_short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
|
||||
- name: Set Build Variable
|
||||
shell: bash
|
||||
run: echo "build_variable=$(git rev-list HEAD --count)" >> $GITHUB_ENV
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- name: Bundle Shared Objects
|
||||
id: bundle_shared_objects
|
||||
run: |
|
||||
cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ./libssl.so.3
|
||||
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ./libcrypto.so.3
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
- name: Ccache statistics
|
||||
run: ccache -s
|
||||
|
||||
- name: Create DMG (macos-latest)
|
||||
run: |
|
||||
cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
create-dmg \
|
||||
--volname "Vita3K Installer" \
|
||||
--volicon Vita3K.app/Contents/Resources/Vita3K.icns \
|
||||
--window-size 500 300 \
|
||||
--icon-size 100 \
|
||||
--icon Vita3K.app 120 115 \
|
||||
--app-drop-link 360 115 \
|
||||
vita3k-${{ env.git_short_sha }}-${{ matrix.version }}-${{ matrix.os }}.dmg \
|
||||
Vita3K.app
|
||||
rm -rf Vita3K.app
|
||||
if: matrix.os == 'macos-latest'
|
||||
|
||||
- name: Clean appimage build (ubuntu-latest, appimage)
|
||||
run: |
|
||||
cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
cp -f *AppImage* ../
|
||||
rm -rf ./*
|
||||
cp -f ../*AppImage* ./
|
||||
rm -f ../*AppImage*
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.version == 'appimage'
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vita3k-${{ env.git_short_sha }}-${{ matrix.version }}-${{ matrix.os }}
|
||||
# path is set up to be <binary_dir>/bin/<config_type> since that's how multi-config
|
||||
# generators work on CMake
|
||||
path: build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
|
||||
outputs:
|
||||
BuildTag: ${{ env.build_variable }}
|
||||
|
||||
create-release:
|
||||
needs: [build]
|
||||
runs-on: "ubuntu-20.04"
|
||||
if: github.ref == 'refs/heads/master'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Get Build Variable
|
||||
run: echo "Build_Variable=${{ needs.build.outputs.BuildTag }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir artifacts/
|
||||
files=$(find . -name "*latest")
|
||||
for f in $files; do
|
||||
if [[ $f == *macos-latest ]]
|
||||
then
|
||||
cp $(basename $f)/$(basename $f).dmg artifacts/macos-latest.dmg
|
||||
else
|
||||
if [[ $f == *ubuntu-latest ]]
|
||||
then
|
||||
if [[ $f == *appimage* ]]
|
||||
then
|
||||
cp $(basename $f)/*.AppImage* artifacts/
|
||||
else
|
||||
rm -f $(basename $f)/*.AppImage*
|
||||
echo "Compressing $f"
|
||||
(cd $(basename $f) && zip -r ../artifacts/$(basename $f | cut -d "-" -f 4)-latest.zip *)
|
||||
fi
|
||||
else
|
||||
echo "Compressing $f"
|
||||
(cd $(basename $f) && zip -r ../artifacts/$(basename $f | cut -d "-" -f 4)-latest.zip *)
|
||||
fi
|
||||
fi
|
||||
done
|
||||
ls -al artifacts/
|
||||
wget -c https://github.com/tcnksm/ghr/releases/download/v0.14.0/ghr_v0.14.0_linux_amd64.tar.gz
|
||||
tar xfv ghr_v0.14.0_linux_amd64.tar.gz
|
||||
ghr_v0.14.0_linux_amd64/ghr -u Vita3K -r Vita3K -recreate -n 'Automatic CI builds' -b "$(printf "Corresponding commit: ${{ github.sha }}\nVita3K Build: ${{ env.Build_Variable }}")" continuous artifacts/
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
#name: C/C++ CI
|
||||
#
|
||||
#on: [push, pull_request]
|
||||
#
|
||||
#jobs:
|
||||
# format-check:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v4
|
||||
#
|
||||
# - name: Format check
|
||||
# run: .github/format-check.sh
|
||||
#
|
||||
# build:
|
||||
# needs: [format-check]
|
||||
# runs-on: ${{ matrix.os }}
|
||||
#
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# matrix:
|
||||
# os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
# config: [Release]
|
||||
# version: [zip, appimage]
|
||||
# include:
|
||||
# - os: ubuntu-latest
|
||||
# version: appimage
|
||||
# cache_path: ~/.ccache
|
||||
# extra_cmake_args: -DLINUXDEPLOY_COMMAND=/usr/local/bin/linuxdeploy-x86_64.AppImage
|
||||
# cmake_preset: linux-ninja-clang15-appimage
|
||||
# - os: ubuntu-latest
|
||||
# version: zip
|
||||
# cache_path: ~/.ccache
|
||||
# extra_cmake_args:
|
||||
# cmake_preset: linux-ninja-clang15
|
||||
# - os: windows-latest
|
||||
# version: zip
|
||||
# cache_path: |
|
||||
# C:\vcpkg\installed
|
||||
# C:\vcpkg\packages
|
||||
# C:\Users\runneradmin\AppData\Local\ccache
|
||||
# extra_cmake_args: -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
|
||||
# cmake_preset: windows-ninja
|
||||
# - os: macos-latest
|
||||
# version: zip
|
||||
# cache_path: ~/Library/Caches/ccache
|
||||
# extra_cmake_args: -DCMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
# cmake_preset: macos-ninja
|
||||
# exclude:
|
||||
# - os: macos-latest
|
||||
# version: appimage
|
||||
# - os: windows-latest
|
||||
# version: appimage
|
||||
#
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
# submodules: recursive
|
||||
#
|
||||
# - name: Set up build environment (macos-latest)
|
||||
# run: |
|
||||
# brew install ccache ninja create-dmg
|
||||
# brew fetch --force --bottle-tag=x86_64_monterey boost openssl@3 molten-vk
|
||||
# brew install $(brew --cache --bottle-tag=x86_64_monterey boost)
|
||||
# brew install $(brew --cache --bottle-tag=x86_64_monterey molten-vk)
|
||||
# brew reinstall $(brew --cache --bottle-tag=x86_64_monterey openssl@3)
|
||||
# echo "$(brew --prefix ccache)/libexec" >> $GITHUB_PATH
|
||||
# ccache --set-config=compiler_check=content
|
||||
# if: matrix.os == 'macos-latest'
|
||||
#
|
||||
# - name: Set up build environment (ubuntu-latest)
|
||||
# run: |
|
||||
# sudo add-apt-repository -y ppa:mhier/libboost-latest
|
||||
# sudo add-apt-repository universe
|
||||
# sudo apt update
|
||||
# sudo apt -y install ccache libboost-filesystem1.83-dev libboost-program-options1.83-dev libboost-system1.83-dev libgtk-3-dev libsdl2-dev ninja-build libfuse2
|
||||
# if: matrix.os == 'ubuntu-latest'
|
||||
#
|
||||
# - uses: ilammy/msvc-dev-cmd@v1
|
||||
# if: matrix.os == 'windows-latest'
|
||||
#
|
||||
# - uses: actions/cache@v4
|
||||
# with:
|
||||
# path: ${{ matrix.cache_path }}
|
||||
# key: cache-${{ matrix.os }}-${{ matrix.config }}-${{ github.sha }}
|
||||
# restore-keys: |
|
||||
# cache-${{ matrix.os }}-${{ matrix.config }}-
|
||||
#
|
||||
# - name: Set up build environment (windows-latest)
|
||||
# run: |
|
||||
# vcpkg install zlib:x64-windows-static-md boost-system:x64-windows-static-md boost-filesystem:x64-windows-static-md boost-program-options:x64-windows-static-md boost-icl:x64-windows-static-md boost-variant:x64-windows-static-md curl:x64-windows-static-md openssl:x64-windows-static-md
|
||||
# choco install ccache
|
||||
# if: matrix.os == 'windows-latest'
|
||||
#
|
||||
# - name: Set up SDL 2.28.3 (ubuntu-latest)
|
||||
# run: |
|
||||
# SDL2VER=2.28.3
|
||||
# if [[ ! -e ~/.ccache ]]; then
|
||||
# mkdir ~/.ccache
|
||||
# fi
|
||||
# cd ~/.ccache
|
||||
# if [[ ! -e SDL2-${SDL2VER} ]]; then
|
||||
# curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz
|
||||
# tar -xzf SDL2-${SDL2VER}.tar.gz
|
||||
# cd SDL2-${SDL2VER}
|
||||
# ./configure --prefix=/usr/local
|
||||
# make && cd ../
|
||||
# rm SDL2-${SDL2VER}.tar.gz
|
||||
# fi
|
||||
# sudo make -C SDL2-${SDL2VER} install
|
||||
# if: matrix.os == 'ubuntu-latest'
|
||||
#
|
||||
# - name: Set up linuxdeploy (ubuntu-latest, appimage)
|
||||
# run: |
|
||||
# if [[ ! -e linuxdeploy-x86_64.AppImage ]]; then
|
||||
# curl -sLO https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-x86_64.AppImage
|
||||
# fi
|
||||
# sudo cp -f linuxdeploy-x86_64.AppImage /usr/local/bin/
|
||||
# sudo chmod +x /usr/local/bin/linuxdeploy-x86_64.AppImage
|
||||
# if: matrix.os == 'ubuntu-latest' && matrix.version == 'appimage'
|
||||
#
|
||||
# - name: Ccache setup
|
||||
# run: ccache -z
|
||||
#
|
||||
# - name: CMake
|
||||
# run: |
|
||||
# cmake ${{ matrix.extra_cmake_args }} --preset ${{ matrix.cmake_preset }}
|
||||
# cmake --build build/${{ matrix.cmake_preset }} --config ${{ matrix.config }}
|
||||
#
|
||||
# - name: CTest
|
||||
# working-directory: build/${{ matrix.cmake_preset }}
|
||||
# run: ctest --build-config ${{ matrix.config }} --output-on-failure
|
||||
#
|
||||
# - name: Compute git short sha
|
||||
# shell: bash
|
||||
# run: echo "git_short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
#
|
||||
# - name: Set Build Variable
|
||||
# shell: bash
|
||||
# run: echo "build_variable=$(git rev-list HEAD --count)" >> $GITHUB_ENV
|
||||
# if: matrix.os == 'ubuntu-latest'
|
||||
#
|
||||
# - name: Bundle Shared Objects
|
||||
# id: bundle_shared_objects
|
||||
# run: |
|
||||
# cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
# cp /usr/lib/x86_64-linux-gnu/libssl.so.3 ./libssl.so.3
|
||||
# cp /usr/lib/x86_64-linux-gnu/libcrypto.so.3 ./libcrypto.so.3
|
||||
# if: matrix.os == 'ubuntu-latest'
|
||||
#
|
||||
# - name: Ccache statistics
|
||||
# run: ccache -s
|
||||
#
|
||||
# - name: Create DMG (macos-latest)
|
||||
# run: |
|
||||
# cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
# create-dmg \
|
||||
# --volname "Vita3K Installer" \
|
||||
# --volicon Vita3K.app/Contents/Resources/Vita3K.icns \
|
||||
# --window-size 500 300 \
|
||||
# --icon-size 100 \
|
||||
# --icon Vita3K.app 120 115 \
|
||||
# --app-drop-link 360 115 \
|
||||
# vita3k-${{ env.git_short_sha }}-${{ matrix.version }}-${{ matrix.os }}.dmg \
|
||||
# Vita3K.app
|
||||
# rm -rf Vita3K.app
|
||||
# if: matrix.os == 'macos-latest'
|
||||
#
|
||||
# - name: Clean appimage build (ubuntu-latest, appimage)
|
||||
# run: |
|
||||
# cd build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
# cp -f *AppImage* ../
|
||||
# rm -rf ./*
|
||||
# cp -f ../*AppImage* ./
|
||||
# rm -f ../*AppImage*
|
||||
# if: matrix.os == 'ubuntu-latest' && matrix.version == 'appimage'
|
||||
#
|
||||
# - uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: vita3k-${{ env.git_short_sha }}-${{ matrix.version }}-${{ matrix.os }}
|
||||
# # path is set up to be <binary_dir>/bin/<config_type> since that's how multi-config
|
||||
# # generators work on CMake
|
||||
# path: build/${{ matrix.cmake_preset }}/bin/${{ matrix.config }}
|
||||
#
|
||||
# outputs:
|
||||
# BuildTag: ${{ env.build_variable }}
|
||||
#
|
||||
# create-release:
|
||||
# needs: [build]
|
||||
# runs-on: "ubuntu-20.04"
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
#
|
||||
# - name: Download Artifacts
|
||||
# uses: actions/download-artifact@v4
|
||||
#
|
||||
# - name: Get Build Variable
|
||||
# run: echo "Build_Variable=${{ needs.build.outputs.BuildTag }}" >> $GITHUB_ENV
|
||||
#
|
||||
# - name: Upload
|
||||
# shell: bash
|
||||
# run: |
|
||||
# mkdir artifacts/
|
||||
# files=$(find . -name "*latest")
|
||||
# for f in $files; do
|
||||
# if [[ $f == *macos-latest ]]
|
||||
# then
|
||||
# cp $(basename $f)/$(basename $f).dmg artifacts/macos-latest.dmg
|
||||
# else
|
||||
# if [[ $f == *ubuntu-latest ]]
|
||||
# then
|
||||
# if [[ $f == *appimage* ]]
|
||||
# then
|
||||
# cp $(basename $f)/*.AppImage* artifacts/
|
||||
# else
|
||||
# rm -f $(basename $f)/*.AppImage*
|
||||
# echo "Compressing $f"
|
||||
# (cd $(basename $f) && zip -r ../artifacts/$(basename $f | cut -d "-" -f 4)-latest.zip *)
|
||||
# fi
|
||||
# else
|
||||
# echo "Compressing $f"
|
||||
# (cd $(basename $f) && zip -r ../artifacts/$(basename $f | cut -d "-" -f 4)-latest.zip *)
|
||||
# fi
|
||||
# fi
|
||||
# done
|
||||
# ls -al artifacts/
|
||||
# wget -c https://github.com/tcnksm/ghr/releases/download/v0.14.0/ghr_v0.14.0_linux_amd64.tar.gz
|
||||
# tar xfv ghr_v0.14.0_linux_amd64.tar.gz
|
||||
# ghr_v0.14.0_linux_amd64/ghr -u Vita3K -r Vita3K -recreate -n 'Automatic CI builds' -b "$(printf "Corresponding commit: ${{ github.sha }}\nVita3K Build: ${{ env.Build_Variable }}")" continuous artifacts/
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
@ -4,14 +4,16 @@ android {
|
||||
namespace "org.vita3k.emulator"
|
||||
compileSdk 34
|
||||
ndkVersion "26.3.11579264"
|
||||
buildToolsVersion "34.0.0"
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.vita3k.emulator"
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
versionCode 11
|
||||
versionName "0.2.0-11"
|
||||
versionCode 12
|
||||
versionName "0.2.0-12"
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
@ -45,9 +45,16 @@
|
||||
|
||||
<!-- Allow downloading to the external storage on Android 5.1 and older -->
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="22" /> -->
|
||||
<!-- For android API <= 29 (Up to Android 10), use Legacy storage, otherwise use the MANAGE_EXTERNAL_STORAGE permission -->
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission
|
||||
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||
android:minSdkVersion="30" />
|
||||
|
||||
<!-- Allow access to Bluetooth devices -->
|
||||
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
|
||||
@ -70,6 +77,8 @@
|
||||
then replace "SDLActivity" with the name of your class (e.g. "MyGame")
|
||||
in the XML below.
|
||||
An example Java class can be found in README-android.md
|
||||
|
||||
The requestLegacyExternalStorage parameter only has an effect when running on Android <= 10
|
||||
-->
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@ -78,7 +87,9 @@
|
||||
android:hardwareAccelerated="true"
|
||||
android:appCategory="game"
|
||||
android:isGame="true"
|
||||
android:hasFragileUserData="true" tools:targetApi="q">
|
||||
android:hasFragileUserData="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
tools:targetApi="q">
|
||||
|
||||
<!-- Example of setting SDL hints from AndroidManifest.xml:
|
||||
<meta-data android:name="SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK" android:value="0"/>
|
||||
@ -89,8 +100,10 @@
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:theme="@style/Theme.Design.NoActionBar"
|
||||
android:exported="true"
|
||||
>
|
||||
tools:targetApi="r">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
@ -1,14 +1,24 @@
|
||||
package org.vita3k.emulator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
|
||||
import org.libsdl.app.SDLSurface;
|
||||
import org.vita3k.emulator.overlay.InputOverlay;
|
||||
|
||||
public class EmuSurface extends SDLSurface {
|
||||
|
||||
private InputOverlay mOverlay;
|
||||
|
||||
public InputOverlay getmOverlay() {
|
||||
return mOverlay;
|
||||
}
|
||||
|
||||
public EmuSurface(Context context){
|
||||
super(context);
|
||||
mOverlay = new InputOverlay(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -23,6 +33,16 @@ public class EmuSurface extends SDLSurface {
|
||||
super.surfaceDestroyed(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if(mOverlay.onTouch(v, event)){
|
||||
// priority is given to the overlay
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onTouch(v, event);
|
||||
}
|
||||
|
||||
public native void setSurfaceStatus(boolean surface_present);
|
||||
|
||||
}
|
||||
|
@ -1,28 +1,33 @@
|
||||
package org.vita3k.emulator;
|
||||
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.provider.Settings;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.view.Surface;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import com.jakewharton.processphoenix.ProcessPhoenix;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -32,11 +37,11 @@ import org.vita3k.emulator.overlay.InputOverlay;
|
||||
|
||||
public class Emulator extends SDLActivity
|
||||
{
|
||||
private InputOverlay mOverlay;
|
||||
private String currentGameId = "";
|
||||
private EmuSurface mSurface;
|
||||
|
||||
public InputOverlay getInputOverlay(){
|
||||
return mOverlay;
|
||||
public InputOverlay getmOverlay() {
|
||||
return mSurface.getmOverlay();
|
||||
}
|
||||
|
||||
@Keep
|
||||
@ -69,17 +74,17 @@ public class Emulator extends SDLActivity
|
||||
@Override
|
||||
protected SDLSurface createSDLSurface(Context context) {
|
||||
// Create the input overlay in the same time
|
||||
mOverlay = new InputOverlay(this);
|
||||
return new EmuSurface(context);
|
||||
mSurface = new EmuSurface(context);
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupLayout(ViewGroup layout){
|
||||
super.setupLayout(layout);
|
||||
layout.addView(mOverlay);
|
||||
layout.addView(getmOverlay());
|
||||
}
|
||||
|
||||
static private String APP_RESTART_PARAMETERS = "AppStartParameters";
|
||||
static private final String APP_RESTART_PARAMETERS = "AppStartParameters";
|
||||
|
||||
@Override
|
||||
protected String[] getArguments() {
|
||||
@ -107,7 +112,7 @@ public class Emulator extends SDLActivity
|
||||
|
||||
@Keep
|
||||
public void restartApp(String app_path, String exec_path, String exec_args){
|
||||
ArrayList<String> args = new ArrayList<String>();
|
||||
ArrayList<String> args = new ArrayList<>();
|
||||
|
||||
// first build the args given to Vita3K when it restarts
|
||||
// this is similar to run_execv in main.cpp
|
||||
@ -134,17 +139,43 @@ public class Emulator extends SDLActivity
|
||||
}
|
||||
|
||||
static final int FILE_DIALOG_CODE = 545;
|
||||
static final int FOLDER_DIALOG_CODE = 546;
|
||||
static final int STORAGE_MANAGER_DIALOG_CODE = 547;
|
||||
|
||||
@Keep
|
||||
public void showFileDialog(){
|
||||
public void showFileDialog() {
|
||||
Intent intent = new Intent()
|
||||
.setType("*/*")
|
||||
.setAction(Intent.ACTION_GET_CONTENT);
|
||||
.setAction(Intent.ACTION_GET_CONTENT)
|
||||
.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
||||
|
||||
intent = Intent.createChooser(intent, "Choose a file");
|
||||
startActivityForResult(intent, FILE_DIALOG_CODE);
|
||||
}
|
||||
|
||||
private boolean isStorageManagerEnabled(){
|
||||
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && Environment.isExternalStorageManager();
|
||||
}
|
||||
|
||||
@Keep
|
||||
public void showFolderDialog() {
|
||||
// If running Android 10-, SDL should have already asked for read and write permissions
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || isStorageManagerEnabled()) {
|
||||
Intent intent = new Intent()
|
||||
.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
||||
|
||||
intent = Intent.createChooser(intent, "Choose a folder");
|
||||
startActivityForResult(intent, FOLDER_DIALOG_CODE);
|
||||
} else {
|
||||
Intent intent = new Intent()
|
||||
.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
||||
.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID));
|
||||
|
||||
startActivityForResult(intent, STORAGE_MANAGER_DIALOG_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
private File getFileFromUri(Uri uri){
|
||||
try {
|
||||
InputStream inputStream = getContentResolver().openInputStream(uri);
|
||||
@ -166,75 +197,76 @@ public class Emulator extends SDLActivity
|
||||
}
|
||||
}
|
||||
|
||||
// from https://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content
|
||||
private String getFileName(Uri uri){
|
||||
String result = null;
|
||||
if(uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)){
|
||||
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
|
||||
try {
|
||||
if(cursor != null && cursor.moveToFirst()){
|
||||
int name_index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||
if(name_index >= 0)
|
||||
result = cursor.getString(name_index);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
if(result == null){
|
||||
result = uri.getLastPathSegment();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if(requestCode == FILE_DIALOG_CODE){
|
||||
String result_path = "";
|
||||
int result_fd = -1;
|
||||
if(resultCode == RESULT_OK){
|
||||
Uri result_uri = data.getData();
|
||||
String filename = getFileName(result_uri);
|
||||
String result_uri_string = result_uri.toString();
|
||||
int result_fd = -1;
|
||||
try {
|
||||
AssetFileDescriptor asset_fd = getContentResolver().openAssetFileDescriptor(result_uri, "r");
|
||||
// if the file is less than 64 KB, make a temporary copy
|
||||
if(asset_fd.getLength() >= 64*1024) {
|
||||
ParcelFileDescriptor file_descr = getContentResolver().openFileDescriptor(result_uri, "r");
|
||||
result_fd = file_descr.detachFd();
|
||||
try (AssetFileDescriptor asset_fd = getContentResolver().openAssetFileDescriptor(result_uri, "r")){
|
||||
// if the file is less than 4 KB, make a temporary copy
|
||||
if(asset_fd.getLength() >= 4*1024) {
|
||||
try (ParcelFileDescriptor file_descr = getContentResolver().openFileDescriptor(result_uri, "r")) {
|
||||
result_fd = file_descr.detachFd();
|
||||
// in case the last call returns a ErrnoException
|
||||
result_path = result_uri.toString();
|
||||
result_path = Os.readlink("/proc/self/fd/" + result_fd);
|
||||
}
|
||||
} else {
|
||||
File f = getFileFromUri(result_uri);
|
||||
result_uri_string = f.getAbsolutePath();
|
||||
result_path = f.getAbsolutePath();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (ErrnoException | IOException e) {
|
||||
}
|
||||
filedialogReturn(result_uri_string, result_fd, filename);
|
||||
} else if(resultCode == RESULT_CANCELED){
|
||||
filedialogReturn("", -1, "");
|
||||
}
|
||||
filedialogReturn(result_path, result_fd);
|
||||
} else if(requestCode == FOLDER_DIALOG_CODE){
|
||||
String result_path = "";
|
||||
if(resultCode == RESULT_OK){
|
||||
Uri result_uri = data.getData();
|
||||
DocumentFile tree = DocumentFile.fromTreeUri(getApplicationContext(), result_uri);
|
||||
try(ParcelFileDescriptor file_descr = getContentResolver().openFileDescriptor(tree.getUri(), "r")) {
|
||||
int result_fd = file_descr.getFd();
|
||||
|
||||
result_path = Os.readlink("/proc/self/fd/" + result_fd);
|
||||
// replace /mnt/user/{id} with /storage
|
||||
if(result_path.startsWith("/mnt/user/")){
|
||||
result_path = result_path.substring("/mnt/user/".length());
|
||||
result_path = "/storage" + result_path.substring(result_path.indexOf('/'));
|
||||
}
|
||||
} catch (ErrnoException | IOException e) {
|
||||
}
|
||||
}
|
||||
filedialogReturn(result_path, 0);
|
||||
} else if (requestCode == STORAGE_MANAGER_DIALOG_CODE) {
|
||||
if (isStorageManagerEnabled()) {
|
||||
showFolderDialog();
|
||||
} else {
|
||||
filedialogReturn("", -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
public void setControllerOverlayState(int overlay_mask, boolean edit, boolean reset){
|
||||
mOverlay.setState(overlay_mask);
|
||||
mOverlay.setIsInEditMode(edit);
|
||||
getmOverlay().setState(overlay_mask);
|
||||
getmOverlay().setIsInEditMode(edit);
|
||||
|
||||
if(reset)
|
||||
mOverlay.resetButtonPlacement();
|
||||
getmOverlay().resetButtonPlacement();
|
||||
}
|
||||
|
||||
@Keep
|
||||
public void setControllerOverlayScale(float scale){
|
||||
mOverlay.setScale(scale);
|
||||
getmOverlay().setScale(scale);
|
||||
}
|
||||
|
||||
@Keep
|
||||
public void setControllerOverlayOpacity(int opacity){
|
||||
mOverlay.setOpacity(opacity);
|
||||
getmOverlay().setOpacity(opacity);
|
||||
}
|
||||
|
||||
@Keep
|
||||
@ -270,5 +302,13 @@ public class Emulator extends SDLActivity
|
||||
return true;
|
||||
}
|
||||
|
||||
public native void filedialogReturn(String result_uri, int result_fd, String filename);
|
||||
@Keep
|
||||
public boolean isDefaultOrientationLandscape() {
|
||||
// we know the current device orientation is landscape
|
||||
// so the default one is also landscape if and only if the rotation is 0 or 180
|
||||
int rotation = getWindowManager().getDefaultDisplay().getRotation();
|
||||
return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180;
|
||||
}
|
||||
|
||||
public native void filedialogReturn(String result_path, int result_fd);
|
||||
}
|
@ -106,7 +106,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
||||
defaultOverlay();
|
||||
|
||||
// Set the on touch listener.
|
||||
setOnTouchListener(this);
|
||||
// Do not register the overlay as a touch listener
|
||||
// Instead let EmuSurface forward touch events
|
||||
// setOnTouchListener(this);
|
||||
|
||||
// Force draw
|
||||
setWillNotDraw(false);
|
||||
@ -126,7 +128,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
||||
@Override
|
||||
public void run() {
|
||||
Emulator emu = (Emulator) SDL.getContext();
|
||||
emu.getInputOverlay().tick();
|
||||
emu.getmOverlay().tick();
|
||||
}
|
||||
}, 1000, 1000);
|
||||
|
||||
|
@ -147,12 +147,12 @@ Note: The CMake preset `linux-ninja-clang` makes use of the LLD linker, which wi
|
||||
|
||||
- Building can be done with Android studio: select the Vita3K Android folder and click on the build icon or by command line:
|
||||
```sh
|
||||
./gradlew --stacktrace --configuration-cache --build-cache --parallel --configure-on-demand assembleRelease
|
||||
./gradlew --stacktrace --configuration-cache --build-cache --parallel --configure-on-demand assembleReldebug
|
||||
```
|
||||
|
||||
### Building SDL
|
||||
|
||||
Note that if you want to build the SDL library yourself for Android instead of using the prebuilt version, its source code must be patched to allow for custom drivers to be loaded. Please refer to (get permalink)
|
||||
Note that if you want to build the SDL library yourself for Android instead of using the prebuilt version, its source code must be patched to allow for custom drivers to be loaded. Please refer to [this part of the code](https://github.com/Vita3K/Vita3K-Android/blob/2791cf6bbf694a549080b958a7127ff483b11b99/vita3k/app/src/app_init.cpp#L132). If Vita3K is built using an unpatched version of SDL, it will compile and run correctly but crash when trying to load a custom driver.
|
||||
|
||||
## Note
|
||||
|
||||
|
@ -88,9 +88,8 @@ void add_custom_driver(EmuEnvState &emuenv) {
|
||||
if (result != host::dialog::filesystem::SUCCESS)
|
||||
return;
|
||||
|
||||
std::string driver = host::dialog::filesystem::resolve_filename(file_path);
|
||||
// remove the .zip extension
|
||||
driver = fs::path(driver).stem().string();
|
||||
std::string driver = file_path.filename().stem().string();
|
||||
|
||||
fs::path driver_path = fs::path(SDL_AndroidGetInternalStoragePath()) / "driver" / driver;
|
||||
|
||||
|
@ -209,7 +209,7 @@ void draw_archive_install_dialog(GuiState &gui, EmuEnvState &emuenv) {
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
for (const auto &archive : contents_archives) {
|
||||
ImGui::TextWrapped("%s", host::dialog::filesystem::resolve_filename(archive.first).c_str());
|
||||
ImGui::TextWrapped("%s", archive.first.filename().string().c_str());
|
||||
ImGui::Spacing();
|
||||
const auto count_contents_successed = count_content_state(archive.first, true);
|
||||
if (count_contents_successed) {
|
||||
|
@ -26,9 +26,7 @@ namespace gui {
|
||||
|
||||
enum InitialSetup {
|
||||
SELECT_LANGUAGE,
|
||||
#ifndef ANDROID
|
||||
SELECT_PREF_PATH,
|
||||
#endif
|
||||
INSTALL_FIRMWARE,
|
||||
SELECT_INTERFACE_SETTINGS,
|
||||
FINISHED
|
||||
@ -106,6 +104,9 @@ void draw_initial_setup(GuiState &gui, EmuEnvState &emuenv) {
|
||||
ImGui::Text("%s", title_str.c_str());
|
||||
ImGui::SetCursorPosY(94.f * SCALE.y);
|
||||
ImGui::Separator();
|
||||
#ifdef ANDROID
|
||||
const char* path_warning = "Using a different path requires additional permissions";
|
||||
#endif
|
||||
switch (setup) {
|
||||
case SELECT_LANGUAGE:
|
||||
title_str = lang["select_language"];
|
||||
@ -142,12 +143,15 @@ void draw_initial_setup(GuiState &gui, EmuEnvState &emuenv) {
|
||||
ImGui::PopStyleVar();
|
||||
break;
|
||||
|
||||
#ifndef ANDROID
|
||||
case SELECT_PREF_PATH:
|
||||
title_str = lang["select_pref_path"];
|
||||
ImGui::SetCursorPos(ImVec2((WINDOW_SIZE.x / 2.f) - (ImGui::CalcTextSize(lang["current_emu_path"].c_str()).x / 2.f), (WINDOW_SIZE.y / 2.f) - ImGui::GetFontSize()));
|
||||
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%s", lang["current_emu_path"].c_str());
|
||||
ImGui::Spacing();
|
||||
#ifdef ANDROID
|
||||
ImGui::SetCursorPosX((WINDOW_SIZE.x / 2.f) - (ImGui::CalcTextSize(path_warning).x / 2.f));
|
||||
ImGui::TextColored(ImVec4(0.98f, 0.01f, 0.20f, 1.0f), "%s", path_warning);
|
||||
#endif
|
||||
ImGui::SetCursorPosX((WINDOW_SIZE.x / 2.f) - (ImGui::CalcTextSize(emuenv.cfg.pref_path.c_str()).x / 2.f));
|
||||
ImGui::TextWrapped("%s", emuenv.cfg.pref_path.c_str());
|
||||
ImGui::SetCursorPos(!is_default_path ? ImVec2((WINDOW_SIZE.x / 2.f) - BIG_BUTTON_SIZE.x - (20.f * SCALE.x), BIG_BUTTON_POS.y) : BIG_BUTTON_POS);
|
||||
@ -172,7 +176,6 @@ void draw_initial_setup(GuiState &gui, EmuEnvState &emuenv) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case INSTALL_FIRMWARE:
|
||||
title_str = lang["install_firmware"];
|
||||
|
@ -111,7 +111,7 @@ static void change_emulator_path(GuiState &gui, EmuEnvState &emuenv) {
|
||||
|
||||
if (result == host::dialog::filesystem::Result::SUCCESS && emulator_path.native() != emuenv.pref_path.native()) {
|
||||
// Refresh the working paths
|
||||
emuenv.pref_path = fs::path(emulator_path.native()) / "";
|
||||
emuenv.pref_path = emulator_path / "";
|
||||
|
||||
// TODO: Move app old to new path
|
||||
reset_emulator(gui, emuenv);
|
||||
@ -1081,7 +1081,7 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) {
|
||||
ImGui::SetTooltip("%s", lang.emulator["case_insensitive_description"].c_str());
|
||||
#endif
|
||||
ImGui::Separator();
|
||||
#ifndef ANDROID
|
||||
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.f) - (ImGui::CalcTextSize(lang.emulator["emu_storage_folder"].c_str()).x / 2.f));
|
||||
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%s", lang.emulator["emu_storage_folder"].c_str());
|
||||
ImGui::Spacing();
|
||||
@ -1107,8 +1107,12 @@ void draw_settings_dialog(GuiState &gui, EmuEnvState &emuenv) {
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", lang.emulator["reset_emu_path_description"].c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::Spacing();
|
||||
#ifdef ANDROID
|
||||
ImGui::TextColored(GUI_COLOR_TEXT, "%s", "Using a different path requires additional permissions");
|
||||
ImGui::Spacing();
|
||||
#endif
|
||||
ImGui::Separator();
|
||||
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.f) - (ImGui::CalcTextSize(lang.emulator["custom_config_settings"].c_str()).x / 2.f));
|
||||
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%s", lang.emulator["custom_config_settings"].c_str());
|
||||
|
@ -108,13 +108,6 @@ Result pick_folder(fs::path &resulting_path, const fs::path& default_path = "");
|
||||
*/
|
||||
FILE *resolve_host_handle(const fs::path &path);
|
||||
|
||||
/**
|
||||
* @brief Return a print-friendly path
|
||||
*/
|
||||
std::string resolve_path_string(const fs::path &path);
|
||||
|
||||
std::string resolve_filename(const fs::path &path);
|
||||
|
||||
/**
|
||||
* @brief Get a string describing the last dialog error
|
||||
*
|
||||
|
@ -33,28 +33,23 @@
|
||||
#include <SDL.h>
|
||||
#include <jni.h>
|
||||
|
||||
static bool file_dialog_running = false;
|
||||
static std::atomic<bool> file_dialog_running = false;
|
||||
|
||||
// the result from the dialog, this is an UTF-8 string
|
||||
static std::string dialog_result_uri = "";
|
||||
static fs::path dialog_result_path = "";
|
||||
// the resulting file descriptor from the dialog
|
||||
static int dialog_result_fd = -1;
|
||||
static std::string dialog_result_filename = "";
|
||||
|
||||
static std::map<fs::path, std::pair<int, std::string>> path_mapping;
|
||||
static std::map<fs::path, int> path_mapping;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_org_vita3k_emulator_Emulator_filedialogReturn(JNIEnv *env, jobject thiz, jstring result_uri, jint result_fd, jstring filename) {
|
||||
const char *result_ptr = env->GetStringUTFChars(result_uri, nullptr);
|
||||
dialog_result_uri = std::string(result_ptr);
|
||||
env->ReleaseStringUTFChars(result_uri, result_ptr);
|
||||
|
||||
result_ptr = env->GetStringUTFChars(filename, nullptr);
|
||||
dialog_result_filename = std::string(result_ptr);
|
||||
env->ReleaseStringUTFChars(filename, result_ptr);
|
||||
|
||||
Java_org_vita3k_emulator_Emulator_filedialogReturn(JNIEnv *env, jobject thiz, jstring result_path, jint result_fd) {
|
||||
const char *result_ptr = env->GetStringUTFChars(result_path, nullptr);
|
||||
dialog_result_path = fs::path(result_ptr);
|
||||
env->ReleaseStringUTFChars(result_path, result_ptr);
|
||||
dialog_result_fd = result_fd;
|
||||
file_dialog_running = false;
|
||||
|
||||
file_dialog_running.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,11 +81,15 @@ std::string format_file_filter_extension_list(const std::vector<std::string> &fi
|
||||
return formatted_string;
|
||||
};
|
||||
|
||||
namespace host {
|
||||
namespace dialog {
|
||||
namespace filesystem {
|
||||
Result open_file(fs::path &resulting_path, const std::vector<FileFilter>& file_filters, const fs::path& default_path) {
|
||||
SDL_AndroidRequestPermission("android.permission.READ_EXTERNAL_STORAGE");
|
||||
static void call_dialog_java_function(const char* name, bool need_write){
|
||||
// These permissions are not needed on Android 11+
|
||||
if(SDL_GetAndroidSDKVersion() < 30) {
|
||||
SDL_AndroidRequestPermission("android.permission.READ_EXTERNAL_STORAGE");
|
||||
|
||||
if(need_write) {
|
||||
SDL_AndroidRequestPermission("android.permission.WRITE_EXTERNAL_STORAGE");
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = reinterpret_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||
@ -102,7 +101,7 @@ Result open_file(fs::path &resulting_path, const std::vector<FileFilter>& file_f
|
||||
jclass clazz(env->GetObjectClass(activity));
|
||||
|
||||
// find the identifier of the method to call
|
||||
jmethodID method_id = env->GetMethodID(clazz, "showFileDialog", "()V");
|
||||
jmethodID method_id = env->GetMethodID(clazz, name, "()V");
|
||||
|
||||
file_dialog_running = true;
|
||||
// effectively call the Java method
|
||||
@ -112,22 +111,36 @@ Result open_file(fs::path &resulting_path, const std::vector<FileFilter>& file_f
|
||||
env->DeleteLocalRef(activity);
|
||||
env->DeleteLocalRef(clazz);
|
||||
|
||||
while (file_dialog_running)
|
||||
while (file_dialog_running.load(std::memory_order_acquire))
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
if (dialog_result_uri.empty())
|
||||
namespace host {
|
||||
namespace dialog {
|
||||
namespace filesystem {
|
||||
Result open_file(fs::path &resulting_path, const std::vector<FileFilter>& file_filters, const fs::path& default_path) {
|
||||
call_dialog_java_function("showFileDialog", false);
|
||||
|
||||
if (dialog_result_path.empty())
|
||||
return Result::CANCEL;
|
||||
|
||||
resulting_path = fs::path(dialog_result_uri);
|
||||
// if dialog_result_fd is -1, it means the file was copied and we can open it with the usual io functions
|
||||
if (dialog_result_fd != -1)
|
||||
path_mapping[resulting_path] = {dialog_result_fd, dialog_result_filename};
|
||||
if(dialog_result_fd > 0)
|
||||
path_mapping[dialog_result_path] = dialog_result_fd;
|
||||
|
||||
resulting_path = std::move(dialog_result_path);
|
||||
|
||||
return Result::SUCCESS;
|
||||
};
|
||||
|
||||
Result pick_folder(fs::path &resulting_path, const fs::path& default_path) {
|
||||
return Result::ERROR;
|
||||
call_dialog_java_function("showFolderDialog", true);
|
||||
|
||||
if(dialog_result_path.empty())
|
||||
return Result::CANCEL;
|
||||
|
||||
resulting_path = std::move(dialog_result_path);
|
||||
|
||||
return Result::SUCCESS;
|
||||
};
|
||||
|
||||
std::string get_error() {
|
||||
@ -143,33 +156,15 @@ std::string get_error() {
|
||||
|
||||
FILE *resolve_host_handle(const fs::path &path) {
|
||||
auto it = path_mapping.find(path);
|
||||
if (it != path_mapping.end() && it->second.first != -1) {
|
||||
int fd = it->second.first;
|
||||
|
||||
if (it != path_mapping.end()) {
|
||||
int fd = it->second;
|
||||
return fdopen(fd, "rb");
|
||||
} else {
|
||||
return fopen(path.c_str(), "rb");
|
||||
}
|
||||
}
|
||||
|
||||
std::string resolve_path_string(const fs::path &path){
|
||||
auto it = path_mapping.find(path);
|
||||
if (it != path_mapping.end()) {
|
||||
// this is only the filename but that's still better than giving the Uri
|
||||
return it->second.second;
|
||||
} else {
|
||||
return std::string(path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string resolve_filename(const fs::path &path){
|
||||
auto it = path_mapping.find(path);
|
||||
if (it != path_mapping.end()) {
|
||||
return it->second.second;
|
||||
} else {
|
||||
return std::string(path.filename().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
} // namespace dialog
|
||||
} // namespace host
|
||||
|
@ -217,14 +217,6 @@ FILE *resolve_host_handle(const fs::path &path) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string resolve_path_string(const fs::path &path){
|
||||
return path.string();
|
||||
}
|
||||
|
||||
std::string resolve_filename(const fs::path &path){
|
||||
return path.filename().string();
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
} // namespace dialog
|
||||
} // namespace host
|
||||
|
@ -8,3 +8,6 @@ add_library(
|
||||
target_include_directories(motion PUBLIC include)
|
||||
target_link_libraries(motion PUBLIC emuenv sdl2 util)
|
||||
target_link_libraries(motion PRIVATE ctrl)
|
||||
if(ANDROID)
|
||||
target_link_libraries(host_dialog PRIVATE sdl2)
|
||||
endif()
|
||||
|
@ -25,6 +25,30 @@
|
||||
#include <SDL.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
static bool is_device_landscape = false;
|
||||
|
||||
static void init_device_orientation(){
|
||||
JNIEnv *env = reinterpret_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||
jobject activity = reinterpret_cast<jobject>(SDL_AndroidGetActivity());
|
||||
jclass clazz(env->GetObjectClass(activity));
|
||||
|
||||
jmethodID method_id = env->GetMethodID(clazz, "isDefaultOrientationLandscape", "()Z");
|
||||
|
||||
is_device_landscape = env->CallBooleanMethod(activity, method_id);
|
||||
|
||||
// clean up the local references.
|
||||
env->DeleteLocalRef(activity);
|
||||
env->DeleteLocalRef(clazz);
|
||||
}
|
||||
|
||||
#else
|
||||
constexpr bool is_device_landscape = true;
|
||||
#endif
|
||||
|
||||
static void init_device_sensors(MotionState& state){
|
||||
const int num_sensors = SDL_NumSensors();
|
||||
for(int idx = 0; idx < num_sensors; idx++){
|
||||
@ -48,6 +72,10 @@ static void init_device_sensors(MotionState& state){
|
||||
SDL_SensorClose(sensor);
|
||||
}
|
||||
state.has_device_motion_support = (state.device_accel && state.device_gyro);
|
||||
|
||||
#ifdef ANDROID
|
||||
init_device_orientation();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MotionState::init(){
|
||||
@ -189,16 +217,15 @@ void refresh_motion(MotionState &state, CtrlState &ctrl_state) {
|
||||
}
|
||||
|
||||
gyro /= static_cast<float>(2.0 * M_PI);
|
||||
if(gyro_from_device)
|
||||
std::tie(gyro.x, gyro.y, gyro.z) = std::make_tuple(-gyro.y, gyro.z, -gyro.x);
|
||||
std::swap(gyro.y, gyro.z);
|
||||
gyro.y *= -1;
|
||||
|
||||
accel /= -SDL_STANDARD_GRAVITY;
|
||||
if(accel_from_device)
|
||||
std::tie(accel.x, accel.y, accel.z) = std::make_tuple(-accel.y, accel.z, -accel.x);
|
||||
std::swap(accel.y, accel.z);
|
||||
accel.y *= -1;
|
||||
|
||||
if(gyro_from_device && !is_device_landscape){
|
||||
std::tie(gyro.x, gyro.y, gyro.z) = std::make_tuple(-gyro.y, gyro.x, gyro.z);
|
||||
std::tie(accel.x, accel.y, accel.z) = std::make_tuple(-accel.y, accel.x, accel.z);
|
||||
} else if (!gyro_from_device) {
|
||||
std::tie(gyro.x, gyro.y, gyro.z) = std::make_tuple(gyro.x, -gyro.z, gyro.y);
|
||||
std::tie(accel.x, accel.y, accel.z) = std::make_tuple(accel.x, -accel.z, accel.y);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(state.mutex);
|
||||
|
||||
|
@ -252,6 +252,7 @@ bool install_pkg(const fs::path &pkg_path, EmuEnvState &emuenv, std::string &p_z
|
||||
EVP_DecryptFinal_ex(cipher_ctx, data + dec_len, &dec_len);
|
||||
};
|
||||
|
||||
std::vector<uint8_t> buffer(0x10000);
|
||||
for (uint32_t i = 0; i < byte_swap(pkg_header.file_count); i++) {
|
||||
PkgEntry entry;
|
||||
uint64_t file_offset = items_offset + i * 32;
|
||||
@ -289,16 +290,14 @@ bool install_pkg(const fs::path &pkg_path, EmuEnvState &emuenv, std::string &p_z
|
||||
EVP_DecryptInit_ex(cipher_ctx, cipher_CTR, nullptr, main_key, counter);
|
||||
EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
|
||||
|
||||
std::vector<uint8_t> buffer(0x10000);
|
||||
fseek(infile, byte_swap(pkg_header.data_offset) + offset, SEEK_SET);
|
||||
while (data_size != 0) {
|
||||
auto size = data_size < sizeof(buffer) ? data_size : sizeof(buffer);
|
||||
fseek(infile, byte_swap(pkg_header.data_offset) + offset, SEEK_SET);
|
||||
size_t size = data_size < buffer.size() ? data_size : buffer.size();
|
||||
fread(buffer.data(), size, 1, infile);
|
||||
|
||||
EVP_DecryptUpdate(cipher_ctx, buffer.data(), &dec_len, buffer.data(), size);
|
||||
|
||||
outfile.write(reinterpret_cast<char *>(buffer.data()), dec_len);
|
||||
offset += size;
|
||||
data_size -= size;
|
||||
}
|
||||
|
||||
|
@ -241,8 +241,8 @@ void convert_f32m_to_f32(void *dest, const void *data, const uint32_t width, con
|
||||
|
||||
for (uint32_t row = 0; row < height; ++row) {
|
||||
for (uint32_t col = 0; col < width; ++col) {
|
||||
const uint32_t src_value = src[row * width + height];
|
||||
dst[row * width + height] = src_value & 0x7FFFFFFF;
|
||||
const uint32_t src_value = src[row * width + col];
|
||||
dst[row * width + col] = src_value & 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user