summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml18
-rwxr-xr-x.travis/linux/docker.sh10
-rwxr-xr-x.travis/macos/build.sh2
-rwxr-xr-x.travis/macos/deps.sh7
-rw-r--r--CMakeLists.txt73
-rw-r--r--README.md1
-rw-r--r--appveyor.yml22
m---------externals/unicorn0
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/arm/arm_interface.h3
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp2
-rw-r--r--src/core/hle/ipc.h11
-rw-r--r--src/core/hle/ipc_helpers.h22
-rw-r--r--src/core/hle/kernel/hle_ipc.h12
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/memory.cpp6
-rw-r--r--src/core/hle/kernel/mutex.h6
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/svc.cpp36
-rw-r--r--src/core/hle/kernel/svc.h14
-rw-r--r--src/core/hle/kernel/vm_manager.cpp9
-rw-r--r--src/core/hle/service/acc/acc.cpp16
-rw-r--r--src/core/hle/service/acc/acc.h16
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp26
-rw-r--r--src/core/hle/service/acc/acc_u0.h22
-rw-r--r--src/core/hle/service/am/applet_oe.cpp114
-rw-r--r--src/core/hle/service/apm/apm.cpp45
-rw-r--r--src/core/hle/service/apm/apm.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h4
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp (renamed from src/core/hle/service/nvdrv/nvdrv_a.cpp)41
-rw-r--r--src/core/hle/service/nvdrv/interface.h29
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp47
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h123
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_a.h51
-rw-r--r--src/core/hle/service/service.cpp4
-rw-r--r--src/core/hle/service/vi/vi.cpp85
-rw-r--r--src/core/hle/service/vi/vi.h9
-rw-r--r--src/core/loader/linker.cpp12
-rw-r--r--src/core/loader/nso.cpp13
-rw-r--r--src/core/loader/nso.h3
-rw-r--r--src/core/memory.h4
-rw-r--r--src/input_common/main.cpp11
-rw-r--r--src/input_common/main.h32
-rw-r--r--src/input_common/sdl/sdl.cpp183
-rw-r--r--src/input_common/sdl/sdl.h23
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h3
-rw-r--r--src/yuzu/about_dialog.cpp2
-rw-r--r--src/yuzu/bootmanager.cpp1
-rw-r--r--src/yuzu/configuration/config.cpp10
-rw-r--r--src/yuzu/configuration/configure_debug.cpp1
-rw-r--r--src/yuzu/configuration/configure_debug.ui12
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_input.cpp216
-rw-r--r--src/yuzu/configuration/configure_input.h31
-rw-r--r--src/yuzu/configuration/configure_input.ui296
-rw-r--r--src/yuzu/configuration/configure_system.cpp1
-rw-r--r--src/yuzu/debugger/registers.cpp1
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/game_list_p.h2
-rw-r--r--src/yuzu/main.cpp63
-rw-r--r--src/yuzu/main.h3
-rw-r--r--src/yuzu/main.ui11
-rw-r--r--src/yuzu/ui_settings.h1
-rw-r--r--src/yuzu/util/spinbox.cpp2
-rw-r--r--src/yuzu_cmd/yuzu.cpp1
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
2matrix: 2matrix:
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
32deploy: 32deploy:
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
3apt-get update 3apt-get update
4apt-get install -y build-essential git libcurl4-openssl-dev libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev wget 4apt-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
7wget https://cmake.org/files/v3.10/cmake-3.10.1-Linux-x86_64.sh 7wget https://cmake.org/files/v3.10/cmake-3.10.1-Linux-x86_64.sh
8sh cmake-3.10.1-Linux-x86_64.sh --exclude-subdir --prefix=/ --skip-license 8sh cmake-3.10.1-Linux-x86_64.sh --exclude-subdir --prefix=/ --skip-license
9 9
10mkdir /unicorn
11cd /unicorn
12git clone https://github.com/yuzu-emu/unicorn .
13UNICORN_ARCHS=aarch64 ./make.sh
14./make.sh install
15
16cd /yuzu 10cd /yuzu
17 11
18mkdir build && cd build 12mkdir build && cd build
19cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_BUILD_TYPE=Release 13cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_BUILD_TYPE=Release
20make -j4 14make -j4
21 15
22ctest -VV -C Release 16ctest -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
9mkdir build && cd build 9mkdir build && cd build
10cmake --version 10cmake --version
11cmake .. -DUSE_SYSTEM_CURL=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release 11cmake .. -DYUZU_BUILD_UNICORN=ON -DCMAKE_OSX_ARCHITECTURES="x86_64;x86_64h" -DCMAKE_BUILD_TYPE=Release
12make -j4 12make -j4
13 13
14ctest -VV -C Release 14ctest -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
3brew update 3brew update
4brew install dylibbundler p7zip qt5 sdl2 4brew install dylibbundler p7zip qt5 sdl2
5 5brew outdated cmake || brew upgrade cmake
6mkdir externals/unicorn
7pushd externals/unicorn
8git clone https://github.com/yuzu-emu/unicorn .
9UNICORN_ARCHS=aarch64 ./make.sh macos-universal-no
10popd
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)
12option(ENABLE_QT "Enable the Qt frontend" ON) 12option(ENABLE_QT "Enable the Qt frontend" ON)
13option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) 13option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF)
14 14
15option(YUZU_USE_BUNDLED_UNICORN "Download bundled Unicorn binaries" OFF)
16
17if(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit) 15if(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)
205endif() 203endif()
206 204
207if (YUZU_USE_BUNDLED_UNICORN) 205# If unicorn isn't found, msvc -> download bundled unicorn; everyone else -> build external
208 # Detect toolchain and platform 206find_package(Unicorn QUIET)
209 if (MSVC14 AND ARCHITECTURE_x86_64) 207if (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)
227else() 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()
229endif() 256endif()
230 257
231if (UNICORN_FOUND) 258if (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}")
262else()
263 message(FATAL_ERROR "Could not find or build unicorn which is required.")
235endif() 264endif()
236 265
237if (ENABLE_QT) 266if (ENABLE_QT)
diff --git a/README.md b/README.md
index 2f769770c..4b0b151a4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
1yuzu emulator 1yuzu emulator
2============= 2=============
3[![Travis CI Build Status](https://travis-ci.org/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.org/yuzu-emu/yuzu) 3[![Travis CI Build Status](https://travis-ci.org/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.org/yuzu-emu/yuzu)
4[![AppVeyor CI Build Status](https://ci.appveyor.com/api/projects/status/77k97svb2usreu68?svg=true)](https://ci.appveyor.com/project/bunnei/yuzu)
4 5
5yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/). 6yuzu 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>
16struct LoadDll { 16struct LoadDll {
17private: 17private:
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.
20constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; 20constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS;
21 21
22
23enum class ControlCommand : u32 { 22enum 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
17namespace IPC { 20namespace 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
178private: 186private:
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
109public: 108public:
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
98void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { 98void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {}
99}
100 99
101void MapSharedPages(VMManager& address_space) { 100void 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
737static ResultCode SetThreadCoreMask(u64, u64, u64) {
738 LOG_WARNING(Kernel_SVC, "(STUBBED) called");
739 return RESULT_SUCCESS;
740}
741
712namespace { 742namespace {
713struct FunctionDef { 743struct 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 {
24enum class GetInfoType : u64 { 24enum 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
37void CallSVC(u32 immediate); 51void 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
357u64 VMManager::GetTotalMemoryUsage() { 358u64 VMManager::GetTotalMemoryUsage() {
358 LOG_WARNING(Kernel, "(STUBBED) called"); 359 LOG_WARNING(Kernel, "(STUBBED) called");
359 return 0x400000; 360 return 0xBE000000;
360} 361}
361 362
362u64 VMManager::GetTotalHeapUsage() { 363u64 VMManager::GetTotalHeapUsage() {
363 LOG_WARNING(Kernel, "(STUBBED) called"); 364 LOG_WARNING(Kernel, "(STUBBED) called");
364 return 0x10000; 365 return 0x0;
365} 366}
366 367
367VAddr VMManager::GetAddressSpaceBaseAddr() { 368VAddr 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
8namespace Service {
9namespace Account {
10
11void 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
9namespace Service {
10namespace Account {
11
12/// Registers all ACC services with the specified service manager.
13void 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
9namespace Service {
10namespace Account {
11
12void 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
18ACC_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
9namespace Service {
10namespace Account {
11
12class ACC_U0 final : public ServiceFramework<ACC_U0> {
13public:
14 ACC_U0();
15 ~ACC_U0() = default;
16
17private:
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
10namespace Service { 11namespace Service {
11namespace AM { 12namespace AM {
@@ -54,7 +55,14 @@ class ISelfController final : public ServiceFramework<ISelfController> {
54public: 55public:
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
74class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 133class 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
87private: 148private:
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
141class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { 253class 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
16class ISession final : public ServiceFramework<ISession> {
17public:
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
26private:
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
16APM::APM() : ServiceFramework("apm") { 52APM::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
59void 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 @@
9namespace Service { 9namespace Service {
10namespace APM { 10namespace APM {
11 11
12enum class PerformanceMode : u8 {
13 Handheld = 0,
14 Docked = 1,
15};
16
12class APM final : public ServiceFramework<APM> { 17class APM final : public ServiceFramework<APM> {
13public: 18public:
14 APM(); 19 APM();
15 ~APM() = default; 20 ~APM() = default;
21
22private:
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
10namespace Service { 10namespace Service {
11namespace NVDRV { 11namespace Nvidia {
12namespace Devices { 12namespace 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
12namespace Service { 12namespace Service {
13namespace NVDRV { 13namespace Nvidia {
14namespace Devices { 14namespace Devices {
15 15
16u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { 16u32 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
12namespace Service { 12namespace Service {
13namespace NVDRV { 13namespace Nvidia {
14namespace Devices { 14namespace Devices {
15 15
16class nvmap; 16class 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
9namespace Service { 9namespace Service {
10namespace NVDRV { 10namespace Nvidia {
11namespace Devices { 11namespace Devices {
12 12
13u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { 13u32 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
11namespace Service { 11namespace Service {
12namespace NVDRV { 12namespace Nvidia {
13namespace Devices { 13namespace Devices {
14 14
15class nvhost_as_gpu final : public nvdevice { 15class 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
11namespace Service { 11namespace Service {
12namespace NVDRV { 12namespace Nvidia {
13namespace Devices { 13namespace Devices {
14 14
15VAddr nvmap::GetObjectAddress(u32 handle) const { 15VAddr 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
15namespace Service { 15namespace Service {
16namespace NVDRV { 16namespace Nvidia {
17namespace Devices { 17namespace Devices {
18 18
19class nvmap final : public nvdevice { 19class 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
14namespace Service { 10namespace Service {
15namespace NVDRV { 11namespace Nvidia {
16 12
17void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { 13void 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
35void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { 27void 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
62void NVDRV_A::Initialize(Kernel::HLERequestContext& ctx) { 51void 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
69NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { 58NVDRV::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
12namespace Service {
13namespace Nvidia {
14
15class NVDRV final : public ServiceFramework<NVDRV> {
16public:
17 NVDRV(std::shared_ptr<Module> nvdrv, const char* name);
18 ~NVDRV() = default;
19
20private:
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
8namespace Service { 13namespace Service {
9namespace NVDRV { 14namespace Nvidia {
10 15
11std::weak_ptr<NVDRV_A> nvdrv_a; 16std::weak_ptr<Module> nvdrv;
12 17
13void InstallInterfaces(SM::ServiceManager& service_manager) { 18void 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 25Module::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
32u32 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
44u32 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
13namespace Service { 13namespace Service {
14namespace NVDRV { 14namespace Nvidia {
15 15
16class nvdevice { 16namespace Devices {
17public: 17class 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
23class nvmap : public nvdevice { 20class Module final {
24public: 21public:
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;
29private: 39private:
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
101class nvdisp_disp0 : public nvdevice {
102public:
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
111private:
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.
116void InstallInterfaces(SM::ServiceManager& service_manager); 51void InstallInterfaces(SM::ServiceManager& service_manager);
117 52
118} // namespace NVDRV 53extern 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
12namespace Service {
13namespace NVDRV {
14
15namespace Devices {
16class nvdevice;
17}
18
19class NVDRV_A final : public ServiceFramework<NVDRV_A> {
20public:
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
33private:
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
48extern 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
583void 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
568void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { 592void 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
607void 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
583void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { 616void 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
641void 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
665void 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
608void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { 675void 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
781BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {} 852BufferQueue::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
783void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { 856void 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
62private: 66private:
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
69struct Layer { 74struct 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};
49static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size."); 49static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size.");
50 50
51void Linker::WriteRelocations(std::vector<u8>& program_image, 51void 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
93void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, 93void 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};
24static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size."); 27static_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 {
18class AppLoader_NSO final : public AppLoader, Linker { 18class AppLoader_NSO final : public AppLoader, Linker {
19public: 19public:
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
74namespace Polling {
75
76std::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
11namespace Common {
12class ParamPackage;
13}
8 14
9namespace InputCommon { 15namespace InputCommon {
10 16
@@ -31,4 +37,30 @@ std::string GenerateKeyboardParam(int key_code);
31std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, 37std::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
40namespace Polling {
41
42enum 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 */
48class DevicePoller {
49public:
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
64std::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
15namespace InputCommon { 17namespace 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
72private: 78private:
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 */
260static 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
271Common::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
313namespace Polling {
314
315class SDLPoller : public InputCommon::Polling::DevicePoller {
316public:
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
338private:
339 std::vector<std::shared_ptr<SDLJoystick>> joysticks_opened;
340};
341
342class SDLButtonPoller final : public SDLPoller {
343public:
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
365class SDLAnalogPoller final : public SDLPoller {
366public:
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
411private:
412 int analog_xaxis = -1;
413 int analog_yaxis = -1;
414 SDL_JoystickID analog_axes_joystick = -1;
415};
416
417std::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
11union SDL_Event;
12namespace Common {
13class ParamPackage;
14}
15namespace InputCommon {
16namespace Polling {
17class DevicePoller;
18enum class DeviceType;
19} // namespace Polling
20} // namespace InputCommon
21
9namespace InputCommon { 22namespace InputCommon {
10namespace SDL { 23namespace 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.
16void Shutdown(); 29void Shutdown();
17 30
31/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice
32Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event);
33
34namespace Polling {
35
36/// Get all DevicePoller that use the SDL backend for a specific device type
37std::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 @@
9AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { 9AboutDialog::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(
12Common::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
15AboutDialog::~AboutDialog() {} 15AboutDialog::~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
20const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { 20const 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
27const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ 27const 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
10ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { 9ConfigureDebug::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
11ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { 10ConfigureDialog::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
15const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM> 15const 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
35static void SetButtonKey(int key, Common::ParamPackage& button_param) { 35static 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
39static 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
45static 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
69static 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
49ConfigureInput::ConfigureInput(QWidget* parent) 91ConfigureInput::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
133void ConfigureInput::restoreDefaults() { 197void 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
148void ConfigureInput::updateButtonLabels() { 214void 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
180void ConfigureInput::handleClick(QPushButton* button, std::function<void(int)> new_key_setter) { 230void 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
191void ConfigureInput::keyPressEvent(QKeyEvent* event) { 253void 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
270void 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
18class QPushButton; 20class QPushButton;
@@ -35,10 +37,11 @@ public:
35private: 37private:
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
91Capture:</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>
265Capture:</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
12static const std::array<int, 12> days_in_month = {{ 11static 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
12RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { 11RegistersWidget::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() {
185void GMainWindow::InitializeHotkeys() { 186void 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
196void GMainWindow::SetDefaultUIGeometry() { 209void 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
573void GMainWindow::ToggleFullscreen() {
574 if (!emulation_running) {
575 return;
576 }
577 if (ui.action_Fullscreen->isChecked()) {
578 ShowFullscreen();
579 } else {
580 HideFullscreen();
581 }
582}
583
584void 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
596void 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
551void GMainWindow::ToggleWindowMode() { 608void 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
37CSpinBox::CSpinBox(QWidget* parent) 37CSpinBox::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
41static void PrintHelp(const char* argv0) { 40static void PrintHelp(const char* argv0) {
42 std::cout << "Usage: " << argv0 41 std::cout << "Usage: " << argv0
43 << " [options] <filename>\n" 42 << " [options] <filename>\n"