Merge branch 'stenzek:master' into master
This commit is contained in:
commit
390e796ffc
|
@ -2,6 +2,7 @@ name: 🐧 Linux AppImage
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-x64-appimage-build:
|
||||
|
@ -14,7 +15,7 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/appimage/install-packages.sh
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
|
@ -66,7 +67,7 @@ jobs:
|
|||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
|
@ -85,7 +86,7 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/appimage/install-packages.sh
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
|
@ -137,7 +138,7 @@ jobs:
|
|||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDISABLE_SSE4=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
|
|
|
@ -11,6 +11,7 @@ on:
|
|||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-flatpak-build:
|
||||
|
@ -59,21 +60,21 @@ jobs:
|
|||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
scripts/generate-metainfo.sh scripts/flatpak
|
||||
cat scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
scripts/packaging/generate-metainfo.sh scripts/packaging/flatpak
|
||||
cat scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate AppStream XML
|
||||
run: flatpak-builder-lint appstream scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
run: flatpak-builder-lint appstream scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate Manifest
|
||||
run: flatpak-builder-lint manifest scripts/flatpak/org.duckstation.DuckStation.yaml
|
||||
run: flatpak-builder-lint manifest scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: duckstation-x64.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: scripts/flatpak/org.duckstation.DuckStation.yaml
|
||||
manifest-path: scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
|
@ -81,7 +82,7 @@ jobs:
|
|||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/flatpak/**/*.yaml') }}
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/packaging/flatpak/**/*.yaml') }}
|
||||
|
||||
- name: Validate Build
|
||||
run: |
|
||||
|
|
|
@ -2,6 +2,7 @@ name: 🍎 MacOS
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
macos-build:
|
||||
|
@ -13,8 +14,8 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Xcode 15.4
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.4.app
|
||||
- name: Use Xcode 16.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.1.app
|
||||
|
||||
- name: Install packages
|
||||
shell: bash
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
name: Automated Builds
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
|
|
@ -2,6 +2,7 @@ name: 💻 Windows
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
windows-x64-build:
|
||||
|
|
|
@ -42,10 +42,6 @@ if(LINUX OR BSD)
|
|||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
|
||||
# Release build optimizations for MSVC.
|
||||
if(MSVC)
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS")
|
||||
|
@ -59,14 +55,18 @@ if(MSVC)
|
|||
|
||||
# RelWithDebInfo is set to Ob1 instead of Ob2.
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_DEVEL}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_DEVEL}")
|
||||
|
||||
# Disable incremental linking in RelWithDebInfo.
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL}")
|
||||
|
||||
# COMDAT folding/remove unused functions.
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL} /OPT:REF /OPT:ICF")
|
||||
endif()
|
||||
|
||||
# Warning disables.
|
||||
|
|
|
@ -16,3 +16,17 @@ endif()
|
|||
if(APPLE)
|
||||
option(SKIP_POSTPROCESS_BUNDLE "Disable bundle post-processing, including Qt additions" OFF)
|
||||
endif()
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
|
||||
# Create the Devel build type based on RelWithDebInfo.
|
||||
set(CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the C compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the CXX compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used for the linker during DEVEL builds." FORCE)
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEVEL "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of modules during DEVEL builds." FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of shared libraries during DEVEL builds." FORCE)
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_DEVEL "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of static libraries during DEVEL builds." FORCE)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES "Devel")
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MODULE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_STATIC_LINKER_FLAGS_DEVEL)
|
||||
|
|
|
@ -9735,6 +9735,9 @@ SLES-02626:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -9754,6 +9757,9 @@ SLES-02627:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -9773,6 +9779,9 @@ SLES-02628:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -9792,6 +9801,9 @@ SLES-02630:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -9811,6 +9823,9 @@ SLES-02629:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -9833,6 +9848,9 @@ SLUS-00914:
|
|||
controllers:
|
||||
- AnalogController
|
||||
- DigitalController
|
||||
settings:
|
||||
dmaMaxSliceTicks: 100 # Stops large VRAM transfer DMA from blazing
|
||||
dmaHaltTicks: 200 # past the deferred CDROM async interrupt.
|
||||
metadata:
|
||||
publisher: "3DO"
|
||||
developer: "3DO"
|
||||
|
@ -15751,6 +15769,7 @@ SLPS-02300:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
metadata:
|
||||
publisher: "Capcom"
|
||||
developer: "Capcom Production Studio 4"
|
||||
|
@ -15772,6 +15791,7 @@ SLPM-80485:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
SLPM-87224:
|
||||
name: "Biohazard 3 - Last Escape (Japan) (Rev 1)"
|
||||
controllers:
|
||||
|
@ -15780,6 +15800,7 @@ SLPM-87224:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
metadata:
|
||||
publisher: "Capcom"
|
||||
developer: "Capcom Production Studio 4"
|
||||
|
@ -19208,6 +19229,7 @@ SLUS-01170:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- PlayStationMouse
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Atari / Hasbro Interactive"
|
||||
developer: "Supersonic Software Ltd"
|
||||
|
@ -19228,6 +19250,7 @@ SLES-02854:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- PlayStationMouse
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Atari / Hasbro Interactive"
|
||||
developer: "Supersonic Software Ltd"
|
||||
|
@ -113120,6 +113143,7 @@ SLUS-01003:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Electronic Arts / Infogrames"
|
||||
developer: "Eden Studios"
|
||||
|
@ -131665,6 +131689,7 @@ SCPS-45354:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
codes:
|
||||
- SCPS-45354
|
||||
- SCPS-45355
|
||||
|
@ -131688,6 +131713,7 @@ SLPS-01798:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Namco"
|
||||
developer: "Namco"
|
||||
|
@ -131708,6 +131734,7 @@ SCPS-45356:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
codes:
|
||||
- SCPS-45356
|
||||
- SLPS-01800
|
||||
|
@ -131733,6 +131760,7 @@ SLUS-00797:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Namco"
|
||||
developer: "Namco"
|
||||
|
@ -131753,6 +131781,7 @@ SLPS-91463:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Namco"
|
||||
developer: "Namco"
|
||||
|
@ -135716,6 +135745,7 @@ SLES-02529:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Eidos Interactive"
|
||||
|
@ -135738,6 +135768,7 @@ SLED-02541:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
SLES-02530:
|
||||
name: "Resident Evil 3 - Nemesis (France)"
|
||||
controllers:
|
||||
|
@ -135746,6 +135777,7 @@ SLES-02530:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Eidos Interactive"
|
||||
|
@ -135769,6 +135801,7 @@ SLES-02531:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Eidos Interactive"
|
||||
|
@ -135792,6 +135825,7 @@ SLES-02698:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Eidos Interactive"
|
||||
|
@ -135815,6 +135849,7 @@ SLES-02533:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Eidos Interactive"
|
||||
|
@ -135841,6 +135876,7 @@ SLES-02532:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Proein / Eidos Interactive"
|
||||
|
@ -135867,6 +135903,7 @@ SLUS-00923:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
metadata:
|
||||
publisher: "Capcom"
|
||||
developer: "Capcom Production Studio 4"
|
||||
|
@ -135888,6 +135925,7 @@ SLUS-90064:
|
|||
traits:
|
||||
- DisableWidescreen
|
||||
- ForcePGXPCPUMode # Fixes jitter in character models.
|
||||
- ForceRecompilerICache # Fixes hangs in CD code.
|
||||
SLPS-01974:
|
||||
name: "Restaurant Dream (Japan)"
|
||||
controllers:
|
||||
|
@ -136471,6 +136509,7 @@ SCES-01706:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
metadata:
|
||||
publisher: "Sony Computer Entertaiment Europe"
|
||||
developer: "Namco"
|
||||
|
@ -179398,6 +179437,7 @@ SLES-01907:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
libcrypt: true
|
||||
metadata:
|
||||
publisher: "Infogrames"
|
||||
|
@ -179421,6 +179461,7 @@ SLPS-02516:
|
|||
- AnalogController
|
||||
- DigitalController
|
||||
- NeGcon
|
||||
- JogCon
|
||||
codes:
|
||||
- SLPS-02516
|
||||
- SLPS-91467
|
||||
|
|
|
@ -82,4 +82,9 @@
|
|||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="$(Configuration.Contains(Devel))">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEVEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
|
@ -57,6 +57,14 @@
|
|||
<Configuration>Release-Clang</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Devel-Clang|ARM64">
|
||||
<Configuration>Devel-Clang</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Devel-Clang|x64">
|
||||
<Configuration>Devel-Clang</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
|
|
162
duckstation.sln
162
duckstation.sln
|
@ -67,6 +67,8 @@ Global
|
|||
DebugFast|x64 = DebugFast|x64
|
||||
DebugFast-Clang|ARM64 = DebugFast-Clang|ARM64
|
||||
DebugFast-Clang|x64 = DebugFast-Clang|x64
|
||||
Devel-Clang|ARM64 = Devel-Clang|ARM64
|
||||
Devel-Clang|x64 = Devel-Clang|x64
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release-Clang|ARM64 = Release-Clang|ARM64
|
||||
|
@ -79,6 +81,44 @@ Global
|
|||
ReleaseLTCG-Clang-SSE2|x64 = ReleaseLTCG-Clang-SSE2|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.Build.0 = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.Build.0 = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.Build.0 = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.ActiveCfg = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.Build.0 = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.ActiveCfg = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.Build.0 = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.Build.0 = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.Build.0 = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|x64.Build.0 = Debug|x64
|
||||
|
@ -96,6 +136,10 @@ Global
|
|||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|x64.ActiveCfg = Release|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -130,6 +174,10 @@ Global
|
|||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|x64.ActiveCfg = Release|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -164,6 +212,10 @@ Global
|
|||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|x64.ActiveCfg = Release|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -198,6 +250,10 @@ Global
|
|||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|x64.ActiveCfg = Release|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -232,6 +288,10 @@ Global
|
|||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|x64.ActiveCfg = Release|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -249,40 +309,6 @@ Global
|
|||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.Build.0 = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.Build.0 = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.Build.0 = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.ActiveCfg = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.Build.0 = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.ActiveCfg = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.Build.0 = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.Build.0 = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.Build.0 = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|x64.Build.0 = Debug|x64
|
||||
|
@ -300,6 +326,10 @@ Global
|
|||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|x64.ActiveCfg = Release|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -334,6 +364,10 @@ Global
|
|||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -368,6 +402,10 @@ Global
|
|||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|x64.ActiveCfg = Release|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -402,6 +440,10 @@ Global
|
|||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|x64.ActiveCfg = Release|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -436,6 +478,10 @@ Global
|
|||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|x64.ActiveCfg = Release|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -470,6 +516,10 @@ Global
|
|||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|x64.ActiveCfg = Release|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -497,6 +547,8 @@ Global
|
|||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release|x64.ActiveCfg = Release|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
|
@ -524,6 +576,10 @@ Global
|
|||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|x64.ActiveCfg = Release|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -551,6 +607,8 @@ Global
|
|||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release|x64.ActiveCfg = Release|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
|
@ -576,6 +634,9 @@ Global
|
|||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release|x64.ActiveCfg = Release|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
|
@ -605,6 +666,10 @@ Global
|
|||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|x64.ActiveCfg = Release|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -633,6 +698,8 @@ Global
|
|||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release|x64.ActiveCfg = Release|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
|
@ -661,6 +728,10 @@ Global
|
|||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|x64.ActiveCfg = Release|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -695,6 +766,10 @@ Global
|
|||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -729,6 +804,10 @@ Global
|
|||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|x64.ActiveCfg = Release|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -761,6 +840,9 @@ Global
|
|||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release|x64.ActiveCfg = Release|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
|
@ -788,6 +870,10 @@ Global
|
|||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|x64.ActiveCfg = Release|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -822,6 +908,10 @@ Global
|
|||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|x64.ActiveCfg = Release|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|x64.Build.0 = Release|x64
|
||||
|
@ -856,6 +946,10 @@ Global
|
|||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|x64.ActiveCfg = Release|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|x64.Build.0 = Release|x64
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
set(CMAKE_C_COMPILER /usr/bin/clang-16)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/clang++-16)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
|
@ -62,14 +62,14 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
|||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
HARFBUZZ=10.1.0
|
||||
LIBBACKTRACE=86885d14049fab06ef8a33aac51664230ca09200
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBPNG=1.6.44
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.1
|
||||
LIBZIP=1.11.2
|
||||
SDL2=2.30.9
|
||||
QT=6.8.0
|
||||
QT=6.8.1
|
||||
ZSTD=1.5.6
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
|
@ -116,7 +116,7 @@ if [ "$SKIP_HARFBUZZ" != true ]; then
|
|||
curl -C - -L -o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
|
@ -148,7 +148,7 @@ if [ "$SKIP_LIBZIP" != true ]; then
|
|||
curl -C - -L -O "https://github.com/nih-at/libzip/releases/download/v$LIBZIP/libzip-$LIBZIP.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
721e0e4e851073b508c243fd75eda04e4c5006158a900441de10ce274cc3b633 libzip-$LIBZIP.tar.xz
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
|
@ -170,12 +170,12 @@ if [ "$SKIP_QT" != true ]; then
|
|||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
1bad481710aa27f872de6c9f72651f89a6107f0077003d0ebfcc9fd15cba3c75 qtbase-everywhere-src-$QT.tar.xz
|
||||
595bf8557b91e1f8ebc726f1e09868a3c7e610ff5045068f2d4ea2428c49a5d4 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
cf7a593d5e520f8177240610d9e55d5b75b0887fe5f385554ff64377f1646199 qtsvg-everywhere-src-$QT.tar.xz
|
||||
403115d8268503c6cc6e43310c8ae28eb9e605072a5d04e4a2de8b6af39981f7 qttools-everywhere-src-$QT.tar.xz
|
||||
84bf2b67c243cd0c50a08acd7bfa9df2b1965028511815c1b6b65a0687437cb6 qttranslations-everywhere-src-$QT.tar.xz
|
||||
175758591638ebf1c6fbb66ac11c7fa0eb8d4ed52e9243cc59075d06a6a2060a qtwayland-everywhere-src-$QT.tar.xz
|
||||
40b14562ef3bd779bc0e0418ea2ae08fa28235f8ea6e8c0cb3bce1d6ad58dcaf qtbase-everywhere-src-$QT.tar.xz
|
||||
138cc2909aa98f5ff7283e36eb3936eb5e625d3ca3b4febae2ca21d8903dd237 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3d0de73596e36b2daa7c48d77c4426bb091752856912fba720215f756c560dd0 qtsvg-everywhere-src-$QT.tar.xz
|
||||
9d43d409be08b8681a0155a9c65114b69c9a3fc11aef6487bb7fdc5b283c432d qttools-everywhere-src-$QT.tar.xz
|
||||
635a6093e99152243b807de51077485ceadd4786d4acb135b9340b2303035a4a qttranslations-everywhere-src-$QT.tar.xz
|
||||
2226fbde4e2ddd12f8bf4b239c8f38fd706a54e789e63467dfddc77129eca203 qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
|
|
@ -37,16 +37,16 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
|||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
HARFBUZZ=10.1.0
|
||||
SDL2=2.30.9
|
||||
ZSTD=1.5.6
|
||||
LIBPNG=1.6.44
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.1
|
||||
FFMPEG=7.0.2
|
||||
LIBZIP=1.11.2
|
||||
FFMPEG=7.1
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.8.0
|
||||
QT=6.8.1
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
|
@ -73,22 +73,28 @@ CMAKE_ARCH_X64=-DCMAKE_OSX_ARCHITECTURES="x86_64"
|
|||
CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
# SBOM generation appears to be broken on MacOS, and I can't be arsed to debug it.
|
||||
CMAKE_COMMON_QT=(
|
||||
-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
-DQT_GENERATE_SBOM=OFF
|
||||
)
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
60c4da1d5b7f0aa8d158da48e8f8afa9773c1c8baa5d21974df61f1886b8ce8e libpng-$LIBPNG.tar.xz
|
||||
99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
721e0e4e851073b508c243fd75eda04e4c5006158a900441de10ce274cc3b633 libzip-$LIBZIP.tar.xz
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
24b574f71c87a763f50704bbb630cbe38298d544a1f890f099a4696b1d6beba4 SDL2-$SDL2.tar.gz
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
8646515b638a3ad303e23af6a3587734447cb8fc0a0c064ecdb8e95c4fd8b389 ffmpeg-$FFMPEG.tar.xz
|
||||
40973d44970dbc83ef302b0609f2e74982be2d85916dd2ee7472d30678a7abe6 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
1bad481710aa27f872de6c9f72651f89a6107f0077003d0ebfcc9fd15cba3c75 qtbase-everywhere-src-$QT.tar.xz
|
||||
595bf8557b91e1f8ebc726f1e09868a3c7e610ff5045068f2d4ea2428c49a5d4 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
cf7a593d5e520f8177240610d9e55d5b75b0887fe5f385554ff64377f1646199 qtsvg-everywhere-src-$QT.tar.xz
|
||||
403115d8268503c6cc6e43310c8ae28eb9e605072a5d04e4a2de8b6af39981f7 qttools-everywhere-src-$QT.tar.xz
|
||||
84bf2b67c243cd0c50a08acd7bfa9df2b1965028511815c1b6b65a0687437cb6 qttranslations-everywhere-src-$QT.tar.xz
|
||||
40b14562ef3bd779bc0e0418ea2ae08fa28235f8ea6e8c0cb3bce1d6ad58dcaf qtbase-everywhere-src-$QT.tar.xz
|
||||
138cc2909aa98f5ff7283e36eb3936eb5e625d3ca3b4febae2ca21d8903dd237 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3d0de73596e36b2daa7c48d77c4426bb091752856912fba720215f756c560dd0 qtsvg-everywhere-src-$QT.tar.xz
|
||||
9d43d409be08b8681a0155a9c65114b69c9a3fc11aef6487bb7fdc5b283c432d qttools-everywhere-src-$QT.tar.xz
|
||||
635a6093e99152243b807de51077485ceadd4786d4acb135b9340b2303035a4a qttranslations-everywhere-src-$QT.tar.xz
|
||||
e1351218d270db49c3dddcba04fb2153b09731ea3fa6830e423f5952f44585be cpuinfo-$CPUINFO.tar.gz
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
|
@ -301,7 +307,7 @@ patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
|||
// Platforminputcontext plugins if QtGui is in use
|
||||
EOF
|
||||
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
@ -312,7 +318,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
|||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}"
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
@ -323,7 +329,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
|||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
@ -334,7 +340,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
|||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_linguist=ON -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_linguist=ON -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
@ -345,7 +351,7 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
|||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}"
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
|
|
@ -46,14 +46,14 @@ echo INSTALLDIR=%INSTALLDIR%
|
|||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.0
|
||||
set QT=6.8.1
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.9
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.1
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.6
|
||||
|
@ -68,20 +68,20 @@ set DXCOMPILER=1.8.2407.12
|
|||
set DXAGILITY=1.614.1
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" "https://download.savannah.gnu.org/releases/freetype/freetype-%FREETYPE%.tar.gz" 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" f93ff7ec6f2fcb9242256976a7e6d1da2588b5e57a559fb71a025b74bd1f5539 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" 7d7571a1faa1898b69888716dfdea0e4d466f1a5cf518e6aa626df2242bbadbe || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b || goto error
|
||||
call :downloadfile "SDL2-%SDL2%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL2%/SDL2-%SDL2%.zip" ec855bcd815b4b63d0c958c42c2923311c656227d6e0c1ae1e721406d346444b || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c3b41915341d853b6374cf93f1fcced2c8e4be9360f29c656960e1d0d15046a3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 809081a7bdf7e48262fbe9437e4e756df6ad2649433e803c4040026e650d7c91 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 89f1ef4595f68c3d34c63a7c1c4ce475e701e103f0473f3fd0718a2e5234de6e || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 3f813f49d6d28c532dc4b104084f60ff382337f184698fcd6e70ab9efad977c1 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 91c33d9946279c9c613b02e52a33df610cc01d13ea6e321b4c4d8ee708b9a03e || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" e22d997bd15b795a176c8da62c8c1da0a674eb534e02f7c01ca507bf11bce0c3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 247a0a58039275a5a4fb499a600a90f66dc6e00321bb6f86a9b8d8020344d853 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 57bd332e5550ff70a852560c591b786b6ba587c5e41cb5ef91038d82db137ab9 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c65a89140f5d68137ffec67d631ec97002fb37077d9b4eb4ee45cbec39b1c38a || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 30a8e7773e1f274557e049a97f158b808f344247da03ae5240e4956c81d51cd5 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" c0e6fa52a62ba11efd30262290dc6970947aef32e0cc294ee50e9005ceac092a || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 6b2a43837005e1c23fdfee532b78f806863e412d2089b9c42b49ab08cbcd7665 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 8df152f4969b308546306c074628de761f0b80265de7de534e3822fab22d7535 || goto error
|
||||
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/pytorch/cpuinfo/archive/%CPUINFO%.zip" 13146ae7983d767a678dd01b0d6af591e77cec82babd41264b9164ab808d7d41 || goto error
|
||||
call :downloadfile "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
|
|
|
@ -44,14 +44,14 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
|||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.0
|
||||
set QT=6.8.1
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.9
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.1
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.6
|
||||
|
@ -66,20 +66,20 @@ set DXCOMPILER=1.8.2407.12
|
|||
set DXAGILITY=1.614.1
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" "https://download.savannah.gnu.org/releases/freetype/freetype-%FREETYPE%.tar.gz" 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" f93ff7ec6f2fcb9242256976a7e6d1da2588b5e57a559fb71a025b74bd1f5539 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" 7d7571a1faa1898b69888716dfdea0e4d466f1a5cf518e6aa626df2242bbadbe || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b || goto error
|
||||
call :downloadfile "SDL2-%SDL2%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL2%/SDL2-%SDL2%.zip" ec855bcd815b4b63d0c958c42c2923311c656227d6e0c1ae1e721406d346444b || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c3b41915341d853b6374cf93f1fcced2c8e4be9360f29c656960e1d0d15046a3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 809081a7bdf7e48262fbe9437e4e756df6ad2649433e803c4040026e650d7c91 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 89f1ef4595f68c3d34c63a7c1c4ce475e701e103f0473f3fd0718a2e5234de6e || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 3f813f49d6d28c532dc4b104084f60ff382337f184698fcd6e70ab9efad977c1 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 91c33d9946279c9c613b02e52a33df610cc01d13ea6e321b4c4d8ee708b9a03e || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" e22d997bd15b795a176c8da62c8c1da0a674eb534e02f7c01ca507bf11bce0c3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 247a0a58039275a5a4fb499a600a90f66dc6e00321bb6f86a9b8d8020344d853 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 57bd332e5550ff70a852560c591b786b6ba587c5e41cb5ef91038d82db137ab9 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c65a89140f5d68137ffec67d631ec97002fb37077d9b4eb4ee45cbec39b1c38a || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 30a8e7773e1f274557e049a97f158b808f344247da03ae5240e4956c81d51cd5 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" c0e6fa52a62ba11efd30262290dc6970947aef32e0cc294ee50e9005ceac092a || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 6b2a43837005e1c23fdfee532b78f806863e412d2089b9c42b49ab08cbcd7665 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 8df152f4969b308546306c074628de761f0b80265de7de534e3822fab22d7535 || goto error
|
||||
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/pytorch/cpuinfo/archive/%CPUINFO%.zip" 13146ae7983d767a678dd01b0d6af591e77cec82babd41264b9164ab808d7d41 || goto error
|
||||
call :downloadfile "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
|
|
|
@ -127,8 +127,8 @@ DEPLOY_PLATFORM_THEMES="1" \
|
|||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/duckstation-qt" ${EXTRA_LIBS_ARGS[@]} \
|
||||
--desktop-file="$ROOTDIR/scripts/org.duckstation.DuckStation.desktop" \
|
||||
--icon-file="$ROOTDIR/scripts/org.duckstation.DuckStation.png" \
|
||||
--desktop-file="$ROOTDIR/scripts/packaging/org.duckstation.DuckStation.desktop" \
|
||||
--icon-file="$ROOTDIR/scripts/packaging/org.duckstation.DuckStation.png" \
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
|
@ -26,7 +26,7 @@ build-options:
|
|||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/nih-at/libzip.git"
|
||||
commit: "9c8b818a1de143a4a8ee445351fb8f92115e33e1"
|
||||
commit: "64b62d6b1a686a1b0bac1b6b9dcb635be0499afb"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
|
@ -80,21 +80,21 @@ modules:
|
|||
- "-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld"
|
||||
sources:
|
||||
- type: dir
|
||||
path: ../..
|
||||
path: ../../..
|
||||
|
||||
post-install:
|
||||
# Manually copy desktop file/metadata, it's not done as part of the regular build.
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/org.duckstation.DuckStation.png"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/org.duckstation.DuckStation.png"
|
||||
"${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png"
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/org.duckstation.DuckStation.desktop"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/org.duckstation.DuckStation.desktop"
|
||||
"${FLATPAK_DEST}/share/applications/org.duckstation.DuckStation.desktop"
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/flatpak/org.duckstation.DuckStation.metainfo.xml"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml"
|
||||
"${FLATPAK_DEST}/share/metainfo/org.duckstation.DuckStation.metainfo.xml"
|
||||
|
||||
# Ensure ffmpeg-full mount point exists.
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
@ -4,6 +4,7 @@ add_executable(common-tests
|
|||
gsvector_yuvtorgb_test.cpp
|
||||
path_tests.cpp
|
||||
rectangle_tests.cpp
|
||||
sha256_tests.cpp
|
||||
string_tests.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<ClCompile Include="file_system_tests.cpp" />
|
||||
<ClCompile Include="path_tests.cpp" />
|
||||
<ClCompile Include="rectangle_tests.cpp" />
|
||||
<ClCompile Include="sha256_tests.cpp" />
|
||||
<ClCompile Include="string_tests.cpp" />
|
||||
<ClCompile Include="gsvector_yuvtorgb_test.cpp" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -8,5 +8,6 @@
|
|||
<ClCompile Include="path_tests.cpp" />
|
||||
<ClCompile Include="string_tests.cpp" />
|
||||
<ClCompile Include="gsvector_yuvtorgb_test.cpp" />
|
||||
<ClCompile Include="sha256_tests.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,34 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "common/sha256_digest.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(SHA256Digest, Simple)
|
||||
{
|
||||
// https://github.com/B-Con/crypto-algorithms/blob/master/sha256_test.c
|
||||
|
||||
static constexpr const char text1[] = "abc";
|
||||
static constexpr const char text2[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
static constexpr const char text3[] = "aaaaaaaaaa";
|
||||
|
||||
static constexpr SHA256Digest::Digest hash1 = {{0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
|
||||
0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
|
||||
0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}};
|
||||
static constexpr SHA256Digest::Digest hash2 = {{0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
|
||||
0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
|
||||
0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}};
|
||||
static constexpr SHA256Digest::Digest hash3 = {{0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
|
||||
0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
|
||||
0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0}};
|
||||
|
||||
ASSERT_EQ(SHA256Digest::GetDigest(text1, std::size(text1) - 1), hash1);
|
||||
ASSERT_EQ(SHA256Digest::GetDigest(text2, std::size(text2) - 1), hash2);
|
||||
|
||||
SHA256Digest ldigest;
|
||||
for (u32 i = 0; i < 100000; i++)
|
||||
ldigest.Update(text3, std::size(text3) - 1);
|
||||
|
||||
ASSERT_EQ(ldigest.Final(), hash3);
|
||||
}
|
|
@ -33,3 +33,41 @@ TEST(StringUtil, EllipsiseInPlace)
|
|||
StringUtil::EllipsiseInPlace(s, 10, "...");
|
||||
ASSERT_EQ(s, "Hello");
|
||||
}
|
||||
|
||||
TEST(StringUtil, Base64EncodeDecode)
|
||||
{
|
||||
struct TestCase
|
||||
{
|
||||
const char* hexString;
|
||||
const char* base64String;
|
||||
};
|
||||
static const TestCase testCases[] = {
|
||||
{"33326a6f646933326a68663937683732383368", "MzJqb2RpMzJqaGY5N2g3MjgzaA=="},
|
||||
{"32753965333268756979386672677537366967723839683432703075693132393065755c5d0931325c335c31323439303438753839333272",
|
||||
"MnU5ZTMyaHVpeThmcmd1NzZpZ3I4OWg0MnAwdWkxMjkwZXVcXQkxMlwzXDEyNDkwNDh1ODkzMnI="},
|
||||
{"3332726a33323738676838666233326830393233386637683938323139", "MzJyajMyNzhnaDhmYjMyaDA5MjM4ZjdoOTgyMTk="},
|
||||
{"9956967BE9C96E10B27FF8897A5B768A2F4B103CE934718D020FE6B5B770", "mVaWe+nJbhCyf/iJelt2ii9LEDzpNHGNAg/mtbdw"},
|
||||
{"BC94251814827A5D503D62D5EE6CBAB0FD55D2E2FCEDBB2261D6010084B95DD648766D8983F03AFA3908956D8201E26BB09FE52B515A61A9E"
|
||||
"1D3ADC207BD9E622128F22929CDED456B595A410F7168B0BA6370289E6291E38E47C18278561C79A7297C21D23C06BB2F694DC2F65FAAF994"
|
||||
"59E3FC14B1FA415A3320AF00ACE54C00BE",
|
||||
"vJQlGBSCel1QPWLV7my6sP1V0uL87bsiYdYBAIS5XdZIdm2Jg/A6+jkIlW2CAeJrsJ/"
|
||||
"lK1FaYanh063CB72eYiEo8ikpze1Fa1laQQ9xaLC6Y3AonmKR445HwYJ4Vhx5pyl8IdI8BrsvaU3C9l+q+ZRZ4/wUsfpBWjMgrwCs5UwAvg=="},
|
||||
{"192B42CB0F66F69BE8A5", "GStCyw9m9pvopQ=="},
|
||||
{"38ABD400F3BB6960EB60C056719B5362", "OKvUAPO7aWDrYMBWcZtTYg=="},
|
||||
{"776FAB27DC7F8DA86F298D55B69F8C278D53871F8CBCCF", "d2+rJ9x/jahvKY1Vtp+MJ41Thx+MvM8="},
|
||||
{"B1ED3EA2E35EE69C7E16707B05042A", "se0+ouNe5px+FnB7BQQq"},
|
||||
};
|
||||
|
||||
for (const TestCase& tc : testCases)
|
||||
{
|
||||
std::optional<std::vector<u8>> bytes = StringUtil::DecodeHex(tc.hexString);
|
||||
ASSERT_TRUE(bytes.has_value());
|
||||
|
||||
std::string encoded_b64 = StringUtil::EncodeBase64(bytes.value());
|
||||
ASSERT_EQ(encoded_b64, tc.base64String);
|
||||
|
||||
std::optional<std::vector<u8>> dbytes = StringUtil::DecodeBase64(tc.base64String);
|
||||
ASSERT_TRUE(dbytes.has_value());
|
||||
ASSERT_EQ(dbytes.value(), bytes.value());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,12 +50,16 @@ add_library(common
|
|||
settings_interface.h
|
||||
sha1_digest.cpp
|
||||
sha1_digest.h
|
||||
sha256_digest.cpp
|
||||
sha256_digest.h
|
||||
small_string.cpp
|
||||
small_string.h
|
||||
string_util.cpp
|
||||
string_util.h
|
||||
thirdparty/SmallVector.cpp
|
||||
thirdparty/SmallVector.h
|
||||
thirdparty/aes.cpp
|
||||
thirdparty/aes.h
|
||||
threading.cpp
|
||||
threading.h
|
||||
timer.cpp
|
||||
|
|
|
@ -19,7 +19,7 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
|||
Y_OnAssertFailed("Assertion failed: '" msg "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
#define DebugAssert(expr) \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
|
@ -41,7 +41,7 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
|||
// Kills the application, indicating a pure function call that should not have happened.
|
||||
#define PureCall() Y_OnPanicReached("PureCall encountered", __FUNCTION__, __FILE__, __LINE__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
// Kills the application, indicating that code that was never supposed to be reached has been executed.
|
||||
#define UnreachableCode() Y_OnPanicReached("Unreachable code reached", __FUNCTION__, __FILE__, __LINE__)
|
||||
#else
|
||||
|
|
|
@ -36,10 +36,12 @@
|
|||
<ClInclude Include="scoped_guard.h" />
|
||||
<ClInclude Include="settings_interface.h" />
|
||||
<ClInclude Include="sha1_digest.h" />
|
||||
<ClInclude Include="sha256_digest.h" />
|
||||
<ClInclude Include="small_string.h" />
|
||||
<ClInclude Include="heterogeneous_containers.h" />
|
||||
<ClInclude Include="binary_reader_writer.h" />
|
||||
<ClInclude Include="string_util.h" />
|
||||
<ClInclude Include="thirdparty\aes.h" />
|
||||
<ClInclude Include="thirdparty\SmallVector.h" />
|
||||
<ClInclude Include="thirdparty\StackWalker.h" />
|
||||
<ClInclude Include="threading.h" />
|
||||
|
@ -64,9 +66,11 @@
|
|||
<ClCompile Include="perf_scope.cpp" />
|
||||
<ClCompile Include="progress_callback.cpp" />
|
||||
<ClCompile Include="sha1_digest.cpp" />
|
||||
<ClCompile Include="sha256_digest.cpp" />
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
<ClCompile Include="binary_reader_writer.cpp" />
|
||||
<ClCompile Include="string_util.cpp" />
|
||||
<ClCompile Include="thirdparty\aes.cpp" />
|
||||
<ClCompile Include="thirdparty\SmallVector.cpp" />
|
||||
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
||||
<ClCompile Include="threading.cpp" />
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
<ClInclude Include="gsvector_nosimd.h" />
|
||||
<ClInclude Include="ryml_helpers.h" />
|
||||
<ClInclude Include="log_channels.h" />
|
||||
<ClInclude Include="sha256_digest.h" />
|
||||
<ClInclude Include="thirdparty\aes.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
|
@ -78,6 +80,8 @@
|
|||
<ClCompile Include="dynamic_library.cpp" />
|
||||
<ClCompile Include="binary_reader_writer.cpp" />
|
||||
<ClCompile Include="gsvector.cpp" />
|
||||
<ClCompile Include="sha256_digest.cpp" />
|
||||
<ClCompile Include="thirdparty\aes.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="bitfield.natvis" />
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
|
@ -923,7 +924,7 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* path, s32 retry_ms,
|
|||
// if there's a sharing violation, keep retrying
|
||||
if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION && retry_ms >= 0)
|
||||
{
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
while (retry_ms == 0 || timer.GetTimeMilliseconds() <= retry_ms)
|
||||
{
|
||||
Sleep(1);
|
||||
|
@ -2787,19 +2788,25 @@ bool FileSystem::SetPathCompression(const char* path, bool enable)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool SetLock(int fd, bool lock)
|
||||
static bool SetLock(int fd, bool lock, bool block, Error* error)
|
||||
{
|
||||
// We want to lock the whole file.
|
||||
const off_t offs = lseek(fd, 0, SEEK_CUR);
|
||||
if (offs < 0)
|
||||
{
|
||||
ERROR_LOG("lseek({}) failed: {}", fd, errno);
|
||||
if (error)
|
||||
error->SetErrno("lseek() failed: ", errno);
|
||||
else
|
||||
ERROR_LOG("lseek({}) failed: {}", fd, errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offs != 0 && lseek(fd, 0, SEEK_SET) < 0)
|
||||
{
|
||||
ERROR_LOG("lseek({}, 0) failed: {}", fd, errno);
|
||||
if (error)
|
||||
error->SetErrno("lseek(0) failed: ", errno);
|
||||
else
|
||||
ERROR_LOG("lseek({}, 0) failed: {}", fd, errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2807,38 +2814,66 @@ static bool SetLock(int fd, bool lock)
|
|||
bool res;
|
||||
for (;;)
|
||||
{
|
||||
res = (lockf(fd, lock ? F_LOCK : F_ULOCK, 0) == 0);
|
||||
res = (lockf(fd, lock ? (block ? F_TLOCK : F_LOCK) : F_ULOCK, 0) == 0);
|
||||
if (!res && errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
{
|
||||
if (error)
|
||||
error->SetErrno("lockf() failed: ", errno);
|
||||
else
|
||||
ERROR_LOG("lockf() for {} failed: {}", lock ? "lock" : "unlock", errno);
|
||||
}
|
||||
|
||||
if (lseek(fd, offs, SEEK_SET) < 0)
|
||||
Panic("Repositioning file descriptor after lock failed.");
|
||||
|
||||
if (!res)
|
||||
ERROR_LOG("lockf() for {} failed: {}", lock ? "lock" : "unlock", errno);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock::POSIXLock(int fd) : m_fd(fd)
|
||||
FileSystem::POSIXLock::POSIXLock() : m_fd(-1)
|
||||
{
|
||||
if (!SetLock(m_fd, true))
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock::POSIXLock(int fd, bool block, Error* error) : m_fd(fd)
|
||||
{
|
||||
if (!SetLock(m_fd, true, block, error))
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock::POSIXLock(std::FILE* fp) : m_fd(fileno(fp))
|
||||
FileSystem::POSIXLock::POSIXLock(std::FILE* fp, bool block, Error* error) : m_fd(fileno(fp))
|
||||
{
|
||||
if (!SetLock(m_fd, true))
|
||||
if (!SetLock(m_fd, true, block, error))
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock::POSIXLock(POSIXLock&& move)
|
||||
{
|
||||
m_fd = std::exchange(move.m_fd, -1);
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock::~POSIXLock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void FileSystem::POSIXLock::Unlock()
|
||||
{
|
||||
if (m_fd >= 0)
|
||||
SetLock(m_fd, false);
|
||||
{
|
||||
SetLock(m_fd, false, true, nullptr);
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
FileSystem::POSIXLock& FileSystem::POSIXLock::operator=(POSIXLock&& move)
|
||||
{
|
||||
m_fd = std::exchange(move.m_fd, -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -159,10 +159,19 @@ void DiscardAtomicRenamedFile(AtomicRenamedFile& file);
|
|||
class POSIXLock
|
||||
{
|
||||
public:
|
||||
POSIXLock(int fd);
|
||||
POSIXLock(std::FILE* fp);
|
||||
POSIXLock();
|
||||
POSIXLock(int fd, bool block = true, Error* error = nullptr);
|
||||
POSIXLock(std::FILE* fp, bool block = true, Error* error = nullptr);
|
||||
POSIXLock(POSIXLock&& move);
|
||||
POSIXLock(const POSIXLock&) = delete;
|
||||
~POSIXLock();
|
||||
|
||||
POSIXLock& operator=(POSIXLock&& move);
|
||||
POSIXLock& operator=(const POSIXLock&) = delete;
|
||||
|
||||
ALWAYS_INLINE bool IsLocked() const { return (m_fd >= 0); }
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
int m_fd;
|
||||
};
|
||||
|
|
|
@ -81,7 +81,7 @@ struct State
|
|||
std::vector<RegisteredCallback> callbacks;
|
||||
std::mutex callbacks_mutex;
|
||||
|
||||
Common::Timer::Value start_timestamp = Common::Timer::GetCurrentValue();
|
||||
Timer::Value start_timestamp = Timer::GetCurrentValue();
|
||||
|
||||
FileSystem::ManagedCFilePtr file_handle;
|
||||
|
||||
|
@ -146,8 +146,7 @@ const std::array<const char*, static_cast<size_t>(Log::Channel::MaxCount)>& Log:
|
|||
|
||||
float Log::GetCurrentMessageTime()
|
||||
{
|
||||
return static_cast<float>(
|
||||
Common::Timer::ConvertValueToSeconds(Common::Timer::GetCurrentValue() - s_state.start_timestamp));
|
||||
return static_cast<float>(Timer::ConvertValueToSeconds(Timer::GetCurrentValue() - s_state.start_timestamp));
|
||||
}
|
||||
|
||||
bool Log::AreTimestampsEnabled()
|
||||
|
@ -377,7 +376,7 @@ void Log::DebugOutputLogCallback(void* pUserParam, MessageCategory cat, const ch
|
|||
if (message.empty())
|
||||
return;
|
||||
|
||||
static constexpr int logPriority[static_cast<size_t>(Level::Count)] = {
|
||||
static constexpr int logPriority[static_cast<size_t>(Level::MaxCount)] = {
|
||||
ANDROID_LOG_INFO, // None
|
||||
ANDROID_LOG_ERROR, // Error
|
||||
ANDROID_LOG_WARN, // Warning
|
||||
|
|
|
@ -195,7 +195,7 @@ ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, L
|
|||
#define VERBOSE_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, __VA_ARGS__)
|
||||
#define DEV_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Dev, __VA_ARGS__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
#define DEBUG_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Debug, __VA_ARGS__)
|
||||
#define TRACE_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Trace, __VA_ARGS__)
|
||||
#else
|
||||
|
@ -216,7 +216,7 @@ ALWAYS_INLINE static void FastWrite(Channel channel, const char* functionName, L
|
|||
#define VERBOSE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, Log::Color::colour, __VA_ARGS__)
|
||||
#define DEV_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Dev, Log::Color::colour, __VA_ARGS__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
#define DEBUG_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Debug, Log::Color::colour, __VA_ARGS__)
|
||||
#define TRACE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Trace, Log::Color::colour,__VA_ARGS__)
|
||||
#else
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#define ENUMERATE_LOG_CHANNELS(X) \
|
||||
X(Achievements) \
|
||||
X(AnalogController) \
|
||||
X(AnalogJoystick) \
|
||||
X(AudioStream) \
|
||||
X(AutoUpdaterDialog) \
|
||||
X(BIOS) \
|
||||
|
@ -16,7 +14,7 @@
|
|||
X(Cheats) \
|
||||
X(CodeCache) \
|
||||
X(CompressHelpers) \
|
||||
X(ControllerBindingWidget) \
|
||||
X(Controller) \
|
||||
X(CubebAudioStream) \
|
||||
X(CueParser) \
|
||||
X(DInputSource) \
|
||||
|
@ -27,17 +25,12 @@
|
|||
X(FullscreenUI) \
|
||||
X(GDBProtocol) \
|
||||
X(GPU) \
|
||||
X(GPUBackend) \
|
||||
X(GPUDevice) \
|
||||
X(GPUDump) \
|
||||
X(GPUShaderCache) \
|
||||
X(GPUTextureCache) \
|
||||
X(GPU_HW) \
|
||||
X(GPU_SW) \
|
||||
X(GPU_SW_Rasterizer) \
|
||||
X(GPU_HW) \
|
||||
X(GameDatabase) \
|
||||
X(GameList) \
|
||||
X(GunCon) \
|
||||
X(HTTPDownloader) \
|
||||
X(Host) \
|
||||
X(ImGuiFullscreen) \
|
||||
|
@ -45,19 +38,16 @@
|
|||
X(Image) \
|
||||
X(InputManager) \
|
||||
X(InterruptController) \
|
||||
X(Justifier) \
|
||||
X(Log) \
|
||||
X(MDEC) \
|
||||
X(MediaCapture) \
|
||||
X(MemMap) \
|
||||
X(MemoryCard) \
|
||||
X(Multitap) \
|
||||
X(NeGconRumble) \
|
||||
X(PCDrv) \
|
||||
X(Pad) \
|
||||
X(PerfMon) \
|
||||
X(PlatformMisc) \
|
||||
X(PlayStationMouse) \
|
||||
X(PostProcessing) \
|
||||
X(ProgressCallback) \
|
||||
X(ReShadeFXShader) \
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "sha1_digest.h"
|
||||
#include "assert.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
@ -162,22 +163,7 @@ void SHA1Digest::Reset()
|
|||
|
||||
std::string SHA1Digest::DigestToString(const std::span<const u8, DIGEST_SIZE> digest)
|
||||
{
|
||||
std::string ret;
|
||||
ret.reserve(DIGEST_SIZE * 2);
|
||||
for (u32 i = 0; i < DIGEST_SIZE; i++)
|
||||
{
|
||||
u8 nibble = digest[i] >> 4;
|
||||
if (nibble >= 0xA)
|
||||
ret.push_back('A' + (nibble - 0xA));
|
||||
else
|
||||
ret.push_back('0' + nibble);
|
||||
nibble = digest[i] & 0xF;
|
||||
if (nibble >= 0xA)
|
||||
ret.push_back('A' + (nibble - 0xA));
|
||||
else
|
||||
ret.push_back('0' + nibble);
|
||||
}
|
||||
return ret;
|
||||
return StringUtil::EncodeHex<u8>(digest);
|
||||
}
|
||||
|
||||
std::array<u8, SHA1Digest::DIGEST_SIZE> SHA1Digest::GetDigest(const void* data, size_t len)
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
// Based on https://github.com/B-Con/crypto-algorithms/blob/master/sha256.c
|
||||
// By Brad Conte (brad AT bradconte.com)
|
||||
|
||||
#include "sha256_digest.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
SHA256Digest::SHA256Digest()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
std::string SHA256Digest::DigestToString(const std::span<const u8, DIGEST_SIZE> digest)
|
||||
{
|
||||
return StringUtil::EncodeHex<u8>(digest);
|
||||
}
|
||||
|
||||
SHA256Digest::Digest SHA256Digest::GetDigest(const void* data, size_t len)
|
||||
{
|
||||
Digest ret;
|
||||
SHA256Digest digest;
|
||||
digest.Update(data, len);
|
||||
digest.Final(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SHA256Digest::Digest SHA256Digest::GetDigest(std::span<const u8> data)
|
||||
{
|
||||
Digest ret;
|
||||
SHA256Digest digest;
|
||||
digest.Update(data);
|
||||
digest.Final(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
|
||||
|
||||
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
|
||||
#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
|
||||
#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
|
||||
|
||||
static constexpr std::array<u32, 64> k = {
|
||||
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}};
|
||||
|
||||
void SHA256Digest::TransformBlock()
|
||||
{
|
||||
std::array<u32, 64> m;
|
||||
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (m_block[j] << 24) | (m_block[j + 1] << 16) | (m_block[j + 2] << 8) | (m_block[j + 3]);
|
||||
for (; i < 64; ++i)
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
||||
u32 a = m_state[0];
|
||||
u32 b = m_state[1];
|
||||
u32 c = m_state[2];
|
||||
u32 d = m_state[3];
|
||||
u32 e = m_state[4];
|
||||
u32 f = m_state[5];
|
||||
u32 g = m_state[6];
|
||||
u32 h = m_state[7];
|
||||
|
||||
for (i = 0; i < 64; ++i)
|
||||
{
|
||||
u32 t1 = h + EP1(e) + CH(e, f, g) + k[i] + m[i];
|
||||
u32 t2 = EP0(a) + MAJ(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
m_state[0] += a;
|
||||
m_state[1] += b;
|
||||
m_state[2] += c;
|
||||
m_state[3] += d;
|
||||
m_state[4] += e;
|
||||
m_state[5] += f;
|
||||
m_state[6] += g;
|
||||
m_state[7] += h;
|
||||
}
|
||||
|
||||
void SHA256Digest::Reset()
|
||||
{
|
||||
m_block_length = 0;
|
||||
m_bit_length = 0;
|
||||
m_state[0] = 0x6a09e667;
|
||||
m_state[1] = 0xbb67ae85;
|
||||
m_state[2] = 0x3c6ef372;
|
||||
m_state[3] = 0xa54ff53a;
|
||||
m_state[4] = 0x510e527f;
|
||||
m_state[5] = 0x9b05688c;
|
||||
m_state[6] = 0x1f83d9ab;
|
||||
m_state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void SHA256Digest::Update(std::span<const u8> data)
|
||||
{
|
||||
const size_t len = data.size();
|
||||
for (size_t pos = 0; pos < len;)
|
||||
{
|
||||
const u32 copy_len = static_cast<u32>(std::min<size_t>(len - pos, BLOCK_SIZE - m_block_length));
|
||||
std::memcpy(&m_block[m_block_length], &data[pos], copy_len);
|
||||
m_block_length += copy_len;
|
||||
pos += copy_len;
|
||||
|
||||
if (m_block_length == BLOCK_SIZE)
|
||||
{
|
||||
TransformBlock();
|
||||
m_bit_length += 512;
|
||||
m_block_length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHA256Digest::Update(const void* data, size_t len)
|
||||
{
|
||||
Update(std::span<const u8>(static_cast<const u8*>(data), len));
|
||||
}
|
||||
|
||||
void SHA256Digest::Final(std::span<u8, DIGEST_SIZE> digest)
|
||||
{
|
||||
// Pad whatever data is left in the buffer.
|
||||
if (m_block_length < 56)
|
||||
{
|
||||
size_t i = m_block_length;
|
||||
m_block[i++] = 0x80;
|
||||
while (i < 56)
|
||||
m_block[i++] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i = m_block_length;
|
||||
m_block[i++] = 0x80;
|
||||
while (i < 64)
|
||||
m_block[i++] = 0x00;
|
||||
TransformBlock();
|
||||
m_block = {};
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
m_bit_length += m_block_length * 8;
|
||||
m_block[63] = static_cast<u8>(m_bit_length);
|
||||
m_block[62] = static_cast<u8>(m_bit_length >> 8);
|
||||
m_block[61] = static_cast<u8>(m_bit_length >> 16);
|
||||
m_block[60] = static_cast<u8>(m_bit_length >> 24);
|
||||
m_block[59] = static_cast<u8>(m_bit_length >> 32);
|
||||
m_block[58] = static_cast<u8>(m_bit_length >> 40);
|
||||
m_block[57] = static_cast<u8>(m_bit_length >> 48);
|
||||
m_block[56] = static_cast<u8>(m_bit_length >> 56);
|
||||
TransformBlock();
|
||||
|
||||
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||
// reverse all the bytes when copying the final state to the output hash.
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
digest[i] = (m_state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 4] = (m_state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 8] = (m_state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 12] = (m_state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 16] = (m_state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 20] = (m_state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 24] = (m_state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
digest[i + 28] = (m_state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
||||
|
||||
SHA256Digest::Digest SHA256Digest::Final()
|
||||
{
|
||||
Digest ret;
|
||||
Final(ret);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <array>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
class SHA256Digest
|
||||
{
|
||||
public:
|
||||
enum : u32
|
||||
{
|
||||
DIGEST_SIZE = 32,
|
||||
BLOCK_SIZE = 64,
|
||||
};
|
||||
|
||||
using Digest = std::array<u8, DIGEST_SIZE>;
|
||||
|
||||
SHA256Digest();
|
||||
|
||||
void Update(const void* data, size_t len);
|
||||
void Update(std::span<const u8> data);
|
||||
void Final(std::span<u8, DIGEST_SIZE> digest);
|
||||
Digest Final();
|
||||
void Reset();
|
||||
|
||||
static std::string DigestToString(const std::span<const u8, DIGEST_SIZE> digest);
|
||||
|
||||
static Digest GetDigest(const void* data, size_t len);
|
||||
static Digest GetDigest(std::span<const u8> data);
|
||||
|
||||
private:
|
||||
void TransformBlock();
|
||||
|
||||
u64 m_bit_length = 0;
|
||||
std::array<u32, 8> m_state = {};
|
||||
u32 m_block_length = 0;
|
||||
std::array<u8, BLOCK_SIZE> m_block = {};
|
||||
};
|
|
@ -506,6 +506,26 @@ std::wstring SmallStringBase::wstring() const
|
|||
|
||||
#endif
|
||||
|
||||
std::span<const char> SmallStringBase::cspan() const
|
||||
{
|
||||
return std::span<const char>(m_buffer, m_length);
|
||||
}
|
||||
|
||||
std::span<char> SmallStringBase::span()
|
||||
{
|
||||
return std::span<char>(m_buffer, m_length);
|
||||
}
|
||||
|
||||
std::span<const u8> SmallStringBase::cbspan() const
|
||||
{
|
||||
return std::span<const u8>(reinterpret_cast<const u8*>(m_buffer), m_length);
|
||||
}
|
||||
|
||||
std::span<u8> SmallStringBase::bspan()
|
||||
{
|
||||
return std::span<u8>(reinterpret_cast<u8*>(m_buffer), m_length);
|
||||
}
|
||||
|
||||
void SmallStringBase::vformat(fmt::string_view fmt, fmt::format_args args)
|
||||
{
|
||||
clear();
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
|
@ -207,10 +208,18 @@ public:
|
|||
std::wstring wstring() const;
|
||||
#endif
|
||||
|
||||
// span creators
|
||||
std::span<const char> cspan() const;
|
||||
std::span<char> span();
|
||||
std::span<const u8> cbspan() const;
|
||||
std::span<u8> bspan();
|
||||
|
||||
// accessor operators
|
||||
ALWAYS_INLINE operator const char*() const { return c_str(); }
|
||||
ALWAYS_INLINE operator char*() { return data(); }
|
||||
ALWAYS_INLINE operator std::string_view() const { return view(); }
|
||||
ALWAYS_INLINE operator std::span<const char>() const { return cspan(); }
|
||||
ALWAYS_INLINE operator std::span<char>() { return span(); }
|
||||
|
||||
// comparative operators
|
||||
ALWAYS_INLINE bool operator==(const char* str) const { return equals(str); }
|
||||
|
|
|
@ -197,6 +197,107 @@ std::string StringUtil::EncodeHex(const void* data, size_t length)
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t StringUtil::EncodeBase64(const std::span<char> dest, const std::span<const u8> data)
|
||||
{
|
||||
const size_t expected_length = EncodedBase64Length(data);
|
||||
Assert(dest.size() <= expected_length);
|
||||
|
||||
static constexpr std::array<char, 64> table = {
|
||||
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
|
||||
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}};
|
||||
|
||||
const size_t dataLength = data.size();
|
||||
size_t dest_pos = 0;
|
||||
|
||||
for (size_t i = 0; i < dataLength;)
|
||||
{
|
||||
const size_t bytes_in_sequence = std::min<size_t>(dataLength - i, 3);
|
||||
switch (bytes_in_sequence)
|
||||
{
|
||||
case 1:
|
||||
dest[dest_pos++] = table[(data[i] >> 2) & 63];
|
||||
dest[dest_pos++] = table[(data[i] & 3) << 4];
|
||||
dest[dest_pos++] = '=';
|
||||
dest[dest_pos++] = '=';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dest[dest_pos++] = table[(data[i] >> 2) & 63];
|
||||
dest[dest_pos++] = table[((data[i] & 3) << 4) | ((data[i + 1] >> 4) & 15)];
|
||||
dest[dest_pos++] = table[(data[i + 1] & 15) << 2];
|
||||
dest[dest_pos++] = '=';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dest[dest_pos++] = table[(data[i] >> 2) & 63];
|
||||
dest[dest_pos++] = table[((data[i] & 3) << 4) | ((data[i + 1] >> 4) & 15)];
|
||||
dest[dest_pos++] = table[((data[i + 1] & 15) << 2) | ((data[i + 2] >> 6) & 3)];
|
||||
dest[dest_pos++] = table[data[i + 2] & 63];
|
||||
break;
|
||||
|
||||
DefaultCaseIsUnreachable();
|
||||
}
|
||||
|
||||
i += bytes_in_sequence;
|
||||
}
|
||||
|
||||
DebugAssert(dest_pos == expected_length);
|
||||
return dest_pos;
|
||||
}
|
||||
|
||||
size_t StringUtil::DecodeBase64(const std::span<u8> data, const std::string_view str)
|
||||
{
|
||||
static constexpr std::array<u8, 128> table = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55,
|
||||
56, 57, 58, 59, 60, 61, 64, 64, 64, 0, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64};
|
||||
|
||||
const size_t str_length = str.length();
|
||||
if ((str_length % 4) != 0)
|
||||
return 0;
|
||||
|
||||
size_t data_pos = 0;
|
||||
for (size_t i = 0; i < str_length;)
|
||||
{
|
||||
const u8 byte1 = table[str[i++] & 0x7F];
|
||||
const u8 byte2 = table[str[i++] & 0x7F];
|
||||
const u8 byte3 = table[str[i++] & 0x7F];
|
||||
const u8 byte4 = table[str[i++] & 0x7F];
|
||||
|
||||
if (byte1 == 64 || byte2 == 64 || byte3 == 64 || byte4 == 64)
|
||||
break;
|
||||
|
||||
data[data_pos++] = (byte1 << 2) | (byte2 >> 4);
|
||||
if (str[i - 2] != '=')
|
||||
data[data_pos++] = ((byte2 << 4) | (byte3 >> 2));
|
||||
if (str[i - 1] != '=')
|
||||
data[data_pos++] = ((byte3 << 6) | byte4);
|
||||
}
|
||||
|
||||
return data_pos;
|
||||
}
|
||||
|
||||
std::optional<std::vector<u8>> StringUtil::DecodeBase64(const std::string_view str)
|
||||
{
|
||||
std::vector<u8> ret;
|
||||
const size_t len = DecodedBase64Length(str);
|
||||
ret.resize(len);
|
||||
if (DecodeBase64(ret, str) != len)
|
||||
ret = {};
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string StringUtil::EncodeBase64(const std::span<u8> data)
|
||||
{
|
||||
std::string ret;
|
||||
ret.resize(EncodedBase64Length(data));
|
||||
ret.resize(EncodeBase64(ret, data));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string_view StringUtil::StripWhitespace(const std::string_view str)
|
||||
{
|
||||
std::string_view::size_type start = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
@ -22,9 +23,6 @@
|
|||
#if !defined(_MSC_VER)
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#ifdef __APPLE__
|
||||
#include <Availability.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace StringUtil {
|
||||
|
@ -175,8 +173,6 @@ inline std::optional<T> FromChars(const std::string_view str, std::string_view*
|
|||
template<typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
|
||||
inline std::string ToChars(T value, int base = 10)
|
||||
{
|
||||
// to_chars() requires macOS 10.15+.
|
||||
#if !defined(__APPLE__) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
|
||||
constexpr size_t MAX_SIZE = 32;
|
||||
char buf[MAX_SIZE];
|
||||
std::string ret;
|
||||
|
@ -186,12 +182,6 @@ inline std::string ToChars(T value, int base = 10)
|
|||
ret.append(buf, result.ptr - buf);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
std::ostringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss << std::setbase(base) << value;
|
||||
return ss.str();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
|
||||
|
@ -260,6 +250,54 @@ ALWAYS_INLINE static bool IsHexDigit(T ch)
|
|||
(ch >= static_cast<T>('0') && ch <= static_cast<T>('9')));
|
||||
}
|
||||
|
||||
/// Returns a byte array from the provided hex string, computed at compile-time.
|
||||
template<size_t Length>
|
||||
static constexpr std::array<u8, Length> ParseFixedHexString(const char str[])
|
||||
{
|
||||
std::array<u8, Length> h{};
|
||||
for (int i = 0; str[i] != '\0'; i++)
|
||||
{
|
||||
u8 nibble = 0;
|
||||
char ch = str[i];
|
||||
if (ch >= '0' && ch <= '9')
|
||||
nibble = str[i] - '0';
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
nibble = 0xA + (str[i] - 'a');
|
||||
else if (ch >= 'A' && ch <= 'Z')
|
||||
nibble = 0xA + (str[i] - 'A');
|
||||
|
||||
h[i / 2] |= nibble << (((i & 1) ^ 1) * 4);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/// Encode/decode Base64 buffers.
|
||||
static constexpr size_t DecodedBase64Length(const std::string_view str)
|
||||
{
|
||||
// Should be a multiple of 4.
|
||||
const size_t str_length = str.length();
|
||||
if ((str_length % 4) != 0)
|
||||
return 0;
|
||||
|
||||
// Reverse padding.
|
||||
size_t padding = 0;
|
||||
if (str.length() >= 2)
|
||||
{
|
||||
padding += static_cast<size_t>(str[str_length - 1] == '=');
|
||||
padding += static_cast<size_t>(str[str_length - 2] == '=');
|
||||
}
|
||||
|
||||
return (str_length / 4) * 3 - padding;
|
||||
}
|
||||
static constexpr size_t EncodedBase64Length(const std::span<const u8> data)
|
||||
{
|
||||
return ((data.size() + 2) / 3) * 4;
|
||||
}
|
||||
size_t DecodeBase64(const std::span<u8> data, const std::string_view str);
|
||||
size_t EncodeBase64(const std::span<char> dest, const std::span<const u8> data);
|
||||
std::string EncodeBase64(const std::span<u8> data);
|
||||
std::optional<std::vector<u8>> DecodeBase64(const std::string_view str);
|
||||
|
||||
/// StartsWith/EndsWith variants which aren't case sensitive.
|
||||
ALWAYS_INLINE static bool StartsWithNoCase(const std::string_view str, const std::string_view prefix)
|
||||
{
|
||||
|
|
|
@ -183,7 +183,7 @@ protected:
|
|||
/// NewSize.
|
||||
bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
|
||||
// Past the end.
|
||||
if (LLVM_LIKELY(!isReferenceToStorage(Elt)))
|
||||
if (!isReferenceToStorage(Elt)) [[likely]]
|
||||
return true;
|
||||
|
||||
// Return false if Elt will be destroyed by shrinking.
|
||||
|
@ -946,7 +946,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
|
||||
if (LLVM_UNLIKELY(this->size() >= this->capacity()))
|
||||
if (this->size() >= this->capacity()) [[unlikely]]
|
||||
return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
|
||||
|
||||
::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
/*********************************************************************
|
||||
* Filename: aes.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding AES implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
static constexpr uint32_t AES_BLOCK_SIZE = 16; // AES operates on 16 bytes at a time
|
||||
static constexpr uint32_t AES_KEY_SCHEDULE_SIZE = 60;
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
///////////////////
|
||||
// AES
|
||||
///////////////////
|
||||
// Key setup must be done before any AES en/de-cryption functions can be used.
|
||||
void aes_key_setup(const uint8_t key[], // The key, must be 128, 192, or 256 bits
|
||||
uint32_t w[], // Output key schedule to be used later
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_encrypt(const uint8_t in[], // 16 bytes of plaintext
|
||||
uint8_t out[], // 16 bytes of ciphertext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
void aes_decrypt(const uint8_t in[], // 16 bytes of ciphertext
|
||||
uint8_t out[], // 16 bytes of plaintext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize); // Bit length of the key, 128, 192, or 256
|
||||
|
||||
///////////////////
|
||||
// AES - CBC
|
||||
///////////////////
|
||||
bool aes_encrypt_cbc(const uint8_t in[], // Plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
uint8_t out[], // Ciphertext, same length as plaintext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const uint8_t iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
bool aes_decrypt_cbc(const uint8_t in[], // Ciphertext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
uint8_t out[], // Plaintext, same length as ciphertext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const uint8_t iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
#if 0
|
||||
// Disabled since it's not being used.
|
||||
// Only output the CBC-MAC of the input.
|
||||
bool aes_encrypt_cbc_mac(const uint8_t in[], // plaintext
|
||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||
uint8_t out[], // Output MAC
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const uint8_t iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CTR
|
||||
///////////////////
|
||||
void aes_increment_iv(uint8_t iv[], // Must be a multiple of AES_BLOCK_SIZE
|
||||
int counter_size); // Bytes of the IV used for counting (low end)
|
||||
|
||||
void aes_encrypt_ctr(const uint8_t in[], // Plaintext
|
||||
size_t in_len, // Any byte length
|
||||
uint8_t out[], // Ciphertext, same length as plaintext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const uint8_t iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
void aes_decrypt_ctr(const uint8_t in[], // Ciphertext
|
||||
size_t in_len, // Any byte length
|
||||
uint8_t out[], // Plaintext, same length as ciphertext
|
||||
const uint32_t key[], // From the key setup
|
||||
int keysize, // Bit length of the key, 128, 192, or 256
|
||||
const uint8_t iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||
|
||||
///////////////////
|
||||
// AES - CCM
|
||||
///////////////////
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
bool aes_encrypt_ccm(
|
||||
const uint8_t plaintext[], // IN - Plaintext.
|
||||
uint32_t plaintext_len, // IN - Plaintext length.
|
||||
const uint8_t associated_data[], // IN - Associated Data included in authentication, but not encryption.
|
||||
unsigned short associated_data_len, // IN - Associated Data length in bytes.
|
||||
const uint8_t nonce[], // IN - The Nonce to be used for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
uint8_t ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
|
||||
uint32_t* ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
|
||||
uint32_t mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
|
||||
const uint8_t key[], // IN - The AES key for encryption.
|
||||
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
|
||||
|
||||
// Returns True if the input parameters do not violate any constraint.
|
||||
// Use mac_auth to ensure decryption/validation was preformed correctly.
|
||||
// If authentication does not succeed, the plaintext is zeroed out. To overwride
|
||||
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
|
||||
// authentication enabled (mac_auth != NULL) and make a second call to that
|
||||
// ignores authentication explicitly if the first call failes.
|
||||
bool aes_decrypt_ccm(
|
||||
const uint8_t ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
|
||||
uint32_t ciphertext_len, // IN - Ciphertext length in bytes.
|
||||
const uint8_t assoc[], // IN - The Associated Data, required for authentication.
|
||||
unsigned short assoc_len, // IN - Associated Data length in bytes.
|
||||
const uint8_t nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
|
||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||
uint8_t plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len -
|
||||
// mac_len.
|
||||
uint32_t* plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
|
||||
uint32_t mac_len, // IN - The length of the MAC that was calculated.
|
||||
int* mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the
|
||||
// authentication.
|
||||
const uint8_t key[], // IN - The AES key for decryption.
|
||||
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
|
||||
#endif
|
|
@ -15,8 +15,6 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static double s_counter_frequency;
|
||||
|
@ -399,5 +397,3 @@ void Timer::NanoSleep(std::uint64_t ns)
|
|||
nanosleep(&ts, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Common {
|
||||
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
|
@ -47,5 +45,3 @@ public:
|
|||
private:
|
||||
Value m_tvStartValue;
|
||||
};
|
||||
|
||||
} // namespace Common
|
|
@ -81,6 +81,8 @@ add_library(core
|
|||
imgui_overlays.h
|
||||
interrupt_controller.cpp
|
||||
interrupt_controller.h
|
||||
jogcon.cpp
|
||||
jogcon.h
|
||||
justifier.cpp
|
||||
justifier.h
|
||||
mdec.cpp
|
||||
|
@ -145,7 +147,7 @@ if(CPU_ARCH_X64)
|
|||
cpu_recompiler_x64.h
|
||||
)
|
||||
target_link_libraries(core PRIVATE xbyak)
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
if(CMAKE_BUILD_TYPE MATCHES "Debug|Devel")
|
||||
target_link_libraries(core PRIVATE zydis)
|
||||
endif()
|
||||
message(STATUS "Building x64 recompiler.")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
LOG_CHANNEL(AnalogController);
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
AnalogController::AnalogController(u32 index) : Controller(index)
|
||||
{
|
||||
|
@ -416,7 +416,7 @@ void AnalogController::UpdateHostVibration()
|
|||
hvalues[motor] = (state != 0) ? static_cast<float>(strength / 65535.0) : 0.0f;
|
||||
}
|
||||
|
||||
WARNING_LOG("Set small to {}, large to {}", hvalues[SmallMotor], hvalues[LargeMotor]);
|
||||
DEV_LOG("Set small motor to {}, large motor to {}", hvalues[SmallMotor], hvalues[LargeMotor]);
|
||||
InputManager::SetPadVibrationIntensity(m_index, hvalues[LargeMotor], hvalues[SmallMotor]);
|
||||
}
|
||||
|
||||
|
@ -621,7 +621,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
|||
m_status_byte = 0x5A;
|
||||
}
|
||||
|
||||
DEV_LOG("0x{:02x}({}) config mode", m_rx_buffer[2], m_configuration_mode ? "enter" : "leave");
|
||||
DEBUG_LOG("0x{:02x}({}) config mode", m_rx_buffer[2], m_configuration_mode ? "enter" : "leave");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -706,9 +706,9 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
|||
m_rumble_config[index] = data_in;
|
||||
|
||||
if (data_in == LargeMotor)
|
||||
WARNING_LOG("Large mapped to byte index {}", index);
|
||||
DEBUG_LOG("Large motor mapped to byte index {}", index);
|
||||
else if (data_in == SmallMotor)
|
||||
WARNING_LOG("Small mapped to byte index {}", index);
|
||||
DEBUG_LOG("Small motor mapped to byte index {}", index);
|
||||
}
|
||||
else if (m_command_step == 7)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "IconsPromptFont.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
LOG_CHANNEL(AnalogJoystick);
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
AnalogJoystick::AnalogJoystick(u32 index) : Controller(index)
|
||||
{
|
||||
|
|
|
@ -21,21 +21,7 @@ namespace BIOS {
|
|||
|
||||
static constexpr ImageInfo::Hash MakeHashFromString(const char str[])
|
||||
{
|
||||
ImageInfo::Hash h{};
|
||||
for (int i = 0; str[i] != '\0'; i++)
|
||||
{
|
||||
u8 nibble = 0;
|
||||
char ch = str[i];
|
||||
if (ch >= '0' && ch <= '9')
|
||||
nibble = str[i] - '0';
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
nibble = 0xA + (str[i] - 'a');
|
||||
else if (ch >= 'A' && ch <= 'Z')
|
||||
nibble = 0xA + (str[i] - 'A');
|
||||
|
||||
h[i / 2] |= nibble << (((i & 1) ^ 1) * 4);
|
||||
}
|
||||
return h;
|
||||
return StringUtil::ParseFixedHexString<ImageInfo::HASH_SIZE>(str);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
|
|
@ -941,7 +941,7 @@ void Bus::AddTTYCharacter(char ch)
|
|||
if (!s_tty_line_buffer.empty())
|
||||
{
|
||||
Log::FastWrite(Log::Channel::TTY, Log::Level::Info, "\033[1;34m{}\033[0m", s_tty_line_buffer);
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if (CPU::IsTraceEnabled())
|
||||
CPU::WriteToExecutionLog("TTY: %s\n", s_tty_line_buffer.c_str());
|
||||
#endif
|
||||
|
@ -2299,7 +2299,7 @@ void** Bus::GetMemoryHandlers(bool isolate_cache, bool swap_caches)
|
|||
if (!isolate_cache)
|
||||
return g_memory_handlers;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if (swap_caches)
|
||||
WARNING_LOG("Cache isolated and swapped, icache will be written instead of scratchpad?");
|
||||
#endif
|
||||
|
|
|
@ -46,6 +46,7 @@ enum : u32
|
|||
SECTOR_HEADER_SIZE = CDImage::SECTOR_HEADER_SIZE,
|
||||
MODE1_HEADER_SIZE = CDImage::MODE1_HEADER_SIZE,
|
||||
MODE2_HEADER_SIZE = CDImage::MODE2_HEADER_SIZE,
|
||||
SUBQ_SECTOR_SKEW = 2,
|
||||
XA_ADPCM_SAMPLES_PER_SECTOR_4BIT = 4032, // 28 words * 8 nibbles per word * 18 chunks
|
||||
XA_ADPCM_SAMPLES_PER_SECTOR_8BIT = 2016, // 28 words * 4 bytes per word * 18 chunks
|
||||
XA_RESAMPLE_RING_BUFFER_SIZE = 32,
|
||||
|
@ -1610,7 +1611,7 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba, bool ignore_speed_change)
|
|||
1.0f, 72.0f))));
|
||||
const float seconds = (lba_diff < switch_point) ? 0.05f : 0.1f;
|
||||
ticks += static_cast<u32>(seconds * static_cast<float>(System::MASTER_CLOCK));
|
||||
seek_type = (new_lba > current_lba) ? "NT forward" : "NT backward";
|
||||
seek_type = (new_lba > current_lba) ? "2N forward" : "2N backward";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1625,7 +1626,7 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba, bool ignore_speed_change)
|
|||
(((SLED_VARIABLE_COST * (std::log(static_cast<float>(lba_diff)) / std::log(MAX_SLED_LBA)))) * LOG_WEIGHT) +
|
||||
((SLED_VARIABLE_COST * (lba_diff / MAX_SLED_LBA)) * (1.0f - LOG_WEIGHT));
|
||||
ticks += static_cast<u32>(seconds * static_cast<float>(System::MASTER_CLOCK));
|
||||
seek_type = (new_lba > current_lba) ? "2N/sled forward" : "2N/sled backward";
|
||||
seek_type = (new_lba > current_lba) ? "sled forward" : "sled backward";
|
||||
}
|
||||
|
||||
if (g_settings.cdrom_seek_speedup > 1)
|
||||
|
@ -2101,11 +2102,6 @@ void CDROM::ExecuteCommand(void*, TickCount ticks, TickCount ticks_late)
|
|||
|
||||
case Command::Pause:
|
||||
{
|
||||
if (IsReadingOrPlaying())
|
||||
DEV_COLOR_LOG(StrongOrange, "Pause");
|
||||
else
|
||||
DEV_COLOR_LOG(StrongRed, "Pause Not Reading");
|
||||
|
||||
const TickCount pause_time = GetTicksForPause();
|
||||
if (IsReading() && s_state.last_subq.IsData())
|
||||
{
|
||||
|
@ -2124,22 +2120,34 @@ void CDROM::ExecuteCommand(void*, TickCount ticks, TickCount ticks_late)
|
|||
((s_state.drive_state == DriveState::Reading || s_state.drive_state == DriveState::Playing) &&
|
||||
s_state.secondary_status.seeking))
|
||||
{
|
||||
WARNING_LOG("CDROM Pause command while seeking - sending error response");
|
||||
if (Log::GetLogLevel() >= Log::Level::Dev)
|
||||
DEV_COLOR_LOG(StrongRed, "Pause Seeking => Error");
|
||||
else
|
||||
WARNING_LOG("CDROM Pause command while seeking - sending error response");
|
||||
|
||||
SendErrorResponse(STAT_ERROR, ERROR_REASON_NOT_READY);
|
||||
EndCommand();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Small window of time when another INT1 could sneak in, don't let it.
|
||||
ClearAsyncInterrupt();
|
||||
|
||||
// Stop reading.
|
||||
s_state.drive_state = DriveState::Idle;
|
||||
s_state.drive_event.Deactivate();
|
||||
s_state.secondary_status.ClearActiveBits();
|
||||
if (Log::GetLogLevel() >= Log::Level::Dev)
|
||||
{
|
||||
const double pause_time_ms =
|
||||
static_cast<double>(pause_time) / (static_cast<double>(System::MASTER_CLOCK) / 1000.0);
|
||||
if (IsReadingOrPlaying())
|
||||
DEV_COLOR_LOG(StrongOrange, "Pause {:.2f}ms", pause_time_ms);
|
||||
else
|
||||
DEV_COLOR_LOG(Yellow, "Pause Not Reading {:.2f}ms", pause_time_ms);
|
||||
}
|
||||
|
||||
// Small window of time when another INT1 could sneak in, don't let it.
|
||||
ClearAsyncInterrupt();
|
||||
|
||||
// Stop reading.
|
||||
s_state.drive_state = DriveState::Idle;
|
||||
s_state.drive_event.Deactivate();
|
||||
s_state.secondary_status.ClearActiveBits();
|
||||
|
||||
// Reset audio buffer here - control room cutscene audio repeats in Dino Crisis otherwise.
|
||||
ResetAudioDecoder();
|
||||
|
||||
|
@ -2875,7 +2883,7 @@ void CDROM::UpdateSubQPosition(bool update_logical)
|
|||
const CDImage::LBA old_offset = s_state.current_subq_lba - tjump_position;
|
||||
const CDImage::LBA new_offset = (old_offset + sector_diff) % sectors_per_track;
|
||||
const CDImage::LBA new_subq_lba = tjump_position + new_offset;
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
DEV_LOG("{} sectors @ {} SPT, old pos {}, hold pos {}, tjump pos {}, new pos {}", sector_diff, sectors_per_track,
|
||||
LBAToMSFString(s_state.current_subq_lba), LBAToMSFString(hold_position), LBAToMSFString(tjump_position),
|
||||
LBAToMSFString(new_subq_lba));
|
||||
|
@ -2960,10 +2968,13 @@ bool CDROM::CompleteSeek()
|
|||
if (seek_okay)
|
||||
{
|
||||
const CDImage::SubChannelQ& subq = GetSectorSubQ(s_reader.GetLastReadSector(), s_reader.GetSectorSubQ());
|
||||
s_state.current_lba = s_reader.GetLastReadSector();
|
||||
|
||||
if (subq.IsCRCValid())
|
||||
{
|
||||
// seek and update sub-q for ReadP command
|
||||
s_state.last_subq = subq;
|
||||
s_state.last_subq_needs_update = false;
|
||||
const auto [seek_mm, seek_ss, seek_ff] = CDImage::Position::FromLBA(s_reader.GetLastReadSector()).ToBCD();
|
||||
seek_okay = (subq.absolute_minute_bcd == seek_mm && subq.absolute_second_bcd == seek_ss &&
|
||||
subq.absolute_frame_bcd == seek_ff);
|
||||
|
@ -2977,12 +2988,16 @@ bool CDROM::CompleteSeek()
|
|||
seek_okay = (s_state.last_sector_header.minute == seek_mm && s_state.last_sector_header.second == seek_ss &&
|
||||
s_state.last_sector_header.frame == seek_ff);
|
||||
|
||||
if (seek_okay)
|
||||
if (seek_okay && !s_state.play_after_seek && !s_state.read_after_seek)
|
||||
{
|
||||
// after reading the target, the mech immediately does a 1T reverse
|
||||
const u32 spt = GetSectorsPerTrack(s_state.current_subq_lba);
|
||||
SetHoldPosition(s_state.current_subq_lba,
|
||||
(spt <= s_state.current_subq_lba) ? (s_state.current_subq_lba - spt) : 0);
|
||||
// This is pretty janky. The mech completes the seek when it "sees" a data header
|
||||
// 2 sectors before the seek target, so that a subsequent ReadN can complete nearly
|
||||
// immediately. Therefore when the seek completes, SubQ = Target, Data = Target - 2.
|
||||
// Hack the SubQ back by 2 frames so that following seeks will read forward. If we
|
||||
// ever properly handle SubQ versus data positions, this can be removed.
|
||||
s_state.current_subq_lba =
|
||||
(s_state.current_lba >= SUBQ_SECTOR_SKEW) ? (s_state.current_lba - SUBQ_SECTOR_SKEW) : 0;
|
||||
s_state.last_subq_needs_update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3009,8 +3024,6 @@ bool CDROM::CompleteSeek()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_state.current_lba = s_reader.GetLastReadSector();
|
||||
}
|
||||
|
||||
return seek_okay;
|
||||
|
@ -3227,7 +3240,7 @@ void CDROM::DoSectorRead()
|
|||
// so that multiple sectors could be read in one back, in which case we could just "look ahead" to grab the
|
||||
// subq, but I haven't got around to it. It'll break libcrypt, but CC doesn't use it. One day I'll get around to
|
||||
// doing the refactor.... but given this is the only game that relies on it, priorities.
|
||||
s_reader.GetMedia()->GenerateSubChannelQ(&s_state.last_subq, s_state.current_lba + 2);
|
||||
s_reader.GetMedia()->GenerateSubChannelQ(&s_state.last_subq, s_state.current_lba + SUBQ_SECTOR_SKEW);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -187,7 +187,7 @@ bool CDROMAsyncReader::WaitForReadToComplete()
|
|||
return m_buffers[m_buffer_front.load()].result;
|
||||
}
|
||||
|
||||
Common::Timer wait_timer;
|
||||
Timer wait_timer;
|
||||
DEBUG_LOG("Sector read pending, waiting");
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
@ -226,7 +226,7 @@ void CDROMAsyncReader::EmptyBuffers()
|
|||
|
||||
bool CDROMAsyncReader::ReadSectorIntoBuffer(std::unique_lock<std::mutex>& lock)
|
||||
{
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
|
||||
const u32 slot = m_buffer_back.load();
|
||||
m_buffer_back.store((slot + 1) % static_cast<u32>(m_buffers.size()));
|
||||
|
@ -259,7 +259,7 @@ bool CDROMAsyncReader::ReadSectorIntoBuffer(std::unique_lock<std::mutex>& lock)
|
|||
|
||||
void CDROMAsyncReader::ReadSectorNonThreaded(CDImage::LBA lba)
|
||||
{
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
|
||||
m_buffers.resize(1);
|
||||
m_seek_error.store(false);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "game_database.h"
|
||||
#include "guncon.h"
|
||||
#include "host.h"
|
||||
#include "jogcon.h"
|
||||
#include "justifier.h"
|
||||
#include "negcon.h"
|
||||
#include "negcon_rumble.h"
|
||||
|
@ -38,6 +39,7 @@ static const Controller::ControllerInfo* s_controller_info[] = {
|
|||
&Justifier::INFO,
|
||||
&DigitalController::INFO_POPN,
|
||||
&DigitalController::INFO_DDGO,
|
||||
&JogCon::INFO,
|
||||
};
|
||||
|
||||
const std::array<u32, NUM_CONTROLLER_AND_CARD_PORTS> Controller::PortDisplayOrder = {{0, 2, 3, 4, 1, 5, 6, 7}};
|
||||
|
@ -140,6 +142,9 @@ std::unique_ptr<Controller> Controller::Create(ControllerType type, u32 index)
|
|||
case ControllerType::NeGconRumble:
|
||||
return NeGconRumble::Create(index);
|
||||
|
||||
case ControllerType::JogCon:
|
||||
return JogCon::Create(index);
|
||||
|
||||
case ControllerType::None:
|
||||
default:
|
||||
return {};
|
||||
|
@ -238,6 +243,12 @@ const char* Controller::GetPortDisplayName(u32 port, u32 slot, bool mtap)
|
|||
return mtap ? mtap_labels[port][slot] : no_mtap_labels[port];
|
||||
}
|
||||
|
||||
const char* Controller::GetPortDisplayName(u32 index)
|
||||
{
|
||||
const auto& [port, slot] = ConvertPadToPortAndSlot(index);
|
||||
return GetPortDisplayName(port, slot, g_settings.IsMultitapPortEnabled(port));
|
||||
}
|
||||
|
||||
std::string Controller::GetSettingsSection(u32 pad)
|
||||
{
|
||||
return fmt::format("Pad{}", pad + 1u);
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
|
||||
/// Returns a printable label for a given port.
|
||||
static const char* GetPortDisplayName(u32 port, u32 slot, bool mtap);
|
||||
static const char* GetPortDisplayName(u32 index);
|
||||
|
||||
/// List of controller indices in the order that they should be displayed.
|
||||
static const std::array<u32, NUM_CONTROLLER_AND_CARD_PORTS> PortDisplayOrder;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<ClCompile Include="hotkeys.cpp" />
|
||||
<ClCompile Include="imgui_overlays.cpp" />
|
||||
<ClCompile Include="interrupt_controller.cpp" />
|
||||
<ClCompile Include="jogcon.cpp" />
|
||||
<ClCompile Include="justifier.cpp" />
|
||||
<ClCompile Include="mdec.cpp" />
|
||||
<ClCompile Include="memory_card.cpp" />
|
||||
|
@ -131,6 +132,7 @@
|
|||
<ClInclude Include="imgui_overlays.h" />
|
||||
<ClInclude Include="input_types.h" />
|
||||
<ClInclude Include="interrupt_controller.h" />
|
||||
<ClInclude Include="jogcon.h" />
|
||||
<ClInclude Include="justifier.h" />
|
||||
<ClInclude Include="mdec.h" />
|
||||
<ClInclude Include="memory_card.h" />
|
||||
|
@ -178,7 +180,7 @@
|
|||
<ProjectReference Include="..\..\dep\xxhash\xxhash.vcxproj">
|
||||
<Project>{09553c96-9f39-49bf-8ae6-7acbd07c410c}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\dep\zydis\zydis.vcxproj" Condition="'$(Platform)'=='x64' And $(Configuration.Contains('Debug'))">
|
||||
<ProjectReference Include="..\..\dep\zydis\zydis.vcxproj" Condition="'$(Platform)'=='x64' And ($(Configuration.Contains('Debug')) Or $(Configuration.Contains('Devel')))">
|
||||
<Project>{c51a346a-86b2-46df-9bb3-d0aa7e5d8699}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\scmversion\scmversion.vcxproj">
|
||||
|
@ -198,8 +200,8 @@
|
|||
<Import Project="core.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions Condition="'$(Platform)'=='x64' And $(Configuration.Contains('Debug'))">ZYDIS_DISABLE_ENCODER;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Platform)'=='x64' And $(Configuration.Contains('Debug'))">%(AdditionalIncludeDirectories);$(SolutionDir)dep\zydis\include;$(SolutionDir)dep\zydis\dependencies\zycore\include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Platform)'=='x64' And ($(Configuration.Contains('Debug')) Or $(Configuration.Contains('Devel')))">ZYDIS_DISABLE_ENCODER;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Platform)'=='x64' And ($(Configuration.Contains('Debug')) Or $(Configuration.Contains('Devel')))">%(AdditionalIncludeDirectories);$(SolutionDir)dep\zydis\include;$(SolutionDir)dep\zydis\dependencies\zycore\include</AdditionalIncludeDirectories>
|
||||
<ObjectFileName>$(IntDir)/%(RelativeDir)/</ObjectFileName>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<ClCompile Include="gpu_dump.cpp" />
|
||||
<ClCompile Include="cdrom_subq_replacement.cpp" />
|
||||
<ClCompile Include="performance_counters.cpp" />
|
||||
<ClCompile Include="jogcon.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="types.h" />
|
||||
|
@ -139,6 +140,7 @@
|
|||
<ClInclude Include="cdrom_subq_replacement.h" />
|
||||
<ClInclude Include="performance_counters.h" />
|
||||
<ClInclude Include="system_private.h" />
|
||||
<ClInclude Include="jogcon.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="gpu_sw_rasterizer.inl" />
|
||||
|
|
|
@ -154,9 +154,10 @@ static u8* s_free_far_code_ptr = nullptr;
|
|||
static u32 s_far_code_size = 0;
|
||||
static u32 s_far_code_used = 0;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef DUMP_CODE_SIZE_STATS
|
||||
static u32 s_total_instructions_compiled = 0;
|
||||
static u32 s_total_host_instructions_emitted = 0;
|
||||
static u32 s_total_host_code_used_by_instructions = 0;
|
||||
#endif
|
||||
} // namespace CPU::CodeCache
|
||||
|
||||
|
@ -691,7 +692,6 @@ void CPU::CodeCache::InvalidateAllRAMBlocks()
|
|||
|
||||
void CPU::CodeCache::ClearBlocks()
|
||||
{
|
||||
|
||||
for (u32 i = 0; i < Bus::RAM_8MB_CODE_PAGE_COUNT; i++)
|
||||
{
|
||||
PageProtectionInfo& ppi = s_page_protection[i];
|
||||
|
@ -1023,7 +1023,7 @@ bool CPU::CodeCache::ReadBlockInstructions(u32 start_pc, BlockInstructionList* i
|
|||
|
||||
instructions->back().second.is_last_instruction = true;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
SmallString disasm;
|
||||
DEBUG_LOG("Block at 0x{:08X}", start_pc);
|
||||
DEBUG_LOG(" Uncached fetch ticks: {}", metadata->uncached_fetch_ticks);
|
||||
|
@ -1345,10 +1345,13 @@ void CPU::CodeCache::CompileOrRevalidateBlock(u32 start_pc)
|
|||
}
|
||||
|
||||
// Ensure we're not going to run out of space while compiling this block.
|
||||
// We could definitely do better here... TODO: far code is no longer needed for newrec
|
||||
// We could definitely do better here...
|
||||
const u32 block_size = static_cast<u32>(s_block_instructions.size());
|
||||
if (GetFreeCodeSpace() < (block_size * Recompiler::MAX_NEAR_HOST_BYTES_PER_INSTRUCTION) ||
|
||||
GetFreeFarCodeSpace() < (block_size * Recompiler::MAX_FAR_HOST_BYTES_PER_INSTRUCTION))
|
||||
const u32 free_code_space = GetFreeCodeSpace();
|
||||
const u32 free_far_code_space = GetFreeFarCodeSpace();
|
||||
if (free_code_space < (block_size * Recompiler::MAX_NEAR_HOST_BYTES_PER_INSTRUCTION) ||
|
||||
free_code_space < Recompiler::MIN_CODE_RESERVE_FOR_BLOCK ||
|
||||
free_far_code_space < Recompiler::MIN_CODE_RESERVE_FOR_BLOCK)
|
||||
{
|
||||
ERROR_LOG("Out of code space while compiling {:08X}. Resetting code cache.", start_pc);
|
||||
CodeCache::Reset();
|
||||
|
@ -1540,9 +1543,10 @@ void CPU::CodeCache::CompileASMFunctions()
|
|||
{
|
||||
MemMap::BeginCodeWrite();
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef DUMP_CODE_SIZE_STATS
|
||||
s_total_instructions_compiled = 0;
|
||||
s_total_host_instructions_emitted = 0;
|
||||
s_total_host_code_used_by_instructions = 0;
|
||||
#endif
|
||||
|
||||
const u32 asm_size = EmitASMFunctions(GetFreeCodePointer(), GetFreeCodeSpace());
|
||||
|
@ -1580,14 +1584,18 @@ bool CPU::CodeCache::CompileBlock(Block* block)
|
|||
const u32 host_instructions = GetHostInstructionCount(host_code, host_code_size);
|
||||
s_total_instructions_compiled += block->size;
|
||||
s_total_host_instructions_emitted += host_instructions;
|
||||
s_total_host_code_used_by_instructions += host_code_size;
|
||||
|
||||
DEV_LOG("0x{:08X}: {}/{}b for {}b ({}i), blowup: {:.2f}x, cache: {:.2f}%/{:.2f}%, ipi: {:.2f}/{:.2f}", block->pc,
|
||||
host_code_size, host_far_code_size, block->size * 4, block->size,
|
||||
static_cast<float>(host_code_size) / static_cast<float>(block->size * 4),
|
||||
(static_cast<float>(s_code_used) / static_cast<float>(s_code_size)) * 100.0f,
|
||||
(static_cast<float>(s_far_code_used) / static_cast<float>(s_far_code_size)) * 100.0f,
|
||||
static_cast<float>(host_instructions) / static_cast<float>(block->size),
|
||||
static_cast<float>(s_total_host_instructions_emitted) / static_cast<float>(s_total_instructions_compiled));
|
||||
DEV_LOG(
|
||||
"0x{:08X}: {}/{}b for {}b ({}i), blowup: {:.2f}x, cache: {:.2f}%/{:.2f}%, ipi: {:.2f}/{:.2f}, bpi: {:.2f}/{:.2f}",
|
||||
block->pc, host_code_size, host_far_code_size, block->size * 4, block->size,
|
||||
static_cast<float>(host_code_size) / static_cast<float>(block->size * 4),
|
||||
(static_cast<float>(s_code_used) / static_cast<float>(s_code_size)) * 100.0f,
|
||||
(static_cast<float>(s_far_code_used) / static_cast<float>(s_far_code_size)) * 100.0f,
|
||||
static_cast<float>(host_instructions) / static_cast<float>(block->size),
|
||||
static_cast<float>(s_total_host_instructions_emitted) / static_cast<float>(s_total_instructions_compiled),
|
||||
static_cast<float>(block->host_code_size) / static_cast<float>(block->size),
|
||||
static_cast<float>(s_total_host_code_used_by_instructions) / static_cast<float>(s_total_instructions_compiled));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -215,7 +215,7 @@ void InterpretUncachedBlock();
|
|||
|
||||
void LogCurrentState();
|
||||
|
||||
#if defined(_DEBUG) || false
|
||||
#if defined(_DEBUG) || defined(_DEVEL) || false
|
||||
// Enable disassembly of host assembly code.
|
||||
#define ENABLE_HOST_DISASSEMBLY 1
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "common/fastjmp.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
|
@ -48,9 +49,6 @@ static u32 ReadReg(Reg rs);
|
|||
static void WriteReg(Reg rd, u32 value);
|
||||
static void WriteRegDelayed(Reg rd, u32 value);
|
||||
|
||||
static u32 ReadCop0Reg(Cop0Reg reg);
|
||||
static void WriteCop0Reg(Cop0Reg reg, u32 value);
|
||||
|
||||
static void DispatchCop0Breakpoint();
|
||||
static bool IsCop0ExecutionBreakpointUnmasked();
|
||||
static void Cop0ExecutionBreakpointCheck();
|
||||
|
@ -147,9 +145,9 @@ void CPU::StopTrace()
|
|||
|
||||
void CPU::WriteToExecutionLog(const char* format, ...)
|
||||
{
|
||||
if (!s_log_file_opened)
|
||||
if (!s_log_file_opened) [[unlikely]]
|
||||
{
|
||||
s_log_file = FileSystem::OpenCFile("cpu_log.txt", "wb");
|
||||
s_log_file = FileSystem::OpenCFile(Path::Combine(EmuFolders::DataRoot, "cpu_log.txt").c_str(), "wb");
|
||||
s_log_file_opened = true;
|
||||
}
|
||||
|
||||
|
@ -338,7 +336,7 @@ ALWAYS_INLINE_RELEASE void CPU::RaiseException(u32 CAUSE_bits, u32 EPC, u32 vect
|
|||
g_state.cop0_regs.cause.bits = (g_state.cop0_regs.cause.bits & ~Cop0Registers::CAUSE::EXCEPTION_WRITE_MASK) |
|
||||
(CAUSE_bits & Cop0Registers::CAUSE::EXCEPTION_WRITE_MASK);
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if (g_state.cop0_regs.cause.Excode != Exception::INT && g_state.cop0_regs.cause.Excode != Exception::Syscall &&
|
||||
g_state.cop0_regs.cause.Excode != Exception::BP)
|
||||
{
|
||||
|
@ -494,122 +492,6 @@ ALWAYS_INLINE_RELEASE void CPU::WriteRegDelayed(Reg rd, u32 value)
|
|||
g_state.next_load_delay_value = value;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE u32 CPU::ReadCop0Reg(Cop0Reg reg)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case Cop0Reg::BPC:
|
||||
return g_state.cop0_regs.BPC;
|
||||
|
||||
case Cop0Reg::BPCM:
|
||||
return g_state.cop0_regs.BPCM;
|
||||
|
||||
case Cop0Reg::BDA:
|
||||
return g_state.cop0_regs.BDA;
|
||||
|
||||
case Cop0Reg::BDAM:
|
||||
return g_state.cop0_regs.BDAM;
|
||||
|
||||
case Cop0Reg::DCIC:
|
||||
return g_state.cop0_regs.dcic.bits;
|
||||
|
||||
case Cop0Reg::JUMPDEST:
|
||||
return g_state.cop0_regs.TAR;
|
||||
|
||||
case Cop0Reg::BadVaddr:
|
||||
return g_state.cop0_regs.BadVaddr;
|
||||
|
||||
case Cop0Reg::SR:
|
||||
return g_state.cop0_regs.sr.bits;
|
||||
|
||||
case Cop0Reg::CAUSE:
|
||||
return g_state.cop0_regs.cause.bits;
|
||||
|
||||
case Cop0Reg::EPC:
|
||||
return g_state.cop0_regs.EPC;
|
||||
|
||||
case Cop0Reg::PRID:
|
||||
return g_state.cop0_regs.PRID;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE void CPU::WriteCop0Reg(Cop0Reg reg, u32 value)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case Cop0Reg::BPC:
|
||||
{
|
||||
g_state.cop0_regs.BPC = value;
|
||||
DEV_LOG("COP0 BPC <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BPCM:
|
||||
{
|
||||
g_state.cop0_regs.BPCM = value;
|
||||
DEV_LOG("COP0 BPCM <- {:08X}", value);
|
||||
if (UpdateDebugDispatcherFlag())
|
||||
ExitExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDA:
|
||||
{
|
||||
g_state.cop0_regs.BDA = value;
|
||||
DEV_LOG("COP0 BDA <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDAM:
|
||||
{
|
||||
g_state.cop0_regs.BDAM = value;
|
||||
DEV_LOG("COP0 BDAM <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::JUMPDEST:
|
||||
{
|
||||
WARNING_LOG("Ignoring write to Cop0 JUMPDEST");
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::DCIC:
|
||||
{
|
||||
g_state.cop0_regs.dcic.bits =
|
||||
(g_state.cop0_regs.dcic.bits & ~Cop0Registers::DCIC::WRITE_MASK) | (value & Cop0Registers::DCIC::WRITE_MASK);
|
||||
DEV_LOG("COP0 DCIC <- {:08X} (now {:08X})", value, g_state.cop0_regs.dcic.bits);
|
||||
if (UpdateDebugDispatcherFlag())
|
||||
ExitExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::SR:
|
||||
{
|
||||
g_state.cop0_regs.sr.bits =
|
||||
(g_state.cop0_regs.sr.bits & ~Cop0Registers::SR::WRITE_MASK) | (value & Cop0Registers::SR::WRITE_MASK);
|
||||
DEBUG_LOG("COP0 SR <- {:08X} (now {:08X})", value, g_state.cop0_regs.sr.bits);
|
||||
UpdateMemoryPointers();
|
||||
CheckForPendingInterrupt();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::CAUSE:
|
||||
{
|
||||
g_state.cop0_regs.cause.bits =
|
||||
(g_state.cop0_regs.cause.bits & ~Cop0Registers::CAUSE::WRITE_MASK) | (value & Cop0Registers::CAUSE::WRITE_MASK);
|
||||
DEBUG_LOG("COP0 CAUSE <- {:08X} (now {:08X})", value, g_state.cop0_regs.cause.bits);
|
||||
CheckForPendingInterrupt();
|
||||
}
|
||||
break;
|
||||
|
||||
[[unlikely]] default : DEV_LOG("Unknown COP0 reg write {} ({:08X})", static_cast<u8>(reg), value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE_RELEASE bool CPU::IsCop0ExecutionBreakpointUnmasked()
|
||||
{
|
||||
static constexpr const u32 code_address_ranges[][2] = {
|
||||
|
@ -1775,7 +1657,59 @@ restart_instruction:
|
|||
{
|
||||
case CopCommonInstruction::mfcn:
|
||||
{
|
||||
const u32 value = ReadCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()));
|
||||
u32 value;
|
||||
|
||||
switch (static_cast<Cop0Reg>(inst.r.rd.GetValue()))
|
||||
{
|
||||
case Cop0Reg::BPC:
|
||||
value = g_state.cop0_regs.BPC;
|
||||
break;
|
||||
|
||||
case Cop0Reg::BPCM:
|
||||
value = g_state.cop0_regs.BPCM;
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDA:
|
||||
value = g_state.cop0_regs.BDA;
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDAM:
|
||||
value = g_state.cop0_regs.BDAM;
|
||||
break;
|
||||
|
||||
case Cop0Reg::DCIC:
|
||||
value = g_state.cop0_regs.dcic.bits;
|
||||
break;
|
||||
|
||||
case Cop0Reg::JUMPDEST:
|
||||
value = g_state.cop0_regs.TAR;
|
||||
break;
|
||||
|
||||
case Cop0Reg::BadVaddr:
|
||||
value = g_state.cop0_regs.BadVaddr;
|
||||
break;
|
||||
|
||||
case Cop0Reg::SR:
|
||||
value = g_state.cop0_regs.sr.bits;
|
||||
break;
|
||||
|
||||
case Cop0Reg::CAUSE:
|
||||
value = g_state.cop0_regs.cause.bits;
|
||||
break;
|
||||
|
||||
case Cop0Reg::EPC:
|
||||
value = g_state.cop0_regs.EPC;
|
||||
break;
|
||||
|
||||
case Cop0Reg::PRID:
|
||||
value = g_state.cop0_regs.PRID;
|
||||
break;
|
||||
|
||||
default:
|
||||
RaiseException(Exception::RI);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteRegDelayed(inst.r.rt, value);
|
||||
|
||||
if constexpr (pgxp_mode == PGXPMode::CPU)
|
||||
|
@ -1785,11 +1719,86 @@ restart_instruction:
|
|||
|
||||
case CopCommonInstruction::mtcn:
|
||||
{
|
||||
const u32 rtVal = ReadReg(inst.r.rt);
|
||||
WriteCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()), rtVal);
|
||||
u32 value = ReadReg(inst.r.rt);
|
||||
[[maybe_unused]] const u32 orig_value = value;
|
||||
|
||||
switch (static_cast<Cop0Reg>(inst.r.rd.GetValue()))
|
||||
{
|
||||
case Cop0Reg::BPC:
|
||||
{
|
||||
g_state.cop0_regs.BPC = value;
|
||||
DEV_LOG("COP0 BPC <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BPCM:
|
||||
{
|
||||
g_state.cop0_regs.BPCM = value;
|
||||
DEV_LOG("COP0 BPCM <- {:08X}", value);
|
||||
if (UpdateDebugDispatcherFlag())
|
||||
ExitExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDA:
|
||||
{
|
||||
g_state.cop0_regs.BDA = value;
|
||||
DEV_LOG("COP0 BDA <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::BDAM:
|
||||
{
|
||||
g_state.cop0_regs.BDAM = value;
|
||||
DEV_LOG("COP0 BDAM <- {:08X}", value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::JUMPDEST:
|
||||
{
|
||||
WARNING_LOG("Ignoring write to Cop0 JUMPDEST");
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::DCIC:
|
||||
{
|
||||
g_state.cop0_regs.dcic.bits = (g_state.cop0_regs.dcic.bits & ~Cop0Registers::DCIC::WRITE_MASK) |
|
||||
(value & Cop0Registers::DCIC::WRITE_MASK);
|
||||
DEV_LOG("COP0 DCIC <- {:08X} (now {:08X})", value, g_state.cop0_regs.dcic.bits);
|
||||
value = g_state.cop0_regs.dcic.bits;
|
||||
if (UpdateDebugDispatcherFlag())
|
||||
ExitExecution();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::SR:
|
||||
{
|
||||
g_state.cop0_regs.sr.bits = (g_state.cop0_regs.sr.bits & ~Cop0Registers::SR::WRITE_MASK) |
|
||||
(value & Cop0Registers::SR::WRITE_MASK);
|
||||
DEBUG_LOG("COP0 SR <- {:08X} (now {:08X})", value, g_state.cop0_regs.sr.bits);
|
||||
value = g_state.cop0_regs.sr.bits;
|
||||
UpdateMemoryPointers();
|
||||
CheckForPendingInterrupt();
|
||||
}
|
||||
break;
|
||||
|
||||
case Cop0Reg::CAUSE:
|
||||
{
|
||||
g_state.cop0_regs.cause.bits = (g_state.cop0_regs.cause.bits & ~Cop0Registers::CAUSE::WRITE_MASK) |
|
||||
(value & Cop0Registers::CAUSE::WRITE_MASK);
|
||||
DEBUG_LOG("COP0 CAUSE <- {:08X} (now {:08X})", value, g_state.cop0_regs.cause.bits);
|
||||
value = g_state.cop0_regs.cause.bits;
|
||||
CheckForPendingInterrupt();
|
||||
}
|
||||
break;
|
||||
|
||||
[[unlikely]] default:
|
||||
RaiseException(Exception::RI);
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (pgxp_mode == PGXPMode::CPU)
|
||||
PGXP::CPU_MTC0(inst, ReadCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue())), rtVal);
|
||||
PGXP::CPU_MTC0(inst, value, orig_value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1817,7 +1826,7 @@ restart_instruction:
|
|||
case Cop0Instruction::tlbwr:
|
||||
case Cop0Instruction::tlbp:
|
||||
RaiseException(Exception::RI);
|
||||
break;
|
||||
return;
|
||||
|
||||
default:
|
||||
[[unlikely]] ERROR_LOG("Unhandled instruction at {:08X}: {:08X}", g_state.current_instruction_pc,
|
||||
|
@ -2840,10 +2849,7 @@ ALWAYS_INLINE_RELEASE bool CPU::FetchInstruction()
|
|||
case 0x07: // KSEG2
|
||||
default:
|
||||
{
|
||||
CPU::RaiseException(Cop0Registers::CAUSE::MakeValueForException(Exception::IBE,
|
||||
g_state.current_instruction_in_branch_delay_slot,
|
||||
g_state.current_instruction_was_branch_taken, 0),
|
||||
address);
|
||||
CPU::RaiseException(Cop0Registers::CAUSE::MakeValueForException(Exception::IBE, false, false, 0), address);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -354,7 +354,7 @@ bool CPU::Recompiler::Recompiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
|
|||
const Reg opcode_rt = next_instruction->r.rt;
|
||||
const Reg opcode_rd = next_instruction->r.rd;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
TinyString disasm;
|
||||
DisassembleInstruction(&disasm, m_current_instruction_pc + 4, next_instruction->bits);
|
||||
#endif
|
||||
|
@ -492,7 +492,7 @@ bool CPU::Recompiler::Recompiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
|
|||
}
|
||||
|
||||
is_safe:
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
DEBUG_LOG("Swapping delay slot {:08X} {}", m_current_instruction_pc + 4, disasm);
|
||||
#endif
|
||||
|
||||
|
@ -504,7 +504,7 @@ is_safe:
|
|||
return true;
|
||||
|
||||
is_unsafe:
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
DEBUG_LOG("NOT swapping delay slot {:08X} {}", m_current_instruction_pc + 4, disasm);
|
||||
#endif
|
||||
|
||||
|
@ -1178,7 +1178,7 @@ void CPU::Recompiler::Recompiler::AddLoadStoreInfo(void* code_address, u32 code_
|
|||
|
||||
void CPU::Recompiler::Recompiler::CompileInstruction()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
TinyString str;
|
||||
DisassembleInstruction(&str, m_current_instruction_pc, inst->bits);
|
||||
DEBUG_LOG("Compiling{} {:08X}: {}", m_current_instruction_branch_delay_slot ? " branch delay slot" : "",
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
namespace CPU {
|
||||
|
||||
// TODO: Get rid of the virtuals... somehow.
|
||||
class Recompiler
|
||||
{
|
||||
public:
|
||||
|
@ -26,8 +25,10 @@ public:
|
|||
#if defined(CPU_ARCH_X64)
|
||||
|
||||
// A reasonable "maximum" number of bytes per instruction.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
|
||||
static constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
|
||||
// Seems to hover around ~21 bytes without PGXP, and ~26 bytes with.
|
||||
// Use an upper bound of 32 bytes to be safe.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 32;
|
||||
static constexpr u32 MIN_CODE_RESERVE_FOR_BLOCK = 512;
|
||||
|
||||
// Number of host registers.
|
||||
static constexpr u32 NUM_HOST_REGS = 16;
|
||||
|
@ -37,7 +38,7 @@ public:
|
|||
|
||||
// A reasonable "maximum" number of bytes per instruction.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
|
||||
static constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
|
||||
static constexpr u32 MIN_CODE_RESERVE_FOR_BLOCK = 512;
|
||||
|
||||
// Number of host registers.
|
||||
static constexpr u32 NUM_HOST_REGS = 16;
|
||||
|
@ -45,14 +46,16 @@ public:
|
|||
|
||||
#elif defined(CPU_ARCH_ARM64)
|
||||
|
||||
// A reasonable "maximum" number of bytes per instruction.
|
||||
// Seems to hover around ~24 bytes without PGXP, and ~40 bytes with.
|
||||
// Use an upper bound of 48 bytes to be safe.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 48;
|
||||
static constexpr u32 MIN_CODE_RESERVE_FOR_BLOCK = 512;
|
||||
|
||||
// Number of host registers.
|
||||
static constexpr u32 NUM_HOST_REGS = 32;
|
||||
static constexpr bool HAS_MEMORY_OPERANDS = false;
|
||||
|
||||
// A reasonable "maximum" number of bytes per instruction.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
|
||||
static constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
|
||||
|
||||
#elif defined(CPU_ARCH_RISCV64)
|
||||
|
||||
// Number of host registers.
|
||||
|
@ -61,7 +64,7 @@ public:
|
|||
|
||||
// A reasonable "maximum" number of bytes per instruction.
|
||||
static constexpr u32 MAX_NEAR_HOST_BYTES_PER_INSTRUCTION = 64;
|
||||
static constexpr u32 MAX_FAR_HOST_BYTES_PER_INSTRUCTION = 128;
|
||||
static constexpr u32 MIN_CODE_RESERVE_FOR_BLOCK = 512;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -772,7 +772,7 @@ template<DMA::Channel channel>
|
|||
TickCount DMA::TransferMemoryToDevice(u32 address, u32 increment, u32 word_count)
|
||||
{
|
||||
const u32 mask = Bus::g_ram_mask;
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if ((address & mask) != address)
|
||||
DEBUG_LOG("DMA TO {} from masked RAM address 0x{:08X} => 0x{:08X}", channel, address, (address & mask));
|
||||
#endif
|
||||
|
@ -862,7 +862,7 @@ template<DMA::Channel channel>
|
|||
TickCount DMA::TransferDeviceToMemory(u32 address, u32 increment, u32 word_count)
|
||||
{
|
||||
const u32 mask = Bus::g_ram_mask;
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if ((address & mask) != address)
|
||||
DEBUG_LOG("DMA FROM {} to masked RAM address 0x{:08X} => 0x{:08X}", channel, address, (address & mask));
|
||||
#endif
|
||||
|
|
|
@ -422,7 +422,7 @@ static std::string s_input_binding_key;
|
|||
static std::string s_input_binding_display_name;
|
||||
static std::vector<InputBindingKey> s_input_binding_new_bindings;
|
||||
static std::vector<std::pair<InputBindingKey, std::pair<float, float>>> s_input_binding_value_ranges;
|
||||
static Common::Timer s_input_binding_timer;
|
||||
static Timer s_input_binding_timer;
|
||||
static bool s_controller_macro_expanded[NUM_CONTROLLER_AND_CARD_PORTS][InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER] =
|
||||
{};
|
||||
|
||||
|
@ -1651,7 +1651,7 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
|||
if (!visible)
|
||||
return;
|
||||
|
||||
if (oneline)
|
||||
if (oneline && type != InputBindingInfo::Type::Pointer && type != InputBindingInfo::Type::Device)
|
||||
InputManager::PrettifyInputBinding(value);
|
||||
|
||||
if (show_type)
|
||||
|
@ -1677,6 +1677,9 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
|||
case InputBindingInfo::Type::Macro:
|
||||
title.format(ICON_FA_PIZZA_SLICE " {}", display_name);
|
||||
break;
|
||||
case InputBindingInfo::Type::Device:
|
||||
title.format(ICON_FA_GAMEPAD " {}", display_name);
|
||||
break;
|
||||
default:
|
||||
title = display_name;
|
||||
break;
|
||||
|
@ -4323,7 +4326,8 @@ void FullscreenUI::DrawGraphicsSettingsPage()
|
|||
DrawEnumSetting(bsi, FSUI_ICONSTR(ICON_FA_CROP_ALT, "Crop Mode"),
|
||||
FSUI_CSTR("Determines how much of the area typically not visible on a consumer TV set to crop/hide."),
|
||||
"Display", "CropMode", Settings::DEFAULT_DISPLAY_CROP_MODE, &Settings::ParseDisplayCropMode,
|
||||
&Settings::GetDisplayCropModeName, &Settings::GetDisplayCropModeDisplayName, DisplayCropMode::MaxCount);
|
||||
&Settings::GetDisplayCropModeName, &Settings::GetDisplayCropModeDisplayName,
|
||||
DisplayCropMode::MaxCount);
|
||||
|
||||
DrawEnumSetting(
|
||||
bsi, FSUI_ICONSTR(ICON_FA_EXPAND, "Scaling"),
|
||||
|
@ -4602,7 +4606,7 @@ void FullscreenUI::DrawGraphicsSettingsPage()
|
|||
FSUI_CSTR("Dumps textures that have replacements already loaded."), "TextureReplacements", "DumpReplacedTextures",
|
||||
false, texture_cache_enabled && GetEffectiveBoolSetting(bsi, "TextureReplacements", "DumpTextures", false));
|
||||
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FILE_ALT, "Enable VRAM Write Texture Replacement"),
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FILE_ALT, "Enable VRAM Write Replacement"),
|
||||
FSUI_CSTR("Enables the replacement of background textures in supported games."),
|
||||
"TextureReplacements", "EnableVRAMWriteReplacements", false);
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ void GameDatabase::EnsureLoaded()
|
|||
if (s_loaded)
|
||||
return;
|
||||
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
|
||||
s_loaded = true;
|
||||
|
||||
|
@ -646,7 +646,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
|
|||
#else
|
||||
Host::AddIconOSDWarning("gamedb_force_pgxp_cpu", ICON_EMOJI_WARNING,
|
||||
"This game requires PGXP CPU mode, which increases system requirements.\n"
|
||||
" If the game runs too slow, disable PGXP for this game.",
|
||||
" If the game runs too slow, disable PGXP for this game.",
|
||||
Host::OSD_WARNING_DURATION);
|
||||
#endif
|
||||
}
|
||||
|
@ -1417,7 +1417,7 @@ void GameDatabase::EnsureTrackHashesMapLoaded()
|
|||
|
||||
bool GameDatabase::LoadTrackHashes()
|
||||
{
|
||||
Common::Timer load_timer;
|
||||
Timer load_timer;
|
||||
|
||||
Error error;
|
||||
std::optional<std::string> gamedb_data(Host::ReadResourceFileToString(DISCDB_YAML_FILENAME, false, &error));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "system.h"
|
||||
|
||||
#include "util/cd_image.h"
|
||||
#include "util/elf_file.h"
|
||||
#include "util/http_downloader.h"
|
||||
#include "util/image.h"
|
||||
#include "util/ini_settings_interface.h"
|
||||
|
@ -199,6 +200,18 @@ bool GameList::GetExeListEntry(const std::string& path, GameList::Entry* entry)
|
|||
// Who knows
|
||||
entry->region = DiscRegion::Other;
|
||||
}
|
||||
else if (StringUtil::EndsWithNoCase(filename, ".elf"))
|
||||
{
|
||||
ELFFile::Elf32_Ehdr header;
|
||||
if (std::fread(&header, sizeof(header), 1, fp.get()) != 1 || !ELFFile::IsValidElfHeader(header))
|
||||
{
|
||||
WARNING_LOG("{} is not a valid ELF.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Who knows
|
||||
entry->region = DiscRegion::Other;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIOS::PSEXEHeader header;
|
||||
|
@ -1690,7 +1703,7 @@ FileSystem::ManagedCFilePtr GameList::OpenMemoryCardTimestampCache(bool for_writ
|
|||
if (errno != EACCES)
|
||||
return nullptr;
|
||||
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
while (timer.GetTimeMilliseconds() <= 100.0f)
|
||||
{
|
||||
fp = FileSystem::OpenManagedSharedCFile(filename.c_str(), mode, share_mode, nullptr);
|
||||
|
|
|
@ -171,7 +171,39 @@ void GPU::UpdateResolutionScale()
|
|||
|
||||
std::tuple<u32, u32> GPU::GetFullDisplayResolution() const
|
||||
{
|
||||
return std::tie(m_crtc_state.display_width, m_crtc_state.display_height);
|
||||
u32 width, height;
|
||||
if (IsDisplayDisabled())
|
||||
{
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 xmin, xmax, ymin, ymax;
|
||||
if (!m_GPUSTAT.pal_mode)
|
||||
{
|
||||
xmin = NTSC_HORIZONTAL_ACTIVE_START;
|
||||
xmax = NTSC_HORIZONTAL_ACTIVE_END;
|
||||
ymin = NTSC_VERTICAL_ACTIVE_START;
|
||||
ymax = NTSC_VERTICAL_ACTIVE_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
xmin = PAL_HORIZONTAL_ACTIVE_START;
|
||||
xmax = PAL_HORIZONTAL_ACTIVE_END;
|
||||
ymin = PAL_VERTICAL_ACTIVE_START;
|
||||
ymax = PAL_VERTICAL_ACTIVE_END;
|
||||
}
|
||||
|
||||
width = static_cast<u32>(std::max<s32>(std::clamp<s32>(m_crtc_state.regs.X2, xmin, xmax) -
|
||||
std::clamp<s32>(m_crtc_state.regs.X1, xmin, xmax),
|
||||
0) /
|
||||
m_crtc_state.dot_clock_divider);
|
||||
height = static_cast<u32>(std::max<s32>(
|
||||
std::clamp<s32>(m_crtc_state.regs.Y2, ymin, ymax) - std::clamp<s32>(m_crtc_state.regs.Y1, ymin, ymax), 0));
|
||||
}
|
||||
|
||||
return std::tie(width, height);
|
||||
}
|
||||
|
||||
void GPU::Reset(bool clear_vram)
|
||||
|
@ -629,7 +661,9 @@ float GPU::ComputeDisplayAspectRatio() const
|
|||
float GPU::ComputeSourceAspectRatio() const
|
||||
{
|
||||
const float source_aspect_ratio =
|
||||
static_cast<float>(m_crtc_state.display_width) / static_cast<float>(m_crtc_state.display_height);
|
||||
(g_settings.debugging.show_vram ?
|
||||
(static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT)) :
|
||||
static_cast<float>(m_crtc_state.display_width) / static_cast<float>(m_crtc_state.display_height));
|
||||
|
||||
// Correction is applied to the GTE for stretch to fit, that way it fills the window.
|
||||
const float source_aspect_ratio_correction =
|
||||
|
@ -643,7 +677,8 @@ float GPU::ComputeAspectRatioCorrection() const
|
|||
const CRTCState& cs = m_crtc_state;
|
||||
float relative_width = static_cast<float>(cs.horizontal_visible_end - cs.horizontal_visible_start);
|
||||
float relative_height = static_cast<float>(cs.vertical_visible_end - cs.vertical_visible_start);
|
||||
if (relative_width <= 0 || relative_height <= 0 || g_settings.display_aspect_ratio == DisplayAspectRatio::PAR1_1 ||
|
||||
if (relative_width <= 0 || relative_height <= 0 || g_settings.debugging.show_vram ||
|
||||
g_settings.display_aspect_ratio == DisplayAspectRatio::PAR1_1 ||
|
||||
g_settings.display_crop_mode == DisplayCropMode::OverscanUncorrected ||
|
||||
g_settings.display_crop_mode == DisplayCropMode::BordersUncorrected)
|
||||
{
|
||||
|
@ -1550,32 +1585,31 @@ void GPU::HandleGetGPUInfoCommand(u32 value)
|
|||
|
||||
case 0x02: // Get Texture Window
|
||||
{
|
||||
DEBUG_LOG("Get texture window");
|
||||
m_GPUREAD_latch = m_draw_mode.texture_window_value;
|
||||
DEBUG_LOG("Get texture window => 0x{:08X}", m_GPUREAD_latch);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: // Get Draw Area Top Left
|
||||
{
|
||||
DEBUG_LOG("Get drawing area top left");
|
||||
m_GPUREAD_latch =
|
||||
((m_drawing_area.left & UINT32_C(0b1111111111)) | ((m_drawing_area.top & UINT32_C(0b1111111111)) << 10));
|
||||
m_GPUREAD_latch = (m_drawing_area.left | (m_drawing_area.top << 10));
|
||||
DEBUG_LOG("Get drawing area top left: ({}, {}) => 0x{:08X}", m_drawing_area.left, m_drawing_area.top,
|
||||
m_GPUREAD_latch);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04: // Get Draw Area Bottom Right
|
||||
{
|
||||
DEBUG_LOG("Get drawing area bottom right");
|
||||
m_GPUREAD_latch =
|
||||
((m_drawing_area.right & UINT32_C(0b1111111111)) | ((m_drawing_area.bottom & UINT32_C(0b1111111111)) << 10));
|
||||
m_GPUREAD_latch = (m_drawing_area.right | (m_drawing_area.bottom << 10));
|
||||
DEBUG_LOG("Get drawing area bottom right: ({}, {}) => 0x{:08X}", m_drawing_area.bottom, m_drawing_area.right,
|
||||
m_GPUREAD_latch);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x05: // Get Drawing Offset
|
||||
{
|
||||
DEBUG_LOG("Get drawing offset");
|
||||
m_GPUREAD_latch =
|
||||
((m_drawing_offset.x & INT32_C(0b11111111111)) | ((m_drawing_offset.y & INT32_C(0b11111111111)) << 11));
|
||||
m_GPUREAD_latch = (m_drawing_offset.x & 0x7FF) | ((m_drawing_offset.y & 0x7FF) << 11);
|
||||
DEBUG_LOG("Get drawing offset: ({}, {}) => 0x{:08X}", m_drawing_offset.x, m_drawing_offset.y, m_GPUREAD_latch);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "common/log.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
LOG_CHANNEL(GPUBackend);
|
||||
LOG_CHANNEL(GPU);
|
||||
|
||||
std::unique_ptr<GPUBackend> g_gpu_backend;
|
||||
|
||||
|
@ -217,7 +217,7 @@ void GPUBackend::Sync(bool allow_sleep)
|
|||
void GPUBackend::RunGPULoop()
|
||||
{
|
||||
static constexpr double SPIN_TIME_NS = 1 * 1000000;
|
||||
Common::Timer::Value last_command_time = 0;
|
||||
Timer::Value last_command_time = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -225,8 +225,8 @@ void GPUBackend::RunGPULoop()
|
|||
u32 read_ptr = m_command_fifo_read_ptr.load();
|
||||
if (read_ptr == write_ptr)
|
||||
{
|
||||
const Common::Timer::Value current_time = Common::Timer::GetCurrentValue();
|
||||
if (Common::Timer::ConvertValueToNanoseconds(current_time - last_command_time) < SPIN_TIME_NS)
|
||||
const Timer::Value current_time = Timer::GetCurrentValue();
|
||||
if (Timer::ConvertValueToNanoseconds(current_time - last_command_time) < SPIN_TIME_NS)
|
||||
continue;
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_sync_mutex);
|
||||
|
@ -273,7 +273,7 @@ void GPUBackend::RunGPULoop()
|
|||
}
|
||||
}
|
||||
|
||||
last_command_time = allow_sleep ? 0 : Common::Timer::GetCurrentValue();
|
||||
last_command_time = allow_sleep ? 0 : Timer::GetCurrentValue();
|
||||
m_command_fifo_read_ptr.store(read_ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
virtual ~GPUBackend();
|
||||
|
||||
ALWAYS_INLINE const Threading::Thread* GetThread() const { return m_use_gpu_thread ? &m_gpu_thread : nullptr; }
|
||||
ALWAYS_INLINE bool IsUsingThread() const { return m_use_gpu_thread; }
|
||||
|
||||
virtual bool Initialize(bool use_thread);
|
||||
virtual void Reset();
|
||||
|
|
|
@ -267,7 +267,7 @@ bool GPU::HandleSetDrawingAreaBottomRightCommand()
|
|||
|
||||
const u32 right = param & DRAWING_AREA_COORD_MASK;
|
||||
const u32 bottom = (param >> 10) & DRAWING_AREA_COORD_MASK;
|
||||
DEBUG_LOG("Set drawing area bottom-right: ({}, {})", m_drawing_area.right, m_drawing_area.bottom);
|
||||
DEBUG_LOG("Set drawing area bottom-right: ({}, {})", right, bottom);
|
||||
if (m_drawing_area.right != right || m_drawing_area.bottom != bottom)
|
||||
{
|
||||
FlushRender();
|
||||
|
@ -288,7 +288,7 @@ bool GPU::HandleSetDrawingOffsetCommand()
|
|||
const u32 param = FifoPop() & 0x00FFFFFFu;
|
||||
const s32 x = SignExtendN<11, s32>(param & 0x7FFu);
|
||||
const s32 y = SignExtendN<11, s32>((param >> 11) & 0x7FFu);
|
||||
DEBUG_LOG("Set drawing offset ({}, {})", m_drawing_offset.x, m_drawing_offset.y);
|
||||
DEBUG_LOG("Set drawing offset ({}, {})", x, y);
|
||||
if (m_drawing_offset.x != x || m_drawing_offset.y != y)
|
||||
{
|
||||
FlushRender();
|
||||
|
|
|
@ -320,7 +320,7 @@ std::unique_ptr<GPUDump::Player> GPUDump::Player::Open(std::string path, Error*
|
|||
{
|
||||
std::unique_ptr<Player> ret;
|
||||
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
|
||||
std::optional<DynamicHeapArray<u8>> data;
|
||||
if (StringUtil::EndsWithNoCase(path, ".psxgpu.zst") || StringUtil::EndsWithNoCase(path, ".psxgpu.xz"))
|
||||
|
@ -507,7 +507,7 @@ bool GPUDump::Player::FindFrameStarts(Error* error)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
for (size_t i = 0; i < m_frame_offsets.size(); i++)
|
||||
DEBUG_LOG("Frame {} starts at offset {}", i, m_frame_offsets[i]);
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ static constexpr GPUTexture::Format VRAM_DS_FORMAT = GPUTexture::Format::D16;
|
|||
static constexpr GPUTexture::Format VRAM_DS_DEPTH_FORMAT = GPUTexture::Format::D32F;
|
||||
static constexpr GPUTexture::Format VRAM_DS_COLOR_FORMAT = GPUTexture::Format::R32F;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
|
||||
static u32 s_draw_number = 0;
|
||||
|
||||
|
@ -152,8 +152,8 @@ class ShaderCompileProgressTracker
|
|||
{
|
||||
public:
|
||||
ShaderCompileProgressTracker(std::string title, u32 total)
|
||||
: m_title(std::move(title)), m_min_time(Common::Timer::ConvertSecondsToValue(1.0)),
|
||||
m_update_interval(Common::Timer::ConvertSecondsToValue(0.1)), m_start_time(Common::Timer::GetCurrentValue()),
|
||||
: m_title(std::move(title)), m_min_time(Timer::ConvertSecondsToValue(1.0)),
|
||||
m_update_interval(Timer::ConvertSecondsToValue(0.1)), m_start_time(Timer::GetCurrentValue()),
|
||||
m_last_update_time(0), m_progress(0), m_total(total)
|
||||
{
|
||||
}
|
||||
|
@ -161,14 +161,14 @@ public:
|
|||
|
||||
double GetElapsedMilliseconds() const
|
||||
{
|
||||
return Common::Timer::ConvertValueToMilliseconds(Common::Timer::GetCurrentValue() - m_start_time);
|
||||
return Timer::ConvertValueToMilliseconds(Timer::GetCurrentValue() - m_start_time);
|
||||
}
|
||||
|
||||
void Increment(u32 progress = 1)
|
||||
{
|
||||
m_progress += progress;
|
||||
|
||||
const u64 tv = Common::Timer::GetCurrentValue();
|
||||
const u64 tv = Timer::GetCurrentValue();
|
||||
if ((tv - m_start_time) >= m_min_time && (tv - m_last_update_time) >= m_update_interval)
|
||||
{
|
||||
Host::DisplayLoadingScreen(m_title.c_str(), 0, static_cast<int>(m_total), static_cast<int>(m_progress));
|
||||
|
@ -178,10 +178,10 @@ public:
|
|||
|
||||
private:
|
||||
std::string m_title;
|
||||
Common::Timer::Value m_min_time;
|
||||
Common::Timer::Value m_update_interval;
|
||||
Common::Timer::Value m_start_time;
|
||||
Common::Timer::Value m_last_update_time;
|
||||
Timer::Value m_min_time;
|
||||
Timer::Value m_update_interval;
|
||||
Timer::Value m_start_time;
|
||||
Timer::Value m_last_update_time;
|
||||
u32 m_progress;
|
||||
u32 m_total;
|
||||
};
|
||||
|
@ -189,7 +189,7 @@ private:
|
|||
|
||||
GPU_HW::GPU_HW() : GPU()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
s_draw_number = 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -1612,7 +1612,7 @@ bool GPU_HW::CompilePipelines(Error* error)
|
|||
|
||||
bool GPU_HW::CompileResolutionDependentPipelines(Error* error)
|
||||
{
|
||||
Common::Timer timer;
|
||||
Timer timer;
|
||||
|
||||
m_vram_readback_pipeline.reset();
|
||||
for (std::unique_ptr<GPUPipeline>& p : m_vram_extract_pipeline)
|
||||
|
@ -3199,7 +3199,8 @@ void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
|||
GL_SCOPE_FMT("FillVRAM({},{} => {},{} ({}x{}) with 0x{:08X}", x, y, x + width, y + height, width, height, color);
|
||||
DeactivateROV();
|
||||
|
||||
if (m_sw_renderer)
|
||||
const bool handle_with_tc = (m_use_texture_cache && !IsInterlacedRenderingEnabled());
|
||||
if (m_sw_renderer && !handle_with_tc)
|
||||
{
|
||||
GPUBackendFillVRAMCommand* cmd = m_sw_renderer->NewFillVRAMCommand();
|
||||
FillBackendCommandParameters(cmd);
|
||||
|
@ -3216,7 +3217,7 @@ void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
|
|||
const GSVector4i bounds = GetVRAMTransferBounds(x, y, width, height);
|
||||
|
||||
// If TC is enabled, we have to update local memory.
|
||||
if (m_use_texture_cache && !IsInterlacedRenderingEnabled())
|
||||
if (handle_with_tc)
|
||||
{
|
||||
AddWrittenRectangle(bounds);
|
||||
GPU_SW_Rasterizer::FillVRAM(x, y, width, height, color, false, 0);
|
||||
|
@ -3328,7 +3329,7 @@ void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, b
|
|||
DebugAssert(bounds.right <= static_cast<s32>(VRAM_WIDTH) && bounds.bottom <= static_cast<s32>(VRAM_HEIGHT));
|
||||
AddWrittenRectangle(bounds);
|
||||
|
||||
if (m_sw_renderer)
|
||||
if (m_sw_renderer && m_sw_renderer->IsUsingThread())
|
||||
{
|
||||
const u32 num_words = width * height;
|
||||
GPUBackendUpdateVRAMCommand* cmd = m_sw_renderer->NewUpdateVRAMCommand(num_words);
|
||||
|
@ -3785,7 +3786,7 @@ void GPU_HW::FlushRender()
|
|||
if (index_count == 0)
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
GL_SCOPE_FMT("Hardware Draw {}: {}", ++s_draw_number, m_current_draw_rect);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
|
||||
LOG_CHANNEL(GPUTextureCache);
|
||||
LOG_CHANNEL(GPU_HW);
|
||||
|
||||
#include "common/ryml_helpers.h"
|
||||
|
||||
|
@ -242,6 +242,7 @@ static bool ShouldTrackVRAMWrites();
|
|||
static bool IsDumpingVRAMWriteTextures();
|
||||
static void UpdateVRAMTrackingState();
|
||||
|
||||
static void SetHashCacheTextureFormat();
|
||||
static bool CompilePipelines();
|
||||
static void DestroyPipelines();
|
||||
|
||||
|
@ -280,11 +281,14 @@ static void RemoveVRAMWrite(VRAMWrite* entry);
|
|||
static void DumpTexturesFromVRAMWrite(VRAMWrite* entry);
|
||||
static void DumpTextureFromPage(const Source* src);
|
||||
|
||||
static void DecodeTexture(GPUTextureMode mode, const u16* page_ptr, const u16* palette, u32* dest, u32 dest_stride,
|
||||
u32 width, u32 height);
|
||||
static void DecodeTexture4(const u16* page, const u16* palette, u32 width, u32 height, u32* dest, u32 dest_stride);
|
||||
static void DecodeTexture8(const u16* page, const u16* palette, u32 width, u32 height, u32* dest, u32 dest_stride);
|
||||
static void DecodeTexture16(const u16* page, u32 width, u32 height, u32* dest, u32 dest_stride);
|
||||
static void DecodeTexture(GPUTextureMode mode, const u16* page_ptr, const u16* palette, u8* dest, u32 dest_stride,
|
||||
u32 width, u32 height, GPUTexture::Format dest_format);
|
||||
template<GPUTexture::Format dest_format>
|
||||
static void DecodeTexture4(const u16* page, const u16* palette, u32 width, u32 height, u8* dest, u32 dest_stride);
|
||||
template<GPUTexture::Format dest_format>
|
||||
static void DecodeTexture8(const u16* page, const u16* palette, u32 width, u32 height, u8* dest, u32 dest_stride);
|
||||
template<GPUTexture::Format dest_format>
|
||||
static void DecodeTexture16(const u16* page, u32 width, u32 height, u8* dest, u32 dest_stride);
|
||||
static void DecodeTexture(u8 page, GPUTexturePaletteReg palette, GPUTextureMode mode, GPUTexture* texture);
|
||||
|
||||
static std::optional<TextureReplacementType> GetTextureReplacementTypeFromFileTitle(const std::string_view file_title);
|
||||
|
@ -512,6 +516,7 @@ struct GPUTextureCacheState
|
|||
VRAMWrite* last_vram_write = nullptr;
|
||||
bool track_vram_writes = false;
|
||||
|
||||
GPUTexture::Format hash_cache_texture_format = GPUTexture::Format::Unknown;
|
||||
HashCache hash_cache;
|
||||
|
||||
/// List of candidates for purging when the hash cache gets too large.
|
||||
|
@ -568,6 +573,7 @@ bool GPUTextureCache::IsDumpingVRAMWriteTextures()
|
|||
|
||||
bool GPUTextureCache::Initialize()
|
||||
{
|
||||
SetHashCacheTextureFormat();
|
||||
LoadLocalConfiguration(false, false);
|
||||
UpdateVRAMTrackingState();
|
||||
if (!CompilePipelines())
|
||||
|
@ -770,6 +776,17 @@ void GPUTextureCache::Shutdown()
|
|||
s_state.game_id = {};
|
||||
}
|
||||
|
||||
void GPUTextureCache::SetHashCacheTextureFormat()
|
||||
{
|
||||
// Prefer 16-bit texture formats where possible.
|
||||
if (g_gpu_device->SupportsTextureFormat(GPUTexture::Format::RGB5A1))
|
||||
s_state.hash_cache_texture_format = GPUTexture::Format::RGB5A1;
|
||||
else
|
||||
s_state.hash_cache_texture_format = GPUTexture::Format::RGBA8;
|
||||
|
||||
INFO_LOG("Using {} format for hash cache entries.", GPUTexture::GetFormatName(s_state.hash_cache_texture_format));
|
||||
}
|
||||
|
||||
bool GPUTextureCache::CompilePipelines()
|
||||
{
|
||||
if (!g_settings.texture_replacements.enable_texture_replacements)
|
||||
|
@ -1063,29 +1080,116 @@ ALWAYS_INLINE_RELEASE static const u16* VRAMPalettePointer(GPUTexturePaletteReg
|
|||
return &g_vram[VRAM_WIDTH * palette.GetYBase() + palette.GetXBase()];
|
||||
}
|
||||
|
||||
// TODO: Vectorize these with gather.
|
||||
void GPUTextureCache::DecodeTexture4(const u16* page, const u16* palette, u32 width, u32 height, u32* dest,
|
||||
template<GPUTexture::Format format>
|
||||
ALWAYS_INLINE static void WriteDecodedTexel(u8*& dest, u16 c16)
|
||||
{
|
||||
if constexpr (format == GPUTexture::Format::RGBA8)
|
||||
{
|
||||
const u32 c32 = VRAMRGBA5551ToRGBA8888(c16);
|
||||
std::memcpy(std::assume_aligned<sizeof(c32)>(dest), &c32, sizeof(c32));
|
||||
dest += sizeof(c32);
|
||||
}
|
||||
else if constexpr (format == GPUTexture::Format::RGB5A1)
|
||||
{
|
||||
const u16 repacked = (c16 & 0x83E0) | ((c16 >> 10) & 0x1F) | ((c16 & 0x1F) << 10);
|
||||
std::memcpy(std::assume_aligned<sizeof(repacked)>(dest), &repacked, sizeof(repacked));
|
||||
dest += sizeof(repacked);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CPU_ARCH_SIMD
|
||||
|
||||
ALWAYS_INLINE static GSVector4i VRAM5BitTo8Bit(GSVector4i val)
|
||||
{
|
||||
return val.mul32l(GSVector4i::cxpr(527)).add32(GSVector4i::cxpr(23)).srl32<6>();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static GSVector4i VRAMRGB5A1ToRGBA8888(GSVector4i val)
|
||||
{
|
||||
static constexpr GSVector4i cmask = GSVector4i::cxpr(0x1F);
|
||||
|
||||
const GSVector4i r = VRAM5BitTo8Bit(val & cmask);
|
||||
const GSVector4i g = VRAM5BitTo8Bit((val.srl32<5>() & cmask));
|
||||
const GSVector4i b = VRAM5BitTo8Bit((val.srl32<10>() & cmask));
|
||||
const GSVector4i a = val.srl32<15>().sll32<31>().sra32<7>();
|
||||
|
||||
return r | g.sll32<8>() | b.sll32<16>() | b.sll32<24>() | a;
|
||||
}
|
||||
|
||||
template<GPUTexture::Format format>
|
||||
ALWAYS_INLINE static void WriteDecodedTexels(u8*& dest, GSVector4i c16)
|
||||
{
|
||||
if constexpr (format == GPUTexture::Format::RGBA8)
|
||||
{
|
||||
const GSVector4i low = VRAMRGB5A1ToRGBA8888(c16.upl16());
|
||||
const GSVector4i high = VRAMRGB5A1ToRGBA8888(c16.uph16());
|
||||
|
||||
GSVector4i::store<false>(dest, low);
|
||||
dest += sizeof(GSVector4i);
|
||||
|
||||
GSVector4i::store<false>(dest, high);
|
||||
dest += sizeof(GSVector4i);
|
||||
}
|
||||
else if constexpr (format == GPUTexture::Format::RGB5A1)
|
||||
{
|
||||
static constexpr GSVector4i cmask = GSVector4i::cxpr16(0x1F);
|
||||
|
||||
const GSVector4i repacked =
|
||||
(c16 & GSVector4i::cxpr16(static_cast<s16>(0x83E0))) | (c16.srl16<10>() & cmask) | (c16 & cmask).sll16<10>();
|
||||
|
||||
GSVector4i::store<false>(dest, repacked);
|
||||
dest += sizeof(GSVector4i);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<GPUTexture::Format format>
|
||||
void GPUTextureCache::DecodeTexture4(const u16* page, const u16* palette, u32 width, u32 height, u8* dest,
|
||||
u32 dest_stride)
|
||||
{
|
||||
if ((width % 4u) == 0)
|
||||
{
|
||||
const u32 vram_width = width / 4;
|
||||
[[maybe_unused]] constexpr u32 vram_pixels_per_vec = 2;
|
||||
[[maybe_unused]] const u32 aligned_vram_width = Common::AlignDownPow2(vram_width, vram_pixels_per_vec);
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u16* page_ptr = page;
|
||||
u32* dest_ptr = dest;
|
||||
u8* dest_ptr = dest;
|
||||
u32 x = 0;
|
||||
|
||||
for (u32 x = 0; x < vram_width; x++)
|
||||
#ifdef CPU_ARCH_SIMD
|
||||
for (; x < aligned_vram_width; x += vram_pixels_per_vec)
|
||||
{
|
||||
// No variable shift without AVX, kinda pointless to vectorize the extract...
|
||||
alignas(VECTOR_ALIGNMENT) u16 c16[vram_pixels_per_vec * 4];
|
||||
u32 pp = *(page_ptr++);
|
||||
c16[0] = palette[pp & 0x0F];
|
||||
c16[1] = palette[(pp >> 4) & 0x0F];
|
||||
c16[2] = palette[(pp >> 8) & 0x0F];
|
||||
c16[3] = palette[pp >> 12];
|
||||
pp = *(page_ptr++);
|
||||
c16[4] = palette[pp & 0x0F];
|
||||
c16[5] = palette[(pp >> 4) & 0x0F];
|
||||
c16[6] = palette[(pp >> 8) & 0x0F];
|
||||
c16[7] = palette[pp >> 12];
|
||||
WriteDecodedTexels<format>(dest_ptr, GSVector4i::load<true>(c16));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; x < vram_width; x++)
|
||||
{
|
||||
const u32 pp = *(page_ptr++);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[pp & 0x0F]);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[(pp >> 4) & 0x0F]);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[(pp >> 8) & 0x0F]);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[pp >> 12]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[pp & 0x0F]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[(pp >> 4) & 0x0F]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[(pp >> 8) & 0x0F]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[pp >> 12]);
|
||||
}
|
||||
|
||||
page += VRAM_WIDTH;
|
||||
dest = reinterpret_cast<u32*>(reinterpret_cast<u8*>(dest) + dest_stride);
|
||||
dest += dest_stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1093,7 +1197,7 @@ void GPUTextureCache::DecodeTexture4(const u16* page, const u16* palette, u32 wi
|
|||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u16* page_ptr = page;
|
||||
u32* dest_ptr = dest;
|
||||
u8* dest_ptr = dest;
|
||||
|
||||
u32 offs = 0;
|
||||
u16 texel = 0;
|
||||
|
@ -1102,37 +1206,64 @@ void GPUTextureCache::DecodeTexture4(const u16* page, const u16* palette, u32 wi
|
|||
if (offs == 0)
|
||||
texel = *(page_ptr++);
|
||||
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[texel & 0x0F]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[texel & 0x0F]);
|
||||
texel >>= 4;
|
||||
|
||||
offs = (offs + 1) % 4;
|
||||
}
|
||||
|
||||
page += VRAM_WIDTH;
|
||||
dest = reinterpret_cast<u32*>(reinterpret_cast<u8*>(dest) + dest_stride);
|
||||
dest += dest_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
void GPUTextureCache::DecodeTexture8(const u16* page, const u16* palette, u32 width, u32 height, u32* dest,
|
||||
|
||||
template<GPUTexture::Format format>
|
||||
void GPUTextureCache::DecodeTexture8(const u16* page, const u16* palette, u32 width, u32 height, u8* dest,
|
||||
u32 dest_stride)
|
||||
{
|
||||
if ((width % 2u) == 0)
|
||||
{
|
||||
const u32 vram_width = width / 2;
|
||||
[[maybe_unused]] constexpr u32 vram_pixels_per_vec = 4;
|
||||
[[maybe_unused]] const u32 aligned_vram_width = Common::AlignDownPow2(vram_width, vram_pixels_per_vec);
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u16* page_ptr = page;
|
||||
u32* dest_ptr = dest;
|
||||
u8* dest_ptr = dest;
|
||||
u32 x = 0;
|
||||
|
||||
for (u32 x = 0; x < vram_width; x++)
|
||||
#ifdef CPU_ARCH_SIMD
|
||||
for (; x < aligned_vram_width; x += vram_pixels_per_vec)
|
||||
{
|
||||
// No variable shift without AVX, kinda pointless to vectorize the extract...
|
||||
alignas(VECTOR_ALIGNMENT) u16 c16[vram_pixels_per_vec * 2];
|
||||
u32 pp = *(page_ptr++);
|
||||
c16[0] = palette[pp & 0xFF];
|
||||
c16[1] = palette[(pp >> 8) & 0xFF];
|
||||
pp = *(page_ptr++);
|
||||
c16[2] = palette[pp & 0xFF];
|
||||
c16[3] = palette[(pp >> 8) & 0xFF];
|
||||
pp = *(page_ptr++);
|
||||
c16[4] = palette[pp & 0xFF];
|
||||
c16[5] = palette[(pp >> 8) & 0xFF];
|
||||
pp = *(page_ptr++);
|
||||
c16[6] = palette[pp & 0xFF];
|
||||
c16[7] = palette[(pp >> 8) & 0xFF];
|
||||
WriteDecodedTexels<format>(dest_ptr, GSVector4i::load<true>(c16));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; x < vram_width; x++)
|
||||
{
|
||||
const u32 pp = *(page_ptr++);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[pp & 0xFF]);
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[pp >> 8]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[pp & 0xFF]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[pp >> 8]);
|
||||
}
|
||||
|
||||
page += VRAM_WIDTH;
|
||||
dest = reinterpret_cast<u32*>(reinterpret_cast<u8*>(dest) + dest_stride);
|
||||
dest += dest_stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1140,7 +1271,7 @@ void GPUTextureCache::DecodeTexture8(const u16* page, const u16* palette, u32 wi
|
|||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u16* page_ptr = page;
|
||||
u32* dest_ptr = dest;
|
||||
u8* dest_ptr = dest;
|
||||
|
||||
u32 offs = 0;
|
||||
u16 texel = 0;
|
||||
|
@ -1149,70 +1280,110 @@ void GPUTextureCache::DecodeTexture8(const u16* page, const u16* palette, u32 wi
|
|||
if (offs == 0)
|
||||
texel = *(page_ptr++);
|
||||
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(palette[texel & 0xFF]);
|
||||
WriteDecodedTexel<format>(dest_ptr, palette[texel & 0xFF]);
|
||||
texel >>= 8;
|
||||
|
||||
offs ^= 1;
|
||||
}
|
||||
|
||||
page += VRAM_WIDTH;
|
||||
dest = reinterpret_cast<u32*>(reinterpret_cast<u8*>(dest) + dest_stride);
|
||||
dest += dest_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUTextureCache::DecodeTexture16(const u16* page, u32 width, u32 height, u32* dest, u32 dest_stride)
|
||||
template<GPUTexture::Format format>
|
||||
void GPUTextureCache::DecodeTexture16(const u16* page, u32 width, u32 height, u8* dest, u32 dest_stride)
|
||||
{
|
||||
[[maybe_unused]] constexpr u32 pixels_per_vec = 8;
|
||||
[[maybe_unused]] const u32 aligned_width = Common::AlignDownPow2(width, pixels_per_vec);
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u16* page_ptr = page;
|
||||
u32* dest_ptr = dest;
|
||||
u8* dest_ptr = dest;
|
||||
u32 x = 0;
|
||||
|
||||
for (u32 x = 0; x < width; x++)
|
||||
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(*(page_ptr++));
|
||||
#ifdef CPU_ARCH_SIMD
|
||||
for (; x < aligned_width; x += pixels_per_vec)
|
||||
{
|
||||
WriteDecodedTexels<format>(dest_ptr, GSVector4i::load<false>(page_ptr));
|
||||
page_ptr += pixels_per_vec;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; x < width; x++)
|
||||
WriteDecodedTexel<format>(dest_ptr, *(page_ptr++));
|
||||
|
||||
page += VRAM_WIDTH;
|
||||
dest = reinterpret_cast<u32*>(reinterpret_cast<u8*>(dest) + dest_stride);
|
||||
dest += dest_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUTextureCache::DecodeTexture(GPUTextureMode mode, const u16* page_ptr, const u16* palette, u32* dest,
|
||||
u32 dest_stride, u32 width, u32 height)
|
||||
void GPUTextureCache::DecodeTexture(GPUTextureMode mode, const u16* page_ptr, const u16* palette, u8* dest,
|
||||
u32 dest_stride, u32 width, u32 height, GPUTexture::Format dest_format)
|
||||
{
|
||||
switch (mode)
|
||||
if (dest_format == GPUTexture::Format::RGBA8)
|
||||
{
|
||||
case GPUTextureMode::Palette4Bit:
|
||||
DecodeTexture4(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Palette8Bit:
|
||||
DecodeTexture8(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Direct16Bit:
|
||||
case GPUTextureMode::Reserved_Direct16Bit:
|
||||
DecodeTexture16(page_ptr, width, height, dest, dest_stride);
|
||||
break;
|
||||
switch (mode)
|
||||
{
|
||||
case GPUTextureMode::Palette4Bit:
|
||||
DecodeTexture4<GPUTexture::Format::RGBA8>(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Palette8Bit:
|
||||
DecodeTexture8<GPUTexture::Format::RGBA8>(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Direct16Bit:
|
||||
case GPUTextureMode::Reserved_Direct16Bit:
|
||||
DecodeTexture16<GPUTexture::Format::RGBA8>(page_ptr, width, height, dest, dest_stride);
|
||||
break;
|
||||
|
||||
DefaultCaseIsUnreachable()
|
||||
DefaultCaseIsUnreachable()
|
||||
}
|
||||
}
|
||||
else if (dest_format == GPUTexture::Format::RGB5A1)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case GPUTextureMode::Palette4Bit:
|
||||
DecodeTexture4<GPUTexture::Format::RGB5A1>(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Palette8Bit:
|
||||
DecodeTexture8<GPUTexture::Format::RGB5A1>(page_ptr, palette, width, height, dest, dest_stride);
|
||||
break;
|
||||
case GPUTextureMode::Direct16Bit:
|
||||
case GPUTextureMode::Reserved_Direct16Bit:
|
||||
DecodeTexture16<GPUTexture::Format::RGB5A1>(page_ptr, width, height, dest, dest_stride);
|
||||
break;
|
||||
|
||||
DefaultCaseIsUnreachable()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Panic("Unsupported texture format.");
|
||||
}
|
||||
}
|
||||
|
||||
void GPUTextureCache::DecodeTexture(u8 page, GPUTexturePaletteReg palette, GPUTextureMode mode, GPUTexture* texture)
|
||||
{
|
||||
alignas(16) static u32 s_temp_buffer[TEXTURE_PAGE_WIDTH * TEXTURE_PAGE_HEIGHT];
|
||||
alignas(16) static u8 s_temp_buffer[TEXTURE_PAGE_WIDTH * TEXTURE_PAGE_HEIGHT * sizeof(u32)];
|
||||
|
||||
u32* tex_map;
|
||||
const u32 ps = texture->GetPixelSize();
|
||||
u8* tex_map;
|
||||
u32 tex_stride;
|
||||
const bool mapped =
|
||||
texture->Map(reinterpret_cast<void**>(&tex_map), &tex_stride, 0, 0, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT);
|
||||
if (!mapped)
|
||||
{
|
||||
tex_map = s_temp_buffer;
|
||||
tex_stride = sizeof(u32) * TEXTURE_PAGE_WIDTH;
|
||||
tex_stride = Common::AlignUpPow2(ps * TEXTURE_PAGE_WIDTH, 4);
|
||||
}
|
||||
|
||||
const u16* page_ptr = VRAMPagePointer(page);
|
||||
const u16* palette_ptr = TextureModeHasPalette(mode) ? VRAMPalettePointer(palette) : nullptr;
|
||||
DecodeTexture(mode, page_ptr, palette_ptr, tex_map, tex_stride, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT);
|
||||
DecodeTexture(mode, page_ptr, palette_ptr, tex_map, tex_stride, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT,
|
||||
texture->GetFormat());
|
||||
|
||||
if (mapped)
|
||||
texture->Unmap();
|
||||
|
@ -1242,7 +1413,7 @@ const GPUTextureCache::Source* GPUTextureCache::LookupSource(SourceKey key, cons
|
|||
const GPUTextureCache::Source* GPUTextureCache::ReturnSource(Source* source, const GSVector4i uv_rect,
|
||||
PaletteRecordFlags flags)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
// GL_INS_FMT("Tex hash: {:016X}", source->texture_hash);
|
||||
// GL_INS_FMT("Palette hash: {:016X}", source->palette_hash);
|
||||
if (!uv_rect.eq(INVALID_RECT))
|
||||
|
@ -1300,7 +1471,7 @@ bool GPUTextureCache::IsRectDrawn(const GSVector4i rect)
|
|||
bool GPUTextureCache::AreSourcePagesDrawn(SourceKey key, const GSVector4i rect)
|
||||
{
|
||||
// NOTE: This doesn't handle VRAM wrapping. But neither does the caller. YOLO?
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
{
|
||||
for (u32 offset = 0; offset < TexturePageCountForMode(key.mode); offset++)
|
||||
{
|
||||
|
@ -1358,7 +1529,7 @@ void GPUTextureCache::Invalidate()
|
|||
}
|
||||
|
||||
// should all be null
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
for (u32 i = 0; i < NUM_VRAM_PAGES; i++)
|
||||
DebugAssert(!s_state.pages[i].sources.head && !s_state.pages[i].sources.tail);
|
||||
DebugAssert(!s_state.last_vram_write);
|
||||
|
@ -1787,7 +1958,7 @@ void GPUTextureCache::RemoveVRAMWrite(VRAMWrite* entry)
|
|||
LoopRectPagesWithEarlyExit(entry->write_rect, [&entry, &other_write](u32 pn) {
|
||||
PageEntry& pg = s_state.pages[pn];
|
||||
ListIterateWithEarlyExit(pg.writes, [&entry, &other_write](VRAMWrite* cur) {
|
||||
if (cur->hash != entry->hash)
|
||||
if (cur == entry || cur->hash != entry->hash)
|
||||
return true;
|
||||
|
||||
other_write = cur;
|
||||
|
@ -2064,7 +2235,7 @@ GPUTextureCache::HashCacheEntry* GPUTextureCache::LookupHashCache(SourceKey key,
|
|||
entry.sources = {};
|
||||
entry.texture =
|
||||
g_gpu_device->FetchTexture(TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_HEIGHT, 1, 1, 1, GPUTexture::Type::Texture,
|
||||
GPUTexture::Format::RGBA8, GPUTexture::Flags::None);
|
||||
s_state.hash_cache_texture_format, GPUTexture::Flags::None);
|
||||
if (!entry.texture)
|
||||
{
|
||||
ERROR_LOG("Failed to create texture.");
|
||||
|
@ -2616,8 +2787,8 @@ void GPUTextureCache::DumpTexture(TextureReplacementType type, u32 offset_x, u32
|
|||
DEV_LOG("Dumping VRAM write {:016X} [{}x{}] at {}", src_hash, width, height, rect);
|
||||
|
||||
Image image(width, height, ImageFormat::RGBA8);
|
||||
GPUTextureCache::DecodeTexture(mode, &g_vram[rect.top * VRAM_WIDTH + rect.left], palette_data,
|
||||
reinterpret_cast<u32*>(image.GetPixels()), image.GetPitch(), width, height);
|
||||
GPUTextureCache::DecodeTexture(mode, &g_vram[rect.top * VRAM_WIDTH + rect.left], palette_data, image.GetPixels(),
|
||||
image.GetPitch(), width, height, GPUTexture::Format::RGBA8);
|
||||
|
||||
// TODO: Vectorize this.
|
||||
u32* image_pixels = reinterpret_cast<u32*>(image.GetPixels());
|
||||
|
@ -3100,7 +3271,7 @@ void GPUTextureCache::PreloadReplacementTextures()
|
|||
{
|
||||
static constexpr float UPDATE_INTERVAL = 1.0f;
|
||||
|
||||
Common::Timer last_update_time;
|
||||
Timer last_update_time;
|
||||
u32 num_textures_loaded = 0;
|
||||
const size_t total_textures = s_state.vram_replacements.size() + s_state.vram_write_texture_replacements.size() +
|
||||
s_state.texture_page_texture_replacements.size();
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
LOG_CHANNEL(GPU_SW);
|
||||
LOG_CHANNEL(GPU);
|
||||
|
||||
GPU_SW::GPU_SW() = default;
|
||||
|
||||
|
@ -41,10 +41,10 @@ bool GPU_SW::Initialize(Error* error)
|
|||
if (!GPU::Initialize(error) || !m_backend.Initialize(g_settings.gpu_use_thread))
|
||||
return false;
|
||||
|
||||
static constexpr const std::array formats_for_16bit = {GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551,
|
||||
static constexpr const std::array formats_for_16bit = {GPUTexture::Format::RGB565, GPUTexture::Format::RGB5A1,
|
||||
GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8};
|
||||
static constexpr const std::array formats_for_24bit = {GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8,
|
||||
GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551};
|
||||
GPUTexture::Format::RGB565, GPUTexture::Format::RGB5A1};
|
||||
for (const GPUTexture::Format format : formats_for_16bit)
|
||||
{
|
||||
if (g_gpu_device->SupportsTextureFormat(format))
|
||||
|
@ -115,7 +115,7 @@ template<GPUTexture::Format out_format, typename out_type>
|
|||
static out_type VRAM16ToOutput(u16 value);
|
||||
|
||||
template<>
|
||||
ALWAYS_INLINE u16 VRAM16ToOutput<GPUTexture::Format::RGBA5551, u16>(u16 value)
|
||||
ALWAYS_INLINE u16 VRAM16ToOutput<GPUTexture::Format::RGB5A1, u16>(u16 value)
|
||||
{
|
||||
return (value & 0x3E0) | ((value >> 10) & 0x1F) | ((value & 0x1F) << 10);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ ALWAYS_INLINE u32 VRAM16ToOutput<GPUTexture::Format::BGRA8, u32>(u16 value)
|
|||
}
|
||||
|
||||
template<>
|
||||
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGBA5551, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
|
||||
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGB5A1, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
|
||||
{
|
||||
u32 col = 0;
|
||||
|
||||
|
@ -167,7 +167,7 @@ ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGBA5551, u16>(const u16* sr
|
|||
}
|
||||
|
||||
for (; col < width; col++)
|
||||
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::RGBA5551, u16>(*(src_ptr++));
|
||||
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::RGB5A1, u16>(*(src_ptr++));
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -317,7 +317,7 @@ ALWAYS_INLINE_RELEASE bool GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x
|
|||
src_row_ptr += 3;
|
||||
}
|
||||
}
|
||||
else if constexpr (display_format == GPUTexture::Format::RGBA5551)
|
||||
else if constexpr (display_format == GPUTexture::Format::RGB5A1)
|
||||
{
|
||||
const u8* src_row_ptr = src_ptr;
|
||||
u16* dst_row_ptr = reinterpret_cast<u16*>(dst_ptr);
|
||||
|
@ -362,7 +362,7 @@ ALWAYS_INLINE_RELEASE bool GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x
|
|||
{
|
||||
*(dst_row_ptr++) = ((rgb >> 3) & 0x1F) | (((rgb >> 10) << 5) & 0x7E0) | (((rgb >> 19) << 11) & 0x3E0000);
|
||||
}
|
||||
else if constexpr (display_format == GPUTexture::Format::RGBA5551)
|
||||
else if constexpr (display_format == GPUTexture::Format::RGB5A1)
|
||||
{
|
||||
*(dst_row_ptr++) = ((rgb >> 3) & 0x1F) | (((rgb >> 11) << 5) & 0x3E0) | (((rgb >> 19) << 10) & 0x1F0000);
|
||||
}
|
||||
|
@ -389,8 +389,8 @@ bool GPU_SW::CopyOut(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, u3
|
|||
|
||||
switch (m_16bit_display_format)
|
||||
{
|
||||
case GPUTexture::Format::RGBA5551:
|
||||
return CopyOut15Bit<GPUTexture::Format::RGBA5551>(src_x, src_y, width, height, line_skip);
|
||||
case GPUTexture::Format::RGB5A1:
|
||||
return CopyOut15Bit<GPUTexture::Format::RGB5A1>(src_x, src_y, width, height, line_skip);
|
||||
|
||||
case GPUTexture::Format::RGB565:
|
||||
return CopyOut15Bit<GPUTexture::Format::RGB565>(src_x, src_y, width, height, line_skip);
|
||||
|
@ -409,8 +409,8 @@ bool GPU_SW::CopyOut(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, u3
|
|||
{
|
||||
switch (m_24bit_display_format)
|
||||
{
|
||||
case GPUTexture::Format::RGBA5551:
|
||||
return CopyOut24Bit<GPUTexture::Format::RGBA5551>(src_x, src_y, skip_x, width, height, line_skip);
|
||||
case GPUTexture::Format::RGB5A1:
|
||||
return CopyOut24Bit<GPUTexture::Format::RGB5A1>(src_x, src_y, skip_x, width, height, line_skip);
|
||||
|
||||
case GPUTexture::Format::RGB565:
|
||||
return CopyOut24Bit<GPUTexture::Format::RGB565>(src_x, src_y, skip_x, width, height, line_skip);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
LOG_CHANNEL(GPU_SW_Rasterizer);
|
||||
LOG_CHANNEL(GPU_SW);
|
||||
|
||||
namespace GPU_SW_Rasterizer {
|
||||
constinit const DitherLUT g_dither_lut = []() constexpr {
|
||||
|
|
|
@ -1639,8 +1639,6 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in
|
|||
|
||||
static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask)
|
||||
{
|
||||
// TODO: Vector implementation
|
||||
|
||||
// Fast path when the copy is not oversized.
|
||||
if ((x + width) <= VRAM_WIDTH && (y + height) <= VRAM_HEIGHT && !set_mask && !check_mask)
|
||||
{
|
||||
|
@ -1661,10 +1659,49 @@ static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data,
|
|||
const u16 mask_and = check_mask ? 0x8000u : 0x0000u;
|
||||
const u16 mask_or = set_mask ? 0x8000u : 0x0000u;
|
||||
|
||||
#ifdef USE_VECTOR
|
||||
constexpr u32 write_pixels_per_vec = sizeof(GSVectorNi) / sizeof(u16);
|
||||
const u32 aligned_width = Common::AlignDownPow2(std::min(width, VRAM_WIDTH - x), write_pixels_per_vec);
|
||||
const GSVectorNi mask_or_vec = GSVectorNi::cxpr16(mask_or);
|
||||
const GSVectorNi mask_and_vec = GSVectorNi::cxpr16(mask_and);
|
||||
#endif
|
||||
|
||||
for (u32 row = 0; row < height;)
|
||||
{
|
||||
u16* dst_row_ptr = &g_vram[((y + row++) % VRAM_HEIGHT) * VRAM_WIDTH];
|
||||
for (u32 col = 0; col < width;)
|
||||
|
||||
u32 col = 0;
|
||||
|
||||
#ifdef USE_VECTOR
|
||||
// This doesn't do wraparound.
|
||||
if (mask_and != 0)
|
||||
{
|
||||
for (; col < aligned_width; col += write_pixels_per_vec)
|
||||
{
|
||||
const GSVectorNi src = GSVectorNi::load<false>(src_ptr);
|
||||
src_ptr += write_pixels_per_vec;
|
||||
|
||||
GSVectorNi dst = GSVectorNi::load<false>(&dst_row_ptr[x + col]);
|
||||
|
||||
const GSVectorNi mask = (dst & mask_and_vec).sra16<15>();
|
||||
dst = (dst & mask) | src.andnot(mask) | mask_or_vec;
|
||||
|
||||
GSVectorNi::store<false>(&dst_row_ptr[x + col], dst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; col < aligned_width; col += write_pixels_per_vec)
|
||||
{
|
||||
const GSVectorNi src = GSVectorNi::load<false>(src_ptr);
|
||||
src_ptr += write_pixels_per_vec;
|
||||
|
||||
GSVectorNi::store<false>(&dst_row_ptr[x + col], src | mask_or_vec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; col < width;)
|
||||
{
|
||||
// TODO: Handle unaligned reads...
|
||||
u16* pixel_ptr = &dst_row_ptr[(x + col++) % VRAM_WIDTH];
|
||||
|
@ -1678,8 +1715,6 @@ static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data,
|
|||
static void CopyVRAMImpl(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height, bool set_mask,
|
||||
bool check_mask)
|
||||
{
|
||||
// TODO: Vector implementation.
|
||||
|
||||
// Break up oversized copies. This behavior has not been verified on console.
|
||||
if ((src_x + width) > VRAM_WIDTH || (dst_x + width) > VRAM_WIDTH)
|
||||
{
|
||||
|
@ -1698,8 +1733,8 @@ static void CopyVRAMImpl(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width,
|
|||
{
|
||||
const u32 columns_to_copy =
|
||||
std::min<u32>(remaining_columns, std::min<u32>(VRAM_WIDTH - current_src_x, VRAM_WIDTH - current_dst_x));
|
||||
CopyVRAM(current_src_x, current_src_y, current_dst_x, current_dst_y, columns_to_copy, rows_to_copy, set_mask,
|
||||
check_mask);
|
||||
CopyVRAMImpl(current_src_x, current_src_y, current_dst_x, current_dst_y, columns_to_copy, rows_to_copy,
|
||||
set_mask, check_mask);
|
||||
current_src_x = (current_src_x + columns_to_copy) % VRAM_WIDTH;
|
||||
current_dst_x = (current_dst_x + columns_to_copy) % VRAM_WIDTH;
|
||||
remaining_columns -= columns_to_copy;
|
||||
|
@ -1735,12 +1770,47 @@ static void CopyVRAMImpl(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width,
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_VECTOR
|
||||
constexpr u32 copy_pixels_per_vec = sizeof(GSVectorNi) / sizeof(u16);
|
||||
const u32 aligned_width = Common::AlignDownPow2(
|
||||
std::min(width, std::min<u32>(VRAM_WIDTH - src_x, VRAM_WIDTH - dst_x)), copy_pixels_per_vec);
|
||||
const GSVectorNi mask_or_vec = GSVectorNi::cxpr16(mask_or);
|
||||
const GSVectorNi mask_and_vec = GSVectorNi::cxpr16(mask_and);
|
||||
#endif
|
||||
|
||||
for (u32 row = 0; row < height; row++)
|
||||
{
|
||||
const u16* src_row_ptr = &g_vram[((src_y + row) % VRAM_HEIGHT) * VRAM_WIDTH];
|
||||
u16* dst_row_ptr = &g_vram[((dst_y + row) % VRAM_HEIGHT) * VRAM_WIDTH];
|
||||
|
||||
for (u32 col = 0; col < width; col++)
|
||||
u32 col = 0;
|
||||
|
||||
#ifdef USE_VECTOR
|
||||
// This doesn't do wraparound.
|
||||
if (mask_and != 0)
|
||||
{
|
||||
for (; col < aligned_width; col += copy_pixels_per_vec)
|
||||
{
|
||||
const GSVectorNi src = GSVectorNi::load<false>(&src_row_ptr[src_x + col]);
|
||||
GSVectorNi dst = GSVectorNi::load<false>(&dst_row_ptr[dst_x + col]);
|
||||
|
||||
const GSVectorNi mask = (dst & mask_and_vec).sra16<15>();
|
||||
dst = (dst & mask) | src.andnot(mask) | mask_or_vec;
|
||||
|
||||
GSVectorNi::store<false>(&dst_row_ptr[dst_x + col], dst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; col < aligned_width; col += copy_pixels_per_vec)
|
||||
{
|
||||
const GSVectorNi src = GSVectorNi::load<false>(&src_row_ptr[src_x + col]);
|
||||
GSVectorNi::store<false>(&dst_row_ptr[dst_x + col], src | mask_or_vec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; col < width; col++)
|
||||
{
|
||||
const u16 src_pixel = src_row_ptr[(src_x + col) % VRAM_WIDTH];
|
||||
u16* dst_pixel_ptr = &dst_row_ptr[(dst_x + col) % VRAM_WIDTH];
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "util/state_wrapper.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
|
@ -18,10 +19,7 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#include "common/log.h"
|
||||
LOG_CHANNEL(GunCon);
|
||||
#endif
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
static constexpr std::array<u8, static_cast<size_t>(GunCon::Binding::ButtonCount)> s_button_indices = {{13, 3, 14}};
|
||||
|
||||
|
@ -264,13 +262,9 @@ std::unique_ptr<GunCon> GunCon::Create(u32 index)
|
|||
|
||||
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||
#define BUTTON(name, display_name, icon_name, binding, genb) \
|
||||
{ \
|
||||
name, display_name, icon_name, static_cast<u32>(binding), InputBindingInfo::Type::Button, genb \
|
||||
}
|
||||
{name, display_name, icon_name, static_cast<u32>(binding), InputBindingInfo::Type::Button, genb}
|
||||
#define HALFAXIS(name, display_name, icon_name, binding, genb) \
|
||||
{ \
|
||||
name, display_name, icon_name, static_cast<u32>(binding), InputBindingInfo::Type::HalfAxis, genb \
|
||||
}
|
||||
{name, display_name, icon_name, static_cast<u32>(binding), InputBindingInfo::Type::HalfAxis, genb}
|
||||
|
||||
// clang-format off
|
||||
{"Pointer", TRANSLATE_NOOP("GunCon", "Pointer/Aiming"), ICON_PF_MOUSE, static_cast<u32>(GunCon::Binding::ButtonCount), InputBindingInfo::Type::Pointer, GenericInputBinding::Unknown},
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
private:
|
||||
void Redraw(bool force);
|
||||
|
||||
Common::Timer m_open_time;
|
||||
Timer m_open_time;
|
||||
float m_open_delay = 1.0f;
|
||||
int m_last_progress_percent = -1;
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ struct InputBindingInfo
|
|||
Motor,
|
||||
Pointer, // Absolute pointer, does not receive any events, but is queryable.
|
||||
RelativePointer, // Receive relative mouse movement events, bind_index is offset by the axis.
|
||||
Device, // Used for special-purpose device selection, e.g. force feedback.
|
||||
Macro,
|
||||
};
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void InterruptController::SetLineState(IRQ irq, bool state)
|
|||
if (s_interrupt_line_state == prev_state)
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
if (!(prev_state & bit) && state)
|
||||
DEBUG_LOG("{} IRQ triggered", s_irq_names[static_cast<size_t>(irq)]);
|
||||
else if ((prev_state & bit) && !state)
|
||||
|
@ -84,7 +84,7 @@ void InterruptController::WriteRegister(u32 offset, u32 value)
|
|||
{
|
||||
case 0x00: // I_STATUS
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
const u32 cleared_bits = (s_interrupt_status_register & ~value);
|
||||
for (u32 i = 0; i < static_cast<u32>(IRQ::MaxCount); i++)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,638 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "jogcon.h"
|
||||
#include "host.h"
|
||||
#include "system.h"
|
||||
|
||||
#include "util/imgui_manager.h"
|
||||
#include "util/input_manager.h"
|
||||
#include "util/state_wrapper.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/bitutils.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include "IconsEmoji.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
JogCon::JogCon(u32 index) : Controller(index)
|
||||
{
|
||||
}
|
||||
|
||||
JogCon::~JogCon() = default;
|
||||
|
||||
ControllerType JogCon::GetType() const
|
||||
{
|
||||
return ControllerType::JogCon;
|
||||
}
|
||||
|
||||
void JogCon::Reset()
|
||||
{
|
||||
// Reset starts in jogcon mode?
|
||||
m_jogcon_mode = true;
|
||||
ResetTransferState();
|
||||
ResetMotorConfig();
|
||||
}
|
||||
|
||||
bool JogCon::DoState(StateWrapper& sw, bool apply_input_state)
|
||||
{
|
||||
if (!Controller::DoState(sw, apply_input_state))
|
||||
return false;
|
||||
|
||||
u16 button_state = m_button_state;
|
||||
s8 steering_state = m_steering_state;
|
||||
sw.Do(&button_state);
|
||||
sw.Do(&steering_state);
|
||||
if (apply_input_state)
|
||||
{
|
||||
m_button_state = button_state;
|
||||
m_steering_state = steering_state;
|
||||
}
|
||||
|
||||
sw.Do(&m_command);
|
||||
sw.Do(&m_command_step);
|
||||
sw.Do(&m_status_byte);
|
||||
sw.Do(&m_last_steering_state);
|
||||
sw.Do(&m_last_motor_command);
|
||||
sw.Do(&m_steering_hold_position);
|
||||
sw.Do(&m_steering_hold_strength);
|
||||
|
||||
sw.Do(&m_configuration_mode);
|
||||
|
||||
bool jogcon_mode = m_jogcon_mode;
|
||||
sw.Do(&jogcon_mode);
|
||||
if (jogcon_mode != m_jogcon_mode)
|
||||
SetJogConMode(jogcon_mode, true);
|
||||
|
||||
sw.Do(&m_rx_buffer);
|
||||
sw.Do(&m_tx_buffer);
|
||||
sw.Do(&m_rumble_config);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float JogCon::GetBindState(u32 index) const
|
||||
{
|
||||
if (index >= static_cast<u32>(Button::MaxCount))
|
||||
{
|
||||
const u32 sub_index = index - static_cast<u32>(Button::MaxCount);
|
||||
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||
return 0.0f;
|
||||
|
||||
return static_cast<float>(m_half_axis_state[sub_index]) * (1.0f / 255.0f);
|
||||
}
|
||||
else if (index < static_cast<u32>(Button::Mode))
|
||||
{
|
||||
return static_cast<float>(((m_button_state >> index) & 1u) ^ 1u);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void JogCon::SetBindState(u32 index, float value)
|
||||
{
|
||||
if (index == static_cast<u32>(Button::Mode))
|
||||
{
|
||||
// analog toggle
|
||||
if (value >= m_button_deadzone)
|
||||
{
|
||||
if (m_command == Command::Idle)
|
||||
SetJogConMode(!m_jogcon_mode, true);
|
||||
else
|
||||
m_mode_toggle_queued = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (index >= static_cast<u32>(Button::MaxCount))
|
||||
{
|
||||
const u32 sub_index = index - static_cast<u32>(Button::MaxCount);
|
||||
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||
return;
|
||||
|
||||
const u8 u8_value = static_cast<u8>(
|
||||
std::clamp(((value < m_analog_deadzone) ? 0.0f : value) * m_analog_sensitivity * 255.0f, 0.0f, 255.0f));
|
||||
if (u8_value == m_half_axis_state[sub_index])
|
||||
return;
|
||||
|
||||
m_half_axis_state[sub_index] = u8_value;
|
||||
System::SetRunaheadReplayFlag();
|
||||
|
||||
m_steering_state =
|
||||
(m_half_axis_state[static_cast<u32>(HalfAxis::SteeringRight)] != 0) ?
|
||||
static_cast<s8>((m_half_axis_state[static_cast<u32>(HalfAxis::SteeringRight)] / 2)) :
|
||||
-static_cast<s8>((static_cast<u32>(m_half_axis_state[static_cast<u32>(HalfAxis::SteeringLeft)]) + 1) / 2);
|
||||
}
|
||||
|
||||
const u16 bit = u16(1) << static_cast<u8>(index);
|
||||
|
||||
if (value >= m_button_deadzone)
|
||||
{
|
||||
if (m_button_state & bit)
|
||||
System::SetRunaheadReplayFlag();
|
||||
|
||||
m_button_state &= ~(bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(m_button_state & bit))
|
||||
System::SetRunaheadReplayFlag();
|
||||
|
||||
m_button_state |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
u32 JogCon::GetButtonStateBits() const
|
||||
{
|
||||
return m_button_state ^ 0xFFFF;
|
||||
}
|
||||
|
||||
void JogCon::ResetTransferState()
|
||||
{
|
||||
if (m_mode_toggle_queued)
|
||||
{
|
||||
SetJogConMode(!m_jogcon_mode, true);
|
||||
m_mode_toggle_queued = false;
|
||||
}
|
||||
|
||||
m_command = Command::Idle;
|
||||
m_command_step = 0;
|
||||
}
|
||||
|
||||
u32 JogCon::GetInputOverlayIconColor() const
|
||||
{
|
||||
return m_jogcon_mode ? 0xFF2534F0u : 0xFFCCCCCCu;
|
||||
}
|
||||
|
||||
void JogCon::SetJogConMode(bool enabled, bool show_message)
|
||||
{
|
||||
if (m_jogcon_mode == enabled)
|
||||
return;
|
||||
|
||||
m_jogcon_mode = enabled;
|
||||
m_configuration_mode = enabled && m_configuration_mode;
|
||||
|
||||
INFO_LOG("Controller {} switched to {} mode.", m_index + 1u, m_jogcon_mode ? "JogCon" : "Digital");
|
||||
if (show_message)
|
||||
{
|
||||
Host::AddIconOSDMessage(
|
||||
fmt::format("Controller{}JogConMode", m_index), ICON_PF_GAMEPAD_ALT,
|
||||
m_jogcon_mode ? fmt::format(TRANSLATE_FS("Controller", "Controller {} switched to JogCon mode."), m_index + 1u) :
|
||||
fmt::format(TRANSLATE_FS("Controller", "Controller {} switched to Digital mode."), m_index + 1u));
|
||||
}
|
||||
}
|
||||
|
||||
u8 JogCon::GetIDByte() const
|
||||
{
|
||||
return Truncate8((GetModeID() << 4) | GetResponseNumHalfwords());
|
||||
}
|
||||
|
||||
u8 JogCon::GetModeID() const
|
||||
{
|
||||
if (m_configuration_mode)
|
||||
return 0xF;
|
||||
else if (m_jogcon_mode)
|
||||
return 0xE;
|
||||
else
|
||||
return 0x4;
|
||||
}
|
||||
|
||||
u8 JogCon::GetResponseNumHalfwords() const
|
||||
{
|
||||
return m_jogcon_mode ? 3 : 1;
|
||||
}
|
||||
|
||||
void JogCon::SetMotorState(u8 value)
|
||||
{
|
||||
const u8 command = (value >> 4);
|
||||
const u8 strength = (value & 0x0F);
|
||||
|
||||
DEV_LOG("0x{:02X} command=0x{:X} force={}", value, command, strength);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case MOTOR_COMMAND_STOP:
|
||||
{
|
||||
m_steering_hold_strength = 0;
|
||||
SetMotorDirection(MOTOR_COMMAND_STOP, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_COMMAND_RIGHT:
|
||||
case MOTOR_COMMAND_LEFT:
|
||||
{
|
||||
m_steering_hold_strength = 0;
|
||||
SetMotorDirection(command, strength);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_COMMAND_HOLD:
|
||||
case MOTOR_COMMAND_DROP_REVOLUTIONS_AND_HOLD:
|
||||
{
|
||||
DEV_LOG("Hold wheel in position {} with {} strength.", m_steering_hold_position, strength);
|
||||
m_steering_hold_strength = strength;
|
||||
UpdateSteeringHold();
|
||||
|
||||
if (command == MOTOR_COMMAND_DROP_REVOLUTIONS_AND_HOLD)
|
||||
ERROR_LOG("JogCon Drop revolutions and hold command is not handled.");
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_COMMAND_DROP_REVOLUTIONS:
|
||||
{
|
||||
ERROR_LOG("JogCon drop revolutions command is not handled.");
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_COMMAND_NEW_HOLD:
|
||||
{
|
||||
ERROR_LOG("JogCon new hold position {}", m_steering_state);
|
||||
m_steering_hold_position = m_steering_state;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ERROR_LOG("Unknown JogCon command 0x{:X}", command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_last_motor_command = command;
|
||||
}
|
||||
|
||||
void JogCon::SetMotorDirection(u8 direction_command, u8 strength)
|
||||
{
|
||||
if (direction_command == MOTOR_COMMAND_STOP || strength == 0)
|
||||
{
|
||||
DEV_LOG("Stop motor");
|
||||
if (m_force_feedback_device)
|
||||
m_force_feedback_device->DisableForce(ForceFeedbackDevice::Effect::Constant);
|
||||
InputManager::SetPadVibrationIntensity(m_index, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
DEV_LOG("Turn wheel {} with {} strength", (direction_command == MOTOR_COMMAND_LEFT) ? "LEFT" : "RIGHT", strength);
|
||||
|
||||
const float f_strength = (static_cast<float>(strength) / 15.0f);
|
||||
if (m_force_feedback_device)
|
||||
{
|
||||
// 0->15 => -32768..32767, direction is flipped because it's indicating where the force is coming _from_.
|
||||
const s32 ffb_value =
|
||||
static_cast<s32>(f_strength * ((direction_command == MOTOR_COMMAND_LEFT) ? 32767.0f : -32768.0f));
|
||||
m_force_feedback_device->SetConstantForce(ffb_value);
|
||||
}
|
||||
|
||||
InputManager::SetPadVibrationIntensity(m_index, f_strength, 0.0f);
|
||||
}
|
||||
|
||||
void JogCon::UpdateSteeringHold()
|
||||
{
|
||||
if (m_steering_hold_strength > 0)
|
||||
{
|
||||
const u8 direction_command =
|
||||
(std::abs(static_cast<int>(m_steering_state) - static_cast<int>(m_steering_hold_position)) <
|
||||
m_steering_hold_deadzone) ?
|
||||
MOTOR_COMMAND_STOP :
|
||||
((m_steering_state < m_steering_hold_position) ? MOTOR_COMMAND_RIGHT : MOTOR_COMMAND_LEFT);
|
||||
DEV_LOG("Hold strength {} pos {} hold {} dir {}", m_steering_hold_strength, m_steering_state,
|
||||
m_steering_hold_position, direction_command);
|
||||
SetMotorDirection(direction_command, m_steering_hold_strength);
|
||||
}
|
||||
}
|
||||
|
||||
void JogCon::ResetMotorConfig()
|
||||
{
|
||||
m_rumble_config.fill(0xFF);
|
||||
SetMotorState(0);
|
||||
}
|
||||
|
||||
void JogCon::Poll()
|
||||
{
|
||||
m_tx_buffer[2] = Truncate8(m_button_state);
|
||||
m_tx_buffer[3] = Truncate8(m_button_state >> 8);
|
||||
|
||||
m_tx_buffer[4] = Truncate8(m_steering_state);
|
||||
m_tx_buffer[5] = Truncate8(m_steering_state >> 8); // 0xFF if negative, otherwise 0x00
|
||||
|
||||
u8 rotation_state = 0;
|
||||
if (m_steering_state > m_last_steering_state)
|
||||
rotation_state = 1;
|
||||
else if (m_steering_state < m_last_steering_state)
|
||||
rotation_state = 2;
|
||||
|
||||
m_tx_buffer[6] = rotation_state | (m_last_motor_command << 4);
|
||||
|
||||
m_last_steering_state = m_steering_state;
|
||||
UpdateSteeringHold();
|
||||
}
|
||||
|
||||
bool JogCon::Transfer(const u8 data_in, u8* data_out)
|
||||
{
|
||||
bool ack;
|
||||
m_rx_buffer[m_command_step] = data_in;
|
||||
|
||||
switch (m_command)
|
||||
{
|
||||
case Command::Idle:
|
||||
{
|
||||
*data_out = 0xFF;
|
||||
|
||||
if (data_in == 0x01)
|
||||
{
|
||||
DEBUG_LOG("ACK controller access");
|
||||
m_command = Command::Ready;
|
||||
m_tx_buffer.fill(0);
|
||||
m_rx_buffer.fill(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Ready:
|
||||
{
|
||||
Assert(m_command_step == 0);
|
||||
|
||||
if (data_in == 0x42)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::ReadPad;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
Poll();
|
||||
}
|
||||
else if (m_jogcon_mode && data_in == 0x43)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::SetMode;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
Poll();
|
||||
}
|
||||
else if (m_configuration_mode && data_in == 0x45)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::GetAnalogMode;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x01, 0x02, BoolToUInt8(m_jogcon_mode), 0x01, 0x01, 0x00};
|
||||
}
|
||||
else if (m_configuration_mode && data_in == 0x46)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::Command46;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
}
|
||||
else if (m_configuration_mode && data_in == 0x47)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::Command47;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
|
||||
}
|
||||
else if (m_configuration_mode && data_in == 0x4C)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::Command4C;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
}
|
||||
else if (m_configuration_mode && data_in == 0x4D)
|
||||
{
|
||||
m_response_length = (GetResponseNumHalfwords() + 1) * 2;
|
||||
m_command = Command::GetSetRumble;
|
||||
m_tx_buffer = {GetIDByte(), m_status_byte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG("Unimplemented command 0x{:02X}", data_in);
|
||||
|
||||
*data_out = 0xFF;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::ReadPad:
|
||||
{
|
||||
if (m_command_step >= 2 && m_command_step < 7 && m_rumble_config[m_command_step - 2] == 0x00)
|
||||
SetMotorState(data_in);
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::GetAnalogMode:
|
||||
{
|
||||
// just send the byte, nothing special to do here
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::SetMode:
|
||||
{
|
||||
m_configuration_mode = (m_rx_buffer[2] == 1 && m_jogcon_mode);
|
||||
|
||||
if (m_configuration_mode)
|
||||
m_status_byte = 0x5A;
|
||||
|
||||
DEV_LOG("0x{:02x}({}) config mode", m_rx_buffer[2], m_configuration_mode ? "enter" : "leave");
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::GetSetRumble:
|
||||
{
|
||||
if (m_command_step >= 2 && m_command_step < 7)
|
||||
{
|
||||
const u8 index = m_command_step - 2;
|
||||
if (index >= 0)
|
||||
{
|
||||
m_tx_buffer[m_command_step] = m_rumble_config[index];
|
||||
m_rumble_config[index] = data_in;
|
||||
|
||||
if (data_in == 0x00)
|
||||
WARNING_LOG("Motor mapped to byte index {}", index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset motor value if we're no longer mapping it
|
||||
if (std::find(m_rumble_config.begin(), m_rumble_config.end(), 0) == m_rumble_config.end())
|
||||
SetMotorState(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Command46:
|
||||
{
|
||||
if (m_command_step == 2)
|
||||
{
|
||||
if (data_in == 0x00)
|
||||
{
|
||||
m_tx_buffer[4] = 0x01;
|
||||
m_tx_buffer[5] = 0x02;
|
||||
m_tx_buffer[6] = 0x00;
|
||||
m_tx_buffer[7] = 0x0A;
|
||||
}
|
||||
else if (data_in == 0x01)
|
||||
{
|
||||
m_tx_buffer[4] = 0x01;
|
||||
m_tx_buffer[5] = 0x01;
|
||||
m_tx_buffer[6] = 0x01;
|
||||
m_tx_buffer[7] = 0x14;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Command47:
|
||||
{
|
||||
if (m_command_step == 2 && data_in != 0x00)
|
||||
{
|
||||
m_tx_buffer[4] = 0x00;
|
||||
m_tx_buffer[5] = 0x00;
|
||||
m_tx_buffer[6] = 0x00;
|
||||
m_tx_buffer[7] = 0x00;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Command4C:
|
||||
{
|
||||
if (m_command_step == 2)
|
||||
{
|
||||
if (data_in == 0x00)
|
||||
m_tx_buffer[5] = 0x04;
|
||||
else if (data_in == 0x01)
|
||||
m_tx_buffer[4] = 0x03;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
DefaultCaseIsUnreachable();
|
||||
}
|
||||
|
||||
*data_out = m_tx_buffer[m_command_step];
|
||||
|
||||
m_command_step = (m_command_step + 1) % m_response_length;
|
||||
ack = (m_command_step != 0);
|
||||
|
||||
if (m_command_step == 0)
|
||||
{
|
||||
m_command = Command::Idle;
|
||||
|
||||
DEBUG_LOG("Rx: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}", m_rx_buffer[0], m_rx_buffer[1],
|
||||
m_rx_buffer[2], m_rx_buffer[3], m_rx_buffer[4], m_rx_buffer[5], m_rx_buffer[6], m_rx_buffer[7]);
|
||||
DEBUG_LOG("Tx: {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x} {:02x}", m_tx_buffer[0], m_tx_buffer[1],
|
||||
m_tx_buffer[2], m_tx_buffer[3], m_tx_buffer[4], m_tx_buffer[5], m_tx_buffer[6], m_tx_buffer[7]);
|
||||
}
|
||||
|
||||
return ack;
|
||||
}
|
||||
|
||||
void JogCon::LoadSettings(const SettingsInterface& si, const char* section, bool initial)
|
||||
{
|
||||
Controller::LoadSettings(si, section, initial);
|
||||
|
||||
m_analog_deadzone = std::clamp(si.GetFloatValue(section, "AnalogDeadzone", DEFAULT_STICK_DEADZONE), 0.0f, 1.0f);
|
||||
m_analog_sensitivity =
|
||||
std::clamp(si.GetFloatValue(section, "AnalogSensitivity", DEFAULT_STICK_SENSITIVITY), 0.01f, 3.0f);
|
||||
m_button_deadzone = std::clamp(si.GetFloatValue(section, "ButtonDeadzone", DEFAULT_BUTTON_DEADZONE), 0.01f, 1.0f);
|
||||
m_steering_hold_deadzone = static_cast<s8>(std::ceil(
|
||||
std::clamp(si.GetFloatValue(section, "SteeringHoldDeadzone", DEFAULT_STEERING_HOLD_DEADZONE), 0.0f, 1.0f) *
|
||||
127.0f));
|
||||
|
||||
std::string force_feedback_device_name = si.GetStringValue(section, "ForceFeedbackDevice");
|
||||
if (m_force_feedback_device_name != force_feedback_device_name)
|
||||
{
|
||||
m_force_feedback_device_name = std::move(force_feedback_device_name);
|
||||
m_force_feedback_device.reset();
|
||||
if (!m_force_feedback_device_name.empty())
|
||||
{
|
||||
Error error;
|
||||
m_force_feedback_device = InputManager::CreateForceFeedbackDevice(m_force_feedback_device_name, &error);
|
||||
if (!m_force_feedback_device)
|
||||
{
|
||||
ERROR_LOG("Failed to create force feedback device: {}", error.GetDescription());
|
||||
if (initial)
|
||||
{
|
||||
Host::AddIconOSDWarning(
|
||||
fmt::format("NoFFDevice{}", m_index), ICON_EMOJI_WARNING,
|
||||
fmt::format(TRANSLATE_FS("JogCon", "Failed to create force feedback device for Port {}:\n{}"),
|
||||
Controller::GetPortDisplayName(m_index), error.GetDescription()),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<JogCon> JogCon::Create(u32 index)
|
||||
{
|
||||
return std::make_unique<JogCon>(index);
|
||||
}
|
||||
|
||||
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||
#define BUTTON(name, display_name, icon_name, button, genb) \
|
||||
{name, display_name, icon_name, static_cast<u32>(button), InputBindingInfo::Type::Button, genb}
|
||||
#define AXIS(name, display_name, icon_name, halfaxis, genb) \
|
||||
{name, \
|
||||
display_name, \
|
||||
icon_name, \
|
||||
static_cast<u32>(JogCon::Button::MaxCount) + static_cast<u32>(halfaxis), \
|
||||
InputBindingInfo::Type::HalfAxis, \
|
||||
genb}
|
||||
|
||||
// clang-format off
|
||||
BUTTON("Up", TRANSLATE_NOOP("JogCon", "D-Pad Up"), ICON_PF_DPAD_UP, JogCon::Button::Up, GenericInputBinding::DPadUp),
|
||||
BUTTON("Right", TRANSLATE_NOOP("JogCon", "D-Pad Right"), ICON_PF_DPAD_RIGHT, JogCon::Button::Right, GenericInputBinding::DPadRight),
|
||||
BUTTON("Down", TRANSLATE_NOOP("JogCon", "D-Pad Down"), ICON_PF_DPAD_DOWN, JogCon::Button::Down, GenericInputBinding::DPadDown),
|
||||
BUTTON("Left", TRANSLATE_NOOP("JogCon", "D-Pad Left"), ICON_PF_DPAD_LEFT, JogCon::Button::Left, GenericInputBinding::DPadLeft),
|
||||
BUTTON("Triangle", TRANSLATE_NOOP("JogCon", "Triangle"), ICON_PF_BUTTON_TRIANGLE, JogCon::Button::Triangle, GenericInputBinding::Triangle),
|
||||
BUTTON("Circle", TRANSLATE_NOOP("JogCon", "Circle"), ICON_PF_BUTTON_CIRCLE, JogCon::Button::Circle, GenericInputBinding::Circle),
|
||||
BUTTON("Cross", TRANSLATE_NOOP("JogCon", "Cross"), ICON_PF_BUTTON_CROSS, JogCon::Button::Cross, GenericInputBinding::Cross),
|
||||
BUTTON("Square", TRANSLATE_NOOP("JogCon", "Square"), ICON_PF_BUTTON_SQUARE, JogCon::Button::Square, GenericInputBinding::Square),
|
||||
BUTTON("Select", TRANSLATE_NOOP("JogCon", "Select"), ICON_PF_SELECT_SHARE, JogCon::Button::Select, GenericInputBinding::Select),
|
||||
BUTTON("Start", TRANSLATE_NOOP("JogCon", "Start"), ICON_PF_START, JogCon::Button::Start, GenericInputBinding::Start),
|
||||
BUTTON("L1", TRANSLATE_NOOP("JogCon", "L1"), ICON_PF_LEFT_SHOULDER_L1, JogCon::Button::L1, GenericInputBinding::L1),
|
||||
BUTTON("R1", TRANSLATE_NOOP("JogCon", "R1"), ICON_PF_RIGHT_SHOULDER_R1, JogCon::Button::R1, GenericInputBinding::R1),
|
||||
BUTTON("L2", TRANSLATE_NOOP("JogCon", "L2"), ICON_PF_LEFT_TRIGGER_L2, JogCon::Button::L2, GenericInputBinding::L2),
|
||||
BUTTON("R2", TRANSLATE_NOOP("JogCon", "R2"), ICON_PF_RIGHT_TRIGGER_R2, JogCon::Button::R2, GenericInputBinding::R2),
|
||||
BUTTON("Mode", TRANSLATE_NOOP("JogCon", "Mode"), ICON_PF_ANALOG_LEFT_RIGHT, JogCon::Button::Mode, GenericInputBinding::System),
|
||||
|
||||
AXIS("SteeringLeft", TRANSLATE_NOOP("JogCon", "Steering Left"), ICON_PF_ANALOG_LEFT, JogCon::HalfAxis::SteeringLeft, GenericInputBinding::LeftStickLeft),
|
||||
AXIS("SteeringRight", TRANSLATE_NOOP("JogCon", "Steering Right"), ICON_PF_ANALOG_RIGHT, JogCon::HalfAxis::SteeringRight, GenericInputBinding::LeftStickRight),
|
||||
|
||||
// clang-format on
|
||||
|
||||
{"ForceFeedbackDevice", TRANSLATE_NOOP("JogCon", "Force Feedback Device"), nullptr,
|
||||
static_cast<u32>(JogCon::Button::MaxCount) + static_cast<u32>(JogCon::HalfAxis::MaxCount),
|
||||
InputBindingInfo::Type::Device, GenericInputBinding::Unknown},
|
||||
|
||||
#undef BUTTON
|
||||
#undef AXIS
|
||||
};
|
||||
|
||||
static const SettingInfo s_settings[] = {
|
||||
{SettingInfo::Type::Float, "AnalogDeadzone", TRANSLATE_NOOP("JogCon", "Analog Deadzone"),
|
||||
TRANSLATE_NOOP("JogCon",
|
||||
"Sets the analog stick deadzone, i.e. the fraction of the stick movement which will be ignored."),
|
||||
"0.00f", "0.00f", "1.00f", "0.01f", "%.0f%%", nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "AnalogSensitivity", TRANSLATE_NOOP("JogCon", "Analog Sensitivity"),
|
||||
TRANSLATE_NOOP("JogCon", "Sets the analog stick axis scaling factor. A value between 130% and 140% is recommended "
|
||||
"when using recent controllers, e.g. DualShock 4, Xbox One Controller."),
|
||||
"1.33f", "0.01f", "2.00f", "0.01f", "%.0f%%", nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "ButtonDeadzone", TRANSLATE_NOOP("JogCon", "Button/Trigger Deadzone"),
|
||||
TRANSLATE_NOOP(
|
||||
"JogCon",
|
||||
"Sets the deadzone for activating buttons/triggers, i.e. the fraction of the trigger which will be ignored."),
|
||||
"0.25", "0.01", "1.00", "0.01", "%.0f%%", nullptr, 100.0f},
|
||||
{SettingInfo::Type::Float, "SteeringHoldDeadzone", TRANSLATE_NOOP("JogCon", "Steering Hold Deadzone"),
|
||||
TRANSLATE_NOOP(
|
||||
"JogCon", "Sets the deadzone for holding the wheel at the set position, i.e. when it will not trigger an effect."),
|
||||
"0.03", "0.01", "1.00", "0.01", "%.0f%%", nullptr, 100.0f},
|
||||
};
|
||||
|
||||
const Controller::ControllerInfo JogCon::INFO = {
|
||||
ControllerType::JogCon, "JogCon", TRANSLATE_NOOP("ControllerType", "JogCon"), ICON_PF_STEERING_WHEEL,
|
||||
s_binding_info, s_settings, Controller::VibrationCapabilities::SingleMotor};
|
|
@ -0,0 +1,150 @@
|
|||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "controller.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class ForceFeedbackDevice;
|
||||
|
||||
class JogCon final : public Controller
|
||||
{
|
||||
public:
|
||||
enum class Button : u8
|
||||
{
|
||||
Select = 0,
|
||||
L3 = 1,
|
||||
R3 = 2,
|
||||
Start = 3,
|
||||
Up = 4,
|
||||
Right = 5,
|
||||
Down = 6,
|
||||
Left = 7,
|
||||
L2 = 8,
|
||||
R2 = 9,
|
||||
L1 = 10,
|
||||
R1 = 11,
|
||||
Triangle = 12,
|
||||
Circle = 13,
|
||||
Cross = 14,
|
||||
Square = 15,
|
||||
Mode = 16,
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class HalfAxis : u8
|
||||
{
|
||||
SteeringLeft,
|
||||
SteeringRight,
|
||||
MaxCount,
|
||||
};
|
||||
|
||||
static const Controller::ControllerInfo INFO;
|
||||
|
||||
JogCon(u32 index);
|
||||
~JogCon() override;
|
||||
|
||||
static std::unique_ptr<JogCon> Create(u32 index);
|
||||
|
||||
ControllerType GetType() const override;
|
||||
|
||||
void Reset() override;
|
||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||
|
||||
float GetBindState(u32 index) const override;
|
||||
void SetBindState(u32 index, float value) override;
|
||||
u32 GetButtonStateBits() const override;
|
||||
u32 GetInputOverlayIconColor() const override;
|
||||
|
||||
void ResetTransferState() override;
|
||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||
|
||||
void LoadSettings(const SettingsInterface& si, const char* section, bool initial) override;
|
||||
|
||||
private:
|
||||
enum class Command : u8
|
||||
{
|
||||
Idle,
|
||||
Ready,
|
||||
ReadPad,
|
||||
SetMode,
|
||||
GetAnalogMode,
|
||||
GetSetRumble,
|
||||
Command46,
|
||||
Command47,
|
||||
Command4C,
|
||||
};
|
||||
|
||||
enum : u8
|
||||
{
|
||||
LargeMotor = 0,
|
||||
SmallMotor = 1
|
||||
};
|
||||
|
||||
enum : u8
|
||||
{
|
||||
MOTOR_COMMAND_STOP = 0x0,
|
||||
MOTOR_COMMAND_RIGHT = 0x1,
|
||||
MOTOR_COMMAND_LEFT = 0x2,
|
||||
MOTOR_COMMAND_HOLD = 0x3,
|
||||
MOTOR_COMMAND_DROP_REVOLUTIONS = 0x8,
|
||||
MOTOR_COMMAND_DROP_REVOLUTIONS_AND_HOLD = 0xB,
|
||||
MOTOR_COMMAND_NEW_HOLD = 0xC,
|
||||
};
|
||||
|
||||
static constexpr float DEFAULT_STEERING_HOLD_DEADZONE = 0.03f;
|
||||
|
||||
u8 GetIDByte() const;
|
||||
u8 GetModeID() const;
|
||||
|
||||
// Get number of response halfwords (excluding the initial controller info halfword)
|
||||
u8 GetResponseNumHalfwords() const;
|
||||
|
||||
void Poll();
|
||||
void UpdateSteeringHold();
|
||||
|
||||
void SetMotorState(u8 value);
|
||||
void SetMotorDirection(u8 direction_command, u8 strength);
|
||||
void ResetMotorConfig();
|
||||
|
||||
void SetJogConMode(bool enabled, bool show_message);
|
||||
|
||||
// buttons are active low
|
||||
u16 m_button_state = UINT16_C(0xFFFF);
|
||||
s8 m_steering_state = 0;
|
||||
|
||||
// both directions of axis state, merged to m_steering_state
|
||||
std::array<u8, static_cast<u32>(HalfAxis::MaxCount)> m_half_axis_state{};
|
||||
|
||||
Command m_command = Command::Idle;
|
||||
u8 m_command_step = 0;
|
||||
u8 m_response_length = 0;
|
||||
u8 m_status_byte = 0x5A;
|
||||
|
||||
s8 m_last_steering_state = 0;
|
||||
u8 m_last_motor_command = 0;
|
||||
s8 m_steering_hold_position = 0;
|
||||
u8 m_steering_hold_strength = 0;
|
||||
|
||||
bool m_configuration_mode = false;
|
||||
bool m_jogcon_mode = false;
|
||||
bool m_mode_toggle_queued = false;
|
||||
|
||||
std::array<u8, 6> m_rumble_config{};
|
||||
|
||||
// Transmit and receive buffers, not including the first Hi-Z/ack response byte
|
||||
static constexpr u32 MAX_RESPONSE_LENGTH = 8;
|
||||
std::array<u8, MAX_RESPONSE_LENGTH> m_rx_buffer;
|
||||
std::array<u8, MAX_RESPONSE_LENGTH> m_tx_buffer;
|
||||
|
||||
s8 m_steering_hold_deadzone = 0;
|
||||
|
||||
float m_analog_deadzone = 0.0f;
|
||||
float m_analog_sensitivity = 1.33f;
|
||||
float m_button_deadzone = 0.0f;
|
||||
|
||||
std::string m_force_feedback_device_name;
|
||||
std::unique_ptr<ForceFeedbackDevice> m_force_feedback_device;
|
||||
};
|
|
@ -19,7 +19,7 @@
|
|||
#include "IconsPromptFont.h"
|
||||
#include <array>
|
||||
|
||||
LOG_CHANNEL(Justifier);
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
// #define CHECK_TIMING 1
|
||||
#ifdef CHECK_TIMING
|
||||
|
|
|
@ -88,7 +88,7 @@ void MemoryCard::ResetTransferState()
|
|||
bool MemoryCard::Transfer(const u8 data_in, u8* data_out)
|
||||
{
|
||||
bool ack = false;
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
const State old_state = m_state;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
LOG_CHANNEL(NeGconRumble);
|
||||
LOG_CHANNEL(Controller);
|
||||
|
||||
// Mapping of Button to index of corresponding bit in m_button_state
|
||||
static constexpr std::array<u8, static_cast<size_t>(NeGconRumble::Button::Count)> s_button_indices = {3, 4, 5, 6,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue