mirror of
https://github.com/thejerf/baijiSteamVR.git
synced 2026-10-17 21:01:42 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70d096f8d7 | ||
|
|
38fc6d9a95 | ||
|
|
3d27e75026 | ||
|
|
f395e45ddf | ||
|
|
14effdb34e | ||
|
|
8b4a0723fc | ||
|
|
982671b53f | ||
|
|
38cf5cf933 | ||
|
|
24634ba1bd | ||
|
|
0775c13109 | ||
|
|
6b197206e8 | ||
|
|
89dc31c6e8 | ||
|
|
46a987148d | ||
|
|
0cef1d3651 | ||
|
|
dbb7283447 | ||
|
|
52ffacb887 | ||
|
|
ac2b377e23 | ||
|
|
20c13cc035 | ||
|
|
57f026c120 | ||
|
|
122721b259 | ||
|
|
23b616ebf8 | ||
|
|
652ee1ef1b | ||
|
|
f55ab9b06e | ||
|
|
ce1c7928a7 | ||
|
|
c4eb076a49 | ||
|
|
6712e7cdbf | ||
|
|
3a5060500c | ||
|
|
fbeefedb2a | ||
|
|
97f1160707 | ||
|
|
c652e2d702 | ||
|
|
18e1811dec | ||
|
|
9dd817d864 | ||
|
|
8a150c187e | ||
|
|
75d1994b9c | ||
|
|
6c95b40453 | ||
|
|
4465c932fb | ||
|
|
22f6884ca0 | ||
|
|
ef1a3a0500 | ||
|
|
8c549d2036 | ||
|
|
7df6a30691 | ||
|
|
5fa8d90d8b | ||
|
|
d3bdaab03a | ||
|
|
ce93e0606d | ||
|
|
834cdddd2e | ||
|
|
bec9d1beae | ||
|
|
3ec01541fd | ||
|
|
0e74b57e09 | ||
|
|
2e826d8914 | ||
|
|
1190e903be | ||
|
|
a02a554c86 | ||
|
|
cf72cfeb53 | ||
|
|
8fb66a2936 | ||
|
|
75dc76990b | ||
|
|
328997747a | ||
|
|
f6d7395ea2 | ||
|
|
c7499b4ccf | ||
|
|
d9ed82e38f | ||
|
|
4359d8c989 | ||
|
|
7726dbe5a5 | ||
|
|
64878c16c4 | ||
|
|
fb2e70a608 | ||
|
|
49cf50d0e2 | ||
|
|
3deb147e55 | ||
|
|
aa2871d9e6 | ||
|
|
5e9a304a65 | ||
|
|
1678bc7cd5 | ||
|
|
ffe128309f | ||
|
|
6955095298 | ||
|
|
308ce19adf | ||
|
|
6f5b20ac24 | ||
|
|
1292404e31 | ||
|
|
2d41ce7ac4 | ||
|
|
ca0070222d | ||
|
|
3d069f0bb9 | ||
|
|
9bd33b5f6b |
No files matched your search
@@ -0,0 +1,52 @@
|
||||
### Copy of gitignore
|
||||
# Ignore image thumbnail files created by windows
|
||||
Thumbs.db
|
||||
# Ignore Finder view option files created by OS X
|
||||
.DS_Store
|
||||
# Ignore autogenerated source files
|
||||
Externals/mGBA/version.c
|
||||
Source/Core/Common/scmrev.h
|
||||
# Ignore files output by build
|
||||
/cmake-build-debug
|
||||
/cmake-build-release
|
||||
/[Bb]uild/
|
||||
/[Bb]inary/
|
||||
/obj/
|
||||
# Ignore files output by Android cmake build
|
||||
/Source/Android/app/.cxx/
|
||||
/libs/
|
||||
# Ignore various files created by visual studio/msbuild
|
||||
*.ipch
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.suo
|
||||
*.vcxproj.user
|
||||
*.obj
|
||||
*.tlog
|
||||
*.VC.opendb
|
||||
*.VC.db
|
||||
.vs*/
|
||||
/Source/enc_temp_folder/
|
||||
# Ignore build info file created by QtCreator
|
||||
CMakeLists.txt.user
|
||||
|
||||
# Ignore vim swapfiles
|
||||
*.swp
|
||||
# Ignore kdevelop files/dirs
|
||||
*.kdev4
|
||||
# Ignore IDEA/Clion files/dirs
|
||||
.idea/
|
||||
# Ignore Visual Studio Code's working dir
|
||||
/.vscode/
|
||||
# Ignore flatpak-builder's cache dir
|
||||
.flatpak-builder
|
||||
# DolphinXR dev artifacts
|
||||
codex_apk_backups/
|
||||
quest_perf_capture/
|
||||
vulkan_pipeline_failures/
|
||||
vulkan_pipeline_failures_latest/
|
||||
vulkan_pipeline_failures_latest2/
|
||||
quest_first_mv_vs.glsl
|
||||
quest_mv_vs.glsl
|
||||
|
||||
### Changes from gitignore
|
||||
@@ -0,0 +1,15 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [iChris4] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
+8
-1
@@ -43,7 +43,7 @@ CMakeLists.txt.user
|
||||
/.vscode/
|
||||
# Ignore flatpak-builder's cache dir
|
||||
.flatpak-builder
|
||||
# DolphinXR dev artifacts
|
||||
# Local development artifacts
|
||||
codex_apk_backups/
|
||||
quest_perf_capture/
|
||||
vulkan_pipeline_failures/
|
||||
@@ -51,3 +51,10 @@ vulkan_pipeline_failures_latest/
|
||||
vulkan_pipeline_failures_latest2/
|
||||
quest_first_mv_vs.glsl
|
||||
quest_mv_vs.glsl
|
||||
legacy/
|
||||
hostpid/
|
||||
patches/
|
||||
|
||||
/state/
|
||||
/dist/*
|
||||
/hostpid/libhostpid.so
|
||||
@@ -0,0 +1,167 @@
|
||||
# Repository guidance
|
||||
|
||||
- This is a CMake-based Dolphin/OpenXR fork. Native Steam Frame (AArch64) builds
|
||||
use `scripts/compile-cross-sdk.sh`; the maintained build/deploy workflow and
|
||||
local SDK details are in `docs/build-runbook.md`. Flatpak files under
|
||||
`legacy/flatpak/` are archived, not the active Frame workflow.
|
||||
- Recent `openxr-work` changes focus on Steam Frame OpenXR presentation and input.
|
||||
`OpenXRPresentationMode` (Vulkan, Immersive, StereoScreen, or legacy settings)
|
||||
is resolved in `VideoCommon/VideoConfig.cpp`; keep its config/UI and backend
|
||||
paths in sync. StereoScreen reuses the SBS presenter path but submits separate
|
||||
OpenXR quad layers; its shared submission/pose logic is in `VideoCommon/Present.*`
|
||||
and `VideoCommon/VR/OpenXRManager.*`, with swapchain work in video backends.
|
||||
OpenXR reference-space events are polled on the XR pacing thread; flat-screen pose
|
||||
invalidation is deferred until `LocateViews` refreshes the video-thread view snapshot.
|
||||
Preserve this ordering and the cache synchronization when changing recenter behavior.
|
||||
- Config defaults are declared in `Source/Core/Core/Config/GraphicsSettings.cpp`;
|
||||
the VR mode is `GFX_VR_PRESENTATION_MODE` (`Graphics.VR.PresentationMode`). Keep
|
||||
its choices aligned with `DolphinQt/Config/VRConfigWidget.cpp` and
|
||||
`DolphinQt/Settings/VRPane.cpp`; runtime mode resolution is in
|
||||
`VideoCommon/VideoConfig.cpp`.
|
||||
- XR heartbeat is `GFX_VR_EAGER_HEARTBEAT` (`Graphics.VR.EagerHeartbeat`), declared
|
||||
in `GraphicsSettings.cpp` and loaded in `VideoConfig.cpp`. `true` is Eager (submit
|
||||
each HMD refresh, reusing the last frame); `false` is Lazy (pace submissions to game
|
||||
frames so PC runtime motion smoothing can engage).
|
||||
- Steam Frame presentation fixes (SMG2, 2026-10-04): the XR pacing loop does not
|
||||
wait for new game content after `xrWaitFrame`; that removed a significant source
|
||||
of hitching. StereoScreen also batches both Vulkan eye blits, waits once for GPU
|
||||
completion, releases both images, then publishes the quad layers. Submitted but
|
||||
unfinished eye writes produced conspicuous doubling/stale-image hiccups on Frame;
|
||||
the completed-pair handoff resolved them in headset testing at 2x/120 Hz. Keep
|
||||
this completion wait even when timeline semaphores are enabled. It trades some
|
||||
CPU/GPU overlap for correct image delivery. `PresentBackbuffer` already advances
|
||||
frame resources; the stereo submit must not advance them again.
|
||||
- `m_video_handoff_mutex` excludes `xrEndFrame` from the video's blit/completion/
|
||||
release/publish transaction. The previous atomic flag had a check-to-submit race.
|
||||
Keep the handoff -> publish/graphics-queue lock order; never take the handoff
|
||||
lock while holding either of those other locks. Do not hold the graphics-queue
|
||||
lock during the GPU-completion wait.
|
||||
- Investigation evidence: 16699 XFB copies showed no detected gameplay source,
|
||||
GPU-submit, XR display-time reversal, or eye-ID mismatch, while CPU-side handoff
|
||||
locking alone did not cure doubling. SteamVR motion smoothing was already
|
||||
ForceOff (`motionSmoothingOverride=2`); reprojection counts did not establish
|
||||
temporal blending. GPU readbacks accounted for long waits and 1x improved the
|
||||
remaining isolated drops. Keep 120 Hz for comparison; refresh-rate mismatch was
|
||||
already investigated. Temporary timing/order captures and analyzers were removed
|
||||
after the fix. Desktop mirroring is forced off and its Qt options are hidden.
|
||||
- Frame controller changes span `Common/VR/OpenXRInputState.h`,
|
||||
`InputCommon/ControllerInterface/OpenXR/OpenXR.cpp`, Vulkan/OpenXR session setup,
|
||||
the Qt mapping UI, and `Data/Sys/Profiles/`. For Frame controllers, Flat Vulkan
|
||||
uses SDL/Steam Input; StereoScreen and Immersive VR use OpenXR controller actions.
|
||||
Preserve this mode-dependent split. Keep profile defaults and UI/controller
|
||||
loading order aligned.
|
||||
- Open issue (tabled while focusing on StereoScreen): Flat-mode orientation pointing
|
||||
through SDL is unresolved. The Frame's `SDL/0/Steam Frame Controllers` provides
|
||||
button/axis inputs, but the diagnostic trace found no SDL Accel/Gyro inputs and
|
||||
sensor values stayed zero while the user rotated the controller. The captured trace
|
||||
did show d-pad, trigger, and stick events, so it did not reproduce total SDL input
|
||||
loss. Keep the thumbstick IR fallback; do not assume SDL sensor support.
|
||||
- Frame audio quirk (2026-10-11): AudioCommon sends stereo through Cubeb/PipeWire;
|
||||
SteamOS WirePlumber creates a `spatialize_filter_chain` for output streams when the
|
||||
built-in speaker sink is default. `node.stream.enable-spatial-audio` is a global
|
||||
setting, and the current policy has no per-application opt-out. Do not change this
|
||||
global setting for Baiji; leave the UI-position spatialization documented as a quirk
|
||||
unless Frame exposes a supported per-stream opt-out.
|
||||
- Baiji is a Steam Frame-only Dolphin cut; changes may be intentionally more
|
||||
aggressive than upstream Dolphin. This branch is temporary and can end once
|
||||
upstream incorporates its features. Inspect Baiji data only under
|
||||
`~/.config/baiji` and `~/.local/share/baiji`; ignore the separate Dolphin
|
||||
installation/config. Legacy INI filenames may remain, but Dolphin installation
|
||||
or user-data paths inside Baiji config are suspicious and must not be followed.
|
||||
- Never modify Frame/SteamOS/SteamVR system or runtime settings as part of Baiji
|
||||
development, testing, or deployment, even for temporary experiments. Treat
|
||||
`~/.config/openvr/config/steamvr.vrsettings` and other non-Baiji settings as
|
||||
read-only; keep testing changes within Baiji-owned code, binaries, and config.
|
||||
- Frame build: from the repository root run
|
||||
`INSTALL_PREFIX=/home/steamos/baiji ./scripts/compile-cross-sdk.sh`, then
|
||||
`./scripts/deploy-frame.sh frame`. The build uses Podman, installs the AArch64 KDE SDK
|
||||
into ignored `state/` via Flatpak when missing, rebuilds the image when
|
||||
`Containerfile.cross` changes, and stages to
|
||||
`state/stage-frame/`. Its persistent build/cache are
|
||||
`state/build-baiji/` and `state/ccache-cross-sdk/`. It configures
|
||||
`ENABLE_TESTS=OFF`; this is not a test build.
|
||||
- `scripts/compile.sh [native|aarch64] [target...]` is the general container build
|
||||
helper; it defaults to `native` and `dolphin-emu`. It uses cached local Podman
|
||||
images `baijisteamvr-build:amd64` and `baijisteamvr-build:arm64` and does not rebuild
|
||||
the container environment for each code build. Run `scripts/build-env.sh` for a
|
||||
missing image or after changing `Containerfile.build`; normal `compile.sh` builds
|
||||
reuse the tagged images and ignored `state/build-*` CMake build directories.
|
||||
`state/ccache/` also persists between builds and is wired through CMake compiler
|
||||
launchers. Do not clear either cache for normal edits; a changed compiler/image may
|
||||
cause one full rebuild, but later builds should be incremental. Use
|
||||
`compile-cross-sdk.sh` for the maintained Steam Frame SDK/staging workflow above.
|
||||
- `scripts/compile.sh aarch64 dolphin-emu` builds an arm64 executable at
|
||||
`state/build-aarch64/Binaries/baiji`, but this uses the Ubuntu 26.04 build image
|
||||
(glibc 2.43). The Frame has glibc 2.39, so do not copy that raw executable there;
|
||||
use `compile-cross-sdk.sh` and its Frame-compatible SDK/staging output instead.
|
||||
- For binary-only Frame builds, atomically replace
|
||||
`~/baiji/bin/baiji` with `state/stage-frame/home/steamos/baiji/bin/baiji`; this is
|
||||
the emulator executable launched by `~/baiji/bin/baiji-vr` from the Big Picture /
|
||||
Gamescope shortcut. Leave `baiji-vr` in place. Use `deploy-frame.sh` when staged
|
||||
libraries/assets also changed.
|
||||
The user promoted the current Frame build to known-good on 2026-10-04 despite
|
||||
uncertainty about intermittent controller input and reported performance improvement.
|
||||
Preserve `~/baiji/bin/baiji-known-good`; only replace it on explicit user promotion.
|
||||
To restore the Big Picture shortcut to that build, copy it back to `~/baiji/bin/baiji`.
|
||||
We cannot test headset controls directly from the development host: collaborate with
|
||||
the user on debug runs and retrieve logs over SSH.
|
||||
- On the Frame, creating `~/.config/baiji/debug-logging` makes the existing
|
||||
`baiji-vr` shortcut enable verbose Video/OpenXR/Controller Interface (`CI`) logging.
|
||||
Retrieve `~/.local/share/baiji/Logs/dolphin.log` and
|
||||
`~/.local/share/baiji/Logs/baiji-launcher.log` over SSH; remove the marker to
|
||||
return to normal logging. Collaborate with the user for headset input tests, then
|
||||
inspect the resulting logs.
|
||||
- The configured SSH alias is `frame`. If it is absent on a development machine,
|
||||
ask the user to create it; it makes build transfer and device debugging much easier.
|
||||
- Steam Frame debugging guidance, especially core-dump access and processing, is at
|
||||
<https://partner.steamgames.com/doc/steamhardware/steamframe/debugging>; consult it
|
||||
before retrieving or processing Frame crash dumps.
|
||||
- The deploy script copies Baiji-named files under `~/baiji` on the target. CLI
|
||||
smoke tests are documented in `docs/build-runbook.md`; the GUI launcher is
|
||||
`baiji-vr`.
|
||||
- For a host Linux VR build, configure with
|
||||
`cmake -S . -B Build -DENABLE_VR=ON -DENABLE_VULKAN=ON`, then build with
|
||||
`cmake --build Build --target dolphin-emu -j "$(nproc)"`.
|
||||
- Unit tests are enabled by default in the root CMake configuration, but the
|
||||
Frame cross-build disables them. In a test-enabled build, use
|
||||
`cmake --build <build-dir> --target unittests`; to run a focused GoogleTest,
|
||||
build `tests` and invoke `<build-dir>/Binaries/Tests/tests --gtest_filter=<filter>`.
|
||||
- `Tools/lint.sh` checks changed/staged source files and requires clang-format
|
||||
19.1. See `Contributing.md` for formatting details.
|
||||
- Before changing submodules, inspect their worktrees and preserve local edits.
|
||||
`scripts/fix-submodules.sh` force-checks out fmt and OpenXR revisions; the
|
||||
runbook marks it for reviewed use on a fresh checkout only.
|
||||
- Keep build/cache/staging outputs in ignored `state/` and `dist/`. Do not deploy
|
||||
or alter unrelated existing Frame binaries, user data, or Steam shortcuts;
|
||||
follow the runbook's Baiji-only paths. Do not publish from this checkout unless
|
||||
explicitly requested.
|
||||
- This project is not particularly worried about linting. Don't worry
|
||||
about trying to run clang-format. Nor is there any practical way to
|
||||
unit test most of the work this project is doing as it is all UI work.
|
||||
|
||||
## External technical references
|
||||
|
||||
- [Steam Frame developer setup](https://partner.steamgames.com/doc/steamhardware/steamframe/setup)
|
||||
covers Developer Mode, SSH/ADB access, and recommended beta channels; consult it
|
||||
when setting up or troubleshooting access to a Frame development headset.
|
||||
- [Steam Frame OpenXR engine integrations](https://partner.steamgames.com/doc/steamhardware/steamframe/engines)
|
||||
collects platform-specific OpenXR integration guidance for supported engines.
|
||||
Start here when adapting general OpenXR behavior to the Frame runtime.
|
||||
- [Steam Frame custom engine integration](https://partner.steamgames.com/doc/steamhardware/steamframe/engines/custom)
|
||||
is the more direct reference for applications integrating OpenXR without one of
|
||||
the documented game engines; check its runtime and extension guidance for
|
||||
Frame-specific requirements.
|
||||
- [Steam Frame Input](https://partner.steamgames.com/doc/steamhardware/steamframe/input)
|
||||
documents the headset's controller/input behavior and is useful when investigating
|
||||
controller profiles, bindings, or input expectations on-device.
|
||||
- [Khronos OpenXR Tutorial](https://openxr-tutorial.com/)
|
||||
provides practical, API-level examples of initialization, graphics/swapchains,
|
||||
actions, and extensions across platforms; use it for implementation patterns, then
|
||||
verify runtime-specific support separately.
|
||||
- [Khronos OpenXR 1.1 Specification](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html)
|
||||
is the normative reference for API semantics, synchronization, and extension behavior;
|
||||
consult it when tutorial examples leave behavior ambiguous.
|
||||
- [Khronos OpenXR SDK Source](https://github.com/KhronosGroup/OpenXR-SDK-Source)
|
||||
contains the OpenXR loader and SDK source; use it to investigate loader behavior or
|
||||
SDK integration details, not as a substitute for checking extensions exposed by the
|
||||
Frame runtime.
|
||||
@@ -0,0 +1,34 @@
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index b26bbcc..f687560 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -166 +166 @@ option(
|
||||
- ON
|
||||
+ OFF
|
||||
@@ -167,0 +168,4 @@ option(
|
||||
+if(NOT BUILD_LOADER_WITH_EXCEPTION_HANDLING)
|
||||
+ add_definitions(-DXRLOADER_DISABLE_EXCEPTION_HANDLING)
|
||||
+ add_definitions(-DJSON_USE_EXCEPTIONS=0)
|
||||
+endif()
|
||||
diff --git a/src/loader/CMakeLists.txt b/src/loader/CMakeLists.txt
|
||||
index fead046..9db503f 100644
|
||||
--- a/src/loader/CMakeLists.txt
|
||||
+++ b/src/loader/CMakeLists.txt
|
||||
@@ -157,0 +158,5 @@ endif()
|
||||
+# Parent project (Dolphin) builds with -fno-exceptions, but a few loader
|
||||
+# destructors still contain unconditional catch(...) blocks. Re-enable
|
||||
+# exceptions for this target only so those compile.
|
||||
+target_compile_options(openxr_loader PRIVATE -fexceptions)
|
||||
+
|
||||
diff --git a/src/loader/api_layer_interface.cpp b/src/loader/api_layer_interface.cpp
|
||||
index b8f0881..90f5a31 100644
|
||||
--- a/src/loader/api_layer_interface.cpp
|
||||
+++ b/src/loader/api_layer_interface.cpp
|
||||
@@ -455,0 +456 @@ ApiLayerInterface::~ApiLayerInterface() {
|
||||
+#ifndef XRLOADER_DISABLE_EXCEPTION_HANDLING
|
||||
@@ -456,0 +458 @@ ApiLayerInterface::~ApiLayerInterface() {
|
||||
+#endif
|
||||
@@ -459,0 +462 @@ ApiLayerInterface::~ApiLayerInterface() {
|
||||
+#ifndef XRLOADER_DISABLE_EXCEPTION_HANDLING
|
||||
@@ -465,0 +469 @@ ApiLayerInterface::~ApiLayerInterface() {
|
||||
+#endif
|
||||
+70
-14
@@ -13,7 +13,7 @@ endif()
|
||||
# This is inserted into the Info.plist as well.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0.0" CACHE STRING "")
|
||||
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FlagsOverride.cmake")
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "CMake/FlagsOverride.cmake")
|
||||
|
||||
# CMake 3.28 and later scan c++ source files for module imports by default. Since we don't use
|
||||
# modules scanning is pointless, so disable it. This also prevents Clang from generating an error
|
||||
@@ -23,6 +23,10 @@ set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
|
||||
|
||||
project(dolphin-emu)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_compile_definitions(BAIJI_STEAMVR)
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS "3.25" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
@@ -61,7 +65,7 @@ endif()
|
||||
# Name of the Dolphin distributor. If you redistribute Dolphin builds (forks,
|
||||
# unofficial builds) please consider identifying your distribution with a
|
||||
# unique name here.
|
||||
set(DISTRIBUTOR "None" CACHE STRING "Name of the distributor.")
|
||||
set(DISTRIBUTOR "BaijiSteamVR" CACHE STRING "Name of the distributor.")
|
||||
|
||||
set(DOLPHIN_DEFAULT_UPDATE_TRACK "" CACHE STRING "Name of the default update track. If empty, disables auto-update.")
|
||||
|
||||
@@ -171,7 +175,7 @@ include(RemoveCompileFlag)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Set up paths
|
||||
set(datadir ${CMAKE_INSTALL_FULL_DATADIR}/dolphin-emu CACHE PATH "datadir")
|
||||
set(datadir ${CMAKE_INSTALL_FULL_DATADIR}/baiji CACHE PATH "datadir")
|
||||
add_definitions(-DDATA_DIR="${datadir}/")
|
||||
|
||||
if(CMAKE_SYSROOT)
|
||||
@@ -490,6 +494,13 @@ endif()
|
||||
# TODO: We should have options for dependencies included in the externals to
|
||||
# override autodetection of system libraries and force the usage of the
|
||||
# externals.
|
||||
if (ENABLE_QT AND MSVC)
|
||||
# Windows has no system Qt6 package, so use the vendored one from Externals/Qt (locked to 6.5.1).
|
||||
# On Linux we use the system Qt6 package instead: mixing the vendored Qt6.5.1 (which lacks a DBus
|
||||
# module) with a system Qt6 for DBus fails, since CMake's Qt6 package requires all found
|
||||
# components to share the exact same version.
|
||||
list(PREPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.5.1/x64")
|
||||
endif()
|
||||
include(CheckLib)
|
||||
include(CheckCXXSourceRuns)
|
||||
|
||||
@@ -677,7 +688,46 @@ if(ENABLE_VR)
|
||||
set(BUILD_CONFORMANCE_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_SDK_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(DYNAMIC_LOADER OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(Externals/OpenXR "${CMAKE_BINARY_DIR}/Externals/OpenXR" EXCLUDE_FROM_ALL)
|
||||
|
||||
# Keep the Khronos SDK submodule pinned upstream and apply Baiji's narrow
|
||||
# no-exceptions loader compatibility patch to a binary-tree copy. This also
|
||||
# works when the checked-out source tree is read-only.
|
||||
set(OPENXR_PATCHED_SOURCE_DIR "${CMAKE_BINARY_DIR}/OpenXR-patched-source")
|
||||
file(REMOVE_RECURSE "${OPENXR_PATCHED_SOURCE_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/Externals/OpenXR/"
|
||||
DESTINATION "${OPENXR_PATCHED_SOURCE_DIR}"
|
||||
PATTERN ".git" EXCLUDE)
|
||||
find_program(OPENXR_PATCH_GIT_EXECUTABLE git)
|
||||
if(NOT OPENXR_PATCH_GIT_EXECUTABLE)
|
||||
message(FATAL_ERROR "Git is required to prepare the OpenXR SDK.")
|
||||
endif()
|
||||
set(OPENXR_COMPATIBILITY_PATCH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake/OpenXR-Loader-Exceptions.patch")
|
||||
execute_process(
|
||||
COMMAND "${OPENXR_PATCH_GIT_EXECUTABLE}" -C "${OPENXR_PATCHED_SOURCE_DIR}" apply
|
||||
--unidiff-zero --check "${OPENXR_COMPATIBILITY_PATCH}"
|
||||
RESULT_VARIABLE OPENXR_PATCH_CHECK_RESULT
|
||||
OUTPUT_VARIABLE OPENXR_PATCH_CHECK_OUTPUT
|
||||
ERROR_VARIABLE OPENXR_PATCH_CHECK_ERROR)
|
||||
if(NOT OPENXR_PATCH_CHECK_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"OpenXR compatibility patch does not match the pinned SDK.\n"
|
||||
"${OPENXR_PATCH_CHECK_OUTPUT}\n${OPENXR_PATCH_CHECK_ERROR}")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND "${OPENXR_PATCH_GIT_EXECUTABLE}" -C "${OPENXR_PATCHED_SOURCE_DIR}" apply
|
||||
--unidiff-zero "${OPENXR_COMPATIBILITY_PATCH}"
|
||||
RESULT_VARIABLE OPENXR_PATCH_APPLY_RESULT
|
||||
OUTPUT_VARIABLE OPENXR_PATCH_APPLY_OUTPUT
|
||||
ERROR_VARIABLE OPENXR_PATCH_APPLY_ERROR)
|
||||
if(NOT OPENXR_PATCH_APPLY_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"Could not apply OpenXR compatibility patch.\n"
|
||||
"${OPENXR_PATCH_APPLY_OUTPUT}\n${OPENXR_PATCH_APPLY_ERROR}")
|
||||
endif()
|
||||
|
||||
add_subdirectory("${OPENXR_PATCHED_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/Externals/OpenXR"
|
||||
EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
if(NOT (WIN32 AND _M_ARM_64))
|
||||
@@ -881,22 +931,28 @@ if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux|FreeBSD|OpenBSD|Darwin")
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux|FreeBSD|OpenBSD")
|
||||
# Install the application icon and menu item
|
||||
install(FILES Data/dolphin-emu.svg
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
|
||||
install(FILES Data/dolphin-emu.png
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps)
|
||||
install(FILES Data/dolphin-emu.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
install(FILES Data/baiji.png
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps)
|
||||
install(FILES Data/org.baijisteamvr.BaijiSteamVR.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||
# Install manpages
|
||||
install(FILES Data/dolphin-emu.6
|
||||
install(FILES Data/baiji.6
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man6)
|
||||
install(FILES Data/dolphin-emu-nogui.6
|
||||
install(FILES Data/baiji-nogui.6
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man6)
|
||||
install(PROGRAMS scripts/baiji-vr DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
# packaging information
|
||||
set(CPACK_PACKAGE_NAME "dolphin-emu")
|
||||
set(CPACK_PACKAGE_VENDOR "Dolphin Team")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(CPACK_PACKAGE_NAME "baijisteamvr")
|
||||
set(CPACK_PACKAGE_VENDOR "BaijiSteamVR")
|
||||
set(CPACK_PACKAGE_CONTACT "https://github.com/thejerf/baijiSteamVR")
|
||||
else()
|
||||
set(CPACK_PACKAGE_NAME "dolphin-emu")
|
||||
set(CPACK_PACKAGE_VENDOR "Dolphin Team")
|
||||
set(CPACK_PACKAGE_CONTACT "dolphinxr@example.com")
|
||||
endif()
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${DOLPHIN_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${DOLPHIN_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${DOLPHIN_VERSION_PATCH})
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
FROM ubuntu:26.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# BaijiSteamVR's Linux build dependencies, plus ccache and ninja-build.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
ccache \
|
||||
clang \
|
||||
cmake \
|
||||
file \
|
||||
ninja-build \
|
||||
qt6-base-dev \
|
||||
qt6-base-private-dev \
|
||||
qt6-svg-dev \
|
||||
pkg-config \
|
||||
libgl1-mesa-dev \
|
||||
libx11-dev \
|
||||
libxrandr-dev \
|
||||
libxi-dev \
|
||||
libegl1-mesa-dev \
|
||||
libavcodec-dev \
|
||||
libavformat-dev \
|
||||
libavutil-dev \
|
||||
libswresample-dev \
|
||||
libswscale-dev \
|
||||
libudev-dev \
|
||||
libevdev-dev \
|
||||
libsdl3-dev \
|
||||
glslang-dev \
|
||||
glslang-tools \
|
||||
libpugixml-dev \
|
||||
libenet-dev \
|
||||
libxxhash-dev \
|
||||
libbz2-dev \
|
||||
liblzma-dev \
|
||||
libzstd-dev \
|
||||
zlib1g-dev \
|
||||
libminizip-ng-dev \
|
||||
liblzo2-dev \
|
||||
liblz4-dev \
|
||||
libspng-dev \
|
||||
libcubeb-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libsfml-dev \
|
||||
libminiupnpc-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libhidapi-dev \
|
||||
libsystemd-dev \
|
||||
libgtest-dev \
|
||||
libasound2-dev \
|
||||
libpulse-dev \
|
||||
llvm-dev \
|
||||
libbluetooth-dev \
|
||||
gettext \
|
||||
libvulkan-dev \
|
||||
vulkan-tools \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /work
|
||||
@@ -0,0 +1,49 @@
|
||||
FROM docker.io/library/ubuntu:26.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
cmake \
|
||||
ninja-build \
|
||||
meson \
|
||||
git \
|
||||
ccache \
|
||||
pkgconf \
|
||||
python3 \
|
||||
gettext \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
qemu-user \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
binutils-aarch64-linux-gnu \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Wrapper for CMake try_run and AArch64 SDK tools imported from Qt CMake packages.
|
||||
RUN printf '%s\n' \
|
||||
'#!/bin/sh' \
|
||||
'if [ "$0" = "/usr/local/bin/qemu-aarch64-wrapper" ]; then' \
|
||||
' exec /usr/bin/qemu-aarch64 "$@"' \
|
||||
'fi' \
|
||||
'case "$0" in' \
|
||||
' /usr/bin/*) target="/sysroot/usr/bin/${0##*/}" ;;' \
|
||||
' /usr/lib/libexec/*) target="/sysroot/usr/lib/libexec/${0##*/}" ;;' \
|
||||
' /usr/lib/aarch64-linux-gnu/libexec/kf6/*) target="/sysroot/usr/lib/aarch64-linux-gnu/libexec/kf6/${0##*/}" ;;' \
|
||||
' *) exec /usr/bin/qemu-aarch64 "$@" ;;' \
|
||||
'esac' \
|
||||
'exec /usr/bin/qemu-aarch64 "$target" "$@"' \
|
||||
> /usr/local/bin/qemu-aarch64-wrapper && chmod +x /usr/local/bin/qemu-aarch64-wrapper
|
||||
|
||||
# The KDE SDK's glibc linker scripts use absolute AArch64 library paths.
|
||||
RUN ln -sfn /sysroot/usr/lib/aarch64-linux-gnu/libm.so.6 \
|
||||
/usr/lib/aarch64-linux-gnu/libm.so.6 && \
|
||||
ln -sfn /sysroot/usr/lib/aarch64-linux-gnu/libmvec.so.1 \
|
||||
/usr/lib/aarch64-linux-gnu/libmvec.so.1
|
||||
|
||||
# Qt package exports also check their installed plugin paths during configuration.
|
||||
RUN ln -sfn /sysroot/usr/lib/plugins /usr/lib/plugins
|
||||
|
||||
ENV QEMU_LD_PREFIX=/sysroot
|
||||
ENV CCACHE_DIR=/run/ccache
|
||||
WORKDIR /work
|
||||
+62
-302
@@ -1,302 +1,62 @@
|
||||
# <a name="main-section-overview"></a>Dolphin Coding Style & Legal Requirements
|
||||
|
||||
- [Legal](#legal)
|
||||
- [Coding style introduction](#introduction)
|
||||
- [C++ coding style and formatting](#cpp-coding-style-and-formatting)
|
||||
- [C++ code-specific guidelines](#cpp-code-specific-guidelines)
|
||||
- [Android](#android)
|
||||
- [Help](#help)
|
||||
|
||||
# <a name="legal"></a>Legal
|
||||
|
||||
Summary:
|
||||
|
||||
- [Trade secrets](#trade-secrets)
|
||||
- [Code licensing](#code-licensing)
|
||||
|
||||
## <a name="trade-secrets"></a>Trade secrets
|
||||
|
||||
Following all relevant laws is of utmost importance for an emulation project like Dolphin.
|
||||
|
||||
If you know any confidential information related to the GameCube, Wii, or Triforce, either because you signed a non-disclosure agreement or because you looked at leaked materials, we ask that you don't contribute code to Dolphin **at all**. While accepting code from contributors who know confidential information is legal if the code is unrelated to the confidential information, we refuse to accept code from such contributors because it greatly increases our review burden and increases the legal risk we take.
|
||||
|
||||
Also, this probably goes without saying, but piracy is strictly forbidden both on GitHub and in all other Dolphin channels.
|
||||
|
||||
## <a name="code-licensing"></a>Code licensing
|
||||
|
||||
If you make any contributions to Dolphin after December 1st, 2014, you are agreeing that any code you have contributed will be licensed under the GNU GPL version 2 (or any later version).
|
||||
|
||||
# <a name="introduction"></a>Coding style introduction
|
||||
|
||||
Summary:
|
||||
|
||||
- [Aims](#intro-aims)
|
||||
- [Checking and fixing formatting issues](#intro-formatting-issues)
|
||||
|
||||
## <a name="intro-aims"></a>Aims
|
||||
|
||||
This guide is for developers who wish to contribute to the Dolphin codebase. It details how to properly style and format code for this project. This guide also offers suggestions on specific functions and other elements that may be used in code.
|
||||
|
||||
Following this guide and formatting your code as detailed will likely get your pull request merged much faster than if you don't (assuming the code itself has no mistakes).
|
||||
|
||||
This project uses clang-format 19.1 to check for common style issues. In case of conflicts between this guide and clang-format rules, the latter should be followed instead of this guide.
|
||||
|
||||
## <a name="intro-formatting-issues"></a>Checking and fixing formatting issues
|
||||
|
||||
Windows users need to be careful about line endings. Windows users should configure git to checkout UNIX-style line endings to keep clang-format simple.
|
||||
|
||||
In most cases, clang-format can and **should** be used to automatically reformat code and solve most formatting issues.
|
||||
|
||||
- To run clang-format on all staged files:
|
||||
```
|
||||
git diff --cached --name-only | grep -E '[.](cpp|h|mm)$' | xargs -I {} clang-format -i {}
|
||||
```
|
||||
|
||||
- Formatting issues can be checked for before committing with a lint script that is included with the codebase. To enable it as a pre-commit hook (assuming you are in the repository root):
|
||||
```
|
||||
ln -s ../../Tools/lint.sh .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
- Alternatively, a custom git filter driver can be used to automatically and transparently reformat any changes:
|
||||
```
|
||||
git config filter.clang_format.smudge 'cat'
|
||||
git config filter.clang_format.clean 'clang-format %f'
|
||||
echo '/Source/Core/**/*.cpp filter=clang_format' >> .git/info/attributes
|
||||
echo '/Source/Core/**/*.h filter=clang_format' >> .git/info/attributes
|
||||
echo '/Source/Core/**/*.mm filter=clang_format' >> .git/info/attributes
|
||||
```
|
||||
|
||||
- Visual Studio supports automatically formatting the current document according to the clang-format configuration by pressing <kbd>Control</kbd>+<kbd>K</kbd> followed by <kbd>Control</kbd>+<kbd>D</kbd> (or selecting Edit → Advanced → Format Document). This can be used without separately installing clang-format.
|
||||
|
||||
# <a name="cpp-coding-style-and-formatting"></a>C++ coding style and formatting
|
||||
|
||||
Summary:
|
||||
|
||||
- [General](#cpp-style-general)
|
||||
- [Naming](#cpp-style-naming)
|
||||
- [Conditionals](#cpp-style-conditionals)
|
||||
- [Classes and structs](#cpp-style-classes-and-structs)
|
||||
|
||||
## <a name="cpp-style-general"></a>General
|
||||
- Try to limit lines of code to a maximum of 100 characters.
|
||||
- Note that this does not mean you should try and use all 100 characters every time you have the chance. Typically with well formatted code, you normally shouldn't hit a line count of anything over 80 or 90 characters.
|
||||
- The indentation style we use is 2 spaces per level.
|
||||
- The opening brace for namespaces, classes, functions, enums, structs, unions, conditionals, and loops go on the next line.
|
||||
- With array initializer lists and lambda expressions it is OK to keep the brace on the same line.
|
||||
- References and pointers have the ampersand or asterisk against the type name, not the variable name. Example: `int* var`, not `int *var`.
|
||||
- Don't use multi-line comments (`/* Comment text */`), use single-line comments (`// Comment text`) instead.
|
||||
- Don't collapse single line conditional or loop bodies onto the same line as its header. Put it on the next line.
|
||||
- Yes:
|
||||
|
||||
```c++
|
||||
if (condition)
|
||||
return 0;
|
||||
|
||||
while (var != 0)
|
||||
var--;
|
||||
```
|
||||
- No:
|
||||
|
||||
```c++
|
||||
if (condition) return 0;
|
||||
|
||||
while (var != 0) var--;
|
||||
```
|
||||
|
||||
## <a name="cpp-style-naming"></a>Naming
|
||||
- All class, enum, function, and struct names should be in upper CamelCase. If the name contains an abbreviation uppercase it.
|
||||
- `class SomeClassName`
|
||||
- `enum IPCCommandType`
|
||||
- All compile time constants should be fully uppercased. With constants that have more than one word in them, use an underscore to separate them.
|
||||
- `constexpr double PI = 3.14159;`
|
||||
- `constexpr int MAX_PATH = 260;`
|
||||
- All variables should be lowercase with underscores separating the individual words in the name.
|
||||
- `int this_variable_name;`
|
||||
- Please do not use [Hungarian notation](https://en.wikipedia.org/wiki/Hungarian_notation) prefixes with variables. The only exceptions to this are the variable prefixes below.
|
||||
- Global variables – `g_`
|
||||
- Class variables – `m_`
|
||||
- Static variables – `s_`
|
||||
|
||||
## <a name="cpp-style-conditionals"></a>Conditionals
|
||||
- Do not leave `else` or `else if` conditions dangling unless the `if` condition lacks braces.
|
||||
- Yes:
|
||||
|
||||
```c++
|
||||
if (condition)
|
||||
{
|
||||
// code
|
||||
}
|
||||
else
|
||||
{
|
||||
// code
|
||||
}
|
||||
```
|
||||
- Acceptable:
|
||||
|
||||
```c++
|
||||
if (condition)
|
||||
// code line
|
||||
else
|
||||
// code line
|
||||
```
|
||||
- No:
|
||||
|
||||
```c++
|
||||
if (condition)
|
||||
{
|
||||
// code
|
||||
}
|
||||
else
|
||||
// code line
|
||||
```
|
||||
|
||||
|
||||
## <a name="cpp-style-classes-and-structs"></a>Classes and structs
|
||||
- If making a [POD](https://en.wikipedia.org/wiki/Passive_data_structure) type, use a `struct` for this. Use a `class` otherwise.
|
||||
- Class layout should be in the order, `public`, `protected`, and then `private`.
|
||||
- If one or more of these sections are not needed, then simply don't include them.
|
||||
- For each of the above specified access levels, the contents of each should follow this given order: constructor, destructor, operator overloads, functions, then variables.
|
||||
- When defining the variables, define `static` variables before the non-static ones.
|
||||
|
||||
```c++
|
||||
class ExampleClass : public SomeParent
|
||||
{
|
||||
public:
|
||||
ExampleClass(int x, int y);
|
||||
|
||||
int GetX() const;
|
||||
int GetY() const;
|
||||
|
||||
protected:
|
||||
virtual void SomeProtectedFunction() = 0;
|
||||
static float s_some_variable;
|
||||
|
||||
private:
|
||||
int m_x;
|
||||
int m_y;
|
||||
};
|
||||
```
|
||||
|
||||
# <a name="cpp-code-specific-guidelines"></a>C++ code-specific guidelines
|
||||
|
||||
Summary:
|
||||
|
||||
- [General](#cpp-code-general)
|
||||
- [Headers](#cpp-code-headers)
|
||||
- [Loops](#cpp-code-loops)
|
||||
- [Functions](#cpp-code-functions)
|
||||
- [Classes and Structs](#cpp-code-classes-and-structs)
|
||||
|
||||
## <a name="cpp-code-general"></a>General
|
||||
- The codebase currently uses C++20, though not all compilers support all C++20 features.
|
||||
- See CMakeLists.txt "Enforce minimum compiler versions" for the currently supported compilers.
|
||||
- Use the [nullptr](https://en.cppreference.com/w/cpp/language/nullptr) type over the macro `NULL`.
|
||||
- If a [range-based for loop](https://en.cppreference.com/w/cpp/language/range-for) can be used instead of container iterators, use it.
|
||||
- Obviously, try not to use `goto` unless you have a *really* good reason for it.
|
||||
- If a compiler warning is found, please try and fix it.
|
||||
- Try to avoid using raw pointers (pointers allocated with `new`) as much as possible. There are cases where using a raw pointer is unavoidable, and in these situations it is OK to use them. An example of this is functions from a C library that require them. In cases where it is avoidable, the STL usually has a means to solve this (`vector`, `unique_ptr`, etc).
|
||||
- Do not use the `auto` keyword everywhere. While it's nice that the type can be determined by the compiler, it cannot be resolved at 'readtime' by the developer as easily. Use auto only in cases where it is obvious what the type being assigned is (note: 'obvious' means not having to open other files or reading the header file). Some situations where it is appropriate to use `auto` is when iterating over a `std::map` container in a foreach loop, or to shorten the length of container iterator variable declarations.
|
||||
- Do not use `using namespace [x];` in headers. Try not to use it at all if you can.
|
||||
- The preferred form of the increment and decrement operator in for-loops is prefix-form (e.g. `++var`).
|
||||
|
||||
## <a name="cpp-code-headers"></a>Headers
|
||||
- If a header is not necessary in a certain source file, remove them.
|
||||
- If you find duplicate includes of a certain header, remove it.
|
||||
- When declaring includes in a source file, make sure they follow the given pattern:
|
||||
- The header for the source file
|
||||
- Standard library headers
|
||||
- System-specific headers (these should also likely be in an `#ifdef` block unless the source file itself is system-specific).
|
||||
- Other Dolphin source file headers
|
||||
- Each of the above header sections should also be in alphabetical order
|
||||
- Project source file headers should be included in a way that is relative to the `[Dolphin Root]/Source/Core` directory.
|
||||
- This project uses `#pragma once` as header guards.
|
||||
|
||||
## <a name="cpp-code-loops"></a>Loops
|
||||
- If an infinite loop is required, do not use `for (;;)`, use `while (true)`.
|
||||
- Empty-bodied loops should use braces after their header, not a semicolon.
|
||||
- Yes: `while (condition) {}`
|
||||
- No: `while (condition);`
|
||||
- For do-while loops, place 'while' on the same line as the closing brackets
|
||||
|
||||
```c++
|
||||
do
|
||||
{
|
||||
// code
|
||||
} while (false);
|
||||
```
|
||||
|
||||
## <a name="cpp-code-functions"></a>Functions
|
||||
- If a function parameter is a pointer or reference and its value or data isn't intended to be changed, please mark that parameter as `const`.
|
||||
- Functions that specifically modify their parameters should have the respective parameter(s) marked as a pointer so that the variables being modified are syntactically obvious.
|
||||
- What not to do:
|
||||
|
||||
```c++
|
||||
template<class T>
|
||||
inline void Clamp(T& val, const T& min, const T& max)
|
||||
{
|
||||
if (val < min)
|
||||
val = min;
|
||||
else if (val > max)
|
||||
val = max;
|
||||
}
|
||||
```
|
||||
|
||||
Example call: `Clamp(var, 1000, 5000);`
|
||||
|
||||
- What to do:
|
||||
|
||||
```c++
|
||||
template<class T>
|
||||
inline void Clamp(T* val, const T& min, const T& max)
|
||||
{
|
||||
if (*val < min)
|
||||
*val = min;
|
||||
else if (*val > max)
|
||||
*val = max;
|
||||
}
|
||||
```
|
||||
|
||||
Example call: `Clamp(&var, 1000, 5000);`
|
||||
|
||||
- Class member functions that you do not want to be overridden in inheriting classes should be marked with the `final` specifier.
|
||||
|
||||
```c++
|
||||
class ClassName : ParentClass
|
||||
{
|
||||
public:
|
||||
void Update() final;
|
||||
};
|
||||
```
|
||||
|
||||
- Overridden member functions that can also be inherited should be marked with the `override` specifier to make it easier to see which functions belong to the parent class.
|
||||
|
||||
```c++
|
||||
class ClassName : ParentClass
|
||||
{
|
||||
public:
|
||||
void Update() override;
|
||||
};
|
||||
```
|
||||
|
||||
## <a name="cpp-code-classes-and-structs"></a>Classes and structs
|
||||
- Classes and structs that are not intended to be extended through inheritance should be marked with the `final` specifier.
|
||||
|
||||
```c++
|
||||
class ClassName final : ParentClass
|
||||
{
|
||||
// Class definitions
|
||||
};
|
||||
```
|
||||
|
||||
# <a name="android"></a>Android
|
||||
|
||||
If you are using Kotlin, just use the built-in official Kotlin code style.
|
||||
|
||||
To install the Java code style in Android Studio, select the gear icon in the Code Style settings as shown, select `Import Scheme...` and select `dolphin/Source/Android/code-style-java.xml`. The Code Style menu should look like this when complete. ![Code Style Window][code-style]
|
||||
|
||||
You can now select any section of code and press `Ctrl + Alt + L` to automatically format it.
|
||||
|
||||
# <a name="help"></a>Help
|
||||
If you have any questions about Dolphin's development or would like some help, Dolphin developers use `#dolphin-emu @ irc.libera.chat` to communicate. If you are new to IRC, [Libera.Chat has resources to get started chatting with IRC.](https://libera.chat/)
|
||||
|
||||
[code-style]: https://i.imgur.com/3b3UBhb.png
|
||||
# Contributing to Baiji
|
||||
|
||||
In an era of AI, the value you bring to a PR
|
||||
submitted to any project *IS NOT THE CODE*. Code may not be free yet,
|
||||
but its value is rapidly dropping.
|
||||
|
||||
Or, in other words, I have an AI too. The utility to me of just
|
||||
shoving some AI code at the project is fairly limited.
|
||||
|
||||
The value you bring is [in the
|
||||
*TESTING*](https://jerf.org/iri/post/2026/what_value_code_in_ai_era/).
|
||||
|
||||
You may develop code in any way you like for Baiji, but the value is
|
||||
in the testing, not a code dump.
|
||||
|
||||
Once you have a tested branch in your local repo(s), the AI can walk
|
||||
you through the process of creating a PR if you don't already
|
||||
know. The PR prompt will hopefull guide you in this as well, but
|
||||
please tell us all what testing you have done on your PR.
|
||||
|
||||
That doesn't mean you need to have tested every possible interaction
|
||||
with every possible feature on every possible game. Goodness knows
|
||||
Baiji's work doesn't even remotely rise to that standard either! But
|
||||
it is very helpful to know what testing has and has not been done, so
|
||||
we can know what to look out for, and others may know to make their
|
||||
own PRs against your PR. Do not be shy to say "I haven't tested this
|
||||
with X". The space of "all possible Wii and Gamecube games" is
|
||||
huge.
|
||||
|
||||
Because the true value of a PR is testing, note that _testing_ someone
|
||||
else's PR can be as valuable or even more valuable than coming up with
|
||||
one of your own. Before starting a PR check the PR tab and see if
|
||||
there's anything either close to your work or is what you'd have
|
||||
made. If so, please join with that PR rather than source a new
|
||||
one by building that PR yourself and running it on your local Steam
|
||||
Frame. There is nothing as valuable as the _second_ pair of eyes on a
|
||||
PR!
|
||||
|
||||
# Baiji's Scope
|
||||
|
||||
The scope of Baiji is:
|
||||
|
||||
* The UI as it is presented in Steam OS.
|
||||
* The stereoscopic and VR views.
|
||||
|
||||
The Baiji project will not fix game-specific emulation bugs, unless
|
||||
someone can make an extremely good case for why it really is a Steam
|
||||
Frame-specific issue. Fixing emulation bugs is a frought process of
|
||||
testing hundreds of games for regressions, having deep knowledge of
|
||||
the relevant systems, and testing, testing, testing. Resources Baiji
|
||||
does not have.
|
||||
|
||||
At most, if someone wants to port in the latest Dolphin work, and then
|
||||
test it and see that it is some sort of improvement, I might take
|
||||
that. But it's the only emulation improvement we're going to take.
|
||||
|
||||
As such, all Issues filed about games will be closed without
|
||||
work. Replicate them in the latest official Dolphin release and file
|
||||
them there, if they are still a problem.
|
||||
|
||||
Plus this keeps us out of hot water with Nintendo. We haven't touched
|
||||
the parts of Dolphin Nintendo cares about.
|
||||
@@ -0,0 +1,27 @@
|
||||
[Profile]
|
||||
Device = OpenXR/0/OpenXR Controller
|
||||
Buttons/A = `Right Button A`
|
||||
Buttons/B = `Right Button B`
|
||||
Buttons/X = `Right Button X`
|
||||
Buttons/Y = `Right Button Y`
|
||||
Buttons/Z = `Right Button Squeeze`
|
||||
Buttons/Start = `Right Button Menu`
|
||||
Main Stick/Up = `Left Thumbstick Y+`
|
||||
Main Stick/Down = `Left Thumbstick Y-`
|
||||
Main Stick/Left = `Left Thumbstick X-`
|
||||
Main Stick/Right = `Left Thumbstick X+`
|
||||
Main Stick/Calibration = 100.00
|
||||
C-Stick/Up = `Right Thumbstick Y+`
|
||||
C-Stick/Down = `Right Thumbstick Y-`
|
||||
C-Stick/Left = `Right Thumbstick X-`
|
||||
C-Stick/Right = `Right Thumbstick X+`
|
||||
C-Stick/Calibration = 100.00
|
||||
Triggers/L = `Left Button Trigger`
|
||||
Triggers/R = `Right Button Trigger`
|
||||
Triggers/L-Analog = `Left Trigger`
|
||||
Triggers/R-Analog = `Right Trigger`
|
||||
D-Pad/Up = `Left D-Pad Up`
|
||||
D-Pad/Down = `Left D-Pad Down`
|
||||
D-Pad/Left = `Left D-Pad Left`
|
||||
D-Pad/Right = `Left D-Pad Right`
|
||||
Rumble/Motor = Motor
|
||||
@@ -0,0 +1,5 @@
|
||||
[Profile]
|
||||
Device = OpenXR/0/OpenXR Controller
|
||||
; Right Button Menu is reserved for GameCube Start.
|
||||
General/Stop = `Left Button View`
|
||||
; Steam Frame handles headset recentering; leave the application hotkey unbound.
|
||||
@@ -0,0 +1,31 @@
|
||||
[Profile]
|
||||
Device = OpenXR/0/OpenXR Controller
|
||||
Buttons/A = `Right Button A`
|
||||
Buttons/B = `Right Trigger`
|
||||
Buttons/1 = `Right Button X`
|
||||
Buttons/2 = `Right Button Y`
|
||||
Buttons/- = `Left Button Bumper`
|
||||
Buttons/+ = `Right Button Bumper`
|
||||
Buttons/Home = `Left Button System`
|
||||
D-Pad/Up = `Left D-Pad Up`
|
||||
D-Pad/Down = `Left D-Pad Down`
|
||||
D-Pad/Left = `Left D-Pad Left`
|
||||
D-Pad/Right = `Left D-Pad Right`
|
||||
IR/Up = `Right Thumbstick Y-`
|
||||
IR/Down = `Right Thumbstick Y+`
|
||||
IR/Left = `Right Thumbstick X-`
|
||||
IR/Right = `Right Thumbstick X+`
|
||||
IR/Relative Input = False
|
||||
Shake/X = `Right Button Squeeze`
|
||||
Shake/Y = `Right Button Squeeze`
|
||||
Shake/Z = `Right Button Squeeze`
|
||||
IMUIR/Enabled = False
|
||||
Extension = Nunchuk
|
||||
Nunchuk/Buttons/C = `Left Button Squeeze`
|
||||
Nunchuk/Buttons/Z = `Left Trigger`
|
||||
Nunchuk/Stick/Up = `Left Thumbstick Y+`
|
||||
Nunchuk/Stick/Down = `Left Thumbstick Y-`
|
||||
Nunchuk/Stick/Left = `Left Thumbstick X-`
|
||||
Nunchuk/Stick/Right = `Left Thumbstick X+`
|
||||
Nunchuk/Stick/Calibration = 100 100 100 100 100 100 100 100
|
||||
Rumble/Motor = Motor
|
||||
@@ -0,0 +1,24 @@
|
||||
[Profile]
|
||||
Device = OpenXR/0/OpenXR Controller
|
||||
Buttons/A = `Right Button A`
|
||||
Buttons/B = `Right Trigger`
|
||||
Buttons/1 = `Right Button X`
|
||||
Buttons/2 = `Right Button Y`
|
||||
Buttons/- = `Left Button View`
|
||||
Buttons/+ = `Right Button Menu`
|
||||
Buttons/Home = `Left Button System`
|
||||
D-Pad/Up = `Left D-Pad Up`
|
||||
D-Pad/Down = `Left D-Pad Down`
|
||||
D-Pad/Left = `Left D-Pad Left`
|
||||
D-Pad/Right = `Left D-Pad Right`
|
||||
IR/Up = `Right Thumbstick Y-`
|
||||
IR/Down = `Right Thumbstick Y+`
|
||||
IR/Left = `Right Thumbstick X-`
|
||||
IR/Right = `Right Thumbstick X+`
|
||||
IR/Relative Input = False
|
||||
Shake/X = `Right Button Squeeze`
|
||||
Shake/Y = `Right Button Squeeze`
|
||||
Shake/Z = `Right Button Squeeze`
|
||||
IMUIR/Enabled = False
|
||||
Extension = None
|
||||
Rumble/Motor = Motor
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 548 KiB |
@@ -0,0 +1,29 @@
|
||||
.Dd October 4, 2026
|
||||
.Dt BAIJI-NOGUI 6
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm baiji-nogui
|
||||
.Nd headless GameCube and Wii emulator
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl hv
|
||||
.Op Fl e Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
runs BaijiSteamVR without a graphical user interface.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl e Ar file , Fl Fl exec= Ns Ar file
|
||||
Load the specified file.
|
||||
.It Fl h , Fl Fl help
|
||||
Print a help message.
|
||||
.It Fl v , Fl Fl version
|
||||
Print version and exit.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
.It Pa $HOME/.local/share/baiji
|
||||
Default application data directory.
|
||||
.It Pa $HOME/.config/baiji
|
||||
Default configuration directory.
|
||||
.El
|
||||
@@ -0,0 +1,48 @@
|
||||
.Dd October 4, 2026
|
||||
.Dt BAIJI 6
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm baiji
|
||||
.Nd GameCube and Wii emulator for Steam Frame
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bdhl
|
||||
.Op Fl a Ar audio
|
||||
.Op Fl c Ar str
|
||||
.Op Fl e Ar file
|
||||
.Op Fl m Ar file
|
||||
.Op Fl u Ar path
|
||||
.Op Fl v Ar video
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a GameCube and Wii emulator with a graphical user interface.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a Ar audio , Fl Fl audio_emulation= Ns Ar audio
|
||||
Select low-level or high-level audio emulation.
|
||||
.It Fl b , Fl Fl batch
|
||||
Run without the user interface.
|
||||
.It Fl c Ar text , Fl Fl confirm= Ns Ar text
|
||||
Set confirmation on stop.
|
||||
.It Fl d , Fl Fl debugger
|
||||
Open the debugger.
|
||||
.It Fl e Ar file , Fl Fl exec= Ns Ar file
|
||||
Load the specified file.
|
||||
.It Fl h , Fl Fl help
|
||||
Print a help message.
|
||||
.It Fl l , Fl Fl logger
|
||||
Open the logger.
|
||||
.It Fl m Ar file , Fl Fl movie= Ns Ar file
|
||||
Play a movie file.
|
||||
.It Fl u Ar path , Fl Fl user= Ns Ar path
|
||||
Set the user folder path.
|
||||
.It Fl v , Fl Fl video_backend= Ns Ar video
|
||||
Select a video backend.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
.It Pa $HOME/.local/share/baiji
|
||||
Default application data directory.
|
||||
.It Pa $HOME/.config/baiji
|
||||
Default configuration directory.
|
||||
.El
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=BaijiSteamVR
|
||||
GenericName=VR GameCube/Wii Emulator
|
||||
Comment=GameCube and Wii emulator for Steam Frame
|
||||
Icon=baiji
|
||||
Exec=/home/steamos/baiji/bin/baiji-vr
|
||||
TryExec=/home/steamos/baiji/bin/baiji-vr
|
||||
Terminal=false
|
||||
Categories=Game;Emulator;
|
||||
StartupWMClass=BaijiSteamVR
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
FROM ubuntu:26.04
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
file \
|
||||
qt6-base-dev \
|
||||
qt6-base-private-dev \
|
||||
qt6-svg-dev \
|
||||
pkg-config \
|
||||
libgl1-mesa-dev \
|
||||
libx11-dev \
|
||||
libxrandr-dev \
|
||||
libxi-dev \
|
||||
libegl1-mesa-dev \
|
||||
libavcodec-dev \
|
||||
libavformat-dev \
|
||||
libavutil-dev \
|
||||
libswresample-dev \
|
||||
libswscale-dev \
|
||||
libudev-dev \
|
||||
libevdev-dev \
|
||||
libsdl3-dev \
|
||||
glslang-dev \
|
||||
glslang-tools \
|
||||
libpugixml-dev \
|
||||
libenet-dev \
|
||||
libxxhash-dev \
|
||||
libbz2-dev \
|
||||
liblzma-dev \
|
||||
libzstd-dev \
|
||||
zlib1g-dev \
|
||||
libminizip-ng-dev \
|
||||
liblzo2-dev \
|
||||
liblz4-dev \
|
||||
libspng-dev \
|
||||
libcubeb-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libsfml-dev \
|
||||
libminiupnpc-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libhidapi-dev \
|
||||
libsystemd-dev \
|
||||
libgtest-dev \
|
||||
libasound2-dev \
|
||||
libpulse-dev \
|
||||
llvm-dev \
|
||||
libbluetooth-dev \
|
||||
gettext \
|
||||
libvulkan-dev \
|
||||
vulkan-tools
|
||||
## fmt that comes with ubuntu 26 also seems incorrect.
|
||||
# libfmt-dev \
|
||||
|
||||
RUN mkdir -p /app/dolphinxr
|
||||
WORKDIR /app/dolphinxr
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN mkdir Build \
|
||||
&& cd Build \
|
||||
&& cmake .. -DENABLE_VR=ON -DENABLE_VULKAN=ON -DUSE_SYSTEM_MBEDTLS=OFF -DUSE_SYSTEM_LIBMGBA=OFF \
|
||||
&& cd .. \
|
||||
&& cmake --build Build --target dolphin-emu -j $(nproc)
|
||||
Vendored
+1
-1
Submodule Externals/OpenXR updated: 472d817ffe...f2448a8797.
Vendored
+1
-1
Submodule Externals/Qt updated: 495517af2b...306289108d.
Vendored
+1
-1
Submodule Externals/fmt/fmt updated: e424e3f2e6...0c9fce2ffe.
@@ -0,0 +1,18 @@
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index 7efde81..9d5e1fd 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -163,8 +163,12 @@ option(BUILD_ALL_EXTENSIONS "Build loader and layers with all extensions" OFF)
|
||||
option(
|
||||
BUILD_LOADER_WITH_EXCEPTION_HANDLING
|
||||
"Enable exception handling in the loader. Leave this on unless your standard library is built to not throw."
|
||||
- ON
|
||||
+ OFF
|
||||
)
|
||||
+if(NOT BUILD_LOADER_WITH_EXCEPTION_HANDLING)
|
||||
+ add_definitions(-DXRLOADER_DISABLE_EXCEPTION_HANDLING)
|
||||
+ add_definitions(-DJSON_USE_EXCEPTIONS=0)
|
||||
+endif()
|
||||
|
||||
if(WIN32)
|
||||
set(OPENXR_DEBUG_POSTFIX
|
||||
@@ -1,251 +1,310 @@
|
||||
# Dolphin - A GameCube and Wii Emulator
|
||||
# Baiji - Steam Frame-specific fork of DolphinXR, a fork of Dolphin
|
||||
|
||||
[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Buildbot](https://dolphin.ci/) | [Forums](https://forums.dolphin-emu.org/) | [Wiki](https://wiki.dolphin-emu.org/) | [GitHub Wiki](https://github.com/dolphin-emu/dolphin/wiki) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://app.transifex.com/dolphinemu/dolphin-emu/dashboard/) | [Analytics](https://mon.dolphin-emu.org/)
|
||||
Baiji is an AI-slop fork of
|
||||
[dolphinXR](https://github.com/iChris4/dolphinXR/), a "developed with
|
||||
the use of AI tools" (straight from their readme) fork of Dolphin.
|
||||
|
||||
Dolphin is an emulator for running GameCube and Wii games on Windows,
|
||||
Linux, macOS, and recent Android devices. It's licensed under the terms
|
||||
of the GNU General Public License, version 2 or later (GPLv2+).
|
||||
Baiji may be AI slop but this Readme.md is organic and home-grown by a
|
||||
human.
|
||||
|
||||
This fork adds OpenXR support to Dolphin so users can play in VR on Windows,
|
||||
desktop Linux, and standalone Meta Quest headsets, and was developed with the
|
||||
use of AI tools.
|
||||
Baiji is intended to be a near-term fork that directly integrates with
|
||||
the Steam Frame, removing the complication of trying to figure out how
|
||||
to stream VR from a remote computer, deal with VR control schemes,
|
||||
etc., and so forth, making a fork of Dolphin that _just works_ in 3D
|
||||
on the Steam Frame.
|
||||
|
||||
* **Windows** — VR runs on the Direct3D 11, Direct3D 12, Vulkan, and OpenGL
|
||||
backends with any OpenXR runtime (SteamVR, Oculus/Meta Link, VDXR, etc.).
|
||||
* **Linux** — VR runs on the Vulkan and OpenGL backends and requires a working
|
||||
system OpenXR runtime such as Monado or SteamVR.
|
||||
* **Meta Quest** — a standalone Android build (Quest 2, Quest 3, Quest 3S, and
|
||||
Quest Pro) renders natively in the headset on the Vulkan and OpenGL ES
|
||||
backends, with OpenXR controller support.
|
||||
3D? Did I say 3D? Yes, 3D. Core Dolphin has a long-standing feature
|
||||
called [stereoscopic
|
||||
3D](https://wiki.dolphin-emu.org/index.php?title=Stereoscopic_3D_Setup),
|
||||
which allows the running of Dolphin on a 3D monitor or with 3D
|
||||
glasses. However the hardware is specialized and the setup was not VR
|
||||
aware, so a default Dolphin install can only run flat on a virtual
|
||||
screen.
|
||||
|
||||
Please read the [FAQ](https://dolphin-emu.org/docs/faq/) before using Dolphin.
|
||||
The primary purpose of this fork is to make this stereoscopic 3D Just
|
||||
Work™. I can't show what this looks like in a static shot on GitHub,
|
||||
but if you can cross your eyes, here's [Super Mario Galaxy 2 in
|
||||
stereoscopic 3D on
|
||||
YouTube](https://www.youtube.com/watch?v=XmgdqCL2toE). I found a
|
||||
normal phone a pretty good way to view that with cross-eyes; getting
|
||||
the sizing right on a desktop is pretty challenging.
|
||||
|
||||
## System Requirements
|
||||
In principle it is as easy as installing Baiji, getting a legal file
|
||||
Dolphin can read as a Wii game, and starting the ROM. Baiji should
|
||||
come up with a sensible Steam Frame controller mapping for a WiiMote +
|
||||
Nunchunk, in stereoscopic 3D, with sensible performance settings
|
||||
(which includes "precompiling shaders" before startup, though you may
|
||||
see some initial stutters as the cache is built out), and be off to
|
||||
the races. In practice, this is the work of a long weekend and I've
|
||||
tested a whopping 4 games, only one from the Gamecube, and one of
|
||||
which had an early crash with at least one of the development
|
||||
version.
|
||||
|
||||
### Desktop
|
||||
So don't expect miracles.
|
||||
|
||||
* OS
|
||||
* Windows (10 1903 or higher).
|
||||
* Linux.
|
||||
* macOS (11.0 Big Sur or higher).
|
||||
* Unix-like systems other than Linux are not officially supported but might work.
|
||||
* Processor
|
||||
* A CPU with SSE2 support.
|
||||
* A modern CPU (3 GHz and Dual Core, not older than 2008) is highly recommended.
|
||||
* Graphics
|
||||
* A reasonably modern graphics card (Direct3D 11.1 / OpenGL 3.3).
|
||||
* A graphics card that supports Direct3D 11.1 / OpenGL 4.4 is recommended.
|
||||
But I figured this had gotten to the point where more eyes was the
|
||||
better way to go.
|
||||
|
||||
### Android
|
||||
A ["Baiji" is a possibly-extinct subspecies of
|
||||
dolphin](https://en.wikipedia.org/wiki/Baiji). Most dolphin species
|
||||
have clumsy, branding-unfriendly names like "Hector's Dolphin". Baiji
|
||||
is a nice snappy name. Baiji are also possibly extinct, which
|
||||
represents the fact I don't necessarily expect this to be a long-term
|
||||
fork of the Dolphin project. I expect that someday, they will
|
||||
incorporate the major features of this project into the
|
||||
mainline, and that will mark the end of this fork. However, due to
|
||||
their completely rational and justifiable policy about AI, it may take
|
||||
some time because they can not and will not just pick this code up.
|
||||
|
||||
* OS
|
||||
* Android (5.0 Lollipop or higher).
|
||||
* Processor
|
||||
* A processor with support for 64-bit applications (either ARMv8 or x86-64).
|
||||
* Graphics
|
||||
* A graphics processor that supports OpenGL ES 3.0 or higher. Performance varies heavily with [driver quality](https://dolphin-emu.org/blog/2013/09/26/dolphin-emulator-and-opengl-drivers-hall-fameshame/).
|
||||
* A graphics processor that supports standard desktop OpenGL features is recommended for best performance.
|
||||
I also aspire to demonstrate the utility for any emulator of any 3D
|
||||
system of building a native Steam Frame build that Just Works™ with
|
||||
similar stereoscopic 3D, until someday the release of Baiji is looked
|
||||
back as the harbinger of when running the Emustation or similar
|
||||
install script doesn't just install a bunch of flat emulators but
|
||||
installs 3D-aware emulators for all the 3D systems. Especially the
|
||||
3DS, because as the only native 3D commercial gaming system that will
|
||||
not have the issues with eye-twisting things like text behind other 3D
|
||||
objects and stuff.
|
||||
|
||||
Dolphin can only be installed on devices that satisfy the above requirements. Attempting to install on an unsupported device will fail and display an error message.
|
||||
I aspire to see the Steam Frame become considered
|
||||
_the_ definitive way to emulate 3D-based systems because of the additional
|
||||
3D experience it can offer, out of the box, such that anyone can use
|
||||
it without trying to get widely disparate enviromnents and libraries
|
||||
and streaming and everything set up. Perhaps even, dare I think it,
|
||||
that this use case becomes considered one of the definitive reasons to
|
||||
get a Steam Frame. Vive le matériel libre.
|
||||
|
||||
### VR (OpenXR)
|
||||
# Features
|
||||
|
||||
* Windows
|
||||
* An OpenXR runtime (SteamVR, Oculus/Meta Link, VDXR, etc.) and a headset it supports.
|
||||
* Direct3D 11, Direct3D 12, Vulkan, or OpenGL backend.
|
||||
* Linux
|
||||
* An OpenXR runtime such as Monado or SteamVR.
|
||||
* Vulkan (recommended) or OpenGL backend.
|
||||
* Meta Quest
|
||||
* Quest 2, Quest 3, Quest 3S, or Quest Pro, running the standalone `quest` build.
|
||||
* Vulkan or OpenGL ES backend.
|
||||
* VR is not supported on macOS.
|
||||
* Steam Frame-centric default settings, including mappings and such.
|
||||
* Integrated Stereoscopic 3D, including some new settings not in the
|
||||
original 3D support of use in VR.
|
||||
* Retained the VR work from the dolphinXR branch, selectable in a
|
||||
drop-down.
|
||||
* Also retained flat mode, where at least the default Steam Frame
|
||||
configurations can be of some use.
|
||||
* Controller configuration that works in the Steam Frame UI.
|
||||
|
||||
## Building for Windows
|
||||
# Installation And Startup
|
||||
|
||||
Use the solution file `Source/dolphin-emu.sln` to build Dolphin on Windows.
|
||||
Dolphin targets the latest MSVC shipped with Visual Studio or Build Tools.
|
||||
Other compilers might be able to build Dolphin on Windows but have not been
|
||||
tested and are not recommended to be used. Git and latest Windows SDK must be
|
||||
installed when building.
|
||||
Unfortunately, as far as I can tell, it is not currently possible to
|
||||
release this as a Flatpak, because Flatpak software can not get to the
|
||||
VR infrastructure. I expect this to change over time, but who knows
|
||||
when.
|
||||
|
||||
Make sure to pull submodules before building:
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
## Install From Snapshot
|
||||
|
||||
### Building the OpenXR VR version
|
||||
(These instructions assume you haven't changed the `steamos` user. If
|
||||
you don't know what that means, you haven't. I think some paths end up
|
||||
in the executable. If you have changed it, you may need to do some
|
||||
symlinking or hardlinking to have this end up unpacked into
|
||||
`/home/steamos/baiji`.)
|
||||
|
||||
To build the VR-enabled version of this fork, OpenXR support must be enabled
|
||||
with `-DENABLE_VR=ON`. VR is supported on Windows, desktop Linux, and Android
|
||||
(Meta Quest); see the Linux and Android sections below for those platforms.
|
||||
1. Start the Desktop environment in your Steam Frame.
|
||||
2. Navigate to this URL in a browser.
|
||||
3. Start `Konsole`, or the terminal of your choice.
|
||||
4. Copy this by clicking on the little double-square next to these
|
||||
commands:
|
||||
|
||||
If you are generating a Visual Studio build with CMake, configure with
|
||||
`-DENABLE_VR=ON`:
|
||||
```sh
|
||||
cmake -S . -B Build-vs2022 -G "Visual Studio 17 2022" -A x64 -DENABLE_VR=ON
|
||||
```
|
||||
```bash
|
||||
cd
|
||||
wget https://github.com/thejerf/baijiSteamVR/releases/download/baiji-v0.1-alpha/baiji-v0.1-alpha.tar.bz2
|
||||
tar xjf baiji-v0.1-alpha.tar.bz2
|
||||
ssh frame "steamos-add-to-steam ./baiji/bin/baiji-vr"
|
||||
```
|
||||
5. Paste that into your Konsole session and hit "enter" on the
|
||||
keyboard.
|
||||
|
||||
`baiji-vr` will appear as an option in your Non-Steam Games library.
|
||||
|
||||
When using the Visual Studio generator, build the OpenXR loader first:
|
||||
```sh
|
||||
cmake --build Build-vs2022 --config Release --target openxr_loader
|
||||
```
|
||||
From there you'll need to load it up with your legally-acquired ROMs.
|
||||
|
||||
Finally, build Dolphin:
|
||||
```sh
|
||||
cmake --build Build-vs2022 --config Release --target dolphin-emu
|
||||
```
|
||||
## Build and Install From an x86_64 Linux Machine
|
||||
|
||||
If you prefer building OpenXR separately first, the repository also includes
|
||||
`Externals/OpenXR/build-win64/OPENXR.sln`.
|
||||
This is the maintained way to build a Steam Frame version. The host needs
|
||||
Git and Podman. If the AArch64 KDE SDK is not already present in the
|
||||
checkout, Flatpak is needed on the first build to install it into ignored
|
||||
`state/` build data. This SDK is a compiler sysroot; Baiji itself is built
|
||||
as a regular executable, not a Flatpak. QEMU's AArch64 emulator is installed
|
||||
in the build image, so the host does not need to provide it.
|
||||
|
||||
The "Release" solution configuration includes performance optimizations for the best user experience but complicates debugging Dolphin.
|
||||
The "Debug" solution configuration is significantly slower, more verbose and less permissive but makes debugging Dolphin easier.
|
||||
1. Turn on Developer Mode on the Frame and enable SSH access. Configure an
|
||||
SSH host alias on your Linux machine (replace the example address with
|
||||
the Frame's IP address):
|
||||
|
||||
## Building for Linux and macOS
|
||||
```sshconfig
|
||||
Host frame
|
||||
HostName 192.168.1.123
|
||||
User steamos
|
||||
```
|
||||
|
||||
Dolphin requires [CMake](https://cmake.org/) for systems other than Windows.
|
||||
You need a recent version of GCC or Clang with decent c++20 support. CMake will
|
||||
inform you if your compiler is too old.
|
||||
Many libraries are bundled with Dolphin and used if they're not installed on
|
||||
your system. CMake will inform you if a bundled library is used or if you need
|
||||
to install any missing packages yourself. You may refer to the [wiki](https://github.com/dolphin-emu/dolphin/wiki/Building-for-Linux) for more information.
|
||||
Verify the connection with `ssh frame`. If you use a different alias,
|
||||
pass it instead of `frame` in the deploy command below.
|
||||
|
||||
Make sure to pull submodules before building:
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
2. Clone baiji, set up some necessary cross-compilation code, build,
|
||||
and deploy:
|
||||
|
||||
### Building the OpenXR VR version on Linux:
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/thejerf/baijiSteamVR.git
|
||||
cd baijiSteamVR
|
||||
./scripts/compile-cross-sdk.sh
|
||||
./scripts/deploy-frame.sh frame
|
||||
ssh frame "steamos-add-to-steam ./baiji/bin/baiji-vr"
|
||||
```
|
||||
|
||||
OpenXR VR is available on desktop Linux (it is not supported on macOS). It
|
||||
requires a working system OpenXR runtime such as Monado or SteamVR, and runs on
|
||||
the Vulkan and OpenGL backends. Configure with OpenXR and Vulkan enabled:
|
||||
Debug symbols are omitted by default. To include them, run the build command as
|
||||
`DEBUG_SYMBOLS=1 ./scripts/compile-cross-sdk.sh`.
|
||||
|
||||
```sh
|
||||
cmake -S . -B Build -DENABLE_VR=ON -DENABLE_VULKAN=ON
|
||||
cmake --build Build --target dolphin-emu -j $(nproc)
|
||||
```
|
||||
These instructions build the current checkout rather than a packaged
|
||||
release, so the code may be unstable.
|
||||
|
||||
OpenGL (GLX) is always built on desktop Linux, so VR remains usable even
|
||||
without `-DENABLE_VULKAN=ON`, though Vulkan is recommended.
|
||||
The build stages the Frame-compatible files under
|
||||
`state/stage-frame/home/steamos/baiji` before transferring them. The
|
||||
deploy script installs Baiji's executables, private libraries, and data
|
||||
under `~/baiji`.
|
||||
|
||||
### macOS Build Steps:
|
||||
3. On the Frame, launch `~/baiji/bin/baiji-vr` from a Desktop terminal, or
|
||||
add that path as a non-Steam game to launch it from Big
|
||||
Picture. Add legally dumped game images through Baiji's open dialog or configure the
|
||||
game search paths in Baiji.
|
||||
|
||||
A binary supporting a single architecture can be built using the following steps:
|
||||
I don't use Windows but any ol' AI can probably adapt this to a
|
||||
Windows or MacOS build process pretty easily. If an AI offers to build
|
||||
you an "emulation-based" toolchain, where it runs a native ARM
|
||||
toolchain on an x86 CPU, decline that. It was miserably slow. I don't
|
||||
know about ARM-based Mac OS machines.
|
||||
|
||||
1. `mkdir build`
|
||||
2. `cd build`
|
||||
3. `cmake ..`
|
||||
4. `make -j $(sysctl -n hw.logicalcpu)`
|
||||
# Performance Issues
|
||||
|
||||
An application bundle will be created in `./Binaries`.
|
||||
* Remarkably, there are still even some Gamecube games that the Steam
|
||||
Frame can struggle with. I have verified this with a native build of
|
||||
Dolphin 2609: The Steam Frame can only barely push Wind Waker
|
||||
at native resolution on one screen, and it still makes some stutters
|
||||
even so. The good news is, if you sit through the emulation stuttering,
|
||||
it actually doesn't look all that great in 3D. The cell shading effect
|
||||
flattens everything out into a rather visually boring 3D effect,
|
||||
rather than looking awesome, so we're not missing anything.
|
||||
|
||||
A script is also provided to build universal binaries supporting both x64 and ARM in the same
|
||||
application bundle using the following steps:
|
||||
# Ownership
|
||||
|
||||
1. `mkdir build`
|
||||
2. `cd build`
|
||||
3. `python ../BuildMacOSUniversalBinary.py`
|
||||
4. Universal binaries will be available in the `universal` folder
|
||||
I see a number of other people are working on similar forks. Honestly,
|
||||
I don't really care to own this. All I want is the stereoscopic 3D,
|
||||
even if you pursue VR being another option, because of the ability to
|
||||
manipulate the stereoscopic 3D settings as I have them in this repo
|
||||
and the utility I think that will have. (Skies of Arcadia is seriously
|
||||
eye-crossing if you don't turn down the 3D.) Have a look at the
|
||||
reconfigured UI for the VR panel in this branch and how it allows you
|
||||
to select the various options. If anyone wants to have their AI look
|
||||
over my patch stream, break it down by feature, and incorporate it
|
||||
into your project, that's great. You can have the branding too if you
|
||||
like. I don't care.
|
||||
|
||||
Doing this is more complex as it requires installation of library dependencies for both x64 and ARM (or universal library
|
||||
equivalents) and may require specifying additional arguments to point to relevant library locations.
|
||||
Execute BuildMacOSUniversalBinary.py --help for more details.
|
||||
# Known Quirks
|
||||
|
||||
### Linux Global Build Steps:
|
||||
* In Stereoscopic 3D mode, stopping the emulation (default the "View"
|
||||
button, the button on top of the left controller) pops up a dialog
|
||||
box in the QT environment asking you if you want to stop
|
||||
emulation. The user experience is that emulation just freezes and
|
||||
there is no indication of this. You must hit the Steam button to
|
||||
pull up the Steam UI, and then, it seems to be random whether it
|
||||
shows the default Steam OS controls for stopping or resuming the
|
||||
game or the QT UI. You can select the QT UI from the list of running
|
||||
windows on the left, then click "Yes", and emulation will stop and
|
||||
control return to the main UI.
|
||||
* You may need to recenter once to align the pointer in Stereoscopic
|
||||
3D mode.
|
||||
* If you choose to emulate in Flat Mode, your controllers will be in
|
||||
laser mode when you click "play". You *must* be in gamepad mode to
|
||||
actually play the game. I panicked several times during
|
||||
development that I had broken controller support but it was just
|
||||
that I had forgotten to switch. There is a dialog that should remind
|
||||
you. Note this is an aspect of the Steam OS, not Baiji.
|
||||
* The main UI
|
||||
is mostly frozen during emulation. But only mostly. Still, best just
|
||||
to treat it as frozen until you stop the emulation.
|
||||
* The "Immersive VR" only works with a certain set of settings,
|
||||
but they are not locked in when it is selected. This is next
|
||||
on the agenda.
|
||||
|
||||
To install to your system.
|
||||
# The Usual Fake FAQs
|
||||
|
||||
1. `mkdir build`
|
||||
2. `cd build`
|
||||
3. `cmake ..`
|
||||
4. `make -j $(nproc)`
|
||||
5. `sudo make install`
|
||||
Most FAQs aren't really "frequently asked", they're just made up
|
||||
things the developer expects to be asked. This list is no different.
|
||||
|
||||
### Linux Local Build Steps:
|
||||
## Why Not A Flatpak?
|
||||
|
||||
Useful for development as root access is not required.
|
||||
As near as I can tell, it is currently *impossible* to get to VR from
|
||||
a flatpak, and the reason why can only be fixed by Valve.
|
||||
|
||||
1. `mkdir Build`
|
||||
2. `cd Build`
|
||||
3. `cmake .. -DLINUX_LOCAL_DEV=true`
|
||||
4. `make -j $(nproc)`
|
||||
5. `ln -s ../../Data/Sys Binaries/`
|
||||
To get to VR, you need to open a Unix socket to the VR server. The VR
|
||||
server has some validation on the incoming PID and possibly some other
|
||||
checks that flatpaks can't pass. The AI and tried some hacking around
|
||||
but I was focused on getting this to work at all and didn't bang on
|
||||
this too hard.
|
||||
|
||||
### Linux Portable Build Steps:
|
||||
A successful Flatpak PR that proves me wrong is one I'd accept with gusto.
|
||||
|
||||
Can be stored on external storage and used on different Linux systems.
|
||||
Or useful for having multiple distinct Dolphin setups for testing/development/TAS.
|
||||
This also, unfortunately, suggests that until this is fixed, it may
|
||||
not be a great idea to try to pack this with Emustation or
|
||||
anything. If they disagree I have no objection, but I would suggest
|
||||
that at least as I write this, this project is not necessarily ready
|
||||
for that sort of prime time.
|
||||
|
||||
1. `mkdir Build`
|
||||
2. `cd Build`
|
||||
3. `cmake .. -DLINUX_LOCAL_DEV=true`
|
||||
4. `make -j $(nproc)`
|
||||
5. `cp -r ../Data/Sys/ Binaries/`
|
||||
6. `touch Binaries/portable.txt`
|
||||
## Why Did You Rename This Project? Are You Trying To Steal Credit Or Something?
|
||||
|
||||
## Building for Android
|
||||
No, this is actually out of politeness to the Dolphin project, and I
|
||||
believe in accordance with their wishes. The name of the project isn't
|
||||
just about the name of the executable or the title screen that comes
|
||||
up when you run it. It's about who is standing behind it and who is
|
||||
responsible for it.
|
||||
|
||||
These instructions assume familiarity with Android development. If you do not have an
|
||||
Android dev environment set up, see [AndroidSetup.md](AndroidSetup.md).
|
||||
The Dolphin team is not behind this project. In particular that means,
|
||||
if the pieces break, you own them, maybe I have a bit of
|
||||
responsibility for them, but the Dolphin team has no responsibility
|
||||
whatsoever. Not even the polite one of at least listening to your
|
||||
problem. The correct solution for the Dolphin project, if anyone files a
|
||||
bug with them, or starts a forum thread about bugs in Baiji, or
|
||||
anything else like that, is to immediately close it/lock it, and scold
|
||||
you a bit for putting it in the wrong place.
|
||||
|
||||
Make sure to pull submodules before building:
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
Renaming this project is part of a statement that says, if you have a
|
||||
problem with Baiji, you do not go to the Dolphin forum for support any
|
||||
more than you'd go there for support with LibreOffice.
|
||||
|
||||
If using Android Studio, import the Gradle project located in `./Source/Android`.
|
||||
Anyone who distributes a very modified version of an open source
|
||||
project, especially if like me the _know_ upstream can not and will
|
||||
not take their patches as-is, _should_ rename the project.
|
||||
|
||||
Android apps are compiled using a build system called Gradle. Dolphin's native component,
|
||||
however, is compiled using CMake. The Gradle script will attempt to run a CMake build
|
||||
automatically while building the Java code.
|
||||
Me trying to steal credit would look like me trying to erase all signs
|
||||
of the Dolphin heritage out of the executable entirely.
|
||||
|
||||
### Building the Meta Quest VR version
|
||||
Instead: I am a mere minnow next to the awesome Dolphin project. I am standing
|
||||
on the shoulder of their giantness, and to a lesser but still
|
||||
significant extent, on the work of the dolphinXR fork. I am
|
||||
deeply appreciative and while I want to help the Steam Frame, this is
|
||||
a mere trivial "couple o' weekends" gloss on top of the
|
||||
who-knows-how-many person-centuries of work the Dolphin project
|
||||
represents. Do not overestimate my "contribution". Nothing in this
|
||||
paragraph is a joke or even slightly sarcastic.
|
||||
|
||||
The Android project has two product flavors on the `device` dimension:
|
||||
`standard` (phones and tablets, built with `-DENABLE_VR=OFF`) and `quest`
|
||||
(standalone headsets, built with `-DENABLE_VR=ON`). The `quest` flavor is
|
||||
arm64-only, installs under the application ID `org.dolphinemu.dolphinemu.quest`
|
||||
so it can live alongside a standard install, and declares the OpenXR manifest
|
||||
entries required by Quest 2, Quest 3, Quest 3S, and Quest Pro.
|
||||
On that note, if I've screwed up licensing or if anyone from the
|
||||
Dolphin project has opinions about the details around how I've done
|
||||
this, I am very open to change, correction, PRs on this matter,
|
||||
etc. This is a sign of me trying to do it very correctly and
|
||||
carefully, not carelessly, and not to steal credit.
|
||||
|
||||
Build it with Gradle from `Source/Android`:
|
||||
```sh
|
||||
./gradlew assembleQuestDebug # or assembleQuestRelease
|
||||
```
|
||||
|
||||
Helper scripts are also provided for Windows:
|
||||
```powershell
|
||||
.\Source\Android\build-quest.ps1 # debug APK
|
||||
.\Source\Android\build-quest-release.ps1 # release APK (needs signing properties)
|
||||
```
|
||||
|
||||
Install the resulting APK on a headset with adb:
|
||||
```sh
|
||||
adb install -r Source/Android/app/build/outputs/apk/quest/debug/app-quest-debug.apk
|
||||
```
|
||||
|
||||
VR settings for the headset (launch in VR, resolution scale, reference space,
|
||||
controller bindings, and so on) live under the OpenXR section of the in-app
|
||||
settings.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
On Windows, simply remove the extracted directory, unless it was installed with the NSIS installer,
|
||||
in which case you can uninstall Dolphin like any other Windows application.
|
||||
|
||||
Linux users can run `cat install_manifest.txt | xargs -d '\n' rm` as root from the build directory
|
||||
to uninstall Dolphin from their system.
|
||||
|
||||
macOS users can simply delete Dolphin.app to uninstall it.
|
||||
|
||||
Additionally, you'll want to remove the global user directory if you don't plan on reinstalling Dolphin.
|
||||
# Command Line Tooling
|
||||
|
||||
## Command Line Usage
|
||||
|
||||
Command line is inherited from Dolphin, just renamed. This has not
|
||||
been gone over with a fine-toothed comb and may contain options not
|
||||
relevant to the Steam Frame, may partially or completely not work on a
|
||||
Steam Frame (e.g. I have no idea what a "movie" will do on a Steam
|
||||
Frame, especially in its various modes), etc.
|
||||
|
||||
```
|
||||
Usage: Dolphin.exe [options]... [FILE]...
|
||||
Usage: baiji [options]... [FILE]...
|
||||
|
||||
Options:
|
||||
--version show program's version number and exit
|
||||
@@ -277,14 +336,10 @@ LLE (Low Level Emulation). HLE is faster but less accurate whereas
|
||||
LLE is slower but close to perfect. Note that LLE has two submodes (Interpreter and Recompiler)
|
||||
but they cannot be selected from the command line.
|
||||
|
||||
Available video backends are "D3D" and "D3D12" (they are only available on Windows), "OGL", and "Vulkan".
|
||||
There's also "Null", which will not render anything, and
|
||||
"Software Renderer", which uses the CPU for rendering and
|
||||
is intended for debugging purposes only.
|
||||
## Baiji Tool Usage
|
||||
|
||||
## DolphinTool Usage
|
||||
```
|
||||
usage: dolphin-tool COMMAND -h
|
||||
usage: baiji-tool COMMAND -h
|
||||
|
||||
commands supported: [convert, verify, header, extract]
|
||||
```
|
||||
@@ -364,3 +419,68 @@ Options:
|
||||
-q, --quiet Mute all messages except for errors.
|
||||
-g, --gameonly Only extracts the DATA partition.
|
||||
```
|
||||
|
||||
# Dolphin Links
|
||||
|
||||
Relevant links for the original Dolphin underneath Baiji:
|
||||
|
||||
* [Homepage](https://dolphin-emu.org/)
|
||||
* [Project Site](https://github.com/dolphin-emu/dolphin)
|
||||
* [Forums](https://forums.dolphin-emu.org/) but DO NOT report Baiji
|
||||
bugs
|
||||
* [Wiki](https://wiki.dolphin-emu.org/)
|
||||
* [GitHub Wiki](https://github.com/dolphin-emu/dolphin/wiki)
|
||||
* [Issue
|
||||
Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) but
|
||||
DO NOT... you ought to have gotten this by now... report Baiji bugs
|
||||
* [FAQ](https://dolphin-emu.org/docs/faq/)
|
||||
|
||||
# Known Quirks/Bugs That Don't Seem Fixable
|
||||
|
||||
For any of these, a PR that proves me wrong would be great, but as far
|
||||
as I know these are currently not reasonable fixable:
|
||||
|
||||
* When the QT UI is visible during 3D emulation, SteamOS spatializes
|
||||
Baiji's emulation output to be coming from the location of the QT
|
||||
UI, not the emulation. The Frame's OS does not seem to offer a way
|
||||
to bypass this for just one application. It seems to have a switch
|
||||
that could be thrown for the whole OS but I'm not touching it.
|
||||
|
||||
# Changelog
|
||||
|
||||
* Todo before release:
|
||||
* Check Room View in VR, can probably leave that rendering while the
|
||||
Steam UI is up
|
||||
* Check the Reddit feedback about the settings that make VR work,
|
||||
and lock the ones that _must_ be set for Immersive VR to work,
|
||||
when Immersive VR is selected.
|
||||
|
||||
* v0.2-alpha (not released yet)
|
||||
* Fixed what seems to be the last major performance regression
|
||||
against a natively-compiled Dolphin.
|
||||
* Added + and - to mapping on left & right bumper for Wii +
|
||||
Nunchuck.
|
||||
* Turning on Room View with the Steam UI stops rendering in Stereo
|
||||
and VR mode and pauses the emulation, rather than continuing to
|
||||
render and emulate and making it look like it was ignoring
|
||||
controls.
|
||||
|
||||
Ideally, we'd leave the game UI up if you bring up the Steam UI,
|
||||
and only stop displaying the game if you go to full room view
|
||||
mode, but once focus is removed from the game, baiji can't tell
|
||||
what you're doing. Since we can't be smart about this, we have to
|
||||
not display the game even if you only are looking at the Steam UI.
|
||||
|
||||
This may be a bug in the UI's Room View support; it shouldn't let
|
||||
us draw on it. If it correctly ignored our draw requests we could
|
||||
get it to work like most other games, which still render in the
|
||||
background.
|
||||
* Improved the way a surface is requested for flat 2D mode. I'm
|
||||
honestly uncertain if v0.1-alpha was broken, but if it was this
|
||||
should fix it, if it wasn't, this should make future builds less
|
||||
likely to break.
|
||||
* v0.1-alpha - Initial release.
|
||||
* Many Frame-specific UI changes to make working with the Frame
|
||||
specifically slicker.
|
||||
* Support for the full Frame controllers with their XR profile.
|
||||
* Support for native display of stereoscopic 3D.
|
||||
@@ -83,7 +83,7 @@ bool CubebStream::Init()
|
||||
INFO_LOG_FMT(AUDIO, "Minimum latency: {} frames", minimum_latency);
|
||||
|
||||
return_value =
|
||||
cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr,
|
||||
cubeb_stream_init(m_ctx.get(), &m_stream, "BaijiSteamVR Audio Output", nullptr, nullptr,
|
||||
nullptr, ¶ms, std::max(BUFFER_SAMPLES, minimum_latency),
|
||||
DataCallback, StateCallback, this) == CUBEB_OK;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,11 @@ std::shared_ptr<cubeb> GetContext()
|
||||
}
|
||||
|
||||
cubeb* ctx;
|
||||
#ifdef BAIJI_STEAMVR
|
||||
if (cubeb_init(&ctx, "BaijiSteamVR", nullptr) != CUBEB_OK)
|
||||
#else
|
||||
if (cubeb_init(&ctx, "Dolphin Emulator", nullptr) != CUBEB_OK)
|
||||
#endif
|
||||
{
|
||||
ERROR_LOG_FMT(AUDIO, "Error initializing cubeb library");
|
||||
return nullptr;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#define NORMAL_USER_DIR "Library/Application Support/Dolphin"
|
||||
#elif defined(ANDROID)
|
||||
#define NORMAL_USER_DIR "/sdcard/dolphin-emu"
|
||||
#elif defined(__linux__)
|
||||
#define NORMAL_USER_DIR "baiji"
|
||||
#else
|
||||
#define NORMAL_USER_DIR "dolphin-emu"
|
||||
#endif
|
||||
|
||||
@@ -155,7 +155,11 @@ void ClearCurrentRunLayer()
|
||||
}
|
||||
|
||||
static const std::map<System, std::string> system_to_name = {
|
||||
#ifdef BAIJI_STEAMVR
|
||||
{System::Main, "BaijiSteamVR"},
|
||||
#else
|
||||
{System::Main, "Dolphin"},
|
||||
#endif
|
||||
{System::GCPad, "GCPad"},
|
||||
{System::WiiPad, "Wiimote"},
|
||||
{System::GCKeyboard, "GCKeyboard"},
|
||||
|
||||
@@ -655,7 +655,7 @@ std::string CreateTempDir()
|
||||
return dir;
|
||||
#else
|
||||
const char* base = getenv("TMPDIR") ?: "/tmp";
|
||||
std::string path = std::string(base) + "/DolphinWii.XXXXXX";
|
||||
std::string path = std::string(base) + "/BaijiWii.XXXXXX";
|
||||
if (!mkdtemp(&path[0]))
|
||||
return "";
|
||||
return path;
|
||||
|
||||
@@ -102,7 +102,7 @@ LogManager::LogManager()
|
||||
m_log[LogType::BOOT] = {"BOOT", "Boot"};
|
||||
m_log[LogType::COMMANDPROCESSOR] = {"CP", "Command Processor"};
|
||||
m_log[LogType::COMMON] = {"COMMON", "Common"};
|
||||
m_log[LogType::CONSOLE] = {"CONSOLE", "Dolphin Console"};
|
||||
m_log[LogType::CONSOLE] = {"CONSOLE", "BaijiSteamVR Console"};
|
||||
m_log[LogType::CONTROLLERINTERFACE] = {"CI", "Controller Interface"};
|
||||
m_log[LogType::CORE] = {"CORE", "Core"};
|
||||
m_log[LogType::DISCIO] = {"DIO", "Disc IO"};
|
||||
|
||||
@@ -175,7 +175,7 @@ void TraversalClient::HandleServerPacket(TraversalPacket* packet)
|
||||
ENetAddress addr = MakeENetAddress(packet->pleaseSendPacket.address);
|
||||
if (addr.port != 0)
|
||||
{
|
||||
char message[] = "Hello from Dolphin Netplay...";
|
||||
char message[] = "Hello from BaijiSteamVR Netplay...";
|
||||
ENetBuffer buf;
|
||||
buf.data = message;
|
||||
buf.dataLength = sizeof(message) - 1;
|
||||
|
||||
@@ -134,7 +134,7 @@ static bool MapPort(const char* addr, const u16 port)
|
||||
std::string port_str = std::to_string(port);
|
||||
int result = UPNP_AddPortMapping(
|
||||
s_urls.controlURL, s_data.first.servicetype, port_str.c_str(), port_str.c_str(), addr,
|
||||
(std::string("dolphin-emu UDP on ") + addr).c_str(), "UDP", nullptr, nullptr);
|
||||
(std::string("BaijiSteamVR UDP on ") + addr).c_str(), "UDP", nullptr, nullptr);
|
||||
|
||||
if (result != 0)
|
||||
return false;
|
||||
|
||||
@@ -44,7 +44,16 @@ struct OpenXRControllerState
|
||||
bool connected = false;
|
||||
bool primary_button = false;
|
||||
bool secondary_button = false;
|
||||
bool frame_x_button = false;
|
||||
bool frame_y_button = false;
|
||||
bool menu_button = false;
|
||||
bool system_button = false;
|
||||
bool view_button = false;
|
||||
bool bumper_button = false;
|
||||
bool dpad_up = false;
|
||||
bool dpad_down = false;
|
||||
bool dpad_left = false;
|
||||
bool dpad_right = false;
|
||||
bool trigger_button = false;
|
||||
bool squeeze_button = false;
|
||||
bool thumbstick_button = false;
|
||||
@@ -114,6 +123,16 @@ public:
|
||||
++s_state.generation;
|
||||
}
|
||||
|
||||
static void SetSessionFocused(bool focused)
|
||||
{
|
||||
std::lock_guard lk(s_state_mutex);
|
||||
if (s_state.session_focused == focused)
|
||||
return;
|
||||
|
||||
s_state.session_focused = focused;
|
||||
++s_state.generation;
|
||||
}
|
||||
|
||||
static std::string GetDiagnosticString()
|
||||
{
|
||||
std::lock_guard lk(s_state_mutex);
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
|
||||
namespace Common
|
||||
{
|
||||
#ifdef BAIJI_STEAMVR
|
||||
#define EMULATOR_NAME "BaijiSteamVR"
|
||||
#else
|
||||
#define EMULATOR_NAME "Dolphin"
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define BUILD_TYPE_STR "Debug "
|
||||
|
||||
@@ -82,7 +82,7 @@ static void WarnIfRunningUnderEmulation()
|
||||
|
||||
// The process is not native; could use IsWow64Process2 to get native machine type, but for now
|
||||
// we can assume it is arm64.
|
||||
PanicAlertFmtT("This build of Dolphin is not natively compiled for your CPU.\n"
|
||||
PanicAlertFmtT("This build of BaijiSteamVR is not natively compiled for your CPU.\n"
|
||||
"Please run the ARM64 build of Dolphin for a better experience.");
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ void AchievementManager::Init(void* hwnd)
|
||||
// In non-x64 build, will only look for RA_Integration.dll.
|
||||
rc_client_begin_load_raintegration(
|
||||
m_client, UTF8ToWString(File::GetExeDirectory()).c_str(), reinterpret_cast<HWND>(hwnd),
|
||||
"Dolphin", Common::GetScmDescStr().c_str(), LoadIntegrationCallback, NULL);
|
||||
"BaijiSteamVR", Common::GetScmDescStr().c_str(), LoadIntegrationCallback, NULL);
|
||||
#else // RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
if (HasAPIToken())
|
||||
Login("");
|
||||
@@ -989,10 +989,10 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
|
||||
instance.m_loading_volume.reset(nullptr);
|
||||
if (result == RC_API_FAILURE)
|
||||
{
|
||||
WARN_LOG_FMT(ACHIEVEMENTS, "Load data request rejected for old Dolphin version.");
|
||||
OSD::AddMessage("RetroAchievements no longer supports this version of Dolphin.",
|
||||
WARN_LOG_FMT(ACHIEVEMENTS, "Load data request rejected for an old BaijiSteamVR version.");
|
||||
OSD::AddMessage("RetroAchievements no longer supports this version of BaijiSteamVR.",
|
||||
OSD::Duration::VERY_LONG, OSD::Color::RED);
|
||||
OSD::AddMessage("Please update Dolphin to a newer version.", OSD::Duration::VERY_LONG,
|
||||
OSD::AddMessage("Please update BaijiSteamVR to a newer version.", OSD::Duration::VERY_LONG,
|
||||
OSD::Color::RED);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -973,7 +973,7 @@ static bool RunCodeLocked(const Core::CPUThreadGuard& guard, const ARCode& arcod
|
||||
|
||||
default:
|
||||
LogInfo("ZCode: Unknown");
|
||||
PanicAlertFmtT("Zero code unknown to Dolphin: {0:08x}", zcode);
|
||||
PanicAlertFmtT("Zero code unknown to BaijiSteamVR: {0:08x}", zcode);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ bool ElfReader::LoadIntoMemory(Core::System& system, bool only_in_mem1) const
|
||||
|
||||
if (bRelocate)
|
||||
{
|
||||
PanicAlertFmt("Error: Dolphin doesn't know how to load a relocatable elf.");
|
||||
PanicAlertFmt("Error: BaijiSteamVR doesn't know how to load a relocatable elf.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ const Info<bool> GFX_ENABLE_PIXEL_LIGHTING{{System::GFX, "Settings", "EnablePixe
|
||||
const Info<bool> GFX_FAST_DEPTH_CALC{{System::GFX, "Settings", "FastDepthCalc"}, true};
|
||||
const Info<u32> GFX_MSAA{{System::GFX, "Settings", "MSAA"}, 1};
|
||||
const Info<bool> GFX_SSAA{{System::GFX, "Settings", "SSAA"}, false};
|
||||
const Info<int> GFX_EFB_SCALE{{System::GFX, "Settings", "InternalResolution"}, 1};
|
||||
const Info<int> GFX_EFB_SCALE{{System::GFX, "Settings", "InternalResolution"}, 2};
|
||||
const Info<int> GFX_MAX_EFB_SCALE{{System::GFX, "Settings", "MaxInternalResolution"}, 12};
|
||||
const Info<bool> GFX_TEXFMT_OVERLAY_ENABLE{{System::GFX, "Settings", "TexFmtOverlayEnable"}, false};
|
||||
const Info<bool> GFX_TEXFMT_OVERLAY_CENTER{{System::GFX, "Settings", "TexFmtOverlayCenter"}, false};
|
||||
@@ -104,7 +104,7 @@ const Info<int> GFX_COMMAND_BUFFERS_IN_FLIGHT{
|
||||
|
||||
const Info<bool> GFX_SHADER_CACHE{{System::GFX, "Settings", "ShaderCache"}, true};
|
||||
const Info<bool> GFX_WAIT_FOR_SHADERS_BEFORE_STARTING{
|
||||
{System::GFX, "Settings", "WaitForShadersBeforeStarting"}, false};
|
||||
{System::GFX, "Settings", "WaitForShadersBeforeStarting"}, true};
|
||||
const Info<ShaderCompilationMode> GFX_SHADER_COMPILATION_MODE{
|
||||
{System::GFX, "Settings", "ShaderCompilationMode"}, ShaderCompilationMode::Synchronous};
|
||||
const Info<int> GFX_SHADER_COMPILER_THREADS{{System::GFX, "Settings", "ShaderCompilerThreads"}, 1};
|
||||
@@ -191,7 +191,13 @@ const Info<bool> GFX_VR_ENABLE_OPENXR{{System::GFX, "VR", "EnableOpenXR"}, true}
|
||||
// When OpenXR is enabled, render the game as a flat mono panel in the VR scene instead of
|
||||
// per-eye stereoscopic 3D (the "Launch games in VR" off / cinema path).
|
||||
const Info<bool> GFX_VR_FLAT_SCREEN{{System::GFX, "VR", "FlatScreen"}, false};
|
||||
// When OpenXR is enabled, render the game using classic SBS stereoscopy and submit it as a
|
||||
// stereoscopic virtual screen (two quad layers) instead of immersive per-eye reprojection.
|
||||
const Info<bool> GFX_VR_STEREO_SCREEN{{System::GFX, "VR", "StereoScreen"}, false};
|
||||
const Info<OpenXRPresentationMode> GFX_VR_PRESENTATION_MODE{
|
||||
{System::GFX, "VR", "PresentationMode"}, OpenXRPresentationMode::StereoScreen};
|
||||
const Info<float> GFX_VR_UNITS_PER_METER{{System::GFX, "VR", "UnitsPerMeter"}, 1.0f};
|
||||
const Info<float> GFX_VR_STEREO_SEPARATION{{System::GFX, "VR", "StereoSeparation"}, 100.0f};
|
||||
const Info<bool> GFX_VR_ENABLE_LEAN_BACK_ANGLE{{System::GFX, "VR", "EnableLeanBackAngle"}, true};
|
||||
const Info<float> GFX_VR_LEAN_BACK_ANGLE{{System::GFX, "VR", "LeanBackAngle"}, 0.0f};
|
||||
const Info<bool> GFX_VR_ENABLE_CAMERA_FORWARD{{System::GFX, "VR", "EnableCameraForward"}, true};
|
||||
@@ -204,14 +210,18 @@ const Info<float> GFX_VR_CAMERA_ANCHOR_SMOOTHING{{System::GFX, "VR", "CameraAnch
|
||||
const Info<bool> GFX_VR_ENABLE_CONTROLLER_ANCHOR{{System::GFX, "VR", "EnableControllerAnchor"},
|
||||
false};
|
||||
const Info<bool> GFX_VR_VIRTUAL_SCREEN{{System::GFX, "VR", "VirtualScreen"}, true};
|
||||
const Info<float> GFX_VR_SCREEN_DISTANCE{{System::GFX, "VR", "ScreenDistance"}, 1.5f};
|
||||
const Info<float> GFX_VR_SCREEN_DISTANCE{{System::GFX, "VR", "ScreenDistance"}, 2.0f};
|
||||
const Info<float> GFX_VR_SCREEN_SIZE{{System::GFX, "VR", "ScreenSize"}, 1.5f};
|
||||
const Info<float> GFX_VR_HEAD_LOCKED_CURVATURE{{System::GFX, "VR", "HeadLockedCurvature"}, 0.0f};
|
||||
const Info<bool> GFX_VR_DONT_CLEAR_SCREEN{{System::GFX, "VR", "DontClearScreen"}, false};
|
||||
const Info<bool> GFX_VR_LOAD_CUSTOM_SHADERS{{System::GFX, "VR", "LoadCustomShaders"}, false};
|
||||
const Info<bool> GFX_VR_DISABLE_CPU_CULL{{System::GFX, "VR", "DisableCPUCull"}, false};
|
||||
const Info<OpenXRMirrorView> GFX_VR_MIRROR_VIEW{{System::GFX, "VR", "MirrorView"},
|
||||
OpenXRMirrorView::BothEyes};
|
||||
#ifdef BAIJI_STEAMVR
|
||||
OpenXRMirrorView::None};
|
||||
#else
|
||||
OpenXRMirrorView::BothEyes};
|
||||
#endif
|
||||
const Info<OpenXRReferenceSpaceMode> GFX_VR_REFERENCE_SPACE_MODE{
|
||||
{System::GFX, "VR", "ReferenceSpaceMode"}, OpenXRReferenceSpaceMode::Local};
|
||||
const Info<OpenXRTrackingMode> GFX_VR_TRACKING_MODE{{System::GFX, "VR", "TrackingMode"},
|
||||
@@ -226,7 +236,7 @@ constexpr bool DEFAULT_VR_PIN_EMULATION_CORES = false;
|
||||
#endif
|
||||
const Info<bool> GFX_VR_PIN_EMULATION_CORES{{System::GFX, "VR", "PinEmulationCores"},
|
||||
DEFAULT_VR_PIN_EMULATION_CORES};
|
||||
const Info<bool> GFX_VR_EAGER_HEARTBEAT{{System::GFX, "VR", "EagerHeartbeat"}, false};
|
||||
const Info<bool> GFX_VR_EAGER_HEARTBEAT{{System::GFX, "VR", "EagerHeartbeat"}, true};
|
||||
#if defined(__ANDROID__) && defined(ENABLE_VR)
|
||||
constexpr bool DEFAULT_VR_ANDROID_DIRECT_TO_HMD = true;
|
||||
constexpr bool DEFAULT_IMMEDIATE_XFB = true;
|
||||
@@ -236,6 +246,9 @@ constexpr bool DEFAULT_IMMEDIATE_XFB = false;
|
||||
#endif
|
||||
|
||||
const Info<int> GFX_VR_FORCED_VBI_FREQUENCY{{System::GFX, "VR", "ForcedVBIFrequency"}, 0};
|
||||
// Request a specific display refresh rate from the OpenXR runtime (Hz). 0 means no request
|
||||
// (use the runtime's default). The runtime may clamp to the nearest available rate.
|
||||
const Info<int> GFX_VR_REQUESTED_REFRESH_RATE{{System::GFX, "VR", "RequestedRefreshRate"}, 0};
|
||||
const Info<bool> GFX_VR_AUTO_VBI_FROM_HMD{{System::GFX, "VR", "AutoVBIFromHMD"}, false};
|
||||
const Info<bool> GFX_VR_EXACT_SCREEN_DEPTH{{System::GFX, "VR", "ExactScreenDepth"}, true};
|
||||
const Info<bool> GFX_VR_AUTO_NATIVE_EFB_EFFECTS{{System::GFX, "VR", "AutoNativeEfbEffects"},
|
||||
|
||||
@@ -22,6 +22,7 @@ enum class VertexLoaderType : int;
|
||||
enum class OpenXRMirrorView : int;
|
||||
enum class OpenXRReferenceSpaceMode : int;
|
||||
enum class OpenXRTrackingMode : int;
|
||||
enum class OpenXRPresentationMode : int;
|
||||
enum class VRPassthroughCoverageMode : int;
|
||||
|
||||
namespace Config
|
||||
@@ -172,7 +173,10 @@ static constexpr float GFX_STEREO_CONVERGENCE_MAXIMUM = 200;
|
||||
|
||||
extern const Info<bool> GFX_VR_ENABLE_OPENXR;
|
||||
extern const Info<bool> GFX_VR_FLAT_SCREEN;
|
||||
extern const Info<bool> GFX_VR_STEREO_SCREEN;
|
||||
extern const Info<OpenXRPresentationMode> GFX_VR_PRESENTATION_MODE;
|
||||
extern const Info<float> GFX_VR_UNITS_PER_METER;
|
||||
extern const Info<float> GFX_VR_STEREO_SEPARATION;
|
||||
extern const Info<bool> GFX_VR_ENABLE_LEAN_BACK_ANGLE;
|
||||
extern const Info<float> GFX_VR_LEAN_BACK_ANGLE;
|
||||
extern const Info<bool> GFX_VR_ENABLE_CAMERA_FORWARD;
|
||||
@@ -186,6 +190,9 @@ extern const Info<bool> GFX_VR_ENABLE_CONTROLLER_ANCHOR;
|
||||
static constexpr float GFX_VR_UNITS_PER_METER_MIN = 0.1f;
|
||||
static constexpr float GFX_VR_UNITS_PER_METER_MAX = 2000.0f;
|
||||
static constexpr float GFX_VR_UNITS_PER_METER_STEP = 0.1f;
|
||||
static constexpr float GFX_VR_STEREO_SEPARATION_MIN = 0.0f;
|
||||
static constexpr float GFX_VR_STEREO_SEPARATION_MAX = 200.0f;
|
||||
static constexpr float GFX_VR_STEREO_SEPARATION_STEP = 1.0f;
|
||||
static constexpr float GFX_VR_LEAN_BACK_ANGLE_MIN = -45.0f;
|
||||
static constexpr float GFX_VR_LEAN_BACK_ANGLE_MAX = 45.0f;
|
||||
static constexpr float GFX_VR_LEAN_BACK_ANGLE_STEP = 0.1f;
|
||||
@@ -211,6 +218,7 @@ extern const Info<OpenXRReferenceSpaceMode> GFX_VR_REFERENCE_SPACE_MODE;
|
||||
extern const Info<OpenXRTrackingMode> GFX_VR_TRACKING_MODE;
|
||||
extern const Info<bool> GFX_VR_USE_OPENXR_PLAY_SPACE_CENTER;
|
||||
extern const Info<int> GFX_VR_FORCED_VBI_FREQUENCY;
|
||||
extern const Info<int> GFX_VR_REQUESTED_REFRESH_RATE;
|
||||
// Dedicated XR frame-pacing thread: owns xrWaitFrame/xrBeginFrame/xrEndFrame and
|
||||
// re-submits the last frame at HMD cadence when the game runs slower (replaces the
|
||||
// legacy Opcode Replay). INI-only escape hatch; disable to fall back to the inline
|
||||
@@ -279,6 +287,11 @@ static constexpr int GFX_VR_FORCED_VBI_FREQUENCY_OFF = 0;
|
||||
static constexpr int GFX_VR_FORCED_VBI_FREQUENCY_72 = 72;
|
||||
static constexpr int GFX_VR_FORCED_VBI_FREQUENCY_90 = 90;
|
||||
static constexpr int GFX_VR_FORCED_VBI_FREQUENCY_120 = 120;
|
||||
static constexpr int GFX_VR_REQUESTED_REFRESH_RATE_AUTO = 0;
|
||||
static constexpr int GFX_VR_REQUESTED_REFRESH_RATE_60 = 60;
|
||||
static constexpr int GFX_VR_REQUESTED_REFRESH_RATE_72 = 72;
|
||||
static constexpr int GFX_VR_REQUESTED_REFRESH_RATE_90 = 90;
|
||||
static constexpr int GFX_VR_REQUESTED_REFRESH_RATE_120 = 120;
|
||||
static constexpr float GFX_VR_HUD_THICKNESS_MIN = 0.0f;
|
||||
static constexpr float GFX_VR_HUD_THICKNESS_MAX = 1.0f;
|
||||
static constexpr float GFX_VR_HUD_THICKNESS_STEP = 0.02f;
|
||||
|
||||
@@ -426,6 +426,8 @@ const Info<bool> MAIN_ABORT_ON_PANIC_ALERT{{System::Main, "Interface", "AbortOnP
|
||||
const Info<bool> MAIN_OSD_MESSAGES{{System::Main, "Interface", "OnScreenDisplayMessages"}, true};
|
||||
const Info<int> MAIN_OSD_FONT_SIZE{{System::Main, "Settings", "OSDFontSize"}, 13};
|
||||
const Info<bool> MAIN_SKIP_NKIT_WARNING{{System::Main, "Interface", "SkipNKitWarning"}, false};
|
||||
const Info<bool> MAIN_SKIP_FLAT_MODE_INPUT_WARNING{
|
||||
{System::Main, "Interface", "SkipFlatModeInputWarning"}, false};
|
||||
const Info<bool> MAIN_CONFIRM_ON_STOP{{System::Main, "Interface", "ConfirmStop"}, true};
|
||||
const Info<ShowCursor> MAIN_SHOW_CURSOR{{System::Main, "Interface", "CursorVisibility"},
|
||||
ShowCursor::OnMovement};
|
||||
|
||||
@@ -248,6 +248,7 @@ extern const Info<bool> MAIN_ABORT_ON_PANIC_ALERT;
|
||||
extern const Info<bool> MAIN_OSD_MESSAGES;
|
||||
extern const Info<int> MAIN_OSD_FONT_SIZE;
|
||||
extern const Info<bool> MAIN_SKIP_NKIT_WARNING;
|
||||
extern const Info<bool> MAIN_SKIP_FLAT_MODE_INPUT_WARNING;
|
||||
extern const Info<bool> MAIN_CONFIRM_ON_STOP;
|
||||
|
||||
enum class ShowCursor
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace Config
|
||||
{
|
||||
const Info<WiimoteSource> WIIMOTE_1_SOURCE{{System::WiiPad, "Wiimote1", "Source"},
|
||||
WiimoteSource::Emulated};
|
||||
WiimoteSource::OpenXR};
|
||||
const Info<WiimoteSource> WIIMOTE_2_SOURCE{{System::WiiPad, "Wiimote2", "Source"},
|
||||
WiimoteSource::None};
|
||||
const Info<WiimoteSource> WIIMOTE_3_SOURCE{{System::WiiPad, "Wiimote3", "Source"},
|
||||
|
||||
@@ -158,7 +158,10 @@ static void ClearAppliedVRSettings()
|
||||
{
|
||||
ClearAppliedVRSetting("EnableOpenXR", Config::GFX_VR_ENABLE_OPENXR);
|
||||
ClearAppliedVRSetting("FlatScreen", Config::GFX_VR_FLAT_SCREEN);
|
||||
ClearAppliedVRSetting("StereoScreen", Config::GFX_VR_STEREO_SCREEN);
|
||||
ClearAppliedVRSetting("PresentationMode", Config::GFX_VR_PRESENTATION_MODE);
|
||||
ClearAppliedVRSetting("UnitsPerMeter", Config::GFX_VR_UNITS_PER_METER);
|
||||
ClearAppliedVRSetting("StereoSeparation", Config::GFX_VR_STEREO_SEPARATION);
|
||||
ClearAppliedVRSetting("EnableLeanBackAngle", Config::GFX_VR_ENABLE_LEAN_BACK_ANGLE);
|
||||
ClearAppliedVRSetting("LeanBackAngle", Config::GFX_VR_LEAN_BACK_ANGLE);
|
||||
ClearAppliedVRSetting("EnableCameraForward", Config::GFX_VR_ENABLE_CAMERA_FORWARD);
|
||||
@@ -237,7 +240,10 @@ static void ApplyGameVRConfigOverrides(std::string_view game_id, std::optional<u
|
||||
|
||||
ApplyVRSetting(values, "EnableOpenXR", Config::GFX_VR_ENABLE_OPENXR);
|
||||
ApplyVRSetting(values, "FlatScreen", Config::GFX_VR_FLAT_SCREEN);
|
||||
ApplyVRSetting(values, "StereoScreen", Config::GFX_VR_STEREO_SCREEN);
|
||||
ApplyVRSetting(values, "PresentationMode", Config::GFX_VR_PRESENTATION_MODE);
|
||||
ApplyVRSetting(values, "UnitsPerMeter", Config::GFX_VR_UNITS_PER_METER);
|
||||
ApplyVRSetting(values, "StereoSeparation", Config::GFX_VR_STEREO_SEPARATION);
|
||||
ApplyVRSetting(values, "EnableLeanBackAngle", Config::GFX_VR_ENABLE_LEAN_BACK_ANGLE);
|
||||
ApplyVRSetting(values, "LeanBackAngle", Config::GFX_VR_LEAN_BACK_ANGLE);
|
||||
ApplyVRSetting(values, "EnableCameraForward", Config::GFX_VR_ENABLE_CAMERA_FORWARD);
|
||||
|
||||
@@ -45,7 +45,9 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef USE_ANALYTICS
|
||||
constexpr char ANALYTICS_ENDPOINT[] = "https://analytics.dolphin-emu.org/report";
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
#if defined(ANDROID)
|
||||
@@ -90,10 +92,12 @@ void DolphinAnalytics::ReloadConfig()
|
||||
|
||||
// Install the HTTP backend if analytics support is enabled.
|
||||
std::unique_ptr<Common::AnalyticsReportingBackend> new_backend;
|
||||
#ifdef USE_ANALYTICS
|
||||
if (m_last_analytics_enabled)
|
||||
{
|
||||
new_backend = std::make_unique<Common::HttpAnalyticsBackend>(ANALYTICS_ENDPOINT);
|
||||
}
|
||||
#endif
|
||||
m_reporter.SetBackend(std::move(new_backend));
|
||||
|
||||
// Load the unique ID or generate it if needed.
|
||||
|
||||
@@ -407,7 +407,7 @@ void DVDInterface::SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
|
||||
{
|
||||
OSD::AddMessage("You are running a disc image with a very large block size.", 60000);
|
||||
OSD::AddMessage("This will likely lead to performance problems.", 60000);
|
||||
OSD::AddMessage("You can use Dolphin's convert feature to reduce the block size.", 60000);
|
||||
OSD::AddMessage("You can use BaijiSteamVR's convert feature to reduce the block size.", 60000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -730,7 +730,7 @@ void CEXIETHERNET::BuiltInBBAInterface::ReadThreadHandler(CEXIETHERNET::BuiltInB
|
||||
if (datasize > BBA_RECV_SIZE)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Frame size is exceiding BBA capacity, frame stack might be corrupted"
|
||||
"Killing Dolphin...");
|
||||
"Killing BaijiSteamVR...");
|
||||
std::exit(0);
|
||||
}
|
||||
std::memcpy(self->m_eth_ref->mRecvBuffer.get(), self->m_queue_data[self->m_queue_read].data(),
|
||||
|
||||
@@ -31,7 +31,7 @@ bool CEXIETHERNET::TAPNetworkInterface::Activate()
|
||||
if (IsActivated())
|
||||
return true;
|
||||
|
||||
// Assumes that there is a TAP device named "Dolphin" preconfigured for
|
||||
// Assumes that there is a TAP device named "Baiji" preconfigured for
|
||||
// bridge/NAT/whatever the user wants it configured.
|
||||
|
||||
if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
|
||||
@@ -47,7 +47,7 @@ bool CEXIETHERNET::TAPNetworkInterface::Activate()
|
||||
const int MAX_INTERFACES = 32;
|
||||
for (int i = 0; i < MAX_INTERFACES; ++i)
|
||||
{
|
||||
fmt::format_to_n(ifr.ifr_name, IFNAMSIZ, "Dolphin{}", i);
|
||||
fmt::format_to_n(ifr.ifr_name, IFNAMSIZ, "Baiji{}", i);
|
||||
|
||||
int err;
|
||||
if ((err = ioctl(fd, TUNSETIFF, (void*)&ifr)) < 0)
|
||||
|
||||
@@ -140,7 +140,7 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(Core::System& system, const EXIDevi
|
||||
#ifdef HAVE_CUBEB
|
||||
result = std::make_unique<CEXIMic>(system, channel_num);
|
||||
#else
|
||||
PanicAlertFmtT("Dolphin was built with Cubeb disabled. The Microphone device cannot be used.");
|
||||
PanicAlertFmtT("BaijiSteamVR was built with Cubeb disabled. The Microphone device cannot be used.");
|
||||
result = std::make_unique<IEXIDevice>(system);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -205,7 +205,7 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data)
|
||||
{
|
||||
// TODO more user friendly abort
|
||||
PanicAlertFmtT("{0} is not a directory, failed to move to *.original.\n Verify your "
|
||||
"write permissions or move the file outside of Dolphin",
|
||||
"write permissions or move the file outside of BaijiSteamVR",
|
||||
dir_path);
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ void CEXIMic::StreamStart()
|
||||
}
|
||||
|
||||
if (cubeb_stream_init(m_cubeb_ctx.get(), &m_cubeb_stream,
|
||||
"Dolphin Emulated GameCube Microphone", nullptr, ¶ms, nullptr,
|
||||
"BaijiSteamVR Emulated GameCube Microphone", nullptr, ¶ms, nullptr,
|
||||
nullptr, std::max<u32>(buff_size_samples, minimum_latency), DataCallback,
|
||||
state_callback, this) != CUBEB_OK)
|
||||
{
|
||||
|
||||
@@ -469,7 +469,7 @@ void Core::SetAVStream()
|
||||
void Core::SetupEvent()
|
||||
{
|
||||
m_event.context = this;
|
||||
m_event.name = "Dolphin Sync";
|
||||
m_event.name = "BaijiSteamVR Sync";
|
||||
m_event.callback = [](mTiming* timing, void* context, u32 cycles_late) {
|
||||
Core* core = static_cast<Core*>(context);
|
||||
if (core->m_core->platform(core->m_core) == mPLATFORM_GBA)
|
||||
|
||||
@@ -597,7 +597,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int save_index)
|
||||
block = current_bat->GetNextBlock(block);
|
||||
if (block == 0)
|
||||
{
|
||||
PanicAlertFmtT("BAT incorrect. Dolphin will now exit");
|
||||
PanicAlertFmtT("BAT incorrect. BaijiSteamVR will now exit");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ void MemoryCard::FlushThread()
|
||||
{
|
||||
PanicAlertFmtT(
|
||||
"Could not write memory card file {0}.\n\n"
|
||||
"Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?\n\n"
|
||||
"Are you running BaijiSteamVR from a CD/DVD, or is the save file maybe write protected?\n\n"
|
||||
"Are you receiving this after moving the emulator directory?\nIf so, then you may "
|
||||
"need to re-specify your memory card location in the options.",
|
||||
m_filename);
|
||||
|
||||
@@ -191,7 +191,39 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface)
|
||||
{
|
||||
EmulatedController::LoadDefaults(ciface);
|
||||
|
||||
#ifdef ANDROID
|
||||
#ifdef ENABLE_VR
|
||||
SetDefaultDevice("OpenXR/0/OpenXR Controller");
|
||||
|
||||
// Baiju's default pad is the Steam Frame controller, not a keyboard.
|
||||
m_buttons->SetControlExpression(0, "`Right Button A`");
|
||||
m_buttons->SetControlExpression(1, "`Right Button B`");
|
||||
m_buttons->SetControlExpression(2, "`Right Button X`");
|
||||
m_buttons->SetControlExpression(3, "`Right Button Y`");
|
||||
m_buttons->SetControlExpression(4, "`Right Button Squeeze`");
|
||||
m_buttons->SetControlExpression(5, "`Right Button Menu`");
|
||||
|
||||
m_main_stick->SetControlExpression(0, "`Left Thumbstick Y+`");
|
||||
m_main_stick->SetControlExpression(1, "`Left Thumbstick Y-`");
|
||||
m_main_stick->SetControlExpression(2, "`Left Thumbstick X-`");
|
||||
m_main_stick->SetControlExpression(3, "`Left Thumbstick X+`");
|
||||
|
||||
m_c_stick->SetControlExpression(0, "`Right Thumbstick Y+`");
|
||||
m_c_stick->SetControlExpression(1, "`Right Thumbstick Y-`");
|
||||
m_c_stick->SetControlExpression(2, "`Right Thumbstick X-`");
|
||||
m_c_stick->SetControlExpression(3, "`Right Thumbstick X+`");
|
||||
|
||||
m_triggers->SetControlExpression(0, "`Left Button Trigger`");
|
||||
m_triggers->SetControlExpression(1, "`Right Button Trigger`");
|
||||
m_triggers->SetControlExpression(2, "`Left Trigger`");
|
||||
m_triggers->SetControlExpression(3, "`Right Trigger`");
|
||||
|
||||
m_dpad->SetControlExpression(0, "`Left D-Pad Up`");
|
||||
m_dpad->SetControlExpression(1, "`Left D-Pad Down`");
|
||||
m_dpad->SetControlExpression(2, "`Left D-Pad Left`");
|
||||
m_dpad->SetControlExpression(3, "`Left D-Pad Right`");
|
||||
|
||||
m_rumble->SetControlExpression(0, "Motor");
|
||||
#elif defined(ANDROID)
|
||||
// Rumble
|
||||
m_rumble->SetControlExpression(0, "`Android/0/Device Sensors:Motor 0`");
|
||||
|
||||
|
||||
@@ -178,7 +178,16 @@ void Nunchuk::DoState(PointerWrap& p)
|
||||
|
||||
void Nunchuk::LoadDefaults()
|
||||
{
|
||||
#ifndef ANDROID
|
||||
#ifdef ENABLE_VR
|
||||
m_stick->SetControlExpression(0, "`Left Thumbstick Y+`");
|
||||
m_stick->SetControlExpression(1, "`Left Thumbstick Y-`");
|
||||
m_stick->SetControlExpression(2, "`Left Thumbstick X-`");
|
||||
m_stick->SetControlExpression(3, "`Left Thumbstick X+`");
|
||||
|
||||
m_buttons->SetControlExpression(0, "`Left Button Squeeze`");
|
||||
m_buttons->SetControlExpression(1, "`Left Trigger`");
|
||||
|
||||
#elif !defined(ANDROID)
|
||||
// Stick
|
||||
m_stick->SetControlExpression(0, "W"); // up
|
||||
m_stick->SetControlExpression(1, "S"); // down
|
||||
|
||||
@@ -693,7 +693,33 @@ void Wiimote::LoadDefaults(const ControllerInterface& ciface)
|
||||
{
|
||||
EmulatedController::LoadDefaults(ciface);
|
||||
|
||||
#ifdef ANDROID
|
||||
#ifdef ENABLE_VR
|
||||
SetDefaultDevice("OpenXR/0/OpenXR Controller");
|
||||
|
||||
m_buttons->SetControlExpression(0, "`Right Button A`");
|
||||
m_buttons->SetControlExpression(1, "`Right Trigger`");
|
||||
m_buttons->SetControlExpression(2, "`Right Button X`");
|
||||
m_buttons->SetControlExpression(3, "`Right Button Y`");
|
||||
m_buttons->SetControlExpression(4, "`Left Button View`");
|
||||
m_buttons->SetControlExpression(5, "`Right Button Menu`");
|
||||
m_buttons->SetControlExpression(6, "`Left Button System`");
|
||||
|
||||
m_dpad->SetControlExpression(0, "`Left D-Pad Up`");
|
||||
m_dpad->SetControlExpression(1, "`Left D-Pad Down`");
|
||||
m_dpad->SetControlExpression(2, "`Left D-Pad Left`");
|
||||
m_dpad->SetControlExpression(3, "`Left D-Pad Right`");
|
||||
|
||||
m_ir->SetControlExpression(0, "`Right Thumbstick Y-`");
|
||||
m_ir->SetControlExpression(1, "`Right Thumbstick Y+`");
|
||||
m_ir->SetControlExpression(2, "`Right Thumbstick X-`");
|
||||
m_ir->SetControlExpression(3, "`Right Thumbstick X+`");
|
||||
m_ir->SetRelativeInput(false);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
m_shake->SetControlExpression(i, "`Right Button Squeeze`");
|
||||
|
||||
m_rumble->SetControlExpression(0, "Motor");
|
||||
#elif defined(ANDROID)
|
||||
// Rumble
|
||||
m_rumble->SetControlExpression(0, "`Android/0/Device Sensors:Motor 0`");
|
||||
|
||||
|
||||
@@ -456,6 +456,14 @@ void HotkeyManager::LoadDefaults(const ControllerInterface& ciface)
|
||||
return fmt::format("@({})", fmt::join(inputs, "+"));
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VR
|
||||
SetDefaultDevice("OpenXR/0/OpenXR Controller");
|
||||
// Keep Right Button Menu available for GameCube Start.
|
||||
set_key_expression(HK_STOP, "`Left Button View`");
|
||||
// Steam Frame provides headset recentering at the OS/runtime level; leave the app hotkey unset.
|
||||
return;
|
||||
#endif
|
||||
|
||||
// General hotkeys
|
||||
set_key_expression(HK_OPEN, hotkey_string({"Ctrl", "O"}));
|
||||
set_key_expression(HK_PLAY_PAUSE, "F10");
|
||||
|
||||
@@ -340,8 +340,7 @@ bool ESDevice::LaunchTitle(u64 title_id, HangPPC hang_ppc)
|
||||
ERROR_LOG_FMT(IOS_ES, "Refusing to launch the shop channel with default device credentials");
|
||||
CriticalAlertFmtT(
|
||||
"You cannot use the Wii Shop Channel without using your own device credentials."
|
||||
"\nPlease refer to the NAND usage guide for setup instructions: "
|
||||
"https://dolphin-emu.org/docs/guides/nand-usage-guide/");
|
||||
"\nPlease check the NAND setup instructions and use your own device credentials.");
|
||||
|
||||
// Send the user back to the system menu instead of returning an error, which would
|
||||
// likely make the system menu crash. Doing this is okay as anyone who has the shop
|
||||
|
||||
@@ -51,7 +51,7 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
|
||||
if (!IsEmulated(TitleID))
|
||||
{
|
||||
view_count = 0;
|
||||
ERROR_LOG_FMT(IOS_ES, "GetViewCount: Dolphin doesn't emulate IOS title {:016x}", TitleID);
|
||||
ERROR_LOG_FMT(IOS_ES, "GetViewCount: BaijiSteamVR doesn't emulate IOS title {:016x}", TitleID);
|
||||
}
|
||||
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_core.m_title_context))
|
||||
{
|
||||
@@ -81,7 +81,7 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
|
||||
|
||||
if (!IsEmulated(TitleID))
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "GetViews: Dolphin doesn't emulate IOS title {:016x}", TitleID);
|
||||
ERROR_LOG_FMT(IOS_ES, "GetViews: BaijiSteamVR doesn't emulate IOS title {:016x}", TitleID);
|
||||
}
|
||||
else if (ticket.IsValid())
|
||||
{
|
||||
|
||||
@@ -162,9 +162,8 @@ static std::vector<u8> ReadCertFile(const std::string& path, const std::array<u8
|
||||
ERROR_LOG_FMT(IOS_SSL, "Failed to read {}", path);
|
||||
if (!silent)
|
||||
{
|
||||
PanicAlertFmtT("IOS: Could not read a file required for SSL services ({0}). Please refer to "
|
||||
"https://dolphin-emu.org/docs/guides/wii-network-guide/ for "
|
||||
"instructions on setting up Wii networking.",
|
||||
PanicAlertFmtT("IOS: Could not read a file required for SSL services ({0}). "
|
||||
"Check the Wii networking certificate files in the user data directory.",
|
||||
path);
|
||||
}
|
||||
return {};
|
||||
@@ -177,9 +176,8 @@ static std::vector<u8> ReadCertFile(const std::string& path, const std::array<u8
|
||||
ERROR_LOG_FMT(IOS_SSL, "Wrong hash for {}", path);
|
||||
if (!silent)
|
||||
{
|
||||
PanicAlertFmtT("IOS: A file required for SSL services ({0}) is invalid. Please refer to "
|
||||
"https://dolphin-emu.org/docs/guides/wii-network-guide/ for "
|
||||
"instructions on setting up Wii networking.",
|
||||
PanicAlertFmtT("IOS: A file required for SSL services ({0}) is invalid. "
|
||||
"Check the Wii networking certificate files in the user data directory.",
|
||||
path);
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace IOS::HLE
|
||||
{
|
||||
std::optional<IPCReply> BluetoothStubDevice::Open(const OpenRequest& request)
|
||||
{
|
||||
PanicAlertFmtT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
|
||||
PanicAlertFmtT("Bluetooth passthrough mode is enabled, but BaijiSteamVR was built without libusb."
|
||||
" Passthrough mode cannot be used.");
|
||||
return IPCReply(IPC_ENOENT);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ LibUSBBluetoothAdapter::LibUSBBluetoothAdapter()
|
||||
{
|
||||
CriticalAlertFmtT(
|
||||
"Could not find any usable Bluetooth USB adapter for Bluetooth Passthrough.\n"
|
||||
"The following error occurred when Dolphin tried to use an adapter:\n{0}\n\n"
|
||||
"The following error occurred when BaijiSteamVR tried to use an adapter:\n{0}\n\n"
|
||||
"The emulated console will now stop.",
|
||||
m_last_open_error);
|
||||
}
|
||||
|
||||
@@ -485,8 +485,7 @@ static void ShowFirmwareReadError(std::string_view fw_path)
|
||||
{
|
||||
PanicAlertFmtT("Bluetooth passthrough failed to read firmware file from:\n"
|
||||
"{0}\n\n"
|
||||
"Refer to https://wiki.dolphin-emu.org/index.php?title=Bluetooth_Passthrough "
|
||||
"for instructions.",
|
||||
"Refer to the Bluetooth passthrough setup instructions.",
|
||||
fw_path);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
}
|
||||
std::string GetCubebStreamName() const override
|
||||
{
|
||||
return "Dolphin Emulated Logitech USB Microphone " + std::to_string(m_index);
|
||||
return "BaijiSteamVR Emulated Logitech USB Microphone " + std::to_string(m_index);
|
||||
}
|
||||
s16 GetVolumeModifier() const override
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
{
|
||||
return Config::Get(Config::MAIN_WII_SPEAK_MICROPHONE);
|
||||
}
|
||||
std::string GetCubebStreamName() const override { return "Dolphin Emulated Wii Speak"; }
|
||||
std::string GetCubebStreamName() const override { return "BaijiSteamVR Emulated Wii Speak"; }
|
||||
s16 GetVolumeModifier() const override
|
||||
{
|
||||
return Config::Get(Config::MAIN_WII_SPEAK_VOLUME_MODIFIER);
|
||||
|
||||
@@ -335,7 +335,7 @@ void CachedInterpreter::Jit(u32 em_address, bool clear_cache_and_retry_on_failur
|
||||
}
|
||||
|
||||
PanicAlertFmtT("JIT failed to find code space after a cache clear. This should never happen. "
|
||||
"Please report this incident on the bug tracker. Dolphin will now exit.");
|
||||
"Please report this incident in the BaijiSteamVR project. The application will now exit.");
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -883,7 +883,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
||||
}
|
||||
|
||||
PanicAlertFmtT("JIT failed to find code space after a cache clear. This should never happen. "
|
||||
"Please report this incident on the bug tracker. Dolphin will now exit.");
|
||||
"Please report this incident in the BaijiSteamVR project. The application will now exit.");
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1079,7 +1079,7 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
||||
}
|
||||
|
||||
PanicAlertFmtT("JIT failed to find code space after a cache clear. This should never happen. "
|
||||
"Please report this incident on the bug tracker. Dolphin will now exit.");
|
||||
"Please report this incident in the BaijiSteamVR project. The application will now exit.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -743,7 +743,7 @@ static bool ValidateHeaders(const StateHeader& header)
|
||||
std::string oldest_version = version_range.first;
|
||||
std::string newest_version = version_range.second;
|
||||
|
||||
loaded_str = "Dolphin " + oldest_version + " - " + newest_version;
|
||||
loaded_str = "BaijiSteamVR " + oldest_version + " - " + newest_version;
|
||||
}
|
||||
else if (loaded_version != STATE_VERSION)
|
||||
{
|
||||
@@ -754,7 +754,7 @@ static bool ValidateHeaders(const StateHeader& header)
|
||||
{
|
||||
const std::string message =
|
||||
loaded_str.empty() ?
|
||||
"This savestate was created using an incompatible version of Dolphin" :
|
||||
"This savestate was created using an incompatible version of BaijiSteamVR" :
|
||||
"This savestate was created using the incompatible version " + loaded_str;
|
||||
Core::DisplayMessage(message, OSD::Duration::NORMAL);
|
||||
}
|
||||
|
||||
@@ -1358,22 +1358,22 @@ void VolumeVerifier::Finish()
|
||||
else
|
||||
{
|
||||
m_result.summary_text =
|
||||
Common::GetStringT("This is a good dump according to Redump.org, but Dolphin has found "
|
||||
"problems. This might be a bug in Dolphin.");
|
||||
Common::GetStringT("This is a good dump according to Redump.org, but BaijiSteamVR has found "
|
||||
"problems. This might be a bug in BaijiSteamVR.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_is_datel)
|
||||
{
|
||||
m_result.summary_text = Common::GetStringT("Dolphin is unable to verify unlicensed discs.");
|
||||
m_result.summary_text = Common::GetStringT("BaijiSteamVR is unable to verify unlicensed discs.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_is_tgc)
|
||||
{
|
||||
m_result.summary_text =
|
||||
Common::GetStringT("Dolphin is unable to verify typical TGC files properly, "
|
||||
Common::GetStringT("BaijiSteamVR is unable to verify typical TGC files properly, "
|
||||
"since they are not dumps of actual discs.");
|
||||
return;
|
||||
}
|
||||
@@ -1381,7 +1381,7 @@ void VolumeVerifier::Finish()
|
||||
if (m_is_triforce)
|
||||
{
|
||||
m_result.summary_text =
|
||||
Common::GetStringT("Dolphin is currently unable to verify Triforce games.");
|
||||
Common::GetStringT("BaijiSteamVR is currently unable to verify Triforce games.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1393,7 +1393,7 @@ void VolumeVerifier::Finish()
|
||||
m_result.summary_text =
|
||||
Common::GetStringT("Compared to the Wii disc release of the game, this is a bad dump. "
|
||||
"Despite this, it's possible that this is a good dump compared to the "
|
||||
"Wii U eShop release of the game. Dolphin can't verify this.");
|
||||
"Wii U eShop release of the game. BaijiSteamVR can't verify this.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1429,7 +1429,7 @@ void VolumeVerifier::Finish()
|
||||
m_result.summary_text = Common::GetStringT(
|
||||
"Compared to the Wii disc release of the game, problems of low severity were found. "
|
||||
"Despite this, it's possible that this is a good dump compared to the Wii U eShop "
|
||||
"release of the game. Dolphin can't verify this.");
|
||||
"release of the game. BaijiSteamVR can't verify this.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1454,13 +1454,13 @@ void VolumeVerifier::Finish()
|
||||
{
|
||||
m_result.summary_text +=
|
||||
Common::GetStringT("\n\nBecause GameCube disc images contain little verification data, "
|
||||
"there may be problems that Dolphin is unable to detect.");
|
||||
"there may be problems that BaijiSteamVR is unable to detect.");
|
||||
}
|
||||
else if (m_is_not_retail)
|
||||
{
|
||||
m_result.summary_text +=
|
||||
Common::GetStringT("\n\nBecause this title is not for retail Wii consoles, "
|
||||
"Dolphin cannot ensure that it hasn't been tampered with, even if "
|
||||
"BaijiSteamVR cannot ensure that it hasn't been tampered with, even if "
|
||||
"signatures appear valid.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ if (WIN32)
|
||||
DEBUG_POSTFIX D
|
||||
OUTPUT_NAME DolphinNoGUI
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set_target_properties(dolphin-nogui PROPERTIES OUTPUT_NAME baiji-nogui)
|
||||
else()
|
||||
set_target_properties(dolphin-nogui PROPERTIES OUTPUT_NAME dolphin-emu-nogui)
|
||||
endif()
|
||||
@@ -66,4 +68,3 @@ endif()
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} dolphin-nogui)
|
||||
install(TARGETS dolphin-nogui RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
@@ -33,7 +33,8 @@ static std::unique_ptr<Platform> s_platform;
|
||||
|
||||
static void signal_handler(int)
|
||||
{
|
||||
constexpr char message[] = "A signal was received. A second signal will force Dolphin to stop.\n";
|
||||
constexpr char message[] =
|
||||
"A signal was received. A second signal will force BaijiSteamVR to stop.\n";
|
||||
#ifdef _WIN32
|
||||
puts(message);
|
||||
#else
|
||||
|
||||
@@ -14,68 +14,27 @@
|
||||
|
||||
AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("About Dolphin"));
|
||||
|
||||
QString branch_str = QString::fromStdString(Common::GetScmBranchStr());
|
||||
const int commits_ahead = Common::GetScmCommitsAheadMaster();
|
||||
if (commits_ahead > 0)
|
||||
{
|
||||
branch_str = tr("%1 (%2)").arg(
|
||||
branch_str,
|
||||
// i18n: A positive number of version control commits made compared to some named branch
|
||||
tr("%1 commit(s) ahead of %2").arg(commits_ahead).arg(QStringLiteral("master")));
|
||||
}
|
||||
setWindowTitle(tr("About BaijiSteamVR"));
|
||||
|
||||
const QString text =
|
||||
QStringLiteral(R"(
|
||||
<p style='font-size:38pt; font-weight:400;'>Dolphin</p>
|
||||
<p style='font-size:38pt; font-weight:400;'>BaijiSteamVR</p>
|
||||
|
||||
<p style='font-size:18pt;'>%VERSION_STRING%</p>
|
||||
<p style='font-size:18pt;'>%VERSION%</p>
|
||||
|
||||
<p style='font-size: small;'>
|
||||
%BRANCH%<br>
|
||||
%REVISION%<br><br>
|
||||
%QT_VERSION%
|
||||
<p>
|
||||
BaijiSteamVR is a free and open-source GameCube and Wii emulator.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
%CHECK_FOR_UPDATES%: <a href='https://dolphin-emu.org/download'>dolphin-emu.org/download</a>
|
||||
<a href='https://github.com/thejerf/baijiSteamVR'>BaijiSteamVR project page</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
%ABOUT_DOLPHIN%
|
||||
</p>
|
||||
|
||||
<p>
|
||||
%GAMES_YOU_OWN%
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href='https://github.com/dolphin-emu/dolphin/blob/master/COPYING'>%LICENSE%</a> |
|
||||
<a href='https://github.com/dolphin-emu/dolphin/graphs/contributors'>%AUTHORS%</a> |
|
||||
<a href='https://forums.dolphin-emu.org/'>%SUPPORT%</a>
|
||||
Licensed under GPL-2.0-or-later. See COPYING and LICENSES in the installation for license texts.
|
||||
)")
|
||||
.replace(QStringLiteral("%VERSION_STRING%"),
|
||||
QString::fromUtf8(Common::GetScmDescStr().c_str()))
|
||||
.replace(QStringLiteral("%BRANCH%"),
|
||||
// i18n: "Branch" means the version control term, not a literal tree branch.
|
||||
tr("Branch: %1").arg(branch_str))
|
||||
.replace(QStringLiteral("%REVISION%"),
|
||||
tr("Revision: %1").arg(QString::fromUtf8(Common::GetScmRevGitStr().c_str())))
|
||||
.replace(QStringLiteral("%QT_VERSION%"),
|
||||
tr("Using Qt %1").arg(QStringLiteral(QT_VERSION_STR)))
|
||||
.replace(QStringLiteral("%CHECK_FOR_UPDATES%"), tr("Check for updates"))
|
||||
.replace(QStringLiteral("%ABOUT_DOLPHIN%"),
|
||||
// i18n: The word "free" in the standard phrase "free and open source"
|
||||
// is "free" as in "freedom" - it refers to certain properties of the
|
||||
// software's license, not the software's price. (It is true that Dolphin
|
||||
// can be downloaded at no cost, but that's not what this message says.)
|
||||
tr("Dolphin is a free and open-source GameCube and Wii emulator."))
|
||||
.replace(QStringLiteral("%GAMES_YOU_OWN%"),
|
||||
tr("This software should not be used to play games you do not legally own."))
|
||||
.replace(QStringLiteral("%LICENSE%"), tr("License"))
|
||||
.replace(QStringLiteral("%AUTHORS%"), tr("Authors"))
|
||||
.replace(QStringLiteral("%SUPPORT%"), tr("Support"));
|
||||
.replace(QStringLiteral("%VERSION%"),
|
||||
QString::fromUtf8(Common::GetScmDescStr().c_str()));
|
||||
|
||||
QLabel* text_label = new QLabel(text);
|
||||
text_label->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
@@ -88,8 +47,8 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent)
|
||||
// in your translation, please use the type of curly quotes that's appropriate for
|
||||
// your language. If you aren't sure which type is appropriate, see
|
||||
// https://en.wikipedia.org/wiki/Quotation_mark#Specific_language_features
|
||||
tr("\u00A9 2003-2024+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are "
|
||||
"trademarks of Nintendo. Dolphin is not affiliated with Nintendo in any way.")));
|
||||
tr("\u00A9 2003-2024+ Dolphin Team. \u201cGameCube\u201d and \u201cWii\u201d are "
|
||||
"trademarks of Nintendo. BaijiSteamVR is not affiliated with Nintendo.")));
|
||||
|
||||
QLabel* logo = new QLabel();
|
||||
logo->setPixmap(Resources::GetAppIcon().pixmap(200, 200));
|
||||
|
||||
@@ -66,7 +66,7 @@ void AchievementSettingsWidget::CreateLayout()
|
||||
new ToolTipCheckBox(tr("Enable RetroAchievements.org Integration"));
|
||||
m_common_integration_enabled_input->SetDescription(
|
||||
tr("Enable integration with RetroAchievements for earning achievements and competing in "
|
||||
"leaderboards.<br><br>Must log in with a RetroAchievements account to use. Dolphin does "
|
||||
"leaderboards.<br><br>Must log in with a RetroAchievements account to use. BaijiSteamVR does "
|
||||
"not save your password locally and uses an API token to maintain login."));
|
||||
m_common_username_label = new QLabel(tr("Username"));
|
||||
m_common_username_input = new QLineEdit(QStringLiteral(""));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
if (MSVC)
|
||||
if(_M_ARM_64)
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/Externals/Qt/Qt6.5.1/ARM64")
|
||||
@@ -338,6 +339,8 @@ add_executable(dolphin-emu
|
||||
NetPlay/PadMappingDialog.h
|
||||
NANDRepairDialog.cpp
|
||||
NANDRepairDialog.h
|
||||
FrameFlatModeInputWarningDialog.cpp
|
||||
FrameFlatModeInputWarningDialog.h
|
||||
NKitWarningDialog.cpp
|
||||
NKitWarningDialog.h
|
||||
QtUtils/AnalyticsPrompt.cpp
|
||||
@@ -450,6 +453,10 @@ add_executable(dolphin-emu
|
||||
WiiUpdate.h
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set_target_properties(dolphin-emu PROPERTIES OUTPUT_NAME baiji)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_sources(dolphin-emu PRIVATE
|
||||
Styles/Dark/dark.qrc
|
||||
@@ -622,6 +629,9 @@ if(GETTEXT_MSGFMT_EXECUTABLE)
|
||||
if(WIN32)
|
||||
set(mo_dir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Languages)
|
||||
set(mo ${mo_dir}/${lang}.mo)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(mo_dir ${CMAKE_CURRENT_BINARY_DIR}/${lang})
|
||||
set(mo ${mo_dir}/baiji.mo)
|
||||
else()
|
||||
set(mo_dir ${CMAKE_CURRENT_BINARY_DIR}/${lang})
|
||||
set(mo ${mo_dir}/dolphin-emu.mo)
|
||||
@@ -632,6 +642,8 @@ if(GETTEXT_MSGFMT_EXECUTABLE)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set_source_files_properties(${mo} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/${lang}.lproj")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
install(FILES ${mo} DESTINATION ${datadir}/locale/${lang}/LC_MESSAGES)
|
||||
else()
|
||||
install(FILES ${mo} DESTINATION share/locale/${lang}/LC_MESSAGES)
|
||||
endif()
|
||||
|
||||
@@ -35,7 +35,7 @@ CheatWarningWidget::CheatWarningWidget(const std::string& game_id, bool restart_
|
||||
void CheatWarningWidget::CreateWidgets()
|
||||
{
|
||||
m_text = new QLabel();
|
||||
m_config_button = new QPushButton(tr("Configure Dolphin"));
|
||||
m_config_button = new QPushButton(tr("Configure BaijiSteamVR"));
|
||||
|
||||
m_config_button->setHidden(true);
|
||||
|
||||
@@ -62,7 +62,7 @@ void CheatWarningWidget::Update(bool running)
|
||||
{
|
||||
hide_widget = false;
|
||||
hide_config_button = false;
|
||||
m_text->setText(tr("Dolphin's cheat system is currently disabled."));
|
||||
m_text->setText(tr("BaijiSteamVR's cheat system is currently disabled."));
|
||||
}
|
||||
|
||||
setHidden(hide_widget);
|
||||
|
||||
@@ -48,10 +48,7 @@ void DualShockUDPClientWidget::CreateWidgets()
|
||||
|
||||
auto* description =
|
||||
new QLabel(tr("DSU protocol enables the use of input and motion data from compatible "
|
||||
"sources, like PlayStation, Nintendo Switch and Steam controllers.<br><br>"
|
||||
"For setup instructions, "
|
||||
"<a href=\"https://wiki.dolphin-emu.org/index.php?title=DSU_Client\">"
|
||||
"refer to this page</a>."));
|
||||
"sources, like PlayStation, Nintendo Switch and Steam controllers."));
|
||||
description->setTextFormat(Qt::RichText);
|
||||
description->setWordWrap(true);
|
||||
description->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
|
||||
@@ -54,9 +54,7 @@ void FreeLookWidget::CreateLayout()
|
||||
auto* description =
|
||||
new QLabel(tr("Free Look allows for manipulation of the in-game camera. "
|
||||
"Different camera types are available from the dropdown.<br><br>"
|
||||
"For detailed instructions, "
|
||||
"<a href=\"https://wiki.dolphin-emu.org/index.php?title=Free_Look\">"
|
||||
"refer to this page</a>."));
|
||||
"Use the camera type and movement controls to adjust the view."));
|
||||
description->setTextFormat(Qt::RichText);
|
||||
description->setWordWrap(true);
|
||||
description->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
|
||||
@@ -263,7 +263,7 @@ void GameConfigWidget::CreateWidgets()
|
||||
"settings are disabled when the global graphics backend doesn't "
|
||||
"match the game setting.");
|
||||
|
||||
auto* const help_label = new QLabel(tr("These settings override core Dolphin settings."));
|
||||
auto* const help_label = new QLabel(tr("These settings override core BaijiSteamVR settings."));
|
||||
|
||||
auto* const help_widget =
|
||||
QtUtils::CreateIconWarning(this, QStyle::SP_MessageBoxQuestion, help_label);
|
||||
|
||||
@@ -94,6 +94,14 @@ void GamecubeControllersWidget::CreateLayout()
|
||||
m_gc_layout->addWidget(gc_label, controller_row, 0);
|
||||
m_gc_layout->addWidget(gc_box, controller_row, 1);
|
||||
m_gc_layout->addWidget(gc_button, controller_row, 2);
|
||||
|
||||
// Baiju exposes one controller port on the Frame; retain the other ports in core config.
|
||||
if (i != 0)
|
||||
{
|
||||
gc_label->hide();
|
||||
gc_box->hide();
|
||||
gc_button->hide();
|
||||
}
|
||||
}
|
||||
m_gc_box->setLayout(m_gc_layout);
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ void AdvancedWidget::AddDescriptions()
|
||||
"leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_LOG_RENDERTIME_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Logs the render time of every frame to User/Logs/render_time.txt.<br><br>Use this "
|
||||
"feature to measure Dolphin's performance.<br><br><dolphin_emphasis>If "
|
||||
"feature to measure BaijiSteamVR's performance.<br><br><dolphin_emphasis>If "
|
||||
"unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_DUMP_TEXTURE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dumps decoded game textures based on the other flags to "
|
||||
@@ -360,7 +360,7 @@ void AdvancedWidget::AddDescriptions()
|
||||
"<dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_COMMAND_BUFFERS_IN_FLIGHT_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"How many command lists (D3D12) or command buffers (Vulkan) the backend keeps in flight. "
|
||||
"Each time one is submitted, Dolphin reuses the oldest and must wait for it to finish on "
|
||||
"Each time one is submitted, BaijiSteamVR reuses the oldest and must wait for it to finish on "
|
||||
"the GPU, so a shallow ring stalls whenever the GPU is slower to complete work than Dolphin "
|
||||
"is to queue it. Raising this can recover a lot of performance in games that submit many "
|
||||
"times per frame, such as those needing CPU EFB Access, and in VR.<br><br>Higher values cost "
|
||||
|
||||
@@ -46,8 +46,6 @@ EnhancementsWidget::EnhancementsWidget(GraphicsPane* gfx_pane)
|
||||
connect(gfx_pane, &GraphicsPane::UseGPUTextureDecodingChanged, this, [this] {
|
||||
m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
|
||||
});
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
&EnhancementsWidget::UpdateStereoscopyAvailability);
|
||||
}
|
||||
|
||||
constexpr int ANISO_1x = std::to_underlying(AnisotropicFilteringMode::Force1x);
|
||||
@@ -209,46 +207,7 @@ void EnhancementsWidget::CreateWidgets()
|
||||
enhancements_layout->addWidget(m_hdr, row, 1, 1, -1);
|
||||
++row;
|
||||
|
||||
// Stereoscopy
|
||||
m_stereoscopy_box = new QGroupBox(tr("Stereoscopy"));
|
||||
auto* stereoscopy_layout = new QGridLayout();
|
||||
m_stereoscopy_box->setLayout(stereoscopy_layout);
|
||||
|
||||
m_3d_mode = new ConfigChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"),
|
||||
tr("HDMI 3D"), tr("Passive")},
|
||||
Config::GFX_STEREO_MODE, m_game_layer);
|
||||
m_3d_depth = new ConfigFloatSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH,
|
||||
1.0f, m_game_layer);
|
||||
m_3d_convergence = new ConfigFloatSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM,
|
||||
Config::GFX_STEREO_CONVERGENCE, 0.01f, m_game_layer);
|
||||
m_3d_depth_value = new QLabel();
|
||||
m_3d_convergence_value = new QLabel();
|
||||
|
||||
m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES, m_game_layer);
|
||||
|
||||
m_3d_per_eye_resolution = new ConfigBool(
|
||||
tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL, m_game_layer);
|
||||
|
||||
stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_mode, 0, 1);
|
||||
stereoscopy_layout->addWidget(new ConfigFloatLabel(tr("Depth:"), m_3d_depth), 1, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_depth, 1, 1);
|
||||
stereoscopy_layout->addWidget(m_3d_depth_value, 1, 2);
|
||||
stereoscopy_layout->addWidget(new ConfigFloatLabel(tr("Convergence:"), m_3d_convergence), 2, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_convergence, 2, 1);
|
||||
stereoscopy_layout->addWidget(m_3d_convergence_value, 2, 2);
|
||||
stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_per_eye_resolution, 4, 0);
|
||||
|
||||
m_3d_depth_value->setText(QString::asprintf("%.0f", m_3d_depth->GetValue()));
|
||||
m_3d_convergence_value->setText(QString::asprintf("%.2f", m_3d_convergence->GetValue()));
|
||||
|
||||
auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
|
||||
if (current_stereo_mode != StereoMode::SBS && current_stereo_mode != StereoMode::TAB)
|
||||
m_3d_per_eye_resolution->hide();
|
||||
|
||||
main_layout->addWidget(enhancements_box);
|
||||
main_layout->addWidget(m_stereoscopy_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
@@ -256,16 +215,6 @@ void EnhancementsWidget::CreateWidgets()
|
||||
|
||||
void EnhancementsWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] {
|
||||
auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
|
||||
LoadPostProcessingShaders();
|
||||
|
||||
if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB)
|
||||
m_3d_per_eye_resolution->show();
|
||||
else
|
||||
m_3d_per_eye_resolution->hide();
|
||||
});
|
||||
|
||||
connect(m_post_processing_effect, &QComboBox::currentIndexChanged, this,
|
||||
&EnhancementsWidget::ShaderChanged);
|
||||
|
||||
@@ -273,12 +222,6 @@ void EnhancementsWidget::ConnectWidgets()
|
||||
&EnhancementsWidget::ConfigureColorCorrection);
|
||||
connect(m_configure_post_processing_effect, &QPushButton::clicked, this,
|
||||
&EnhancementsWidget::ConfigurePostProcessingShader);
|
||||
|
||||
connect(m_3d_depth, &ConfigFloatSlider::valueChanged, this,
|
||||
[this] { m_3d_depth_value->setText(QString::asprintf("%.0f", m_3d_depth->GetValue())); });
|
||||
connect(m_3d_convergence, &ConfigFloatSlider::valueChanged, this, [this] {
|
||||
m_3d_convergence_value->setText(QString::asprintf("%.2f", m_3d_convergence->GetValue()));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -353,8 +296,6 @@ void EnhancementsWidget::OnBackendChanged()
|
||||
m_configure_color_correction->setEnabled(g_backend_info.bSupportsPostProcessing);
|
||||
m_hdr->setEnabled(g_backend_info.bSupportsHDROutput);
|
||||
|
||||
UpdateStereoscopyAvailability();
|
||||
|
||||
// PostProcessing
|
||||
const bool supports_postprocessing = g_backend_info.bSupportsPostProcessing;
|
||||
if (!supports_postprocessing)
|
||||
@@ -375,13 +316,6 @@ void EnhancementsWidget::OnBackendChanged()
|
||||
UpdateAntialiasingOptions();
|
||||
}
|
||||
|
||||
void EnhancementsWidget::UpdateStereoscopyAvailability()
|
||||
{
|
||||
const bool supports_stereoscopy = g_backend_info.bSupportsGeometryShaders;
|
||||
const bool openxr_enabled = Config::Get(Config::GFX_VR_ENABLE_OPENXR);
|
||||
m_stereoscopy_box->setEnabled(supports_stereoscopy && !openxr_enabled);
|
||||
}
|
||||
|
||||
void EnhancementsWidget::ShaderChanged()
|
||||
{
|
||||
auto shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
|
||||
@@ -416,7 +350,6 @@ void EnhancementsWidget::OnConfigChanged()
|
||||
// being global.
|
||||
m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
|
||||
m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
|
||||
UpdateStereoscopyAvailability();
|
||||
UpdateAntialiasingOptions();
|
||||
|
||||
// Needs to update after deleting a key for 3d settings.
|
||||
@@ -538,28 +471,6 @@ void EnhancementsWidget::AddDescriptions()
|
||||
"detail.<br><br>Disabling fog will break some games which rely on proper fog "
|
||||
"emulation.<br><br><dolphin_emphasis>If unsure, leave this "
|
||||
"unchecked.</dolphin_emphasis>");
|
||||
static const char TR_3D_MODE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Selects the stereoscopic 3D mode. Stereoscopy allows a better feeling "
|
||||
"of depth if the necessary hardware is present. Heavily decreases "
|
||||
"emulation speed and sometimes causes issues.<br><br>Side-by-Side and Top-and-Bottom are "
|
||||
"used by most 3D TVs.<br>Anaglyph is used for Red-Cyan colored glasses.<br>HDMI 3D is "
|
||||
"used when the monitor supports 3D display resolutions.<br>Passive is another type of 3D "
|
||||
"used by some TVs."
|
||||
"<br><br><dolphin_emphasis>If unsure, select Off.</dolphin_emphasis>");
|
||||
static const char TR_3D_DEPTH_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Controls the separation distance between the virtual cameras.<br><br>A higher "
|
||||
"value creates a stronger feeling of depth while a lower value is more comfortable.");
|
||||
static const char TR_3D_CONVERGENCE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Controls the distance of the convergence plane. This is the distance at which "
|
||||
"virtual objects will appear to be in front of the screen.<br><br>A higher value creates "
|
||||
"stronger out-of-screen effects while a lower value is more comfortable.");
|
||||
static const char TR_3D_SWAP_EYES_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Swaps the left and right eye. Most useful in side-by-side stereoscopy "
|
||||
"mode.<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_3D_PER_EYE_RESOLUTION_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Whether each eye gets full or half image resolution when using side-by-side "
|
||||
"or above-and-below 3D."
|
||||
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_FORCE_24BIT_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Forces the game to render the RGB color channels in 24-bit, thereby increasing "
|
||||
"quality by reducing color banding.<br><br>Has no impact on performance and causes "
|
||||
@@ -620,19 +531,6 @@ void EnhancementsWidget::AddDescriptions()
|
||||
m_arbitrary_mipmap_detection->SetDescription(tr(TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION));
|
||||
|
||||
m_hdr->SetDescription(tr(TR_HDR_DESCRIPTION));
|
||||
|
||||
m_3d_mode->SetTitle(tr("Stereoscopic 3D Mode"));
|
||||
m_3d_mode->SetDescription(tr(TR_3D_MODE_DESCRIPTION));
|
||||
|
||||
m_3d_depth->SetTitle(tr("Depth"));
|
||||
m_3d_depth->SetDescription(tr(TR_3D_DEPTH_DESCRIPTION));
|
||||
|
||||
m_3d_convergence->SetTitle(tr("Convergence"));
|
||||
m_3d_convergence->SetDescription(tr(TR_3D_CONVERGENCE_DESCRIPTION));
|
||||
|
||||
m_3d_per_eye_resolution->SetDescription(tr(TR_3D_PER_EYE_RESOLUTION_DESCRIPTION));
|
||||
|
||||
m_3d_swap_eyes->SetDescription(tr(TR_3D_SWAP_EYES_DESCRIPTION));
|
||||
}
|
||||
|
||||
void EnhancementsWidget::ConfigureColorCorrection()
|
||||
|
||||
@@ -11,7 +11,6 @@ class ConfigComplexChoice;
|
||||
class ConfigStringChoice;
|
||||
class ConfigFloatSlider;
|
||||
class GraphicsPane;
|
||||
class QGroupBox;
|
||||
class QPushButton;
|
||||
class QLabel;
|
||||
class ToolTipPushButton;
|
||||
@@ -38,7 +37,6 @@ private:
|
||||
void AddDescriptions();
|
||||
|
||||
void OnBackendChanged();
|
||||
void UpdateStereoscopyAvailability();
|
||||
void UpdateAntialiasingOptions();
|
||||
void LoadPostProcessingShaders();
|
||||
void ShaderChanged();
|
||||
@@ -64,15 +62,5 @@ private:
|
||||
ConfigBool* m_arbitrary_mipmap_detection;
|
||||
ConfigBool* m_hdr;
|
||||
|
||||
// Stereoscopy
|
||||
QGroupBox* m_stereoscopy_box;
|
||||
ConfigChoice* m_3d_mode;
|
||||
ConfigFloatSlider* m_3d_depth;
|
||||
QLabel* m_3d_depth_value;
|
||||
ConfigFloatSlider* m_3d_convergence;
|
||||
QLabel* m_3d_convergence_value;
|
||||
ConfigBool* m_3d_swap_eyes;
|
||||
ConfigBool* m_3d_per_eye_resolution;
|
||||
|
||||
Config::Layer* m_game_layer = nullptr;
|
||||
};
|
||||
@@ -234,14 +234,14 @@ void GeneralWidget::AddDescriptions()
|
||||
QT_TR_NOOP("Automatically adjusts the window size to the internal resolution.<br><br>"
|
||||
"<dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_RENDER_TO_MAINWINDOW_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Uses the main Dolphin window for rendering rather than "
|
||||
QT_TR_NOOP("Uses the main BaijiSteamVR window for rendering rather than "
|
||||
"a separate render window.<br><br><dolphin_emphasis>If unsure, leave "
|
||||
"this unchecked.</dolphin_emphasis>");
|
||||
static const char TR_ASPECT_RATIO_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Selects which aspect ratio to use for displaying the game."
|
||||
"<br><br>The aspect ratio of the image sent out by the original consoles varied depending on "
|
||||
"the game and rarely exactly matched 4:3 or 16:9. Some of the image would be cut off by the "
|
||||
"edges of the TV, or the image wouldn't fill the TV entirely. By default, Dolphin shows the "
|
||||
"edges of the TV, or the image wouldn't fill the TV entirely. By default, BaijiSteamVR shows the "
|
||||
"whole image without distorting its proportions, which means it's normal for the image to "
|
||||
"not entirely fill your display."
|
||||
"<br><br><b>Auto</b>: Mimics a TV with either a 4:3 or 16:9 aspect ratio, depending on which "
|
||||
|
||||
@@ -26,7 +26,7 @@ void GraphicsModWarningWidget::CreateWidgets()
|
||||
{
|
||||
m_text = new QLabel();
|
||||
|
||||
m_config_button = new QPushButton(tr("Configure Dolphin"));
|
||||
m_config_button = new QPushButton(tr("Configure BaijiSteamVR"));
|
||||
m_config_button->setHidden(true);
|
||||
|
||||
auto* const layout = new QHBoxLayout{this};
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QSignalBlocker>
|
||||
|
||||
#include "DolphinQt/Config/Mapping/IOWindow.h"
|
||||
#include "DolphinQt/Config/Mapping/MappingButton.h"
|
||||
@@ -31,6 +33,88 @@
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerEmu/StickGate.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/MappingCommon.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class FrameMappingComboBox final : public QComboBox
|
||||
{
|
||||
public:
|
||||
FrameMappingComboBox(MappingWidget* widget, ControlReference* reference)
|
||||
: QComboBox(widget), m_reference(reference)
|
||||
{
|
||||
setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
|
||||
setMinimumContentsLength(18);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
addItem(tr("Unmapped"), QString{});
|
||||
|
||||
connect(widget, &MappingWidget::ConfigChanged, this, [this, widget] {
|
||||
PopulateControls(widget);
|
||||
UpdateSelection();
|
||||
});
|
||||
}
|
||||
|
||||
ControlReference* GetControlReference() const { return m_reference; }
|
||||
|
||||
private:
|
||||
void PopulateControls(MappingWidget* widget)
|
||||
{
|
||||
if (m_populated || !widget->GetController())
|
||||
return;
|
||||
|
||||
const auto& default_device = widget->GetController()->GetDefaultDevice();
|
||||
const auto device = g_controller_interface.FindDevice(default_device);
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
ciface::Core::DeviceQualifier control_device;
|
||||
control_device.FromDevice(device.get());
|
||||
|
||||
const auto add_control = [this, &control_device, &default_device](
|
||||
const ciface::Core::Device::Control* control) {
|
||||
if (control->IsHidden())
|
||||
return;
|
||||
|
||||
const auto expression = ciface::MappingCommon::GetExpressionForControl(
|
||||
control->GetName(), control_device, default_device, ciface::MappingCommon::Quote::On);
|
||||
addItem(QString::fromStdString(control->GetName()), QString::fromStdString(expression));
|
||||
};
|
||||
|
||||
if (m_reference->IsInput())
|
||||
{
|
||||
for (const auto* input : device->Inputs())
|
||||
add_control(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto* output : device->Outputs())
|
||||
add_control(output);
|
||||
}
|
||||
|
||||
m_populated = true;
|
||||
}
|
||||
|
||||
void UpdateSelection()
|
||||
{
|
||||
const auto lock = ControllerEmu::EmulatedController::GetStateLock();
|
||||
const QString expression = QString::fromStdString(m_reference->GetExpression());
|
||||
QSignalBlocker blocker(this);
|
||||
|
||||
int index = findData(expression);
|
||||
if (index == -1 && !expression.isEmpty())
|
||||
{
|
||||
addItem(tr("Current mapping: %1").arg(expression), expression);
|
||||
index = count() - 1;
|
||||
}
|
||||
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
ControlReference* const m_reference;
|
||||
bool m_populated = false;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
MappingWidget::MappingWidget(MappingWindow* parent) : m_parent(parent)
|
||||
{
|
||||
@@ -403,20 +487,45 @@ void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLa
|
||||
(is_modifier ? ControlType::ModifierInput : ControlType::NormalInput) :
|
||||
ControlType::Output;
|
||||
|
||||
auto* const button = new MappingButton(this, control->control_ref.get(), control_type);
|
||||
|
||||
if (control->control_ref->IsInput())
|
||||
QWidget* mapping_widget = nullptr;
|
||||
if (m_parent->IsFrameControllerMapping())
|
||||
{
|
||||
if (m_previous_mapping_button)
|
||||
auto* const combo = new FrameMappingComboBox(this, control->control_ref.get());
|
||||
mapping_widget = combo;
|
||||
|
||||
connect(combo, &QComboBox::currentIndexChanged, this, [this, combo] {
|
||||
auto* const control_reference = combo->GetControlReference();
|
||||
const auto expression = combo->currentData().toString().toStdString();
|
||||
auto* const controller = GetController();
|
||||
{
|
||||
const auto lock = controller->GetStateLock();
|
||||
control_reference->SetExpression(expression);
|
||||
controller->UpdateSingleControlReference(g_controller_interface, control_reference);
|
||||
controller->GetConfig()->GenerateControllerTextures();
|
||||
}
|
||||
|
||||
emit ConfigChanged();
|
||||
GetParent()->Save();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* const button = new MappingButton(this, control->control_ref.get(), control_type);
|
||||
mapping_widget = button;
|
||||
|
||||
if (control->control_ref->IsInput())
|
||||
{
|
||||
connect(m_previous_mapping_button, &MappingButton::QueueNextButtonMapping,
|
||||
[this, button] { m_parent->QueueInputDetection(button); });
|
||||
if (m_previous_mapping_button)
|
||||
{
|
||||
connect(m_previous_mapping_button, &MappingButton::QueueNextButtonMapping,
|
||||
[this, button] { m_parent->QueueInputDetection(button); });
|
||||
}
|
||||
m_previous_mapping_button = button;
|
||||
}
|
||||
m_previous_mapping_button = button;
|
||||
}
|
||||
|
||||
button->setMinimumWidth(100);
|
||||
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
mapping_widget->setMinimumWidth(100);
|
||||
mapping_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
const bool translate = control->translate == ControllerEmu::Translatability::Translate;
|
||||
const QString translated_name =
|
||||
@@ -430,12 +539,12 @@ void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLa
|
||||
auto* const hbox = new QHBoxLayout;
|
||||
hbox->setSpacing(0);
|
||||
hbox->addWidget(button_indicator);
|
||||
hbox->addWidget(button);
|
||||
hbox->addWidget(mapping_widget);
|
||||
layout->addRow(translated_name, hbox);
|
||||
}
|
||||
else
|
||||
{
|
||||
layout->addRow(translated_name, button);
|
||||
layout->addRow(translated_name, mapping_widget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "DolphinQt/Config/Mapping/HotkeyVR.h"
|
||||
#include "DolphinQt/Config/Mapping/HotkeyWii.h"
|
||||
#include "DolphinQt/Config/Mapping/MappingCommon.h"
|
||||
#include "DolphinQt/Config/Mapping/OpenXRWiimoteConfigSessionController.h"
|
||||
#include "DolphinQt/Config/Mapping/WiimoteEmuExtension.h"
|
||||
#include "DolphinQt/Config/Mapping/WiimoteEmuExtensionMotionInput.h"
|
||||
#include "DolphinQt/Config/Mapping/WiimoteEmuExtensionMotionSimulation.h"
|
||||
@@ -79,9 +78,9 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const char* OPENXR_WIIMOTE_DEFAULT_PROFILE = "OpenXR Wii Remote.ini";
|
||||
constexpr const char* OPENXR_GCPAD_DEFAULT_PROFILE = "Quest Touch GameCube.ini";
|
||||
constexpr const char* OPENXR_HOTKEY_DEFAULT_PROFILE = "Quest.ini";
|
||||
constexpr const char* STEAM_FRAME_WIIMOTE_DEFAULT_PROFILE = "Steam Frame Wii Remote + Nunchuk.ini";
|
||||
constexpr const char* STEAM_FRAME_GCPAD_DEFAULT_PROFILE = "Steam Frame GameCube.ini";
|
||||
constexpr const char* STEAM_FRAME_HOTKEY_DEFAULT_PROFILE = "Steam Frame.ini";
|
||||
constexpr const char* OPENXR_CONTROLLER_DEVICE = "OpenXR/0/OpenXR Controller";
|
||||
}
|
||||
|
||||
@@ -116,32 +115,11 @@ MappingWindow::MappingWindow(QWidget* parent, Type type, int port_num)
|
||||
const auto lock = GetController()->GetStateLock();
|
||||
emit ConfigChanged();
|
||||
|
||||
#if defined(ENABLE_VR) && defined(HAS_VULKAN)
|
||||
const bool is_openxr_wiimote_mapper =
|
||||
m_mapping_type == Type::MAPPING_WIIMOTE_EMU && m_is_openxr_wiimote;
|
||||
const bool is_gamecube_mapper = m_mapping_type == Type::MAPPING_GCPAD;
|
||||
const bool is_hotkey_mapper = m_mapping_type == Type::MAPPING_HOTKEYS;
|
||||
if (is_openxr_wiimote_mapper || is_gamecube_mapper || is_hotkey_mapper)
|
||||
{
|
||||
using TargetType = OpenXRWiimoteConfigSessionController::TargetType;
|
||||
const TargetType target_type = is_openxr_wiimote_mapper ?
|
||||
TargetType::WiiRemote :
|
||||
(is_gamecube_mapper ? TargetType::GameCubeController :
|
||||
TargetType::Hotkeys);
|
||||
m_openxr_config_session_controller =
|
||||
new OpenXRWiimoteConfigSessionController(this, m_port, target_type);
|
||||
if (auto* outer = qobject_cast<QVBoxLayout*>(m_devices_box->layout()))
|
||||
outer->addWidget(m_openxr_config_session_controller->GetButton(), 0);
|
||||
UpdateOpenXRConfigButtonVisibility();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VR
|
||||
if (m_is_openxr_wiimote)
|
||||
{
|
||||
m_openxr_profile_label = new QLabel(
|
||||
tr("OpenXR: not connected\n"
|
||||
"Launch a game or use \"Configure in VR\" to bind VR controller inputs."));
|
||||
m_openxr_profile_label =
|
||||
new QLabel(tr("OpenXR: not connected\nLaunch a game to bind VR controller inputs."));
|
||||
m_openxr_profile_label->setWordWrap(true);
|
||||
auto* outer = qobject_cast<QVBoxLayout*>(m_devices_box->layout());
|
||||
if (outer)
|
||||
@@ -171,7 +149,8 @@ void MappingWindow::CreateDevicesLayout()
|
||||
m_devices_box = new QGroupBox(tr("Device"));
|
||||
m_devices_combo = new QComboBox();
|
||||
|
||||
auto* const options = new QToolButton();
|
||||
m_device_options = new QToolButton();
|
||||
auto* const options = m_device_options;
|
||||
// Make it more apparent that this is a menu with more options.
|
||||
options->setPopupMode(QToolButton::ToolButtonPopupMode::MenuButtonPopup);
|
||||
|
||||
@@ -309,8 +288,6 @@ void MappingWindow::ConnectWidgets()
|
||||
connect(&Settings::Instance(), &Settings::DevicesChanged, this, &MappingWindow::ConfigChanged);
|
||||
connect(this, &MappingWindow::ConfigChanged, this, &MappingWindow::UpdateDeviceList);
|
||||
connect(m_devices_combo, &QComboBox::currentIndexChanged, this, &MappingWindow::OnSelectDevice);
|
||||
connect(m_devices_combo, &QComboBox::currentIndexChanged, this,
|
||||
&MappingWindow::UpdateOpenXRConfigButtonVisibility);
|
||||
|
||||
connect(m_reset_clear, &QPushButton::clicked, this, &MappingWindow::OnClearFieldsPressed);
|
||||
connect(m_reset_default, &QPushButton::clicked, this, &MappingWindow::OnDefaultFieldsPressed);
|
||||
@@ -483,17 +460,17 @@ void MappingWindow::OnSelectDevice(int)
|
||||
|
||||
bool MappingWindow::IsCreateOtherDeviceMappingsEnabled() const
|
||||
{
|
||||
return m_other_device_mappings->isChecked();
|
||||
return !IsFrameControllerMapping() && m_other_device_mappings->isChecked();
|
||||
}
|
||||
|
||||
bool MappingWindow::IsWaitForAlternateMappingsEnabled() const
|
||||
{
|
||||
return m_wait_for_alternate_mappings->isChecked();
|
||||
return !IsFrameControllerMapping() && m_wait_for_alternate_mappings->isChecked();
|
||||
}
|
||||
|
||||
bool MappingWindow::IsIterativeMappingEnabled() const
|
||||
{
|
||||
return m_iterative_mapping->isChecked();
|
||||
return !IsFrameControllerMapping() && m_iterative_mapping->isChecked();
|
||||
}
|
||||
|
||||
void MappingWindow::RefreshDevices()
|
||||
@@ -513,47 +490,60 @@ void MappingWindow::UpdateDeviceList()
|
||||
|
||||
m_devices_combo->clear();
|
||||
|
||||
for (const auto& name : g_controller_interface.GetAllDeviceStrings())
|
||||
if (IsFrameControllerMapping())
|
||||
{
|
||||
const auto qname = QString::fromStdString(name);
|
||||
m_devices_combo->addItem(qname, qname);
|
||||
}
|
||||
const auto fixed_device = QString::fromLatin1(OPENXR_CONTROLLER_DEVICE);
|
||||
m_devices_combo->addItem(tr("Steam Frame Controller"), fixed_device);
|
||||
m_devices_combo->setCurrentIndex(0);
|
||||
m_devices_combo->setEnabled(false);
|
||||
m_device_options->hide();
|
||||
|
||||
const auto default_device = m_controller->GetDefaultDevice().ToString();
|
||||
|
||||
if (!default_device.empty())
|
||||
{
|
||||
const auto default_device_index =
|
||||
m_devices_combo->findText(QString::fromStdString(default_device));
|
||||
|
||||
if (default_device_index != -1)
|
||||
if (m_controller->GetDefaultDevice().ToString() != OPENXR_CONTROLLER_DEVICE)
|
||||
{
|
||||
m_devices_combo->setCurrentIndex(default_device_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Selected device is not currently attached.
|
||||
m_devices_combo->insertSeparator(m_devices_combo->count());
|
||||
const auto qname = QString::fromStdString(default_device);
|
||||
m_devices_combo->addItem(QLatin1Char{'['} + tr("disconnected") + QStringLiteral("] ") + qname,
|
||||
qname);
|
||||
m_devices_combo->setCurrentIndex(m_devices_combo->count() - 1);
|
||||
m_controller->SetDefaultDevice(OPENXR_CONTROLLER_DEVICE);
|
||||
m_controller->UpdateReferences(g_controller_interface);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_devices_combo->setEnabled(true);
|
||||
m_device_options->show();
|
||||
|
||||
UpdateOpenXRConfigButtonVisibility();
|
||||
for (const auto& name : g_controller_interface.GetAllDeviceStrings())
|
||||
{
|
||||
const auto qname = QString::fromStdString(name);
|
||||
m_devices_combo->addItem(qname, qname);
|
||||
}
|
||||
|
||||
const auto default_device = m_controller->GetDefaultDevice().ToString();
|
||||
|
||||
if (!default_device.empty())
|
||||
{
|
||||
const auto default_device_index =
|
||||
m_devices_combo->findText(QString::fromStdString(default_device));
|
||||
|
||||
if (default_device_index != -1)
|
||||
{
|
||||
m_devices_combo->setCurrentIndex(default_device_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Selected device is not currently attached.
|
||||
m_devices_combo->insertSeparator(m_devices_combo->count());
|
||||
const auto qname = QString::fromStdString(default_device);
|
||||
m_devices_combo->addItem(QLatin1Char{'['} + tr("disconnected") + QStringLiteral("] ") +
|
||||
qname,
|
||||
qname);
|
||||
m_devices_combo->setCurrentIndex(m_devices_combo->count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MappingWindow::UpdateOpenXRConfigButtonVisibility()
|
||||
bool MappingWindow::IsFrameControllerMapping() const
|
||||
{
|
||||
if (!m_openxr_config_session_controller)
|
||||
return;
|
||||
|
||||
const bool visible =
|
||||
m_mapping_type == Type::MAPPING_WIIMOTE_EMU ||
|
||||
((m_mapping_type == Type::MAPPING_GCPAD || m_mapping_type == Type::MAPPING_HOTKEYS) &&
|
||||
m_devices_combo->currentData().toString() == QString::fromLatin1(OPENXR_CONTROLLER_DEVICE));
|
||||
m_openxr_config_session_controller->GetButton()->setVisible(visible);
|
||||
return m_mapping_type == Type::MAPPING_WIIMOTE_EMU || m_mapping_type == Type::MAPPING_GCPAD ||
|
||||
m_mapping_type == Type::MAPPING_HOTKEYS;
|
||||
}
|
||||
|
||||
void MappingWindow::SetMappingType(MappingWindow::Type type)
|
||||
@@ -666,9 +656,25 @@ void MappingWindow::PopulateProfileSelection()
|
||||
{
|
||||
m_profiles_combo->clear();
|
||||
|
||||
const auto profile_uses_frame_device = [this](const std::string& path) {
|
||||
if (!IsFrameControllerMapping())
|
||||
return true;
|
||||
|
||||
Common::IniFile profile;
|
||||
if (!profile.Load(path))
|
||||
return false;
|
||||
|
||||
std::string device;
|
||||
return profile.GetOrCreateSection("Profile")->Get("Device", &device, "") &&
|
||||
device == OPENXR_CONTROLLER_DEVICE;
|
||||
};
|
||||
|
||||
const std::string profiles_path = m_config->GetUserProfileDirectoryPath();
|
||||
for (const auto& filename : Common::DoFileSearch(profiles_path, ".ini"))
|
||||
{
|
||||
if (!profile_uses_frame_device(filename))
|
||||
continue;
|
||||
|
||||
std::string basename;
|
||||
SplitPath(filename, nullptr, &basename, nullptr);
|
||||
if (!basename.empty()) // Ignore files with an empty name to avoid multiple problems
|
||||
@@ -679,9 +685,13 @@ void MappingWindow::PopulateProfileSelection()
|
||||
|
||||
for (const auto& filename : Common::DoFileSearch(m_config->GetSysProfileDirectoryPath(), ".ini"))
|
||||
{
|
||||
if (!profile_uses_frame_device(filename))
|
||||
continue;
|
||||
|
||||
std::string basename;
|
||||
SplitPath(filename, nullptr, &basename, nullptr);
|
||||
if (!basename.empty())
|
||||
if (!basename.empty() &&
|
||||
(!IsFrameControllerMapping() || basename.starts_with("Steam Frame")))
|
||||
{
|
||||
// i18n: "Stock" refers to input profiles included with Dolphin
|
||||
m_profiles_combo->addItem(tr("%1 (Stock)").arg(QString::fromStdString(basename)),
|
||||
@@ -729,25 +739,21 @@ bool MappingWindow::LoadOpenXRDefaultProfile()
|
||||
switch (m_mapping_type)
|
||||
{
|
||||
case Type::MAPPING_WIIMOTE_EMU:
|
||||
profile_name = OPENXR_WIIMOTE_DEFAULT_PROFILE;
|
||||
profile_name = STEAM_FRAME_WIIMOTE_DEFAULT_PROFILE;
|
||||
break;
|
||||
case Type::MAPPING_GCPAD:
|
||||
profile_name = OPENXR_GCPAD_DEFAULT_PROFILE;
|
||||
profile_name = STEAM_FRAME_GCPAD_DEFAULT_PROFILE;
|
||||
break;
|
||||
case Type::MAPPING_HOTKEYS:
|
||||
profile_name = OPENXR_HOTKEY_DEFAULT_PROFILE;
|
||||
profile_name = STEAM_FRAME_HOTKEY_DEFAULT_PROFILE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dolphin's built-in defaults target a keyboard or physical pad, which is useless once the
|
||||
// VR controllers are the input device, so "Default" restores the stock OpenXR profile instead.
|
||||
// The Wii Remote has a dedicated OpenXR source: honour that even before a device is selected.
|
||||
const bool openxr_selected =
|
||||
(m_mapping_type == Type::MAPPING_WIIMOTE_EMU && m_is_openxr_wiimote) ||
|
||||
m_controller->GetDefaultDevice().ToString() == OPENXR_CONTROLLER_DEVICE;
|
||||
if (!openxr_selected)
|
||||
// Dolphin's generic defaults target a keyboard or physical pad, so Frame mappings load their
|
||||
// Steam Frame profiles instead.
|
||||
if (!IsFrameControllerMapping())
|
||||
return false;
|
||||
|
||||
Common::IniFile ini;
|
||||
@@ -818,8 +824,7 @@ void MappingWindow::UpdateOpenXRProfileLabel()
|
||||
if (!snapshot.runtime_active)
|
||||
{
|
||||
m_openxr_profile_label->setText(
|
||||
tr("OpenXR: not connected\n"
|
||||
"Launch a game or use \"Configure in VR\" to bind VR controller inputs."));
|
||||
tr("OpenXR: not connected\nLaunch a game to bind VR controller inputs."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPointer>
|
||||
#include <QString>
|
||||
|
||||
namespace ControllerEmu
|
||||
@@ -14,7 +13,6 @@ class EmulatedController;
|
||||
|
||||
class InputConfig;
|
||||
class MappingButton;
|
||||
class OpenXRWiimoteConfigSessionController;
|
||||
|
||||
class QComboBox;
|
||||
class QDialogButtonBox;
|
||||
@@ -59,6 +57,7 @@ public:
|
||||
bool IsCreateOtherDeviceMappingsEnabled() const;
|
||||
bool IsWaitForAlternateMappingsEnabled() const;
|
||||
bool IsIterativeMappingEnabled() const;
|
||||
bool IsFrameControllerMapping() const;
|
||||
void ShowExtensionMotionTabs(bool show);
|
||||
void ActivateExtensionTab();
|
||||
|
||||
@@ -97,7 +96,6 @@ private:
|
||||
void UpdateProfileButtonState();
|
||||
void PopulateProfileSelection();
|
||||
void UpdateDeviceList();
|
||||
void UpdateOpenXRConfigButtonVisibility();
|
||||
|
||||
void OnDefaultFieldsPressed();
|
||||
void OnClearFieldsPressed();
|
||||
@@ -119,6 +117,7 @@ private:
|
||||
QWidget* m_profile_and_reset_container = nullptr;
|
||||
QHBoxLayout* m_devices_layout;
|
||||
QComboBox* m_devices_combo;
|
||||
QToolButton* m_device_options;
|
||||
QLabel* m_openxr_profile_label = nullptr;
|
||||
QAction* m_other_device_mappings;
|
||||
QAction* m_wait_for_alternate_mappings;
|
||||
@@ -151,5 +150,4 @@ private:
|
||||
const int m_port;
|
||||
bool m_is_openxr_wiimote = false;
|
||||
InputConfig* m_config;
|
||||
QPointer<OpenXRWiimoteConfigSessionController> m_openxr_config_session_controller;
|
||||
};
|
||||
@@ -43,15 +43,6 @@ void WiimoteEmuMotionControlIMU::CreateMainLayout()
|
||||
groups_layout->addWidget(
|
||||
CreateGroupBox(Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IMUGyroscope)));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* imu_layout = new QVBoxLayout();
|
||||
imu_layout->addWidget(
|
||||
CreateGroupBox(Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IMUGyroscope)));
|
||||
imu_layout->addWidget(CreateGroupBox(
|
||||
Wiimote::GetWiimoteGroup(GetPort(), WiimoteEmu::WiimoteGroup::IMUAccelerometer)));
|
||||
groups_layout->addLayout(imu_layout);
|
||||
}
|
||||
|
||||
m_main_layout = new QVBoxLayout();
|
||||
if (source != WiimoteSource::OpenXR)
|
||||
|
||||
@@ -85,7 +85,7 @@ void SDLHintsWindow::CreateMainLayout()
|
||||
m_directinput_detection = new ToolTipCheckBox(tr("Enable DirectInput Detection"));
|
||||
m_directinput_detection->SetDescription(
|
||||
tr("Controls whether SDL should use DirectInput for detecting controllers. Enabling this "
|
||||
"fixes hotplug detection issues with DualSense controllers but causes Dolphin to hang up "
|
||||
"fixes hotplug detection issues with DualSense controllers but causes BaijiSteamVR to hang up "
|
||||
"on shutdown when using certain 8BitDo controllers.<br><br><dolphin_emphasis>If unsure, "
|
||||
"leave this checked.</dolphin_emphasis>"));
|
||||
connect(m_directinput_detection, &ToolTipCheckBox::toggled, [](bool checked) {
|
||||
@@ -144,7 +144,7 @@ void SDLHintsWindow::CreateMainLayout()
|
||||
connect(m_tab_widget, &QTabWidget::currentChanged, this, &SDLHintsWindow::TabChanged);
|
||||
|
||||
auto* const warning_text =
|
||||
new QLabel(tr("Dolphin must be restarted for these changes to take effect."));
|
||||
new QLabel(tr("BaijiSteamVR must be restarted for these changes to take effect."));
|
||||
warning_text->setWordWrap(true);
|
||||
|
||||
// Create main layout
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "DolphinQt/Config/ToolTipControls/BalloonTip.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <QApplication>
|
||||
@@ -16,7 +18,6 @@
|
||||
#include <QPen>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QScreen>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
@@ -39,7 +40,8 @@ QWidget* s_parent = nullptr;
|
||||
} // namespace
|
||||
|
||||
void BalloonTip::ShowBalloon(const QString& title, const QString& message,
|
||||
const QPoint& target_arrow_tip_position, QWidget* const parent,
|
||||
const QPoint& target_arrow_tip_position,
|
||||
const QRect& target_widget_rect_global, QWidget* const parent,
|
||||
const ShowArrow show_arrow, const int border_width)
|
||||
{
|
||||
HideBalloon();
|
||||
@@ -47,13 +49,16 @@ void BalloonTip::ShowBalloon(const QString& title, const QString& message,
|
||||
return;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
(void)target_widget_rect_global;
|
||||
QString the_message = message;
|
||||
the_message.replace(QStringLiteral("<dolphin_emphasis>"), QStringLiteral("<b>"));
|
||||
the_message.replace(QStringLiteral("</dolphin_emphasis>"), QStringLiteral("</b>"));
|
||||
QToolTip::showText(target_arrow_tip_position, the_message, parent);
|
||||
#else
|
||||
s_the_balloon_tip = std::make_unique<BalloonTip>(PrivateTag{}, title, message, parent);
|
||||
s_the_balloon_tip->UpdateBoundsAndRedraw(target_arrow_tip_position, show_arrow, border_width);
|
||||
s_the_balloon_tip =
|
||||
std::make_unique<BalloonTip>(PrivateTag{}, title, message, parent, border_width);
|
||||
s_the_balloon_tip->UpdateBoundsAndRedraw(target_arrow_tip_position, target_widget_rect_global,
|
||||
show_arrow, border_width);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -70,12 +75,16 @@ void BalloonTip::HideBalloon()
|
||||
#endif
|
||||
}
|
||||
|
||||
BalloonTip::BalloonTip(PrivateTag, const QString& title, QString message, QWidget* const parent)
|
||||
BalloonTip::BalloonTip(PrivateTag, const QString& title, QString message, QWidget* const parent,
|
||||
const int border_width)
|
||||
: QWidget(nullptr, Qt::ToolTip)
|
||||
{
|
||||
s_parent = parent;
|
||||
setMouseTracking(true);
|
||||
|
||||
const QWidget* const owner_window = parent->window();
|
||||
m_owner_rect = QRect(owner_window->mapToGlobal(QPoint(0, 0)), owner_window->size());
|
||||
|
||||
QColor window_color;
|
||||
QColor text_color;
|
||||
QColor dolphin_emphasis;
|
||||
@@ -92,9 +101,19 @@ BalloonTip::BalloonTip(PrivateTag, const QString& title, QString message, QWidge
|
||||
message.replace(QStringLiteral("</dolphin_emphasis>"), QStringLiteral("</b></font>"));
|
||||
|
||||
auto* const balloontip_layout = new QVBoxLayout;
|
||||
balloontip_layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
balloontip_layout->setSizeConstraint(QLayout::SetNoConstraint);
|
||||
setLayout(balloontip_layout);
|
||||
|
||||
const float border_half_width = border_width / 2.0;
|
||||
const int rounded_corner_margin = border_half_width / 4;
|
||||
const int horizontal_margin = border_width + rounded_corner_margin + 12;
|
||||
const int bounded_horizontal_margin =
|
||||
std::min(horizontal_margin, std::max(0, (m_owner_rect.width() - 1) / 2));
|
||||
const int max_width = std::max(1, m_owner_rect.width() - 2 * bounded_horizontal_margin);
|
||||
const int vertical_margin = bounded_horizontal_margin;
|
||||
balloontip_layout->setContentsMargins(bounded_horizontal_margin, vertical_margin,
|
||||
bounded_horizontal_margin, vertical_margin);
|
||||
|
||||
const auto create_label = [=](const QString& text) {
|
||||
QLabel* const label = new QLabel;
|
||||
balloontip_layout->addWidget(label);
|
||||
@@ -102,7 +121,6 @@ BalloonTip::BalloonTip(PrivateTag, const QString& title, QString message, QWidge
|
||||
label->setText(text);
|
||||
label->setTextFormat(Qt::RichText);
|
||||
|
||||
const int max_width = label->screen()->availableGeometry().width() / 3;
|
||||
label->setMaximumWidth(max_width);
|
||||
|
||||
if (label->sizeHint().width() > max_width)
|
||||
@@ -185,37 +203,71 @@ void BalloonTip::paintEvent(QPaintEvent* const event)
|
||||
}
|
||||
|
||||
void BalloonTip::UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
const QRect& target_widget_rect_global,
|
||||
const ShowArrow show_arrow, const int border_full_width)
|
||||
{
|
||||
const float border_half_width = border_full_width / 2.0;
|
||||
|
||||
// This should be odd so that the arrow tip is a single pixel wide.
|
||||
const int arrow_full_width = 35;
|
||||
const float arrow_half_width = arrow_full_width / 2.0;
|
||||
// The y distance between the inner edge of the rectangle border and the inner tip of the arrow
|
||||
// border, and also the distance between the outer edge of the rectangle border and the outer tip
|
||||
// of the arrow border
|
||||
const int arrow_height = (1 + arrow_full_width) / 2;
|
||||
constexpr int preferred_arrow_full_width = 35;
|
||||
|
||||
// Distance between the label layout and the inner rectangle border edge
|
||||
const int balloon_interior_padding = 12;
|
||||
constexpr int balloon_interior_padding = 12;
|
||||
// Prevent the corners of the label layout from portruding into the rounded rectangle corners at
|
||||
// larger border sizes.
|
||||
const int rounded_corner_margin = border_half_width / 4;
|
||||
const int horizontal_margin =
|
||||
const int nominal_horizontal_margin =
|
||||
border_full_width + rounded_corner_margin + balloon_interior_padding;
|
||||
const int vertical_margin = horizontal_margin + arrow_height;
|
||||
const int horizontal_margin =
|
||||
std::min(nominal_horizontal_margin, std::max(0, (m_owner_rect.width() - 1) / 2));
|
||||
const int preferred_arrow_height =
|
||||
show_arrow == ShowArrow::Yes ? (1 + preferred_arrow_full_width) / 2 : 0;
|
||||
const int vertical_margin = horizontal_margin + preferred_arrow_height;
|
||||
|
||||
// Create enough space around the layout containing the title and message to draw the balloon and
|
||||
// both arrow tips (at most one of which will be visible)
|
||||
// Reserve space for the chevron only when one is requested.
|
||||
layout()->setContentsMargins(horizontal_margin, vertical_margin, horizontal_margin,
|
||||
vertical_margin);
|
||||
|
||||
QSize size_hint = sizeHint();
|
||||
size_hint.setWidth(std::min(size_hint.width(), m_owner_rect.width()));
|
||||
size_hint.setHeight(std::min(size_hint.height(), m_owner_rect.height()));
|
||||
|
||||
// Keep the balloon beside its target, choosing the side with more room if it must be clipped.
|
||||
const int space_above = std::max(0, target_widget_rect_global.top() - m_owner_rect.top());
|
||||
const int space_below =
|
||||
std::max(0, m_owner_rect.bottom() - target_widget_rect_global.bottom());
|
||||
const bool popup_above_widget =
|
||||
size_hint.height() <= space_above ||
|
||||
(size_hint.height() > space_below && space_above >= space_below);
|
||||
const int available_height = popup_above_widget ? space_above : space_below;
|
||||
size_hint.setHeight(std::min(size_hint.height(), std::max(1, available_height)));
|
||||
|
||||
// The content layout may prefer a larger size, but the visible tooltip is always bounded by its
|
||||
// owning window.
|
||||
setMaximumSize(m_owner_rect.size());
|
||||
resize(size_hint);
|
||||
|
||||
// Reduce the arrow with the available height/width so even unusually small windows have a
|
||||
// non-negative rounded-rectangle area.
|
||||
int arrow_full_width =
|
||||
show_arrow == ShowArrow::Yes ?
|
||||
std::min(preferred_arrow_full_width, size_hint.width() - border_full_width) :
|
||||
0;
|
||||
if (arrow_full_width > 0 && arrow_full_width % 2 == 0)
|
||||
--arrow_full_width;
|
||||
const int max_arrow_height = std::max(0, (size_hint.height() - border_full_width - 1) / 2);
|
||||
const int max_arrow_width = max_arrow_height > 0 ? 2 * max_arrow_height - 1 : 0;
|
||||
arrow_full_width = std::max(0, std::min(arrow_full_width, max_arrow_width));
|
||||
const float arrow_half_width = arrow_full_width / 2.0;
|
||||
// The y distance between the inner edge of the rectangle border and the inner tip of the arrow
|
||||
// border, and also the distance between the outer edge of the rectangle border and the outer tip
|
||||
// of the arrow border.
|
||||
const int arrow_height = (1 + arrow_full_width) / 2;
|
||||
|
||||
// These positions represent the middle of each edge of the BalloonTip's rounded rectangle
|
||||
const float rect_width = size_hint.width() - border_full_width;
|
||||
const float rect_height = size_hint.height() - border_full_width - 2 * arrow_height;
|
||||
const float rect_width = std::max(0, size_hint.width() - border_full_width);
|
||||
const float rect_height =
|
||||
std::max(0, size_hint.height() - border_full_width - 2 * arrow_height);
|
||||
const float rect_top = border_half_width + arrow_height;
|
||||
const float rect_bottom = rect_top + rect_height;
|
||||
const float rect_left = border_half_width;
|
||||
@@ -240,22 +292,29 @@ void BalloonTip::UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
// the left edge of the arrow interior; otherwise the distance between the right edges.
|
||||
const int arrow_nearest_edge_x_offset =
|
||||
std::min(adjusted_arrow_x_offset, centered_arrow_x_offset);
|
||||
const int arrow_tip_x_offset = arrow_nearest_edge_x_offset + arrow_half_width;
|
||||
|
||||
// The BalloonTip should be contained entirely within the screen that contains the target
|
||||
// position.
|
||||
QScreen* screen = QGuiApplication::screenAt(target_arrow_tip_position);
|
||||
if (screen == nullptr)
|
||||
{
|
||||
// If the target position isn't on any screen (which can happen if the window is partly off the
|
||||
// screen and the user hovers over the label) then use the screen containing the cursor instead.
|
||||
screen = QGuiApplication::screenAt(QCursor::pos());
|
||||
}
|
||||
const QRect screen_rect = screen->geometry();
|
||||
const int left_arrow_tip_x = static_cast<int>(arrow_nearest_edge_x_offset + arrow_half_width);
|
||||
const int right_arrow_tip_x =
|
||||
static_cast<int>(size_hint.width() - arrow_nearest_edge_x_offset - arrow_full_width +
|
||||
arrow_half_width);
|
||||
const int rightmost_valid_x =
|
||||
std::max(m_owner_rect.left(), m_owner_rect.right() - size_hint.width() + 1);
|
||||
const int left_arrow_window_x = std::clamp(target_arrow_tip_position.x() - left_arrow_tip_x,
|
||||
m_owner_rect.left(), rightmost_valid_x);
|
||||
const int right_arrow_window_x = std::clamp(target_arrow_tip_position.x() - right_arrow_tip_x,
|
||||
m_owner_rect.left(), rightmost_valid_x);
|
||||
const int left_arrow_error =
|
||||
std::abs(left_arrow_window_x + left_arrow_tip_x - target_arrow_tip_position.x());
|
||||
const int right_arrow_error =
|
||||
std::abs(right_arrow_window_x + right_arrow_tip_x - target_arrow_tip_position.x());
|
||||
const bool arrow_at_left = left_arrow_error <= right_arrow_error;
|
||||
const int actual_balloontip_global_x = arrow_at_left ? left_arrow_window_x : right_arrow_window_x;
|
||||
|
||||
QPainterPath rect_path;
|
||||
rect_path.addRoundedRect(rect_left, rect_top, rect_width, rect_height, corner_outer_radius,
|
||||
corner_outer_radius);
|
||||
if (rect_width > 0 && rect_height > 0)
|
||||
{
|
||||
rect_path.addRoundedRect(rect_left, rect_top, rect_width, rect_height, corner_outer_radius,
|
||||
corner_outer_radius);
|
||||
}
|
||||
|
||||
// The default pen cap style Qt::SquareCap extends drawn lines one half width before the starting
|
||||
// point and one half width after the ending point such that the starting and ending points are
|
||||
@@ -290,25 +349,18 @@ void BalloonTip::UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
mask_painter.setBrush(QBrush(Qt::color1));
|
||||
mask_painter.drawPath(rect_path);
|
||||
|
||||
const bool arrow_at_bottom =
|
||||
target_arrow_tip_position.y() - size_hint.height() + arrow_height >= 0;
|
||||
const bool arrow_at_left =
|
||||
target_arrow_tip_position.x() + size_hint.width() - arrow_tip_x_offset < screen_rect.width();
|
||||
|
||||
const float arrow_base_y =
|
||||
arrow_at_bottom ? rect_bottom - border_half_width : rect_top + border_half_width;
|
||||
popup_above_widget ? rect_bottom - border_half_width : rect_top + border_half_width;
|
||||
|
||||
const float arrow_tip_vertical_offset = arrow_at_bottom ? arrow_height : -arrow_height;
|
||||
const float arrow_tip_vertical_offset = popup_above_widget ? arrow_height : -arrow_height;
|
||||
const float arrow_tip_interior_y = arrow_base_y + arrow_tip_vertical_offset;
|
||||
const float arrow_tip_exterior_y =
|
||||
arrow_tip_interior_y + (arrow_at_bottom ? border_full_width : -border_full_width);
|
||||
const float arrow_base_left_edge_x =
|
||||
arrow_at_left ? arrow_nearest_edge_x_offset :
|
||||
size_hint.width() - arrow_nearest_edge_x_offset - arrow_full_width;
|
||||
const float arrow_base_right_edge_x = arrow_base_left_edge_x + arrow_full_width;
|
||||
const float arrow_tip_x = arrow_base_left_edge_x + arrow_half_width;
|
||||
|
||||
if (show_arrow == ShowArrow::Yes)
|
||||
if (show_arrow == ShowArrow::Yes && arrow_full_width > 0)
|
||||
{
|
||||
// Drawing diagonal lines in Qt is filled with edge cases and inexplicable behavior. Getting it
|
||||
// to do what you want at one border size is simple enough, but doing so flexibly is an exercise
|
||||
@@ -324,14 +376,14 @@ void BalloonTip::UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
|
||||
QPainterPath arrow_border_path;
|
||||
QPainterPath arrow_interior_fill_path;
|
||||
const float y_end_offset = arrow_at_bottom ? border_full_width : -border_full_width;
|
||||
const float y_end_offset = popup_above_widget ? border_full_width : -border_full_width;
|
||||
|
||||
// Draw the arrow border and interior lines from the outside inward. Each loop iteration draws
|
||||
// one pair of border lines and one pair of interior lines.
|
||||
for (int i = 1; i <= arrow_half_width; i++)
|
||||
{
|
||||
const float x_offset_from_arrow_base_edge = i - 0.5;
|
||||
const float border_y_start = arrow_base_y + (arrow_at_bottom ? i : -i);
|
||||
const float border_y_start = arrow_base_y + (popup_above_widget ? i : -i);
|
||||
const float border_y_end = border_y_start + y_end_offset;
|
||||
const float interior_y_start = arrow_base_y;
|
||||
const float interior_y_end = border_y_start;
|
||||
@@ -377,22 +429,15 @@ void BalloonTip::UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
|
||||
setMask(mask_bitmap);
|
||||
|
||||
// Place the arrow tip at the target position whether the arrow tip is drawn or not
|
||||
const int target_balloontip_global_x =
|
||||
target_arrow_tip_position.x() - static_cast<int>(arrow_tip_x);
|
||||
const int rightmost_valid_balloontip_global_x =
|
||||
screen_rect.left() + screen_rect.width() - size_hint.width();
|
||||
// If the balloon would extend off the screen, push it left or right until it's not
|
||||
const int actual_balloontip_global_x =
|
||||
std::max(screen_rect.left(),
|
||||
std::min(rightmost_valid_balloontip_global_x, target_balloontip_global_x));
|
||||
// The tip pixel should be in the middle of the control, and arrow_tip_exterior_y is at the bottom
|
||||
// of that pixel. When arrow_at_bottom is true the arrow is above arrow_tip_exterior_y and so the
|
||||
// tip pixel is in the right place, but when it's false the arrow is below arrow_tip_exterior_y
|
||||
// so the tip pixel would be the one below that. Make this adjustment to fix that.
|
||||
const int tip_pixel_adjustment = arrow_at_bottom ? 0 : 1;
|
||||
// Anchor the popup edge to the source widget edge selected for this side, so its border doesn't
|
||||
// cut through the widget.
|
||||
const int preferred_balloontip_global_y =
|
||||
popup_above_widget ? target_widget_rect_global.top() - size_hint.height() :
|
||||
target_widget_rect_global.bottom() + 1;
|
||||
const int lowest_valid_y =
|
||||
std::max(m_owner_rect.top(), m_owner_rect.bottom() - size_hint.height() + 1);
|
||||
const int actual_balloontip_global_y =
|
||||
target_arrow_tip_position.y() - arrow_tip_exterior_y - tip_pixel_adjustment;
|
||||
std::clamp(preferred_balloontip_global_y, m_owner_rect.top(), lowest_valid_y);
|
||||
|
||||
move(actual_balloontip_global_x, actual_balloontip_global_y);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <QColor>
|
||||
#include <QPixmap>
|
||||
#include <QRect>
|
||||
#include <QWidget>
|
||||
|
||||
class QEnterEvent;
|
||||
@@ -29,14 +30,15 @@ public:
|
||||
No
|
||||
};
|
||||
static void ShowBalloon(const QString& title, const QString& message,
|
||||
const QPoint& target_arrow_tip_position, QWidget* parent,
|
||||
const QPoint& target_arrow_tip_position,
|
||||
const QRect& target_widget_rect_global, QWidget* parent,
|
||||
ShowArrow show_arrow = ShowArrow::Yes, int border_width = 1);
|
||||
static void HideBalloon();
|
||||
static bool IsCursorInsideWidgetBoundingBox(const QWidget& widget);
|
||||
static bool IsCursorOnBalloonTip();
|
||||
static bool IsWidgetBalloonTipActive(const QWidget& widget);
|
||||
|
||||
BalloonTip(PrivateTag, const QString& title, QString message, QWidget* parent);
|
||||
BalloonTip(PrivateTag, const QString& title, QString message, QWidget* parent, int border_width);
|
||||
|
||||
protected:
|
||||
void enterEvent(QEnterEvent* event) override;
|
||||
@@ -45,9 +47,11 @@ protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
private:
|
||||
void UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position, ShowArrow show_arrow,
|
||||
void UpdateBoundsAndRedraw(const QPoint& target_arrow_tip_position,
|
||||
const QRect& target_widget_rect_global, ShowArrow show_arrow,
|
||||
int border_width);
|
||||
|
||||
QColor m_border_color;
|
||||
QPixmap m_pixmap;
|
||||
QRect m_owner_rect;
|
||||
};
|
||||
@@ -60,8 +60,11 @@ private:
|
||||
this->killTimer(*m_timer_id);
|
||||
m_timer_id.reset();
|
||||
|
||||
BalloonTip::ShowBalloon(m_title, m_description,
|
||||
this->parentWidget()->mapToGlobal(GetToolTipPosition()), this);
|
||||
const QPoint target_position = this->parentWidget()->mapToGlobal(GetToolTipPosition());
|
||||
const QRect target_widget_rect_global(this->mapToGlobal(this->rect().topLeft()),
|
||||
this->rect().size());
|
||||
BalloonTip::ShowBalloon(m_title, m_description, target_position, target_widget_rect_global,
|
||||
this, BalloonTip::ShowArrow::No);
|
||||
|
||||
Derived::timerEvent(event);
|
||||
}
|
||||
|
||||
@@ -323,8 +323,47 @@ void VRConfigWidget::CreateWidgets()
|
||||
|
||||
auto* openxr_group = new QGroupBox(tr("OpenXR"));
|
||||
auto* openxr_layout = new QGridLayout(openxr_group);
|
||||
openxr_layout->addWidget(make_bool(tr("Enable VR"), Config::GFX_VR_ENABLE_OPENXR), 0, 0, 1, 3);
|
||||
add_float(
|
||||
const auto get_game_or_base = [layer, this](const auto& setting) {
|
||||
if (layer->Exists(setting.GetLocation()))
|
||||
return layer->Get(setting);
|
||||
if (m_global_layer->Exists(setting.GetLocation()))
|
||||
return m_global_layer->Get(setting);
|
||||
return Config::GetBase(setting);
|
||||
};
|
||||
QString legacy_mode_name = tr("Use existing settings");
|
||||
if (!get_game_or_base(Config::GFX_VR_ENABLE_OPENXR))
|
||||
legacy_mode_name += tr(" (Vulkan flat display)");
|
||||
else if (get_game_or_base(Config::GFX_VR_FLAT_SCREEN))
|
||||
legacy_mode_name += tr(" (2D screen in VR)");
|
||||
else if (get_game_or_base(Config::GFX_VR_STEREO_SCREEN))
|
||||
legacy_mode_name += tr(" (stereo 3D screen)");
|
||||
else
|
||||
legacy_mode_name += tr(" (immersive VR)");
|
||||
|
||||
auto* presentation_mode = mark_default(new ConfigChoiceMap<OpenXRPresentationMode>(
|
||||
{{legacy_mode_name, OpenXRPresentationMode::Legacy},
|
||||
{tr("Flat Display (Vulkan)"), OpenXRPresentationMode::Vulkan},
|
||||
{tr("Immersive VR"), OpenXRPresentationMode::Immersive},
|
||||
{tr("Stereo 3D Screen"), OpenXRPresentationMode::StereoScreen}},
|
||||
Config::GFX_VR_PRESENTATION_MODE, layer, m_global_layer.get()));
|
||||
presentation_mode->setToolTip(
|
||||
tr("Selects standard Vulkan flat output, BaijiSteamVR immersive VR, or a stereoscopic 3D "
|
||||
"screen in the headset."));
|
||||
connect(presentation_mode, &QComboBox::currentIndexChanged, this, [layer] {
|
||||
const OpenXRPresentationMode mode = layer->Get(Config::GFX_VR_PRESENTATION_MODE);
|
||||
if (mode == OpenXRPresentationMode::Legacy)
|
||||
return;
|
||||
|
||||
layer->Set(Config::GFX_VR_ENABLE_OPENXR.GetLocation(),
|
||||
mode != OpenXRPresentationMode::Vulkan);
|
||||
layer->Set(Config::GFX_VR_FLAT_SCREEN.GetLocation(), false);
|
||||
layer->Set(Config::GFX_VR_STEREO_SCREEN.GetLocation(),
|
||||
mode == OpenXRPresentationMode::StereoScreen);
|
||||
Config::OnConfigChanged();
|
||||
});
|
||||
openxr_layout->addWidget(new QLabel(tr("Presentation Mode:")), 0, 0);
|
||||
openxr_layout->addWidget(presentation_mode, 0, 1, 1, 2);
|
||||
auto* units_per_meter = add_float(
|
||||
openxr_layout, 1, tr("Units per Meter:"), Config::GFX_VR_UNITS_PER_METER_MIN,
|
||||
Config::GFX_VR_UNITS_PER_METER_MAX, Config::GFX_VR_UNITS_PER_METER,
|
||||
Config::GFX_VR_UNITS_PER_METER_STEP,
|
||||
@@ -333,18 +372,35 @@ void VRConfigWidget::CreateWidgets()
|
||||
value);
|
||||
},
|
||||
ConfigFloatSlider::ScaleMode::Exponential);
|
||||
units_per_meter->setToolTip(
|
||||
tr("Default: 1.0. Sets game-world units per real meter. "
|
||||
"Higher values make the world smaller and "
|
||||
"increase effective stereo depth relative to game geometry; lower values make it "
|
||||
"larger and reduce depth. Use Stereo Separation to adjust depth without changing "
|
||||
"world scale."));
|
||||
auto* stereo_separation = add_float(
|
||||
openxr_layout, 2, tr("Stereo Separation (%):"),
|
||||
Config::GFX_VR_STEREO_SEPARATION_MIN, Config::GFX_VR_STEREO_SEPARATION_MAX,
|
||||
Config::GFX_VR_STEREO_SEPARATION, Config::GFX_VR_STEREO_SEPARATION_STEP,
|
||||
[](float value) { return QString::asprintf("%.0f%%", value); });
|
||||
stereo_separation->setToolTip(
|
||||
tr("Scales the virtual left/right eye offset while leaving world scale and head movement "
|
||||
"unchanged. 100% preserves the current OpenXR eye spacing; lower values reduce stereo "
|
||||
"depth and 0% approaches mono. Lower separation may make strong near-field pop-out "
|
||||
"easier to fuse and may ease eye strain, but comfort varies. Higher values increase "
|
||||
"depth and may increase strain. This affects Immersive VR; Stereo 3D Screen uses the "
|
||||
"Stereoscopic Depth setting instead."));
|
||||
|
||||
#ifndef BAIJI_STEAMVR
|
||||
auto* mirror_view = mark_default(new ConfigChoiceMap<OpenXRMirrorView>(
|
||||
{{tr("Both Eyes"), OpenXRMirrorView::BothEyes},
|
||||
{tr("Left Eye"), OpenXRMirrorView::LeftEye},
|
||||
{tr("Right Eye"), OpenXRMirrorView::RightEye},
|
||||
{tr("None"), OpenXRMirrorView::None}},
|
||||
Config::GFX_VR_MIRROR_VIEW, layer, m_global_layer.get()));
|
||||
openxr_layout->addWidget(new QLabel(tr("Desktop Mirror View:")), 2, 0);
|
||||
openxr_layout->addWidget(mirror_view, 2, 1, 1, 2);
|
||||
openxr_layout->addWidget(make_bool(tr("Flat Screen (2D, no stereo)"), Config::GFX_VR_FLAT_SCREEN),
|
||||
3, 0, 1, 3);
|
||||
|
||||
openxr_layout->addWidget(new QLabel(tr("Desktop Mirror View:")), 3, 0);
|
||||
openxr_layout->addWidget(mirror_view, 3, 1, 1, 2);
|
||||
#endif
|
||||
auto* camera_group = new QGroupBox(tr("Camera"));
|
||||
auto* camera_layout = new QGridLayout(camera_group);
|
||||
camera_layout->addWidget(
|
||||
@@ -383,10 +439,15 @@ void VRConfigWidget::CreateWidgets()
|
||||
virtual_screen_layout->addWidget(
|
||||
make_bool(tr("Auto-Exclude EFB Effects"), Config::GFX_VR_AUTO_NATIVE_EFB_EFFECTS), 2, 0, 1,
|
||||
3);
|
||||
add_float(virtual_screen_layout, 3, tr("Screen Distance (m):"),
|
||||
Config::GFX_VR_SCREEN_DISTANCE_MIN, Config::GFX_VR_SCREEN_DISTANCE_MAX,
|
||||
Config::GFX_VR_SCREEN_DISTANCE, Config::GFX_VR_SCREEN_DISTANCE_STEP,
|
||||
[](float value) { return QString::asprintf("%.1f", value); });
|
||||
auto* screen_distance = add_float(
|
||||
virtual_screen_layout, 3, tr("Screen Distance (m):"), Config::GFX_VR_SCREEN_DISTANCE_MIN,
|
||||
Config::GFX_VR_SCREEN_DISTANCE_MAX, Config::GFX_VR_SCREEN_DISTANCE,
|
||||
Config::GFX_VR_SCREEN_DISTANCE_STEP,
|
||||
[](float value) { return QString::asprintf("%.1f", value); });
|
||||
screen_distance->setToolTip(
|
||||
tr("Default: 2.0 m. Distance in meters to the virtual screen used for 2D content (menus, "
|
||||
"FMV, and HUD). The screen is fixed in space like a TV; it stays in place when you turn "
|
||||
"your head."));
|
||||
add_float(virtual_screen_layout, 4, tr("Screen Size (m):"), Config::GFX_VR_SCREEN_SIZE_MIN,
|
||||
Config::GFX_VR_SCREEN_SIZE_MAX, Config::GFX_VR_SCREEN_SIZE,
|
||||
Config::GFX_VR_SCREEN_SIZE_STEP,
|
||||
@@ -467,8 +528,17 @@ void VRConfigWidget::CreateWidgets()
|
||||
Config::GFX_VR_FORCED_VBI_FREQUENCY, layer, m_global_layer.get()));
|
||||
framerate_layout->addWidget(new QLabel(tr("Forced VBI Frequency:")), 0, 0);
|
||||
framerate_layout->addWidget(forced_vbi, 0, 1);
|
||||
auto* requested_refresh_rate = mark_default(new ConfigChoiceMap<int>(
|
||||
{{tr("Auto"), Config::GFX_VR_REQUESTED_REFRESH_RATE_AUTO},
|
||||
{tr("60 Hz"), Config::GFX_VR_REQUESTED_REFRESH_RATE_60},
|
||||
{tr("72 Hz"), Config::GFX_VR_REQUESTED_REFRESH_RATE_72},
|
||||
{tr("90 Hz"), Config::GFX_VR_REQUESTED_REFRESH_RATE_90},
|
||||
{tr("120 Hz"), Config::GFX_VR_REQUESTED_REFRESH_RATE_120}},
|
||||
Config::GFX_VR_REQUESTED_REFRESH_RATE, layer, m_global_layer.get()));
|
||||
framerate_layout->addWidget(new QLabel(tr("Requested Refresh Rate:")), 1, 0);
|
||||
framerate_layout->addWidget(requested_refresh_rate, 1, 1);
|
||||
framerate_layout->addWidget(
|
||||
make_bool(tr("Eager Frame Heartbeat"), Config::GFX_VR_EAGER_HEARTBEAT), 1, 0, 1, 2);
|
||||
make_bool(tr("Eager Frame Heartbeat"), Config::GFX_VR_EAGER_HEARTBEAT), 2, 0, 1, 2);
|
||||
|
||||
auto* shaders_group = new QGroupBox(tr("Shaders"));
|
||||
auto* shaders_layout = new QVBoxLayout(shaders_group);
|
||||
@@ -555,7 +625,7 @@ void VRConfigWidget::CreateWidgets()
|
||||
const QString help_message =
|
||||
tr("Italics mark default game settings and bold marks user settings. "
|
||||
"Right-click a control to remove its user setting.");
|
||||
auto* help_label = new QLabel(tr("These VR settings override core Dolphin settings."));
|
||||
auto* help_label = new QLabel(tr("These VR settings override core BaijiSteamVR settings."));
|
||||
auto* help_widget = QtUtils::CreateIconWarning(this, QStyle::SP_MessageBoxQuestion, help_label);
|
||||
help_widget->setToolTip(help_message);
|
||||
|
||||
|
||||
@@ -287,6 +287,15 @@ void WiimoteControllersWidget::CreateLayout()
|
||||
m_wiimote_layout->addWidget(wm_label, wm_row, 1);
|
||||
m_wiimote_layout->addWidget(wm_box, wm_row, 2);
|
||||
m_wiimote_layout->addWidget(wm_button, wm_row, 3);
|
||||
|
||||
// Baiju exposes the one controller set on the Frame; keep the other emulation slots in
|
||||
// configuration/core for upstream compatibility, but remove them from this fork's UI.
|
||||
if (i != 0)
|
||||
{
|
||||
wm_label->hide();
|
||||
wm_box->hide();
|
||||
wm_button->hide();
|
||||
}
|
||||
}
|
||||
|
||||
m_wiimote_layout->addWidget(m_wiimote_real_balance_board, m_wiimote_layout->rowCount(), 1, 1, -1);
|
||||
|
||||
@@ -73,13 +73,13 @@ ConvertDialog::ConvertDialog(QList<std::shared_ptr<const UICommon::GameFile>> fi
|
||||
auto* const info_text = new QLabel(
|
||||
tr("ISO: A simple and robust format which is supported by many programs. It takes up more "
|
||||
"space than any other format.\n\n"
|
||||
"GCZ: A basic compressed format which is compatible with most versions of Dolphin and "
|
||||
"GCZ: A basic compressed format which is compatible with most versions of BaijiSteamVR and "
|
||||
"some other programs. It can't efficiently compress junk data (unless removed) or "
|
||||
"encrypted Wii data.\n\n"
|
||||
"WIA: An advanced compressed format which is compatible with Dolphin 5.0-12188 and later, "
|
||||
"WIA: An advanced compressed format which is compatible with BaijiSteamVR 5.0-12188 and later, "
|
||||
"and a few other programs. It can efficiently compress encrypted Wii data, but not junk "
|
||||
"data (unless removed).\n\n"
|
||||
"RVZ: An advanced compressed format which is compatible with Dolphin 5.0-12188 and later. "
|
||||
"RVZ: An advanced compressed format which is compatible with BaijiSteamVR 5.0-12188 and later. "
|
||||
"It can efficiently compress both junk data and encrypted Wii data."));
|
||||
info_text->setWordWrap(true);
|
||||
info_text->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
@@ -162,7 +162,7 @@ void ConvertDialog::OnFormatChanged()
|
||||
if (!block_size_ok(DiscIO::GCZ_FALLBACK_BLOCK_SIZE))
|
||||
{
|
||||
ERROR_LOG_FMT(MASTER_LOG, "Failed to find a block size which does not cause problems "
|
||||
"when decompressing using an old version of Dolphin");
|
||||
"when decompressing using an old version of BaijiSteamVR");
|
||||
}
|
||||
AddToBlockSizeComboBox(DiscIO::GCZ_FALLBACK_BLOCK_SIZE);
|
||||
}
|
||||
@@ -311,8 +311,8 @@ void ConvertDialog::Convert()
|
||||
if (std::ranges::any_of(m_files, &UICommon::GameFile::IsNKit))
|
||||
{
|
||||
if (!ShowAreYouSureDialog(
|
||||
tr("Dolphin can't convert NKit files to non-NKit files. Converting an NKit file in "
|
||||
"Dolphin will result in another NKit file.\n"
|
||||
tr("BaijiSteamVR can't convert NKit files to non-NKit files. Converting an NKit file in "
|
||||
"BaijiSteamVR will result in another NKit file.\n"
|
||||
"\n"
|
||||
"If you want to convert an NKit file to a non-NKit file, you can use the same "
|
||||
"program as you originally used when converting the file to the NKit format.\n"
|
||||
@@ -511,7 +511,7 @@ void ConvertDialog::Convert()
|
||||
if (!success.get())
|
||||
{
|
||||
ModalMessageBox::critical(this, tr("Error"),
|
||||
tr("Dolphin failed to complete the requested action."));
|
||||
tr("BaijiSteamVR failed to complete the requested action."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -734,7 +734,7 @@ void BranchWatchDialog::OnHelp()
|
||||
"\n\n"
|
||||
"Press the \"Start Branch Watch\" button to activate Branch Watch. Branch Watch persists "
|
||||
"across emulation sessions, and a snapshot of your progress can be saved to and loaded "
|
||||
"from the User Directory to persist after Dolphin Emulator is closed. \"Save As...\" and "
|
||||
"from the User Directory to persist after BaijiSteamVR is closed. \"Save As...\" and "
|
||||
"\"Load From...\" actions are also available, and auto-saving can be enabled to save a "
|
||||
"snapshot at every step of a search. The \"Pause Branch Watch\" button will halt Branch "
|
||||
"Watch from tracking further branch hits until it is told to resume. Press the \"Clear "
|
||||
|
||||
Loaded 100 of 177 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user