mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
27 Commits
mach-excep
...
v2.7.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
976d4a8dbb | ||
|
|
40b1b9b717 | ||
|
|
a3b817cb1f | ||
|
|
83e152cd21 | ||
|
|
50a9568d65 | ||
|
|
a33cbdee09 | ||
|
|
b02bcc5690 | ||
|
|
2e60a1d081 | ||
|
|
28da984b01 | ||
|
|
967987b25f | ||
|
|
e41f63b821 | ||
|
|
0f82503cf7 | ||
|
|
33f625a4e2 | ||
|
|
5b0c22c343 | ||
|
|
ea963ffd72 | ||
|
|
bd9dcbe441 | ||
|
|
2a1f29c641 | ||
|
|
38883e8df4 | ||
|
|
f971040912 | ||
|
|
9aac7e8426 | ||
|
|
96284205a1 | ||
|
|
4a1d9d31d0 | ||
|
|
12d6087f2a | ||
|
|
251962c415 | ||
|
|
1bdd7d2352 | ||
|
|
7b98259ea1 | ||
|
|
ee8166d1fe |
15
.github/workflows/cron_publish_flatpak.yml
vendored
15
.github/workflows/cron_publish_flatpak.yml
vendored
@@ -4,6 +4,17 @@ on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
||||
workflow_dispatch: # As well as manually.
|
||||
inputs:
|
||||
stableBuild:
|
||||
description: 'Build stable version'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
publish:
|
||||
description: 'Publish to Flathub'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -52,8 +63,8 @@ jobs:
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
publish: ${{ inputs.publish || true }}
|
||||
fetchTags: true
|
||||
stableBuild: false
|
||||
stableBuild: ${{ inputs.stableBuild || false }}
|
||||
secrets: inherit
|
||||
|
||||
|
||||
14
.github/workflows/release_cut_new.yml
vendored
14
.github/workflows/release_cut_new.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
is_prelease:
|
||||
is_prerelease:
|
||||
description: 'Should be a pre-release?'
|
||||
required: true
|
||||
default: 'true'
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: ${{ github.event_name != 'workflow_dispatch' || inputs.is_prelease == 'true' }}
|
||||
prerelease: ${{ github.event_name != 'workflow_dispatch' || inputs.is_prerelease == 'true' }}
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prerelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
build_linux_flatpak:
|
||||
@@ -114,9 +114,9 @@ jobs:
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
publish: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prerelease == 'false' }} # prerelease builds are published by the cron job
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
stableBuild: ${{ inputs.is_prerelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prerelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
jobName: "MacOS Build"
|
||||
artifactPrefixName: "PCSX2-macos-Qt"
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prerelease == 'false' }}
|
||||
sign_and_notarize: true
|
||||
secrets: inherit
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ LIBPNG=1.6.53
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
MOLTENVK=1.4.1
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
@@ -88,7 +88,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
@@ -277,7 +277,7 @@ rm -fr "MoltenVK-${MOLTENVK}"
|
||||
tar xf "v$MOLTENVK.tar.gz"
|
||||
cd "MoltenVK-${MOLTENVK}"
|
||||
./fetchDependencies --macos
|
||||
make macos
|
||||
make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 MVK_CONFIG_USE_METAL_PRIVATE_API=1
|
||||
cp Package/Latest/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib "$INSTALLDIR/lib/"
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ LIBPNG=1.6.53
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
MOLTENVK=1.4.1
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
@@ -69,7 +69,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
@@ -225,7 +225,7 @@ cd "MoltenVK-${MOLTENVK}"
|
||||
sed -i '' 's/xcodebuild "$@"/xcodebuild $XCODEBUILD_EXTRA_ARGS "$@"/g' fetchDependencies
|
||||
sed -i '' 's/XCODEBUILD :=/XCODEBUILD ?=/g' Makefile
|
||||
XCODEBUILD_EXTRA_ARGS="VALID_ARCHS=x86_64" ./fetchDependencies --macos
|
||||
XCODEBUILD="set -o pipefail && xcodebuild VALID_ARCHS=x86_64" make macos
|
||||
XCODEBUILD="set -o pipefail && xcodebuild VALID_ARCHS=x86_64" make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 MVK_CONFIG_USE_METAL_PRIVATE_API=1
|
||||
cp Package/Latest/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib "$INSTALLDIR/lib/"
|
||||
cd ..
|
||||
|
||||
|
||||
@@ -201,10 +201,6 @@ echo Building Qt base...
|
||||
rmdir /S /Q "qtbase-everywhere-src-%QT%"
|
||||
%SEVENZIP% x "qtbase-everywhere-src-%QT%.zip" || goto error
|
||||
cd "qtbase-everywhere-src-%QT%" || goto error
|
||||
|
||||
rem Disable the PCRE2 JIT, it doesn't properly verify AVX2 support.
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-disable-pcre2-jit.patch" || goto error
|
||||
|
||||
cmake -B build -DFEATURE_sql=OFF -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% -DINPUT_gui=yes -DINPUT_widgets=yes -DINPUT_ssl=yes -DINPUT_openssl=no -DINPUT_schannel=yes -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON %QTBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
--- qtbase/src/3rdparty/pcre2/CMakeLists.txt 2024-03-19 08:46:43.000000000 -0700
|
||||
+++ qtbase/src/3rdparty/pcre2/CMakeLists.txt 2024-06-06 21:52:20.539619500 -0700
|
||||
@@ -41,6 +41,7 @@
|
||||
src/pcre2_xclass.c
|
||||
DEFINES
|
||||
HAVE_CONFIG_H
|
||||
+ PCRE2_DISABLE_JIT
|
||||
PUBLIC_DEFINES
|
||||
PCRE2_CODE_UNIT_WIDTH=16
|
||||
PUBLIC_INCLUDE_DIRECTORIES
|
||||
@@ -52,23 +53,8 @@
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION QNX OR UIKIT
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION (TEST_architecture_arch STREQUAL "arm") AND WIN32
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION (TEST_architecture_arch STREQUAL "arm64") AND WIN32
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
if (APPLE)
|
||||
- target_compile_options(BundledPcre2 PRIVATE "SHELL:-Xarch_arm64 -DPCRE2_DISABLE_JIT")
|
||||
+ target_compile_options(BundledPcre2 PRIVATE "SHELL:-Xarch_arm64")
|
||||
endif()
|
||||
|
||||
qt_internal_extend_target(BundledPcre2 CONDITION WIN32
|
||||
@@ -2239,6 +2239,8 @@ SCAJ-20152:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCAJ-20153:
|
||||
name: "コード・エイジ コマンダーズ"
|
||||
@@ -6229,6 +6231,8 @@ SCES-53688:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCES-53795:
|
||||
name: "SingStar - '80s"
|
||||
@@ -7698,6 +7702,8 @@ SCKA-20065:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCKA-20066:
|
||||
name: "아이토이 - 플레이 3"
|
||||
@@ -11384,6 +11390,10 @@ SCUS-97197:
|
||||
name: "War of the Monsters"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
memcardFilters: # Reads Twisted Metal Black for bonus unlockable.
|
||||
- "SCUS-97101"
|
||||
- "SCUS-97179"
|
||||
- "SCUS-97197"
|
||||
SCUS-97198:
|
||||
name: "Sly Cooper and the Thievius Raccoonus"
|
||||
region: "NTSC-U"
|
||||
@@ -20894,10 +20904,8 @@ SLES-52636:
|
||||
gameFixes:
|
||||
- FullVU0SyncHack # Fixes in-game timer.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 3 # Fixes missing lighting and car reflections.
|
||||
halfPixelOffset: 1 # Fixes 4 split lines in stage intros.
|
||||
autoFlush: 1 # Fixes incorrect colors.
|
||||
alignSprite: 1 # Fixes vertical lines such as in FMVs.
|
||||
minimumBlendingLevel: 3 # Fixes missing lighting and car reflections.
|
||||
halfPixelOffset: 4 # Fixes lines in game and FMVs.
|
||||
SLES-52637:
|
||||
name: "TOCA Race Driver 2"
|
||||
region: "PAL-M5"
|
||||
@@ -30585,6 +30593,11 @@ SLES-82030:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLES-82030"
|
||||
- "SLES-82031"
|
||||
- "SLES-50677"
|
||||
- "SLES-50822"
|
||||
SLES-82031:
|
||||
name: "Shadow Hearts - Covenant [Disc 2 of 2]"
|
||||
region: "PAL-M3"
|
||||
@@ -30592,8 +30605,11 @@ SLES-82031:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters:
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLES-82030"
|
||||
- "SLES-82031"
|
||||
- "SLES-50677"
|
||||
- "SLES-50822"
|
||||
SLES-82032:
|
||||
name: "Metal Gear Solid 3 - Snake Eater"
|
||||
region: "PAL-G"
|
||||
@@ -35942,6 +35958,8 @@ SLPM-60272:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLPM-60273:
|
||||
name: "絶体絶命都市2 -凍てついた記憶たち- [体験版 Type-B]"
|
||||
@@ -43475,6 +43493,11 @@ SLPM-65428:
|
||||
name-en: "BioHazard Outbreak"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
memcardFilters:
|
||||
- "SLPM-65428"
|
||||
- "SLPM-74201"
|
||||
- "SLPM-65286"
|
||||
- "BWNETCNF"
|
||||
SLPM-65429:
|
||||
name: "ギャラクシーエンジェル Moonlit Lovers [初回限定版ファーストパッケージ]"
|
||||
name-sort: "ぎゃらくしーえんじぇる Moonlit Lovers [しょかいげんていばんふぁーすとぱっけーじ]"
|
||||
@@ -44975,6 +44998,8 @@ SLPM-65692:
|
||||
- "SLPM-65692"
|
||||
- "SLPM-65428"
|
||||
- "SLPM-74201"
|
||||
- "SLPM-65286"
|
||||
- "BWNETCNF"
|
||||
SLPM-65693:
|
||||
name: "ときめきメモリアル3 ~約束のあの場所で~ [コナミ殿堂セレクション]"
|
||||
name-sort: "ときめきめもりある3 やくそくのあのばしょで [こなみでんどうせれくしょん]"
|
||||
@@ -53682,6 +53707,11 @@ SLPM-74201:
|
||||
name-sort: "ばいおはざーど あうとぶれいく [PlayStation2 the Best]"
|
||||
name-en: "BioHazard Outbreak [PlayStation2 the Best]"
|
||||
region: "NTSC-J"
|
||||
memcardFilters:
|
||||
- "SLPM-65428"
|
||||
- "SLPM-74201"
|
||||
- "SLPM-65286"
|
||||
- "BWNETCNF"
|
||||
SLPM-74202:
|
||||
name: "風雲 新撰組 [PlayStation2 the Best]"
|
||||
name-sort: "ふううん しんせんぐみ [PlayStation2 the Best]"
|
||||
@@ -58847,6 +58877,11 @@ SLPS-25317:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-25317"
|
||||
- "SLPS-25318"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-25318:
|
||||
name: "シャドウハーツⅡ [DXパック] [ディスク2/2]"
|
||||
name-sort: "しゃどうはーつ2 [DXぱっく] [でぃすく2/2]"
|
||||
@@ -58856,8 +58891,11 @@ SLPS-25318:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters:
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-25317"
|
||||
- "SLPS-25318"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-25319:
|
||||
name: "ケロケロキング スーパーDX"
|
||||
name-sort: "けろけろきんぐ すーぱーDX"
|
||||
@@ -58936,6 +58974,11 @@ SLPS-25334:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-25334"
|
||||
- "SLPS-25335"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-25335:
|
||||
name: "シャドウハーツⅡ [通常版] [ディスク2/2]"
|
||||
name-sort: "しゃどうはーつ2 [つうじょうばん] [でぃすく2/2]"
|
||||
@@ -58945,8 +58988,11 @@ SLPS-25335:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters:
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-25334"
|
||||
- "SLPS-25335"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-25336:
|
||||
name: "バスランディング3 [Sammy best] [つりコン2+ 同梱版]"
|
||||
name-sort: "ばすらんでぃんぐ3 [Sammy best] [つりこん2 どうこんばん]"
|
||||
@@ -60302,6 +60348,8 @@ SLPS-25557:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLPS-25558:
|
||||
name: "ネオジオ バトルコロシアム"
|
||||
@@ -63244,6 +63292,11 @@ SLPS-73214:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-73214"
|
||||
- "SLPS-73215"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-73215:
|
||||
name: "シャドウハーツⅡ ディレクターズカット [PlayStation2 the Best] [ディスク2/2]"
|
||||
name-sort: "しゃどうはーつ2 でぃれくたーずかっと [PlayStation2 the Best] [でぃすく2/2]"
|
||||
@@ -63253,8 +63306,11 @@ SLPS-73215:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters:
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLPS-73214"
|
||||
- "SLPS-73215"
|
||||
- "SLPS-25041"
|
||||
- "SLPS-73418"
|
||||
SLPS-73216:
|
||||
name: "マグナカルタ [PlayStation2 the Best]"
|
||||
name-sort: "まぐなかるた [PlayStation2 the Best]"
|
||||
@@ -69323,6 +69379,10 @@ SLUS-21041:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLUS-21041"
|
||||
- "SLUS-21044"
|
||||
- "SLUS-20347"
|
||||
SLUS-21042:
|
||||
name: "Darkwatch"
|
||||
region: "NTSC-U"
|
||||
@@ -69341,8 +69401,10 @@ SLUS-21044:
|
||||
halfPixelOffset: 5 # Fixes shadow positioning.
|
||||
autoFlush: 2 # Makes the shadow monsters appear.
|
||||
nativeScaling: 2 # Aligns post processing and bloom.
|
||||
memcardFilters:
|
||||
memcardFilters: # Reads Shadow Hearts for extra items.
|
||||
- "SLUS-21041"
|
||||
- "SLUS-21044"
|
||||
- "SLUS-20347"
|
||||
SLUS-21045:
|
||||
name: "Conflict - Vietnam"
|
||||
region: "NTSC-U"
|
||||
@@ -70308,6 +70370,8 @@ SLUS-21209:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLUS-21212:
|
||||
name: "Spartan - Total Warrior"
|
||||
|
||||
@@ -245,7 +245,8 @@
|
||||
03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
|
||||
030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000c21100000791000000000000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000c9110000f055000000000000,Be1 GC100XF Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
|
||||
@@ -109,14 +109,14 @@ disable_compiler_warnings_for_target(speex)
|
||||
# Find the Qt components that we need.
|
||||
if(ENABLE_QT_UI)
|
||||
find_package(Qt6 6.10.0 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
|
||||
endif()
|
||||
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.10.0)
|
||||
find_package(Qt6 COMPONENTS CorePrivate GuiPrivate WidgetsPrivate REQUIRED)
|
||||
endif()
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.10.0)
|
||||
find_package(Qt6 COMPONENTS CorePrivate GuiPrivate WidgetsPrivate REQUIRED)
|
||||
endif()
|
||||
|
||||
# The docking system for the debugger.
|
||||
# The docking system for the debugger.
|
||||
find_package(KDDockWidgets-qt6 2.3.0 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL)
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
void restoreGeometry(const QByteArray& geometry);
|
||||
|
||||
Q_SIGNALS:
|
||||
void windowResizedEvent(int width, int height, float scale);
|
||||
void windowResizedEvent(u32 width, u32 height, float scale);
|
||||
void windowRestoredEvent();
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent* event);
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include <QtCore/QLatin1StringView>
|
||||
#include <QtCore/QUtf8StringView>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QScrollBar>
|
||||
|
||||
@@ -46,6 +50,12 @@ void LogWindow::updateSettings()
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableLogWindow", false) && !Host::InNoGUIMode();
|
||||
const bool attach_to_main = Host::GetBaseBoolSettingValue("Logging", "AttachLogWindowToMainWindow", true);
|
||||
const bool curr_enabled = Log::IsHostOutputEnabled();
|
||||
const bool input_enabled = Host::GetBaseBoolSettingValue("Logging", "ShowEESIOInput");
|
||||
|
||||
if(g_log_window && g_log_window->m_line_input)
|
||||
{
|
||||
g_log_window->m_input_widget->setVisible(input_enabled);
|
||||
}
|
||||
|
||||
if (new_enabled == curr_enabled)
|
||||
{
|
||||
@@ -171,6 +181,10 @@ void LogWindow::createUi()
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableTimestamps", true);
|
||||
|
||||
action = settings_menu->addAction(tr("Show EE SIO &Input"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "ShowEESIOInput", false);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
|
||||
// TODO: Log Level
|
||||
@@ -181,6 +195,30 @@ void LogWindow::createUi()
|
||||
m_text->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
m_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_text->setWordWrapMode(QTextOption::WrapAnywhere);
|
||||
m_text->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
m_line_input = new QLineEdit(this);
|
||||
connect(m_line_input, &QLineEdit::returnPressed, this, &LogWindow::onInputEntered);
|
||||
|
||||
m_local_echo_checkbox = new QCheckBox(tr("Local Echo"), this);
|
||||
m_local_echo_checkbox->setChecked(m_local_echo);
|
||||
connect(m_local_echo_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
|
||||
{
|
||||
m_local_echo = state == Qt::CheckState::Checked;
|
||||
});
|
||||
|
||||
m_newline_on_enter_checkbox = new QCheckBox(tr("Newline on send"), this);
|
||||
m_newline_on_enter_checkbox->setChecked(m_newline_on_enter);
|
||||
connect(m_newline_on_enter_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
|
||||
{
|
||||
m_newline_on_enter = state == Qt::CheckState::Checked;
|
||||
});
|
||||
|
||||
m_input_hbox = new QHBoxLayout(this);
|
||||
m_input_hbox->addWidget(m_line_input, 1);
|
||||
m_input_hbox->addWidget(m_local_echo_checkbox);
|
||||
m_input_hbox->addWidget(m_newline_on_enter_checkbox);
|
||||
m_input_hbox->setSpacing(8);
|
||||
|
||||
#if defined(_WIN32)
|
||||
QFont font("Consolas");
|
||||
@@ -194,7 +232,19 @@ void LogWindow::createUi()
|
||||
#endif
|
||||
m_text->setFont(font);
|
||||
|
||||
setCentralWidget(m_text);
|
||||
QWidget* central_widget = new QWidget(this);
|
||||
m_input_widget = new QWidget(this);
|
||||
m_input_widget->setVisible(Host::GetBaseBoolSettingValue("Logging", "ShowEESIOInput"));
|
||||
m_input_widget->setLayout(m_input_hbox);
|
||||
|
||||
QVBoxLayout* vlayout = new QVBoxLayout(central_widget);
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
vlayout->setSpacing(0);
|
||||
vlayout->addWidget(m_text);
|
||||
vlayout->addWidget(m_input_widget);
|
||||
|
||||
central_widget->setLayout(vlayout);
|
||||
setCentralWidget(central_widget);
|
||||
}
|
||||
|
||||
void LogWindow::onClearTriggered()
|
||||
@@ -361,6 +411,31 @@ void LogWindow::appendMessage(quint32 level, quint32 color, const QString& messa
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::onInputEntered()
|
||||
{
|
||||
QString text = m_line_input->text();
|
||||
if (text.isEmpty() && !m_newline_on_enter)
|
||||
return;
|
||||
|
||||
if(m_newline_on_enter)
|
||||
text.append('\n');
|
||||
|
||||
std::string str = text.toUtf8().toStdString();
|
||||
|
||||
if(VMManager::WriteBytesToEESIORXFIFO({reinterpret_cast<const u8*>(str.data()), str.size()}))
|
||||
{
|
||||
m_line_input->clear();
|
||||
|
||||
if(m_local_echo)
|
||||
// appendMessage expects a newline to be at the end of the string
|
||||
appendMessage(0, 0, m_newline_on_enter ? text : (text + '\n') );
|
||||
|
||||
QTextCursor cursor(m_text->textCursor());
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
m_text->setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::saveSize()
|
||||
{
|
||||
const int current_width = Host::GetBaseIntSettingValue("UI", "LogWindowWidth", DEFAULT_WIDTH);
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#include "common/Console.h"
|
||||
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QPlainTextEdit>
|
||||
|
||||
@@ -36,6 +39,7 @@ private Q_SLOTS:
|
||||
void onClearTriggered();
|
||||
void onSaveTriggered();
|
||||
void appendMessage(quint32 level, quint32 color, const QString& message);
|
||||
void onInputEntered();
|
||||
|
||||
private:
|
||||
static constexpr int DEFAULT_WIDTH = 750;
|
||||
@@ -45,8 +49,15 @@ private:
|
||||
void restoreSize();
|
||||
|
||||
QPlainTextEdit* m_text;
|
||||
QLineEdit* m_line_input;
|
||||
QMenu* m_level_menu;
|
||||
QWidget* m_input_widget;
|
||||
QHBoxLayout* m_input_hbox;
|
||||
QCheckBox* m_local_echo_checkbox;
|
||||
QCheckBox* m_newline_on_enter_checkbox;
|
||||
|
||||
bool m_local_echo = false;
|
||||
bool m_newline_on_enter = true;
|
||||
bool m_attached_to_main_window = true;
|
||||
bool m_destroying = false;
|
||||
};
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace QtHost
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static QTimer* s_settings_save_timer = nullptr;
|
||||
static std::unique_ptr<INISettingsInterface> s_base_settings_interface;
|
||||
static std::unique_ptr<INISettingsInterface> s_secrets_settings_interface;
|
||||
static bool s_batch_mode = false;
|
||||
static bool s_nogui_mode = false;
|
||||
static bool s_start_big_picture_mode = false;
|
||||
@@ -776,7 +777,7 @@ void EmuThread::connectDisplaySignals(DisplaySurface* widget)
|
||||
connect(widget, &DisplaySurface::windowRestoredEvent, this, &EmuThread::redrawDisplayWindow);
|
||||
}
|
||||
|
||||
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
|
||||
void EmuThread::onDisplayWindowResized(u32 width, u32 height, float scale)
|
||||
{
|
||||
if (!MTGS::IsOpen())
|
||||
return;
|
||||
@@ -1307,6 +1308,7 @@ bool QtHost::InitializeConfig()
|
||||
// Write crash dumps to the data directory, since that'll be accessible for certain.
|
||||
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
|
||||
|
||||
// Load main settings ini
|
||||
const std::string path = Path::Combine(EmuFolders::Settings, "PCSX2.ini");
|
||||
const bool settings_exists = FileSystem::FileExists(path.c_str());
|
||||
Console.WriteLnFmt("Loading config from {}.", path);
|
||||
@@ -1347,6 +1349,29 @@ bool QtHost::InitializeConfig()
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
// Layer secrets ini on top
|
||||
const std::string secrets_path = Path::Combine(EmuFolders::Settings, "secrets.ini");
|
||||
const bool secrets_settings_exists = FileSystem::FileExists(secrets_path.c_str());
|
||||
Console.WriteLnFmt("Loading secrets from {}.", secrets_path);
|
||||
|
||||
s_secrets_settings_interface = std::make_unique<INISettingsInterface>(std::move(secrets_path));
|
||||
Host::Internal::SetSecretsSettingsLayer(s_secrets_settings_interface.get());
|
||||
if (!secrets_settings_exists || !s_secrets_settings_interface->Load())
|
||||
{
|
||||
if (!s_base_settings_interface->Save(&error))
|
||||
{
|
||||
QMessageBox::critical(
|
||||
nullptr, QStringLiteral("PCSX2"),
|
||||
QStringLiteral(
|
||||
"Failed to save secrets to\n\n%1\n\nThe error was: %2\n\nPlease ensure this directory is writable. You "
|
||||
"can also try portable mode by creating portable.txt in the same directory you installed PCSX2 into.")
|
||||
.arg(QString::fromStdString(s_secrets_settings_interface->GetFileName()))
|
||||
.arg(QString::fromStdString(error.GetDescription())));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Setup wizard was incomplete last time?
|
||||
s_run_setup_wizard =
|
||||
s_run_setup_wizard || s_base_settings_interface->GetBoolValue("UI", "SetupWizardIncomplete", false);
|
||||
|
||||
@@ -191,7 +191,7 @@ private:
|
||||
private Q_SLOTS:
|
||||
void stopInThread();
|
||||
void doBackgroundControllerPoll();
|
||||
void onDisplayWindowResized(int width, int height, float scale);
|
||||
void onDisplayWindowResized(u32 width, u32 height, float scale);
|
||||
void onApplicationStateChanged(Qt::ApplicationState state);
|
||||
void redrawDisplayWindow();
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ namespace SettingWidgetBinder
|
||||
{
|
||||
if (!isNullable(widget))
|
||||
{
|
||||
widget->connect(widget, QOverload<int>::of(&QSpinBox::valueChanged), func);
|
||||
widget->connect(widget, &QSpinBox::valueChanged, func);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -591,7 +591,7 @@ namespace SettingWidgetBinder
|
||||
{
|
||||
if (!isNullable(widget))
|
||||
{
|
||||
widget->connect(widget, QOverload<double>::of(&QDoubleSpinBox::valueChanged), func);
|
||||
widget->connect(widget, &QDoubleSpinBox::valueChanged, func);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -608,7 +608,7 @@ namespace SettingWidgetBinder
|
||||
});
|
||||
menu.exec(widget->mapToGlobal(pt));
|
||||
});
|
||||
widget->connect(widget, QOverload<double>::of(&QDoubleSpinBox::valueChanged), widget, [widget, func = std::move(func)]() {
|
||||
widget->connect(widget, &QDoubleSpinBox::valueChanged, widget, [widget, func = std::move(func)]() {
|
||||
if (widget->property(IS_NULL_PROPERTY).toBool())
|
||||
{
|
||||
widget->setProperty(IS_NULL_PROPERTY, QVariant(false));
|
||||
|
||||
@@ -42,9 +42,9 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* settings_dialog,
|
||||
m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(-1));
|
||||
m_ui.vu0ClampMode->setCurrentIndex(getClampingModeIndex(0));
|
||||
m_ui.vu1ClampMode->setCurrentIndex(getClampingModeIndex(1));
|
||||
connect(m_ui.eeClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(-1, index); });
|
||||
connect(m_ui.vu0ClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(0, index); });
|
||||
connect(m_ui.vu1ClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(1, index); });
|
||||
connect(m_ui.eeClampMode, &QComboBox::currentIndexChanged, [this](int index) { setClampingMode(-1, index); });
|
||||
connect(m_ui.vu0ClampMode, &QComboBox::currentIndexChanged, [this](int index) { setClampingMode(0, index); });
|
||||
connect(m_ui.vu1ClampMode, &QComboBox::currentIndexChanged, [this](int index) { setClampingMode(1, index); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true);
|
||||
|
||||
@@ -60,7 +60,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.savestateCompressionLevel, "EmuCore", "SavestateCompressionRatio", static_cast<int>(SavestateCompressionLevel::Medium));
|
||||
|
||||
connect(m_ui.savestateCompressionMethod, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
connect(m_ui.savestateCompressionMethod, &QComboBox::currentIndexChanged, this,
|
||||
&AdvancedSettingsWidget::onSavestateCompressionTypeChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.backupSaveStates, "EmuCore", "BackupSavestate", true);
|
||||
|
||||
@@ -49,7 +49,7 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(m_dialog->getProfileSettingsInterface(),
|
||||
m_ui.controllerType, m_config_section, "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(port))->name);
|
||||
|
||||
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged);
|
||||
connect(m_ui.controllerType, &QComboBox::currentIndexChanged, this, &ControllerBindingWidget::onTypeChanged);
|
||||
connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked);
|
||||
connect(m_ui.settings, &QPushButton::clicked, this, &ControllerBindingWidget::onSettingsClicked);
|
||||
connect(m_ui.macros, &QPushButton::clicked, this, &ControllerBindingWidget::onMacrosClicked);
|
||||
@@ -202,7 +202,11 @@ void ControllerBindingWidget::onAutomaticBindingClicked()
|
||||
for (const QPair<QString, QString>& dev : m_dialog->getDeviceList())
|
||||
{
|
||||
// we set it as data, because the device list could get invalidated while the menu is up
|
||||
QAction* action = menu.addAction(QStringLiteral("%1 (%2)").arg(dev.first).arg(dev.second));
|
||||
QAction* action;
|
||||
if(dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
|
||||
action = menu.addAction(dev.first);
|
||||
else
|
||||
action = menu.addAction(QStringLiteral("%1: %2").arg(dev.first).arg(dev.second));
|
||||
action->setData(dev.first);
|
||||
connect(action, &QAction::triggered, this, [this, action]() { doDeviceAutomaticBinding(action->data().toString()); });
|
||||
added = true;
|
||||
@@ -998,8 +1002,8 @@ USBDeviceWidget::USBDeviceWidget(QWidget* parent, ControllerSettingsWindow* dial
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
|
||||
m_dialog->getProfileSettingsInterface(), m_ui.deviceType, m_config_section, "Type", "None");
|
||||
|
||||
connect(m_ui.deviceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &USBDeviceWidget::onTypeChanged);
|
||||
connect(m_ui.deviceSubtype, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &USBDeviceWidget::onSubTypeChanged);
|
||||
connect(m_ui.deviceType, &QComboBox::currentIndexChanged, this, &USBDeviceWidget::onTypeChanged);
|
||||
connect(m_ui.deviceSubtype, &QComboBox::currentIndexChanged, this, &USBDeviceWidget::onSubTypeChanged);
|
||||
connect(m_ui.bindings, &QPushButton::clicked, this, &USBDeviceWidget::onBindingsClicked);
|
||||
connect(m_ui.settings, &QPushButton::clicked, this, &USBDeviceWidget::onSettingsClicked);
|
||||
connect(m_ui.automaticBinding, &QPushButton::clicked, this, &USBDeviceWidget::onAutomaticBindingClicked);
|
||||
@@ -1152,7 +1156,11 @@ void USBDeviceWidget::onAutomaticBindingClicked()
|
||||
for (const QPair<QString, QString>& dev : m_dialog->getDeviceList())
|
||||
{
|
||||
// we set it as data, because the device list could get invalidated while the menu is up
|
||||
QAction* action = menu.addAction(QStringLiteral("%1 (%2)").arg(dev.first).arg(dev.second));
|
||||
QAction* action;
|
||||
if(dev.first.compare(dev.second, Qt::CaseInsensitive) == 0)
|
||||
action = menu.addAction(dev.first);
|
||||
else
|
||||
action = menu.addAction(QStringLiteral("%1: %2").arg(dev.first).arg(dev.second));
|
||||
action->setData(dev.first);
|
||||
connect(action, &QAction::triggered, this, [this, action]() { doDeviceAutomaticBinding(action->data().toString()); });
|
||||
added = true;
|
||||
|
||||
@@ -88,7 +88,11 @@ ControllerGlobalSettingsWidget::~ControllerGlobalSettingsWidget() = default;
|
||||
void ControllerGlobalSettingsWidget::addDeviceToList(const QString& identifier, const QString& name)
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(QStringLiteral("%1: %2").arg(identifier).arg(name));
|
||||
if(identifier.compare(name,Qt::CaseInsensitive) == 0)
|
||||
item->setText(identifier);
|
||||
else
|
||||
item->setText(QStringLiteral("%1: %2").arg(identifier).arg(name));
|
||||
|
||||
item->setData(Qt::UserRole, identifier);
|
||||
m_ui.deviceList->addItem(item);
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsWindow* settings_dialog, QWidget*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Eth Device Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
connect(m_ui.ethDevType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DEV9SettingsWidget::onEthDeviceTypeChanged);
|
||||
connect(m_ui.ethDev, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DEV9SettingsWidget::onEthDeviceChanged);
|
||||
connect(m_ui.ethDevType, &QComboBox::currentIndexChanged, this, &DEV9SettingsWidget::onEthDeviceTypeChanged);
|
||||
connect(m_ui.ethDev, &QComboBox::currentIndexChanged, this, &DEV9SettingsWidget::onEthDeviceChanged);
|
||||
//Comboboxes populated in show event
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -125,12 +125,12 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsWindow* settings_dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.ethDNS1Mode, "DEV9/Eth", "ModeDNS1",
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)], "DEV9SettingsWidget");
|
||||
onEthDNSModeChanged(m_ui.ethDNS1Mode, m_ui.ethDNS1Mode->currentIndex(), m_ui.ethDNS1Addr, "DEV9/Eth", "ModeDNS1");
|
||||
connect(m_ui.ethDNS1Mode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS1Mode, index, m_ui.ethDNS1Addr, "DEV9/Eth", "ModeDNS1"); });
|
||||
connect(m_ui.ethDNS1Mode, &QComboBox::currentIndexChanged, this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS1Mode, index, m_ui.ethDNS1Addr, "DEV9/Eth", "ModeDNS1"); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.ethDNS2Mode, "DEV9/Eth", "ModeDNS2",
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)], "DEV9SettingsWidget");
|
||||
onEthDNSModeChanged(m_ui.ethDNS2Mode, m_ui.ethDNS2Mode->currentIndex(), m_ui.ethDNS2Addr, "DEV9/Eth", "ModeDNS2");
|
||||
connect(m_ui.ethDNS2Mode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS2Mode, index, m_ui.ethDNS2Addr, "DEV9/Eth", "ModeDNS2"); });
|
||||
connect(m_ui.ethDNS2Mode, &QComboBox::currentIndexChanged, this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS2Mode, index, m_ui.ethDNS2Addr, "DEV9/Eth", "ModeDNS2"); });
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DNS Settings
|
||||
@@ -144,7 +144,7 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsWindow* settings_dialog, QWidget*
|
||||
headers.push_back(tr("Enabled"));
|
||||
m_ethHost_model->setHorizontalHeaderLabels(headers);
|
||||
|
||||
connect(m_ethHost_model, QOverload<QStandardItem*>::of(&QStandardItemModel::itemChanged), this, &DEV9SettingsWidget::onEthHostEdit);
|
||||
connect(m_ethHost_model, &QStandardItemModel::itemChanged, this, &DEV9SettingsWidget::onEthHostEdit);
|
||||
|
||||
m_ethHosts_proxy = new QSortFilterProxyModel(m_ui.ethHosts);
|
||||
m_ethHosts_proxy->setSourceModel(m_ethHost_model);
|
||||
@@ -186,7 +186,7 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsWindow* settings_dialog, QWidget*
|
||||
connect(m_ui.hddFile, &QLineEdit::editingFinished, this, &DEV9SettingsWidget::onHddFileEdit);
|
||||
connect(m_ui.hddBrowseFile, &QPushButton::clicked, this, &DEV9SettingsWidget::onHddBrowseFileClicked);
|
||||
|
||||
connect(m_ui.hddSizeSlider, QOverload<int>::of(&QSlider::valueChanged), this, &DEV9SettingsWidget::onHddSizeSlide);
|
||||
connect(m_ui.hddSizeSlider, &QSlider::valueChanged, this, &DEV9SettingsWidget::onHddSizeSlide);
|
||||
SettingWidgetBinder::SettingAccessor<QSpinBox>::connectValueChanged(m_ui.hddSizeSpinBox, [&]() { onHddSizeAccessorSpin(); });
|
||||
|
||||
connect(m_ui.hddCreate, &QPushButton::clicked, this, &DEV9SettingsWidget::onHddCreateClicked);
|
||||
|
||||
@@ -94,7 +94,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
||||
const std::optional<int> cycle_rate =
|
||||
dialog()->getIntValue("EmuCore/Speedhacks", "EECycleRate", sif ? std::nullopt : std::optional<int>(DEFAULT_EE_CYCLE_RATE));
|
||||
m_ui.eeCycleRate->setCurrentIndex(cycle_rate.has_value() ? (std::clamp(cycle_rate.value(), MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) + (0 - MINIMUM_EE_CYCLE_RATE) + static_cast<int>(dialog()->isPerGameSettings())) : 0);
|
||||
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int index) {
|
||||
connect(m_ui.eeCycleRate, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||
std::optional<int> value;
|
||||
if (!dialog()->isPerGameSettings() || index > 0)
|
||||
value = MINIMUM_EE_CYCLE_RATE + index - static_cast<int>(dialog()->isPerGameSettings());
|
||||
@@ -218,7 +218,7 @@ void EmulationSettingsWidget::initializeSpeedCombo(QComboBox* cb, const char* se
|
||||
cb->setCurrentIndex(custom_index);
|
||||
}
|
||||
|
||||
connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
connect(cb, &QComboBox::currentIndexChanged, this,
|
||||
[this, cb, section, key](int index) { handleSpeedComboChange(cb, section, key); });
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_display.cropBottom, "EmuCore/GS", "CropBottom", 0);
|
||||
|
||||
connect(
|
||||
m_display.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
m_display.fullscreenModes, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Settings
|
||||
@@ -114,9 +114,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
|
||||
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
connect(m_hw.upscaleMultiplier, &QComboBox::currentIndexChanged, this,
|
||||
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);
|
||||
connect(m_hw.trilinearFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
connect(m_hw.trilinearFiltering, &QComboBox::currentIndexChanged, this,
|
||||
&GraphicsSettingsWidget::onTrilinearFilteringChanged);
|
||||
onTrilinearFilteringChanged();
|
||||
|
||||
@@ -150,7 +150,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.readTCOnClose, "EmuCore/GS", "UserHacks_ReadTCOnClose", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.estimateTextureRegion, "EmuCore/GS", "UserHacks_EstimateTextureRegion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
|
||||
connect(m_fixes.cpuSpriteRenderBW, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
connect(m_fixes.cpuSpriteRenderBW, &QComboBox::currentIndexChanged, this,
|
||||
&GraphicsSettingsWidget::onCPUSpriteRenderBWChanged);
|
||||
connect(m_fixes.gpuPaletteConversion, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::onGpuPaletteConversionChanged);
|
||||
onCPUSpriteRenderBWChanged();
|
||||
@@ -295,8 +295,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
m_header.rendererDropdown->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
connect(m_header.rendererDropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onRendererChanged);
|
||||
connect(m_header.adapterDropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onAdapterChanged);
|
||||
connect(m_header.rendererDropdown, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onRendererChanged);
|
||||
connect(m_header.adapterDropdown, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onAdapterChanged);
|
||||
connect(m_hw.enableHWFixes, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updateRendererDependentOptions);
|
||||
connect(m_advanced.extendedUpscales, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updateRendererDependentOptions);
|
||||
connect(m_hw.textureFiltering, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onTextureFilteringChange);
|
||||
|
||||
@@ -133,18 +133,18 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
|
||||
QtHost::GetDefaultThemeName(), "InterfaceSettingsWidget");
|
||||
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); });
|
||||
connect(m_ui.theme, &QComboBox::currentIndexChanged, [this]() { emit themeChanged(); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.backgroundOpacity, "UI", "GameListBackgroundOpacity", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.backgroundScale, "UI", "GameListBackgroundMode", BACKGROUND_SCALE_NAMES, QtUtils::ScalingMode::Fit);
|
||||
connect(m_ui.backgroundBrowse, &QPushButton::clicked, [this]() { onSetGameListBackgroundTriggered(); });
|
||||
connect(m_ui.backgroundReset, &QPushButton::clicked, [this]() { onClearGameListBackgroundTriggered(); });
|
||||
connect(m_ui.backgroundOpacity, &QSpinBox::editingFinished, [this]() { emit backgroundChanged(); });
|
||||
connect(m_ui.backgroundScale, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit backgroundChanged(); });
|
||||
connect(m_ui.backgroundScale, &QComboBox::currentIndexChanged, [this]() { emit backgroundChanged(); });
|
||||
|
||||
populateLanguages();
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.language, "UI", "Language", QtHost::GetDefaultLanguage());
|
||||
connect(m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit languageChanged(); });
|
||||
connect(m_ui.language, &QComboBox::currentIndexChanged, [this]() { emit languageChanged(); });
|
||||
|
||||
// Per-game settings is special, we don't want to bind it if we're editing per-game settings.
|
||||
if (!dialog()->isPerGameSettings())
|
||||
|
||||
@@ -176,7 +176,7 @@ void SetupWizardDialog::setupLanguagePage()
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.theme, "UI", "Theme",
|
||||
InterfaceSettingsWidget::THEME_NAMES, InterfaceSettingsWidget::THEME_VALUES, QtHost::GetDefaultThemeName(), "InterfaceSettingsWidget");
|
||||
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SetupWizardDialog::themeChanged);
|
||||
connect(m_ui.theme, &QComboBox::currentIndexChanged, this, &SetupWizardDialog::themeChanged);
|
||||
|
||||
for (const std::pair<QString, QString>& it : QtHost::GetAvailableLanguageList())
|
||||
{
|
||||
@@ -189,7 +189,7 @@ void SetupWizardDialog::setupLanguagePage()
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(
|
||||
nullptr, m_ui.language, "UI", "Language", QtHost::GetDefaultLanguage());
|
||||
connect(
|
||||
m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SetupWizardDialog::languageChanged);
|
||||
m_ui.language, &QComboBox::currentIndexChanged, this, &SetupWizardDialog::languageChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
nullptr, m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
|
||||
|
||||
@@ -437,26 +437,26 @@ void QtHost::SetStyleFromSettings()
|
||||
// Alternative dark theme.
|
||||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
const QColor gray(150, 150, 150);
|
||||
const QColor royalBlue(29, 41, 81);
|
||||
const QColor darkishBlue(17, 30, 108);
|
||||
const QColor abyssBlue(39, 58, 114);
|
||||
const QColor darkishBlue(29, 41, 81);
|
||||
const QColor lighterBlue(25, 32, 130);
|
||||
const QColor highlight(36, 93, 218);
|
||||
const QColor link(0, 202, 255);
|
||||
const QColor blue(198, 238, 255);
|
||||
const QColor gray(150, 150, 150);
|
||||
|
||||
QPalette cobaltSkyPalette;
|
||||
cobaltSkyPalette.setColor(QPalette::Window, royalBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::Window, abyssBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
cobaltSkyPalette.setColor(QPalette::Base, royalBlue.lighter());
|
||||
cobaltSkyPalette.setColor(QPalette::AlternateBase, darkishBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::Base, darkishBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::AlternateBase, darkishBlue.darker());
|
||||
cobaltSkyPalette.setColor(QPalette::ToolTipBase, darkishBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
cobaltSkyPalette.setColor(QPalette::Text, Qt::white);
|
||||
cobaltSkyPalette.setColor(QPalette::Button, lighterBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
cobaltSkyPalette.setColor(QPalette::Link, link);
|
||||
cobaltSkyPalette.setColor(QPalette::Highlight, highlight);
|
||||
cobaltSkyPalette.setColor(QPalette::Link, blue);
|
||||
cobaltSkyPalette.setColor(QPalette::Highlight, abyssBlue.lighter());
|
||||
cobaltSkyPalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
cobaltSkyPalette.setColor(QPalette::PlaceholderText, gray);
|
||||
|
||||
cobaltSkyPalette.setColor(QPalette::Active, QPalette::Button, lighterBlue);
|
||||
cobaltSkyPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
|
||||
@@ -475,9 +475,9 @@ void QtHost::SetStyleFromSettings()
|
||||
// OLED screens.
|
||||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
const QColor black(0, 0, 0);
|
||||
const QColor gray(25, 25, 25);
|
||||
const QColor lighterGray(75, 75, 75);
|
||||
const QColor black(5, 5, 5);
|
||||
const QColor gray(22, 22, 29);
|
||||
const QColor lighterGray(65, 79, 98);
|
||||
const QColor blue(198, 238, 255);
|
||||
|
||||
QPalette AMOLEDPalette;
|
||||
@@ -519,7 +519,7 @@ void QtHost::SetStyleFromSettings()
|
||||
rubyPalette.setColor(QPalette::Window, slate);
|
||||
rubyPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
rubyPalette.setColor(QPalette::Base, slate.lighter());
|
||||
rubyPalette.setColor(QPalette::AlternateBase, slate.lighter());
|
||||
rubyPalette.setColor(QPalette::AlternateBase, slate.darker());
|
||||
rubyPalette.setColor(QPalette::ToolTipBase, slate);
|
||||
rubyPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
rubyPalette.setColor(QPalette::Text, Qt::white);
|
||||
@@ -553,7 +553,7 @@ void QtHost::SetStyleFromSettings()
|
||||
sapphirePalette.setColor(QPalette::Window, slate);
|
||||
sapphirePalette.setColor(QPalette::WindowText, Qt::white);
|
||||
sapphirePalette.setColor(QPalette::Base, slate.lighter());
|
||||
sapphirePalette.setColor(QPalette::AlternateBase, slate.lighter());
|
||||
sapphirePalette.setColor(QPalette::AlternateBase, slate.darker());
|
||||
sapphirePalette.setColor(QPalette::ToolTipBase, slate);
|
||||
sapphirePalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
sapphirePalette.setColor(QPalette::Text, Qt::white);
|
||||
@@ -587,7 +587,7 @@ void QtHost::SetStyleFromSettings()
|
||||
emeraldPalette.setColor(QPalette::Window, slate);
|
||||
emeraldPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
emeraldPalette.setColor(QPalette::Base, slate.lighter());
|
||||
emeraldPalette.setColor(QPalette::AlternateBase, slate.lighter());
|
||||
emeraldPalette.setColor(QPalette::AlternateBase, slate.darker());
|
||||
emeraldPalette.setColor(QPalette::ToolTipBase, slate);
|
||||
emeraldPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
emeraldPalette.setColor(QPalette::Text, Qt::white);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
#include "common/MD5Digest.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/ScopedGuard.h"
|
||||
#include "common/SettingsInterface.h"
|
||||
#include "common/SmallString.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/Timer.h"
|
||||
@@ -439,7 +440,25 @@ bool Achievements::Initialize()
|
||||
IdentifyGame(VMManager::GetDiscCRC(), VMManager::GetCurrentCRC());
|
||||
|
||||
const std::string username = Host::GetBaseStringSettingValue("Achievements", "Username");
|
||||
const std::string api_token = Host::GetBaseStringSettingValue("Achievements", "Token");
|
||||
|
||||
// Check the base settings file to see if the token is defined inside. Move if found.
|
||||
std::string oldToken = Host::GetBaseStringSettingValue("Achievements", "Token");
|
||||
if (!oldToken.empty())
|
||||
{
|
||||
auto secretsLock = Host::GetSecretsSettingsLock();
|
||||
SettingsInterface* secretsInterface = Host::Internal::GetSecretsSettingsLayer();
|
||||
secretsInterface->SetStringValue("Achievements", "Token", oldToken.c_str());
|
||||
secretsInterface->Save();
|
||||
|
||||
oldToken.clear();
|
||||
|
||||
auto baseLock = Host::GetSettingsLock();
|
||||
SettingsInterface* baseInterface = Host::Internal::GetBaseSettingsLayer();
|
||||
baseInterface->DeleteValue("Achievements", "Token");
|
||||
baseInterface->Save();
|
||||
}
|
||||
|
||||
const std::string api_token = Host::GetStringSettingValue("Achievements", "Token");
|
||||
if (!username.empty() && !api_token.empty())
|
||||
{
|
||||
Console.WriteLn("Achievements: Attempting login with user '%s'...", username.c_str());
|
||||
@@ -1785,9 +1804,12 @@ void Achievements::ClientLoginWithPasswordCallback(int result, const char* error
|
||||
|
||||
// Store configuration.
|
||||
Host::SetBaseStringSettingValue("Achievements", "Username", params->username);
|
||||
Host::SetBaseStringSettingValue("Achievements", "Token", user->token);
|
||||
Host::SetBaseStringSettingValue("Achievements", "LoginTimestamp", fmt::format("{}", std::time(nullptr)).c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
SettingsInterface* secretsInterface = Host::Internal::GetSecretsSettingsLayer();
|
||||
secretsInterface->SetStringValue("Achievements", "Token", user->token);
|
||||
secretsInterface->Save();
|
||||
|
||||
ShowLoginSuccess(client);
|
||||
}
|
||||
@@ -1887,9 +1909,13 @@ void Achievements::Logout()
|
||||
|
||||
Console.WriteLn("Achievements: Clearing credentials...");
|
||||
Host::RemoveBaseSettingValue("Achievements", "Username");
|
||||
Host::RemoveBaseSettingValue("Achievements", "Token");
|
||||
Host::RemoveBaseSettingValue("Achievements", "LoginTimestamp");
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
auto secretsLock = Host::GetSecretsSettingsLock();
|
||||
SettingsInterface* secretsInterface = Host::Internal::GetSecretsSettingsLayer();
|
||||
secretsInterface->DeleteValue("Achievements", "Token");
|
||||
secretsInterface->Save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
|
||||
std::vector<BreakPoint> CBreakPoints::breakPoints_;
|
||||
u32 CBreakPoints::breakSkipFirstAtEE_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicksEE_ = 0;
|
||||
u32 CBreakPoints::breakSkipFirstAtIop_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicksIop_ = 0;
|
||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck*> CBreakPoints::cleanupMemChecks_;
|
||||
bool CBreakPoints::breakpointTriggered_ = false;
|
||||
@@ -393,20 +391,18 @@ void CBreakPoints::SetSkipFirst(BreakPointCpu cpu, u32 pc)
|
||||
if (cpu == BREAKPOINT_EE)
|
||||
{
|
||||
breakSkipFirstAtEE_ = standardizeBreakpointAddress(pc);
|
||||
breakSkipFirstTicksEE_ = r5900Debug.getCycles();
|
||||
}
|
||||
else if (cpu == BREAKPOINT_IOP)
|
||||
{
|
||||
breakSkipFirstAtIop_ = pc;
|
||||
breakSkipFirstTicksIop_ = r3000Debug.getCycles();
|
||||
}
|
||||
}
|
||||
|
||||
u32 CBreakPoints::CheckSkipFirst(BreakPointCpu cpu, u32 cmpPc)
|
||||
{
|
||||
if (cpu == BREAKPOINT_EE && breakSkipFirstTicksEE_ == r5900Debug.getCycles())
|
||||
if (cpu == BREAKPOINT_EE && breakSkipFirstAtEE_ == r5900Debug.getPC())
|
||||
return breakSkipFirstAtEE_;
|
||||
else if (cpu == BREAKPOINT_IOP && breakSkipFirstTicksIop_ == r3000Debug.getCycles())
|
||||
else if (cpu == BREAKPOINT_IOP && breakSkipFirstAtIop_ == r3000Debug.getPC())
|
||||
return breakSkipFirstAtIop_;
|
||||
return 0;
|
||||
}
|
||||
@@ -414,9 +410,7 @@ u32 CBreakPoints::CheckSkipFirst(BreakPointCpu cpu, u32 cmpPc)
|
||||
void CBreakPoints::ClearSkipFirst()
|
||||
{
|
||||
breakSkipFirstAtEE_ = 0;
|
||||
breakSkipFirstTicksEE_ = 0;
|
||||
breakSkipFirstAtIop_ = 0;
|
||||
breakSkipFirstTicksIop_ = 0;
|
||||
}
|
||||
|
||||
const std::vector<MemCheck> CBreakPoints::GetMemCheckRanges()
|
||||
|
||||
@@ -533,7 +533,7 @@ bool GSHasDisplayWindow()
|
||||
return (g_gs_device->GetWindowInfo().type != WindowInfo::Type::Surfaceless);
|
||||
}
|
||||
|
||||
void GSResizeDisplayWindow(int width, int height, float scale)
|
||||
void GSResizeDisplayWindow(u32 width, u32 height, float scale)
|
||||
{
|
||||
g_gs_device->ResizeWindow(width, height, scale);
|
||||
ImGuiManager::WindowResized();
|
||||
|
||||
@@ -83,7 +83,7 @@ void GSThrottlePresentation();
|
||||
void GSGameChanged();
|
||||
void GSSetDisplayAlignment(GSDisplayAlignment alignment);
|
||||
bool GSHasDisplayWindow();
|
||||
void GSResizeDisplayWindow(int width, int height, float scale);
|
||||
void GSResizeDisplayWindow(u32 width, u32 height, float scale);
|
||||
void GSUpdateDisplayWindow();
|
||||
void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle);
|
||||
|
||||
|
||||
@@ -1019,7 +1019,7 @@ public:
|
||||
virtual bool UpdateWindow() = 0;
|
||||
|
||||
/// Call when the window size changes externally to recreate any resources.
|
||||
virtual void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) = 0;
|
||||
virtual void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) = 0;
|
||||
|
||||
/// Returns true if exclusive fullscreen is supported.
|
||||
virtual bool SupportsExclusiveFullscreen() const = 0;
|
||||
|
||||
@@ -439,7 +439,9 @@ GSRendererType D3D::GetPreferredRenderer()
|
||||
if (!feature_level.has_value())
|
||||
return GSRendererType::DX11;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_12_0)
|
||||
return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::DX11;
|
||||
return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::DX12;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_11_1)
|
||||
return GSRendererType::DX12;
|
||||
else
|
||||
return GSRendererType::DX11;
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
|
||||
for (size_t i = 0; i < std::size(m_merge.ps); i++)
|
||||
{
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_main%d", i));
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_main%zu", i));
|
||||
m_merge.ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *shader, nullptr, entry_point.c_str());
|
||||
if (!m_merge.ps[i])
|
||||
return false;
|
||||
@@ -312,7 +312,7 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
for (size_t i = 0; i < std::size(m_interlace.ps); i++)
|
||||
{
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_main%d", i));
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_main%zu", i));
|
||||
m_interlace.ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *shader, nullptr, entry_point.c_str());
|
||||
if (!m_interlace.ps[i])
|
||||
return false;
|
||||
@@ -498,7 +498,7 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
|
||||
for (size_t i = 0; i < std::size(m_date.primid_init_ps); i++)
|
||||
{
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_stencil_image_init_%d", i));
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_stencil_image_init_%zu", i));
|
||||
m_date.primid_init_ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, nullptr, entry_point.c_str());
|
||||
if (!m_date.primid_init_ps[i])
|
||||
return false;
|
||||
@@ -893,7 +893,7 @@ std::string GSDevice11::GetDriverInfo() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GSDevice11::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||
void GSDevice11::ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale)
|
||||
{
|
||||
if (!m_swap_chain || m_is_exclusive_fullscreen)
|
||||
return;
|
||||
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
RenderAPI GetRenderAPI() const override;
|
||||
|
||||
bool UpdateWindow() override;
|
||||
void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
|
||||
void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) override;
|
||||
bool SupportsExclusiveFullscreen() const override;
|
||||
bool HasSurface() const override;
|
||||
void DestroySurface() override;
|
||||
|
||||
@@ -750,6 +750,8 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
|
||||
InitializeState();
|
||||
InitializeSamplers();
|
||||
// Reference stencil isn't tied to pipeline, so we can set it once and leave it.
|
||||
SetStencilRef(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1054,7 +1056,7 @@ std::string GSDevice12::GetDriverInfo() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GSDevice12::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||
void GSDevice12::ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale)
|
||||
{
|
||||
if (!m_swap_chain)
|
||||
return;
|
||||
@@ -3740,7 +3742,7 @@ void GSDevice12::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSV
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), 4);
|
||||
SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
SetPipeline(m_convert[SetDATMShader(datm)].get());
|
||||
SetStencilRef(1);
|
||||
// Reference stencil value set on Create()
|
||||
BeginRenderPass(D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
|
||||
@@ -3828,26 +3830,6 @@ GSTexture12* GSDevice12::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
||||
|
||||
void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
// Destination Alpha Setup
|
||||
const bool stencil_DATE_One = config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne;
|
||||
const bool stencil_DATE = (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil || stencil_DATE_One);
|
||||
|
||||
// TODO: Backport from vk.
|
||||
if (stencil_DATE_One)
|
||||
{
|
||||
config.ps.date = 0;
|
||||
config.alpha_second_pass.ps.date = 0;
|
||||
if (!config.ps.IsFeedbackLoop())
|
||||
{
|
||||
config.require_one_barrier = false;
|
||||
config.require_full_barrier = false;
|
||||
}
|
||||
if (!config.alpha_second_pass.ps.IsFeedbackLoop())
|
||||
{
|
||||
config.alpha_second_pass.require_one_barrier = false;
|
||||
config.alpha_second_pass.require_full_barrier = false;
|
||||
}
|
||||
}
|
||||
|
||||
GSTexture12* colclip_rt = static_cast<GSTexture12*>(g_gs_device->GetColorClipTexture());
|
||||
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
@@ -3910,8 +3892,29 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
if (stencil_DATE)
|
||||
SetupDATE(draw_rt, config.ds, config.datm, config.drawarea);
|
||||
// Destination Alpha Setup
|
||||
const bool need_barrier = m_features.texture_barrier && (config.require_one_barrier || config.require_full_barrier);
|
||||
switch (config.destination_alpha)
|
||||
{
|
||||
case GSHWDrawConfig::DestinationAlphaMode::Off: // No setup
|
||||
case GSHWDrawConfig::DestinationAlphaMode::Full: // No setup
|
||||
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking: // Setup is done below
|
||||
break;
|
||||
case GSHWDrawConfig::DestinationAlphaMode::StencilOne: // setup is done below
|
||||
{
|
||||
// we only need to do the setup here if we don't have barriers, in which case do full DATE.
|
||||
if (!need_barrier)
|
||||
{
|
||||
SetupDATE(draw_rt, config.ds, config.datm, config.drawarea);
|
||||
config.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Stencil;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GSHWDrawConfig::DestinationAlphaMode::Stencil:
|
||||
SetupDATE(draw_rt, config.ds, config.datm, config.drawarea);
|
||||
break;
|
||||
}
|
||||
|
||||
// stream buffer in first, in case we need to exec
|
||||
SetVSConstantBuffer(config.cb_vs);
|
||||
@@ -4033,6 +4036,17 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// For depth testing and sampling, use a read only dsv, otherwise use a write dsv
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, config.tex && config.tex == config.ds);
|
||||
|
||||
// DX12 equivalent of vkCmdClearAttachments for StencilOne
|
||||
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
|
||||
{
|
||||
EndRenderPass();
|
||||
// Make sure the DSV is in writeable state
|
||||
draw_ds->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE);
|
||||
|
||||
D3D12_RECT rect = {config.drawarea.left, config.drawarea.top, config.drawarea.left + config.drawarea.width(), config.drawarea.top + config.drawarea.height()};
|
||||
GetCommandList()->ClearDepthStencilView(draw_ds->GetWriteDescriptor(), D3D12_CLEAR_FLAG_STENCIL, 0.0f, 1, 1, &rect);
|
||||
}
|
||||
|
||||
// Begin render pass if new target or out of the area.
|
||||
if (!m_in_render_pass)
|
||||
{
|
||||
@@ -4042,14 +4056,18 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// Denormalize clear color for hw colclip.
|
||||
clear_color *= GSVector4::cxpr(255.0f / 65535.0f, 255.0f / 65535.0f, 255.0f / 65535.0f, 1.0f);
|
||||
}
|
||||
|
||||
const bool stencil_DATE = config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne;
|
||||
|
||||
BeginRenderPass(GetLoadOpForTexture(draw_rt),
|
||||
draw_rt ? D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE : D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
GetLoadOpForTexture(draw_ds),
|
||||
draw_ds ? D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE : D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
stencil_DATE ? D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE :
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS,
|
||||
stencil_DATE ? (feedback ? D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE :
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD) :
|
||||
stencil_DATE ? (need_barrier ? D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE :
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD) :
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
clear_color, draw_ds ? draw_ds->GetClearDepth() : 0.0f, 1);
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ public:
|
||||
void Destroy() override;
|
||||
|
||||
bool UpdateWindow() override;
|
||||
void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
|
||||
void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) override;
|
||||
bool SupportsExclusiveFullscreen() const override;
|
||||
void DestroySurface() override;
|
||||
std::string GetDriverInfo() const override;
|
||||
|
||||
@@ -738,7 +738,7 @@ void GSTexture12::TransitionToState(ID3D12GraphicsCommandList* cmdlist, D3D12_RE
|
||||
{D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
{{m_resource.get(), 1, m_resource_state, D3D12_RESOURCE_STATE_DEPTH_WRITE}}},
|
||||
};
|
||||
GSDevice12::GetInstance()->GetCommandList()->ResourceBarrier(m_resource_state == D3D12_RESOURCE_STATE_DEPTH_WRITE ? 1 : 2, barriers);
|
||||
cmdlist->ResourceBarrier(m_resource_state == D3D12_RESOURCE_STATE_DEPTH_WRITE ? 1 : 2, barriers);
|
||||
}
|
||||
else if (m_resource_state == (D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE))
|
||||
{
|
||||
@@ -749,7 +749,7 @@ void GSTexture12::TransitionToState(ID3D12GraphicsCommandList* cmdlist, D3D12_RE
|
||||
{D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
{{m_resource.get(), 1, D3D12_RESOURCE_STATE_DEPTH_WRITE, state}}},
|
||||
};
|
||||
GSDevice12::GetInstance()->GetCommandList()->ResourceBarrier(state == D3D12_RESOURCE_STATE_DEPTH_WRITE ? 1 : 2, barriers);
|
||||
cmdlist->ResourceBarrier(state == D3D12_RESOURCE_STATE_DEPTH_WRITE ? 1 : 2, barriers);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -385,7 +385,7 @@ public:
|
||||
bool SupportsExclusiveFullscreen() const override;
|
||||
std::string GetDriverInfo() const override;
|
||||
|
||||
void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
|
||||
void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) override;
|
||||
|
||||
void UpdateTexture(id<MTLTexture> texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride);
|
||||
|
||||
|
||||
@@ -1267,11 +1267,11 @@ std::string GSDeviceMTL::GetDriverInfo() const
|
||||
return desc;
|
||||
}}
|
||||
|
||||
void GSDeviceMTL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||
void GSDeviceMTL::ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale)
|
||||
{
|
||||
m_window_info.surface_scale = new_window_scale;
|
||||
if (!m_layer ||
|
||||
(m_window_info.surface_width == static_cast<u32>(new_window_width) && m_window_info.surface_height == static_cast<u32>(new_window_height)))
|
||||
(m_window_info.surface_width == new_window_width && m_window_info.surface_height == new_window_height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -888,17 +888,17 @@ bool GSDeviceOGL::UpdateWindow()
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||
void GSDeviceOGL::ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale)
|
||||
{
|
||||
m_window_info.surface_scale = new_window_scale;
|
||||
if (m_window_info.type == WindowInfo::Type::Surfaceless ||
|
||||
(m_window_info.surface_width == static_cast<u32>(new_window_width) &&
|
||||
m_window_info.surface_height == static_cast<u32>(new_window_height)))
|
||||
(m_window_info.surface_width == new_window_width &&
|
||||
m_window_info.surface_height == new_window_height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_gl_context->ResizeSurface(static_cast<u32>(new_window_width), static_cast<u32>(new_window_height));
|
||||
m_gl_context->ResizeSurface(new_window_width, new_window_height);
|
||||
m_window_info = m_gl_context->GetWindowInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
void Destroy() override;
|
||||
|
||||
bool UpdateWindow() override;
|
||||
void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
|
||||
void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) override;
|
||||
bool SupportsExclusiveFullscreen() const override;
|
||||
void DestroySurface() override;
|
||||
std::string GetDriverInfo() const override;
|
||||
|
||||
@@ -2216,12 +2216,12 @@ bool GSDeviceVK::UpdateWindow()
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDeviceVK::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||
void GSDeviceVK::ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale)
|
||||
{
|
||||
m_resize_requested = false;
|
||||
|
||||
if (!m_swap_chain || (m_swap_chain->GetWidth() == static_cast<u32>(new_window_width) &&
|
||||
m_swap_chain->GetHeight() == static_cast<u32>(new_window_height)))
|
||||
if (!m_swap_chain || (m_swap_chain->GetWidth() == new_window_width &&
|
||||
m_swap_chain->GetHeight() == new_window_height))
|
||||
{
|
||||
// skip unnecessary resizes
|
||||
m_window_info.surface_scale = new_window_scale;
|
||||
|
||||
@@ -506,7 +506,7 @@ public:
|
||||
void Destroy() override;
|
||||
|
||||
bool UpdateWindow() override;
|
||||
void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale) override;
|
||||
void ResizeWindow(u32 new_window_width, u32 new_window_height, float new_window_scale) override;
|
||||
bool SupportsExclusiveFullscreen() const override;
|
||||
void DestroySurface() override;
|
||||
std::string GetDriverInfo() const override;
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Host
|
||||
const std::string_view context, const std::string_view msg);
|
||||
|
||||
static std::mutex s_settings_mutex;
|
||||
static std::mutex s_secrets_settings_mutex;
|
||||
static LayeredSettingsInterface s_layered_settings_interface;
|
||||
|
||||
static constexpr u32 TRANSLATION_STRING_CACHE_SIZE = 4 * 1024 * 1024;
|
||||
@@ -164,6 +165,11 @@ std::unique_lock<std::mutex> Host::GetSettingsLock()
|
||||
return std::unique_lock<std::mutex>(s_settings_mutex);
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> Host::GetSecretsSettingsLock()
|
||||
{
|
||||
return std::unique_lock<std::mutex>(s_secrets_settings_mutex);
|
||||
}
|
||||
|
||||
SettingsInterface* Host::GetSettingsInterface()
|
||||
{
|
||||
return &s_layered_settings_interface;
|
||||
@@ -352,6 +358,11 @@ SettingsInterface* Host::Internal::GetBaseSettingsLayer()
|
||||
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE);
|
||||
}
|
||||
|
||||
SettingsInterface* Host::Internal::GetSecretsSettingsLayer()
|
||||
{
|
||||
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_SECRETS);
|
||||
}
|
||||
|
||||
SettingsInterface* Host::Internal::GetGameSettingsLayer()
|
||||
{
|
||||
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_GAME);
|
||||
@@ -365,10 +376,17 @@ SettingsInterface* Host::Internal::GetInputSettingsLayer()
|
||||
void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif)
|
||||
{
|
||||
pxAssertRel(s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE) == nullptr,
|
||||
"Base layer has not been set");
|
||||
"Base layer has already been set");
|
||||
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif);
|
||||
}
|
||||
|
||||
void Host::Internal::SetSecretsSettingsLayer(SettingsInterface* sif)
|
||||
{
|
||||
pxAssertRel(s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_SECRETS) == nullptr,
|
||||
"Secrets layer has already been set");
|
||||
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_SECRETS, sif);
|
||||
}
|
||||
|
||||
void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& settings_lock)
|
||||
{
|
||||
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif);
|
||||
|
||||
@@ -134,6 +134,8 @@ namespace Host
|
||||
|
||||
/// Direct access to settings interface. Must hold the lock when calling GetSettingsInterface() and while using it.
|
||||
std::unique_lock<std::mutex> GetSettingsLock();
|
||||
/// Ditto for secrets file.
|
||||
std::unique_lock<std::mutex> GetSecretsSettingsLock();
|
||||
SettingsInterface* GetSettingsInterface();
|
||||
|
||||
/// Sets host-specific default settings.
|
||||
@@ -147,6 +149,9 @@ namespace Host
|
||||
/// Retrieves the base settings layer. Must call with lock held.
|
||||
SettingsInterface* GetBaseSettingsLayer();
|
||||
|
||||
/// Retrieves the base settings layer. Must call with lock held.
|
||||
SettingsInterface* GetSecretsSettingsLayer();
|
||||
|
||||
/// Retrieves the game settings layer, if present. Must call with lock held.
|
||||
SettingsInterface* GetGameSettingsLayer();
|
||||
|
||||
@@ -156,6 +161,9 @@ namespace Host
|
||||
/// Sets the base settings layer. Should be called by the host at initialization time.
|
||||
void SetBaseSettingsLayer(SettingsInterface* sif);
|
||||
|
||||
/// Sets the secrets settings layer. Should follow call to SetBaseSettingsLayer.
|
||||
void SetSecretsSettingsLayer(SettingsInterface* sif);
|
||||
|
||||
/// Sets the game settings layer. Called by VMManager when the game changes.
|
||||
void SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& settings_lock);
|
||||
|
||||
|
||||
12
pcsx2/Hw.cpp
12
pcsx2/Hw.cpp
@@ -11,15 +11,27 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
using namespace R5900;
|
||||
|
||||
const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX
|
||||
int rdram_sdevid = 0;
|
||||
|
||||
std::deque<u8> ee_sio_rx_fifo;
|
||||
std::deque<u8> ee_sio_tx_fifo;
|
||||
|
||||
void hwReset()
|
||||
{
|
||||
std::memset(eeHw, 0, sizeof(eeHw));
|
||||
|
||||
{
|
||||
std::deque<u8> empty_rx;
|
||||
std::swap(ee_sio_rx_fifo, empty_rx);
|
||||
std::deque<u8> empty_tx;
|
||||
std::swap(ee_sio_tx_fifo, empty_tx);
|
||||
}
|
||||
|
||||
psHu32(SBUS_F260) = 0x1D000060;
|
||||
|
||||
// i guess this is kinda a version, it's used by some bioses
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include <deque>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace EEMemoryMap
|
||||
@@ -355,3 +357,6 @@ extern void hwReset();
|
||||
|
||||
extern const int rdram_devices;
|
||||
extern int rdram_sdevid;
|
||||
|
||||
extern std::deque<u8> ee_sio_rx_fifo;
|
||||
extern std::deque<u8> ee_sio_tx_fifo;
|
||||
|
||||
@@ -125,7 +125,23 @@ mem32_t _hwRead32(u32 mem)
|
||||
switch( mem )
|
||||
{
|
||||
case SIO_ISR:
|
||||
|
||||
// Not (yet) hardware tested
|
||||
// The PS2SDK behaviour is as follows:
|
||||
|
||||
// TX: Don't write to TX FIFO until until bit 15 is 0
|
||||
|
||||
// RX: RX FIFO has data when bits 8-11 are not 0 (maybe a byte count?)
|
||||
// RX: When reading from the RX FIFO, set bits 0-2 to 1 (why??)
|
||||
|
||||
// For TX, we don't do any LLE buffering, so we can keep bit 15 to 0
|
||||
// For RX, just hack it so when the ee_rx_fifo.size() != 0, ISR = 0xf00
|
||||
|
||||
if(!ee_sio_rx_fifo.empty())
|
||||
return 0xf00;
|
||||
|
||||
return 0x0;
|
||||
break;
|
||||
case 0x1000f410:
|
||||
case MCH_RICM:
|
||||
return 0;
|
||||
@@ -211,6 +227,16 @@ mem32_t hwRead32_page_0F_INTC_HACK(u32 mem)
|
||||
template< uint page >
|
||||
mem8_t _hwRead8(u32 mem)
|
||||
{
|
||||
if(mem == SIO_RXFIFO)
|
||||
{
|
||||
if(ee_sio_rx_fifo.empty())
|
||||
return 0; // needs hardware test, what does it return with the FIFO is empty
|
||||
|
||||
const char c = ee_sio_rx_fifo.front();
|
||||
ee_sio_rx_fifo.pop_front();
|
||||
return c;
|
||||
}
|
||||
|
||||
u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
|
||||
return ((u8*)&ret32)[mem & 0x03];
|
||||
}
|
||||
|
||||
@@ -285,26 +285,35 @@ void _hwWrite8(u32 mem, u8 value)
|
||||
#endif
|
||||
if (mem == SIO_TXFIFO)
|
||||
{
|
||||
static bool included_newline = false;
|
||||
static char sio_buffer[1024];
|
||||
static int sio_count;
|
||||
|
||||
if (value == '\r')
|
||||
static bool last_char_was_cr = false;
|
||||
|
||||
// skip the \n in \r\n
|
||||
if(last_char_was_cr && (value == '\n'))
|
||||
{
|
||||
included_newline = true;
|
||||
sio_buffer[sio_count++] = '\n';
|
||||
last_char_was_cr = false;
|
||||
return;
|
||||
}
|
||||
else if (!included_newline || (value != '\n'))
|
||||
|
||||
last_char_was_cr = value == '\r';
|
||||
bool should_flush_cause_newline = false;
|
||||
if (last_char_was_cr)
|
||||
{
|
||||
included_newline = false;
|
||||
sio_buffer[sio_count++] = value;
|
||||
should_flush_cause_newline = true;
|
||||
ee_sio_tx_fifo.push_back('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
should_flush_cause_newline = value == '\n';
|
||||
ee_sio_tx_fifo.push_back(value);
|
||||
}
|
||||
|
||||
if ((sio_count == std::size(sio_buffer)-1) || (sio_count != 0 && sio_buffer[sio_count-1] == '\n'))
|
||||
// Check if the only thing in the buffer
|
||||
if (ee_sio_tx_fifo.size() == 1024 || should_flush_cause_newline)
|
||||
{
|
||||
sio_buffer[sio_count] = 0;
|
||||
eeConLog( ShiftJIS_ConvertString(sio_buffer) );
|
||||
sio_count = 0;
|
||||
std::string output_string(ee_sio_tx_fifo.begin(), ee_sio_tx_fifo.end());
|
||||
|
||||
eeConLog(ShiftJIS_ConvertString(output_string.c_str()));
|
||||
ee_sio_tx_fifo.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3458,8 +3458,11 @@ void FullscreenUI::StartAutomaticBinding(u32 port)
|
||||
names.reserve(devices.size());
|
||||
for (auto& [name, display_name] : devices)
|
||||
{
|
||||
if(!StringUtil::compareNoCase(name, display_name))
|
||||
options.emplace_back(fmt::format("{}: {}", name, display_name), false);
|
||||
else
|
||||
options.emplace_back(std::move(display_name), false);
|
||||
names.push_back(std::move(name));
|
||||
options.emplace_back(std::move(display_name), false);
|
||||
}
|
||||
OpenChoiceDialog(FSUI_CSTR("Select Device"), false, std::move(options),
|
||||
[port, names = std::move(names)](s32 index, const std::string& title, bool checked) {
|
||||
|
||||
@@ -708,16 +708,16 @@ void ImGuiFullscreen::EndLayout()
|
||||
const float notification_margin = LayoutScale(10.0f);
|
||||
const float spacing = LayoutScale(10.0f);
|
||||
const float notification_vertical_pos = GetNotificationVerticalPosition();
|
||||
|
||||
|
||||
// Get the horizonal position based on alignment
|
||||
float horizontal_pos;
|
||||
if (s_notification_horizontal_position <= 0.0f)
|
||||
horizontal_pos = notification_margin; // Left
|
||||
else if (s_notification_horizontal_position >= 1.0f)
|
||||
else if (s_notification_horizontal_position >= 1.0f)
|
||||
horizontal_pos = ImGui::GetIO().DisplaySize.x - notification_margin; // Right
|
||||
else
|
||||
horizontal_pos = ImGui::GetIO().DisplaySize.x * s_notification_horizontal_position; // Center
|
||||
|
||||
|
||||
ImVec2 position(horizontal_pos, notification_vertical_pos * ImGui::GetIO().DisplaySize.y +
|
||||
((notification_vertical_pos >= 0.5f) ? -notification_margin : notification_margin));
|
||||
DrawProgressDialogs(position, spacing);
|
||||
@@ -2574,11 +2574,11 @@ void ImGuiFullscreen::DrawInputDialog()
|
||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags_None;
|
||||
if (s_input_dialog_filter_type != InputFilterType::None)
|
||||
flags |= ImGuiInputTextFlags_CallbackCharFilter;
|
||||
|
||||
|
||||
if (s_focus_reset_queued != FocusResetType::None)
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
|
||||
ImGui::InputText("##input", &s_input_dialog_text, flags,
|
||||
|
||||
ImGui::InputText("##input", &s_input_dialog_text, flags,
|
||||
(s_input_dialog_filter_type != InputFilterType::None) ? input_callback : nullptr,
|
||||
(s_input_dialog_filter_type != InputFilterType::None) ? static_cast<void*>(&s_input_dialog_filter_type) : nullptr);
|
||||
|
||||
@@ -3056,7 +3056,7 @@ void ImGuiFullscreen::DrawNotifications(ImVec2& position, float spacing)
|
||||
final_x = position.x - box_width;
|
||||
else if (s_notification_horizontal_position > 0.0f && s_notification_horizontal_position < 1.0f)
|
||||
final_x = position.x - (box_width * 0.5f);
|
||||
|
||||
|
||||
const ImVec2 box_min(final_x, actual_y);
|
||||
const ImVec2 box_max(box_min.x + box_width, box_min.y + box_height);
|
||||
const u32 background_color = (toast_background_color & ~IM_COL32_A_MASK) | (opacity << IM_COL32_A_SHIFT);
|
||||
@@ -3209,14 +3209,14 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
|
||||
}
|
||||
else if (theme == "AMOLED")
|
||||
{
|
||||
UIBackgroundColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||
UIBackgroundColor = HEX_TO_IMVEC4(0x0A0A0A, 0xff);
|
||||
UIBackgroundTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||
UIBackgroundLineColor = HEX_TO_IMVEC4(0xf0f0f0, 0xff);
|
||||
UIBackgroundHighlightColor = HEX_TO_IMVEC4(0x0c0c0c, 0xff);
|
||||
UIPopupBackgroundColor = HEX_TO_IMVEC4(0x212121, 0xf2);
|
||||
UIPrimaryColor = HEX_TO_IMVEC4(0x0a0a0a, 0xff);
|
||||
UIPrimaryLightColor = HEX_TO_IMVEC4(0xb5b5b5, 0xff);
|
||||
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x0A0A0A, 0xff);
|
||||
UIPrimaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||
UIDisabledColor = HEX_TO_IMVEC4(0x8d8d8d, 0xff);
|
||||
UITextHighlightColor = HEX_TO_IMVEC4(0x676767, 0xff);
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
LAYER_CMDLINE,
|
||||
LAYER_GAME,
|
||||
LAYER_INPUT,
|
||||
LAYER_SECRETS,
|
||||
LAYER_BASE,
|
||||
NUM_LAYERS
|
||||
};
|
||||
|
||||
@@ -946,7 +946,7 @@ void MTGS::ApplySettings()
|
||||
WaitGS(false, false, false);
|
||||
}
|
||||
|
||||
void MTGS::ResizeDisplayWindow(int width, int height, float scale)
|
||||
void MTGS::ResizeDisplayWindow(u32 width, u32 height, float scale)
|
||||
{
|
||||
pxAssertRel(IsOpen(), "MTGS is running");
|
||||
RunOnGSThread([width, height, scale]() {
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace MTGS
|
||||
void RunOnGSThread(AsyncCallType func);
|
||||
void GameChanged();
|
||||
void ApplySettings();
|
||||
void ResizeDisplayWindow(int width, int height, float scale);
|
||||
void ResizeDisplayWindow(u32 width, u32 height, float scale);
|
||||
void UpdateDisplayWindow();
|
||||
void SetVSyncMode(GSVSyncMode mode, bool allow_present_throttle);
|
||||
void UpdateVSyncMode();
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace usb_pad
|
||||
TRANSLATE_NOOP("USB", "Type 2"),
|
||||
TRANSLATE_NOOP("USB", "Shinkansen"),
|
||||
TRANSLATE_NOOP("USB", "Ryojōhen"),
|
||||
TRANSLATE_NOOP("USB", "Train Mascon"),
|
||||
TRANSLATE_NOOP("USB", "Master Controller"),
|
||||
};
|
||||
return subtypes;
|
||||
}
|
||||
@@ -63,6 +65,14 @@ namespace usb_pad
|
||||
CID_TC_L = CID_TC_C,
|
||||
CID_TC_R = CID_TC_D,
|
||||
|
||||
// Train Mascon
|
||||
CID_TC_ATS = CID_TC_D,
|
||||
CID_TC_CLOSE = CID_TC_CAMERA,
|
||||
CID_TC_POWER_UP,
|
||||
CID_TC_POWER_DOWN,
|
||||
CID_TC_REVERSER_UP,
|
||||
CID_TC_REVERSER_DOWN,
|
||||
|
||||
BUTTONS_OFFSET = CID_TC_B,
|
||||
};
|
||||
|
||||
@@ -110,6 +120,43 @@ namespace usb_pad
|
||||
|
||||
return bindings;
|
||||
}
|
||||
case TRAIN_MASCON:
|
||||
{
|
||||
static constexpr const InputBindingInfo bindings[] = {
|
||||
{"PowerUp", TRANSLATE_NOOP("USB", "Power Up"), nullptr, InputBindingInfo::Type::Button, CID_TC_POWER_UP, GenericInputBinding::R1},
|
||||
{"PowerDown", TRANSLATE_NOOP("USB", "Power Down"), nullptr, InputBindingInfo::Type::Button, CID_TC_POWER_DOWN, GenericInputBinding::L1},
|
||||
{"ReverserUp", TRANSLATE_NOOP("USB", "Reverser Up"), nullptr, InputBindingInfo::Type::Button, CID_TC_REVERSER_UP, GenericInputBinding::R2},
|
||||
{"ReverserDown", TRANSLATE_NOOP("USB", "Reverser Down"), nullptr, InputBindingInfo::Type::Button, CID_TC_REVERSER_DOWN, GenericInputBinding::L2},
|
||||
|
||||
{"Up", TRANSLATE_NOOP("USB", "D-Pad Up"), ICON_PF_DPAD_UP, InputBindingInfo::Type::Button, CID_TC_UP, GenericInputBinding::DPadUp},
|
||||
{"Down", TRANSLATE_NOOP("USB", "D-Pad Down"), ICON_PF_DPAD_DOWN, InputBindingInfo::Type::Button, CID_TC_DOWN, GenericInputBinding::DPadDown},
|
||||
{"Left", TRANSLATE_NOOP("USB", "D-Pad Left"), ICON_PF_DPAD_LEFT, InputBindingInfo::Type::Button, CID_TC_LEFT, GenericInputBinding::DPadLeft},
|
||||
{"Right", TRANSLATE_NOOP("USB", "D-Pad Right"), ICON_PF_DPAD_RIGHT, InputBindingInfo::Type::Button, CID_TC_RIGHT, GenericInputBinding::DPadRight},
|
||||
|
||||
{"ATS", TRANSLATE_NOOP("USB", "ATS"), nullptr, InputBindingInfo::Type::Button, CID_TC_ATS, GenericInputBinding::Triangle},
|
||||
{"Close", TRANSLATE_NOOP("USB", "Close"), nullptr, InputBindingInfo::Type::Button, CID_TC_CLOSE, GenericInputBinding::R3},
|
||||
{"A", TRANSLATE_NOOP("USB", "A Button"), ICON_PF_KEY_A, InputBindingInfo::Type::Button, CID_TC_A, GenericInputBinding::Square},
|
||||
{"B", TRANSLATE_NOOP("USB", "B Button"), ICON_PF_KEY_B, InputBindingInfo::Type::Button, CID_TC_B, GenericInputBinding::Cross},
|
||||
{"C", TRANSLATE_NOOP("USB", "C Button"), ICON_PF_KEY_C, InputBindingInfo::Type::Button, CID_TC_C, GenericInputBinding::Circle},
|
||||
{"Select", TRANSLATE_NOOP("USB", "Select"), ICON_PF_SELECT_SHARE, InputBindingInfo::Type::Button, CID_TC_SELECT, GenericInputBinding::Select},
|
||||
{"Start", TRANSLATE_NOOP("USB", "Start"), ICON_PF_START, InputBindingInfo::Type::Button, CID_TC_START, GenericInputBinding::Start},
|
||||
};
|
||||
return bindings;
|
||||
}
|
||||
case MASTER_CONTROLLER:
|
||||
{
|
||||
static constexpr const InputBindingInfo bindings[] = {
|
||||
{"PowerUp", TRANSLATE_NOOP("USB", "Power Up"), nullptr, InputBindingInfo::Type::Button, CID_TC_POWER_UP, GenericInputBinding::R1},
|
||||
{"PowerDown", TRANSLATE_NOOP("USB", "Power Down"), nullptr, InputBindingInfo::Type::Button, CID_TC_POWER_DOWN, GenericInputBinding::L1},
|
||||
{"ReverserUp", TRANSLATE_NOOP("USB", "Reverser Up"), nullptr, InputBindingInfo::Type::Button, CID_TC_REVERSER_UP, GenericInputBinding::R2},
|
||||
{"ReverserDown", TRANSLATE_NOOP("USB", "Reverser Down"), nullptr, InputBindingInfo::Type::Button, CID_TC_REVERSER_DOWN, GenericInputBinding::L2},
|
||||
{"S", TRANSLATE_NOOP("USB", "S"), ICON_PF_KEY_S, InputBindingInfo::Type::Button, CID_TC_D, GenericInputBinding::Cross},
|
||||
{"A", TRANSLATE_NOOP("USB", "A"), ICON_PF_KEY_A, InputBindingInfo::Type::Button, CID_TC_A, GenericInputBinding::Square},
|
||||
{"B", TRANSLATE_NOOP("USB", "B"), ICON_PF_KEY_B, InputBindingInfo::Type::Button, CID_TC_B, GenericInputBinding::Triangle},
|
||||
{"C", TRANSLATE_NOOP("USB", "C"), ICON_PF_KEY_C, InputBindingInfo::Type::Button, CID_TC_C, GenericInputBinding::Circle},
|
||||
};
|
||||
return bindings;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -151,21 +198,66 @@ namespace usb_pad
|
||||
{
|
||||
TrainDeviceState* s = USB_CONTAINER_OF(dev, TrainDeviceState, dev);
|
||||
|
||||
s->passthrough = USB::GetConfigBool(si, s->port, TypeName(), "Passthrough", false);
|
||||
switch (s->type)
|
||||
{
|
||||
case TRAIN_TYPE2:
|
||||
case TRAIN_SHINKANSEN:
|
||||
case TRAIN_RYOJOUHEN:
|
||||
s->passthrough = USB::GetConfigBool(si, s->port, TypeName(), "Passthrough", false);
|
||||
break;
|
||||
case MASTER_CONTROLLER:
|
||||
s->power_notches = USB::GetConfigInt(si, s->port, TypeName(), "power_notches", 5);
|
||||
s->brake_notches = USB::GetConfigInt(si, s->port, TypeName(), "brake_notches", 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::span<const SettingInfo> TrainDevice::Settings(u32 subtype) const
|
||||
{
|
||||
static constexpr const SettingInfo passthrough = {
|
||||
SettingInfo::Type::Boolean,
|
||||
"Passthrough",
|
||||
TRANSLATE_NOOP("USB", "Axes Passthrough"),
|
||||
TRANSLATE_NOOP("USB", "Passes through the unprocessed input axis to the game. Enable if you are using a compatible Densha De Go! controller. Disable if you are using any other joystick."),
|
||||
"false",
|
||||
};
|
||||
|
||||
static constexpr const SettingInfo info[] = {passthrough};
|
||||
return info;
|
||||
switch (subtype)
|
||||
{
|
||||
case TRAIN_TYPE2:
|
||||
case TRAIN_SHINKANSEN:
|
||||
case TRAIN_RYOJOUHEN:
|
||||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{
|
||||
.type = SettingInfo::Type::Boolean,
|
||||
.name = "Passthrough",
|
||||
.display_name = TRANSLATE_NOOP("USB", "Axes Passthrough"),
|
||||
.description = TRANSLATE_NOOP("USB", "Passes through the unprocessed input axis to the game. Enable if you are using a compatible Densha De Go! controller. Disable if you are using any other joystick."),
|
||||
.default_value = "false",
|
||||
}
|
||||
};
|
||||
return info;
|
||||
}
|
||||
case MASTER_CONTROLLER:
|
||||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{
|
||||
.type = SettingInfo::Type::Integer,
|
||||
.name = "power_notches",
|
||||
.display_name = TRANSLATE_NOOP("USB", "Power notches"),
|
||||
.description = TRANSLATE_NOOP("USB", "Selects the number of power notches (3-6)"),
|
||||
.default_value = "5",
|
||||
.min_value = "3",
|
||||
.max_value = "6",
|
||||
},
|
||||
{
|
||||
.type = SettingInfo::Type::Integer,
|
||||
.name = "brake_notches",
|
||||
.display_name = TRANSLATE_NOOP("USB", "Brake notches"),
|
||||
.description = TRANSLATE_NOOP("USB", "Selects the number of brake notches (5-8)"),
|
||||
.default_value = "8",
|
||||
.min_value = "5",
|
||||
.max_value = "8",
|
||||
}
|
||||
};
|
||||
return info;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr u32 button_mask(u32 bind_index)
|
||||
@@ -173,7 +265,7 @@ namespace usb_pad
|
||||
return (1u << (bind_index - TrainControlID::BUTTONS_OFFSET));
|
||||
}
|
||||
|
||||
static constexpr u8 button_at(u8 value, u32 index)
|
||||
static constexpr u16 button_at(u16 value, u32 index)
|
||||
{
|
||||
return value & button_mask(index);
|
||||
}
|
||||
@@ -205,6 +297,10 @@ namespace usb_pad
|
||||
case CID_TC_SELECT:
|
||||
case CID_TC_START:
|
||||
case CID_TC_CAMERA:
|
||||
case CID_TC_POWER_UP:
|
||||
case CID_TC_POWER_DOWN:
|
||||
case CID_TC_REVERSER_UP:
|
||||
case CID_TC_REVERSER_DOWN:
|
||||
{
|
||||
return (button_at(s->data.buttons, bind_index) != 0u) ? 1.0f : 0.0f;
|
||||
}
|
||||
@@ -251,14 +347,18 @@ namespace usb_pad
|
||||
case CID_TC_SELECT:
|
||||
case CID_TC_START:
|
||||
case CID_TC_CAMERA:
|
||||
case CID_TC_POWER_UP:
|
||||
case CID_TC_POWER_DOWN:
|
||||
case CID_TC_REVERSER_UP:
|
||||
case CID_TC_REVERSER_DOWN:
|
||||
{
|
||||
const u32 mask = button_mask(bind_index);
|
||||
if (value >= 0.5f)
|
||||
s->data.buttons |= mask;
|
||||
else
|
||||
s->data.buttons &= ~mask;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -452,11 +552,23 @@ namespace usb_pad
|
||||
return (get_ab(buttons) | (button_at(buttons, CID_TC_CAMERA) >> 4) | ((get_cd(buttons) | get_ss(buttons)) << 1));
|
||||
}
|
||||
|
||||
void TrainDeviceState::UpdateHandles(u8 max_power, u8 max_brake)
|
||||
{
|
||||
if (!button_at(prev_buttons, CID_TC_POWER_UP) && button_at(data.buttons, CID_TC_POWER_UP) && handle < max_brake + 1 + max_power)
|
||||
handle++;
|
||||
if (!button_at(prev_buttons, CID_TC_POWER_DOWN) && button_at(data.buttons, CID_TC_POWER_DOWN) && handle > 0)
|
||||
handle--;
|
||||
if (!button_at(prev_buttons, CID_TC_REVERSER_UP) && button_at(data.buttons, CID_TC_REVERSER_UP) && reverser < 2)
|
||||
reverser++;
|
||||
if (!button_at(prev_buttons, CID_TC_REVERSER_DOWN) && button_at(data.buttons, CID_TC_REVERSER_DOWN) && reverser > 0)
|
||||
reverser--;
|
||||
}
|
||||
|
||||
static void train_handle_data(USBDevice* dev, USBPacket* p)
|
||||
{
|
||||
TrainDeviceState* s = USB_CONTAINER_OF(dev, TrainDeviceState, dev);
|
||||
|
||||
if (p->pid != USB_TOKEN_IN || p->ep->nr != 1)
|
||||
if (s->type < MASTER_CONTROLLER && (p->pid != USB_TOKEN_IN || p->ep->nr != 1))
|
||||
{
|
||||
Console.Error("Unhandled TrainController request pid=%d ep=%u", p->pid, p->ep->nr);
|
||||
p->status = USB_RET_STALL;
|
||||
@@ -501,6 +613,77 @@ namespace usb_pad
|
||||
usb_packet_copy(p, &out, sizeof(out));
|
||||
break;
|
||||
}
|
||||
case TRAIN_MASCON:
|
||||
{
|
||||
s->UpdateHandles(5, 6);
|
||||
s->prev_buttons = s->data.buttons;
|
||||
|
||||
TrainConData_TrainMascon out = {};
|
||||
out.one = 0x01;
|
||||
out.handle = 1 + s->handle;
|
||||
out.reverser = s->reverser < 2 ? !s->reverser : s->reverser;
|
||||
out.ats = !!button_at(s->data.buttons, CID_TC_ATS);
|
||||
out.close = !!button_at(s->data.buttons, CID_TC_CLOSE);
|
||||
out.button_a_soft = !!button_at(s->data.buttons, CID_TC_A);
|
||||
out.button_a_hard = !!button_at(s->data.buttons, CID_TC_A);
|
||||
out.button_b = !!button_at(s->data.buttons, CID_TC_B);
|
||||
out.button_c = !!button_at(s->data.buttons, CID_TC_C);
|
||||
out.start = !!button_at(s->data.buttons, CID_TC_START);
|
||||
out.select = !!button_at(s->data.buttons, CID_TC_SELECT);
|
||||
out.dpad_up = s->data.hat_up;
|
||||
out.dpad_down = s->data.hat_down;
|
||||
out.dpad_left = s->data.hat_left;
|
||||
out.dpad_right = s->data.hat_right;
|
||||
usb_packet_copy(p, &out, sizeof(out));
|
||||
break;
|
||||
}
|
||||
case MASTER_CONTROLLER:
|
||||
{
|
||||
if (p->ep->nr == 1) // interrupt in
|
||||
{
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
else if (p->ep->nr == 2) // bulk out
|
||||
{
|
||||
// The game sends a reset command after ~1500ms without updates. Resend the status during the next transfer
|
||||
s->last_handle = -1;
|
||||
s->last_reverser = -1;
|
||||
break;
|
||||
} // else bulk in
|
||||
|
||||
s->UpdateHandles(s->power_notches, s->brake_notches);
|
||||
|
||||
char data[100];
|
||||
std::memset(data, 0, sizeof(data));
|
||||
u8 pos = 0;
|
||||
|
||||
if (s->last_handle != s->handle)
|
||||
{
|
||||
pos += snprintf(data + pos, sizeof(data) - pos, "%s\x0d", s->mc_handle[s->handle + 8 - s->brake_notches]);
|
||||
s->last_handle = s->handle;
|
||||
}
|
||||
if (s->last_reverser != s->reverser)
|
||||
{
|
||||
pos += snprintf(data + pos, sizeof(data) - pos, "%s\x0d", s->mc_reverser[s->reverser]);
|
||||
s->last_reverser = s->reverser;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (!button_at(s->prev_buttons, BUTTONS_OFFSET + i) && button_at(s->data.buttons, BUTTONS_OFFSET + i))
|
||||
{
|
||||
pos += snprintf(data + pos, sizeof(data) - pos, "%s\x0d", s->mc_button_pressed[i]);
|
||||
}
|
||||
if (button_at(s->prev_buttons, BUTTONS_OFFSET + i) && !button_at(s->data.buttons, BUTTONS_OFFSET + i))
|
||||
{
|
||||
pos += snprintf(data + pos, sizeof(data) - pos, "%s\x0d", s->mc_button_released[i]);
|
||||
}
|
||||
}
|
||||
s->prev_buttons = s->data.buttons;
|
||||
usb_packet_copy(p, data, std::min<u16>(p->buffer_size, pos));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Console.Error("Unhandled TrainController USB_TOKEN_IN pid=%d ep=%u type=%u", p->pid, p->ep->nr, s->type);
|
||||
p->status = USB_RET_IOERROR;
|
||||
@@ -520,25 +703,42 @@ namespace usb_pad
|
||||
s->desc.str = dct01_desc_strings;
|
||||
if (usb_desc_parse_dev(dct01_dev_descriptor, sizeof(dct01_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(taito_denshacon_config_descriptor, sizeof(taito_denshacon_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
break;
|
||||
case TRAIN_SHINKANSEN:
|
||||
s->desc.str = dct02_desc_strings;
|
||||
if (usb_desc_parse_dev(dct02_dev_descriptor, sizeof(dct02_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(taito_denshacon_config_descriptor, sizeof(taito_denshacon_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
break;
|
||||
case TRAIN_RYOJOUHEN:
|
||||
s->desc.str = dct03_desc_strings;
|
||||
if (usb_desc_parse_dev(dct03_dev_descriptor, sizeof(dct03_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(taito_denshacon_config_descriptor, sizeof(taito_denshacon_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
break;
|
||||
case TRAIN_MASCON:
|
||||
s->desc.str = dct03_desc_strings;
|
||||
if (usb_desc_parse_dev(train_mascon_dev_descriptor, sizeof(train_mascon_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(train_mascon_config_descriptor, sizeof(train_mascon_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
break;
|
||||
case MASTER_CONTROLLER:
|
||||
s->desc.str = dct03_desc_strings;
|
||||
if (usb_desc_parse_dev(master_controller_dev_descriptor, sizeof(master_controller_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(master_controller_config_descriptor, sizeof(master_controller_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (usb_desc_parse_config(taito_denshacon_config_descriptor, sizeof(taito_denshacon_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = train_handle_reset;
|
||||
|
||||
@@ -11,10 +11,11 @@ namespace usb_pad
|
||||
{
|
||||
enum TrainDeviceTypes
|
||||
{
|
||||
TRAIN_TYPE2, // TCPP20009 or similar
|
||||
TRAIN_SHINKANSEN, // TCPP20011
|
||||
TRAIN_RYOJOUHEN, // TCPP20014
|
||||
TRAIN_COUNT,
|
||||
TRAIN_TYPE2, // TCPP-20009 or similar
|
||||
TRAIN_SHINKANSEN, // TCPP-20011
|
||||
TRAIN_RYOJOUHEN, // TCPP-20014
|
||||
TRAIN_MASCON, // COTM-02001
|
||||
MASTER_CONTROLLER, // VOK-00105 or VOK-00106 with OGCW-10001 adapter
|
||||
};
|
||||
|
||||
class TrainDevice final : public DeviceProxy
|
||||
@@ -39,7 +40,7 @@ namespace usb_pad
|
||||
u8 control;
|
||||
u8 brake;
|
||||
u8 power;
|
||||
u8 horn;
|
||||
u8 horn; // pedal
|
||||
u8 hat;
|
||||
u8 buttons;
|
||||
};
|
||||
@@ -49,7 +50,7 @@ namespace usb_pad
|
||||
{
|
||||
u8 brake;
|
||||
u8 power;
|
||||
u8 horn;
|
||||
u8 horn; // pedal
|
||||
u8 hat;
|
||||
u8 buttons;
|
||||
u8 pad;
|
||||
@@ -60,12 +61,37 @@ namespace usb_pad
|
||||
{
|
||||
u8 brake;
|
||||
u8 power;
|
||||
u8 horn;
|
||||
u8 horn; // pedal
|
||||
u8 hat;
|
||||
u8 buttons;
|
||||
u8 pad[3];
|
||||
};
|
||||
static_assert(sizeof(TrainConData_Ryojouhen) == 8);
|
||||
|
||||
struct TrainConData_TrainMascon
|
||||
{
|
||||
u8 one;
|
||||
|
||||
u8 handle : 4;
|
||||
u8 reverser : 4;
|
||||
|
||||
u8 ats : 1;
|
||||
u8 close : 1;
|
||||
u8 button_a_soft : 1;
|
||||
u8 button_a_hard : 1;
|
||||
u8 button_b : 1;
|
||||
u8 button_c : 1;
|
||||
u8 : 2;
|
||||
|
||||
u8 start : 1;
|
||||
u8 select : 1;
|
||||
u8 dpad_up : 1;
|
||||
u8 dpad_down : 1;
|
||||
u8 dpad_left : 1;
|
||||
u8 dpad_right : 1;
|
||||
u8 : 2;
|
||||
};
|
||||
static_assert(sizeof(TrainConData_TrainMascon) == 4);
|
||||
#pragma pack(pop)
|
||||
|
||||
struct TrainDeviceState
|
||||
@@ -75,6 +101,7 @@ namespace usb_pad
|
||||
|
||||
void Reset();
|
||||
void UpdateHatSwitch() noexcept;
|
||||
void UpdateHandles(u8 max_power, u8 max_brake);
|
||||
|
||||
USBDevice dev{};
|
||||
USBDesc desc{};
|
||||
@@ -95,12 +122,24 @@ namespace usb_pad
|
||||
u8 power; // 255 is fully applied
|
||||
u8 brake; // 255 is fully applied
|
||||
u8 hatswitch; // direction
|
||||
u8 buttons; // active high
|
||||
u16 buttons; // active high
|
||||
} data = {};
|
||||
|
||||
// Master Controller
|
||||
const char* mc_handle[16] = {"TSB20", "TSB30", "TSB40", "TSE99", "TSA05", "TSA15", "TSA25", "TSA35", "TSA45", "TSA50", "TSA55", "TSA65", "TSA75", "TSA85", "TSA95", "TSB60"};
|
||||
const char* mc_reverser[3] = {"TSG00", "TSG50", "TSG99"};
|
||||
const char* mc_button_pressed[4] = {"TSY99", "TSX99", "TSZ99", "TSK99"};
|
||||
const char* mc_button_released[4] = {"TSY00", "TSX00", "TSZ00", "TSK00"};
|
||||
u8 power_notches;
|
||||
u8 brake_notches;
|
||||
|
||||
u16 prev_buttons;
|
||||
s8 last_handle = -1, handle = 0;
|
||||
s8 last_reverser = -1, reverser = 1;
|
||||
};
|
||||
|
||||
// Taito Densha Controllers as described at:
|
||||
// https://marcriera.github.io/ddgo-controller-docs/controllers/usb/
|
||||
// https://traincontrollerdb.marcriera.cat/hardware/#usb
|
||||
#define DEFINE_DCT_DEV_DESCRIPTOR(prefix, subclass, product) \
|
||||
static const uint8_t prefix##_dev_descriptor[] = { \
|
||||
/* bLength */ USB_DEVICE_DESC_SIZE, \
|
||||
@@ -185,4 +224,114 @@ namespace usb_pad
|
||||
// dct03_dev_descriptor
|
||||
DEFINE_DCT_DEV_DESCRIPTOR(dct03, 0xFF, 0x0007);
|
||||
|
||||
// ---- Train Mascon ----
|
||||
|
||||
static const uint8_t train_mascon_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x10, 0x01, // bcdUSB 1.10
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x08, // bMaxPacketSize0 8
|
||||
0x06, 0x1C, // idVendor 0x1C06
|
||||
0xA7, 0x77, // idProduct 0x77A7
|
||||
0x02, 0x02, // bcdDevice 2.02
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x03, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t train_mascon_config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x19, 0x00, // wTotalLength 25
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x04, // iConfiguration (String Index)
|
||||
0xA0, // bmAttributes Remote Wakeup
|
||||
0x32, // bMaxPower 100mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x00, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x08, 0x00, // wMaxPacketSize 8
|
||||
0x14, // bInterval 20 (unit depends on device speed)
|
||||
};
|
||||
|
||||
// ---- Master Controller ----
|
||||
// Implements a generic PL2303 adapter.
|
||||
// Replace with official OGCW-10001 descriptors when available.
|
||||
|
||||
static const uint8_t master_controller_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x10, 0x01, // bcdUSB 1.10
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0x7B, 0x06, // idVendor 0x067B
|
||||
0x03, 0x23, // idProduct 0x2303
|
||||
0x00, 0x03, // bcdDevice 3.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t master_controller_config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x27, 0x00, // wTotalLength 39
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x32, // bMaxPower 100mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x03, // bNumEndpoints 3
|
||||
0xFF, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x0A, 0x00, // wMaxPacketSize 10
|
||||
0x01, // bInterval 1 (unit depends on device speed)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x02, // bEndpointAddress (OUT/H2D)
|
||||
0x02, // bmAttributes (Bulk)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x00, // bInterval 0 (unit depends on device speed)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x83, // bEndpointAddress (IN/D2H)
|
||||
0x02, // bmAttributes (Bulk)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x00, // bInterval 0 (unit depends on device speed)
|
||||
};
|
||||
|
||||
} // namespace usb_pad
|
||||
|
||||
@@ -526,6 +526,7 @@ void VMManager::SetDefaultLoggingSettings(SettingsInterface& si)
|
||||
si.SetBoolValue("Logging", "EnableSystemConsole", false);
|
||||
si.SetBoolValue("Logging", "EnableFileLogging", true);
|
||||
si.SetBoolValue("Logging", "EnableTimestamps", true);
|
||||
si.SetBoolValue("Logging", "EnableEESIOInput", false);
|
||||
si.SetBoolValue("Logging", "EnableVerbose", false);
|
||||
si.SetBoolValue("Logging", "EnableEEConsole", false);
|
||||
si.SetBoolValue("Logging", "EnableIOPConsole", false);
|
||||
@@ -3747,3 +3748,15 @@ void VMManager::PollDiscordPresence()
|
||||
|
||||
Discord_RunCallbacks();
|
||||
}
|
||||
|
||||
bool VMManager::WriteBytesToEESIORXFIFO(const std::span<const u8> data)
|
||||
{
|
||||
if(ee_sio_rx_fifo.size() + data.size() > 1024)
|
||||
{
|
||||
Console.Warning("EE RX FIFO is full, not appending more bytes.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ee_sio_rx_fifo.insert(ee_sio_rx_fifo.end(), data.begin(), data.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -264,6 +265,9 @@ namespace VMManager
|
||||
/// Called when the rich presence string, provided by RetroAchievements, changes.
|
||||
void UpdateDiscordPresence(bool update_session_time);
|
||||
|
||||
/// Append bytes to the EE SIO RX FIFO. If it returns false, the FIFO is full and data is not inserted.
|
||||
bool WriteBytesToEESIORXFIFO(const std::span<const u8> data);
|
||||
|
||||
/// Internal callbacks, implemented in the emu core.
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user