diff options
72 files changed, 1329 insertions, 544 deletions
diff --git a/.gitmodules b/.gitmodules index 07479dd78..d5a7ade4f 100644 --- a/.gitmodules +++ b/.gitmodules | |||
| @@ -19,3 +19,6 @@ | |||
| 19 | [submodule "lz4"] | 19 | [submodule "lz4"] |
| 20 | path = externals/lz4 | 20 | path = externals/lz4 |
| 21 | url = http://github.com/lz4/lz4.git | 21 | url = http://github.com/lz4/lz4.git |
| 22 | [submodule "unicorn"] | ||
| 23 | path = externals/unicorn | ||
| 24 | url = https://github.com/yuzu-emu/unicorn | ||
diff --git a/.travis.yml b/.travis.yml index 8bad23208..9edfc0809 100644 --- a/.travis.yml +++ b/.travis.yml | |||
| @@ -2,6 +2,14 @@ language: cpp | |||
| 2 | matrix: | 2 | matrix: |
| 3 | include: | 3 | include: |
| 4 | - os: linux | 4 | - os: linux |
| 5 | env: NAME="clang-format" | ||
| 6 | dist: trusty | ||
| 7 | addons: | ||
| 8 | apt: | ||
| 9 | packages: | ||
| 10 | - clang-format-3.9 | ||
| 11 | script: "./.travis/clang-format/script.sh" | ||
| 12 | - os: linux | ||
| 5 | env: NAME="linux build" | 13 | env: NAME="linux build" |
| 6 | sudo: required | 14 | sudo: required |
| 7 | dist: trusty | 15 | dist: trusty |
| @@ -20,19 +28,11 @@ matrix: | |||
| 20 | install: "./.travis/macos/deps.sh" | 28 | install: "./.travis/macos/deps.sh" |
| 21 | script: "./.travis/macos/build.sh" | 29 | script: "./.travis/macos/build.sh" |
| 22 | after_success: "./.travis/macos/upload.sh" | 30 | after_success: "./.travis/macos/upload.sh" |
| 23 | - os: linux | ||
| 24 | env: NAME="clang-format" | ||
| 25 | dist: trusty | ||
| 26 | addons: | ||
| 27 | apt: | ||
| 28 | packages: | ||
| 29 | - clang-format-3.9 | ||
| 30 | script: "./.travis/clang-format/script.sh" | ||
| 31 | 31 | ||
| 32 | deploy: | 32 | deploy: |
| 33 | provider: releases | 33 | provider: releases |
| 34 | api_key: | 34 | api_key: |
| 35 | secure: Mck15DIWaJdxDiS3aYVlM9N3G6y8VKUI1rnwII7/iolfm1s94U+tgvbheZDmT7SSbFyaGaYO/E8HrV/uZR9Vvs7ev20sHsTN1u60OTWfDIIyHs9SqjhcGbtq95m9/dMFschOYqTOR+gAs5BsxjuoeAotHdhpQEwvkO2oo5oR0zhGy45gjFnVvtcxT/IfpZBIpVgcK3aLb9zT6ekcJbSiPmEB15iLq3xXd0nFUNtEZdX3D6Veye4n5jB6n72qN8JVoKvPZAwaC2K0pZxpcGJaXDchLsw1q+4eCvdz6UJfUemeQ/uMAmjfeQ3wrzYGXe3nCM3WmX5wosCsB0mw4zYatzl3si6CZ1W+0GkV4Rwlx03dfp7v3EeFhTsXYCaXqhwuLZnWOLUik8t9vaSoFUx4nUIRwfO9kAMUJQSpLuHNO2nT01s3GxvqxzczuLQ9he5nGSi0RRodUzDwek1qUp6I4uV3gRHKz4B07YIc1i2fK88NLXjyQ0uLVZ+7Oq1+kgDp6+N7vvXXZ5qZ17tdaysSbKEE0Y8zsoXw7Rk1tPN19vrCS+TSpomNMyQyne1k+I5iZ/qkxPTLAS5qI6Utc2dL3GJdxWRAEfGNO9AIX3GV/jmmKfdcvwGsCYP8hxqs5vLYfgacw3D8NLf1941lQUwavC17jm9EV9g5G3Pn1Cp516E= | 35 | secure: IuTT8DjxzNgOtaEsyOpz1JaSmtDtHSsWZnJKmSBwXAzgP2ZU4Ja3/q0z5PwbC5Ql7kuFahuYTE5oi7lbJBuu2P3y1Wj2zvFozGUkA3JUvEXDNOPS9QTJ1EYd6O+wenZoj7d/Pn+ZeIgyEafnnZsGBb8lMQnV9MfIHgYlZQ5EyF3n4XikT2h1UbDBYx74ciXZIxFEulx68kDr9Q4/U+zIYQmYv2N+lgXSLDkFrCJ046gRcujPYGPqE6jVw0kKni80CTTpuDF5prU8yIBeiffjkJ3Qx1a17G07eZ4r83P4XUOlaHbRBmA/8ywZvLF2Gep3wGKfSFgMWbPxBJk5ZSYcOOAgMsEcg0+gBK9gLTwO4pbmc2GvqP21yRQBzgtbFoEtAHLu5lVPBkZU7kZuRMJtRdqvFIwOLhpnRS8IknFOD5vjtaFiNdGWaK9ePdsGvplijnXcPafkumakc4+eVEiXb6/KzdX1zXdur5tuUPFytm0Oy6IJcGIf8FHXGvUlmWsnPzwfusij9JgeQOP+uegc9PdBfL+h7L5rk+ilELt3cXD5K7wgov/4hkl5istNJ2bm0IioIstWss8QQQTkyscGoeh/oXmUpOL4FdsTvsWhDR3QKeq8nSzgDkqLe0iSbplQGnC7o7ytNbldmxJvf3nylwglA8w3HlqLHtZLkUOcuQ0= |
| 36 | file_glob: true | 36 | file_glob: true |
| 37 | file: "artifacts/*" | 37 | file: "artifacts/*" |
| 38 | skip_cleanup: true | 38 | skip_cleanup: true |
diff --git a/.travis/linux/docker.sh b/.travis/linux/docker.sh index a85225c5a..8a23b54b1 100755 --- a/.travis/linux/docker.sh +++ b/.travis/linux/docker.sh | |||
| @@ -1,22 +1,16 @@ | |||
| 1 | #!/bin/bash -ex | 1 | #!/bin/bash -ex |
| 2 | 2 | ||
| 3 | apt-get update | 3 | apt-get update |
| 4 | apt-get install -y build-essential git libcurl4-openssl-dev libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget | 4 | apt-get install -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget |
| 5 | 5 | ||
| 6 | # Get a recent version of CMake | 6 | # Get a recent version of CMake |
| 7 | wget https://cmake.org/files/v3.10/cmake-3.10.1-Linux-x86_64.sh | 7 | wget https://cmake.org/files/v3.10/cmake-3.10.1-Linux-x86_64.sh |
| 8 | sh cmake-3.10.1-Linux-x86_64.sh --exclude-subdir --prefix=/ --skip-license | 8 | sh cmake-3.10.1-Linux-x86_64.sh --exclude-subdir --prefix=/ --skip-license |
| 9 | 9 | ||
| 10 | mkdir /unicorn | ||
| 11 | cd /unicorn | ||
| 12 | git clone https://github.com/yuzu-emu/unicorn . | ||
| 13 | UNICORN_ARCHS=aarch64 ./make.sh | ||
| 14 | ./make.sh install | ||
| 15 | |||
| 16 | cd /yuzu | 10 | cd /yuzu |
| 17 | 11 | ||
| 18 | mkdir build && cd build | 12 | mkdir build && cd build |
| 19 | cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release | 13 | cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release |
| 20 | make -j4 | 14 | make -j4 |
| 21 | 15 | ||
| 22 | ctest -VV -C Release | 16 | ctest -VV -C Release |
diff --git a/.travis/macos/build.sh b/.travis/macos/build.sh index e1c54af55..177e8ac3b 100755 --- a/.travis/macos/build.sh +++ b/.travis/macos/build.sh | |||
| @@ -8,7 +8,7 @@ export UNICORNDIR=$(pwd)/externals/unicorn | |||
| 8 | 8 | ||
| 9 | mkdir build && cd build | 9 | mkdir build && cd build |
| 10 | cmake --version | 10 | cmake --version |
| 11 | cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release | 11 | cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release |
| 12 | make -j4 | 12 | make -j4 |
| 13 | 13 | ||
| 14 | ctest -VV -C Release | 14 | ctest -VV -C Release |
diff --git a/.travis/macos/deps.sh b/.travis/macos/deps.sh index 7dea80438..3cd13a39b 100755 --- a/.travis/macos/deps.sh +++ b/.travis/macos/deps.sh | |||
| @@ -2,9 +2,4 @@ | |||
| 2 | 2 | ||
| 3 | brew update | 3 | brew update |
| 4 | brew install dylibbundler p7zip qt5 sdl2 | 4 | brew install dylibbundler p7zip qt5 sdl2 |
| 5 | 5 | brew outdated cmake || brew upgrade cmake | |
| 6 | mkdir externals/unicorn | ||
| 7 | pushd externals/unicorn | ||
| 8 | git clone https://github.com/yuzu-emu/unicorn . | ||
| 9 | UNICORN_ARCHS=aarch64 ./make.sh macos-universal-no | ||
| 10 | popd | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3da8465b9..d814bb74f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -12,8 +12,6 @@ option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF) | |||
| 12 | option(ENABLE_QT "Enable the Qt frontend" ON) | 12 | option(ENABLE_QT "Enable the Qt frontend" ON) |
| 13 | option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) | 13 | option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) |
| 14 | 14 | ||
| 15 | option(YUZU_USE_BUNDLED_UNICORN "Download bundled Unicorn binaries" OFF) | ||
| 16 | |||
| 17 | if(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit) | 15 | if(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit) |
| 18 | message(STATUS "Copying pre-commit hook") | 16 | message(STATUS "Copying pre-commit hook") |
| 19 | file(COPY hooks/pre-commit | 17 | file(COPY hooks/pre-commit |
| @@ -29,7 +27,7 @@ function(check_submodules_present) | |||
| 29 | foreach(module ${gitmodules}) | 27 | foreach(module ${gitmodules}) |
| 30 | string(REGEX REPLACE "path *= *" "" module ${module}) | 28 | string(REGEX REPLACE "path *= *" "" module ${module}) |
| 31 | if (NOT EXISTS "${CMAKE_SOURCE_DIR}/${module}/.git") | 29 | if (NOT EXISTS "${CMAKE_SOURCE_DIR}/${module}/.git") |
| 32 | message(SEND_ERROR "Git submodule ${module} not found." | 30 | message(FATAL_ERROR "Git submodule ${module} not found. " |
| 33 | "Please run: git submodule update --init --recursive") | 31 | "Please run: git submodule update --init --recursive") |
| 34 | endif() | 32 | endif() |
| 35 | endforeach() | 33 | endforeach() |
| @@ -204,34 +202,65 @@ else() | |||
| 204 | set(SDL2_FOUND NO) | 202 | set(SDL2_FOUND NO) |
| 205 | endif() | 203 | endif() |
| 206 | 204 | ||
| 207 | if (YUZU_USE_BUNDLED_UNICORN) | 205 | # If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external |
| 208 | # Detect toolchain and platform | 206 | find_package(Unicorn QUIET) |
| 209 | if (MSVC14 AND ARCHITECTURE_x86_64) | 207 | if (NOT UNICORN_FOUND) |
| 210 | set(UNICORN_VER "unicorn-yuzu") | 208 | if (MSVC) |
| 211 | else() | 209 | message(STATUS "unicorn not found, falling back to bundled") |
| 212 | message(FATAL_ERROR "No bundled Unicorn binaries for your toolchain. Disable YUZU_USE_BUNDLED_UNICORN and provide your own.") | 210 | # Detect toolchain and platform |
| 213 | endif() | 211 | if (MSVC14 AND ARCHITECTURE_x86_64) |
| 212 | set(UNICORN_VER "unicorn-yuzu") | ||
| 213 | else() | ||
| 214 | message(FATAL_ERROR "No bundled Unicorn binaries for your toolchain. Disable YUZU_USE_BUNDLED_UNICORN and provide your own.") | ||
| 215 | endif() | ||
| 214 | 216 | ||
| 215 | if (DEFINED UNICORN_VER) | 217 | if (DEFINED UNICORN_VER) |
| 216 | download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) | 218 | download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) |
| 217 | endif() | 219 | endif() |
| 218 | 220 | ||
| 219 | if (DEFINED UNICORN_VER) | 221 | if (DEFINED UNICORN_VER) |
| 220 | download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) | 222 | download_bundled_external("unicorn/" ${UNICORN_VER} UNICORN_PREFIX) |
| 221 | endif() | 223 | endif() |
| 222 | 224 | ||
| 223 | set(UNICORN_FOUND YES) | 225 | set(UNICORN_FOUND YES) |
| 224 | set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers") | 226 | set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE) |
| 225 | set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/lib/x64/unicorn_dynload.lib" CACHE PATH "Path to Unicorn library") | 227 | set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/lib/x64/unicorn_dynload.lib" CACHE PATH "Path to Unicorn library" FORCE) |
| 226 | set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/lib/x64/" CACHE PATH "Path to unicorn.dll") | 228 | set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/lib/x64/" CACHE PATH "Path to unicorn.dll" FORCE) |
| 227 | else() | 229 | else() |
| 228 | find_package(Unicorn REQUIRED) | 230 | message(STATUS "unicorn not found, falling back to externals") |
| 231 | if (MINGW) | ||
| 232 | set(UNICORN_LIB_NAME "unicorn.a") | ||
| 233 | else() | ||
| 234 | set(UNICORN_LIB_NAME "libunicorn.a") | ||
| 235 | endif() | ||
| 236 | |||
| 237 | set(UNICORN_FOUND YES) | ||
| 238 | set(UNICORN_PREFIX ${CMAKE_SOURCE_DIR}/externals/unicorn) | ||
| 239 | set(LIBUNICORN_LIBRARY "${UNICORN_PREFIX}/${UNICORN_LIB_NAME}" CACHE PATH "Path to Unicorn library" FORCE) | ||
| 240 | set(LIBUNICORN_INCLUDE_DIR "${UNICORN_PREFIX}/include" CACHE PATH "Path to Unicorn headers" FORCE) | ||
| 241 | set(UNICORN_DLL_DIR "${UNICORN_PREFIX}/" CACHE PATH "Path to unicorn dynamic library" FORCE) | ||
| 242 | |||
| 243 | find_package(PythonInterp 2.7 REQUIRED) | ||
| 244 | |||
| 245 | add_custom_command(OUTPUT ${LIBUNICORN_LIBRARY} | ||
| 246 | COMMAND ${CMAKE_COMMAND} -E env UNICORN_ARCHS="aarch64" PYTHON="${PYTHON_EXECUTABLE}" /bin/sh make.sh | ||
| 247 | WORKING_DIRECTORY ${UNICORN_PREFIX} | ||
| 248 | ) | ||
| 249 | # ALL makes this custom target build every time | ||
| 250 | # but it won't actually build if LIBUNICORN_LIBRARY is up to date | ||
| 251 | add_custom_target(unicorn-build ALL | ||
| 252 | DEPENDS ${LIBUNICORN_LIBRARY} | ||
| 253 | ) | ||
| 254 | unset(UNICORN_LIB_NAME) | ||
| 255 | endif() | ||
| 229 | endif() | 256 | endif() |
| 230 | 257 | ||
| 231 | if (UNICORN_FOUND) | 258 | if (UNICORN_FOUND) |
| 232 | add_library(unicorn INTERFACE) | 259 | add_library(unicorn INTERFACE) |
| 233 | target_link_libraries(unicorn INTERFACE "${LIBUNICORN_LIBRARY}") | 260 | target_link_libraries(unicorn INTERFACE "${LIBUNICORN_LIBRARY}") |
| 234 | target_include_directories(unicorn INTERFACE "${LIBUNICORN_INCLUDE_DIR}") | 261 | target_include_directories(unicorn INTERFACE "${LIBUNICORN_INCLUDE_DIR}") |
| 262 | else() | ||
| 263 | message(FATAL_ERROR "Could not find or build unicorn which is required.") | ||
| 235 | endif() | 264 | endif() |
| 236 | 265 | ||
| 237 | if (ENABLE_QT) | 266 | if (ENABLE_QT) |
| @@ -1,6 +1,7 @@ | |||
| 1 | yuzu emulator | 1 | yuzu emulator |
| 2 | ============= | 2 | ============= |
| 3 | [](https://travis-ci.org/yuzu-emu/yuzu) | 3 | [](https://travis-ci.org/yuzu-emu/yuzu) |
| 4 | [](https://ci.appveyor.com/project/bunnei/yuzu) | ||
| 4 | 5 | ||
| 5 | yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/). | 6 | yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/). |
| 6 | 7 | ||
diff --git a/appveyor.yml b/appveyor.yml index f491e5f0b..954be4e8f 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
| @@ -28,7 +28,6 @@ install: | |||
| 28 | if ($env:BUILD_TYPE -eq 'mingw') { | 28 | if ($env:BUILD_TYPE -eq 'mingw') { |
| 29 | $dependencies = "mingw64/mingw-w64-x86_64-cmake", | 29 | $dependencies = "mingw64/mingw-w64-x86_64-cmake", |
| 30 | "mingw64/mingw-w64-x86_64-qt5", | 30 | "mingw64/mingw-w64-x86_64-qt5", |
| 31 | "mingw64/mingw-w64-x86_64-curl", | ||
| 32 | "mingw64/mingw-w64-x86_64-SDL2" | 31 | "mingw64/mingw-w64-x86_64-SDL2" |
| 33 | # redirect err to null to prevent warnings from becoming errors | 32 | # redirect err to null to prevent warnings from becoming errors |
| 34 | # workaround to prevent pacman from failing due to cyclical dependencies | 33 | # workaround to prevent pacman from failing due to cyclical dependencies |
| @@ -42,9 +41,9 @@ before_build: | |||
| 42 | - ps: | | 41 | - ps: | |
| 43 | if ($env:BUILD_TYPE -eq 'msvc') { | 42 | if ($env:BUILD_TYPE -eq 'msvc') { |
| 44 | # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning | 43 | # redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning |
| 45 | cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DCMAKE_USE_OPENSSL=0 .. 2>&1 && exit 0' | 44 | cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 .. 2>&1 && exit 0' |
| 46 | } else { | 45 | } else { |
| 47 | C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DUSE_SYSTEM_CURL=1 -DYUZU_USE_BUNDLED_CURL=1 -DCMAKE_BUILD_TYPE=Release .. 2>&1" | 46 | C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DYUZU_BUILD_UNICORN=1 -DCMAKE_BUILD_TYPE=Release .. 2>&1" |
| 48 | } | 47 | } |
| 49 | - cd .. | 48 | - cd .. |
| 50 | 49 | ||
| @@ -81,11 +80,12 @@ after_build: | |||
| 81 | $env:BUILD_SYMBOLS = $MSVC_BUILD_PDB | 80 | $env:BUILD_SYMBOLS = $MSVC_BUILD_PDB |
| 82 | $env:BUILD_UPDATE = $MSVC_SEVENZIP | 81 | $env:BUILD_UPDATE = $MSVC_SEVENZIP |
| 83 | 82 | ||
| 84 | 7z a -tzip $MSVC_BUILD_PDB .\msvc_build\bin\release\*.pdb | 83 | mkdir pdb |
| 85 | rm .\msvc_build\bin\release\*.pdb | 84 | Get-ChildItem ".\msvc_build\bin\" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb |
| 85 | 7z a -tzip $MSVC_BUILD_PDB .\pdb\*.pdb | ||
| 86 | 86 | ||
| 87 | mkdir $RELEASE_DIST | 87 | mkdir $RELEASE_DIST |
| 88 | Copy-Item .\msvc_build\bin\release\* -Destination $RELEASE_DIST -Recurse | 88 | Get-ChildItem ".\msvc_build\bin\" -Recurse -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST |
| 89 | Copy-Item .\license.txt -Destination $RELEASE_DIST | 89 | Copy-Item .\license.txt -Destination $RELEASE_DIST |
| 90 | Copy-Item .\README.md -Destination $RELEASE_DIST | 90 | Copy-Item .\README.md -Destination $RELEASE_DIST |
| 91 | 7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\* | 91 | 7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\* |
| @@ -104,16 +104,14 @@ after_build: | |||
| 104 | $env:BUILD_UPDATE = $MINGW_SEVENZIP | 104 | $env:BUILD_UPDATE = $MINGW_SEVENZIP |
| 105 | 105 | ||
| 106 | $CMAKE_SOURCE_DIR = "$env:APPVEYOR_BUILD_FOLDER" | 106 | $CMAKE_SOURCE_DIR = "$env:APPVEYOR_BUILD_FOLDER" |
| 107 | $CMAKE_BINARY_DIR = "$CMAKE_SOURCE_DIR/mingw_build" | 107 | $CMAKE_BINARY_DIR = "$CMAKE_SOURCE_DIR/mingw_build/bin" |
| 108 | $RELEASE_DIST = $RELEASE_DIST + "-mingw" | 108 | $RELEASE_DIST = $RELEASE_DIST + "-mingw" |
| 109 | 109 | ||
| 110 | mkdir $RELEASE_DIST | 110 | mkdir $RELEASE_DIST |
| 111 | mkdir $RELEASE_DIST/platforms | 111 | mkdir $RELEASE_DIST/platforms |
| 112 | 112 | ||
| 113 | # copy the compiled binaries and other release files to the release folder | 113 | # copy the compiled binaries and other release files to the release folder |
| 114 | Get-ChildItem "$CMAKE_BINARY_DIR" -Recurse -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST | 114 | Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST |
| 115 | # copy the libcurl dll | ||
| 116 | Get-ChildItem "$CMAKE_BINARY_DIR" -Recurse -Filter "libcurl.dll" | Copy-Item -destination $RELEASE_DIST | ||
| 117 | Copy-Item -path "$CMAKE_SOURCE_DIR/license.txt" -destination $RELEASE_DIST | 115 | Copy-Item -path "$CMAKE_SOURCE_DIR/license.txt" -destination $RELEASE_DIST |
| 118 | Copy-Item -path "$CMAKE_SOURCE_DIR/README.md" -destination $RELEASE_DIST | 116 | Copy-Item -path "$CMAKE_SOURCE_DIR/README.md" -destination $RELEASE_DIST |
| 119 | # copy all the dll dependencies to the release folder | 117 | # copy all the dll dependencies to the release folder |
| @@ -122,7 +120,7 @@ after_build: | |||
| 122 | # QT dll dependencies | 120 | # QT dll dependencies |
| 123 | "libbz2-*.dll","libicudt*.dll","libicuin*.dll","libicuuc*.dll","libffi-*.dll", | 121 | "libbz2-*.dll","libicudt*.dll","libicuin*.dll","libicuuc*.dll","libffi-*.dll", |
| 124 | "libfreetype-*.dll","libglib-*.dll","libgobject-*.dll","libgraphite2.dll","libiconv-*.dll", | 122 | "libfreetype-*.dll","libglib-*.dll","libgobject-*.dll","libgraphite2.dll","libiconv-*.dll", |
| 125 | "libharfbuzz-*.dll","libintl-*.dll","libpcre-*.dll","libpcre16-*.dll","libpng16-*.dll", | 123 | "libharfbuzz-*.dll","libintl-*.dll","libpcre-*.dll","libpcre2-16-*.dll","libpcre16-*.dll","libpng16-*.dll", |
| 126 | # Runtime/Other dependencies | 124 | # Runtime/Other dependencies |
| 127 | "libgcc_s_seh-*.dll","libstdc++-*.dll","libwinpthread-*.dll","SDL2.dll","zlib1.dll" | 125 | "libgcc_s_seh-*.dll","libstdc++-*.dll","libwinpthread-*.dll","SDL2.dll","zlib1.dll" |
| 128 | foreach ($file in $MingwDLLs) { | 126 | foreach ($file in $MingwDLLs) { |
| @@ -165,7 +163,7 @@ deploy: | |||
| 165 | provider: GitHub | 163 | provider: GitHub |
| 166 | release: $(appveyor_repo_tag_name) | 164 | release: $(appveyor_repo_tag_name) |
| 167 | auth_token: | 165 | auth_token: |
| 168 | secure: "dbpsMC/MgPKWFNJCXpQl4cR8FYhepkPLjgNp/pRMktZ8oLKTqPYErfreaIxb/4P1" | 166 | secure: "argb6oi2TYLB4wDy+HoCC8PuGAmsnocSk12CQ5614XAPO+NVPndlkLv1utnDFfg2" |
| 169 | artifact: update,build | 167 | artifact: update,build |
| 170 | draft: false | 168 | draft: false |
| 171 | prerelease: false | 169 | prerelease: false |
diff --git a/externals/unicorn b/externals/unicorn new file mode 160000 | |||
| Subproject 73f45735354396766a4bfb26d0b96b06e5cf31b | |||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f5c92a5aa..20e41038b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -37,6 +37,8 @@ set(SRCS | |||
| 37 | hle/kernel/wait_object.cpp | 37 | hle/kernel/wait_object.cpp |
| 38 | hle/lock.cpp | 38 | hle/lock.cpp |
| 39 | hle/romfs.cpp | 39 | hle/romfs.cpp |
| 40 | hle/service/acc/acc.cpp | ||
| 41 | hle/service/acc/acc_u0.cpp | ||
| 40 | hle/service/am/am.cpp | 42 | hle/service/am/am.cpp |
| 41 | hle/service/am/applet_oe.cpp | 43 | hle/service/am/applet_oe.cpp |
| 42 | hle/service/aoc/aoc_u.cpp | 44 | hle/service/aoc/aoc_u.cpp |
| @@ -48,8 +50,8 @@ set(SRCS | |||
| 48 | hle/service/nvdrv/devices/nvdisp_disp0.cpp | 50 | hle/service/nvdrv/devices/nvdisp_disp0.cpp |
| 49 | hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 51 | hle/service/nvdrv/devices/nvhost_as_gpu.cpp |
| 50 | hle/service/nvdrv/devices/nvmap.cpp | 52 | hle/service/nvdrv/devices/nvmap.cpp |
| 53 | hle/service/nvdrv/interface.cpp | ||
| 51 | hle/service/nvdrv/nvdrv.cpp | 54 | hle/service/nvdrv/nvdrv.cpp |
| 52 | hle/service/nvdrv/nvdrv_a.cpp | ||
| 53 | hle/service/pctl/pctl.cpp | 55 | hle/service/pctl/pctl.cpp |
| 54 | hle/service/pctl/pctl_a.cpp | 56 | hle/service/pctl/pctl_a.cpp |
| 55 | hle/service/service.cpp | 57 | hle/service/service.cpp |
| @@ -124,6 +126,8 @@ set(HEADERS | |||
| 124 | hle/lock.h | 126 | hle/lock.h |
| 125 | hle/result.h | 127 | hle/result.h |
| 126 | hle/romfs.h | 128 | hle/romfs.h |
| 129 | hle/service/acc/acc.h | ||
| 130 | hle/service/acc/acc_u0.h | ||
| 127 | hle/service/am/am.h | 131 | hle/service/am/am.h |
| 128 | hle/service/am/applet_oe.h | 132 | hle/service/am/applet_oe.h |
| 129 | hle/service/aoc/aoc_u.h | 133 | hle/service/aoc/aoc_u.h |
| @@ -136,8 +140,8 @@ set(HEADERS | |||
| 136 | hle/service/nvdrv/devices/nvdisp_disp0.h | 140 | hle/service/nvdrv/devices/nvdisp_disp0.h |
| 137 | hle/service/nvdrv/devices/nvhost_as_gpu.h | 141 | hle/service/nvdrv/devices/nvhost_as_gpu.h |
| 138 | hle/service/nvdrv/devices/nvmap.h | 142 | hle/service/nvdrv/devices/nvmap.h |
| 143 | hle/service/nvdrv/interface.h | ||
| 139 | hle/service/nvdrv/nvdrv.h | 144 | hle/service/nvdrv/nvdrv.h |
| 140 | hle/service/nvdrv/nvdrv_a.h | ||
| 141 | hle/service/pctl/pctl.h | 145 | hle/service/pctl/pctl.h |
| 142 | hle/service/pctl/pctl_a.h | 146 | hle/service/pctl/pctl_a.h |
| 143 | hle/service/service.h | 147 | hle/service/service.h |
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 531875006..5ae60214e 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -39,7 +39,8 @@ public: | |||
| 39 | Run(1); | 39 | Run(1); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, Kernel::VMAPermission perms) {} | 42 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, |
| 43 | Kernel::VMAPermission perms) {} | ||
| 43 | 44 | ||
| 44 | /// Clear all instruction cache | 45 | /// Clear all instruction cache |
| 45 | virtual void ClearInstructionCache() = 0; | 46 | virtual void ClearInstructionCache() = 0; |
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 13f6c658c..fd64eab39 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "core/hle/kernel/svc.h" | 11 | #include "core/hle/kernel/svc.h" |
| 12 | 12 | ||
| 13 | // Load Unicorn DLL once on Windows using RAII | 13 | // Load Unicorn DLL once on Windows using RAII |
| 14 | #ifdef _WIN32 | 14 | #ifdef _MSC_VER |
| 15 | #include <unicorn_dynload.h> | 15 | #include <unicorn_dynload.h> |
| 16 | struct LoadDll { | 16 | struct LoadDll { |
| 17 | private: | 17 | private: |
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index ec08be0f4..88ba105e5 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -19,7 +19,6 @@ constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); | |||
| 19 | // TODO(yuriks): These will probably go away once translation is implemented inside the kernel. | 19 | // TODO(yuriks): These will probably go away once translation is implemented inside the kernel. |
| 20 | constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; | 20 | constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; |
| 21 | 21 | ||
| 22 | |||
| 23 | enum class ControlCommand : u32 { | 22 | enum class ControlCommand : u32 { |
| 24 | ConvertSessionToDomain = 0, | 23 | ConvertSessionToDomain = 0, |
| 25 | ConvertDomainToSession = 1, | 24 | ConvertDomainToSession = 1, |
| @@ -81,13 +80,13 @@ struct BufferDescriptorX { | |||
| 81 | u32_le address_bits_0_31; | 80 | u32_le address_bits_0_31; |
| 82 | 81 | ||
| 83 | u32_le Counter() const { | 82 | u32_le Counter() const { |
| 84 | u32_le counter{ counter_bits_0_5 }; | 83 | u32_le counter{counter_bits_0_5}; |
| 85 | counter |= counter_bits_9_11 << 9; | 84 | counter |= counter_bits_9_11 << 9; |
| 86 | return counter; | 85 | return counter; |
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | VAddr Address() const { | 88 | VAddr Address() const { |
| 90 | VAddr address{ address_bits_0_31 }; | 89 | VAddr address{address_bits_0_31}; |
| 91 | address |= static_cast<VAddr>(address_bits_32_35) << 32; | 90 | address |= static_cast<VAddr>(address_bits_32_35) << 32; |
| 92 | address |= static_cast<VAddr>(address_bits_36_38) << 36; | 91 | address |= static_cast<VAddr>(address_bits_36_38) << 36; |
| 93 | return address; | 92 | return address; |
| @@ -107,14 +106,14 @@ struct BufferDescriptorABW { | |||
| 107 | }; | 106 | }; |
| 108 | 107 | ||
| 109 | VAddr Address() const { | 108 | VAddr Address() const { |
| 110 | VAddr address{ address_bits_0_31 }; | 109 | VAddr address{address_bits_0_31}; |
| 111 | address |= static_cast<VAddr>(address_bits_32_35) << 32; | 110 | address |= static_cast<VAddr>(address_bits_32_35) << 32; |
| 112 | address |= static_cast<VAddr>(address_bits_36_38) << 36; | 111 | address |= static_cast<VAddr>(address_bits_36_38) << 36; |
| 113 | return address; | 112 | return address; |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | u64 Size() const { | 115 | u64 Size() const { |
| 117 | u64 size{ size_bits_0_31 }; | 116 | u64 size{size_bits_0_31}; |
| 118 | size |= static_cast<u64>(size_bits_32_35) << 32; | 117 | size |= static_cast<u64>(size_bits_32_35) << 32; |
| 119 | return size; | 118 | return size; |
| 120 | } | 119 | } |
| @@ -130,7 +129,7 @@ struct BufferDescriptorC { | |||
| 130 | }; | 129 | }; |
| 131 | 130 | ||
| 132 | VAddr Address() const { | 131 | VAddr Address() const { |
| 133 | VAddr address{ address_bits_0_31 }; | 132 | VAddr address{address_bits_0_31}; |
| 134 | address |= static_cast<VAddr>(address_bits_32_47) << 32; | 133 | address |= static_cast<VAddr>(address_bits_32_47) << 32; |
| 135 | return address; | 134 | return address; |
| 136 | } | 135 | } |
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 0f1077d9e..25530a3c8 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -9,10 +9,13 @@ | |||
| 9 | #include <type_traits> | 9 | #include <type_traits> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include "core/hle/ipc.h" | 11 | #include "core/hle/ipc.h" |
| 12 | #include "core/hle/kernel/client_port.h" | ||
| 13 | #include "core/hle/kernel/client_session.h" | ||
| 12 | #include "core/hle/kernel/domain.h" | 14 | #include "core/hle/kernel/domain.h" |
| 13 | #include "core/hle/kernel/handle_table.h" | 15 | #include "core/hle/kernel/handle_table.h" |
| 14 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 15 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 18 | #include "core/hle/kernel/server_port.h" | ||
| 16 | 19 | ||
| 17 | namespace IPC { | 20 | namespace IPC { |
| 18 | 21 | ||
| @@ -63,13 +66,20 @@ public: | |||
| 63 | : RequestHelperBase(context) { | 66 | : RequestHelperBase(context) { |
| 64 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | 67 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); |
| 65 | 68 | ||
| 69 | context.ClearIncomingObjects(); | ||
| 70 | |||
| 66 | IPC::CommandHeader header{}; | 71 | IPC::CommandHeader header{}; |
| 67 | 72 | ||
| 68 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | 73 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory |
| 69 | // padding. | 74 | // padding. |
| 70 | u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | 75 | u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; |
| 71 | if (context.IsDomain()) | 76 | if (context.IsDomain()) { |
| 72 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | 77 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; |
| 78 | } else { | ||
| 79 | // If we're not in a domain, turn the domain object parameters into move handles. | ||
| 80 | num_handles_to_move += num_domain_objects; | ||
| 81 | num_domain_objects = 0; | ||
| 82 | } | ||
| 73 | 83 | ||
| 74 | header.data_size.Assign(raw_data_size); | 84 | header.data_size.Assign(raw_data_size); |
| 75 | if (num_handles_to_copy || num_handles_to_move) { | 85 | if (num_handles_to_copy || num_handles_to_move) { |
| @@ -100,7 +110,15 @@ public: | |||
| 100 | 110 | ||
| 101 | template <class T, class... Args> | 111 | template <class T, class... Args> |
| 102 | void PushIpcInterface(Args&&... args) { | 112 | void PushIpcInterface(Args&&... args) { |
| 103 | context->AddDomainObject(std::make_shared<T>(std::forward<Args>(args)...)); | 113 | auto iface = std::make_shared<T>(std::forward<Args>(args)...); |
| 114 | if (context->IsDomain()) { | ||
| 115 | context->AddDomainObject(std::move(iface)); | ||
| 116 | } else { | ||
| 117 | auto port = iface->CreatePort(); | ||
| 118 | auto session = port->Connect(); | ||
| 119 | ASSERT(session.Succeeded()); | ||
| 120 | context->AddMoveObject(std::move(session).Unwrap()); | ||
| 121 | } | ||
| 104 | } | 122 | } |
| 105 | 123 | ||
| 106 | // Validate on destruction, as there shouldn't be any case where we don't want it | 124 | // Validate on destruction, as there shouldn't be any case where we don't want it |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 09caa43df..6dceb766d 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -151,13 +151,13 @@ public: | |||
| 151 | return domain != nullptr; | 151 | return domain != nullptr; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | template<typename T> | 154 | template <typename T> |
| 155 | SharedPtr<T> GetCopyObject(size_t index) { | 155 | SharedPtr<T> GetCopyObject(size_t index) { |
| 156 | ASSERT(index < copy_objects.size()); | 156 | ASSERT(index < copy_objects.size()); |
| 157 | return DynamicObjectCast<T>(copy_objects[index]); | 157 | return DynamicObjectCast<T>(copy_objects[index]); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | template<typename T> | 160 | template <typename T> |
| 161 | SharedPtr<T> GetMoveObject(size_t index) { | 161 | SharedPtr<T> GetMoveObject(size_t index) { |
| 162 | ASSERT(index < move_objects.size()); | 162 | ASSERT(index < move_objects.size()); |
| 163 | return DynamicObjectCast<T>(move_objects[index]); | 163 | return DynamicObjectCast<T>(move_objects[index]); |
| @@ -175,6 +175,14 @@ public: | |||
| 175 | domain_objects.emplace_back(std::move(object)); | 175 | domain_objects.emplace_back(std::move(object)); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | /// Clears the list of objects so that no lingering objects are written accidentally to the | ||
| 179 | /// response buffer. | ||
| 180 | void ClearIncomingObjects() { | ||
| 181 | move_objects.clear(); | ||
| 182 | copy_objects.clear(); | ||
| 183 | domain_objects.clear(); | ||
| 184 | } | ||
| 185 | |||
| 178 | private: | 186 | private: |
| 179 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | 187 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; |
| 180 | SharedPtr<Kernel::Domain> domain; | 188 | SharedPtr<Kernel::Domain> domain; |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index df3b4083e..4d9549e45 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -105,7 +105,6 @@ public: | |||
| 105 | UNREACHABLE(); | 105 | UNREACHABLE(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | |||
| 109 | public: | 108 | public: |
| 110 | static unsigned int next_object_id; | 109 | static unsigned int next_object_id; |
| 111 | 110 | ||
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index d990d0569..d2600cdd7 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -95,10 +95,8 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { | 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {} |
| 99 | } | ||
| 100 | 99 | ||
| 101 | void MapSharedPages(VMManager& address_space) { | 100 | void MapSharedPages(VMManager& address_space) {} |
| 102 | } | ||
| 103 | 101 | ||
| 104 | } // namespace Kernel | 102 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 49b6b454e..38db21005 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -41,9 +41,9 @@ public: | |||
| 41 | return HANDLE_TYPE; | 41 | return HANDLE_TYPE; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | u32 priority; ///< The priority of the mutex, used for priority inheritance. | 44 | u32 priority; ///< The priority of the mutex, used for priority inheritance. |
| 45 | std::string name; ///< Name of mutex (optional) | 45 | std::string name; ///< Name of mutex (optional) |
| 46 | VAddr guest_addr; ///< Address of the guest mutex value | 46 | VAddr guest_addr; ///< Address of the guest mutex value |
| 47 | 47 | ||
| 48 | /** | 48 | /** |
| 49 | * Elevate the mutex priority to the best priority | 49 | * Elevate the mutex priority to the best priority |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 20b4e401c..add98472f 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -131,6 +131,8 @@ public: | |||
| 131 | /// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse | 131 | /// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse |
| 132 | /// this value from the process header. | 132 | /// this value from the process header. |
| 133 | u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK; | 133 | u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK; |
| 134 | u32 allowed_thread_priority_mask = 0xFFFFFFFF; | ||
| 135 | u32 is_virtual_address_memory_enabled = 0; | ||
| 134 | /// Current status of the process | 136 | /// Current status of the process |
| 135 | ProcessStatus status; | 137 | ProcessStatus status; |
| 136 | 138 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9c60576c1..088058ebc 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -305,14 +305,27 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 305 | LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, | 305 | LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, |
| 306 | info_sub_id, handle); | 306 | info_sub_id, handle); |
| 307 | 307 | ||
| 308 | ASSERT(handle == 0 || handle == CurrentProcess); | ||
| 309 | |||
| 310 | auto& vm_manager = g_current_process->vm_manager; | 308 | auto& vm_manager = g_current_process->vm_manager; |
| 311 | 309 | ||
| 312 | switch (static_cast<GetInfoType>(info_id)) { | 310 | switch (static_cast<GetInfoType>(info_id)) { |
| 313 | case GetInfoType::AllowedCpuIdBitmask: | 311 | case GetInfoType::AllowedCpuIdBitmask: |
| 314 | *result = g_current_process->allowed_processor_mask; | 312 | *result = g_current_process->allowed_processor_mask; |
| 315 | break; | 313 | break; |
| 314 | case GetInfoType::AllowedThreadPrioBitmask: | ||
| 315 | *result = g_current_process->allowed_thread_priority_mask; | ||
| 316 | break; | ||
| 317 | case GetInfoType::MapRegionBaseAddr: | ||
| 318 | *result = vm_manager.GetAddressSpaceBaseAddr(); | ||
| 319 | break; | ||
| 320 | case GetInfoType::MapRegionSize: | ||
| 321 | *result = vm_manager.GetAddressSpaceSize(); | ||
| 322 | break; | ||
| 323 | case GetInfoType::HeapRegionBaseAddr: | ||
| 324 | *result = vm_manager.GetNewMapRegionBaseAddr() + vm_manager.GetNewMapRegionSize(); | ||
| 325 | break; | ||
| 326 | case GetInfoType::HeapRegionSize: | ||
| 327 | *result = Memory::HEAP_SIZE; | ||
| 328 | break; | ||
| 316 | case GetInfoType::TotalMemoryUsage: | 329 | case GetInfoType::TotalMemoryUsage: |
| 317 | *result = vm_manager.GetTotalMemoryUsage(); | 330 | *result = vm_manager.GetTotalMemoryUsage(); |
| 318 | break; | 331 | break; |
| @@ -334,6 +347,18 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 334 | case GetInfoType::NewMapRegionSize: | 347 | case GetInfoType::NewMapRegionSize: |
| 335 | *result = vm_manager.GetNewMapRegionSize(); | 348 | *result = vm_manager.GetNewMapRegionSize(); |
| 336 | break; | 349 | break; |
| 350 | case GetInfoType::IsVirtualAddressMemoryEnabled: | ||
| 351 | *result = g_current_process->is_virtual_address_memory_enabled; | ||
| 352 | break; | ||
| 353 | case GetInfoType::TitleId: | ||
| 354 | LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); | ||
| 355 | *result = 0; | ||
| 356 | break; | ||
| 357 | case GetInfoType::PrivilegedProcessId: | ||
| 358 | LOG_WARNING(Kernel_SVC, | ||
| 359 | "(STUBBED) Attempted to query priviledged process id bounds, returned 0"); | ||
| 360 | *result = 0; | ||
| 361 | break; | ||
| 337 | default: | 362 | default: |
| 338 | UNIMPLEMENTED(); | 363 | UNIMPLEMENTED(); |
| 339 | } | 364 | } |
| @@ -709,6 +734,11 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 | |||
| 709 | return RESULT_SUCCESS; | 734 | return RESULT_SUCCESS; |
| 710 | } | 735 | } |
| 711 | 736 | ||
| 737 | static ResultCode SetThreadCoreMask(u64, u64, u64) { | ||
| 738 | LOG_WARNING(Kernel_SVC, "(STUBBED) called"); | ||
| 739 | return RESULT_SUCCESS; | ||
| 740 | } | ||
| 741 | |||
| 712 | namespace { | 742 | namespace { |
| 713 | struct FunctionDef { | 743 | struct FunctionDef { |
| 714 | using Func = void(); | 744 | using Func = void(); |
| @@ -735,7 +765,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 735 | {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, | 765 | {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, |
| 736 | {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, | 766 | {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, |
| 737 | {0x0E, nullptr, "GetThreadCoreMask"}, | 767 | {0x0E, nullptr, "GetThreadCoreMask"}, |
| 738 | {0x0F, nullptr, "SetThreadCoreMask"}, | 768 | {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, |
| 739 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, | 769 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, |
| 740 | {0x11, nullptr, "SignalEvent"}, | 770 | {0x11, nullptr, "SignalEvent"}, |
| 741 | {0x12, nullptr, "ClearEvent"}, | 771 | {0x12, nullptr, "ClearEvent"}, |
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index 610cd1d7d..42cc41da3 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h | |||
| @@ -24,14 +24,28 @@ struct PageInfo { | |||
| 24 | enum class GetInfoType : u64 { | 24 | enum class GetInfoType : u64 { |
| 25 | // 1.0.0+ | 25 | // 1.0.0+ |
| 26 | AllowedCpuIdBitmask = 0, | 26 | AllowedCpuIdBitmask = 0, |
| 27 | AllowedThreadPrioBitmask = 1, | ||
| 28 | MapRegionBaseAddr = 2, | ||
| 29 | MapRegionSize = 3, | ||
| 30 | HeapRegionBaseAddr = 4, | ||
| 31 | HeapRegionSize = 5, | ||
| 27 | TotalMemoryUsage = 6, | 32 | TotalMemoryUsage = 6, |
| 28 | TotalHeapUsage = 7, | 33 | TotalHeapUsage = 7, |
| 34 | IsCurrentProcessBeingDebugged = 8, | ||
| 35 | ResourceHandleLimit = 9, | ||
| 36 | IdleTickCount = 10, | ||
| 29 | RandomEntropy = 11, | 37 | RandomEntropy = 11, |
| 38 | PerformanceCounter = 0xF0000002, | ||
| 30 | // 2.0.0+ | 39 | // 2.0.0+ |
| 31 | AddressSpaceBaseAddr = 12, | 40 | AddressSpaceBaseAddr = 12, |
| 32 | AddressSpaceSize = 13, | 41 | AddressSpaceSize = 13, |
| 33 | NewMapRegionBaseAddr = 14, | 42 | NewMapRegionBaseAddr = 14, |
| 34 | NewMapRegionSize = 15, | 43 | NewMapRegionSize = 15, |
| 44 | // 3.0.0+ | ||
| 45 | IsVirtualAddressMemoryEnabled = 16, | ||
| 46 | TitleId = 18, | ||
| 47 | // 4.0.0+ | ||
| 48 | PrivilegedProcessId = 19, | ||
| 35 | }; | 49 | }; |
| 36 | 50 | ||
| 37 | void CallSVC(u32 immediate); | 51 | void CallSVC(u32 immediate); |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index dca637dde..bf261699e 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/arm/arm_interface.h" | 8 | #include "core/arm/arm_interface.h" |
| 9 | #include "core/core.h" | ||
| 9 | #include "core/hle/kernel/errors.h" | 10 | #include "core/hle/kernel/errors.h" |
| 10 | #include "core/hle/kernel/vm_manager.h" | 11 | #include "core/hle/kernel/vm_manager.h" |
| 11 | #include "core/core.h" | ||
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | #include "core/memory_setup.h" | 13 | #include "core/memory_setup.h" |
| 14 | #include "core/mmio.h" | 14 | #include "core/mmio.h" |
| @@ -86,7 +86,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | |||
| 86 | VirtualMemoryArea& final_vma = vma_handle->second; | 86 | VirtualMemoryArea& final_vma = vma_handle->second; |
| 87 | ASSERT(final_vma.size == size); | 87 | ASSERT(final_vma.size == size); |
| 88 | 88 | ||
| 89 | Core::CPU().MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute); | 89 | Core::CPU().MapBackingMemory(target, size, block->data() + offset, |
| 90 | VMAPermission::ReadWriteExecute); | ||
| 90 | 91 | ||
| 91 | final_vma.type = VMAType::AllocatedMemoryBlock; | 92 | final_vma.type = VMAType::AllocatedMemoryBlock; |
| 92 | final_vma.permissions = VMAPermission::ReadWrite; | 93 | final_vma.permissions = VMAPermission::ReadWrite; |
| @@ -356,12 +357,12 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 356 | 357 | ||
| 357 | u64 VMManager::GetTotalMemoryUsage() { | 358 | u64 VMManager::GetTotalMemoryUsage() { |
| 358 | LOG_WARNING(Kernel, "(STUBBED) called"); | 359 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 359 | return 0x400000; | 360 | return 0xBE000000; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | u64 VMManager::GetTotalHeapUsage() { | 363 | u64 VMManager::GetTotalHeapUsage() { |
| 363 | LOG_WARNING(Kernel, "(STUBBED) called"); | 364 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 364 | return 0x10000; | 365 | return 0x0; |
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | VAddr VMManager::GetAddressSpaceBaseAddr() { | 368 | VAddr VMManager::GetAddressSpaceBaseAddr() { |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp new file mode 100644 index 000000000..5716577d6 --- /dev/null +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/acc/acc.h" | ||
| 6 | #include "core/hle/service/acc/acc_u0.h" | ||
| 7 | |||
| 8 | namespace Service { | ||
| 9 | namespace Account { | ||
| 10 | |||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||
| 12 | std::make_shared<ACC_U0>()->InstallAsService(service_manager); | ||
| 13 | } | ||
| 14 | |||
| 15 | } // namespace Account | ||
| 16 | } // namespace Service | ||
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h new file mode 100644 index 000000000..44d024f48 --- /dev/null +++ b/src/core/hle/service/acc/acc.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | namespace Account { | ||
| 11 | |||
| 12 | /// Registers all ACC services with the specified service manager. | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | ||
| 14 | |||
| 15 | } // namespace Account | ||
| 16 | } // namespace Service | ||
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp new file mode 100644 index 000000000..147f4e62e --- /dev/null +++ b/src/core/hle/service/acc/acc_u0.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 7 | #include "core/hle/service/acc/acc_u0.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | namespace Account { | ||
| 11 | |||
| 12 | void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { | ||
| 13 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 14 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 15 | rb.Push(RESULT_SUCCESS); | ||
| 16 | } | ||
| 17 | |||
| 18 | ACC_U0::ACC_U0() : ServiceFramework("acc:u0") { | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, | ||
| 21 | }; | ||
| 22 | RegisterHandlers(functions); | ||
| 23 | } | ||
| 24 | |||
| 25 | } // namespace Account | ||
| 26 | } // namespace Service | ||
diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h new file mode 100644 index 000000000..ac243d5b8 --- /dev/null +++ b/src/core/hle/service/acc/acc_u0.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | namespace Account { | ||
| 11 | |||
| 12 | class ACC_U0 final : public ServiceFramework<ACC_U0> { | ||
| 13 | public: | ||
| 14 | ACC_U0(); | ||
| 15 | ~ACC_U0() = default; | ||
| 16 | |||
| 17 | private: | ||
| 18 | void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Account | ||
| 22 | } // namespace Service | ||
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index f65d6b9f5..b360e7e5f 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/event.h" | 7 | #include "core/hle/kernel/event.h" |
| 8 | #include "core/hle/service/am/applet_oe.h" | 8 | #include "core/hle/service/am/applet_oe.h" |
| 9 | #include "core/hle/service/apm/apm.h" | ||
| 9 | 10 | ||
| 10 | namespace Service { | 11 | namespace Service { |
| 11 | namespace AM { | 12 | namespace AM { |
| @@ -54,7 +55,14 @@ class ISelfController final : public ServiceFramework<ISelfController> { | |||
| 54 | public: | 55 | public: |
| 55 | ISelfController() : ServiceFramework("ISelfController") { | 56 | ISelfController() : ServiceFramework("ISelfController") { |
| 56 | static const FunctionInfo functions[] = { | 57 | static const FunctionInfo functions[] = { |
| 58 | {11, &ISelfController::SetOperationModeChangedNotification, | ||
| 59 | "SetOperationModeChangedNotification"}, | ||
| 60 | {12, &ISelfController::SetPerformanceModeChangedNotification, | ||
| 61 | "SetPerformanceModeChangedNotification"}, | ||
| 57 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | 62 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, |
| 63 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 64 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, | ||
| 65 | "SetOutOfFocusSuspendingEnabled"}, | ||
| 58 | }; | 66 | }; |
| 59 | RegisterHandlers(functions); | 67 | RegisterHandlers(functions); |
| 60 | } | 68 | } |
| @@ -64,11 +72,62 @@ private: | |||
| 64 | // Takes 3 input u8s with each field located immediately after the previous u8, these are | 72 | // Takes 3 input u8s with each field located immediately after the previous u8, these are |
| 65 | // bool flags. No output. | 73 | // bool flags. No output. |
| 66 | 74 | ||
| 75 | IPC::RequestParser rp{ctx}; | ||
| 76 | |||
| 77 | struct FocusHandlingModeParams { | ||
| 78 | u8 unknown0; | ||
| 79 | u8 unknown1; | ||
| 80 | u8 unknown2; | ||
| 81 | }; | ||
| 82 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 83 | |||
| 84 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(RESULT_SUCCESS); | ||
| 86 | |||
| 87 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 88 | } | ||
| 89 | |||
| 90 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { | ||
| 67 | IPC::RequestBuilder rb{ctx, 2}; | 91 | IPC::RequestBuilder rb{ctx, 2}; |
| 68 | rb.Push(RESULT_SUCCESS); | 92 | rb.Push(RESULT_SUCCESS); |
| 69 | 93 | ||
| 70 | LOG_WARNING(Service, "(STUBBED) called"); | 94 | LOG_WARNING(Service, "(STUBBED) called"); |
| 71 | } | 95 | } |
| 96 | |||
| 97 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||
| 98 | IPC::RequestParser rp{ctx}; | ||
| 99 | |||
| 100 | bool flag = rp.Pop<bool>(); | ||
| 101 | |||
| 102 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 103 | rb.Push(RESULT_SUCCESS); | ||
| 104 | |||
| 105 | LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||
| 106 | } | ||
| 107 | |||
| 108 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||
| 109 | IPC::RequestParser rp{ctx}; | ||
| 110 | |||
| 111 | bool flag = rp.Pop<bool>(); | ||
| 112 | |||
| 113 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 114 | rb.Push(RESULT_SUCCESS); | ||
| 115 | |||
| 116 | LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||
| 117 | } | ||
| 118 | |||
| 119 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { | ||
| 120 | // Takes 3 input u8s with each field located immediately after the previous u8, these are | ||
| 121 | // bool flags. No output. | ||
| 122 | IPC::RequestParser rp{ctx}; | ||
| 123 | |||
| 124 | bool enabled = rp.Pop<bool>(); | ||
| 125 | |||
| 126 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(RESULT_SUCCESS); | ||
| 128 | |||
| 129 | LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); | ||
| 130 | } | ||
| 72 | }; | 131 | }; |
| 73 | 132 | ||
| 74 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 133 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
| @@ -77,6 +136,8 @@ public: | |||
| 77 | static const FunctionInfo functions[] = { | 136 | static const FunctionInfo functions[] = { |
| 78 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | 137 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, |
| 79 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | 138 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, |
| 139 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 140 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 80 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | 141 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, |
| 81 | }; | 142 | }; |
| 82 | RegisterHandlers(functions); | 143 | RegisterHandlers(functions); |
| @@ -85,6 +146,16 @@ public: | |||
| 85 | } | 146 | } |
| 86 | 147 | ||
| 87 | private: | 148 | private: |
| 149 | enum class FocusState : u8 { | ||
| 150 | InFocus = 1, | ||
| 151 | NotInFocus = 2, | ||
| 152 | }; | ||
| 153 | |||
| 154 | enum class OperationMode : u8 { | ||
| 155 | Handheld = 0, | ||
| 156 | Docked = 1, | ||
| 157 | }; | ||
| 158 | |||
| 88 | void GetEventHandle(Kernel::HLERequestContext& ctx) { | 159 | void GetEventHandle(Kernel::HLERequestContext& ctx) { |
| 89 | event->Signal(); | 160 | event->Signal(); |
| 90 | 161 | ||
| @@ -106,7 +177,23 @@ private: | |||
| 106 | void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { | 177 | void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { |
| 107 | IPC::RequestBuilder rb{ctx, 3}; | 178 | IPC::RequestBuilder rb{ctx, 3}; |
| 108 | rb.Push(RESULT_SUCCESS); | 179 | rb.Push(RESULT_SUCCESS); |
| 109 | rb.Push<u32>(1); // 1: In focus, 2/3: Out of focus(running in "background") | 180 | rb.Push(static_cast<u8>(FocusState::InFocus)); |
| 181 | |||
| 182 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 183 | } | ||
| 184 | |||
| 185 | void GetOperationMode(Kernel::HLERequestContext& ctx) { | ||
| 186 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 187 | rb.Push(RESULT_SUCCESS); | ||
| 188 | rb.Push(static_cast<u8>(OperationMode::Handheld)); | ||
| 189 | |||
| 190 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 191 | } | ||
| 192 | |||
| 193 | void GetPerformanceMode(Kernel::HLERequestContext& ctx) { | ||
| 194 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 195 | rb.Push(RESULT_SUCCESS); | ||
| 196 | rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld)); | ||
| 110 | 197 | ||
| 111 | LOG_WARNING(Service, "(STUBBED) called"); | 198 | LOG_WARNING(Service, "(STUBBED) called"); |
| 112 | } | 199 | } |
| @@ -119,6 +206,10 @@ public: | |||
| 119 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { | 206 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { |
| 120 | static const FunctionInfo functions[] = { | 207 | static const FunctionInfo functions[] = { |
| 121 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | 208 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, |
| 209 | {66, &IApplicationFunctions::InitializeGamePlayRecording, | ||
| 210 | "InitializeGamePlayRecording"}, | ||
| 211 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 212 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 122 | }; | 213 | }; |
| 123 | RegisterHandlers(functions); | 214 | RegisterHandlers(functions); |
| 124 | } | 215 | } |
| @@ -136,6 +227,27 @@ private: | |||
| 136 | 227 | ||
| 137 | LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); | 228 | LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); |
| 138 | } | 229 | } |
| 230 | |||
| 231 | void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { | ||
| 232 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 233 | rb.Push(RESULT_SUCCESS); | ||
| 234 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 235 | } | ||
| 236 | |||
| 237 | void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { | ||
| 238 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 239 | rb.Push(RESULT_SUCCESS); | ||
| 240 | |||
| 241 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 242 | } | ||
| 243 | |||
| 244 | void NotifyRunning(Kernel::HLERequestContext& ctx) { | ||
| 245 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 246 | rb.Push(RESULT_SUCCESS); | ||
| 247 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 248 | |||
| 249 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 250 | } | ||
| 139 | }; | 251 | }; |
| 140 | 252 | ||
| 141 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | 253 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { |
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index f70b9fc10..66d94ff52 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp | |||
| @@ -13,13 +13,54 @@ void InstallInterfaces(SM::ServiceManager& service_manager) { | |||
| 13 | std::make_shared<APM>()->InstallAsService(service_manager); | 13 | std::make_shared<APM>()->InstallAsService(service_manager); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | class ISession final : public ServiceFramework<ISession> { | ||
| 17 | public: | ||
| 18 | ISession() : ServiceFramework("ISession") { | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, | ||
| 21 | {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, | ||
| 22 | }; | ||
| 23 | RegisterHandlers(functions); | ||
| 24 | } | ||
| 25 | |||
| 26 | private: | ||
| 27 | void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||
| 28 | IPC::RequestParser rp{ctx}; | ||
| 29 | |||
| 30 | auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||
| 31 | u32 config = rp.Pop<u32>(); | ||
| 32 | |||
| 33 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 34 | rb.Push(RESULT_SUCCESS); | ||
| 35 | |||
| 36 | LOG_WARNING(Service, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), config); | ||
| 37 | } | ||
| 38 | |||
| 39 | void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||
| 40 | IPC::RequestParser rp{ctx}; | ||
| 41 | |||
| 42 | auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||
| 43 | |||
| 44 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 45 | rb.Push(RESULT_SUCCESS); | ||
| 46 | rb.Push<u32>(0); // Performance configuration | ||
| 47 | |||
| 48 | LOG_WARNING(Service, "(STUBBED) called mode=%u", static_cast<u32>(mode)); | ||
| 49 | } | ||
| 50 | }; | ||
| 51 | |||
| 16 | APM::APM() : ServiceFramework("apm") { | 52 | APM::APM() : ServiceFramework("apm") { |
| 17 | static const FunctionInfo functions[] = { | 53 | static const FunctionInfo functions[] = { |
| 18 | {0x00000000, nullptr, "OpenSession"}, | 54 | {0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"}, |
| 19 | {0x00000001, nullptr, "GetPerformanceMode"}, | ||
| 20 | }; | 55 | }; |
| 21 | RegisterHandlers(functions); | 56 | RegisterHandlers(functions); |
| 22 | } | 57 | } |
| 23 | 58 | ||
| 59 | void APM::OpenSession(Kernel::HLERequestContext& ctx) { | ||
| 60 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 61 | rb.Push(RESULT_SUCCESS); | ||
| 62 | rb.PushIpcInterface<ISession>(); | ||
| 63 | } | ||
| 64 | |||
| 24 | } // namespace APM | 65 | } // namespace APM |
| 25 | } // namespace Service | 66 | } // namespace Service |
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h index 377db71a4..90a1afbbc 100644 --- a/src/core/hle/service/apm/apm.h +++ b/src/core/hle/service/apm/apm.h | |||
| @@ -9,10 +9,18 @@ | |||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | namespace APM { | 10 | namespace APM { |
| 11 | 11 | ||
| 12 | enum class PerformanceMode : u8 { | ||
| 13 | Handheld = 0, | ||
| 14 | Docked = 1, | ||
| 15 | }; | ||
| 16 | |||
| 12 | class APM final : public ServiceFramework<APM> { | 17 | class APM final : public ServiceFramework<APM> { |
| 13 | public: | 18 | public: |
| 14 | APM(); | 19 | APM(); |
| 15 | ~APM() = default; | 20 | ~APM() = default; |
| 21 | |||
| 22 | private: | ||
| 23 | void OpenSession(Kernel::HLERequestContext& ctx); | ||
| 16 | }; | 24 | }; |
| 17 | 25 | ||
| 18 | /// Registers all AM services with the specified service manager. | 26 | /// Registers all AM services with the specified service manager. |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 1ee2787c6..5ee33b3d6 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | namespace Service { | 10 | namespace Service { |
| 11 | namespace NVDRV { | 11 | namespace Nvidia { |
| 12 | namespace Devices { | 12 | namespace Devices { |
| 13 | 13 | ||
| 14 | /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to | 14 | /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to |
| @@ -29,5 +29,5 @@ public: | |||
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | } // namespace Devices | 31 | } // namespace Devices |
| 32 | } // namespace NVDRV | 32 | } // namespace Nvidia |
| 33 | } // namespace Service | 33 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 992f70b45..c42a65b36 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "video_core/video_core.h" | 10 | #include "video_core/video_core.h" |
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace NVDRV { | 13 | namespace Nvidia { |
| 14 | namespace Devices { | 14 | namespace Devices { |
| 15 | 15 | ||
| 16 | u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | 16 | u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { |
| @@ -32,5 +32,5 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | } // namespace Devices | 34 | } // namespace Devices |
| 35 | } // namespace NVDRV | 35 | } // namespace Nvidia |
| 36 | } // namespace Service | 36 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 601068af1..f5f9de3f4 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace NVDRV { | 13 | namespace Nvidia { |
| 14 | namespace Devices { | 14 | namespace Devices { |
| 15 | 15 | ||
| 16 | class nvmap; | 16 | class nvmap; |
| @@ -30,5 +30,5 @@ private: | |||
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | } // namespace Devices | 32 | } // namespace Devices |
| 33 | } // namespace NVDRV | 33 | } // namespace Nvidia |
| 34 | } // namespace Service | 34 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index c7bf79050..9db08339a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | 7 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" |
| 8 | 8 | ||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | namespace NVDRV { | 10 | namespace Nvidia { |
| 11 | namespace Devices { | 11 | namespace Devices { |
| 12 | 12 | ||
| 13 | u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | 13 | u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { |
| @@ -16,5 +16,5 @@ u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector< | |||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | } // namespace Devices | 18 | } // namespace Devices |
| 19 | } // namespace NVDRV | 19 | } // namespace Nvidia |
| 20 | } // namespace Service | 20 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 6f441b020..01f8861c8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace NVDRV { | 12 | namespace Nvidia { |
| 13 | namespace Devices { | 13 | namespace Devices { |
| 14 | 14 | ||
| 15 | class nvhost_as_gpu final : public nvdevice { | 15 | class nvhost_as_gpu final : public nvdevice { |
| @@ -21,5 +21,5 @@ public: | |||
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | } // namespace Devices | 23 | } // namespace Devices |
| 24 | } // namespace NVDRV | 24 | } // namespace Nvidia |
| 25 | } // namespace Service | 25 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 2d6f30e3e..d37b5b159 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace NVDRV { | 12 | namespace Nvidia { |
| 13 | namespace Devices { | 13 | namespace Devices { |
| 14 | 14 | ||
| 15 | VAddr nvmap::GetObjectAddress(u32 handle) const { | 15 | VAddr nvmap::GetObjectAddress(u32 handle) const { |
| @@ -151,5 +151,5 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | } // namespace Devices | 153 | } // namespace Devices |
| 154 | } // namespace NVDRV | 154 | } // namespace Nvidia |
| 155 | } // namespace Service | 155 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index e74f356e5..6954c0324 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 13 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 14 | 14 | ||
| 15 | namespace Service { | 15 | namespace Service { |
| 16 | namespace NVDRV { | 16 | namespace Nvidia { |
| 17 | namespace Devices { | 17 | namespace Devices { |
| 18 | 18 | ||
| 19 | class nvmap final : public nvdevice { | 19 | class nvmap final : public nvdevice { |
| @@ -104,5 +104,5 @@ private: | |||
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | } // namespace Devices | 106 | } // namespace Devices |
| 107 | } // namespace NVDRV | 107 | } // namespace Nvidia |
| 108 | } // namespace Service | 108 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.cpp b/src/core/hle/service/nvdrv/interface.cpp index 84d89cb49..0670ca155 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -4,35 +4,27 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 7 | #include "core/hle/service/nvdrv/interface.h" |
| 8 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 11 | #include "core/hle/service/nvdrv/nvdrv.h" | 8 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 12 | #include "core/hle/service/nvdrv/nvdrv_a.h" | ||
| 13 | 9 | ||
| 14 | namespace Service { | 10 | namespace Service { |
| 15 | namespace NVDRV { | 11 | namespace Nvidia { |
| 16 | 12 | ||
| 17 | void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { | 13 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { |
| 18 | LOG_WARNING(Service, "(STUBBED) called"); | 14 | LOG_WARNING(Service, "(STUBBED) called"); |
| 19 | 15 | ||
| 20 | auto buffer = ctx.BufferDescriptorA()[0]; | 16 | auto buffer = ctx.BufferDescriptorA()[0]; |
| 21 | 17 | ||
| 22 | std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); | 18 | std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); |
| 23 | 19 | ||
| 24 | auto device = devices[device_name]; | 20 | u32 fd = nvdrv->Open(device_name); |
| 25 | u32 fd = next_fd++; | ||
| 26 | |||
| 27 | open_files[fd] = device; | ||
| 28 | |||
| 29 | IPC::RequestBuilder rb{ctx, 4}; | 21 | IPC::RequestBuilder rb{ctx, 4}; |
| 30 | rb.Push(RESULT_SUCCESS); | 22 | rb.Push(RESULT_SUCCESS); |
| 31 | rb.Push<u32>(fd); | 23 | rb.Push<u32>(fd); |
| 32 | rb.Push<u32>(0); | 24 | rb.Push<u32>(0); |
| 33 | } | 25 | } |
| 34 | 26 | ||
| 35 | void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | 27 | void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { |
| 36 | LOG_WARNING(Service, "(STUBBED) called"); | 28 | LOG_WARNING(Service, "(STUBBED) called"); |
| 37 | 29 | ||
| 38 | IPC::RequestParser rp{ctx}; | 30 | IPC::RequestParser rp{ctx}; |
| @@ -46,11 +38,8 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | |||
| 46 | std::vector<u8> output(output_buffer.Size()); | 38 | std::vector<u8> output(output_buffer.Size()); |
| 47 | 39 | ||
| 48 | Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); | 40 | Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); |
| 49 | auto itr = open_files.find(fd); | ||
| 50 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||
| 51 | 41 | ||
| 52 | auto device = itr->second; | 42 | u32 nv_result = nvdrv->Ioctl(fd, command, input, output); |
| 53 | u32 nv_result = device->ioctl(command, input, output); | ||
| 54 | 43 | ||
| 55 | Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); | 44 | Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); |
| 56 | 45 | ||
| @@ -59,26 +48,22 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | |||
| 59 | rb.Push(nv_result); | 48 | rb.Push(nv_result); |
| 60 | } | 49 | } |
| 61 | 50 | ||
| 62 | void NVDRV_A::Initialize(Kernel::HLERequestContext& ctx) { | 51 | void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { |
| 63 | LOG_WARNING(Service, "(STUBBED) called"); | 52 | LOG_WARNING(Service, "(STUBBED) called"); |
| 64 | IPC::RequestBuilder rb{ctx, 3}; | 53 | IPC::RequestBuilder rb{ctx, 3}; |
| 65 | rb.Push(RESULT_SUCCESS); | 54 | rb.Push(RESULT_SUCCESS); |
| 66 | rb.Push<u32>(0); | 55 | rb.Push<u32>(0); |
| 67 | } | 56 | } |
| 68 | 57 | ||
| 69 | NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { | 58 | NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) |
| 59 | : ServiceFramework(name), nvdrv(std::move(nvdrv)) { | ||
| 70 | static const FunctionInfo functions[] = { | 60 | static const FunctionInfo functions[] = { |
| 71 | {0, &NVDRV_A::Open, "Open"}, | 61 | {0, &NVDRV::Open, "Open"}, |
| 72 | {1, &NVDRV_A::Ioctl, "Ioctl"}, | 62 | {1, &NVDRV::Ioctl, "Ioctl"}, |
| 73 | {3, &NVDRV_A::Initialize, "Initialize"}, | 63 | {3, &NVDRV::Initialize, "Initialize"}, |
| 74 | }; | 64 | }; |
| 75 | RegisterHandlers(functions); | 65 | RegisterHandlers(functions); |
| 76 | |||
| 77 | auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||
| 78 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||
| 79 | devices["/dev/nvmap"] = nvmap_dev; | ||
| 80 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||
| 81 | } | 66 | } |
| 82 | 67 | ||
| 83 | } // namespace NVDRV | 68 | } // namespace Nvidia |
| 84 | } // namespace Service | 69 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h new file mode 100644 index 000000000..8c95b7217 --- /dev/null +++ b/src/core/hle/service/nvdrv/interface.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace Nvidia { | ||
| 14 | |||
| 15 | class NVDRV final : public ServiceFramework<NVDRV> { | ||
| 16 | public: | ||
| 17 | NVDRV(std::shared_ptr<Module> nvdrv, const char* name); | ||
| 18 | ~NVDRV() = default; | ||
| 19 | |||
| 20 | private: | ||
| 21 | void Open(Kernel::HLERequestContext& ctx); | ||
| 22 | void Ioctl(Kernel::HLERequestContext& ctx); | ||
| 23 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 24 | |||
| 25 | std::shared_ptr<Module> nvdrv; | ||
| 26 | }; | ||
| 27 | |||
| 28 | } // namespace Nvidia | ||
| 29 | } // namespace Service | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index c874e6395..cf525a875 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -2,19 +2,52 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/ipc_helpers.h" | ||
| 6 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 7 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||
| 8 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 5 | #include "core/hle/service/nvdrv/nvdrv.h" | 10 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 6 | #include "core/hle/service/nvdrv/nvdrv_a.h" | 11 | #include "core/hle/service/nvdrv/interface.h" |
| 7 | 12 | ||
| 8 | namespace Service { | 13 | namespace Service { |
| 9 | namespace NVDRV { | 14 | namespace Nvidia { |
| 10 | 15 | ||
| 11 | std::weak_ptr<NVDRV_A> nvdrv_a; | 16 | std::weak_ptr<Module> nvdrv; |
| 12 | 17 | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 18 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
| 14 | auto nvdrv = std::make_shared<NVDRV_A>(); | 19 | auto module_ = std::make_shared<Module>(); |
| 15 | nvdrv->InstallAsService(service_manager); | 20 | std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager); |
| 16 | nvdrv_a = nvdrv; | 21 | std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager); |
| 22 | nvdrv = module_; | ||
| 17 | } | 23 | } |
| 18 | 24 | ||
| 19 | } // namespace NVDRV | 25 | Module::Module() { |
| 26 | auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||
| 27 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||
| 28 | devices["/dev/nvmap"] = nvmap_dev; | ||
| 29 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||
| 30 | } | ||
| 31 | |||
| 32 | u32 Module::Open(std::string device_name) { | ||
| 33 | ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device %s", | ||
| 34 | device_name.c_str()); | ||
| 35 | |||
| 36 | auto device = devices[device_name]; | ||
| 37 | u32 fd = next_fd++; | ||
| 38 | |||
| 39 | open_files[fd] = device; | ||
| 40 | |||
| 41 | return fd; | ||
| 42 | } | ||
| 43 | |||
| 44 | u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 45 | auto itr = open_files.find(fd); | ||
| 46 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||
| 47 | |||
| 48 | auto device = itr->second; | ||
| 49 | return device->ioctl(command, input, output); | ||
| 50 | } | ||
| 51 | |||
| 52 | } // namespace Nvidia | ||
| 20 | } // namespace Service | 53 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 7530d80ad..1940ced99 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -11,109 +11,46 @@ | |||
| 11 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service { |
| 14 | namespace NVDRV { | 14 | namespace Nvidia { |
| 15 | 15 | ||
| 16 | class nvdevice { | 16 | namespace Devices { |
| 17 | public: | 17 | class nvdevice; |
| 18 | virtual ~nvdevice() = default; | 18 | } |
| 19 | |||
| 20 | virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; | ||
| 21 | }; | ||
| 22 | 19 | ||
| 23 | class nvmap : public nvdevice { | 20 | class Module final { |
| 24 | public: | 21 | public: |
| 25 | /// Returns the allocated address of an nvmap object given its handle. | 22 | Module(); |
| 26 | VAddr GetObjectAddress(u32 handle) const; | 23 | ~Module() = default; |
| 24 | |||
| 25 | /// Returns a pointer to one of the available devices, identified by its name. | ||
| 26 | template <typename T> | ||
| 27 | std::shared_ptr<T> GetDevice(std::string name) { | ||
| 28 | auto itr = devices.find(name); | ||
| 29 | if (itr == devices.end()) | ||
| 30 | return nullptr; | ||
| 31 | return std::static_pointer_cast<T>(itr->second); | ||
| 32 | } | ||
| 33 | |||
| 34 | /// Opens a device node and returns a file descriptor to it. | ||
| 35 | u32 Open(std::string device_name); | ||
| 36 | /// Sends an ioctl command to the specified file descriptor. | ||
| 37 | u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output); | ||
| 27 | 38 | ||
| 28 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 29 | private: | 39 | private: |
| 30 | // Represents an nvmap object. | 40 | /// Id to use for the next open file descriptor. |
| 31 | struct Object { | 41 | u32 next_fd = 1; |
| 32 | enum class Status { Created, Allocated }; | ||
| 33 | u32 id; | ||
| 34 | u32 size; | ||
| 35 | u32 flags; | ||
| 36 | u32 align; | ||
| 37 | u8 kind; | ||
| 38 | VAddr addr; | ||
| 39 | Status status; | ||
| 40 | }; | ||
| 41 | |||
| 42 | u32 next_handle = 1; | ||
| 43 | u32 next_id = 1; | ||
| 44 | std::unordered_map<u32, std::shared_ptr<Object>> handles; | ||
| 45 | |||
| 46 | enum IoctlCommands { | ||
| 47 | IocCreateCommand = 0xC0080101, | ||
| 48 | IocFromIdCommand = 0xC0080103, | ||
| 49 | IocAllocCommand = 0xC0200104, | ||
| 50 | IocParamCommand = 0xC00C0109, | ||
| 51 | IocGetIdCommand = 0xC008010E | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct IocCreateParams { | ||
| 55 | // Input | ||
| 56 | u32_le size; | ||
| 57 | // Output | ||
| 58 | u32_le handle; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct IocAllocParams { | ||
| 62 | // Input | ||
| 63 | u32_le handle; | ||
| 64 | u32_le heap_mask; | ||
| 65 | u32_le flags; | ||
| 66 | u32_le align; | ||
| 67 | u8 kind; | ||
| 68 | INSERT_PADDING_BYTES(7); | ||
| 69 | u64_le addr; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct IocGetIdParams { | ||
| 73 | // Output | ||
| 74 | u32_le id; | ||
| 75 | // Input | ||
| 76 | u32_le handle; | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct IocFromIdParams { | ||
| 80 | // Input | ||
| 81 | u32_le id; | ||
| 82 | // Output | ||
| 83 | u32_le handle; | ||
| 84 | }; | ||
| 85 | 42 | ||
| 86 | struct IocParamParams { | 43 | /// Mapping of file descriptors to the devices they reference. |
| 87 | // Input | 44 | std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; |
| 88 | u32_le handle; | ||
| 89 | u32_le type; | ||
| 90 | // Output | ||
| 91 | u32_le value; | ||
| 92 | }; | ||
| 93 | 45 | ||
| 94 | u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); | 46 | /// Mapping of device node names to their implementation. |
| 95 | u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); | 47 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; |
| 96 | u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 97 | u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 98 | u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 99 | }; | ||
| 100 | |||
| 101 | class nvdisp_disp0 : public nvdevice { | ||
| 102 | public: | ||
| 103 | nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {} | ||
| 104 | ~nvdisp_disp0() = default; | ||
| 105 | |||
| 106 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 107 | |||
| 108 | /// Performs a screen flip, drawing the buffer pointed to by the handle. | ||
| 109 | void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); | ||
| 110 | |||
| 111 | private: | ||
| 112 | std::shared_ptr<nvmap> nvmap_dev; | ||
| 113 | }; | 48 | }; |
| 114 | 49 | ||
| 115 | /// Registers all NVDRV services with the specified service manager. | 50 | /// Registers all NVDRV services with the specified service manager. |
| 116 | void InstallInterfaces(SM::ServiceManager& service_manager); | 51 | void InstallInterfaces(SM::ServiceManager& service_manager); |
| 117 | 52 | ||
| 118 | } // namespace NVDRV | 53 | extern std::weak_ptr<Module> nvdrv; |
| 54 | |||
| 55 | } // namespace Nvidia | ||
| 119 | } // namespace Service | 56 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.h b/src/core/hle/service/nvdrv/nvdrv_a.h deleted file mode 100644 index 62f10e9f6..000000000 --- a/src/core/hle/service/nvdrv/nvdrv_a.h +++ /dev/null | |||
| @@ -1,51 +0,0 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace NVDRV { | ||
| 14 | |||
| 15 | namespace Devices { | ||
| 16 | class nvdevice; | ||
| 17 | } | ||
| 18 | |||
| 19 | class NVDRV_A final : public ServiceFramework<NVDRV_A> { | ||
| 20 | public: | ||
| 21 | NVDRV_A(); | ||
| 22 | ~NVDRV_A() = default; | ||
| 23 | |||
| 24 | /// Returns a pointer to one of the available devices, identified by its name. | ||
| 25 | template <typename T> | ||
| 26 | std::shared_ptr<T> GetDevice(std::string name) { | ||
| 27 | auto itr = devices.find(name); | ||
| 28 | if (itr == devices.end()) | ||
| 29 | return nullptr; | ||
| 30 | return std::static_pointer_cast<T>(itr->second); | ||
| 31 | } | ||
| 32 | |||
| 33 | private: | ||
| 34 | void Open(Kernel::HLERequestContext& ctx); | ||
| 35 | void Ioctl(Kernel::HLERequestContext& ctx); | ||
| 36 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 37 | |||
| 38 | /// Id to use for the next open file descriptor. | ||
| 39 | u32 next_fd = 1; | ||
| 40 | |||
| 41 | /// Mapping of file descriptors to the devices they reference. | ||
| 42 | std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; | ||
| 43 | |||
| 44 | /// Mapping of device node names to their implementation. | ||
| 45 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | ||
| 46 | }; | ||
| 47 | |||
| 48 | extern std::weak_ptr<NVDRV_A> nvdrv_a; | ||
| 49 | |||
| 50 | } // namespace NVDRV | ||
| 51 | } // namespace Service | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 02d434660..fe76b381c 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 15 | #include "core/hle/kernel/server_port.h" | 15 | #include "core/hle/kernel/server_port.h" |
| 16 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/service/acc/acc.h" | ||
| 17 | #include "core/hle/service/am/am.h" | 18 | #include "core/hle/service/am/am.h" |
| 18 | #include "core/hle/service/aoc/aoc_u.h" | 19 | #include "core/hle/service/aoc/aoc_u.h" |
| 19 | #include "core/hle/service/apm/apm.h" | 20 | #include "core/hle/service/apm/apm.h" |
| @@ -164,13 +165,14 @@ void Init() { | |||
| 164 | SM::g_service_manager = std::make_shared<SM::ServiceManager>(); | 165 | SM::g_service_manager = std::make_shared<SM::ServiceManager>(); |
| 165 | SM::ServiceManager::InstallInterfaces(SM::g_service_manager); | 166 | SM::ServiceManager::InstallInterfaces(SM::g_service_manager); |
| 166 | 167 | ||
| 168 | Account::InstallInterfaces(*SM::g_service_manager); | ||
| 167 | AM::InstallInterfaces(*SM::g_service_manager); | 169 | AM::InstallInterfaces(*SM::g_service_manager); |
| 168 | AOC::InstallInterfaces(*SM::g_service_manager); | 170 | AOC::InstallInterfaces(*SM::g_service_manager); |
| 169 | APM::InstallInterfaces(*SM::g_service_manager); | 171 | APM::InstallInterfaces(*SM::g_service_manager); |
| 170 | Audio::InstallInterfaces(*SM::g_service_manager); | 172 | Audio::InstallInterfaces(*SM::g_service_manager); |
| 171 | HID::InstallInterfaces(*SM::g_service_manager); | 173 | HID::InstallInterfaces(*SM::g_service_manager); |
| 172 | LM::InstallInterfaces(*SM::g_service_manager); | 174 | LM::InstallInterfaces(*SM::g_service_manager); |
| 173 | NVDRV::InstallInterfaces(*SM::g_service_manager); | 175 | Nvidia::InstallInterfaces(*SM::g_service_manager); |
| 174 | PCTL::InstallInterfaces(*SM::g_service_manager); | 176 | PCTL::InstallInterfaces(*SM::g_service_manager); |
| 175 | Time::InstallInterfaces(*SM::g_service_manager); | 177 | Time::InstallInterfaces(*SM::g_service_manager); |
| 176 | VI::InstallInterfaces(*SM::g_service_manager); | 178 | VI::InstallInterfaces(*SM::g_service_manager); |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 93ebbe75f..cae2c4466 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 11 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| 12 | #include "core/hle/service/nvdrv/nvdrv_a.h" | 12 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 13 | #include "core/hle/service/vi/vi.h" | 13 | #include "core/hle/service/vi/vi.h" |
| 14 | #include "core/hle/service/vi/vi_m.h" | 14 | #include "core/hle/service/vi/vi_m.h" |
| 15 | #include "video_core/renderer_base.h" | 15 | #include "video_core/renderer_base.h" |
| @@ -361,7 +361,7 @@ public: | |||
| 361 | static const FunctionInfo functions[] = { | 361 | static const FunctionInfo functions[] = { |
| 362 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | 362 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, |
| 363 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | 363 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, |
| 364 | {2, nullptr, "GetNativeHandle"}, | 364 | {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, |
| 365 | {3, nullptr, "TransactParcelAuto"}, | 365 | {3, nullptr, "TransactParcelAuto"}, |
| 366 | }; | 366 | }; |
| 367 | RegisterHandlers(functions); | 367 | RegisterHandlers(functions); |
| @@ -463,6 +463,21 @@ private: | |||
| 463 | rb.Push(RESULT_SUCCESS); | 463 | rb.Push(RESULT_SUCCESS); |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | void GetNativeHandle(Kernel::HLERequestContext& ctx) { | ||
| 467 | IPC::RequestParser rp{ctx}; | ||
| 468 | u32 id = rp.Pop<u32>(); | ||
| 469 | u32 unknown = rp.Pop<u32>(); | ||
| 470 | |||
| 471 | auto buffer_queue = nv_flinger->GetBufferQueue(id); | ||
| 472 | |||
| 473 | // TODO(Subv): Find out what this actually is. | ||
| 474 | |||
| 475 | LOG_WARNING(Service, "(STUBBED) called id=%u, unknown=%08X", id, unknown); | ||
| 476 | IPC::RequestBuilder rb{ctx, 2, 1}; | ||
| 477 | rb.Push(RESULT_SUCCESS); | ||
| 478 | rb.PushCopyObjects(buffer_queue->GetNativeHandle()); | ||
| 479 | } | ||
| 480 | |||
| 466 | std::shared_ptr<NVFlinger> nv_flinger; | 481 | std::shared_ptr<NVFlinger> nv_flinger; |
| 467 | }; | 482 | }; |
| 468 | 483 | ||
| @@ -565,6 +580,15 @@ void IApplicationDisplayService::GetManagerDisplayService(Kernel::HLERequestCont | |||
| 565 | rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); | 580 | rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); |
| 566 | } | 581 | } |
| 567 | 582 | ||
| 583 | void IApplicationDisplayService::GetIndirectDisplayTransactionService( | ||
| 584 | Kernel::HLERequestContext& ctx) { | ||
| 585 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 586 | |||
| 587 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 588 | rb.Push(RESULT_SUCCESS); | ||
| 589 | rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger); | ||
| 590 | } | ||
| 591 | |||
| 568 | void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | 592 | void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { |
| 569 | LOG_WARNING(Service, "(STUBBED) called"); | 593 | LOG_WARNING(Service, "(STUBBED) called"); |
| 570 | IPC::RequestParser rp{ctx}; | 594 | IPC::RequestParser rp{ctx}; |
| @@ -580,6 +604,15 @@ void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | |||
| 580 | rb.Push<u64>(nv_flinger->OpenDisplay(name)); | 604 | rb.Push<u64>(nv_flinger->OpenDisplay(name)); |
| 581 | } | 605 | } |
| 582 | 606 | ||
| 607 | void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) { | ||
| 608 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 609 | IPC::RequestParser rp{ctx}; | ||
| 610 | u64 display_id = rp.Pop<u64>(); | ||
| 611 | |||
| 612 | IPC::RequestBuilder rb = rp.MakeBuilder(4, 0, 0, 0); | ||
| 613 | rb.Push(RESULT_SUCCESS); | ||
| 614 | } | ||
| 615 | |||
| 583 | void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | 616 | void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { |
| 584 | LOG_WARNING(Service, "(STUBBED) called"); | 617 | LOG_WARNING(Service, "(STUBBED) called"); |
| 585 | IPC::RequestParser rp{ctx}; | 618 | IPC::RequestParser rp{ctx}; |
| @@ -605,6 +638,40 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | |||
| 605 | rb.Push<u64>(data.size()); | 638 | rb.Push<u64>(data.size()); |
| 606 | } | 639 | } |
| 607 | 640 | ||
| 641 | void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { | ||
| 642 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 643 | |||
| 644 | IPC::RequestParser rp{ctx}; | ||
| 645 | u32 flags = rp.Pop<u32>(); | ||
| 646 | u64 display_id = rp.Pop<u64>(); | ||
| 647 | |||
| 648 | auto& buffer = ctx.BufferDescriptorB()[0]; | ||
| 649 | |||
| 650 | // TODO(Subv): What's the difference between a Stray and a Managed layer? | ||
| 651 | |||
| 652 | u64 layer_id = nv_flinger->CreateLayer(display_id); | ||
| 653 | u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); | ||
| 654 | |||
| 655 | NativeWindow native_window{buffer_queue_id}; | ||
| 656 | auto data = native_window.Serialize(); | ||
| 657 | Memory::WriteBlock(buffer.Address(), data.data(), data.size()); | ||
| 658 | |||
| 659 | IPC::RequestBuilder rb = rp.MakeBuilder(6, 0, 0, 0); | ||
| 660 | rb.Push(RESULT_SUCCESS); | ||
| 661 | rb.Push(layer_id); | ||
| 662 | rb.Push<u64>(data.size()); | ||
| 663 | } | ||
| 664 | |||
| 665 | void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) { | ||
| 666 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 667 | |||
| 668 | IPC::RequestParser rp{ctx}; | ||
| 669 | u64 layer_id = rp.Pop<u64>(); | ||
| 670 | |||
| 671 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0, 0, 0); | ||
| 672 | rb.Push(RESULT_SUCCESS); | ||
| 673 | } | ||
| 674 | |||
| 608 | void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { | 675 | void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { |
| 609 | LOG_WARNING(Service, "(STUBBED) called"); | 676 | LOG_WARNING(Service, "(STUBBED) called"); |
| 610 | IPC::RequestParser rp{ctx}; | 677 | IPC::RequestParser rp{ctx}; |
| @@ -633,11 +700,15 @@ IApplicationDisplayService::IApplicationDisplayService(std::shared_ptr<NVFlinger | |||
| 633 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | 700 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, |
| 634 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | 701 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, |
| 635 | {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, | 702 | {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, |
| 636 | {103, nullptr, "GetIndirectDisplayTransactionService"}, | 703 | {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, |
| 704 | "GetIndirectDisplayTransactionService"}, | ||
| 637 | {1000, nullptr, "ListDisplays"}, | 705 | {1000, nullptr, "ListDisplays"}, |
| 638 | {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | 706 | {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, |
| 707 | {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||
| 639 | {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | 708 | {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, |
| 640 | {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | 709 | {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, |
| 710 | {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||
| 711 | {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||
| 641 | {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | 712 | {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, |
| 642 | }; | 713 | }; |
| 643 | RegisterHandlers(functions); | 714 | RegisterHandlers(functions); |
| @@ -763,12 +834,12 @@ void NVFlinger::Compose() { | |||
| 763 | auto& igbp_buffer = buffer->igbp_buffer; | 834 | auto& igbp_buffer = buffer->igbp_buffer; |
| 764 | 835 | ||
| 765 | // Now send the buffer to the GPU for drawing. | 836 | // Now send the buffer to the GPU for drawing. |
| 766 | auto nvdrv = NVDRV::nvdrv_a.lock(); | 837 | auto nvdrv = Nvidia::nvdrv.lock(); |
| 767 | ASSERT(nvdrv); | 838 | ASSERT(nvdrv); |
| 768 | 839 | ||
| 769 | // TODO(Subv): Support more than just disp0. The display device selection is probably based | 840 | // TODO(Subv): Support more than just disp0. The display device selection is probably based |
| 770 | // on which display we're drawing (Default, Internal, External, etc) | 841 | // on which display we're drawing (Default, Internal, External, etc) |
| 771 | auto nvdisp = nvdrv->GetDevice<NVDRV::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); | 842 | auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); |
| 772 | ASSERT(nvdisp); | 843 | ASSERT(nvdisp); |
| 773 | 844 | ||
| 774 | nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, | 845 | nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, |
| @@ -778,7 +849,9 @@ void NVFlinger::Compose() { | |||
| 778 | } | 849 | } |
| 779 | } | 850 | } |
| 780 | 851 | ||
| 781 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {} | 852 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { |
| 853 | native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); | ||
| 854 | } | ||
| 782 | 855 | ||
| 783 | void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { | 856 | void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { |
| 784 | Buffer buffer{}; | 857 | Buffer buffer{}; |
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 10e894f8c..81d4f3daa 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -59,11 +59,16 @@ public: | |||
| 59 | return id; | 59 | return id; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | Kernel::SharedPtr<Kernel::Event> GetNativeHandle() const { | ||
| 63 | return native_handle; | ||
| 64 | } | ||
| 65 | |||
| 62 | private: | 66 | private: |
| 63 | u32 id; | 67 | u32 id; |
| 64 | u64 layer_id; | 68 | u64 layer_id; |
| 65 | 69 | ||
| 66 | std::vector<Buffer> queue; | 70 | std::vector<Buffer> queue; |
| 71 | Kernel::SharedPtr<Kernel::Event> native_handle; | ||
| 67 | }; | 72 | }; |
| 68 | 73 | ||
| 69 | struct Layer { | 74 | struct Layer { |
| @@ -138,9 +143,13 @@ private: | |||
| 138 | void GetRelayService(Kernel::HLERequestContext& ctx); | 143 | void GetRelayService(Kernel::HLERequestContext& ctx); |
| 139 | void GetSystemDisplayService(Kernel::HLERequestContext& ctx); | 144 | void GetSystemDisplayService(Kernel::HLERequestContext& ctx); |
| 140 | void GetManagerDisplayService(Kernel::HLERequestContext& ctx); | 145 | void GetManagerDisplayService(Kernel::HLERequestContext& ctx); |
| 146 | void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx); | ||
| 141 | void OpenDisplay(Kernel::HLERequestContext& ctx); | 147 | void OpenDisplay(Kernel::HLERequestContext& ctx); |
| 148 | void CloseDisplay(Kernel::HLERequestContext& ctx); | ||
| 142 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx); | 149 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx); |
| 143 | void OpenLayer(Kernel::HLERequestContext& ctx); | 150 | void OpenLayer(Kernel::HLERequestContext& ctx); |
| 151 | void CreateStrayLayer(Kernel::HLERequestContext& ctx); | ||
| 152 | void DestroyStrayLayer(Kernel::HLERequestContext& ctx); | ||
| 144 | void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx); | 153 | void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx); |
| 145 | 154 | ||
| 146 | std::shared_ptr<NVFlinger> nv_flinger; | 155 | std::shared_ptr<NVFlinger> nv_flinger; |
diff --git a/src/core/loader/linker.cpp b/src/core/loader/linker.cpp index f82c6f4b4..87cc65e91 100644 --- a/src/core/loader/linker.cpp +++ b/src/core/loader/linker.cpp | |||
| @@ -48,9 +48,9 @@ struct Elf64_Sym { | |||
| 48 | }; | 48 | }; |
| 49 | static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size."); | 49 | static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size."); |
| 50 | 50 | ||
| 51 | void Linker::WriteRelocations(std::vector<u8>& program_image, | 51 | void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<Symbol>& symbols, |
| 52 | const std::vector<Symbol>& symbols, u64 relocation_offset, | 52 | u64 relocation_offset, u64 size, bool is_jump_relocation, |
| 53 | u64 size, bool is_jump_relocation, VAddr load_base) { | 53 | VAddr load_base) { |
| 54 | for (u64 i = 0; i < size; i += sizeof(Elf64_Rela)) { | 54 | for (u64 i = 0; i < size; i += sizeof(Elf64_Rela)) { |
| 55 | Elf64_Rela rela; | 55 | Elf64_Rela rela; |
| 56 | std::memcpy(&rela, &program_image[relocation_offset + i], sizeof(Elf64_Rela)); | 56 | std::memcpy(&rela, &program_image[relocation_offset + i], sizeof(Elf64_Rela)); |
| @@ -90,8 +90,7 @@ void Linker::WriteRelocations(std::vector<u8>& program_image, | |||
| 90 | } | 90 | } |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, | 93 | void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, VAddr load_base) { |
| 94 | VAddr load_base) { | ||
| 95 | std::map<u64, u64> dynamic; | 94 | std::map<u64, u64> dynamic; |
| 96 | while (dynamic_section_offset < program_image.size()) { | 95 | while (dynamic_section_offset < program_image.size()) { |
| 97 | Elf64_Dyn dyn; | 96 | Elf64_Dyn dyn; |
| @@ -141,8 +140,7 @@ void Linker::ResolveImports() { | |||
| 141 | const auto& search = exports.find(import.first); | 140 | const auto& search = exports.find(import.first); |
| 142 | if (search != exports.end()) { | 141 | if (search != exports.end()) { |
| 143 | Memory::Write64(import.second.ea, search->second + import.second.addend); | 142 | Memory::Write64(import.second.ea, search->second + import.second.addend); |
| 144 | } | 143 | } else { |
| 145 | else { | ||
| 146 | LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); | 144 | LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); |
| 147 | } | 145 | } |
| 148 | } | 146 | } |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 7e1953701..ff96e129b 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -19,7 +19,10 @@ struct NsoSegmentHeader { | |||
| 19 | u32_le offset; | 19 | u32_le offset; |
| 20 | u32_le location; | 20 | u32_le location; |
| 21 | u32_le size; | 21 | u32_le size; |
| 22 | u32_le alignment; | 22 | union { |
| 23 | u32_le alignment; | ||
| 24 | u32_le bss_size; | ||
| 25 | }; | ||
| 23 | }; | 26 | }; |
| 24 | static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size."); | 27 | static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size."); |
| 25 | 28 | ||
| @@ -120,14 +123,15 @@ VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base, bool relo | |||
| 120 | 123 | ||
| 121 | // Read MOD header | 124 | // Read MOD header |
| 122 | ModHeader mod_header{}; | 125 | ModHeader mod_header{}; |
| 123 | u32 bss_size{Memory::PAGE_SIZE}; // Default .bss to page size if MOD0 section doesn't exist | 126 | // Default .bss to size in segment header if MOD0 section doesn't exist |
| 127 | u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)}; | ||
| 124 | std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader)); | 128 | std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader)); |
| 125 | const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')}; | 129 | const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')}; |
| 126 | if (has_mod_header) { | 130 | if (has_mod_header) { |
| 127 | // Resize program image to include .bss section and page align each section | 131 | // Resize program image to include .bss section and page align each section |
| 128 | bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); | 132 | bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); |
| 129 | codeset->data.size += bss_size; | ||
| 130 | } | 133 | } |
| 134 | codeset->data.size += bss_size; | ||
| 131 | const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; | 135 | const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; |
| 132 | program_image.resize(image_size); | 136 | program_image.resize(image_size); |
| 133 | 137 | ||
| @@ -157,7 +161,8 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 157 | 161 | ||
| 158 | // Load NSO modules | 162 | // Load NSO modules |
| 159 | VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; | 163 | VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; |
| 160 | for (const auto& module : {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4"}) { | 164 | for (const auto& module : |
| 165 | {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4"}) { | ||
| 161 | const std::string path = filepath.substr(0, filepath.find_last_of("/\\")) + "/" + module; | 166 | const std::string path = filepath.substr(0, filepath.find_last_of("/\\")) + "/" + module; |
| 162 | const VAddr load_addr = next_load_addr; | 167 | const VAddr load_addr = next_load_addr; |
| 163 | next_load_addr = LoadNso(path, load_addr); | 168 | next_load_addr = LoadNso(path, load_addr); |
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 28df00384..03424e70d 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -18,8 +18,7 @@ namespace Loader { | |||
| 18 | class AppLoader_NSO final : public AppLoader, Linker { | 18 | class AppLoader_NSO final : public AppLoader, Linker { |
| 19 | public: | 19 | public: |
| 20 | AppLoader_NSO(FileUtil::IOFile&& file, std::string filepath) | 20 | AppLoader_NSO(FileUtil::IOFile&& file, std::string filepath) |
| 21 | : AppLoader(std::move(file)), filepath(std::move(filepath)) { | 21 | : AppLoader(std::move(file)), filepath(std::move(filepath)) {} |
| 22 | } | ||
| 23 | 22 | ||
| 24 | /** | 23 | /** |
| 25 | * Returns the type of the file | 24 | * Returns the type of the file |
diff --git a/src/core/memory.h b/src/core/memory.h index 91bd4d889..7e554f394 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -136,7 +136,7 @@ enum : VAddr { | |||
| 136 | 136 | ||
| 137 | /// Application heap (includes stack). | 137 | /// Application heap (includes stack). |
| 138 | HEAP_VADDR = 0x108000000, | 138 | HEAP_VADDR = 0x108000000, |
| 139 | HEAP_SIZE = 0x18000000, | 139 | HEAP_SIZE = 0xF0000000, |
| 140 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, | 140 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, |
| 141 | 141 | ||
| 142 | /// Area where shared memory buffers are mapped onto. | 142 | /// Area where shared memory buffers are mapped onto. |
| @@ -177,7 +177,7 @@ enum : VAddr { | |||
| 177 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 177 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 178 | 178 | ||
| 179 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 179 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 180 | TLS_AREA_VADDR = 0x1FF82000, | 180 | TLS_AREA_VADDR = 0x228000000, |
| 181 | TLS_ENTRY_SIZE = 0x200, | 181 | TLS_ENTRY_SIZE = 0x200, |
| 182 | 182 | ||
| 183 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | 183 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 557353740..95d40f09f 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -71,4 +71,15 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, | |||
| 71 | return circle_pad_param.Serialize(); | 71 | return circle_pad_param.Serialize(); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | namespace Polling { | ||
| 75 | |||
| 76 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) { | ||
| 77 | #ifdef HAVE_SDL2 | ||
| 78 | return SDL::Polling::GetPollers(type); | ||
| 79 | #else | ||
| 80 | return {}; | ||
| 81 | #endif | ||
| 82 | } | ||
| 83 | |||
| 84 | } // namespace Polling | ||
| 74 | } // namespace InputCommon | 85 | } // namespace InputCommon |
diff --git a/src/input_common/main.h b/src/input_common/main.h index 5604f0fa8..77a0ce90b 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h | |||
| @@ -4,7 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 7 | #include <string> | 8 | #include <string> |
| 9 | #include <vector> | ||
| 10 | |||
| 11 | namespace Common { | ||
| 12 | class ParamPackage; | ||
| 13 | } | ||
| 8 | 14 | ||
| 9 | namespace InputCommon { | 15 | namespace InputCommon { |
| 10 | 16 | ||
| @@ -31,4 +37,30 @@ std::string GenerateKeyboardParam(int key_code); | |||
| 31 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, | 37 | std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, |
| 32 | int key_modifier, float modifier_scale); | 38 | int key_modifier, float modifier_scale); |
| 33 | 39 | ||
| 40 | namespace Polling { | ||
| 41 | |||
| 42 | enum class DeviceType { Button, Analog }; | ||
| 43 | |||
| 44 | /** | ||
| 45 | * A class that can be used to get inputs from an input device like controllers without having to | ||
| 46 | * poll the device's status yourself | ||
| 47 | */ | ||
| 48 | class DevicePoller { | ||
| 49 | public: | ||
| 50 | virtual ~DevicePoller() = default; | ||
| 51 | /// Setup and start polling for inputs, should be called before GetNextInput | ||
| 52 | virtual void Start() = 0; | ||
| 53 | /// Stop polling | ||
| 54 | virtual void Stop() = 0; | ||
| 55 | /** | ||
| 56 | * Every call to this function returns the next input recorded since calling Start | ||
| 57 | * @return A ParamPackage of the recorded input, which can be used to create an InputDevice. | ||
| 58 | * If there has been no input, the package is empty | ||
| 59 | */ | ||
| 60 | virtual Common::ParamPackage GetNextInput() = 0; | ||
| 61 | }; | ||
| 62 | |||
| 63 | // Get all DevicePoller from all backends for a specific device type | ||
| 64 | std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type); | ||
| 65 | } // namespace Polling | ||
| 34 | } // namespace InputCommon | 66 | } // namespace InputCommon |
diff --git a/src/input_common/sdl/sdl.cpp b/src/input_common/sdl/sdl.cpp index d404afa89..88b557c5d 100644 --- a/src/input_common/sdl/sdl.cpp +++ b/src/input_common/sdl/sdl.cpp | |||
| @@ -3,13 +3,15 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | #include <memory> | ||
| 7 | #include <string> | 6 | #include <string> |
| 8 | #include <tuple> | 7 | #include <tuple> |
| 9 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | #include <utility> | ||
| 10 | #include <SDL.h> | 10 | #include <SDL.h> |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/math_util.h" | 12 | #include "common/math_util.h" |
| 13 | #include "common/param_package.h" | ||
| 14 | #include "input_common/main.h" | ||
| 13 | #include "input_common/sdl/sdl.h" | 15 | #include "input_common/sdl/sdl.h" |
| 14 | 16 | ||
| 15 | namespace InputCommon { | 17 | namespace InputCommon { |
| @@ -69,6 +71,10 @@ public: | |||
| 69 | return (SDL_JoystickGetHat(joystick.get(), hat) & direction) != 0; | 71 | return (SDL_JoystickGetHat(joystick.get(), hat) & direction) != 0; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 74 | SDL_JoystickID GetJoystickID() const { | ||
| 75 | return SDL_JoystickInstanceID(joystick.get()); | ||
| 76 | } | ||
| 77 | |||
| 72 | private: | 78 | private: |
| 73 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> joystick; | 79 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> joystick; |
| 74 | }; | 80 | }; |
| @@ -247,5 +253,180 @@ void Shutdown() { | |||
| 247 | } | 253 | } |
| 248 | } | 254 | } |
| 249 | 255 | ||
| 256 | /** | ||
| 257 | * This function converts a joystick ID used in SDL events to the device index. This is necessary | ||
| 258 | * because Citra opens joysticks using their indices, not their IDs. | ||
| 259 | */ | ||
| 260 | static int JoystickIDToDeviceIndex(SDL_JoystickID id) { | ||
| 261 | int num_joysticks = SDL_NumJoysticks(); | ||
| 262 | for (int i = 0; i < num_joysticks; i++) { | ||
| 263 | auto joystick = GetJoystick(i); | ||
| 264 | if (joystick->GetJoystickID() == id) { | ||
| 265 | return i; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | return -1; | ||
| 269 | } | ||
| 270 | |||
| 271 | Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) { | ||
| 272 | Common::ParamPackage params({{"engine", "sdl"}}); | ||
| 273 | switch (event.type) { | ||
| 274 | case SDL_JOYAXISMOTION: | ||
| 275 | params.Set("joystick", JoystickIDToDeviceIndex(event.jaxis.which)); | ||
| 276 | params.Set("axis", event.jaxis.axis); | ||
| 277 | if (event.jaxis.value > 0) { | ||
| 278 | params.Set("direction", "+"); | ||
| 279 | params.Set("threshold", "0.5"); | ||
| 280 | } else { | ||
| 281 | params.Set("direction", "-"); | ||
| 282 | params.Set("threshold", "-0.5"); | ||
| 283 | } | ||
| 284 | break; | ||
| 285 | case SDL_JOYBUTTONUP: | ||
| 286 | params.Set("joystick", JoystickIDToDeviceIndex(event.jbutton.which)); | ||
| 287 | params.Set("button", event.jbutton.button); | ||
| 288 | break; | ||
| 289 | case SDL_JOYHATMOTION: | ||
| 290 | params.Set("joystick", JoystickIDToDeviceIndex(event.jhat.which)); | ||
| 291 | params.Set("hat", event.jhat.hat); | ||
| 292 | switch (event.jhat.value) { | ||
| 293 | case SDL_HAT_UP: | ||
| 294 | params.Set("direction", "up"); | ||
| 295 | break; | ||
| 296 | case SDL_HAT_DOWN: | ||
| 297 | params.Set("direction", "down"); | ||
| 298 | break; | ||
| 299 | case SDL_HAT_LEFT: | ||
| 300 | params.Set("direction", "left"); | ||
| 301 | break; | ||
| 302 | case SDL_HAT_RIGHT: | ||
| 303 | params.Set("direction", "right"); | ||
| 304 | break; | ||
| 305 | default: | ||
| 306 | return {}; | ||
| 307 | } | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | return params; | ||
| 311 | } | ||
| 312 | |||
| 313 | namespace Polling { | ||
| 314 | |||
| 315 | class SDLPoller : public InputCommon::Polling::DevicePoller { | ||
| 316 | public: | ||
| 317 | SDLPoller() = default; | ||
| 318 | |||
| 319 | ~SDLPoller() = default; | ||
| 320 | |||
| 321 | void Start() override { | ||
| 322 | // SDL joysticks must be opened, otherwise they don't generate events | ||
| 323 | SDL_JoystickUpdate(); | ||
| 324 | int num_joysticks = SDL_NumJoysticks(); | ||
| 325 | for (int i = 0; i < num_joysticks; i++) { | ||
| 326 | joysticks_opened.emplace_back(GetJoystick(i)); | ||
| 327 | } | ||
| 328 | // Empty event queue to get rid of old events. citra-qt doesn't use the queue | ||
| 329 | SDL_Event dummy; | ||
| 330 | while (SDL_PollEvent(&dummy)) { | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | void Stop() override { | ||
| 335 | joysticks_opened.clear(); | ||
| 336 | } | ||
| 337 | |||
| 338 | private: | ||
| 339 | std::vector<std::shared_ptr<SDLJoystick>> joysticks_opened; | ||
| 340 | }; | ||
| 341 | |||
| 342 | class SDLButtonPoller final : public SDLPoller { | ||
| 343 | public: | ||
| 344 | SDLButtonPoller() = default; | ||
| 345 | |||
| 346 | ~SDLButtonPoller() = default; | ||
| 347 | |||
| 348 | Common::ParamPackage GetNextInput() override { | ||
| 349 | SDL_Event event; | ||
| 350 | while (SDL_PollEvent(&event)) { | ||
| 351 | switch (event.type) { | ||
| 352 | case SDL_JOYAXISMOTION: | ||
| 353 | if (std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | case SDL_JOYBUTTONUP: | ||
| 357 | case SDL_JOYHATMOTION: | ||
| 358 | return SDLEventToButtonParamPackage(event); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | return {}; | ||
| 362 | } | ||
| 363 | }; | ||
| 364 | |||
| 365 | class SDLAnalogPoller final : public SDLPoller { | ||
| 366 | public: | ||
| 367 | SDLAnalogPoller() = default; | ||
| 368 | |||
| 369 | ~SDLAnalogPoller() = default; | ||
| 370 | |||
| 371 | void Start() override { | ||
| 372 | SDLPoller::Start(); | ||
| 373 | |||
| 374 | // Reset stored axes | ||
| 375 | analog_xaxis = -1; | ||
| 376 | analog_yaxis = -1; | ||
| 377 | analog_axes_joystick = -1; | ||
| 378 | } | ||
| 379 | |||
| 380 | Common::ParamPackage GetNextInput() override { | ||
| 381 | SDL_Event event; | ||
| 382 | while (SDL_PollEvent(&event)) { | ||
| 383 | if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) { | ||
| 384 | continue; | ||
| 385 | } | ||
| 386 | // An analog device needs two axes, so we need to store the axis for later and wait for | ||
| 387 | // a second SDL event. The axes also must be from the same joystick. | ||
| 388 | int axis = event.jaxis.axis; | ||
| 389 | if (analog_xaxis == -1) { | ||
| 390 | analog_xaxis = axis; | ||
| 391 | analog_axes_joystick = event.jaxis.which; | ||
| 392 | } else if (analog_yaxis == -1 && analog_xaxis != axis && | ||
| 393 | analog_axes_joystick == event.jaxis.which) { | ||
| 394 | analog_yaxis = axis; | ||
| 395 | } | ||
| 396 | } | ||
| 397 | Common::ParamPackage params; | ||
| 398 | if (analog_xaxis != -1 && analog_yaxis != -1) { | ||
| 399 | params.Set("engine", "sdl"); | ||
| 400 | params.Set("joystick", JoystickIDToDeviceIndex(analog_axes_joystick)); | ||
| 401 | params.Set("axis_x", analog_xaxis); | ||
| 402 | params.Set("axis_y", analog_yaxis); | ||
| 403 | analog_xaxis = -1; | ||
| 404 | analog_yaxis = -1; | ||
| 405 | analog_axes_joystick = -1; | ||
| 406 | return params; | ||
| 407 | } | ||
| 408 | return params; | ||
| 409 | } | ||
| 410 | |||
| 411 | private: | ||
| 412 | int analog_xaxis = -1; | ||
| 413 | int analog_yaxis = -1; | ||
| 414 | SDL_JoystickID analog_axes_joystick = -1; | ||
| 415 | }; | ||
| 416 | |||
| 417 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> GetPollers( | ||
| 418 | InputCommon::Polling::DeviceType type) { | ||
| 419 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> pollers; | ||
| 420 | switch (type) { | ||
| 421 | case InputCommon::Polling::DeviceType::Analog: | ||
| 422 | pollers.push_back(std::make_unique<SDLAnalogPoller>()); | ||
| 423 | break; | ||
| 424 | case InputCommon::Polling::DeviceType::Button: | ||
| 425 | pollers.push_back(std::make_unique<SDLButtonPoller>()); | ||
| 426 | break; | ||
| 427 | } | ||
| 428 | return std::move(pollers); | ||
| 429 | } | ||
| 430 | } // namespace Polling | ||
| 250 | } // namespace SDL | 431 | } // namespace SDL |
| 251 | } // namespace InputCommon | 432 | } // namespace InputCommon |
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 3e72debcc..7934099d4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -4,8 +4,21 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | #include <vector> | ||
| 7 | #include "core/frontend/input.h" | 9 | #include "core/frontend/input.h" |
| 8 | 10 | ||
| 11 | union SDL_Event; | ||
| 12 | namespace Common { | ||
| 13 | class ParamPackage; | ||
| 14 | } | ||
| 15 | namespace InputCommon { | ||
| 16 | namespace Polling { | ||
| 17 | class DevicePoller; | ||
| 18 | enum class DeviceType; | ||
| 19 | } // namespace Polling | ||
| 20 | } // namespace InputCommon | ||
| 21 | |||
| 9 | namespace InputCommon { | 22 | namespace InputCommon { |
| 10 | namespace SDL { | 23 | namespace SDL { |
| 11 | 24 | ||
| @@ -15,5 +28,15 @@ void Init(); | |||
| 15 | /// Unresisters SDL device factories and shut them down. | 28 | /// Unresisters SDL device factories and shut them down. |
| 16 | void Shutdown(); | 29 | void Shutdown(); |
| 17 | 30 | ||
| 31 | /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice | ||
| 32 | Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event); | ||
| 33 | |||
| 34 | namespace Polling { | ||
| 35 | |||
| 36 | /// Get all DevicePoller that use the SDL backend for a specific device type | ||
| 37 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> GetPollers( | ||
| 38 | InputCommon::Polling::DeviceType type); | ||
| 39 | |||
| 40 | } // namespace Polling | ||
| 18 | } // namespace SDL | 41 | } // namespace SDL |
| 19 | } // namespace InputCommon | 42 | } // namespace InputCommon |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index dd01e1b1a..db6c355a5 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -61,7 +61,8 @@ private: | |||
| 61 | // Loads framebuffer from emulated memory into the display information structure | 61 | // Loads framebuffer from emulated memory into the display information structure |
| 62 | void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); | 62 | void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); |
| 63 | // Fills active OpenGL texture with the given RGBA color. | 63 | // Fills active OpenGL texture with the given RGBA color. |
| 64 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture); | 64 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, |
| 65 | const TextureInfo& texture); | ||
| 65 | 66 | ||
| 66 | EmuWindow* render_window; ///< Handle to render window | 67 | EmuWindow* render_window; ///< Handle to render window |
| 67 | 68 | ||
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index 0f1b6cdc6..da3429822 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { | 9 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { |
| 10 | ui->setupUi(this); | 10 | ui->setupUi(this); |
| 11 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( | 11 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( |
| 12 | Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | 12 | Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | AboutDialog::~AboutDialog() {} | 15 | AboutDialog::~AboutDialog() {} |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index a1e0cf575..843ac6ad7 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -40,6 +40,7 @@ void EmuThread::run() { | |||
| 40 | 40 | ||
| 41 | Core::System::ResultStatus result = Core::System::GetInstance().RunLoop(); | 41 | Core::System::ResultStatus result = Core::System::GetInstance().RunLoop(); |
| 42 | if (result != Core::System::ResultStatus::Success) { | 42 | if (result != Core::System::ResultStatus::Success) { |
| 43 | this->SetRunning(false); | ||
| 43 | emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails()); | 44 | emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails()); |
| 44 | } | 45 | } |
| 45 | 46 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index ab6ba0ec9..6a40f035c 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -18,10 +18,10 @@ Config::Config() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | 20 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { |
| 21 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, Qt::Key_W, | 21 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, |
| 22 | Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, Qt::Key_H, Qt::Key_G, | 22 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, |
| 23 | Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, Qt::Key_I, Qt::Key_L, | 23 | Qt::Key_H, Qt::Key_G, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, |
| 24 | Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, | 24 | Qt::Key_I, Qt::Key_L, Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ | 27 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ |
| @@ -137,6 +137,7 @@ void Config::ReadValues() { | |||
| 137 | qt_config->endGroup(); | 137 | qt_config->endGroup(); |
| 138 | 138 | ||
| 139 | UISettings::values.single_window_mode = qt_config->value("singleWindowMode", true).toBool(); | 139 | UISettings::values.single_window_mode = qt_config->value("singleWindowMode", true).toBool(); |
| 140 | UISettings::values.fullscreen = qt_config->value("fullscreen", false).toBool(); | ||
| 140 | UISettings::values.display_titlebar = qt_config->value("displayTitleBars", true).toBool(); | 141 | UISettings::values.display_titlebar = qt_config->value("displayTitleBars", true).toBool(); |
| 141 | UISettings::values.show_filter_bar = qt_config->value("showFilterBar", true).toBool(); | 142 | UISettings::values.show_filter_bar = qt_config->value("showFilterBar", true).toBool(); |
| 142 | UISettings::values.show_status_bar = qt_config->value("showStatusBar", true).toBool(); | 143 | UISettings::values.show_status_bar = qt_config->value("showStatusBar", true).toBool(); |
| @@ -216,6 +217,7 @@ void Config::SaveValues() { | |||
| 216 | qt_config->endGroup(); | 217 | qt_config->endGroup(); |
| 217 | 218 | ||
| 218 | qt_config->setValue("singleWindowMode", UISettings::values.single_window_mode); | 219 | qt_config->setValue("singleWindowMode", UISettings::values.single_window_mode); |
| 220 | qt_config->setValue("fullscreen", UISettings::values.fullscreen); | ||
| 219 | qt_config->setValue("displayTitleBars", UISettings::values.display_titlebar); | 221 | qt_config->setValue("displayTitleBars", UISettings::values.display_titlebar); |
| 220 | qt_config->setValue("showFilterBar", UISettings::values.show_filter_bar); | 222 | qt_config->setValue("showFilterBar", UISettings::values.show_filter_bar); |
| 221 | qt_config->setValue("showStatusBar", UISettings::values.show_status_bar); | 223 | qt_config->setValue("showStatusBar", UISettings::values.show_status_bar); |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 9eb71c593..a45edd510 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include "ui_configure_debug.h" | 6 | #include "ui_configure_debug.h" |
| 7 | #include "yuzu/configuration/configure_debug.h" | 7 | #include "yuzu/configuration/configure_debug.h" |
| 8 | 8 | ||
| 9 | |||
| 10 | ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { | 9 | ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { |
| 11 | ui->setupUi(this); | 10 | ui->setupUi(this); |
| 12 | this->setConfiguration(); | 11 | this->setConfiguration(); |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 96638ebdb..a10bea2f4 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -13,24 +13,24 @@ | |||
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Form</string> | 14 | <string>Form</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_1"> |
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 18 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 19 | <item> | 19 | <item> |
| 20 | <widget class="QGroupBox" name="groupBox"> | 20 | <widget class="QGroupBox" name="groupBox"> |
| 21 | <property name="title"> | 21 | <property name="title"> |
| 22 | <string>GDB</string> | 22 | <string>GDB</string> |
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 24 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel"> | 26 | <widget class="QLabel" name="label_1"> |
| 27 | <property name="text"> | 27 | <property name="text"> |
| 28 | <string>The GDB Stub only works correctly when the CPU JIT is off.</string> | 28 | <string>The GDB Stub only works correctly when the CPU JIT is off.</string> |
| 29 | </property> | 29 | </property> |
| 30 | </widget> | 30 | </widget> |
| 31 | </item> | 31 | </item> |
| 32 | <item> | 32 | <item> |
| 33 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 33 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 34 | <item> | 34 | <item> |
| 35 | <widget class="QCheckBox" name="toggle_gdbstub"> | 35 | <widget class="QCheckBox" name="toggle_gdbstub"> |
| 36 | <property name="text"> | 36 | <property name="text"> |
| @@ -52,7 +52,7 @@ | |||
| 52 | </spacer> | 52 | </spacer> |
| 53 | </item> | 53 | </item> |
| 54 | <item> | 54 | <item> |
| 55 | <widget class="QLabel" name="label"> | 55 | <widget class="QLabel" name="label_2"> |
| 56 | <property name="text"> | 56 | <property name="text"> |
| 57 | <string>Port:</string> | 57 | <string>Port:</string> |
| 58 | </property> | 58 | </property> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 23e5687d0..358f33005 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include "yuzu/configuration/config.h" | 7 | #include "yuzu/configuration/config.h" |
| 8 | #include "yuzu/configuration/configure_dialog.h" | 8 | #include "yuzu/configuration/configure_dialog.h" |
| 9 | 9 | ||
| 10 | |||
| 11 | ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { | 10 | ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { |
| 12 | ui->setupUi(this); | 11 | ui->setupUi(this); |
| 13 | this->setConfiguration(); | 12 | this->setConfiguration(); |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index d92a1fed9..10043e6e8 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -5,13 +5,13 @@ | |||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | #include <QMessageBox> | ||
| 8 | #include <QTimer> | 9 | #include <QTimer> |
| 9 | #include "common/param_package.h" | 10 | #include "common/param_package.h" |
| 10 | #include "input_common/main.h" | 11 | #include "input_common/main.h" |
| 11 | #include "yuzu/configuration/config.h" | 12 | #include "yuzu/configuration/config.h" |
| 12 | #include "yuzu/configuration/configure_input.h" | 13 | #include "yuzu/configuration/configure_input.h" |
| 13 | 14 | ||
| 14 | |||
| 15 | const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM> | 15 | const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM> |
| 16 | ConfigureInput::analog_sub_buttons{{ | 16 | ConfigureInput::analog_sub_buttons{{ |
| 17 | "up", "down", "left", "right", "modifier", | 17 | "up", "down", "left", "right", "modifier", |
| @@ -32,38 +32,80 @@ static QString getKeyName(int key_code) { | |||
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | static void SetButtonKey(int key, Common::ParamPackage& button_param) { | 35 | static void SetAnalogButton(const Common::ParamPackage& input_param, |
| 36 | button_param = Common::ParamPackage{InputCommon::GenerateKeyboardParam(key)}; | 36 | Common::ParamPackage& analog_param, const std::string& button_name) { |
| 37 | } | ||
| 38 | |||
| 39 | static void SetAnalogKey(int key, Common::ParamPackage& analog_param, | ||
| 40 | const std::string& button_name) { | ||
| 41 | if (analog_param.Get("engine", "") != "analog_from_button") { | 37 | if (analog_param.Get("engine", "") != "analog_from_button") { |
| 42 | analog_param = { | 38 | analog_param = { |
| 43 | {"engine", "analog_from_button"}, {"modifier_scale", "0.5"}, | 39 | {"engine", "analog_from_button"}, {"modifier_scale", "0.5"}, |
| 44 | }; | 40 | }; |
| 45 | } | 41 | } |
| 46 | analog_param.Set(button_name, InputCommon::GenerateKeyboardParam(key)); | 42 | analog_param.Set(button_name, input_param.Serialize()); |
| 47 | } | 43 | } |
| 48 | 44 | ||
| 45 | static QString ButtonToText(const Common::ParamPackage& param) { | ||
| 46 | if (!param.Has("engine")) { | ||
| 47 | return QObject::tr("[not set]"); | ||
| 48 | } else if (param.Get("engine", "") == "keyboard") { | ||
| 49 | return getKeyName(param.Get("code", 0)); | ||
| 50 | } else if (param.Get("engine", "") == "sdl") { | ||
| 51 | QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str()); | ||
| 52 | if (param.Has("hat")) { | ||
| 53 | text += QString(QObject::tr(" Hat %1 %2")) | ||
| 54 | .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); | ||
| 55 | } | ||
| 56 | if (param.Has("axis")) { | ||
| 57 | text += QString(QObject::tr(" Axis %1%2")) | ||
| 58 | .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); | ||
| 59 | } | ||
| 60 | if (param.Has("button")) { | ||
| 61 | text += QString(QObject::tr(" Button %1")).arg(param.Get("button", "").c_str()); | ||
| 62 | } | ||
| 63 | return text; | ||
| 64 | } else { | ||
| 65 | return QObject::tr("[unknown]"); | ||
| 66 | } | ||
| 67 | }; | ||
| 68 | |||
| 69 | static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { | ||
| 70 | if (!param.Has("engine")) { | ||
| 71 | return QObject::tr("[not set]"); | ||
| 72 | } else if (param.Get("engine", "") == "analog_from_button") { | ||
| 73 | return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); | ||
| 74 | } else if (param.Get("engine", "") == "sdl") { | ||
| 75 | if (dir == "modifier") { | ||
| 76 | return QString(QObject::tr("[unused]")); | ||
| 77 | } | ||
| 78 | |||
| 79 | QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str()); | ||
| 80 | if (dir == "left" || dir == "right") { | ||
| 81 | text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_x", "").c_str()); | ||
| 82 | } else if (dir == "up" || dir == "down") { | ||
| 83 | text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_y", "").c_str()); | ||
| 84 | } | ||
| 85 | return text; | ||
| 86 | } else { | ||
| 87 | return QObject::tr("[unknown]"); | ||
| 88 | } | ||
| 89 | }; | ||
| 90 | |||
| 49 | ConfigureInput::ConfigureInput(QWidget* parent) | 91 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 50 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), | 92 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), |
| 51 | timer(std::make_unique<QTimer>()) { | 93 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { |
| 52 | 94 | ||
| 53 | ui->setupUi(this); | 95 | ui->setupUi(this); |
| 54 | setFocusPolicy(Qt::ClickFocus); | 96 | setFocusPolicy(Qt::ClickFocus); |
| 55 | 97 | ||
| 56 | button_map = { | 98 | button_map = { |
| 57 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, | 99 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, |
| 58 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, | 100 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, |
| 59 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, | 101 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, |
| 60 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, | 102 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, |
| 61 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, | 103 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, |
| 62 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, | 104 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, |
| 63 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, | 105 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, |
| 64 | }; | 106 | }; |
| 65 | 107 | ||
| 66 | analog_map = {{ | 108 | analog_map_buttons = {{ |
| 67 | { | 109 | { |
| 68 | ui->buttonLStickUp, ui->buttonLStickDown, ui->buttonLStickLeft, ui->buttonLStickRight, | 110 | ui->buttonLStickUp, ui->buttonLStickDown, ui->buttonLStickLeft, ui->buttonLStickRight, |
| 69 | ui->buttonLStickMod, | 111 | ui->buttonLStickMod, |
| @@ -74,35 +116,57 @@ ConfigureInput::ConfigureInput(QWidget* parent) | |||
| 74 | }, | 116 | }, |
| 75 | }}; | 117 | }}; |
| 76 | 118 | ||
| 119 | analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; | ||
| 120 | |||
| 77 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 121 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { |
| 78 | if (button_map[button_id]) | 122 | if (button_map[button_id]) |
| 79 | connect(button_map[button_id], &QPushButton::released, [=]() { | 123 | connect(button_map[button_id], &QPushButton::released, [=]() { |
| 80 | handleClick(button_map[button_id], | 124 | handleClick( |
| 81 | [=](int key) { SetButtonKey(key, buttons_param[button_id]); }); | 125 | button_map[button_id], |
| 126 | [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, | ||
| 127 | InputCommon::Polling::DeviceType::Button); | ||
| 82 | }); | 128 | }); |
| 83 | } | 129 | } |
| 84 | 130 | ||
| 85 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 131 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { |
| 86 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 132 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { |
| 87 | if (analog_map[analog_id][sub_button_id] != nullptr) { | 133 | if (analog_map_buttons[analog_id][sub_button_id] != nullptr) { |
| 88 | connect(analog_map[analog_id][sub_button_id], &QPushButton::released, [=]() { | 134 | connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, |
| 89 | handleClick(analog_map[analog_id][sub_button_id], [=](int key) { | 135 | [=]() { |
| 90 | SetAnalogKey(key, analogs_param[analog_id], | 136 | handleClick(analog_map_buttons[analog_id][sub_button_id], |
| 91 | analog_sub_buttons[sub_button_id]); | 137 | [=](const Common::ParamPackage& params) { |
| 92 | }); | 138 | SetAnalogButton(params, analogs_param[analog_id], |
| 93 | }); | 139 | analog_sub_buttons[sub_button_id]); |
| 140 | }, | ||
| 141 | InputCommon::Polling::DeviceType::Button); | ||
| 142 | }); | ||
| 94 | } | 143 | } |
| 95 | } | 144 | } |
| 145 | connect(analog_map_stick[analog_id], &QPushButton::released, [=]() { | ||
| 146 | QMessageBox::information( | ||
| 147 | this, "Information", | ||
| 148 | "After pressing OK, first move your joystick horizontally, and then vertically."); | ||
| 149 | handleClick( | ||
| 150 | analog_map_stick[analog_id], | ||
| 151 | [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, | ||
| 152 | InputCommon::Polling::DeviceType::Analog); | ||
| 153 | }); | ||
| 96 | } | 154 | } |
| 97 | 155 | ||
| 98 | connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); | 156 | connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); |
| 99 | 157 | ||
| 100 | timer->setSingleShot(true); | 158 | timeout_timer->setSingleShot(true); |
| 101 | connect(timer.get(), &QTimer::timeout, [this]() { | 159 | connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); |
| 102 | releaseKeyboard(); | 160 | |
| 103 | releaseMouse(); | 161 | connect(poll_timer.get(), &QTimer::timeout, [this]() { |
| 104 | key_setter = boost::none; | 162 | Common::ParamPackage params; |
| 105 | updateButtonLabels(); | 163 | for (auto& poller : device_pollers) { |
| 164 | params = poller->GetNextInput(); | ||
| 165 | if (params.Has("engine")) { | ||
| 166 | setPollingResult(params, false); | ||
| 167 | return; | ||
| 168 | } | ||
| 169 | } | ||
| 106 | }); | 170 | }); |
| 107 | 171 | ||
| 108 | this->loadConfiguration(); | 172 | this->loadConfiguration(); |
| @@ -132,13 +196,15 @@ void ConfigureInput::loadConfiguration() { | |||
| 132 | 196 | ||
| 133 | void ConfigureInput::restoreDefaults() { | 197 | void ConfigureInput::restoreDefaults() { |
| 134 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { | 198 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { |
| 135 | SetButtonKey(Config::default_buttons[button_id], buttons_param[button_id]); | 199 | buttons_param[button_id] = Common::ParamPackage{ |
| 200 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | ||
| 136 | } | 201 | } |
| 137 | 202 | ||
| 138 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 203 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { |
| 139 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | 204 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { |
| 140 | SetAnalogKey(Config::default_analogs[analog_id][sub_button_id], | 205 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( |
| 141 | analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | 206 | Config::default_analogs[analog_id][sub_button_id])}; |
| 207 | SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | ||
| 142 | } | 208 | } |
| 143 | } | 209 | } |
| 144 | updateButtonLabels(); | 210 | updateButtonLabels(); |
| @@ -146,59 +212,73 @@ void ConfigureInput::restoreDefaults() { | |||
| 146 | } | 212 | } |
| 147 | 213 | ||
| 148 | void ConfigureInput::updateButtonLabels() { | 214 | void ConfigureInput::updateButtonLabels() { |
| 149 | QString non_keyboard(tr("[non-keyboard]")); | ||
| 150 | |||
| 151 | auto KeyToText = [&non_keyboard](const Common::ParamPackage& param) { | ||
| 152 | if (param.Get("engine", "") != "keyboard") { | ||
| 153 | return non_keyboard; | ||
| 154 | } else { | ||
| 155 | return getKeyName(param.Get("code", 0)); | ||
| 156 | } | ||
| 157 | }; | ||
| 158 | |||
| 159 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { | 215 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { |
| 160 | button_map[button]->setText(KeyToText(buttons_param[button])); | 216 | button_map[button]->setText(ButtonToText(buttons_param[button])); |
| 161 | } | 217 | } |
| 162 | 218 | ||
| 163 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 219 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { |
| 164 | if (analogs_param[analog_id].Get("engine", "") != "analog_from_button") { | 220 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { |
| 165 | for (QPushButton* button : analog_map[analog_id]) { | 221 | if (analog_map_buttons[analog_id][sub_button_id]) { |
| 166 | if (button) | 222 | analog_map_buttons[analog_id][sub_button_id]->setText( |
| 167 | button->setText(non_keyboard); | 223 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); |
| 168 | } | ||
| 169 | } else { | ||
| 170 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | ||
| 171 | Common::ParamPackage param( | ||
| 172 | analogs_param[analog_id].Get(analog_sub_buttons[sub_button_id], "")); | ||
| 173 | if (analog_map[analog_id][sub_button_id]) | ||
| 174 | analog_map[analog_id][sub_button_id]->setText(KeyToText(param)); | ||
| 175 | } | 224 | } |
| 176 | } | 225 | } |
| 226 | analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); | ||
| 177 | } | 227 | } |
| 178 | } | 228 | } |
| 179 | 229 | ||
| 180 | void ConfigureInput::handleClick(QPushButton* button, std::function<void(int)> new_key_setter) { | 230 | void ConfigureInput::handleClick(QPushButton* button, |
| 231 | std::function<void(const Common::ParamPackage&)> new_input_setter, | ||
| 232 | InputCommon::Polling::DeviceType type) { | ||
| 181 | button->setText(tr("[press key]")); | 233 | button->setText(tr("[press key]")); |
| 182 | button->setFocus(); | 234 | button->setFocus(); |
| 183 | 235 | ||
| 184 | key_setter = new_key_setter; | 236 | input_setter = new_input_setter; |
| 237 | |||
| 238 | device_pollers = InputCommon::Polling::GetPollers(type); | ||
| 239 | |||
| 240 | // Keyboard keys can only be used as button devices | ||
| 241 | want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; | ||
| 242 | |||
| 243 | for (auto& poller : device_pollers) { | ||
| 244 | poller->Start(); | ||
| 245 | } | ||
| 185 | 246 | ||
| 186 | grabKeyboard(); | 247 | grabKeyboard(); |
| 187 | grabMouse(); | 248 | grabMouse(); |
| 188 | timer->start(5000); // Cancel after 5 seconds | 249 | timeout_timer->start(5000); // Cancel after 5 seconds |
| 250 | poll_timer->start(200); // Check for new inputs every 200ms | ||
| 189 | } | 251 | } |
| 190 | 252 | ||
| 191 | void ConfigureInput::keyPressEvent(QKeyEvent* event) { | 253 | void ConfigureInput::setPollingResult(const Common::ParamPackage& params, bool abort) { |
| 192 | releaseKeyboard(); | 254 | releaseKeyboard(); |
| 193 | releaseMouse(); | 255 | releaseMouse(); |
| 256 | timeout_timer->stop(); | ||
| 257 | poll_timer->stop(); | ||
| 258 | for (auto& poller : device_pollers) { | ||
| 259 | poller->Stop(); | ||
| 260 | } | ||
| 194 | 261 | ||
| 195 | if (!key_setter || !event) | 262 | if (!abort) { |
| 196 | return; | 263 | (*input_setter)(params); |
| 197 | 264 | } | |
| 198 | if (event->key() != Qt::Key_Escape) | ||
| 199 | (*key_setter)(event->key()); | ||
| 200 | 265 | ||
| 201 | updateButtonLabels(); | 266 | updateButtonLabels(); |
| 202 | key_setter = boost::none; | 267 | input_setter = boost::none; |
| 203 | timer->stop(); | 268 | } |
| 269 | |||
| 270 | void ConfigureInput::keyPressEvent(QKeyEvent* event) { | ||
| 271 | if (!input_setter || !event) | ||
| 272 | return; | ||
| 273 | |||
| 274 | if (event->key() != Qt::Key_Escape) { | ||
| 275 | if (want_keyboard_keys) { | ||
| 276 | setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, | ||
| 277 | false); | ||
| 278 | } else { | ||
| 279 | // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling | ||
| 280 | return; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | setPollingResult({}, true); | ||
| 204 | } | 284 | } |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index c950fbcb4..a0bef86d5 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -8,11 +8,13 @@ | |||
| 8 | #include <functional> | 8 | #include <functional> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | #include <string> | 10 | #include <string> |
| 11 | #include <unordered_map> | ||
| 11 | #include <QKeyEvent> | 12 | #include <QKeyEvent> |
| 12 | #include <QWidget> | 13 | #include <QWidget> |
| 13 | #include <boost/optional.hpp> | 14 | #include <boost/optional.hpp> |
| 14 | #include "common/param_package.h" | 15 | #include "common/param_package.h" |
| 15 | #include "core/settings.h" | 16 | #include "core/settings.h" |
| 17 | #include "input_common/main.h" | ||
| 16 | #include "ui_configure_input.h" | 18 | #include "ui_configure_input.h" |
| 17 | 19 | ||
| 18 | class QPushButton; | 20 | class QPushButton; |
| @@ -35,10 +37,11 @@ public: | |||
| 35 | private: | 37 | private: |
| 36 | std::unique_ptr<Ui::ConfigureInput> ui; | 38 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 37 | 39 | ||
| 38 | std::unique_ptr<QTimer> timer; | 40 | std::unique_ptr<QTimer> timeout_timer; |
| 41 | std::unique_ptr<QTimer> poll_timer; | ||
| 39 | 42 | ||
| 40 | /// This will be the the setting function when an input is awaiting configuration. | 43 | /// This will be the the setting function when an input is awaiting configuration. |
| 41 | boost::optional<std::function<void(int)>> key_setter; | 44 | boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter; |
| 42 | 45 | ||
| 43 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; | 46 | std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param; |
| 44 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; | 47 | std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param; |
| @@ -48,13 +51,23 @@ private: | |||
| 48 | /// Each button input is represented by a QPushButton. | 51 | /// Each button input is represented by a QPushButton. |
| 49 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; | 52 | std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map; |
| 50 | 53 | ||
| 51 | /// Each analog input is represented by five QPushButtons which represents up, down, left, right | 54 | /// A group of five QPushButtons represent one analog input. The buttons each represent up, |
| 52 | /// and modifier | 55 | /// down, left, right, and modifier, respectively. |
| 53 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> | 56 | std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs> |
| 54 | analog_map; | 57 | analog_map_buttons; |
| 58 | |||
| 59 | /// Analog inputs are also represented each with a single button, used to configure with an | ||
| 60 | /// actual analog stick | ||
| 61 | std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_stick; | ||
| 55 | 62 | ||
| 56 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; | 63 | static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons; |
| 57 | 64 | ||
| 65 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; | ||
| 66 | |||
| 67 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | ||
| 68 | /// keyboard events are ignored. | ||
| 69 | bool want_keyboard_keys = false; | ||
| 70 | |||
| 58 | /// Load configuration settings. | 71 | /// Load configuration settings. |
| 59 | void loadConfiguration(); | 72 | void loadConfiguration(); |
| 60 | /// Restore all buttons to their default values. | 73 | /// Restore all buttons to their default values. |
| @@ -63,7 +76,13 @@ private: | |||
| 63 | void updateButtonLabels(); | 76 | void updateButtonLabels(); |
| 64 | 77 | ||
| 65 | /// Called when the button was pressed. | 78 | /// Called when the button was pressed. |
| 66 | void handleClick(QPushButton* button, std::function<void(int)> new_key_setter); | 79 | void handleClick(QPushButton* button, |
| 80 | std::function<void(const Common::ParamPackage&)> new_input_setter, | ||
| 81 | InputCommon::Polling::DeviceType type); | ||
| 82 | |||
| 83 | /// Finish polling and configure input using the input_setter | ||
| 84 | void setPollingResult(const Common::ParamPackage& params, bool abort); | ||
| 85 | |||
| 67 | /// Handle key press events. | 86 | /// Handle key press events. |
| 68 | void keyPressEvent(QKeyEvent* event) override; | 87 | void keyPressEvent(QKeyEvent* event) override; |
| 69 | }; | 88 | }; |
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 5143c9d72..c162ca02c 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>343</width> | 9 | <width>343</width> |
| 10 | <height>665</height> | 10 | <height>677</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| @@ -16,10 +16,10 @@ | |||
| 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_5"> |
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QGridLayout" name="gridLayout_7"> | 18 | <layout class="QGridLayout" name="gridLayout_7"> |
| 19 | <item row="0" column="0"> | 19 | <item row="3" column="1"> |
| 20 | <widget class="QGroupBox" name="faceButtons"> | 20 | <widget class="QGroupBox" name="faceButtons_6"> |
| 21 | <property name="title"> | 21 | <property name="title"> |
| 22 | <string>Face Buttons</string> | 22 | <string>Misc.</string> |
| 23 | </property> | 23 | </property> |
| 24 | <property name="flat"> | 24 | <property name="flat"> |
| 25 | <bool>false</bool> | 25 | <bool>false</bool> |
| @@ -27,18 +27,18 @@ | |||
| 27 | <property name="checkable"> | 27 | <property name="checkable"> |
| 28 | <bool>false</bool> | 28 | <bool>false</bool> |
| 29 | </property> | 29 | </property> |
| 30 | <layout class="QGridLayout" name="gridLayout"> | 30 | <layout class="QGridLayout" name="gridLayout_6"> |
| 31 | <item row="0" column="0"> | 31 | <item row="0" column="0"> |
| 32 | <layout class="QVBoxLayout" name="verticalLayout"> | 32 | <layout class="QVBoxLayout" name="verticalLayout_25"> |
| 33 | <item> | 33 | <item> |
| 34 | <widget class="QLabel" name="label"> | 34 | <widget class="QLabel" name="label_29"> |
| 35 | <property name="text"> | 35 | <property name="text"> |
| 36 | <string>A:</string> | 36 | <string>Plus:</string> |
| 37 | </property> | 37 | </property> |
| 38 | </widget> | 38 | </widget> |
| 39 | </item> | 39 | </item> |
| 40 | <item> | 40 | <item> |
| 41 | <widget class="QPushButton" name="buttonA"> | 41 | <widget class="QPushButton" name="buttonPlus"> |
| 42 | <property name="text"> | 42 | <property name="text"> |
| 43 | <string/> | 43 | <string/> |
| 44 | </property> | 44 | </property> |
| @@ -47,16 +47,16 @@ | |||
| 47 | </layout> | 47 | </layout> |
| 48 | </item> | 48 | </item> |
| 49 | <item row="0" column="1"> | 49 | <item row="0" column="1"> |
| 50 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 50 | <layout class="QVBoxLayout" name="verticalLayout_26"> |
| 51 | <item> | 51 | <item> |
| 52 | <widget class="QLabel" name="label_2"> | 52 | <widget class="QLabel" name="label_30"> |
| 53 | <property name="text"> | 53 | <property name="text"> |
| 54 | <string>B:</string> | 54 | <string>Minus:</string> |
| 55 | </property> | 55 | </property> |
| 56 | </widget> | 56 | </widget> |
| 57 | </item> | 57 | </item> |
| 58 | <item> | 58 | <item> |
| 59 | <widget class="QPushButton" name="buttonB"> | 59 | <widget class="QPushButton" name="buttonMinus"> |
| 60 | <property name="text"> | 60 | <property name="text"> |
| 61 | <string/> | 61 | <string/> |
| 62 | </property> | 62 | </property> |
| @@ -65,16 +65,16 @@ | |||
| 65 | </layout> | 65 | </layout> |
| 66 | </item> | 66 | </item> |
| 67 | <item row="1" column="0"> | 67 | <item row="1" column="0"> |
| 68 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 68 | <layout class="QVBoxLayout" name="verticalLayout_27"> |
| 69 | <item> | 69 | <item> |
| 70 | <widget class="QLabel" name="label_3"> | 70 | <widget class="QLabel" name="label_31"> |
| 71 | <property name="text"> | 71 | <property name="text"> |
| 72 | <string>X:</string> | 72 | <string>Home:</string> |
| 73 | </property> | 73 | </property> |
| 74 | </widget> | 74 | </widget> |
| 75 | </item> | 75 | </item> |
| 76 | <item> | 76 | <item> |
| 77 | <widget class="QPushButton" name="buttonX"> | 77 | <widget class="QPushButton" name="buttonHome"> |
| 78 | <property name="text"> | 78 | <property name="text"> |
| 79 | <string/> | 79 | <string/> |
| 80 | </property> | 80 | </property> |
| @@ -83,16 +83,17 @@ | |||
| 83 | </layout> | 83 | </layout> |
| 84 | </item> | 84 | </item> |
| 85 | <item row="1" column="1"> | 85 | <item row="1" column="1"> |
| 86 | <layout class="QVBoxLayout" name="verticalLayout_4"> | 86 | <layout class="QVBoxLayout" name="verticalLayout_28"> |
| 87 | <item> | 87 | <item> |
| 88 | <widget class="QLabel" name="label_4"> | 88 | <widget class="QLabel" name="label_11"> |
| 89 | <property name="text"> | 89 | <property name="text"> |
| 90 | <string>Y:</string> | 90 | <string>Screen |
| 91 | Capture:</string> | ||
| 91 | </property> | 92 | </property> |
| 92 | </widget> | 93 | </widget> |
| 93 | </item> | 94 | </item> |
| 94 | <item> | 95 | <item> |
| 95 | <widget class="QPushButton" name="buttonY"> | 96 | <widget class="QPushButton" name="buttonScreenshot"> |
| 96 | <property name="text"> | 97 | <property name="text"> |
| 97 | <string/> | 98 | <string/> |
| 98 | </property> | 99 | </property> |
| @@ -100,13 +101,26 @@ | |||
| 100 | </item> | 101 | </item> |
| 101 | </layout> | 102 | </layout> |
| 102 | </item> | 103 | </item> |
| 104 | <item row="2" column="1"> | ||
| 105 | <spacer name="verticalSpacer"> | ||
| 106 | <property name="orientation"> | ||
| 107 | <enum>Qt::Vertical</enum> | ||
| 108 | </property> | ||
| 109 | <property name="sizeHint" stdset="0"> | ||
| 110 | <size> | ||
| 111 | <width>20</width> | ||
| 112 | <height>40</height> | ||
| 113 | </size> | ||
| 114 | </property> | ||
| 115 | </spacer> | ||
| 116 | </item> | ||
| 103 | </layout> | 117 | </layout> |
| 104 | </widget> | 118 | </widget> |
| 105 | </item> | 119 | </item> |
| 106 | <item row="0" column="1"> | 120 | <item row="0" column="0"> |
| 107 | <widget class="QGroupBox" name="faceButtons_2"> | 121 | <widget class="QGroupBox" name="faceButtons"> |
| 108 | <property name="title"> | 122 | <property name="title"> |
| 109 | <string>Directional Pad</string> | 123 | <string>Face Buttons</string> |
| 110 | </property> | 124 | </property> |
| 111 | <property name="flat"> | 125 | <property name="flat"> |
| 112 | <bool>false</bool> | 126 | <bool>false</bool> |
| @@ -114,18 +128,18 @@ | |||
| 114 | <property name="checkable"> | 128 | <property name="checkable"> |
| 115 | <bool>false</bool> | 129 | <bool>false</bool> |
| 116 | </property> | 130 | </property> |
| 117 | <layout class="QGridLayout" name="gridLayout_2"> | 131 | <layout class="QGridLayout" name="gridLayout"> |
| 118 | <item row="1" column="0"> | 132 | <item row="0" column="0"> |
| 119 | <layout class="QVBoxLayout" name="verticalLayout_12"> | 133 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 120 | <item> | 134 | <item> |
| 121 | <widget class="QLabel" name="label_34"> | 135 | <widget class="QLabel" name="label"> |
| 122 | <property name="text"> | 136 | <property name="text"> |
| 123 | <string>Up:</string> | 137 | <string>A:</string> |
| 124 | </property> | 138 | </property> |
| 125 | </widget> | 139 | </widget> |
| 126 | </item> | 140 | </item> |
| 127 | <item> | 141 | <item> |
| 128 | <widget class="QPushButton" name="buttonDpadUp"> | 142 | <widget class="QPushButton" name="buttonA"> |
| 129 | <property name="text"> | 143 | <property name="text"> |
| 130 | <string/> | 144 | <string/> |
| 131 | </property> | 145 | </property> |
| @@ -133,17 +147,17 @@ | |||
| 133 | </item> | 147 | </item> |
| 134 | </layout> | 148 | </layout> |
| 135 | </item> | 149 | </item> |
| 136 | <item row="1" column="1"> | 150 | <item row="0" column="1"> |
| 137 | <layout class="QVBoxLayout" name="verticalLayout_9"> | 151 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 138 | <item> | 152 | <item> |
| 139 | <widget class="QLabel" name="label_35"> | 153 | <widget class="QLabel" name="label_2"> |
| 140 | <property name="text"> | 154 | <property name="text"> |
| 141 | <string>Down:</string> | 155 | <string>B:</string> |
| 142 | </property> | 156 | </property> |
| 143 | </widget> | 157 | </widget> |
| 144 | </item> | 158 | </item> |
| 145 | <item> | 159 | <item> |
| 146 | <widget class="QPushButton" name="buttonDpadDown"> | 160 | <widget class="QPushButton" name="buttonB"> |
| 147 | <property name="text"> | 161 | <property name="text"> |
| 148 | <string/> | 162 | <string/> |
| 149 | </property> | 163 | </property> |
| @@ -151,17 +165,17 @@ | |||
| 151 | </item> | 165 | </item> |
| 152 | </layout> | 166 | </layout> |
| 153 | </item> | 167 | </item> |
| 154 | <item row="0" column="0"> | 168 | <item row="1" column="0"> |
| 155 | <layout class="QVBoxLayout" name="verticalLayout_10"> | 169 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 156 | <item> | 170 | <item> |
| 157 | <widget class="QLabel" name="label_32"> | 171 | <widget class="QLabel" name="label_3"> |
| 158 | <property name="text"> | 172 | <property name="text"> |
| 159 | <string>Left:</string> | 173 | <string>X:</string> |
| 160 | </property> | 174 | </property> |
| 161 | </widget> | 175 | </widget> |
| 162 | </item> | 176 | </item> |
| 163 | <item> | 177 | <item> |
| 164 | <widget class="QPushButton" name="buttonDpadLeft"> | 178 | <widget class="QPushButton" name="buttonX"> |
| 165 | <property name="text"> | 179 | <property name="text"> |
| 166 | <string/> | 180 | <string/> |
| 167 | </property> | 181 | </property> |
| @@ -169,17 +183,17 @@ | |||
| 169 | </item> | 183 | </item> |
| 170 | </layout> | 184 | </layout> |
| 171 | </item> | 185 | </item> |
| 172 | <item row="0" column="1"> | 186 | <item row="1" column="1"> |
| 173 | <layout class="QVBoxLayout" name="verticalLayout_11"> | 187 | <layout class="QVBoxLayout" name="verticalLayout_4"> |
| 174 | <item> | 188 | <item> |
| 175 | <widget class="QLabel" name="label_33"> | 189 | <widget class="QLabel" name="label_4"> |
| 176 | <property name="text"> | 190 | <property name="text"> |
| 177 | <string>Right:</string> | 191 | <string>Y:</string> |
| 178 | </property> | 192 | </property> |
| 179 | </widget> | 193 | </widget> |
| 180 | </item> | 194 | </item> |
| 181 | <item> | 195 | <item> |
| 182 | <widget class="QPushButton" name="buttonDpadRight"> | 196 | <widget class="QPushButton" name="buttonY"> |
| 183 | <property name="text"> | 197 | <property name="text"> |
| 184 | <string/> | 198 | <string/> |
| 185 | </property> | 199 | </property> |
| @@ -190,10 +204,10 @@ | |||
| 190 | </layout> | 204 | </layout> |
| 191 | </widget> | 205 | </widget> |
| 192 | </item> | 206 | </item> |
| 193 | <item row="3" column="1"> | 207 | <item row="0" column="1"> |
| 194 | <widget class="QGroupBox" name="faceButtons_6"> | 208 | <widget class="QGroupBox" name="faceButtons_2"> |
| 195 | <property name="title"> | 209 | <property name="title"> |
| 196 | <string>Misc.</string> | 210 | <string>Directional Pad</string> |
| 197 | </property> | 211 | </property> |
| 198 | <property name="flat"> | 212 | <property name="flat"> |
| 199 | <bool>false</bool> | 213 | <bool>false</bool> |
| @@ -201,18 +215,18 @@ | |||
| 201 | <property name="checkable"> | 215 | <property name="checkable"> |
| 202 | <bool>false</bool> | 216 | <bool>false</bool> |
| 203 | </property> | 217 | </property> |
| 204 | <layout class="QGridLayout" name="gridLayout_6"> | 218 | <layout class="QGridLayout" name="gridLayout_2"> |
| 205 | <item row="0" column="0"> | 219 | <item row="1" column="0"> |
| 206 | <layout class="QVBoxLayout" name="verticalLayout_25"> | 220 | <layout class="QVBoxLayout" name="verticalLayout_12"> |
| 207 | <item> | 221 | <item> |
| 208 | <widget class="QLabel" name="label_29"> | 222 | <widget class="QLabel" name="label_34"> |
| 209 | <property name="text"> | 223 | <property name="text"> |
| 210 | <string>Plus:</string> | 224 | <string>Up:</string> |
| 211 | </property> | 225 | </property> |
| 212 | </widget> | 226 | </widget> |
| 213 | </item> | 227 | </item> |
| 214 | <item> | 228 | <item> |
| 215 | <widget class="QPushButton" name="buttonPlus"> | 229 | <widget class="QPushButton" name="buttonDpadUp"> |
| 216 | <property name="text"> | 230 | <property name="text"> |
| 217 | <string/> | 231 | <string/> |
| 218 | </property> | 232 | </property> |
| @@ -220,17 +234,17 @@ | |||
| 220 | </item> | 234 | </item> |
| 221 | </layout> | 235 | </layout> |
| 222 | </item> | 236 | </item> |
| 223 | <item row="0" column="1"> | 237 | <item row="1" column="1"> |
| 224 | <layout class="QVBoxLayout" name="verticalLayout_26"> | 238 | <layout class="QVBoxLayout" name="verticalLayout_9"> |
| 225 | <item> | 239 | <item> |
| 226 | <widget class="QLabel" name="label_30"> | 240 | <widget class="QLabel" name="label_35"> |
| 227 | <property name="text"> | 241 | <property name="text"> |
| 228 | <string>Minus:</string> | 242 | <string>Down:</string> |
| 229 | </property> | 243 | </property> |
| 230 | </widget> | 244 | </widget> |
| 231 | </item> | 245 | </item> |
| 232 | <item> | 246 | <item> |
| 233 | <widget class="QPushButton" name="buttonMinus"> | 247 | <widget class="QPushButton" name="buttonDpadDown"> |
| 234 | <property name="text"> | 248 | <property name="text"> |
| 235 | <string/> | 249 | <string/> |
| 236 | </property> | 250 | </property> |
| @@ -238,17 +252,17 @@ | |||
| 238 | </item> | 252 | </item> |
| 239 | </layout> | 253 | </layout> |
| 240 | </item> | 254 | </item> |
| 241 | <item row="1" column="0"> | 255 | <item row="0" column="0"> |
| 242 | <layout class="QVBoxLayout" name="verticalLayout_27"> | 256 | <layout class="QVBoxLayout" name="verticalLayout_10"> |
| 243 | <item> | 257 | <item> |
| 244 | <widget class="QLabel" name="label_31"> | 258 | <widget class="QLabel" name="label_32"> |
| 245 | <property name="text"> | 259 | <property name="text"> |
| 246 | <string>Home:</string> | 260 | <string>Left:</string> |
| 247 | </property> | 261 | </property> |
| 248 | </widget> | 262 | </widget> |
| 249 | </item> | 263 | </item> |
| 250 | <item> | 264 | <item> |
| 251 | <widget class="QPushButton" name="buttonHome"> | 265 | <widget class="QPushButton" name="buttonDpadLeft"> |
| 252 | <property name="text"> | 266 | <property name="text"> |
| 253 | <string/> | 267 | <string/> |
| 254 | </property> | 268 | </property> |
| @@ -256,18 +270,17 @@ | |||
| 256 | </item> | 270 | </item> |
| 257 | </layout> | 271 | </layout> |
| 258 | </item> | 272 | </item> |
| 259 | <item row="1" column="1"> | 273 | <item row="0" column="1"> |
| 260 | <layout class="QVBoxLayout" name="verticalLayout_28"> | 274 | <layout class="QVBoxLayout" name="verticalLayout_11"> |
| 261 | <item> | 275 | <item> |
| 262 | <widget class="QLabel" name="label_11"> | 276 | <widget class="QLabel" name="label_33"> |
| 263 | <property name="text"> | 277 | <property name="text"> |
| 264 | <string>Screen | 278 | <string>Right:</string> |
| 265 | Capture:</string> | ||
| 266 | </property> | 279 | </property> |
| 267 | </widget> | 280 | </widget> |
| 268 | </item> | 281 | </item> |
| 269 | <item> | 282 | <item> |
| 270 | <widget class="QPushButton" name="buttonScreenshot"> | 283 | <widget class="QPushButton" name="buttonDpadRight"> |
| 271 | <property name="text"> | 284 | <property name="text"> |
| 272 | <string/> | 285 | <string/> |
| 273 | </property> | 286 | </property> |
| @@ -275,19 +288,6 @@ Capture:</string> | |||
| 275 | </item> | 288 | </item> |
| 276 | </layout> | 289 | </layout> |
| 277 | </item> | 290 | </item> |
| 278 | <item row="2" column="1"> | ||
| 279 | <spacer name="verticalSpacer"> | ||
| 280 | <property name="orientation"> | ||
| 281 | <enum>Qt::Vertical</enum> | ||
| 282 | </property> | ||
| 283 | <property name="sizeHint" stdset="0"> | ||
| 284 | <size> | ||
| 285 | <width>20</width> | ||
| 286 | <height>40</height> | ||
| 287 | </size> | ||
| 288 | </property> | ||
| 289 | </spacer> | ||
| 290 | </item> | ||
| 291 | </layout> | 291 | </layout> |
| 292 | </widget> | 292 | </widget> |
| 293 | </item> | 293 | </item> |
| @@ -414,10 +414,13 @@ Capture:</string> | |||
| 414 | </layout> | 414 | </layout> |
| 415 | </widget> | 415 | </widget> |
| 416 | </item> | 416 | </item> |
| 417 | <item row="1" column="0"> | 417 | <item row="1" column="1"> |
| 418 | <widget class="QGroupBox" name="faceButtons_4"> | 418 | <widget class="QGroupBox" name="faceButtons_5"> |
| 419 | <property name="title"> | 419 | <property name="title"> |
| 420 | <string>Left Stick</string> | 420 | <string>Right Stick</string> |
| 421 | </property> | ||
| 422 | <property name="alignment"> | ||
| 423 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
| 421 | </property> | 424 | </property> |
| 422 | <property name="flat"> | 425 | <property name="flat"> |
| 423 | <bool>false</bool> | 426 | <bool>false</bool> |
| @@ -425,18 +428,18 @@ Capture:</string> | |||
| 425 | <property name="checkable"> | 428 | <property name="checkable"> |
| 426 | <bool>false</bool> | 429 | <bool>false</bool> |
| 427 | </property> | 430 | </property> |
| 428 | <layout class="QGridLayout" name="gridLayout_4"> | 431 | <layout class="QGridLayout" name="gridLayout_5"> |
| 429 | <item row="0" column="0"> | 432 | <item row="1" column="1"> |
| 430 | <layout class="QVBoxLayout" name="verticalLayout_17"> | 433 | <layout class="QVBoxLayout" name="verticalLayout_24"> |
| 431 | <item> | 434 | <item> |
| 432 | <widget class="QLabel" name="label_21"> | 435 | <widget class="QLabel" name="label_26"> |
| 433 | <property name="text"> | 436 | <property name="text"> |
| 434 | <string>Left:</string> | 437 | <string>Down:</string> |
| 435 | </property> | 438 | </property> |
| 436 | </widget> | 439 | </widget> |
| 437 | </item> | 440 | </item> |
| 438 | <item> | 441 | <item> |
| 439 | <widget class="QPushButton" name="buttonLStickLeft"> | 442 | <widget class="QPushButton" name="buttonRStickDown"> |
| 440 | <property name="text"> | 443 | <property name="text"> |
| 441 | <string/> | 444 | <string/> |
| 442 | </property> | 445 | </property> |
| @@ -445,16 +448,16 @@ Capture:</string> | |||
| 445 | </layout> | 448 | </layout> |
| 446 | </item> | 449 | </item> |
| 447 | <item row="0" column="1"> | 450 | <item row="0" column="1"> |
| 448 | <layout class="QVBoxLayout" name="verticalLayout_18"> | 451 | <layout class="QVBoxLayout" name="verticalLayout_22"> |
| 449 | <item> | 452 | <item> |
| 450 | <widget class="QLabel" name="label_23"> | 453 | <widget class="QLabel" name="label_27"> |
| 451 | <property name="text"> | 454 | <property name="text"> |
| 452 | <string>Right:</string> | 455 | <string>Right:</string> |
| 453 | </property> | 456 | </property> |
| 454 | </widget> | 457 | </widget> |
| 455 | </item> | 458 | </item> |
| 456 | <item> | 459 | <item> |
| 457 | <widget class="QPushButton" name="buttonLStickRight"> | 460 | <widget class="QPushButton" name="buttonRStickRight"> |
| 458 | <property name="text"> | 461 | <property name="text"> |
| 459 | <string/> | 462 | <string/> |
| 460 | </property> | 463 | </property> |
| @@ -462,17 +465,24 @@ Capture:</string> | |||
| 462 | </item> | 465 | </item> |
| 463 | </layout> | 466 | </layout> |
| 464 | </item> | 467 | </item> |
| 468 | <item row="3" column="0" colspan="2"> | ||
| 469 | <widget class="QPushButton" name="buttonRStickAnalog"> | ||
| 470 | <property name="text"> | ||
| 471 | <string>Set Analog Stick</string> | ||
| 472 | </property> | ||
| 473 | </widget> | ||
| 474 | </item> | ||
| 465 | <item row="1" column="0"> | 475 | <item row="1" column="0"> |
| 466 | <layout class="QVBoxLayout" name="verticalLayout_19"> | 476 | <layout class="QVBoxLayout" name="verticalLayout_21"> |
| 467 | <item> | 477 | <item> |
| 468 | <widget class="QLabel" name="label_24"> | 478 | <widget class="QLabel" name="label_25"> |
| 469 | <property name="text"> | 479 | <property name="text"> |
| 470 | <string>Up:</string> | 480 | <string>Left:</string> |
| 471 | </property> | 481 | </property> |
| 472 | </widget> | 482 | </widget> |
| 473 | </item> | 483 | </item> |
| 474 | <item> | 484 | <item> |
| 475 | <widget class="QPushButton" name="buttonLStickUp"> | 485 | <widget class="QPushButton" name="buttonRStickLeft"> |
| 476 | <property name="text"> | 486 | <property name="text"> |
| 477 | <string/> | 487 | <string/> |
| 478 | </property> | 488 | </property> |
| @@ -480,17 +490,17 @@ Capture:</string> | |||
| 480 | </item> | 490 | </item> |
| 481 | </layout> | 491 | </layout> |
| 482 | </item> | 492 | </item> |
| 483 | <item row="1" column="1"> | 493 | <item row="0" column="0"> |
| 484 | <layout class="QVBoxLayout" name="verticalLayout_20"> | 494 | <layout class="QVBoxLayout" name="verticalLayout_25"> |
| 485 | <item> | 495 | <item> |
| 486 | <widget class="QLabel" name="label_22"> | 496 | <widget class="QLabel" name="label_28"> |
| 487 | <property name="text"> | 497 | <property name="text"> |
| 488 | <string>Down:</string> | 498 | <string>Up:</string> |
| 489 | </property> | 499 | </property> |
| 490 | </widget> | 500 | </widget> |
| 491 | </item> | 501 | </item> |
| 492 | <item> | 502 | <item> |
| 493 | <widget class="QPushButton" name="buttonLStickDown"> | 503 | <widget class="QPushButton" name="buttonRStickUp"> |
| 494 | <property name="text"> | 504 | <property name="text"> |
| 495 | <string/> | 505 | <string/> |
| 496 | </property> | 506 | </property> |
| @@ -499,16 +509,16 @@ Capture:</string> | |||
| 499 | </layout> | 509 | </layout> |
| 500 | </item> | 510 | </item> |
| 501 | <item row="2" column="0"> | 511 | <item row="2" column="0"> |
| 502 | <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0"> | 512 | <layout class="QVBoxLayout" name="verticalLayout_6"> |
| 503 | <item> | 513 | <item> |
| 504 | <widget class="QLabel" name="label_6"> | 514 | <widget class="QLabel" name="label_5"> |
| 505 | <property name="text"> | 515 | <property name="text"> |
| 506 | <string>Pressed:</string> | 516 | <string>Pressed:</string> |
| 507 | </property> | 517 | </property> |
| 508 | </widget> | 518 | </widget> |
| 509 | </item> | 519 | </item> |
| 510 | <item> | 520 | <item> |
| 511 | <widget class="QPushButton" name="buttonLStick"> | 521 | <widget class="QPushButton" name="buttonRStick"> |
| 512 | <property name="text"> | 522 | <property name="text"> |
| 513 | <string/> | 523 | <string/> |
| 514 | </property> | 524 | </property> |
| @@ -517,16 +527,16 @@ Capture:</string> | |||
| 517 | </layout> | 527 | </layout> |
| 518 | </item> | 528 | </item> |
| 519 | <item row="2" column="1"> | 529 | <item row="2" column="1"> |
| 520 | <layout class="QVBoxLayout" name="verticalLayout_31"> | 530 | <layout class="QVBoxLayout" name="verticalLayout_32"> |
| 521 | <item> | 531 | <item> |
| 522 | <widget class="QLabel" name="label_9"> | 532 | <widget class="QLabel" name="label_10"> |
| 523 | <property name="text"> | 533 | <property name="text"> |
| 524 | <string>Modifier:</string> | 534 | <string>Modifier:</string> |
| 525 | </property> | 535 | </property> |
| 526 | </widget> | 536 | </widget> |
| 527 | </item> | 537 | </item> |
| 528 | <item> | 538 | <item> |
| 529 | <widget class="QPushButton" name="buttonLStickMod"> | 539 | <widget class="QPushButton" name="buttonRStickMod"> |
| 530 | <property name="text"> | 540 | <property name="text"> |
| 531 | <string/> | 541 | <string/> |
| 532 | </property> | 542 | </property> |
| @@ -537,13 +547,10 @@ Capture:</string> | |||
| 537 | </layout> | 547 | </layout> |
| 538 | </widget> | 548 | </widget> |
| 539 | </item> | 549 | </item> |
| 540 | <item row="1" column="1"> | 550 | <item row="1" column="0"> |
| 541 | <widget class="QGroupBox" name="faceButtons_5"> | 551 | <widget class="QGroupBox" name="faceButtons_4"> |
| 542 | <property name="title"> | 552 | <property name="title"> |
| 543 | <string>Right Stick</string> | 553 | <string>Left Stick</string> |
| 544 | </property> | ||
| 545 | <property name="alignment"> | ||
| 546 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
| 547 | </property> | 554 | </property> |
| 548 | <property name="flat"> | 555 | <property name="flat"> |
| 549 | <bool>false</bool> | 556 | <bool>false</bool> |
| @@ -551,18 +558,18 @@ Capture:</string> | |||
| 551 | <property name="checkable"> | 558 | <property name="checkable"> |
| 552 | <bool>false</bool> | 559 | <bool>false</bool> |
| 553 | </property> | 560 | </property> |
| 554 | <layout class="QGridLayout" name="gridLayout_5"> | 561 | <layout class="QGridLayout" name="gridLayout_4"> |
| 555 | <item row="1" column="1"> | 562 | <item row="1" column="1"> |
| 556 | <layout class="QVBoxLayout" name="verticalLayout_24"> | 563 | <layout class="QVBoxLayout" name="verticalLayout_20"> |
| 557 | <item> | 564 | <item> |
| 558 | <widget class="QLabel" name="label_26"> | 565 | <widget class="QLabel" name="label_22"> |
| 559 | <property name="text"> | 566 | <property name="text"> |
| 560 | <string>Down:</string> | 567 | <string>Down:</string> |
| 561 | </property> | 568 | </property> |
| 562 | </widget> | 569 | </widget> |
| 563 | </item> | 570 | </item> |
| 564 | <item> | 571 | <item> |
| 565 | <widget class="QPushButton" name="buttonRStickDown"> | 572 | <widget class="QPushButton" name="buttonLStickDown"> |
| 566 | <property name="text"> | 573 | <property name="text"> |
| 567 | <string/> | 574 | <string/> |
| 568 | </property> | 575 | </property> |
| @@ -570,17 +577,24 @@ Capture:</string> | |||
| 570 | </item> | 577 | </item> |
| 571 | </layout> | 578 | </layout> |
| 572 | </item> | 579 | </item> |
| 580 | <item row="4" column="0" colspan="2"> | ||
| 581 | <widget class="QPushButton" name="buttonLStickAnalog"> | ||
| 582 | <property name="text"> | ||
| 583 | <string>Set Analog Stick</string> | ||
| 584 | </property> | ||
| 585 | </widget> | ||
| 586 | </item> | ||
| 573 | <item row="0" column="1"> | 587 | <item row="0" column="1"> |
| 574 | <layout class="QVBoxLayout" name="verticalLayout_22"> | 588 | <layout class="QVBoxLayout" name="verticalLayout_18"> |
| 575 | <item> | 589 | <item> |
| 576 | <widget class="QLabel" name="label_27"> | 590 | <widget class="QLabel" name="label_23"> |
| 577 | <property name="text"> | 591 | <property name="text"> |
| 578 | <string>Right:</string> | 592 | <string>Right:</string> |
| 579 | </property> | 593 | </property> |
| 580 | </widget> | 594 | </widget> |
| 581 | </item> | 595 | </item> |
| 582 | <item> | 596 | <item> |
| 583 | <widget class="QPushButton" name="buttonRStickRight"> | 597 | <widget class="QPushButton" name="buttonLStickRight"> |
| 584 | <property name="text"> | 598 | <property name="text"> |
| 585 | <string/> | 599 | <string/> |
| 586 | </property> | 600 | </property> |
| @@ -588,17 +602,17 @@ Capture:</string> | |||
| 588 | </item> | 602 | </item> |
| 589 | </layout> | 603 | </layout> |
| 590 | </item> | 604 | </item> |
| 591 | <item row="1" column="0"> | 605 | <item row="0" column="0"> |
| 592 | <layout class="QVBoxLayout" name="verticalLayout_23"> | 606 | <layout class="QVBoxLayout" name="verticalLayout_17"> |
| 593 | <item> | 607 | <item> |
| 594 | <widget class="QLabel" name="label_28"> | 608 | <widget class="QLabel" name="label_21"> |
| 595 | <property name="text"> | 609 | <property name="text"> |
| 596 | <string>Up:</string> | 610 | <string>Left:</string> |
| 597 | </property> | 611 | </property> |
| 598 | </widget> | 612 | </widget> |
| 599 | </item> | 613 | </item> |
| 600 | <item> | 614 | <item> |
| 601 | <widget class="QPushButton" name="buttonRStickUp"> | 615 | <widget class="QPushButton" name="buttonLStickLeft"> |
| 602 | <property name="text"> | 616 | <property name="text"> |
| 603 | <string/> | 617 | <string/> |
| 604 | </property> | 618 | </property> |
| @@ -606,17 +620,17 @@ Capture:</string> | |||
| 606 | </item> | 620 | </item> |
| 607 | </layout> | 621 | </layout> |
| 608 | </item> | 622 | </item> |
| 609 | <item row="0" column="0"> | 623 | <item row="1" column="0"> |
| 610 | <layout class="QVBoxLayout" name="verticalLayout_21"> | 624 | <layout class="QVBoxLayout" name="verticalLayout_19"> |
| 611 | <item> | 625 | <item> |
| 612 | <widget class="QLabel" name="label_25"> | 626 | <widget class="QLabel" name="label_24"> |
| 613 | <property name="text"> | 627 | <property name="text"> |
| 614 | <string>Left:</string> | 628 | <string>Up:</string> |
| 615 | </property> | 629 | </property> |
| 616 | </widget> | 630 | </widget> |
| 617 | </item> | 631 | </item> |
| 618 | <item> | 632 | <item> |
| 619 | <widget class="QPushButton" name="buttonRStickLeft"> | 633 | <widget class="QPushButton" name="buttonLStickUp"> |
| 620 | <property name="text"> | 634 | <property name="text"> |
| 621 | <string/> | 635 | <string/> |
| 622 | </property> | 636 | </property> |
| @@ -624,17 +638,17 @@ Capture:</string> | |||
| 624 | </item> | 638 | </item> |
| 625 | </layout> | 639 | </layout> |
| 626 | </item> | 640 | </item> |
| 627 | <item row="2" column="1"> | 641 | <item row="3" column="0"> |
| 628 | <layout class="QVBoxLayout" name="verticalLayout_32"> | 642 | <layout class="QVBoxLayout" name="verticalLayout_31"> |
| 629 | <item> | 643 | <item> |
| 630 | <widget class="QLabel" name="label_10"> | 644 | <widget class="QLabel" name="label_9"> |
| 631 | <property name="text"> | 645 | <property name="text"> |
| 632 | <string>Modifier:</string> | 646 | <string>Modifier:</string> |
| 633 | </property> | 647 | </property> |
| 634 | </widget> | 648 | </widget> |
| 635 | </item> | 649 | </item> |
| 636 | <item> | 650 | <item> |
| 637 | <widget class="QPushButton" name="buttonRStickMod"> | 651 | <widget class="QPushButton" name="buttonLStickMod"> |
| 638 | <property name="text"> | 652 | <property name="text"> |
| 639 | <string/> | 653 | <string/> |
| 640 | </property> | 654 | </property> |
| @@ -642,17 +656,17 @@ Capture:</string> | |||
| 642 | </item> | 656 | </item> |
| 643 | </layout> | 657 | </layout> |
| 644 | </item> | 658 | </item> |
| 645 | <item row="2" column="0"> | 659 | <item row="3" column="1"> |
| 646 | <layout class="QVBoxLayout" name="verticalLayout_6"> | 660 | <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0"> |
| 647 | <item> | 661 | <item> |
| 648 | <widget class="QLabel" name="label_5"> | 662 | <widget class="QLabel" name="label_6"> |
| 649 | <property name="text"> | 663 | <property name="text"> |
| 650 | <string>Pressed:</string> | 664 | <string>Pressed:</string> |
| 651 | </property> | 665 | </property> |
| 652 | </widget> | 666 | </widget> |
| 653 | </item> | 667 | </item> |
| 654 | <item> | 668 | <item> |
| 655 | <widget class="QPushButton" name="buttonRStick"> | 669 | <widget class="QPushButton" name="buttonLStick"> |
| 656 | <property name="text"> | 670 | <property name="text"> |
| 657 | <string/> | 671 | <string/> |
| 658 | </property> | 672 | </property> |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 417afef87..d198e38ae 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "yuzu/configuration/configure_system.h" | 8 | #include "yuzu/configuration/configure_system.h" |
| 9 | #include "yuzu/ui_settings.h" | 9 | #include "yuzu/ui_settings.h" |
| 10 | 10 | ||
| 11 | |||
| 12 | static const std::array<int, 12> days_in_month = {{ | 11 | static const std::array<int, 12> days_in_month = {{ |
| 13 | 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, | 12 | 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, |
| 14 | }}; | 13 | }}; |
diff --git a/src/yuzu/debugger/registers.cpp b/src/yuzu/debugger/registers.cpp index a52725075..06e2d1647 100644 --- a/src/yuzu/debugger/registers.cpp +++ b/src/yuzu/debugger/registers.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "yuzu/debugger/registers.h" | 8 | #include "yuzu/debugger/registers.h" |
| 9 | #include "yuzu/util/util.h" | 9 | #include "yuzu/util/util.h" |
| 10 | 10 | ||
| 11 | |||
| 12 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | 11 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { |
| 13 | cpu_regs_ui.setupUi(this); | 12 | cpu_regs_ui.setupUi(this); |
| 14 | 13 | ||
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 532c4ae63..679c89828 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -174,7 +174,7 @@ void GameList::onTextChanged(const QString& newText) { | |||
| 174 | child_file->data(GameListItemPath::ProgramIdRole).toString().toLower(); | 174 | child_file->data(GameListItemPath::ProgramIdRole).toString().toLower(); |
| 175 | 175 | ||
| 176 | // Only items which filename in combination with its title contains all words | 176 | // Only items which filename in combination with its title contains all words |
| 177 | // that are in the searchfiel will be visible in the gamelist | 177 | // that are in the searchfield will be visible in the gamelist |
| 178 | // The search is case insensitive because of toLower() | 178 | // The search is case insensitive because of toLower() |
| 179 | // I decided not to use Qt::CaseInsensitive in containsAllWords to prevent | 179 | // I decided not to use Qt::CaseInsensitive in containsAllWords to prevent |
| 180 | // multiple conversions of edit_filter_text for each game in the gamelist | 180 | // multiple conversions of edit_filter_text for each game in the gamelist |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index e40cd38b3..a758b77aa 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include <QRunnable> | 9 | #include <QRunnable> |
| 10 | #include <QStandardItem> | 10 | #include <QStandardItem> |
| 11 | #include <QString> | 11 | #include <QString> |
| 12 | #include "yuzu/util/util.h" | ||
| 13 | #include "common/string_util.h" | 12 | #include "common/string_util.h" |
| 13 | #include "yuzu/util/util.h" | ||
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * Gets the default icon (for games without valid SMDH) | 16 | * Gets the default icon (for games without valid SMDH) |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f64e68268..31f2825ee 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -122,8 +122,9 @@ void GMainWindow::InitializeWidgets() { | |||
| 122 | statusBar()->addPermanentWidget(message_label, 1); | 122 | statusBar()->addPermanentWidget(message_label, 1); |
| 123 | 123 | ||
| 124 | emu_speed_label = new QLabel(); | 124 | emu_speed_label = new QLabel(); |
| 125 | emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% " | 125 | emu_speed_label->setToolTip( |
| 126 | "indicate emulation is running faster or slower than a Switch.")); | 126 | tr("Current emulation speed. Values higher or lower than 100% " |
| 127 | "indicate emulation is running faster or slower than a Switch.")); | ||
| 127 | game_fps_label = new QLabel(); | 128 | game_fps_label = new QLabel(); |
| 128 | game_fps_label->setToolTip(tr("How many frames per second the game is currently displaying. " | 129 | game_fps_label->setToolTip(tr("How many frames per second the game is currently displaying. " |
| 129 | "This will vary from game to game and scene to scene.")); | 130 | "This will vary from game to game and scene to scene.")); |
| @@ -185,12 +186,24 @@ void GMainWindow::InitializeRecentFileMenuActions() { | |||
| 185 | void GMainWindow::InitializeHotkeys() { | 186 | void GMainWindow::InitializeHotkeys() { |
| 186 | RegisterHotkey("Main Window", "Load File", QKeySequence::Open); | 187 | RegisterHotkey("Main Window", "Load File", QKeySequence::Open); |
| 187 | RegisterHotkey("Main Window", "Start Emulation"); | 188 | RegisterHotkey("Main Window", "Start Emulation"); |
| 189 | RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); | ||
| 190 | RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence::Cancel, Qt::ApplicationShortcut); | ||
| 188 | LoadHotkeys(); | 191 | LoadHotkeys(); |
| 189 | 192 | ||
| 190 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, | 193 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, |
| 191 | SLOT(OnMenuLoadFile())); | 194 | SLOT(OnMenuLoadFile())); |
| 192 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, | 195 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, |
| 193 | SLOT(OnStartGame())); | 196 | SLOT(OnStartGame())); |
| 197 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated, | ||
| 198 | ui.action_Fullscreen, &QAction::trigger); | ||
| 199 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously, | ||
| 200 | ui.action_Fullscreen, &QAction::trigger); | ||
| 201 | connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] { | ||
| 202 | if (emulation_running) { | ||
| 203 | ui.action_Fullscreen->setChecked(false); | ||
| 204 | ToggleFullscreen(); | ||
| 205 | } | ||
| 206 | }); | ||
| 194 | } | 207 | } |
| 195 | 208 | ||
| 196 | void GMainWindow::SetDefaultUIGeometry() { | 209 | void GMainWindow::SetDefaultUIGeometry() { |
| @@ -219,6 +232,8 @@ void GMainWindow::RestoreUIState() { | |||
| 219 | ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode); | 232 | ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode); |
| 220 | ToggleWindowMode(); | 233 | ToggleWindowMode(); |
| 221 | 234 | ||
| 235 | ui.action_Fullscreen->setChecked(UISettings::values.fullscreen); | ||
| 236 | |||
| 222 | ui.action_Display_Dock_Widget_Headers->setChecked(UISettings::values.display_titlebar); | 237 | ui.action_Display_Dock_Widget_Headers->setChecked(UISettings::values.display_titlebar); |
| 223 | OnDisplayTitleBars(ui.action_Display_Dock_Widget_Headers->isChecked()); | 238 | OnDisplayTitleBars(ui.action_Display_Dock_Widget_Headers->isChecked()); |
| 224 | 239 | ||
| @@ -263,6 +278,10 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 263 | connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar); | 278 | connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar); |
| 264 | connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); | 279 | connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); |
| 265 | 280 | ||
| 281 | // Fullscreen | ||
| 282 | ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key()); | ||
| 283 | connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); | ||
| 284 | |||
| 266 | // Help | 285 | // Help |
| 267 | connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout); | 286 | connect(ui.action_About, &QAction::triggered, this, &GMainWindow::OnAbout); |
| 268 | } | 287 | } |
| @@ -402,6 +421,9 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 402 | render_window->setFocus(); | 421 | render_window->setFocus(); |
| 403 | 422 | ||
| 404 | emulation_running = true; | 423 | emulation_running = true; |
| 424 | if (ui.action_Fullscreen->isChecked()) { | ||
| 425 | ShowFullscreen(); | ||
| 426 | } | ||
| 405 | OnStartGame(); | 427 | OnStartGame(); |
| 406 | } | 428 | } |
| 407 | 429 | ||
| @@ -548,6 +570,41 @@ void GMainWindow::OnStopGame() { | |||
| 548 | ShutdownGame(); | 570 | ShutdownGame(); |
| 549 | } | 571 | } |
| 550 | 572 | ||
| 573 | void GMainWindow::ToggleFullscreen() { | ||
| 574 | if (!emulation_running) { | ||
| 575 | return; | ||
| 576 | } | ||
| 577 | if (ui.action_Fullscreen->isChecked()) { | ||
| 578 | ShowFullscreen(); | ||
| 579 | } else { | ||
| 580 | HideFullscreen(); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | void GMainWindow::ShowFullscreen() { | ||
| 585 | if (ui.action_Single_Window_Mode->isChecked()) { | ||
| 586 | UISettings::values.geometry = saveGeometry(); | ||
| 587 | ui.menubar->hide(); | ||
| 588 | statusBar()->hide(); | ||
| 589 | showFullScreen(); | ||
| 590 | } else { | ||
| 591 | UISettings::values.renderwindow_geometry = render_window->saveGeometry(); | ||
| 592 | render_window->showFullScreen(); | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | void GMainWindow::HideFullscreen() { | ||
| 597 | if (ui.action_Single_Window_Mode->isChecked()) { | ||
| 598 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); | ||
| 599 | ui.menubar->show(); | ||
| 600 | showNormal(); | ||
| 601 | restoreGeometry(UISettings::values.geometry); | ||
| 602 | } else { | ||
| 603 | render_window->showNormal(); | ||
| 604 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | ||
| 605 | } | ||
| 606 | } | ||
| 607 | |||
| 551 | void GMainWindow::ToggleWindowMode() { | 608 | void GMainWindow::ToggleWindowMode() { |
| 552 | if (ui.action_Single_Window_Mode->isChecked()) { | 609 | if (ui.action_Single_Window_Mode->isChecked()) { |
| 553 | // Render in the main window... | 610 | // Render in the main window... |
| @@ -670,6 +727,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det | |||
| 670 | } else { | 727 | } else { |
| 671 | // Only show the message if the game is still running. | 728 | // Only show the message if the game is still running. |
| 672 | if (emu_thread) { | 729 | if (emu_thread) { |
| 730 | emu_thread->SetRunning(true); | ||
| 673 | message_label->setText(status_message); | 731 | message_label->setText(status_message); |
| 674 | message_label->setVisible(true); | 732 | message_label->setVisible(true); |
| 675 | } | 733 | } |
| @@ -700,6 +758,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
| 700 | UISettings::values.microprofile_visible = microProfileDialog->isVisible(); | 758 | UISettings::values.microprofile_visible = microProfileDialog->isVisible(); |
| 701 | #endif | 759 | #endif |
| 702 | UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked(); | 760 | UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked(); |
| 761 | UISettings::values.fullscreen = ui.action_Fullscreen->isChecked(); | ||
| 703 | UISettings::values.display_titlebar = ui.action_Display_Dock_Widget_Headers->isChecked(); | 762 | UISettings::values.display_titlebar = ui.action_Display_Dock_Widget_Headers->isChecked(); |
| 704 | UISettings::values.show_filter_bar = ui.action_Show_Filter_Bar->isChecked(); | 763 | UISettings::values.show_filter_bar = ui.action_Show_Filter_Bar->isChecked(); |
| 705 | UISettings::values.show_status_bar = ui.action_Show_Status_Bar->isChecked(); | 764 | UISettings::values.show_status_bar = ui.action_Show_Status_Bar->isChecked(); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 3add882dd..4a0d912bb 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -127,6 +127,9 @@ private slots: | |||
| 127 | void OnAbout(); | 127 | void OnAbout(); |
| 128 | void OnToggleFilterBar(); | 128 | void OnToggleFilterBar(); |
| 129 | void OnDisplayTitleBars(bool); | 129 | void OnDisplayTitleBars(bool); |
| 130 | void ToggleFullscreen(); | ||
| 131 | void ShowFullscreen(); | ||
| 132 | void HideFullscreen(); | ||
| 130 | void ToggleWindowMode(); | 133 | void ToggleWindowMode(); |
| 131 | void OnCoreError(Core::System::ResultStatus, std::string); | 134 | void OnCoreError(Core::System::ResultStatus, std::string); |
| 132 | 135 | ||
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 721e769e8..0fcd93cc2 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -83,6 +83,7 @@ | |||
| 83 | <string>Debugging</string> | 83 | <string>Debugging</string> |
| 84 | </property> | 84 | </property> |
| 85 | </widget> | 85 | </widget> |
| 86 | <addaction name="action_Fullscreen"/> | ||
| 86 | <addaction name="action_Single_Window_Mode"/> | 87 | <addaction name="action_Single_Window_Mode"/> |
| 87 | <addaction name="action_Display_Dock_Widget_Headers"/> | 88 | <addaction name="action_Display_Dock_Widget_Headers"/> |
| 88 | <addaction name="action_Show_Filter_Bar"/> | 89 | <addaction name="action_Show_Filter_Bar"/> |
| @@ -189,6 +190,14 @@ | |||
| 189 | <string>Selects a folder to display in the game list</string> | 190 | <string>Selects a folder to display in the game list</string> |
| 190 | </property> | 191 | </property> |
| 191 | </action> | 192 | </action> |
| 192 | </widget> | 193 | <action name="action_Fullscreen"> |
| 194 | <property name="checkable"> | ||
| 195 | <bool>true</bool> | ||
| 196 | </property> | ||
| 197 | <property name="text"> | ||
| 198 | <string>Fullscreen</string> | ||
| 199 | </property> | ||
| 200 | </action> | ||
| 201 | </widget> | ||
| 193 | <resources/> | 202 | <resources/> |
| 194 | </ui> | 203 | </ui> |
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h index e965f0ba9..d093da641 100644 --- a/src/yuzu/ui_settings.h +++ b/src/yuzu/ui_settings.h | |||
| @@ -27,6 +27,7 @@ struct Values { | |||
| 27 | bool microprofile_visible; | 27 | bool microprofile_visible; |
| 28 | 28 | ||
| 29 | bool single_window_mode; | 29 | bool single_window_mode; |
| 30 | bool fullscreen; | ||
| 30 | bool display_titlebar; | 31 | bool display_titlebar; |
| 31 | bool show_filter_bar; | 32 | bool show_filter_bar; |
| 32 | bool show_status_bar; | 33 | bool show_status_bar; |
diff --git a/src/yuzu/util/spinbox.cpp b/src/yuzu/util/spinbox.cpp index ede6fe0a8..92753ec1c 100644 --- a/src/yuzu/util/spinbox.cpp +++ b/src/yuzu/util/spinbox.cpp | |||
| @@ -31,8 +31,8 @@ | |||
| 31 | #include <cstdlib> | 31 | #include <cstdlib> |
| 32 | #include <QLineEdit> | 32 | #include <QLineEdit> |
| 33 | #include <QRegExpValidator> | 33 | #include <QRegExpValidator> |
| 34 | #include "yuzu/util/spinbox.h" | ||
| 35 | #include "common/assert.h" | 34 | #include "common/assert.h" |
| 35 | #include "yuzu/util/spinbox.h" | ||
| 36 | 36 | ||
| 37 | CSpinBox::CSpinBox(QWidget* parent) | 37 | CSpinBox::CSpinBox(QWidget* parent) |
| 38 | : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) { | 38 | : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) { |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 785d96672..8f7c75796 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include "yuzu_cmd/config.h" | 37 | #include "yuzu_cmd/config.h" |
| 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 39 | 39 | ||
| 40 | |||
| 41 | static void PrintHelp(const char* argv0) { | 40 | static void PrintHelp(const char* argv0) { |
| 42 | std::cout << "Usage: " << argv0 | 41 | std::cout << "Usage: " << argv0 |
| 43 | << " [options] <filename>\n" | 42 | << " [options] <filename>\n" |