mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-08-08 07:04:55 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54c620a5df | ||
|
|
089b7fa73e | ||
|
|
d9d0e84ca1 | ||
|
|
badede2e2d | ||
|
|
e2ae28741d | ||
|
|
ff34150b15 | ||
|
|
4a93ceac58 | ||
|
|
5a724bf49e | ||
|
|
c23bcf6322 | ||
|
|
c863149ad9 | ||
|
|
5fb6e22bed | ||
|
|
d634088282 | ||
|
|
c99a935831 | ||
|
|
165da677ed | ||
|
|
0bbde2ca52 | ||
|
|
3d13c5d13c | ||
|
|
9d978c67ec | ||
|
|
8766e1fa57 | ||
|
|
c0e4883987 | ||
|
|
57f2cd5f9e | ||
|
|
50d8d06a94 | ||
|
|
2e07328878 | ||
|
|
ad8294e521 | ||
|
|
14426a7b45 | ||
|
|
6697e76be1 | ||
|
|
73cd876f6d | ||
|
|
e626754000 | ||
|
|
1fedd31229 | ||
|
|
bfe1746ddb | ||
|
|
4800c32db4 | ||
|
|
140fc28b3e | ||
|
|
f9833bb8af | ||
|
|
4b6ddaf09e | ||
|
|
d427db4a15 | ||
|
|
deb39cc20f | ||
|
|
3a4c25e916 | ||
|
|
f416eb3d4f | ||
|
|
87cbb1f90c | ||
|
|
68f43121fb | ||
|
|
51ceab1f3c | ||
|
|
2257992a3f | ||
|
|
40ead584d7 | ||
|
|
6f2be7bd17 | ||
|
|
af9ca4cf7d | ||
|
|
ea98203ac5 | ||
|
|
e908bbfae6 | ||
|
|
fa00069068 | ||
|
|
efae58de52 | ||
|
|
39c7f703cb | ||
|
|
96220e509c | ||
|
|
4de495ad59 | ||
|
|
56a950a074 | ||
|
|
2b47254bdd | ||
|
|
da28e2cc37 | ||
|
|
3d64f4a548 | ||
|
|
abf03b0c79 | ||
|
|
8381742422 | ||
|
|
724bb09aec | ||
|
|
ad5de248b4 | ||
|
|
1a1fdf6a5a | ||
|
|
c469b17350 | ||
|
|
01842a3c6b | ||
|
|
4cd385dbff | ||
|
|
72787d103f | ||
|
|
59072272a9 | ||
|
|
ef76666e5a | ||
|
|
0a0994b19c | ||
|
|
ab68c570a9 | ||
|
|
dcdf3b39a3 | ||
|
|
476cb2db34 | ||
|
|
34a7e00413 | ||
|
|
413ba09ee0 | ||
|
|
33eefefffb | ||
|
|
b3c822e31b | ||
|
|
14a458a275 | ||
|
|
6c49f9cf52 | ||
|
|
803ea4dda5 | ||
|
|
c9b23e6e4e | ||
|
|
509c9318af | ||
|
|
46e1e3d904 | ||
|
|
7a045d837b | ||
|
|
574ea820f7 | ||
|
|
7061d48dde | ||
|
|
53633b7279 | ||
|
|
05bb126af9 | ||
|
|
436fba77ac | ||
|
|
91c0e64159 | ||
|
|
7207681485 | ||
|
|
eef53f1b54 | ||
|
|
150d8d3214 | ||
|
|
a14376abb6 | ||
|
|
dfb45a8ebc | ||
|
|
00137c3031 | ||
|
|
b9c7dacbd1 | ||
|
|
3a03b579d2 | ||
|
|
e2bbe5cd8b | ||
|
|
c7347a3a16 | ||
|
|
8749b3c782 | ||
|
|
10389dc3f1 | ||
|
|
5e191a6cd8 | ||
|
|
a247625095 | ||
|
|
0fb234f3e4 | ||
|
|
e3e35d3bc6 | ||
|
|
6b12ca5b39 | ||
|
|
44e2837efb | ||
|
|
27dcd1bba2 | ||
|
|
ebf8cba6a4 | ||
|
|
e06cf23a03 | ||
|
|
dd55887f4b | ||
|
|
39b7b29af8 | ||
|
|
6f0aef3344 | ||
|
|
85c3a413fa | ||
|
|
b6c365b89d | ||
|
|
9eedf3901a |
@@ -6,3 +6,7 @@ updates:
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every week
|
||||
interval: "weekly"
|
||||
groups:
|
||||
ci-deps:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
+147
-87
@@ -2,127 +2,187 @@
|
||||
|
||||
# General Labels
|
||||
'Build | Project System':
|
||||
- '.github/*'
|
||||
- '.github/**/*'
|
||||
- '*.sln'
|
||||
- '**/*.sln'
|
||||
- '*.vcxproj*'
|
||||
- '**/*.vcxproj*'
|
||||
- 'cmake/*'
|
||||
- 'cmake/**/*'
|
||||
- 'CMakeLists.txt'
|
||||
- '**/CMakeLists.txt'
|
||||
- 'build.sh'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '.github/*'
|
||||
- '.github/**/*'
|
||||
- '*.sln'
|
||||
- '**/*.sln'
|
||||
- '*.vcxproj*'
|
||||
- '**/*.vcxproj*'
|
||||
- 'cmake/*'
|
||||
- 'cmake/**/*'
|
||||
- 'CMakeLists.txt'
|
||||
- '**/CMakeLists.txt'
|
||||
- 'build.sh'
|
||||
'Dependencies':
|
||||
- '3rdparty/*'
|
||||
- '3rdparty/**/*'
|
||||
- '**/3rdpartyDeps.props'
|
||||
- '.gitmodules'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '3rdparty/*'
|
||||
- '3rdparty/**/*'
|
||||
- '**/3rdpartyDeps.props'
|
||||
- '.gitmodules'
|
||||
'Documentation':
|
||||
- '*.md'
|
||||
- '**/*.md'
|
||||
- '*.pdf'
|
||||
- '**/*.pdf'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '*.md'
|
||||
- '**/*.md'
|
||||
- '*.pdf'
|
||||
- '**/*.pdf'
|
||||
'GUI/Qt':
|
||||
- 'pcsx2-qt/*'
|
||||
- 'pcsx2-qt/**/*'
|
||||
- '3rdparty/Qt/*'
|
||||
- '3rdparty/Qt/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2-qt/*'
|
||||
- 'pcsx2-qt/**/*'
|
||||
- '3rdparty/Qt/*'
|
||||
- '3rdparty/Qt/**/*'
|
||||
'GameDB':
|
||||
- '**/GameIndex.*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '**/GameIndex.*'
|
||||
'Installer | Package':
|
||||
- 'build.sh'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'build.sh'
|
||||
'Translations':
|
||||
- 'pcsx2-qt/Translations/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2-qt/Translations/*'
|
||||
|
||||
# Tools / Features
|
||||
'Debugger':
|
||||
- 'pcsx2/DebugTools/*'
|
||||
- 'pcsx2/DebugTools/**/*'
|
||||
- 'pcsx2-qt/Debugger/*'
|
||||
- 'pcsx2-qt/Debugger/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/DebugTools/*'
|
||||
- 'pcsx2/DebugTools/**/*'
|
||||
- 'pcsx2-qt/Debugger/*'
|
||||
- 'pcsx2-qt/Debugger/**/*'
|
||||
'IPC':
|
||||
- 'pcsx2/IPC*'
|
||||
- 'pcsx2/**/IPC*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/IPC*'
|
||||
- 'pcsx2/**/IPC*'
|
||||
'TAS Functionality':
|
||||
- 'pcsx2/Recording/*'
|
||||
- 'pcsx2/Recording/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/Recording/*'
|
||||
- 'pcsx2/Recording/**/*'
|
||||
'RetroAchievements':
|
||||
- 'pcsx2/Frontend/Achievements.*'
|
||||
- 'pcsx2/Achievements.*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/Frontend/Achievements.*'
|
||||
- 'pcsx2/Achievements.*'
|
||||
|
||||
# Emulation Components
|
||||
'Counters':
|
||||
- 'pcsx2/Counters.*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/Counters.*'
|
||||
'Vector Units':
|
||||
- 'pcsx2/VU*'
|
||||
- 'pcsx2/**/VU*'
|
||||
- 'pcsx2/*VU*'
|
||||
- 'pcsx2/**/*VU*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/VU*'
|
||||
- 'pcsx2/**/VU*'
|
||||
- 'pcsx2/*VU*'
|
||||
- 'pcsx2/**/*VU*'
|
||||
'VIF':
|
||||
- 'pcsx2/Vif*'
|
||||
- 'pcsx2/**/Vif*'
|
||||
- 'pcsx2/VIF*'
|
||||
- 'pcsx2/**/VIF*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/Vif*'
|
||||
- 'pcsx2/**/Vif*'
|
||||
- 'pcsx2/VIF*'
|
||||
- 'pcsx2/**/VIF*'
|
||||
|
||||
# GS Related Labels
|
||||
'GS':
|
||||
- 'pcsx2/GS/*'
|
||||
- 'pcsx2/GS/**/*'
|
||||
- 'bin/resources/shaders/*'
|
||||
- 'bin/resources/shaders/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/*'
|
||||
- 'pcsx2/GS/**/*'
|
||||
- 'bin/resources/shaders/*'
|
||||
- 'bin/resources/shaders/**/*'
|
||||
'GS: Direct3D 11':
|
||||
- 'pcsx2/GS/Renderers/DX11/*'
|
||||
- 'pcsx2/GS/Renderers/DX11/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/DX11/*'
|
||||
- 'pcsx2/GS/Renderers/DX11/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
'GS: Direct3D 12':
|
||||
- 'pcsx2/GS/Renderers/DX12/*'
|
||||
- 'pcsx2/GS/Renderers/DX12/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/DX12/*'
|
||||
- 'pcsx2/GS/Renderers/DX12/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
'GS: Hardware':
|
||||
- 'pcsx2/GS/Renderers/HW/*'
|
||||
- 'pcsx2/GS/Renderers/HW/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/HW/*'
|
||||
- 'pcsx2/GS/Renderers/HW/**/*'
|
||||
'GS: OpenGL':
|
||||
- 'pcsx2/GS/Renderers/OpenGL/*'
|
||||
- 'pcsx2/GS/Renderers/OpenGL/**/*'
|
||||
- 'bin/resources/shaders/opengl/*'
|
||||
- 'bin/resources/shaders/opengl/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/OpenGL/*'
|
||||
- 'pcsx2/GS/Renderers/OpenGL/**/*'
|
||||
- 'bin/resources/shaders/opengl/*'
|
||||
- 'bin/resources/shaders/opengl/**/*'
|
||||
'GS: Vulkan':
|
||||
- 'pcsx2/GS/Renderers/Vulkan/*'
|
||||
- 'pcsx2/GS/Renderers/Vulkan/**/*'
|
||||
- 'bin/resources/shaders/vulkan/*'
|
||||
- 'bin/resources/shaders/vulkan/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/Vulkan/*'
|
||||
- 'pcsx2/GS/Renderers/Vulkan/**/*'
|
||||
- 'bin/resources/shaders/vulkan/*'
|
||||
- 'bin/resources/shaders/vulkan/**/*'
|
||||
'GS: Metal':
|
||||
- 'pcsx2/GS/Renderers/Metal/*'
|
||||
- 'pcsx2/GS/Renderers/Metal/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/Metal/*'
|
||||
- 'pcsx2/GS/Renderers/Metal/**/*'
|
||||
'GS: Texture Cache':
|
||||
- 'pcsx2/GS/Renderers/*TextureCache*.*'
|
||||
- 'pcsx2/GS/Renderers/**/*TextureCache*.*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/*TextureCache*.*'
|
||||
- 'pcsx2/GS/Renderers/**/*TextureCache*.*'
|
||||
'GS: Software':
|
||||
- 'pcsx2/GS/Renderers/SW/*'
|
||||
- 'pcsx2/GS/Renderers/SW/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/GS/Renderers/SW/*'
|
||||
- 'pcsx2/GS/Renderers/SW/**/*'
|
||||
|
||||
# Other Core Components
|
||||
'CDVD':
|
||||
- 'pcsx2/CDVD/*'
|
||||
- 'pcsx2/CDVD/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/CDVD/*'
|
||||
- 'pcsx2/CDVD/**/*'
|
||||
'DEV9':
|
||||
- 'pcsx2/DEV9/*'
|
||||
- 'pcsx2/DEV9/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/DEV9/*'
|
||||
- 'pcsx2/DEV9/**/*'
|
||||
'IPU':
|
||||
- 'pcsx2/IPU/*'
|
||||
- 'pcsx2/IPU/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/IPU/*'
|
||||
- 'pcsx2/IPU/**/*'
|
||||
'Memory Card':
|
||||
- 'pcsx2/SIO/Memcard/*'
|
||||
- 'pcsx2/SIO/Memcard/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/SIO/Memcard/*'
|
||||
- 'pcsx2/SIO/Memcard/**/*'
|
||||
'PAD':
|
||||
- 'pcsx2/SIO/Pad/*'
|
||||
- 'pcsx2/SIO/Pad/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/SIO/Pad/*'
|
||||
- 'pcsx2/SIO/Pad/**/*'
|
||||
'SPU2':
|
||||
- 'pcsx2/SPU2/*'
|
||||
- 'pcsx2/SPU2/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/SPU2/*'
|
||||
- 'pcsx2/SPU2/**/*'
|
||||
'USB':
|
||||
- 'pcsx2/USB/*'
|
||||
- 'pcsx2/USB/**/*'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/USB/*'
|
||||
- 'pcsx2/USB/**/*'
|
||||
|
||||
@@ -33,6 +33,7 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
|
||||
@@ -6,6 +6,9 @@ on:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
artifactPrefixName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
@@ -36,6 +39,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
stableBuild:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -56,13 +63,18 @@ jobs:
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
BUILD_SYSTEM: flatpak
|
||||
ARCH: ${{ inputs.platform }}
|
||||
PREFIX: ${{ inputs.artifactPrefixName }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
@@ -90,9 +102,11 @@ jobs:
|
||||
flatpak run --command=flatpak-builder-lint org.flatpak.Builder manifest .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6.3
|
||||
# TODO - based on v6.3, switch back to the main action once change is accepted (or they release a breaking change that uses upload-artifact@v4)
|
||||
uses: xTVaser/flatpak-github-actions/flatpak-builder@64267d4cf01f7955a40128039d0abab17bb48aac
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
@@ -131,3 +145,16 @@ jobs:
|
||||
repository: stable
|
||||
token: ${{ secrets.FLATHUB_TOKEN }}
|
||||
|
||||
# NOTE - this is done after on purpose so the flatpak file is wherever it needs to be for the previous pushes
|
||||
- name: Prepare artifacts folder
|
||||
# NOTE - 'flatpak-builder' dumps the artifact out into the current directory
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
mv "./${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "AppImage Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-appimage-sse4"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
@@ -25,6 +26,7 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak-sse4"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
|
||||
@@ -6,6 +6,9 @@ on:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
artifactPrefixName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
@@ -36,6 +39,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
stableBuild:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -69,12 +76,18 @@ jobs:
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
ARCH: ${{ inputs.platform }}
|
||||
PREFIX: ${{ inputs.artifactPrefixName }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
@@ -107,7 +120,7 @@ jobs:
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: .github/workflows/scripts/linux/build-dependencies-qt.sh
|
||||
run: .github/workflows/scripts/linux/build-dependencies-qt.sh "$HOME/deps"
|
||||
|
||||
- name: Download patches
|
||||
run: |
|
||||
@@ -142,7 +155,7 @@ jobs:
|
||||
|
||||
- name: Upload artifact
|
||||
if: inputs.buildAppImage == true
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
@@ -6,6 +6,9 @@ on:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
artifactPrefixName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
@@ -18,6 +21,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
stableBuild:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
@@ -44,6 +51,13 @@ jobs:
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Use Xcode 14.3.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
@@ -51,7 +65,7 @@ jobs:
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: macos
|
||||
PREFIX: ${{ inputs.artifactPrefixName }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
@@ -149,7 +163,7 @@ jobs:
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS.tar.xz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: "*.tar.xz"
|
||||
|
||||
@@ -15,4 +15,5 @@ jobs:
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "MacOS Build"
|
||||
artifactPrefixName: "PCSX2-macos-Qt"
|
||||
secrets: inherit
|
||||
|
||||
@@ -10,16 +10,19 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# TODO - future work
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
# isStable:
|
||||
# description: 'Should it be a stable release?'
|
||||
# required: true
|
||||
# default: 'false'
|
||||
# versionTag:
|
||||
# description: 'The version to tag with'
|
||||
# required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
is_prelease:
|
||||
description: 'Should be a pre-release?'
|
||||
required: true
|
||||
default: 'true'
|
||||
type: choice
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
tag_value:
|
||||
description: 'Create a new release from latest master with the given tag, if this is left blank it will bump the patch version. You dont need to include the "v" prefix'
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -42,6 +45,8 @@ jobs:
|
||||
github_token: ${{ github.token }}
|
||||
tag_prefix: v
|
||||
default_bump: patch
|
||||
# if set, it will overwrite the bump settings
|
||||
custom_tag: ${{ github.event.inputs.tag_value == '' && null || github.event.inputs.tag_value }}
|
||||
|
||||
# TODO - we could do this and remove the node.js script, but auto-generated notes only work
|
||||
# with PRs -- not commits (determine how much we care).
|
||||
@@ -62,9 +67,18 @@ jobs:
|
||||
node index.js
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: ${{ github.event_name != 'workflow_dispatch' || inputs.is_prelease == 'true' }}
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
@@ -81,10 +95,12 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "AppImage Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-appimage"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
build_linux_flatpak:
|
||||
@@ -95,11 +111,13 @@ jobs:
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
branch: "stable"
|
||||
publish: false
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
@@ -111,10 +129,12 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "Windows Build"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
@@ -126,7 +146,9 @@ jobs:
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "MacOS Build"
|
||||
artifactPrefixName: "PCSX2-macos-Qt"
|
||||
fetchTags: true
|
||||
stableBuild: ${{ github.event_name == 'workflow_dispatch' && inputs.is_prelease == 'false' }}
|
||||
secrets: inherit
|
||||
|
||||
# Upload the Artifacts
|
||||
@@ -146,7 +168,7 @@ jobs:
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
@@ -159,9 +181,6 @@ jobs:
|
||||
working-directory: ./ci-artifacts/
|
||||
run: for d in *windows*/; do 7z a "${d}asset.7z" ./$d/*; done
|
||||
|
||||
# Artifact Naming:
|
||||
# MacOS: PCSX2-<tag>-macOS-[additional hyphen seperated tags]
|
||||
# Windows|Linux: PCSX2-<tag>-<windows|linux>-<32bit|64bit>--[additional hyphen seperated tags]
|
||||
- name: Name and Upload the Release Assets
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
@@ -1,39 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Artifact Naming Scheme:
|
||||
# PCSX2-<OS>-Qt-[ARCH]-[SIMD]-[pr\[PR_NUM\]]-[title|sha\[SHA|PR_TITLE\]
|
||||
# PCSX2-<OS>-Qt-[BUILD_SYSTEM]-[ARCH]-[SIMD]-[pr\[PR_NUM\]]-[title|sha\[SHA|PR_TITLE\]
|
||||
# -- limited to 200 chars
|
||||
# Outputs:
|
||||
# - artifact-name
|
||||
|
||||
# Example - PCSX2-linux-Qt-x64-flatpak-sse4-sha[e880a2749]
|
||||
|
||||
# Inputs as env-vars
|
||||
# OS
|
||||
# BUILD_SYSTEM
|
||||
# ARCH
|
||||
# SIMD
|
||||
# PREFIX
|
||||
# EVENT_NAME
|
||||
# PR_TITLE
|
||||
# PR_NUM
|
||||
# PR_SHA
|
||||
|
||||
NAME=""
|
||||
|
||||
if [ "${OS}" == "macos" ]; then
|
||||
# MacOS has combined binaries for x64 and ARM64.
|
||||
NAME="PCSX2-${OS}-Qt"
|
||||
elif [[ ("${OS}" == "windows" && "$BUILD_SYSTEM" != "cmake") ]]; then
|
||||
NAME="PCSX2-${OS}-Qt-${ARCH}-${SIMD}"
|
||||
else
|
||||
NAME="PCSX2-${OS}-Qt-${ARCH}"
|
||||
if [[ -z "${PREFIX}" ]]; then
|
||||
echo "PREFIX is not set, can't name artifact without it!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add cmake if used to differentate it from msbuild builds
|
||||
# Else the two artifacts will have the same name and the files will be merged
|
||||
if [[ ! -z "${BUILD_SYSTEM}" ]]; then
|
||||
if [[ "${BUILD_SYSTEM}" == "cmake" ]] || [[ "${BUILD_SYSTEM}" == "flatpak" ]]; then
|
||||
NAME="${NAME}-${BUILD_SYSTEM}"
|
||||
fi
|
||||
fi
|
||||
NAME="${PREFIX}"
|
||||
|
||||
# Add PR / Commit Metadata
|
||||
if [ "$EVENT_NAME" == "pull_request" ]; then
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
set -e
|
||||
|
||||
INSTALLDIR="$HOME/deps"
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Syntax: $0 <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INSTALLDIR="$1"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.28.5
|
||||
QT=6.6.1
|
||||
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4.3.0
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "MSVC SSE4"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-sse4-msvc"
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
@@ -38,6 +39,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "MSVC AVX2"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-avx2-msvc"
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
@@ -47,6 +49,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "CMake MSVC"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-cmake-msvc"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
secrets: inherit
|
||||
@@ -58,6 +61,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "Clang SSE4"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-sse4-clang"
|
||||
configuration: Release Clang
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
@@ -69,6 +73,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "Clang AVX2"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-avx2-clang"
|
||||
configuration: Release Clang AVX2
|
||||
secrets: inherit
|
||||
|
||||
@@ -78,6 +83,7 @@ jobs:
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "CMake Clang"
|
||||
artifactPrefixName: "PCSX2-windows-Qt-x64-cmake-clang"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DPCSX2_EXE_NAME=pcsx2-qt-clang
|
||||
|
||||
@@ -6,6 +6,9 @@ on:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
artifactPrefixName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
@@ -37,6 +40,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
stableBuild:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_windows_qt:
|
||||
@@ -58,14 +65,18 @@ jobs:
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: windows
|
||||
BUILD_SYSTEM: ${{ inputs.buildSystem }}
|
||||
ARCH: ${{ inputs.platform }}
|
||||
SIMD: ${{ inputs.simd }}
|
||||
PREFIX: ${{ inputs.artifactPrefixName }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
@@ -122,7 +133,7 @@ jobs:
|
||||
cmake --build build --config Release --target unittests
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: |
|
||||
@@ -136,7 +147,7 @@ jobs:
|
||||
!./bin/**/*.lib
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}-symbols
|
||||
path: ./bin/**/*.pdb
|
||||
|
||||
@@ -71,6 +71,7 @@ oprofile_data/
|
||||
/bin/bios
|
||||
/bin/cache
|
||||
/bin/cheats
|
||||
/bin/patches
|
||||
/bin/covers
|
||||
/bin/dumps
|
||||
/bin/gamesettings
|
||||
@@ -84,6 +85,13 @@ oprofile_data/
|
||||
/bin/textures
|
||||
/bin/translations
|
||||
/bin/inputprofiles
|
||||
|
||||
# Resources that are runtime downloaded.
|
||||
/bin/resources/NotoSansJP-Regular.ttf
|
||||
/bin/resources/NotoSansKR-Regular.ttf
|
||||
/bin/resources/NotoSansSC-Regular.ttf
|
||||
/bin/resources/NotoSansTC-Regular.ttf
|
||||
|
||||
/deps
|
||||
/ipch
|
||||
|
||||
|
||||
Vendored
+11
-1
@@ -329,4 +329,14 @@
|
||||
#define ICON_PF_SHOPPING_CART "\xF0\x9F\x9B\x92"
|
||||
#define ICON_PF_ACHIEVEMENTS_PROGRESSION "\xE2\x8E\xB2"
|
||||
#define ICON_PF_ACHIEVEMENTS_MISSABLE "\xE2\x8E\xB3"
|
||||
#define ICON_PF_ACHIEVEMENTS_WIN "\xE2\x8E\xB4"
|
||||
#define ICON_PF_ACHIEVEMENTS_WIN "\xE2\x8E\xB4"
|
||||
#define ICON_PF_POPN_CONTROLLER "\xE2\x8A\xBF"
|
||||
#define ICON_PF_POPN_BLUE_LEFT "\xE2\x8B\x80"
|
||||
#define ICON_PF_POPN_BLUE_RIGHT "\xE2\x8B\x81"
|
||||
#define ICON_PF_POPN_GREEN_LEFT "\xE2\x8B\x82"
|
||||
#define ICON_PF_POPN_GREEN_RIGHT "\xE2\x8B\x83"
|
||||
#define ICON_PF_POPN_YELLOW_LEFT "\xE2\x8B\x84"
|
||||
#define ICON_PF_POPN_YELLOW_RIGHT "\xE2\x8B\x85"
|
||||
#define ICON_PF_POPN_WHITE_LEFT "\xE2\x8B\x86"
|
||||
#define ICON_PF_POPN_WHITE_RIGHT "\xE2\x8B\x87"
|
||||
#define ICON_PF_POPN_RED "\xE2\x8B\x88"
|
||||
Vendored
+91
@@ -0,0 +1,91 @@
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1. This license is copied below, and is also available
|
||||
with a FAQ at <http://scripts.sil.org/OFL>
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Vendored
+33333
File diff suppressed because it is too large
Load Diff
@@ -10,51 +10,17 @@ PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to
|
||||
|
||||
## Project Details
|
||||
|
||||
The PCSX2 project has been running for more than twenty years. Past versions could only run a few public domain game demos, but newer versions can run most games at full speed, including popular titles such as Final Fantasy X and Devil May Cry 3. Visit the [PCSX2 compatibility list](https://pcsx2.net/compat/) to check the latest compatibility status of games (with more than 2500 titles tested), or ask for help in the [official forums](https://forums.pcsx2.net/).
|
||||
PCSX2 has been in development for more than 20 years. Past versions could only run a few public domain game demos, but newer versions can run most games at full speed, including popular titles such as Final Fantasy X and Devil May Cry 3. Visit the [PCSX2 compatibility list](https://pcsx2.net/compat/) to check the latest compatibility status of games (with more than 2500 titles tested).
|
||||
|
||||
The latest officially released stable version is version 1.6.0.
|
||||
|
||||
Installers and binaries for both stable and development builds are available from [our website](https://pcsx2.net/downloads/).
|
||||
Installers and binaries for both stable and nightly builds are available from [our website](https://pcsx2.net/downloads/).
|
||||
|
||||
## System Requirements
|
||||
|
||||
### Minimum
|
||||
PCSX2 supports Windows, Linux, and Mac platforms. Our [setup documentation page](https://pcsx2.net/docs/usage/setup/requirements) contains additional details on software and hardware requirements.
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 11.0 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1500<br/> - Two physical cores, with hyperthreading | - Direct3D 11 (Feature Level 11.0) support <br/> - OpenGL 3.3 support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
|
||||
### Recommended
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 11.0 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2000<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
### Heavy
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 11.0 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
_Note1: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
|
||||
|
||||
_Note2: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- You need the [Visual C++ 2019 x64 Redistributables](https://support.microsoft.com/en-us/help/2977003/) to run PCSX2 on Windows.
|
||||
- Windows XP and Direct3D9 support was dropped after stable release 1.4.0.
|
||||
- Windows 7, Windows 8.0, and Windows 8.1 support was dropped after stable release 1.6.0.
|
||||
- 32-bit and wxWidgets support was dropped after stable release 1.6.0, with the wxWidgets code being removed completely on 25th December 2022.
|
||||
- Make sure to update your operating system and drivers to ensure you have the best experience possible. Having a newer GPU is also recommended so you have the latest supported drivers.
|
||||
- Because of copyright issues, and the complexity of trying to work around it, you need a BIOS dump extracted from a legitimately-owned PS2 console to use the emulator. For more information about the BIOS and how to get it from your console, visit [this page](pcsx2/Docs/PCSX2_FAQ.md#question-13-where-do-i-get-a-ps2-bios).
|
||||
- PCSX2 uses two CPU cores for emulation by default. A third core can be used via the MTVU speed hack, which is compatible with most games. This can be a significant speedup on CPUs with 3+ cores, but it may be a slowdown on GS-limited games (or on CPUs with fewer than 2 cores). Software renderers will then additionally use however many rendering threads it is set to and will need higher core counts to run efficiently.
|
||||
- Requirements benchmarks are based on a statistic from the Passmark CPU bench marking software. When we say "STR", we are referring to Passmark's "Single Thread Rating" statistic. You can look up your CPU on [Passmark's website for CPUs](https://cpubenchmark.net) to see how it compares to PCSX2's requirements.
|
||||
- Vulkan requires an up-to-date GPU driver; old drivers may cause graphical problems.
|
||||
Please note that a BIOS dump from a legitimately-owned PS2 console is required to use the emulator. For more information, visit [this page](https://pcsx2.net/docs/usage/setup/gather/#how-to-dump-your-ps2-bios).
|
||||
|
||||
## Contributing / Building
|
||||
Want to contribute to the development of PCSX2?
|
||||
PCSX2 supports translation into other languages using [Crowdin](https://crowdin.com/project/pcsx2-emulator).
|
||||
|
||||
See the [Contributing Guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md) or visit the [GitHub Wiki](https://github.com/PCSX2/pcsx2/wiki)
|
||||
|
||||
Want more? [Check out the PCSX2 website](https://pcsx2.net/).
|
||||
See the [Contributing Guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md) or visit the [GitHub Wiki](https://github.com/PCSX2/pcsx2/wiki) for more info on how to contribute.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
RunWizard=0
|
||||
+146
-119
@@ -1619,8 +1619,6 @@ SCAJ-20143:
|
||||
name: "Armored Core - Last Raven"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SCAJ-20144:
|
||||
@@ -2025,9 +2023,10 @@ SCAJ-30005:
|
||||
halfPixelOffset: 2 # Corrects fullscreen bloom misalignment.
|
||||
SCAJ-30006:
|
||||
name: "Gran Turismo 4"
|
||||
region: "NTSC-Unk"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Text in GT mode works.
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 3 # Using chop for both normal+div fixes crash in B5 license test.
|
||||
eeDivRoundMode: 3 # See above.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -2046,10 +2045,11 @@ SCAJ-30006:
|
||||
- "SCPS-55007"
|
||||
SCAJ-30007:
|
||||
name: "Gran Turismo 4"
|
||||
region: "NTSC-Unk"
|
||||
region: "NTSC-C"
|
||||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 2 # Text in GT mode works.
|
||||
roundModes:
|
||||
eeRoundMode: 3 # Using chop for both normal+div fixes crash in B5 license test.
|
||||
eeDivRoundMode: 3 # See above.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -2057,9 +2057,10 @@ SCAJ-30007:
|
||||
getSkipCount: "GSC_PolyphonyDigitalGames" # Fixes post processing.
|
||||
SCAJ-30008:
|
||||
name: "Gran Turismo 4 [PS2 The Best]"
|
||||
region: "NTSC-Unk"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Text in GT mode works.
|
||||
region: "NTSC-C"
|
||||
roundModes:
|
||||
eeRoundMode: 3 # Using chop for both normal+div fixes crash in B5 license test.
|
||||
eeDivRoundMode: 3 # See above.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -5188,8 +5189,6 @@ SCES-53285:
|
||||
SCES-53286:
|
||||
name: "Jak X - Combat Racing"
|
||||
region: "PAL-M7"
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
@@ -8234,6 +8233,9 @@ SCPS-17001:
|
||||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 2 # Text in GT mode works.
|
||||
roundModes:
|
||||
eeRoundMode: 3 # Using chop for both normal+div fixes crash in B5 license test.
|
||||
eeDivRoundMode: 3 # See above.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -8886,6 +8888,10 @@ SCPS-51011:
|
||||
SCPS-51012:
|
||||
name: "Gigantic Drive"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SCPS-51013:
|
||||
name: "Torneko's Adventure 3"
|
||||
region: "NTSC-J"
|
||||
@@ -10482,8 +10488,6 @@ SCUS-97429:
|
||||
name: "Jak X - Combat Racing"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
@@ -10764,8 +10768,6 @@ SCUS-97485:
|
||||
SCUS-97486:
|
||||
name: "Jak X - Combat Racing [Regular Demo]"
|
||||
region: "NTSC-U"
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
@@ -10788,8 +10790,6 @@ SCUS-97488:
|
||||
name: "Jak X - Combat Racing [Public Beta v.1]"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
@@ -11126,8 +11126,6 @@ SCUS-97572:
|
||||
SCUS-97574:
|
||||
name: "Jak X - Combat Racing [Greatest Hits]"
|
||||
region: "NTSC-U"
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
@@ -11725,6 +11723,7 @@ SLED-50359:
|
||||
vuClampMode: 3 # Fixes out of place polys (COP2).
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLED-50439:
|
||||
name: "MX 2002 featuring Ricky Carmichael [Demo]"
|
||||
region: "PAL-E"
|
||||
@@ -12912,6 +12911,10 @@ SLES-50211:
|
||||
name: "Gauntlet - Dark Legacy"
|
||||
region: "PAL-M3"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 5 # Corrects lighting to match software.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
SLES-50212:
|
||||
name: "Paris-Dakar Rally"
|
||||
region: "PAL-E"
|
||||
@@ -13266,6 +13269,7 @@ SLES-50358:
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLES-50362:
|
||||
name: "Jonny Moseley Mad Trix"
|
||||
region: "PAL-E"
|
||||
@@ -14505,8 +14509,8 @@ SLES-50879:
|
||||
name: "Paris-Dakar 2"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes sky being shown over the 3D.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Fixes sky being shown over the 3D.
|
||||
SLES-50880:
|
||||
name: "BMX XXX"
|
||||
region: "PAL-M4"
|
||||
@@ -15144,7 +15148,7 @@ SLES-51192:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15155,7 +15159,7 @@ SLES-51193:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15166,7 +15170,7 @@ SLES-51194:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15177,7 +15181,7 @@ SLES-51195:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15188,7 +15192,7 @@ SLES-51196:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15244,7 +15248,7 @@ SLES-51214:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15255,7 +15259,7 @@ SLES-51215:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15266,7 +15270,7 @@ SLES-51216:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15277,7 +15281,7 @@ SLES-51217:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15288,7 +15292,7 @@ SLES-51218:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15299,7 +15303,7 @@ SLES-51219:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
texturePreloading: 0 # Performs better on certain areas like mid-game in and around the castle as the hash goes easily to 200 MB.
|
||||
@@ -15307,9 +15311,6 @@ SLES-51220:
|
||||
name: "TY the Tasmanian Tiger"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 1 # Fixes rendering of the moon.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SLES-51222:
|
||||
name: "Rayman 3 - Hoodlum Havoc"
|
||||
region: "PAL-M5"
|
||||
@@ -16830,8 +16831,8 @@ SLES-51897:
|
||||
name-sort: "Simpsons, The - Hit & Run"
|
||||
region: "PAL-M4"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Lens flare appears even when behind objects.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Lens flare appears even when behind objects.
|
||||
gsHWFixes:
|
||||
autoFlush: 2 # Fixes missing lens flare.
|
||||
SLES-51903:
|
||||
@@ -18328,6 +18329,10 @@ SLES-52563:
|
||||
SLES-52567:
|
||||
name: "Catwoman"
|
||||
region: "PAL-M7"
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes bloom.
|
||||
autoFlush: 1 # Fixes ghosting.
|
||||
textureInsideRT: 1 # Required for offset RTs/textures for post-processing.
|
||||
SLES-52568:
|
||||
name: "Crash Twinsanity"
|
||||
region: "PAL-M5"
|
||||
@@ -20998,7 +21003,6 @@ SLES-53523:
|
||||
minimumBlendingLevel: 3 # Fixes broken light and shadow rendering.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures and water textures and reflections.
|
||||
trilinearFiltering: 1
|
||||
textureInsideRT: 1 # Fixes rainbow artifacting around edges of screen.
|
||||
halfPixelOffset: 2 # Fixes misalgined bloom.
|
||||
autoFlush: 2 # Fixes missing bloom intensity and alignment.
|
||||
SLES-53524:
|
||||
@@ -21276,8 +21280,9 @@ SLES-53561:
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes the inability to take the bottle in the trophy case in Chapter 2: Hattrick vs Galloway.
|
||||
gsHWFixes:
|
||||
wildArmsHack: 1 # Reduces depth ghosting.
|
||||
roundSprite: 2 # Reduces depth ghosting.
|
||||
recommendedBlendingLevel: 2 # Fixes door transitions.
|
||||
halfPixelOffset: 4 # Reduces ghosting.
|
||||
roundSprite: 2 # Reduces ghosting.
|
||||
SLES-53563:
|
||||
name: "Nickelodeon SpongeBob SquarePants and Friends Unite!"
|
||||
region: "PAL-M6"
|
||||
@@ -21515,8 +21520,6 @@ SLES-53645:
|
||||
name: "Knights of the Temple II"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_KnightsOfTheTemple2"
|
||||
SLES-53646:
|
||||
name: "World Racing 2"
|
||||
region: "PAL-M5"
|
||||
@@ -21529,7 +21532,6 @@ SLES-53647:
|
||||
minimumBlendingLevel: 3 # Fixes broken light and shadow rendering.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures and water textures and reflections.
|
||||
trilinearFiltering: 1
|
||||
textureInsideRT: 1 # Fixes rainbow artifacting around edges of screen.
|
||||
halfPixelOffset: 2 # Fixes misalgined bloom.
|
||||
autoFlush: 2 # Fixes missing bloom intensity and alignment.
|
||||
SLES-53651:
|
||||
@@ -22025,8 +22027,8 @@ SLES-53804:
|
||||
SLES-53805:
|
||||
name: "Cocoto Funfair"
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes the cursor not being visible.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Fixes the cursor not being visible.
|
||||
SLES-53809:
|
||||
name: "K-1 Premium Dynamite!!"
|
||||
region: "PAL-E"
|
||||
@@ -22063,8 +22065,6 @@ SLES-53820:
|
||||
name: "Armored Core - Last Raven"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLES-53821:
|
||||
@@ -23830,8 +23830,9 @@ SLES-54483:
|
||||
region: "PAL-E"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes car reflections.
|
||||
mergeSprite: 1 # Fixes bluriness.
|
||||
halfPixelOffset: 1 # Fixes bluriness.
|
||||
halfPixelOffset: 4 # Fixes bluriness.
|
||||
SLES-54485:
|
||||
name: "Cinderella"
|
||||
region: "PAL-M3"
|
||||
@@ -23986,8 +23987,8 @@ SLES-54549:
|
||||
name: "Crazy Frog Racer 2"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes black fade effects and some overlays texts in the menus.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Fixes black fade effects and some overlays texts in the menus.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves road and grass textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -25704,8 +25705,6 @@ SLES-55170:
|
||||
SLES-55172:
|
||||
name: "Code Lyoko - Quest for Infinity"
|
||||
region: "PAL-M4"
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes missing texts on in-game textboxes.
|
||||
gsHWFixes:
|
||||
deinterlace: 9 # Game requires adaptive bff de-interlacing instead of auto for the UI at native.
|
||||
halfPixelOffset: 1 # Reduces ghosting effects.
|
||||
@@ -27300,8 +27299,7 @@ SLKA-15018:
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLKA-15019:
|
||||
name: "F1 Career Challenge"
|
||||
region: "NTSC-K"
|
||||
@@ -27945,8 +27943,7 @@ SLKA-25165:
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLKA-25166:
|
||||
name: "Sengoku Musou"
|
||||
region: "NTSC-K"
|
||||
@@ -28553,8 +28550,7 @@ SLKA-25314:
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLKA-25315:
|
||||
name: "NBA Live 06"
|
||||
region: "NTSC-K"
|
||||
@@ -30683,10 +30679,11 @@ SLPM-61007:
|
||||
speedHacks:
|
||||
mvuFlag: 0
|
||||
SLPM-61008:
|
||||
name: "Devil May Cry [Trial]"
|
||||
name: "Devil May Cry [Trial Edition Ver 2]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-61009:
|
||||
name: "Silent Hill 2 (Red Ribbon) [Trial]"
|
||||
region: "NTSC-J"
|
||||
@@ -30694,10 +30691,11 @@ SLPM-61009:
|
||||
instantVU1: 0 # Fixes hang on FMV's when CDVD timing is accurate.
|
||||
mtvu: 0
|
||||
SLPM-61010:
|
||||
name: "Devil May Cry [Trial Version]"
|
||||
name: "Devil May Cry [Trial Edition Ver 2]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-61011:
|
||||
name: "Silent Hill 2 (Black Ribbon) [Video Trial]"
|
||||
region: "NTSC-J"
|
||||
@@ -31002,16 +31000,12 @@ SLPM-61118:
|
||||
name: "Armored Core - Last Raven [Famitsu Special Trial Version]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLPM-61119:
|
||||
name: "Armored Core - Last Raven [Trial]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLPM-61120:
|
||||
@@ -31722,6 +31716,10 @@ SLPM-62125:
|
||||
name-sort: GAUNTLET DARK LEGACY
|
||||
name-en: "Gauntlet - Dark Legacy"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 5 # Corrects lighting to match software.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
SLPM-62126:
|
||||
name: "Hyper Sports 2002 Winter"
|
||||
region: "NTSC-J"
|
||||
@@ -32059,6 +32057,10 @@ SLPM-62209:
|
||||
name-sort: ぎがんてぃっく どらいぶ
|
||||
name-en: "Gigantic Drive"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SLPM-62211:
|
||||
name: 18WHEELER
|
||||
name-sort: 18WHEELER
|
||||
@@ -32210,7 +32212,7 @@ SLPM-62241:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLPM-62244:
|
||||
@@ -33501,7 +33503,7 @@ SLPM-62513:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLPM-62514:
|
||||
@@ -34858,7 +34860,7 @@ SLPM-64528:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLPM-64532:
|
||||
@@ -35061,6 +35063,7 @@ SLPM-65023:
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-65024:
|
||||
name: バイオハザード コード:ベロニカ 完全版 [ディスク1/2]
|
||||
name-sort: ばいおはざーど こーど:べろにか かんぜんばん [でぃすく1/2]
|
||||
@@ -35134,6 +35137,7 @@ SLPM-65038:
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-65039:
|
||||
name: 電車でGO!新幹線 山陽新幹線編
|
||||
name-sort: でんしゃでGO!しんかんせん さんようしんかんせんへん
|
||||
@@ -35836,6 +35840,10 @@ SLPM-65180:
|
||||
SLPM-65181:
|
||||
name: "Need for Speed - Hot Pursuit 2"
|
||||
region: "NTSC-C"
|
||||
clampModes:
|
||||
vuClampMode: 2 # White textures.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 1 # Fixes blurriness.
|
||||
SLPM-65183:
|
||||
name: auto modellista モデムパック バージョン
|
||||
name-sort: auto modellista もでむぱっく ばーじょん
|
||||
@@ -43321,6 +43329,7 @@ SLPM-66502:
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-66503:
|
||||
name: METAL GEAR SOLID 2 SONS OF LIBERTY MEGA HITS!
|
||||
name-sort: METAL GEAR SOLID 2 SONS OF LIBERTY MEGA HITS!
|
||||
@@ -46115,6 +46124,8 @@ SLPM-67003:
|
||||
name-en: "Sakura Taisen - Atsuki Chishioni"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
mergeSprite: 1 # Removes blur from the image.
|
||||
SLPM-67004:
|
||||
name: メダル オブ オナー ライジングサン
|
||||
name-sort: めだる おぶ おなー らいじんぐさん
|
||||
@@ -46206,6 +46217,7 @@ SLPM-67502:
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-67503:
|
||||
name: "FIFA 2002"
|
||||
region: "NTSC-K"
|
||||
@@ -46404,7 +46416,7 @@ SLPM-68005:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLPM-68007:
|
||||
@@ -46503,8 +46515,6 @@ SLPM-68520:
|
||||
name: "Armored Core - Last Raven [Monthly Champion magazine Special Edition]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLPM-68521:
|
||||
@@ -46741,6 +46751,7 @@ SLPM-74230:
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLPM-74231:
|
||||
name: 決戦III PS2 the Best
|
||||
name-sort: けっせんIII PS2 the Best
|
||||
@@ -48150,7 +48161,7 @@ SLPS-20234:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLPS-20237:
|
||||
@@ -49587,6 +49598,8 @@ SLPS-25034:
|
||||
name-sort: はなとたいようとあめと
|
||||
name-en: "Flower, Sun and Rain"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25035:
|
||||
name: モンスターファーム
|
||||
name-sort: もんすたーふぁーむ
|
||||
@@ -50251,6 +50264,8 @@ SLPS-25154:
|
||||
name-sort: はなとたいようとあめと Victor the Best
|
||||
name-en: "Flower, Sun and Rain [Victor The Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25155:
|
||||
name: ウルトラマン Fighting Evolution 2
|
||||
name-sort: うるとらまん Fighting Evolution 2
|
||||
@@ -50848,13 +50863,21 @@ SLPS-25263:
|
||||
SLPS-25264:
|
||||
name: ラーゼフォン 蒼穹幻想曲 PLUSCULUS
|
||||
name-sort: らーぜふぉん そうきゅうげんそうきょく PLUSCULUS
|
||||
name-en: "RahXephon [Limited Edition]"
|
||||
name-en: "RAhXEPhON - Soukyuu Gensoukyoku [Plusculus]"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeDivRoundMode: 3 # Fixes floating chairs.
|
||||
gsHWFixes:
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SLPS-25265:
|
||||
name: ラーゼフォン 蒼穹幻想曲 [通常版]
|
||||
name-sort: らーぜふぉん そうきゅうげんそうきょく [つうじょうばん]
|
||||
name-en: "RahXephon"
|
||||
name-en: "RAhXEPhON - Soukyuu Gensoukyoku"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeDivRoundMode: 3 # Fixes floating chairs.
|
||||
gsHWFixes:
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SLPS-25266:
|
||||
name: ザ・キング・オブ・ファイターズ 2001
|
||||
name-sort: ざ・きんぐ・おぶ・ふぁいたーず 2001
|
||||
@@ -51817,8 +51840,8 @@ SLPS-25430:
|
||||
name-sort: るぱんさんせい ころんぶすのいさんはしゅにそまる
|
||||
name-en: "Lupin III - Columbus no Isan wa Akenisomaru"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes game softlock after prison level.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Fixes game softlock after prison level.
|
||||
SLPS-25431:
|
||||
name: "Bokujou Monogatari - Oh! Wonderful Life"
|
||||
region: "NTSC-J"
|
||||
@@ -51915,6 +51938,8 @@ SLPS-25451:
|
||||
name-sort: はなとたいようとあめと Super Best Collection
|
||||
name-en: "Hana to Taiyou to Ame to [Super Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25452:
|
||||
name: キノの旅 -the Beautiful World- 電撃SP
|
||||
name-sort: きののたび -the Beautiful World- でんげきSP
|
||||
@@ -51982,8 +52007,6 @@ SLPS-25462:
|
||||
name-en: "Armored Core - Last Raven"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
memcardFilters:
|
||||
@@ -52546,8 +52569,7 @@ SLPS-25569:
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLPS-25570:
|
||||
name: キノの旅II
|
||||
name-sort: きののたびII
|
||||
@@ -53452,8 +53474,7 @@ SLPS-25718:
|
||||
compat: 5
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fix camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fix target loss issue.
|
||||
eeDivRoundMode: 1 # Fix target loss issue.
|
||||
patches:
|
||||
F616C207:
|
||||
content: |-
|
||||
@@ -53521,18 +53542,16 @@ SLPS-25730:
|
||||
name-en: "Armored Core - Last Raven [Machine Side Box]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLPS-25731:
|
||||
name: アーマード・コア 2 -MACHINE SIDE BOX-
|
||||
name-sort: アーマード・コア 2 -MACHINE SIDE BOX-
|
||||
name-sort: あーまーど・こあ 2 -MACHINE SIDE BOX-
|
||||
name-en: "Armored Core 2 [Machine Side Box]"
|
||||
region: "NTSC-J"
|
||||
SLPS-25732:
|
||||
name: アーマード・コア 3 -MACHINE SIDE BOX-
|
||||
name-sort: アーマード・コア 3 -MACHINE SIDE BOX-
|
||||
name-sort: あーまーど・こあ 3 -MACHINE SIDE BOX-
|
||||
name-en: "Armored Core 3 [Machine Side Box]"
|
||||
region: "NTSC-J"
|
||||
SLPS-25733:
|
||||
@@ -54306,8 +54325,9 @@ SLPS-25879:
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes the inability to take the bottle in the trophy case in Chapter 2: Hattrick vs Galloway.
|
||||
gsHWFixes:
|
||||
wildArmsHack: 1 # Reduces depth ghosting.
|
||||
roundSprite: 2 # Reduces depth ghosting.
|
||||
recommendedBlendingLevel: 2 # Fixes door transitions.
|
||||
halfPixelOffset: 4 # Reduces ghosting.
|
||||
roundSprite: 2 # Reduces ghosting.
|
||||
SLPS-25880:
|
||||
name: "True Fortune"
|
||||
region: "NTSC-J"
|
||||
@@ -54465,8 +54485,8 @@ SLPS-25914:
|
||||
name-sort: きどうせんしがんだむ ぎれんのやぼう あくしずのきょういV
|
||||
name-en: "Kidou Senshi Gundam - Giren no Yabou - Axis no Kyoui V"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- FpuNegDivHack
|
||||
roundModes:
|
||||
eeDivRoundMode: 1
|
||||
SLPS-25915:
|
||||
name: ザ・キング・オブ・ファイターズ 2002 アンリミテッドマッチ
|
||||
name-sort: ざ・きんぐ・おぶ・ふぁいたーず 2002 あんりみてっどまっち
|
||||
@@ -54601,8 +54621,9 @@ SLPS-25950:
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes the inability to take the bottle in the trophy case in Chapter 2: Hattrick vs Galloway.
|
||||
gsHWFixes:
|
||||
wildArmsHack: 1 # Reduces depth ghosting.
|
||||
roundSprite: 2 # Reduces depth ghosting.
|
||||
recommendedBlendingLevel: 2 # Fixes door transitions.
|
||||
halfPixelOffset: 4 # Reduces ghosting.
|
||||
roundSprite: 2 # Reduces ghosting.
|
||||
SLPS-25953:
|
||||
name: "Daisenryaku VII - Exceed"
|
||||
region: "NTSC-J"
|
||||
@@ -54625,8 +54646,8 @@ SLPS-25959:
|
||||
name-sort: きどうせんしがんだむ ぎれんのやぼう あくしずのきょういV GUNDAM 30th ANNIVERSARY COLLECTION
|
||||
name-en: "Kidou Senshi Gundam - Giren no Yabou - Axis no Kyoui V"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- FpuNegDivHack
|
||||
roundModes:
|
||||
eeDivRoundMode: 1
|
||||
SLPS-25961:
|
||||
name: 機動戦士ガンダムSEED DESTINY 連合 vs. Z.A.F.T. II plus GUNDAM 30th ANNIVERSARY COLLECTION
|
||||
name-sort: きどうせんしがんだむSEED DESTINY れんごう vs. Z.A.F.T. II plus GUNDAM 30th ANNIVERSARY COLLECTION
|
||||
@@ -54634,8 +54655,7 @@ SLPS-25961:
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLPS-25971:
|
||||
name: "NeoGeo Online Collection Vol. 2 - Bakumatsu Roman - Gekka no Kenshi 1, 2"
|
||||
region: "NTSC-J"
|
||||
@@ -55282,8 +55302,6 @@ SLPS-73247:
|
||||
name-en: "Armored Core - Last Raven [PS2 The Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
memcardFilters:
|
||||
@@ -55418,8 +55436,7 @@ SLPS-73269:
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 1 # Fixes camera issue.
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes target loss issue.
|
||||
eeDivRoundMode: 1 # Fixes target loss issue.
|
||||
SLPS-73270:
|
||||
name: "Super Robot Taisen Z [PS2 The Best]"
|
||||
region: "NTSC-J"
|
||||
@@ -55798,6 +55815,10 @@ SLUS-20047:
|
||||
name: "Gauntlet - Dark Legacy"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 5 # Corrects lighting to match software.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
SLUS-20048:
|
||||
name: "Legion - The Legend of Excalibur"
|
||||
region: "NTSC-U"
|
||||
@@ -56471,6 +56492,7 @@ SLUS-20216:
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
patches:
|
||||
79B8A95F:
|
||||
content: |-
|
||||
@@ -57590,6 +57612,10 @@ SLUS-20445:
|
||||
name: "Robot Alchemic Drive - RAD"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SLUS-20446:
|
||||
name: "Agassi Tennis Generation"
|
||||
region: "NTSC-U"
|
||||
@@ -58224,9 +58250,6 @@ SLUS-20571:
|
||||
name: "TY the Tasmanian Tiger"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 1 # Fixes rendering of the moon.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SLUS-20572:
|
||||
name: "Tiger Woods PGA Tour 2003"
|
||||
region: "NTSC-U"
|
||||
@@ -58258,7 +58281,7 @@ SLUS-20576:
|
||||
- EETimingHack # Fixes flickering textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes missing lighting effects.
|
||||
mipmap: 1 # Fixes blurry textures. Full would be ideal here but causes broken face textures on Harry.
|
||||
mipmap: 2 # Fixes blurry textures.
|
||||
trilinearFiltering: 1 # Fixes blurry textures.
|
||||
cpuFramebufferConversion: 1 # Fixes right side of the screen from garbage textures.
|
||||
SLUS-20577:
|
||||
@@ -58506,8 +58529,8 @@ SLUS-20624:
|
||||
name-sort: "Simpsons, The - Hit & Run"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Lens flare appears even when behind objects.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Lens flare appears even when behind objects.
|
||||
gsHWFixes:
|
||||
autoFlush: 2 # Fixes missing lens flare.
|
||||
SLUS-20625:
|
||||
@@ -60461,6 +60484,10 @@ SLUS-20992:
|
||||
name: "Catwoman"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes bloom.
|
||||
autoFlush: 1 # Fixes ghosting.
|
||||
textureInsideRT: 1 # Required for offset RTs/textures for post-processing.
|
||||
SLUS-20993:
|
||||
name: "Ghosthunter"
|
||||
region: "NTSC-U"
|
||||
@@ -61281,7 +61308,6 @@ SLUS-21139:
|
||||
minimumBlendingLevel: 3 # Fixes broken light and shadow rendering.
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures and water textures and reflections.
|
||||
trilinearFiltering: 1
|
||||
textureInsideRT: 1 # Fixes rainbow artifacting around edges of screen.
|
||||
halfPixelOffset: 2 # Fixes misalgined bloom.
|
||||
autoFlush: 2 # Fixes missing bloom intensity and alignment.
|
||||
SLUS-21140:
|
||||
@@ -62068,8 +62094,9 @@ SLUS-21269:
|
||||
clampModes:
|
||||
eeClampMode: 3 # Fixes the inability to take the bottle in the trophy case in Chapter 2: Hattrick vs Galloway.
|
||||
gsHWFixes:
|
||||
wildArmsHack: 1 # Reduces depth ghosting.
|
||||
roundSprite: 2 # Reduces depth ghosting.
|
||||
recommendedBlendingLevel: 2 # Fixes door transitions.
|
||||
halfPixelOffset: 4 # Reduces ghosting.
|
||||
roundSprite: 2 # Reduces ghosting.
|
||||
SLUS-21270:
|
||||
name: "MS Saga - A New Dawn"
|
||||
region: "NTSC-U"
|
||||
@@ -62506,8 +62533,6 @@ SLUS-21338:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes glow effects, but breaks shadows of certain objects.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
halfPixelOffset: 2 # Corrects shadow alignment and reduces blurriness.
|
||||
recommendedBlendingLevel: 3 # Fixes level and map menu brightness.
|
||||
SLUS-21339:
|
||||
@@ -63227,8 +63252,9 @@ SLUS-21449:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes car reflections.
|
||||
mergeSprite: 1 # Fixes bluriness.
|
||||
halfPixelOffset: 1 # Fixes bluriness.
|
||||
halfPixelOffset: 4 # Fixes bluriness.
|
||||
SLUS-21450:
|
||||
name: "Super PickUps"
|
||||
region: "NTSC-U"
|
||||
@@ -64078,8 +64104,8 @@ SLUS-21634:
|
||||
name: "Crazy Frog Racer 2"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes black fade effects and some overlays texts in the menus.
|
||||
roundModes:
|
||||
eeDivRoundMode: 1 # Fixes black fade effects and some overlays texts in the menus.
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves road and grass textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
@@ -64624,8 +64650,6 @@ SLUS-21743:
|
||||
name: "Code Lyoko - Quest for Infinity"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- FpuNegDivHack # Fixes missing texts on in-game textboxes.
|
||||
gsHWFixes:
|
||||
deinterlace: 9 # Game requires adaptive bff de-interlacing instead of auto for the UI at native.
|
||||
halfPixelOffset: 1 # Reduces ghosting effects.
|
||||
@@ -65840,6 +65864,7 @@ SLUS-29009:
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
disablePartialInvalidation: 1 # Fixes corrupt textures.
|
||||
halfPixelOffset: 2 # Alleviates blur from upscaling.
|
||||
SLUS-29010:
|
||||
name: "Crash Bandicoot - The Wrath of Cortex [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -65882,6 +65907,10 @@ SLUS-29022:
|
||||
SLUS-29025:
|
||||
name: "R.A.D. - Robot Alchemic Drive [Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
autoFlush: 2 # Fixes DOF effect.
|
||||
SLUS-29026:
|
||||
name: "MX SuperFly [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -66645,8 +66674,6 @@ TCES-53286:
|
||||
name: "Jak X Beta Trial Code"
|
||||
region: "PAL-E"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- InstantDMAHack # Fixes bad IPU DMA timing.
|
||||
gsHWFixes:
|
||||
roundSprite: 1 # Fix lines in the sky.
|
||||
autoFlush: 2 # Fixes lighting.
|
||||
|
||||
Binary file not shown.
@@ -352,7 +352,7 @@
|
||||
030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
|
||||
030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,lefttrigger:a2,righttrigger:a5,platform:Windows,
|
||||
030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -461,7 +461,7 @@
|
||||
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
|
||||
03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
|
||||
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
|
||||
@@ -631,7 +631,7 @@ float4 sample_color(float2 st, float uv_w)
|
||||
}
|
||||
else if(PS_AEM_FMT == FMT_16)
|
||||
{
|
||||
c[i].a = c[i].a >= 0.5 ? TA.y : !PS_AEM || any(c[i].rgb) ? TA.x : 0;
|
||||
c[i].a = c[i].a >= 0.5 ? TA.y : !PS_AEM || any(int3(c[i].rgb * 255.0f) & 0xF8) ? TA.x : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,6 +742,25 @@ float4 ps_color(PS_INPUT input)
|
||||
float4 T = sample_color(st, input.t.w);
|
||||
#endif
|
||||
|
||||
if (PS_SHUFFLE && !PS_SHUFFLE_SAME && !PS_READ16_SRC)
|
||||
{
|
||||
uint4 denorm_c_before = uint4(T);
|
||||
if (PS_READ_BA)
|
||||
{
|
||||
T.r = float((denorm_c_before.b << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.b >> 2) & 0x38) | ((denorm_c_before.a << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.a << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.a & 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
T.r = float((denorm_c_before.r << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.r >> 2) & 0x38) | ((denorm_c_before.g << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.g << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.g & 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
float4 C = tfx(T, input.c);
|
||||
|
||||
atst(C);
|
||||
@@ -925,48 +944,6 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
discard;
|
||||
}
|
||||
|
||||
if (PS_SHUFFLE)
|
||||
{
|
||||
uint4 denorm_c = uint4(C);
|
||||
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
if (PS_SHUFFLE_SAME)
|
||||
{
|
||||
if (PS_READ_BA)
|
||||
C = (float4)(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
else
|
||||
C.ga = C.rg;
|
||||
}
|
||||
// Copy of a 16bit source in to this target
|
||||
else if (PS_READ16_SRC)
|
||||
{
|
||||
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u));
|
||||
else
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
|
||||
}
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
else if (PS_READ_BA)
|
||||
{
|
||||
C.rb = C.bb;
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
else
|
||||
{
|
||||
C.rb = C.rr;
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
}
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
@@ -1023,6 +1000,63 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
ps_blend(C, alpha_blend, input.p.xy);
|
||||
|
||||
if (PS_SHUFFLE)
|
||||
{
|
||||
if (!PS_SHUFFLE_SAME && !PS_READ16_SRC)
|
||||
{
|
||||
uint4 denorm_c_after = uint4(C);
|
||||
if (PS_READ_BA)
|
||||
{
|
||||
C.b = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.a = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
}
|
||||
else
|
||||
{
|
||||
C.r = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.g = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
}
|
||||
}
|
||||
|
||||
uint4 denorm_c = uint4(C);
|
||||
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
if (PS_SHUFFLE_SAME)
|
||||
{
|
||||
if (PS_READ_BA)
|
||||
C = (float4)(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
else
|
||||
C.ga = C.rg;
|
||||
}
|
||||
// Copy of a 16bit source in to this target
|
||||
else if (PS_READ16_SRC)
|
||||
{
|
||||
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u));
|
||||
else
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
|
||||
}
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
else if (PS_READ_BA)
|
||||
{
|
||||
C.rb = C.bb;
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
else
|
||||
{
|
||||
C.rb = C.rr;
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
}
|
||||
|
||||
ps_dither(C.rgb, input.p.xy);
|
||||
|
||||
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||
|
||||
@@ -580,7 +580,7 @@ vec4 sample_color(vec2 st)
|
||||
c[i].a = ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||
//c[i].a = ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||
#elif (PS_AEM_FMT == FMT_16)
|
||||
c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||
c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || any(bvec3(ivec3(c[i].rgb * 255.0f) & ivec3(0xF8))) ) ? TA.x : 0.0f;
|
||||
//c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||
#endif
|
||||
}
|
||||
@@ -687,6 +687,21 @@ vec4 ps_color()
|
||||
vec4 T = sample_color(st);
|
||||
#endif
|
||||
|
||||
#if PS_SHUFFLE && !PS_SHUFFLE_SAME && !PS_READ16_SRC
|
||||
uvec4 denorm_c_before = uvec4(T);
|
||||
#if PS_READ_BA
|
||||
T.r = float((denorm_c_before.b << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.b >> 2) & 0x38) | ((denorm_c_before.a << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.a << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.a & 0x80);
|
||||
#else
|
||||
T.r = float((denorm_c_before.r << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.r >> 2) & 0x38) | ((denorm_c_before.g << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.g << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.g & 0x80);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec4 C = tfx(T, PSin.c);
|
||||
|
||||
atst(C);
|
||||
@@ -937,7 +952,56 @@ void ps_main()
|
||||
|
||||
vec4 C = ps_color();
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
#if PS_FIXED_ONE_A
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
vec4 alpha_blend = vec4(RT.a / 128.0f);
|
||||
#else
|
||||
vec4 alpha_blend = vec4(C.a / 128.0f);
|
||||
#endif
|
||||
|
||||
// Correct the ALPHA value based on the output format
|
||||
#if (PS_DST_FMT == FMT_16)
|
||||
float A_one = 128.0f; // alpha output will be 0x80
|
||||
C.a = (PS_FBA != 0) ? A_one : step(128.0f, C.a) * A_one;
|
||||
#elif (PS_DST_FMT == FMT_32) && (PS_FBA != 0)
|
||||
if(C.a < 128.0f) C.a += 128.0f;
|
||||
#endif
|
||||
|
||||
// Get first primitive that will write a failling alpha value
|
||||
#if PS_DATE == 1
|
||||
// DATM == 0
|
||||
// Pixel with alpha equal to 1 will failed (128-255)
|
||||
SV_Target0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#elif PS_DATE == 2
|
||||
// DATM == 1
|
||||
// Pixel with alpha equal to 0 will failed (0-127)
|
||||
SV_Target0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#endif
|
||||
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
|
||||
#if PS_SHUFFLE
|
||||
#if !PS_SHUFFLE_SAME && !PS_READ16_SRC
|
||||
uvec4 denorm_c_after = uvec4(C);
|
||||
#if PS_READ_BA
|
||||
C.b = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.a = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
#else
|
||||
C.r = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.g = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
@@ -991,43 +1055,6 @@ void ps_main()
|
||||
#endif // PS_SHUFFLE_SAME
|
||||
#endif // PS_SHUFFLE
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
#if PS_FIXED_ONE_A
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||
vec4 alpha_blend = vec4(RT.a / 128.0f);
|
||||
#else
|
||||
vec4 alpha_blend = vec4(C.a / 128.0f);
|
||||
#endif
|
||||
|
||||
// Correct the ALPHA value based on the output format
|
||||
#if (PS_DST_FMT == FMT_16)
|
||||
float A_one = 128.0f; // alpha output will be 0x80
|
||||
C.a = (PS_FBA != 0) ? A_one : step(128.0f, C.a) * A_one;
|
||||
#elif (PS_DST_FMT == FMT_32) && (PS_FBA != 0)
|
||||
if(C.a < 128.0f) C.a += 128.0f;
|
||||
#endif
|
||||
|
||||
// Get first primitive that will write a failling alpha value
|
||||
#if PS_DATE == 1
|
||||
// DATM == 0
|
||||
// Pixel with alpha equal to 1 will failed (128-255)
|
||||
SV_Target0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#elif PS_DATE == 2
|
||||
// DATM == 1
|
||||
// Pixel with alpha equal to 0 will failed (0-127)
|
||||
SV_Target0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#endif
|
||||
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
ps_dither(C.rgb);
|
||||
|
||||
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||
|
||||
@@ -817,7 +817,7 @@ vec4 sample_color(vec2 st)
|
||||
#if (PS_AEM_FMT == FMT_24)
|
||||
c[i].a = (PS_AEM == 0 || any(bvec3(c[i].rgb))) ? TA.x : 0.0f;
|
||||
#elif (PS_AEM_FMT == FMT_16)
|
||||
c[i].a = (c[i].a >= 0.5) ? TA.y : ((PS_AEM == 0 || any(bvec3(c[i].rgb))) ? TA.x : 0.0f);
|
||||
c[i].a = (c[i].a >= 0.5) ? TA.y : ((PS_AEM == 0 || any(bvec3(ivec3(c[i].rgb * 255.0f) & ivec3(0xF8)))) ? TA.x : 0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -933,6 +933,21 @@ vec4 ps_color()
|
||||
vec4 T = sample_color(st);
|
||||
#endif
|
||||
|
||||
#if PS_SHUFFLE && !PS_SHUFFLE_SAME && !PS_READ16_SRC
|
||||
uvec4 denorm_c_before = uvec4(T);
|
||||
#if PS_READ_BA
|
||||
T.r = float((denorm_c_before.b << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.b >> 2) & 0x38) | ((denorm_c_before.a << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.a << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.a & 0x80);
|
||||
#else
|
||||
T.r = float((denorm_c_before.r << 3) & 0xF8);
|
||||
T.g = float(((denorm_c_before.r >> 2) & 0x38) | ((denorm_c_before.g << 6) & 0xC0));
|
||||
T.b = float((denorm_c_before.g << 1) & 0xF8);
|
||||
T.a = float(denorm_c_before.g & 0x80);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec4 C = tfx(T, vsIn.c);
|
||||
|
||||
atst(C);
|
||||
@@ -1184,40 +1199,6 @@ void main()
|
||||
|
||||
vec4 C = ps_color();
|
||||
|
||||
#if PS_SHUFFLE
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
#if PS_SHUFFLE_SAME
|
||||
#if (PS_READ_BA)
|
||||
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
#else
|
||||
C.ga = C.rg;
|
||||
#endif
|
||||
// Copy of a 16bit source in to this target
|
||||
#elif PS_READ16_SRC
|
||||
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#elif PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
if ((denorm_c.g & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#endif // PS_SHUFFLE_SAME
|
||||
#endif // PS_SHUFFLE
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
@@ -1254,9 +1235,53 @@ void main()
|
||||
o_col0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
|
||||
#else
|
||||
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
#if PS_SHUFFLE
|
||||
#if !PS_SHUFFLE_SAME && !PS_READ16_SRC
|
||||
uvec4 denorm_c_after = uvec4(C);
|
||||
#if PS_READ_BA
|
||||
C.b = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.a = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
#else
|
||||
C.r = float(((denorm_c_after.r >> 3) & 0x1F) | ((denorm_c_after.g << 2) & 0xE0));
|
||||
C.g = float(((denorm_c_after.g >> 6) & 0x3) | ((denorm_c_after.b >> 1) & 0x7C) | (denorm_c_after.a & 0x80));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uvec4 denorm_c = uvec4(C);
|
||||
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
|
||||
#if PS_SHUFFLE_SAME
|
||||
#if (PS_READ_BA)
|
||||
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
|
||||
#else
|
||||
C.ga = C.rg;
|
||||
#endif
|
||||
// Copy of a 16bit source in to this target
|
||||
#elif PS_READ16_SRC
|
||||
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
|
||||
// Write RB part. Mask will take care of the correct destination
|
||||
#elif PS_READ_BA
|
||||
C.rb = C.bb;
|
||||
if ((denorm_c.a & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#else
|
||||
C.rb = C.rr;
|
||||
if ((denorm_c.g & 0x80u) != 0u)
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
#endif // PS_SHUFFLE_SAME
|
||||
#endif // PS_SHUFFLE
|
||||
|
||||
ps_dither(C.rgb);
|
||||
|
||||
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||
|
||||
@@ -4,7 +4,6 @@ set(PCSX2_DEFS "")
|
||||
#-------------------------------------------------------------------------------
|
||||
# Misc option
|
||||
#-------------------------------------------------------------------------------
|
||||
option(DISABLE_BUILD_DATE "Disable including the binary compile date")
|
||||
option(ENABLE_TESTS "Enables building the unit tests" ON)
|
||||
option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits most from it but not anything else")
|
||||
option(USE_VTUNE "Plug VTUNE to profile GS JIT.")
|
||||
@@ -195,22 +194,12 @@ endif()
|
||||
|
||||
# -Wno-attributes: "always_inline function might not be inlinable" <= real spam (thousand of warnings!!!)
|
||||
# -Wno-missing-field-initializers: standard allow to init only the begin of struct/array in static init. Just a silly warning.
|
||||
# Note: future GCC (aka GCC 5.1.1) has less false positive so warning could maybe put back
|
||||
# -Wno-unused-function: warn for function not used in release build
|
||||
# -Wno-unused-value: lots of warning for this kind of statements "0 && ...". There are used to disable some parts of code in release/dev build.
|
||||
# -Wno-format*: Yeah, these need to be taken care of, but...
|
||||
# -Wno-stringop-truncation: Who comes up with these compiler warnings, anyways?
|
||||
# -Wno-stringop-overflow: Probably the same people as this one...
|
||||
# -Wno-maybe-uninitialized: Lots of gcc warnings like "‘test.GSVector8i::<anonymous>.GSVector8i::<unnamed union>::m’ may be used uninitialized" if this is removed.
|
||||
|
||||
if (MSVC)
|
||||
set(DEFAULT_WARNINGS)
|
||||
else()
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security -Wno-unused-value)
|
||||
endif()
|
||||
|
||||
if (USE_GCC)
|
||||
list(APPEND DEFAULT_WARNINGS -Wno-stringop-truncation -Wno-stringop-overflow -Wno-maybe-uninitialized )
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers)
|
||||
endif()
|
||||
|
||||
if (USE_PGO_GENERATE OR USE_PGO_OPTIMIZE)
|
||||
@@ -241,11 +230,6 @@ endif()
|
||||
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS})
|
||||
|
||||
if(DISABLE_BUILD_DATE)
|
||||
message(STATUS "Disabling the inclusion of the binary compile date.")
|
||||
list(APPEND PCSX2_DEFS DISABLE_BUILD_DATE)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# MacOS-specific things
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
+63
-50
@@ -1,7 +1,12 @@
|
||||
function(detect_operating_system)
|
||||
message(STATUS "CMake Version: ${CMAKE_VERSION}")
|
||||
message(STATUS "CMake System Name: ${CMAKE_SYSTEM_NAME}")
|
||||
|
||||
# LINUX wasn't added until CMake 3.25.
|
||||
if (CMAKE_VERSION VERSION_LESS 3.25.0 AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# Have to make it visible in this scope as well for below.
|
||||
set(LINUX TRUE PARENT_SCOPE)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
@@ -39,84 +44,92 @@ function(detect_compiler)
|
||||
endfunction()
|
||||
|
||||
function(get_git_version_info)
|
||||
set(PCSX2_WC_TIME 0)
|
||||
set(PCSX2_GIT_REV "")
|
||||
set(PCSX2_GIT_TAG "")
|
||||
set(PCSX2_GIT_HASH "")
|
||||
if (GIT_FOUND AND EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} show -s --format=%ci HEAD
|
||||
OUTPUT_VARIABLE PCSX2_WC_TIME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
# Output: "YYYY-MM-DD HH:MM:SS +HHMM" (last part is time zone, offset from UTC)
|
||||
string(REGEX REPLACE "[%:\\-]" "" PCSX2_WC_TIME "${PCSX2_WC_TIME}")
|
||||
string(REGEX REPLACE "([0-9]+) ([0-9]+).*" "\\1\\2" PCSX2_WC_TIME "${PCSX2_WC_TIME}")
|
||||
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
|
||||
OUTPUT_VARIABLE PCSX2_GIT_REV
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} tag --points-at HEAD
|
||||
OUTPUT_VARIABLE PCSX2_GIT_TAG
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} tag --points-at HEAD --sort=version:refname
|
||||
OUTPUT_VARIABLE PCSX2_GIT_TAG_LIST
|
||||
RESULT_VARIABLE TAG_RESULT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
|
||||
# CAUTION: There is a race here, this solves the problem of a commit being tagged multiple times (take the last tag)
|
||||
# however, if simultaneous builds are pushing tags to the same commit you might get inconsistent results (it's a race)
|
||||
#
|
||||
# The easy solution is, don't do that, but just something to be aware of.
|
||||
if(PCSX2_GIT_TAG_LIST AND TAG_RESULT EQUAL 0)
|
||||
string(REPLACE "\n" ";" PCSX2_GIT_TAG_LIST "${PCSX2_GIT_TAG_LIST}")
|
||||
if (PCSX2_GIT_TAG_LIST)
|
||||
list(GET PCSX2_GIT_TAG_LIST -1 PCSX2_GIT_TAG)
|
||||
message("Using tag: ${PCSX2_GIT_TAG}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
|
||||
OUTPUT_VARIABLE PCSX2_GIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} log -1 --format=%cd --date=local
|
||||
OUTPUT_VARIABLE PCSX2_GIT_DATE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
endif()
|
||||
if ("${PCSX2_GIT_TAG}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" PCSX2_VERSION_LONG "${PCSX2_GIT_TAG}")
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" PCSX2_VERSION_SHORT "${PCSX2_GIT_TAG}")
|
||||
elseif(PCSX2_GIT_REV)
|
||||
set(PCSX2_VERSION_LONG "${PCSX2_GIT_REV}")
|
||||
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?(-[a-z][a-z0-9]+)?" PCSX2_VERSION_SHORT "${PCSX2_VERSION_LONG}")
|
||||
else()
|
||||
set(PCSX2_VERSION_LONG "Unknown (git unavailable)")
|
||||
set(PCSX2_VERSION_SHORT "Unknown")
|
||||
endif()
|
||||
if ("${PCSX2_WC_TIME}" STREQUAL "")
|
||||
set(PCSX2_WC_TIME 0)
|
||||
if (NOT PCSX2_GIT_REV)
|
||||
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
|
||||
OUTPUT_VARIABLE PCSX2_GIT_REV
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
if (NOT PCSX2_GIT_REV)
|
||||
set(PCSX2_GIT_REV "Unknown")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(PCSX2_WC_TIME "${PCSX2_WC_TIME}" PARENT_SCOPE)
|
||||
set(PCSX2_GIT_REV "${PCSX2_GIT_REV}" PARENT_SCOPE)
|
||||
set(PCSX2_GIT_TAG "${PCSX2_GIT_TAG}" PARENT_SCOPE)
|
||||
set(PCSX2_GIT_HASH "${PCSX2_GIT_HASH}" PARENT_SCOPE)
|
||||
set(PCSX2_VERSION_LONG "${PCSX2_VERSION_LONG}" PARENT_SCOPE)
|
||||
set(PCSX2_VERSION_SHORT "${PCSX2_VERSION_SHORT}" PARENT_SCOPE)
|
||||
set(PCSX2_GIT_DATE "${PCSX2_GIT_DATE}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(write_svnrev_h)
|
||||
if(PCSX2_GIT_TAG)
|
||||
if ("${PCSX2_GIT_TAG}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define SVN_REV ${PCSX2_WC_TIME}ll\n"
|
||||
"#define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_TAGGED_COMMIT 1\n"
|
||||
"#define GIT_TAG_HI ${CMAKE_MATCH_1}\n"
|
||||
"#define GIT_TAG_MID ${CMAKE_MATCH_2}\n"
|
||||
"#define GIT_TAG_LO ${CMAKE_MATCH_3}\n"
|
||||
"#define GIT_REV \"\"\n"
|
||||
"#define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
|
||||
)
|
||||
else()
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define SVN_REV ${PCSX2_WC_TIME}ll\n"
|
||||
"#define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_TAGGED_COMMIT 1\n"
|
||||
"#define GIT_REV \"\"\n"
|
||||
"#define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define SVN_REV ${PCSX2_WC_TIME}ll\n"
|
||||
if ("${PCSX2_GIT_TAG}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_TAGGED_COMMIT 1\n"
|
||||
"#define GIT_TAG_HI ${CMAKE_MATCH_1}\n"
|
||||
"#define GIT_TAG_MID ${CMAKE_MATCH_2}\n"
|
||||
"#define GIT_TAG_LO ${CMAKE_MATCH_3}\n"
|
||||
"#define GIT_REV \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
|
||||
"#define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
|
||||
)
|
||||
elseif ("${PCSX2_GIT_REV}" MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_TAGGED_COMMIT 0\n"
|
||||
"#define GIT_TAG_HI ${CMAKE_MATCH_1}\n"
|
||||
"#define GIT_TAG_MID ${CMAKE_MATCH_2}\n"
|
||||
"#define GIT_TAG_LO ${CMAKE_MATCH_3}\n"
|
||||
"#define GIT_REV \"${PCSX2_GIT_REV}\"\n"
|
||||
"#define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
|
||||
"#define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
|
||||
)
|
||||
else()
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h
|
||||
"#define GIT_TAG \"${PCSX2_GIT_TAG}\"\n"
|
||||
"#define GIT_TAGGED_COMMIT 0\n"
|
||||
"#define GIT_TAG_HI 0\n"
|
||||
"#define GIT_TAG_MID 0\n"
|
||||
"#define GIT_TAG_LO 0\n"
|
||||
"#define GIT_REV \"${PCSX2_GIT_REV}\"\n"
|
||||
"#define GIT_HASH \"${PCSX2_GIT_HASH}\"\n"
|
||||
"#define GIT_DATE \"${PCSX2_GIT_DATE}\"\n"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
+455
-470
@@ -1,524 +1,509 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "common/Threading.h"
|
||||
#include "common/TraceLog.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/RedtapeWindows.h" // OutputDebugString
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/SmallString.h"
|
||||
#include "common/Timer.h"
|
||||
|
||||
using namespace Threading;
|
||||
#include "fmt/format.h"
|
||||
|
||||
// thread-local console indentation setting.
|
||||
static thread_local int conlog_Indent(0);
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
// thread-local console color storage.
|
||||
static thread_local ConsoleColors conlog_Color(DefaultConsoleColor);
|
||||
|
||||
#ifdef __POSIX__
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
|
||||
static FILE* stdout_fp = stdout;
|
||||
|
||||
static bool checkSupportsColor()
|
||||
{
|
||||
if (!isatty(fileno(stdout_fp)))
|
||||
return false;
|
||||
char* term = getenv("TERM");
|
||||
if (!term || (0 == strcmp(term, "dumb")))
|
||||
return false;
|
||||
return true; // Probably supports color
|
||||
}
|
||||
|
||||
static bool supports_color = checkSupportsColor();
|
||||
|
||||
void Console_SetStdout(FILE* fp)
|
||||
{
|
||||
stdout_fp = fp;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function re-assigns the console log writer(s) to the specified target. It makes sure
|
||||
// to flush any contents from the buffered console log (which typically accumulates due to
|
||||
// log suspension during log file/window re-init operations) into the new log.
|
||||
//
|
||||
// Important! Only Assert and Null console loggers are allowed during C++ startup init (when
|
||||
// the program or DLL first loads). Other log targets rely on the static buffer and a
|
||||
// threaded mutex lock, which are only valid after C++ initialization has finished.
|
||||
void Console_SetActiveHandler(const IConsoleWriter& writer, FILE* flushfp)
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
// Dummy objects, need to get rid of them...
|
||||
ConsoleLogWriter<LOGLEVEL_INFO> Console;
|
||||
ConsoleLogWriter<LOGLEVEL_DEV> DevCon;
|
||||
|
||||
#ifdef _DEBUG
|
||||
ConsoleLogWriter<LOGLEVEL_DEBUG> DbgConWriter;
|
||||
#else
|
||||
NullLogWriter DbgConWriter;
|
||||
#endif
|
||||
|
||||
#define TIMESTAMP_FORMAT_STRING "[{:10.4f}] "
|
||||
#define TIMESTAMP_PRINTF_STRING "[%10.4f] "
|
||||
|
||||
namespace Log
|
||||
{
|
||||
pxAssertMsg(
|
||||
(writer.WriteRaw != NULL) && (writer.DoWriteLn != NULL) &&
|
||||
(writer.Newline != NULL) && (writer.SetTitle != NULL) &&
|
||||
(writer.DoSetColor != NULL),
|
||||
"Invalid IConsoleWriter object! All function pointer interfaces must be implemented.");
|
||||
static void WriteToConsole(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
static void WriteToDebug(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
static void WriteToFile(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
|
||||
Console = writer;
|
||||
DevConWriter = writer;
|
||||
static void UpdateMaxLevel();
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
DbgCon = writer;
|
||||
static void ExecuteCallbacks(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
|
||||
static Common::Timer::Value s_start_timestamp = Common::Timer::GetCurrentValue();
|
||||
|
||||
static LOGLEVEL s_max_level = LOGLEVEL_NONE;
|
||||
static LOGLEVEL s_console_level = LOGLEVEL_NONE;
|
||||
static LOGLEVEL s_debug_level = LOGLEVEL_NONE;
|
||||
static LOGLEVEL s_file_level = LOGLEVEL_NONE;
|
||||
static LOGLEVEL s_host_level = LOGLEVEL_NONE;
|
||||
static bool s_log_timestamps = true;
|
||||
|
||||
static FileSystem::ManagedCFilePtr s_file_handle;
|
||||
static std::string s_file_path;
|
||||
static std::mutex s_file_mutex;
|
||||
|
||||
static HostCallbackType s_host_callback;
|
||||
|
||||
#ifdef _WIN32
|
||||
static HANDLE s_hConsoleStdIn = NULL;
|
||||
static HANDLE s_hConsoleStdOut = NULL;
|
||||
static HANDLE s_hConsoleStdErr = NULL;
|
||||
#endif
|
||||
} // namespace Log
|
||||
|
||||
float Log::GetCurrentMessageTime()
|
||||
{
|
||||
return static_cast<float>(Common::Timer::ConvertValueToSeconds(Common::Timer::GetCurrentValue() - s_start_timestamp));
|
||||
}
|
||||
|
||||
__ri void Log::WriteToConsole(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
static constexpr std::string_view s_ansi_color_codes[ConsoleColors_Count] = {
|
||||
"\033[0m"sv, // default
|
||||
"\033[30m\033[1m"sv, // black
|
||||
"\033[32m"sv, // green
|
||||
"\033[31m"sv, // red
|
||||
"\033[34m"sv, // blue
|
||||
"\033[35m"sv, // magenta
|
||||
"\033[35m"sv, // orange (FIXME)
|
||||
"\033[37m"sv, // gray
|
||||
"\033[36m"sv, // cyan
|
||||
"\033[33m"sv, // yellow
|
||||
"\033[37m"sv, // white
|
||||
"\033[30m\033[1m"sv, // strong black
|
||||
"\033[31m\033[1m"sv, // strong red
|
||||
"\033[32m\033[1m"sv, // strong green
|
||||
"\033[34m\033[1m"sv, // strong blue
|
||||
"\033[35m\033[1m"sv, // strong magenta
|
||||
"\033[35m\033[1m"sv, // strong orange (FIXME)
|
||||
"\033[37m\033[1m"sv, // strong gray
|
||||
"\033[36m\033[1m"sv, // strong cyan
|
||||
"\033[33m\033[1m"sv, // strong yellow
|
||||
"\033[37m\033[1m"sv, // strong white
|
||||
};
|
||||
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
|
||||
SmallStackString<BUFFER_SIZE> buffer;
|
||||
buffer.reserve(32 + message.length());
|
||||
buffer.append(s_ansi_color_codes[color]);
|
||||
|
||||
if (s_log_timestamps)
|
||||
buffer.append_fmt(TIMESTAMP_FORMAT_STRING, Log::GetCurrentMessageTime());
|
||||
|
||||
buffer.append(message);
|
||||
buffer.append('\n');
|
||||
|
||||
#ifdef _WIN32
|
||||
const HANDLE hOutput = (level <= LOGLEVEL_WARNING) ? s_hConsoleStdErr : s_hConsoleStdOut;
|
||||
|
||||
// Convert to UTF-16 first so Unicode characters display correctly. NT is going to do it anyway...
|
||||
wchar_t wbuf[BUFFER_SIZE];
|
||||
wchar_t* wmessage_buf = wbuf;
|
||||
int wmessage_buflen = static_cast<int>(std::size(wbuf) - 1);
|
||||
if (buffer.length() >= std::size(wbuf))
|
||||
{
|
||||
wmessage_buflen = static_cast<int>(buffer.length());
|
||||
wmessage_buf = static_cast<wchar_t*>(std::malloc(static_cast<size_t>(wmessage_buflen) * sizeof(wchar_t)));
|
||||
if (!wmessage_buf)
|
||||
return;
|
||||
}
|
||||
|
||||
const int wmessage_size = MultiByteToWideChar(CP_UTF8, 0, buffer.data(), static_cast<int>(buffer.length()), wmessage_buf, wmessage_buflen);
|
||||
if (wmessage_size <= 0)
|
||||
goto cleanup;
|
||||
|
||||
DWORD chars_written;
|
||||
WriteConsoleW(hOutput, wmessage_buf, static_cast<DWORD>(wmessage_size), &chars_written, nullptr);
|
||||
|
||||
cleanup:
|
||||
if (wmessage_buf != wbuf)
|
||||
std::free(wmessage_buf);
|
||||
#else
|
||||
const int fd = (level <= LOGLEVEL_WARNING) ? STDERR_FILENO : STDOUT_FILENO;
|
||||
write(fd, buffer.data(), buffer.length());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Writes text to the Visual Studio Output window (Microsoft Windows only).
|
||||
// On all other platforms this pipes to Stdout instead.
|
||||
static void MSW_OutputDebugString(const char* text)
|
||||
bool Log::IsConsoleOutputEnabled()
|
||||
{
|
||||
return (s_console_level > LOGLEVEL_NONE);
|
||||
}
|
||||
|
||||
void Log::SetConsoleOutputLevel(LOGLEVEL level)
|
||||
{
|
||||
if (s_console_level == level)
|
||||
return;
|
||||
|
||||
const bool was_enabled = (s_console_level > LOGLEVEL_NONE);
|
||||
const bool now_enabled = (level > LOGLEVEL_NONE);
|
||||
s_console_level = level;
|
||||
UpdateMaxLevel();
|
||||
|
||||
if (was_enabled == now_enabled)
|
||||
return;
|
||||
|
||||
// Worst that happens here is we write to a bad handle..
|
||||
|
||||
#if defined(_WIN32)
|
||||
static constexpr auto enable_virtual_terminal_processing = [](HANDLE hConsole) {
|
||||
DWORD old_mode;
|
||||
if (!GetConsoleMode(hConsole, &old_mode))
|
||||
return;
|
||||
|
||||
// already enabled?
|
||||
if (old_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
return;
|
||||
|
||||
SetConsoleMode(hConsole, old_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
};
|
||||
|
||||
// On windows, no console is allocated by default on a windows based application
|
||||
static bool console_was_allocated = false;
|
||||
static HANDLE old_stdin = NULL;
|
||||
static HANDLE old_stdout = NULL;
|
||||
static HANDLE old_stderr = NULL;
|
||||
|
||||
if (now_enabled)
|
||||
{
|
||||
old_stdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
old_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
old_stderr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
if (!old_stdout)
|
||||
{
|
||||
// Attach to the parent console if we're running from a command window
|
||||
if (!AttachConsole(ATTACH_PARENT_PROCESS) && !AllocConsole())
|
||||
return;
|
||||
|
||||
s_hConsoleStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
s_hConsoleStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
s_hConsoleStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
enable_virtual_terminal_processing(s_hConsoleStdOut);
|
||||
enable_virtual_terminal_processing(s_hConsoleStdErr);
|
||||
|
||||
std::FILE* fp;
|
||||
freopen_s(&fp, "CONIN$", "r", stdin);
|
||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
||||
freopen_s(&fp, "CONOUT$", "w", stderr);
|
||||
|
||||
console_was_allocated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_hConsoleStdIn = old_stdin;
|
||||
s_hConsoleStdOut = old_stdout;
|
||||
s_hConsoleStdErr = old_stderr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (console_was_allocated)
|
||||
{
|
||||
console_was_allocated = false;
|
||||
|
||||
std::FILE* fp;
|
||||
freopen_s(&fp, "NUL:", "w", stderr);
|
||||
freopen_s(&fp, "NUL:", "w", stdout);
|
||||
freopen_s(&fp, "NUL:", "w", stdin);
|
||||
|
||||
SetStdHandle(STD_ERROR_HANDLE, old_stderr);
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, old_stdout);
|
||||
SetStdHandle(STD_INPUT_HANDLE, old_stdin);
|
||||
|
||||
s_hConsoleStdIn = NULL;
|
||||
s_hConsoleStdOut = NULL;
|
||||
s_hConsoleStdErr = NULL;
|
||||
|
||||
FreeConsole();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__ri void Log::WriteToDebug(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
static bool hasDebugger = IsDebuggerPresent();
|
||||
if (hasDebugger)
|
||||
OutputDebugStringA(text);
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
|
||||
// Convert to UTF-16 first so Unicode characters display correctly. NT is going to do it anyway...
|
||||
wchar_t wbuf[BUFFER_SIZE];
|
||||
wchar_t* wmessage_buf = wbuf;
|
||||
int wmessage_buflen = static_cast<int>(std::size(wbuf) - 1);
|
||||
if (message.length() >= std::size(wbuf))
|
||||
{
|
||||
wmessage_buflen = static_cast<int>(message.length());
|
||||
wmessage_buf = static_cast<wchar_t*>(std::malloc((static_cast<size_t>(wmessage_buflen) + 2) * sizeof(wchar_t)));
|
||||
if (!wmessage_buf)
|
||||
return;
|
||||
}
|
||||
|
||||
int wmessage_size = 0;
|
||||
if (!message.empty()) [[likely]]
|
||||
{
|
||||
wmessage_size = MultiByteToWideChar(CP_UTF8, 0, message.data(), static_cast<int>(message.length()), wmessage_buf, wmessage_buflen);
|
||||
if (wmessage_size <= 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
wmessage_buf[wmessage_size++] = L'\n';
|
||||
wmessage_buf[wmessage_size++] = 0;
|
||||
OutputDebugStringW(wmessage_buf);
|
||||
|
||||
cleanup:
|
||||
if (wmessage_buf != wbuf)
|
||||
std::free(wmessage_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Log::IsDebugOutputAvailable()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return IsDebuggerPresent();
|
||||
#else
|
||||
fputs(text, stdout_fp);
|
||||
fflush(stdout_fp);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleNull
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static void ConsoleNull_SetTitle(const char* title) {}
|
||||
static void ConsoleNull_DoSetColor(ConsoleColors color) {}
|
||||
static void ConsoleNull_Newline() {}
|
||||
static void ConsoleNull_DoWrite(const char* fmt) {}
|
||||
static void ConsoleNull_DoWriteLn(const char* fmt) {}
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Null =
|
||||
{
|
||||
ConsoleNull_DoWrite,
|
||||
ConsoleNull_DoWriteLn,
|
||||
ConsoleNull_DoSetColor,
|
||||
|
||||
ConsoleNull_DoWrite,
|
||||
ConsoleNull_Newline,
|
||||
ConsoleNull_SetTitle,
|
||||
|
||||
0, // instance-level indentation (should always be 0)
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Console_Stdout
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
#if defined(__POSIX__)
|
||||
static __fi const char* GetLinuxConsoleColor(ConsoleColors color)
|
||||
bool Log::IsDebugOutputEnabled()
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case Color_Black:
|
||||
case Color_StrongBlack:
|
||||
return "\033[30m\033[1m";
|
||||
|
||||
case Color_Red:
|
||||
return "\033[31m";
|
||||
case Color_StrongRed:
|
||||
return "\033[31m\033[1m";
|
||||
|
||||
case Color_Green:
|
||||
return "\033[32m";
|
||||
case Color_StrongGreen:
|
||||
return "\033[32m\033[1m";
|
||||
|
||||
case Color_Yellow:
|
||||
return "\033[33m";
|
||||
case Color_StrongYellow:
|
||||
return "\033[33m\033[1m";
|
||||
|
||||
case Color_Blue:
|
||||
return "\033[34m";
|
||||
case Color_StrongBlue:
|
||||
return "\033[34m\033[1m";
|
||||
|
||||
// No orange, so use magenta.
|
||||
case Color_Orange:
|
||||
case Color_Magenta:
|
||||
return "\033[35m";
|
||||
case Color_StrongOrange:
|
||||
case Color_StrongMagenta:
|
||||
return "\033[35m\033[1m";
|
||||
|
||||
case Color_Cyan:
|
||||
return "\033[36m";
|
||||
case Color_StrongCyan:
|
||||
return "\033[36m\033[1m";
|
||||
|
||||
// Use 'white' instead of grey.
|
||||
case Color_Gray:
|
||||
case Color_White:
|
||||
return "\033[37m";
|
||||
case Color_StrongGray:
|
||||
case Color_StrongWhite:
|
||||
return "\033[37m\033[1m";
|
||||
|
||||
// On some other value being passed, clear any formatting.
|
||||
case Color_Default:
|
||||
default:
|
||||
return "\033[0m";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// One possible default write action at startup and shutdown is to use the stdout.
|
||||
static void ConsoleStdout_DoWrite(const char* fmt)
|
||||
{
|
||||
MSW_OutputDebugString(fmt);
|
||||
return (s_console_level > LOGLEVEL_NONE);
|
||||
}
|
||||
|
||||
// Default write action at startup and shutdown is to use the stdout.
|
||||
static void ConsoleStdout_DoWriteLn(const char* fmt)
|
||||
void Log::SetDebugOutputLevel(LOGLEVEL level)
|
||||
{
|
||||
MSW_OutputDebugString(fmt);
|
||||
MSW_OutputDebugString("\n");
|
||||
s_debug_level = level;
|
||||
UpdateMaxLevel();
|
||||
}
|
||||
|
||||
static void ConsoleStdout_Newline()
|
||||
__ri void Log::WriteToFile(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
MSW_OutputDebugString("\n");
|
||||
}
|
||||
|
||||
static void ConsoleStdout_DoSetColor(ConsoleColors color)
|
||||
{
|
||||
#if defined(__POSIX__)
|
||||
if (!supports_color)
|
||||
std::unique_lock lock(s_file_mutex);
|
||||
if (!s_file_handle) [[unlikely]]
|
||||
return;
|
||||
fprintf(stdout_fp, "\033[0m%s", GetLinuxConsoleColor(color));
|
||||
fflush(stdout_fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ConsoleStdout_SetTitle(const char* title)
|
||||
{
|
||||
#if defined(__POSIX__)
|
||||
if (supports_color)
|
||||
fputs("\033]0;", stdout_fp);
|
||||
fputs(title, stdout_fp);
|
||||
if (supports_color)
|
||||
fputs("\007", stdout_fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Stdout =
|
||||
if (!message.empty()) [[likely]]
|
||||
{
|
||||
ConsoleStdout_DoWrite, // Writes without newlines go to buffer to avoid error log spam.
|
||||
ConsoleStdout_DoWriteLn,
|
||||
ConsoleStdout_DoSetColor,
|
||||
|
||||
ConsoleNull_DoWrite, // writes from re-piped stdout are ignored here, lest we create infinite loop hell >_<
|
||||
ConsoleStdout_Newline,
|
||||
ConsoleStdout_SetTitle,
|
||||
0, // instance-level indentation (should always be 0)
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleAssert
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
static void ConsoleAssert_DoWrite(const char* fmt)
|
||||
{
|
||||
pxFailRel("Console class has not been initialized");
|
||||
}
|
||||
|
||||
static void ConsoleAssert_DoWriteLn(const char* fmt)
|
||||
{
|
||||
pxFailRel("Console class has not been initialized");
|
||||
}
|
||||
|
||||
const IConsoleWriter ConsoleWriter_Assert =
|
||||
{
|
||||
ConsoleAssert_DoWrite,
|
||||
ConsoleAssert_DoWriteLn,
|
||||
ConsoleNull_DoSetColor,
|
||||
|
||||
ConsoleNull_DoWrite,
|
||||
ConsoleNull_Newline,
|
||||
ConsoleNull_SetTitle,
|
||||
|
||||
0, // instance-level indentation (should always be 0)
|
||||
};
|
||||
|
||||
// =====================================================================================================
|
||||
// IConsoleWriter (implementations)
|
||||
// =====================================================================================================
|
||||
// (all non-virtual members that do common work and then pass the result through DoWrite
|
||||
// or DoWriteLn)
|
||||
|
||||
// Parameters:
|
||||
// glob_indent - this parameter is used to specify a global indentation setting. It is used by
|
||||
// WriteLn function, but defaults to 0 for Warning and Error calls. Local indentation always
|
||||
// applies to all writes.
|
||||
std::string IConsoleWriter::_addIndentation(const std::string& src, int glob_indent = 0) const
|
||||
{
|
||||
const int indent = glob_indent + _imm_indentation;
|
||||
|
||||
std::string indentStr;
|
||||
for (int i = 0; i < indent; i++)
|
||||
indentStr += '\t';
|
||||
|
||||
std::string result;
|
||||
result.reserve(src.length() + 16 * indent);
|
||||
result.append(indentStr);
|
||||
result.append(src);
|
||||
|
||||
std::string::size_type pos = result.find('\n');
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
result.insert(pos + 1, indentStr);
|
||||
pos = result.find('\n', pos + 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Sets the indentation to be applied to all WriteLn's. The indentation is added to the
|
||||
// primary write, and to any newlines specified within the write. Note that this applies
|
||||
// to calls to WriteLn *only* -- calls to Write bypass the indentation parser.
|
||||
const IConsoleWriter& IConsoleWriter::SetIndent(int tabcount) const
|
||||
{
|
||||
conlog_Indent += tabcount;
|
||||
pxAssert(conlog_Indent >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IConsoleWriter IConsoleWriter::Indent(int tabcount) const
|
||||
{
|
||||
IConsoleWriter retval = *this;
|
||||
retval._imm_indentation = tabcount;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Changes the active console color.
|
||||
// This color will be unset by calls to colored text methods
|
||||
// such as ErrorMsg and Notice.
|
||||
const IConsoleWriter& IConsoleWriter::SetColor(ConsoleColors color) const
|
||||
{
|
||||
// Ignore current color requests since, well, the current color is already set. ;)
|
||||
if (color == Color_Current)
|
||||
return *this;
|
||||
|
||||
pxAssertMsg((color > Color_Current) && (color < ConsoleColors_Count), "Invalid ConsoleColor specified.");
|
||||
|
||||
if (conlog_Color != color)
|
||||
DoSetColor(conlog_Color = color);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConsoleColors IConsoleWriter::GetColor() const
|
||||
{
|
||||
return conlog_Color;
|
||||
}
|
||||
|
||||
// Restores the console color to default (usually black, or low-intensity white if the console uses a black background)
|
||||
const IConsoleWriter& IConsoleWriter::ClearColor() const
|
||||
{
|
||||
if (conlog_Color != DefaultConsoleColor)
|
||||
DoSetColor(conlog_Color = DefaultConsoleColor);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ASCII/UTF8 (char*)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
bool IConsoleWriter::FormatV(const char* fmt, va_list args) const
|
||||
{
|
||||
// TODO: Make this less rubbish
|
||||
if ((_imm_indentation + conlog_Indent) > 0)
|
||||
{
|
||||
DoWriteLn(_addIndentation(StringUtil::StdStringFromFormatV(fmt, args), conlog_Indent).c_str());
|
||||
if (s_log_timestamps)
|
||||
{
|
||||
std::fprintf(s_file_handle.get(), TIMESTAMP_PRINTF_STRING "%.*s\n", GetCurrentMessageTime(),
|
||||
static_cast<int>(message.size()), message.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fprintf(s_file_handle.get(), "%.*s\n", static_cast<int>(message.size()), message.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DoWriteLn(StringUtil::StdStringFromFormatV(fmt, args).c_str());
|
||||
if (s_log_timestamps)
|
||||
{
|
||||
std::fprintf(s_file_handle.get(), TIMESTAMP_PRINTF_STRING "\n", GetCurrentMessageTime());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fputc('\n', s_file_handle.get());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
std::fflush(s_file_handle.get());
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(const char* fmt, ...) const
|
||||
bool Log::IsFileOutputEnabled()
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
FormatV(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
return (s_file_level > LOGLEVEL_NONE);
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(ConsoleColors color, const char* fmt, ...) const
|
||||
bool Log::SetFileOutputLevel(LOGLEVEL level, std::string path)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ConsoleColorScope cs(color);
|
||||
FormatV(fmt, args);
|
||||
va_end(args);
|
||||
std::unique_lock lock(s_file_mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Error(const char* fmt, ...) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ConsoleColorScope cs(Color_StrongRed);
|
||||
FormatV(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Warning(const char* fmt, ...) const
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ConsoleColorScope cs(Color_StrongOrange);
|
||||
FormatV(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(ConsoleColors color, const std::string& str) const
|
||||
{
|
||||
ConsoleColorScope cs(color);
|
||||
return WriteLn(str);
|
||||
}
|
||||
|
||||
bool IConsoleWriter::WriteLn(const std::string& str) const
|
||||
{
|
||||
// TODO: Make this less rubbish
|
||||
if ((_imm_indentation + conlog_Indent) > 0)
|
||||
const bool was_enabled = (s_file_level > LOGLEVEL_NONE);
|
||||
const bool new_enabled = (level > LOGLEVEL_NONE && !path.empty());
|
||||
if (was_enabled != new_enabled || (new_enabled && path == s_file_path))
|
||||
{
|
||||
DoWriteLn(_addIndentation(str, conlog_Indent).c_str());
|
||||
if (new_enabled)
|
||||
{
|
||||
if (!s_file_handle || s_file_path != path)
|
||||
{
|
||||
s_file_handle.reset();
|
||||
s_file_handle = FileSystem::OpenManagedCFile(path.c_str(), "wb");
|
||||
if (s_file_handle)
|
||||
{
|
||||
s_file_path = std::move(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_file_path = {};
|
||||
|
||||
if (IsConsoleOutputEnabled())
|
||||
WriteToConsole(LOGLEVEL_ERROR, Color_StrongRed, TinyString::from_fmt("Failed to open log file '{}'", path));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_file_handle.reset();
|
||||
s_file_path = {};
|
||||
}
|
||||
}
|
||||
|
||||
s_file_level = s_file_handle ? level : LOGLEVEL_NONE;
|
||||
return IsFileOutputEnabled();
|
||||
}
|
||||
|
||||
std::FILE* Log::GetFileLogHandle()
|
||||
{
|
||||
std::unique_lock lock(s_file_mutex);
|
||||
return s_file_handle.get();
|
||||
}
|
||||
|
||||
bool Log::IsHostOutputEnabled()
|
||||
{
|
||||
return (s_host_level > LOGLEVEL_NONE);
|
||||
}
|
||||
|
||||
void Log::SetHostOutputLevel(LOGLEVEL level, HostCallbackType callback)
|
||||
{
|
||||
s_host_callback = callback;
|
||||
s_host_level = callback ? level : LOGLEVEL_NONE;
|
||||
UpdateMaxLevel();
|
||||
}
|
||||
|
||||
bool Log::AreTimestampsEnabled()
|
||||
{
|
||||
return s_log_timestamps;
|
||||
}
|
||||
|
||||
void Log::SetTimestampsEnabled(bool enabled)
|
||||
{
|
||||
s_log_timestamps = enabled;
|
||||
}
|
||||
|
||||
LOGLEVEL Log::GetMaxLevel()
|
||||
{
|
||||
return s_max_level;
|
||||
}
|
||||
|
||||
__ri void Log::UpdateMaxLevel()
|
||||
{
|
||||
s_max_level = std::max(s_console_level, std::max(s_debug_level, std::max(s_file_level, s_host_level)));
|
||||
}
|
||||
|
||||
void Log::ExecuteCallbacks(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
// TODO: Cache the message time.
|
||||
|
||||
// Split newlines into separate messages.
|
||||
std::string_view::size_type start_pos = 0;
|
||||
if (std::string_view::size_type end_pos = message.find('\n'); end_pos != std::string::npos) [[unlikely]]
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
std::string_view message_line;
|
||||
if (start_pos != end_pos)
|
||||
message_line = message.substr(start_pos, (end_pos == std::string_view::npos) ? end_pos : end_pos - start_pos);
|
||||
|
||||
ExecuteCallbacks(level, color, message_line);
|
||||
|
||||
if (end_pos == std::string_view::npos)
|
||||
return;
|
||||
|
||||
start_pos = end_pos + 1;
|
||||
end_pos = message.find('\n', start_pos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pxAssert(level > LOGLEVEL_NONE);
|
||||
if (level <= s_console_level)
|
||||
WriteToConsole(level, color, message);
|
||||
|
||||
if (level <= s_debug_level)
|
||||
WriteToDebug(level, color, message);
|
||||
|
||||
if (level <= s_file_level)
|
||||
WriteToFile(level, color, message);
|
||||
|
||||
if (level <= s_host_level)
|
||||
{
|
||||
// double check in case of race here
|
||||
const HostCallbackType callback = s_host_callback;
|
||||
if (callback)
|
||||
s_host_callback(level, color, message);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::Write(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
if (level > s_max_level)
|
||||
return;
|
||||
|
||||
ExecuteCallbacks(level, color, message);
|
||||
}
|
||||
|
||||
void Log::Writef(LOGLEVEL level, ConsoleColors color, const char* format, ...)
|
||||
{
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
Writev(level, color, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Log::Writev(LOGLEVEL level, ConsoleColors color, const char* format, va_list ap)
|
||||
{
|
||||
if (level > s_max_level)
|
||||
return;
|
||||
|
||||
std::va_list ap_copy;
|
||||
va_copy(ap_copy, ap);
|
||||
|
||||
#ifdef _WIN32
|
||||
const u32 required_size = static_cast<u32>(_vscprintf(format, ap_copy));
|
||||
#else
|
||||
const u32 required_size = std::vsnprintf(nullptr, 0, format, ap_copy);
|
||||
#endif
|
||||
va_end(ap_copy);
|
||||
|
||||
if (required_size < 512)
|
||||
{
|
||||
char buffer[512];
|
||||
const int len = std::vsnprintf(buffer, std::size(buffer), format, ap);
|
||||
if (len > 0)
|
||||
ExecuteCallbacks(level, color, std::string_view(buffer, static_cast<size_t>(len)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DoWriteLn(str.c_str());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Error(const std::string& str) const
|
||||
{
|
||||
return WriteLn(Color_StrongRed, str);
|
||||
}
|
||||
|
||||
bool IConsoleWriter::Warning(const std::string& str) const
|
||||
{
|
||||
return WriteLn(Color_StrongOrange, str);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleColorScope / ConsoleIndentScope
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
ConsoleColorScope::ConsoleColorScope(ConsoleColors newcolor)
|
||||
{
|
||||
m_IsScoped = false;
|
||||
m_newcolor = newcolor;
|
||||
EnterScope();
|
||||
}
|
||||
|
||||
ConsoleColorScope::~ConsoleColorScope()
|
||||
{
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
void ConsoleColorScope::EnterScope()
|
||||
{
|
||||
if (!m_IsScoped)
|
||||
{
|
||||
m_old_color = Console.GetColor();
|
||||
Console.SetColor(m_newcolor);
|
||||
m_IsScoped = true;
|
||||
char* buffer = new char[required_size + 1];
|
||||
const int len = std::vsnprintf(buffer, required_size + 1, format, ap);
|
||||
if (len > 0)
|
||||
ExecuteCallbacks(level, color, std::string_view(buffer, static_cast<size_t>(len)));
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleColorScope::LeaveScope()
|
||||
void Log::WriteFmtArgs(LOGLEVEL level, ConsoleColors color, fmt::string_view fmt, fmt::format_args args)
|
||||
{
|
||||
m_IsScoped = m_IsScoped && (Console.SetColor(m_old_color), false);
|
||||
}
|
||||
if (level > s_max_level)
|
||||
return;
|
||||
|
||||
ConsoleIndentScope::ConsoleIndentScope(int tabs)
|
||||
{
|
||||
m_IsScoped = false;
|
||||
m_amount = tabs;
|
||||
EnterScope();
|
||||
}
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::vformat_to(std::back_inserter(buffer), fmt, args);
|
||||
|
||||
ConsoleIndentScope::~ConsoleIndentScope()
|
||||
{
|
||||
LeaveScope();
|
||||
}
|
||||
|
||||
void ConsoleIndentScope::EnterScope()
|
||||
{
|
||||
m_IsScoped = m_IsScoped || (Console.SetIndent(m_amount), true);
|
||||
}
|
||||
|
||||
void ConsoleIndentScope::LeaveScope()
|
||||
{
|
||||
m_IsScoped = m_IsScoped && (Console.SetIndent(-m_amount), false);
|
||||
}
|
||||
|
||||
|
||||
ConsoleAttrScope::ConsoleAttrScope(ConsoleColors newcolor, int indent)
|
||||
{
|
||||
m_old_color = Console.GetColor();
|
||||
Console.SetIndent(m_tabsize = indent);
|
||||
Console.SetColor(newcolor);
|
||||
}
|
||||
|
||||
ConsoleAttrScope::~ConsoleAttrScope()
|
||||
{
|
||||
Console.SetColor(m_old_color);
|
||||
Console.SetIndent(-m_tabsize);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Default Writer for C++ init / startup:
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Currently all build types default to Stdout, which is very functional on Linux but not
|
||||
// always so useful on Windows (which itself lacks a proper stdout console without using
|
||||
// platform specific code). Under windows Stdout will attempt to write to the IDE Debug
|
||||
// console, if one is available (such as running pcsx2 via MSVC). If not available, then
|
||||
// the log message will pretty much be lost into the ether.
|
||||
//
|
||||
#define _DefaultWriter_ ConsoleWriter_Stdout
|
||||
|
||||
IConsoleWriter Console = _DefaultWriter_;
|
||||
IConsoleWriter DevConWriter = _DefaultWriter_;
|
||||
bool DevConWriterEnabled = false;
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
IConsoleWriter DbgConWriter = _DefaultWriter_;
|
||||
#endif
|
||||
|
||||
NullConsoleWriter NullCon = {};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleLogSource (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Writes to the console using the specified color. This overrides the default color setting
|
||||
// for this log.
|
||||
bool ConsoleLogSource::WriteV(ConsoleColors color, const char* fmt, va_list list) const
|
||||
{
|
||||
ConsoleColorScope cs(color);
|
||||
Console.WriteLn(StringUtil::StdStringFromFormatV(fmt, list));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Writes to the console using the source's default color. Note that the source's default
|
||||
// color will always be used, thus ConsoleColorScope() will not be effectual unless the
|
||||
// console's default color is Color_Default.
|
||||
bool ConsoleLogSource::WriteV(const char* fmt, va_list list) const
|
||||
{
|
||||
WriteV(DefaultColor, fmt, list);
|
||||
return false;
|
||||
ExecuteCallbacks(level, color, std::string_view(buffer.data(), buffer.size()));
|
||||
}
|
||||
|
||||
+129
-171
@@ -1,16 +1,19 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Pcsx2Defs.h"
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
|
||||
// TODO: This whole thing needs to get ripped out.
|
||||
|
||||
enum ConsoleColors
|
||||
{
|
||||
Color_Current = -1,
|
||||
|
||||
Color_Default = 0,
|
||||
|
||||
Color_Black,
|
||||
@@ -42,191 +45,146 @@ enum ConsoleColors
|
||||
ConsoleColors_Count
|
||||
};
|
||||
|
||||
static const ConsoleColors DefaultConsoleColor = Color_Default;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// IConsoleWriter -- For printing messages to the console.
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// General ConsoleWrite Threading Guideline:
|
||||
// PCSX2 is a threaded environment and multiple threads can write to the console asynchronously.
|
||||
// Individual calls to ConsoleWriter APIs will be written in atomic fashion, however "partial"
|
||||
// logs may end up interrupted by logs on other threads. This is usually not a problem for
|
||||
// WriteLn, but may be undesirable for typical uses of Write. In cases where you want to
|
||||
// print multi-line blocks of uninterrupted logs, compound the entire log into a single large
|
||||
// string and issue that to WriteLn.
|
||||
//
|
||||
struct IConsoleWriter
|
||||
enum LOGLEVEL
|
||||
{
|
||||
// A direct console write, without tabbing or newlines. Useful to devs who want to do quick
|
||||
// logging of various junk; but should *not* be used in production code due.
|
||||
void(* WriteRaw)(const char* fmt);
|
||||
LOGLEVEL_NONE, // Silences all log traffic
|
||||
LOGLEVEL_ERROR,
|
||||
LOGLEVEL_WARNING,
|
||||
LOGLEVEL_INFO,
|
||||
LOGLEVEL_DEV,
|
||||
LOGLEVEL_DEBUG,
|
||||
LOGLEVEL_TRACE,
|
||||
|
||||
// WriteLn implementation for internal use only. Bypasses tabbing, prefixing, and other
|
||||
// formatting.
|
||||
void(* DoWriteLn)(const char* fmt);
|
||||
|
||||
// SetColor implementation for internal use only.
|
||||
void(* DoSetColor)(ConsoleColors color);
|
||||
|
||||
// Special implementation of DoWrite that's pretty much for MSVC use only.
|
||||
// All implementations should map to DoWrite, except Stdio which should map to Null.
|
||||
// (This avoids circular/recursive stdio output)
|
||||
void(* DoWriteFromStdout)(const char* fmt);
|
||||
|
||||
void(* Newline)();
|
||||
void(* SetTitle)(const char* title);
|
||||
|
||||
// internal value for indentation of individual lines. Use the Indent() member to invoke.
|
||||
int _imm_indentation;
|
||||
|
||||
// For internal use only.
|
||||
std::string _addIndentation(const std::string& src, int glob_indent) const;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Public members; call these to print stuff to console!
|
||||
//
|
||||
// All functions always return false. Return value is provided only so that we can easily
|
||||
// disable logs at compile time using the "0&&action" macro trick.
|
||||
|
||||
ConsoleColors GetColor() const;
|
||||
const IConsoleWriter& SetColor(ConsoleColors color) const;
|
||||
const IConsoleWriter& ClearColor() const;
|
||||
const IConsoleWriter& SetIndent(int tabcount = 1) const;
|
||||
|
||||
IConsoleWriter Indent(int tabcount = 1) const;
|
||||
|
||||
bool FormatV(const char* fmt, va_list args) const;
|
||||
bool WriteLn(ConsoleColors color, const char* fmt, ...) const;
|
||||
bool WriteLn(const char* fmt, ...) const;
|
||||
bool Error(const char* fmt, ...) const;
|
||||
bool Warning(const char* fmt, ...) const;
|
||||
|
||||
bool WriteLn(ConsoleColors color, const std::string& str) const;
|
||||
bool WriteLn(const std::string& str) const;
|
||||
bool Error(const std::string& str) const;
|
||||
bool Warning(const std::string& str) const;
|
||||
LOGLEVEL_COUNT,
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// NullConsoleWriter
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Used by Release builds for Debug and Devel writes (DbgCon / DevCon). Inlines to NOPs. :)
|
||||
//
|
||||
struct NullConsoleWriter
|
||||
// TODO: Move this elsewhere, add channels.
|
||||
|
||||
namespace Log
|
||||
{
|
||||
void WriteRaw(const char* fmt) {}
|
||||
void DoWriteLn(const char* fmt) {}
|
||||
void DoSetColor(ConsoleColors color) {}
|
||||
void DoWriteFromStdout(const char* fmt) {}
|
||||
void Newline() {}
|
||||
void SetTitle(const char* title) {}
|
||||
// log message callback type
|
||||
using HostCallbackType = void (*)(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
|
||||
// returns the time in seconds since the start of the process
|
||||
float GetCurrentMessageTime();
|
||||
|
||||
ConsoleColors GetColor() const { return Color_Current; }
|
||||
const NullConsoleWriter& SetColor(ConsoleColors color) const { return *this; }
|
||||
const NullConsoleWriter& ClearColor() const { return *this; }
|
||||
const NullConsoleWriter& SetIndent(int tabcount = 1) const { return *this; }
|
||||
// adds a standard console output
|
||||
bool IsConsoleOutputEnabled();
|
||||
void SetConsoleOutputLevel(LOGLEVEL level);
|
||||
|
||||
NullConsoleWriter Indent(int tabcount = 1) const { return NullConsoleWriter(); }
|
||||
// adds a debug console output
|
||||
bool IsDebugOutputAvailable();
|
||||
bool IsDebugOutputEnabled();
|
||||
void SetDebugOutputLevel(LOGLEVEL level);
|
||||
|
||||
bool FormatV(const char* fmt, va_list args) const { return false; }
|
||||
bool WriteLn(ConsoleColors color, const char* fmt, ...) const { return false; }
|
||||
bool WriteLn(const char* fmt, ...) const { return false; }
|
||||
bool Error(const char* fmt, ...) const { return false; }
|
||||
bool Warning(const char* fmt, ...) const { return false; }
|
||||
// adds a file output
|
||||
bool IsFileOutputEnabled();
|
||||
bool SetFileOutputLevel(LOGLEVEL level, std::string path);
|
||||
|
||||
// returns the log file, this is really dangerous to use if it changes...
|
||||
std::FILE* GetFileLogHandle();
|
||||
|
||||
// adds host output
|
||||
bool IsHostOutputEnabled();
|
||||
void SetHostOutputLevel(LOGLEVEL level, HostCallbackType callback);
|
||||
|
||||
// sets logging timestamps
|
||||
bool AreTimestampsEnabled();
|
||||
void SetTimestampsEnabled(bool enabled);
|
||||
|
||||
// Returns the current global filtering level.
|
||||
LOGLEVEL GetMaxLevel();
|
||||
|
||||
// writes a message to the log
|
||||
void Write(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
void Writef(LOGLEVEL level, ConsoleColors color, const char* format, ...);
|
||||
void Writev(LOGLEVEL level, ConsoleColors color, const char* format, va_list ap);
|
||||
void WriteFmtArgs(LOGLEVEL level, ConsoleColors color, fmt::string_view fmt, fmt::format_args args);
|
||||
|
||||
template <typename... T>
|
||||
__fi static void Write(LOGLEVEL level, ConsoleColors color, fmt::format_string<T...> fmt, T&&... args)
|
||||
{
|
||||
// Avoid arg packing if filtered.
|
||||
if (level <= GetMaxLevel())
|
||||
return WriteFmtArgs(level, color, fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
} // namespace Log
|
||||
|
||||
// Adapter classes to handle old code.
|
||||
template <LOGLEVEL level>
|
||||
struct ConsoleLogWriter
|
||||
{
|
||||
__fi static void Error(std::string_view str) { Log::Write(level, Color_StrongRed, str); }
|
||||
__fi static void Warning(std::string_view str) { Log::Write(level, Color_StrongOrange, str); }
|
||||
__fi static void WriteLn(std::string_view str) { Log::Write(level, Color_Default, str); }
|
||||
__fi static void WriteLn(ConsoleColors color, std::string_view str) { Log::Write(level, color, str); }
|
||||
__fi static void WriteLn() { Log::Write(level, Color_Default, std::string_view()); }
|
||||
__fi static void FormatV(const char* format, va_list ap) { Log::Writev(level, Color_Default, format, ap); }
|
||||
__fi static void FormatV(ConsoleColors color, const char* format, va_list ap) { Log::Writev(level, color, format, ap); }
|
||||
|
||||
#define MAKE_PRINTF_CONSOLE_WRITER(color) \
|
||||
do \
|
||||
{ \
|
||||
std::va_list ap; \
|
||||
va_start(ap, format); \
|
||||
Log::Writev(level, color, format, ap); \
|
||||
va_end(ap); \
|
||||
} while (0)
|
||||
|
||||
// clang-format off
|
||||
__fi static void Error(const char* format, ...) { MAKE_PRINTF_CONSOLE_WRITER(Color_StrongRed); }
|
||||
__fi static void Warning(const char* format, ...) { MAKE_PRINTF_CONSOLE_WRITER(Color_StrongOrange); }
|
||||
__fi static void WriteLn(const char* format, ...) { MAKE_PRINTF_CONSOLE_WRITER(Color_Default); }
|
||||
__fi static void WriteLn(ConsoleColors color, const char* format, ...) { MAKE_PRINTF_CONSOLE_WRITER(color); }
|
||||
// clang-format on
|
||||
|
||||
#undef MAKE_PRINTF_CONSOLE_WRITER
|
||||
|
||||
#define MAKE_FMT_CONSOLE_WRITER(color) do \
|
||||
{ \
|
||||
if (level <= Log::GetMaxLevel()) \
|
||||
Log::WriteFmtArgs(level, color, fmt, fmt::make_format_args(args...)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
// clang-format off
|
||||
template<typename... T> __fi static void ErrorFmt(fmt::format_string<T...> fmt, T&&... args) { MAKE_FMT_CONSOLE_WRITER(Color_StrongRed); }
|
||||
template<typename... T> __fi static void WarningFmt(fmt::format_string<T...> fmt, T&&... args) { MAKE_FMT_CONSOLE_WRITER(Color_StrongOrange); }
|
||||
template<typename... T> __fi static void WriteLnFmt(fmt::format_string<T...> fmt, T&&... args) { MAKE_FMT_CONSOLE_WRITER(Color_Default); }
|
||||
template<typename... T> __fi static void WriteLnFmt(ConsoleColors color, fmt::format_string<T...> fmt, T&&... args) { MAKE_FMT_CONSOLE_WRITER(color); }
|
||||
// clang-format on
|
||||
|
||||
#undef MAKE_FMT_CONSOLE_WRITER
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleIndentScope
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Provides a scoped indentation of the IConsoleWriter interface for the current thread.
|
||||
// Any console writes performed from this scope will be indented by the specified number
|
||||
// of tab characters.
|
||||
//
|
||||
// Scoped Object Notes: Like most scoped objects, this is intended to be used as a stack
|
||||
// or temporary object only. Using it in a situation where the object's lifespan out-lives
|
||||
// a scope will almost certainly result in unintended /undefined side effects.
|
||||
//
|
||||
class ConsoleIndentScope
|
||||
struct NullLogWriter
|
||||
{
|
||||
DeclareNoncopyableObject(ConsoleIndentScope);
|
||||
// clang-format off
|
||||
__fi static bool Error(std::string_view str) { return false; }
|
||||
__fi static bool Warning(std::string_view str) { return false; }
|
||||
__fi static bool WriteLn(std::string_view str) { return false; }
|
||||
__fi static bool WriteLn(ConsoleColors color, std::string_view str) { return false; }
|
||||
__fi static bool WriteLn() { return false; }
|
||||
|
||||
protected:
|
||||
int m_amount;
|
||||
bool m_IsScoped;
|
||||
__fi static bool Error(const char* format, ...) { return false; }
|
||||
__fi static bool Warning(const char* format, ...) { return false; }
|
||||
__fi static bool WriteLn(const char* format, ...) { return false; }
|
||||
__fi static bool WriteLn(ConsoleColors color, const char* format, ...) { return false; }
|
||||
|
||||
public:
|
||||
// Constructor: The specified number of tabs will be appended to the current indentation
|
||||
// setting. The tabs will be unrolled when the object leaves scope or is destroyed.
|
||||
ConsoleIndentScope(int tabs = 1);
|
||||
virtual ~ConsoleIndentScope();
|
||||
void EnterScope();
|
||||
void LeaveScope();
|
||||
template<typename... T> __fi static bool ErrorFmt(fmt::format_string<T...> fmt, T&&... args) { return false; }
|
||||
template<typename... T> __fi static bool WarningFmt(fmt::format_string<T...> fmt, T&&... args) { return false; }
|
||||
template<typename... T> __fi static bool WriteLnFmt(fmt::format_string<T...> fmt, T&&... args) { return false; }
|
||||
template<typename... T> __fi static bool WriteLnFmt(ConsoleColors color, fmt::format_string<T...> fmt, T&&... args) { return false; }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleColorScope
|
||||
// --------------------------------------------------------------------------------------
|
||||
class ConsoleColorScope
|
||||
{
|
||||
DeclareNoncopyableObject(ConsoleColorScope);
|
||||
extern ConsoleLogWriter<LOGLEVEL_INFO> Console;
|
||||
extern ConsoleLogWriter<LOGLEVEL_DEV> DevCon;
|
||||
|
||||
protected:
|
||||
ConsoleColors m_newcolor;
|
||||
ConsoleColors m_old_color;
|
||||
bool m_IsScoped;
|
||||
|
||||
public:
|
||||
ConsoleColorScope(ConsoleColors newcolor);
|
||||
virtual ~ConsoleColorScope();
|
||||
void EnterScope();
|
||||
void LeaveScope();
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// ConsoleAttrScope
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Applies both color and tab attributes in a single object constructor.
|
||||
//
|
||||
class ConsoleAttrScope
|
||||
{
|
||||
DeclareNoncopyableObject(ConsoleAttrScope);
|
||||
|
||||
protected:
|
||||
ConsoleColors m_old_color;
|
||||
int m_tabsize;
|
||||
|
||||
public:
|
||||
ConsoleAttrScope(ConsoleColors newcolor, int indent = 0);
|
||||
virtual ~ConsoleAttrScope();
|
||||
};
|
||||
|
||||
extern IConsoleWriter Console;
|
||||
|
||||
#if defined(__POSIX__)
|
||||
extern void Console_SetStdout(FILE* fp);
|
||||
#endif
|
||||
extern void Console_SetActiveHandler(const IConsoleWriter& writer, FILE* flushfp = NULL);
|
||||
|
||||
extern const IConsoleWriter ConsoleWriter_Null;
|
||||
extern const IConsoleWriter ConsoleWriter_Stdout;
|
||||
extern const IConsoleWriter ConsoleWriter_Assert;
|
||||
|
||||
extern NullConsoleWriter NullCon;
|
||||
|
||||
extern IConsoleWriter DevConWriter;
|
||||
extern bool DevConWriterEnabled;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
#define DevCon DevConWriter
|
||||
#else
|
||||
#define DevCon DevConWriterEnabled&& DevConWriter
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
extern IConsoleWriter DbgConWriter;
|
||||
#ifdef _DEBUG
|
||||
extern ConsoleLogWriter<LOGLEVEL_DEBUG> DbgConWriter;
|
||||
#define DbgCon DbgConWriter
|
||||
#else
|
||||
#define DbgCon 0 && NullCon
|
||||
extern NullLogWriter DbgConWriter;
|
||||
#define DbgCon 0 && DbgConWriter
|
||||
#endif
|
||||
|
||||
@@ -55,6 +55,11 @@ using r128 = __m128i;
|
||||
return _mm_set_epi64x(0, val);
|
||||
}
|
||||
|
||||
[[maybe_unused]] __fi static r128 r128_from_u32_dup(u32 val)
|
||||
{
|
||||
return _mm_set1_epi32(val);
|
||||
}
|
||||
|
||||
[[maybe_unused]] __fi static r128 r128_from_u32x4(u32 lo0, u32 lo1, u32 hi0, u32 hi1)
|
||||
{
|
||||
return _mm_setr_epi32(lo0, lo1, hi0, hi1);
|
||||
@@ -150,6 +155,11 @@ using r128 = uint32x4_t;
|
||||
return vreinterpretq_u32_u64(vcombine_u64(vcreate_u64(val), vcreate_u64(0)));
|
||||
}
|
||||
|
||||
[[maybe_unused]] __fi static r128 r128_from_u32_dup(u32 val)
|
||||
{
|
||||
return vdupq_n_u32(val);
|
||||
}
|
||||
|
||||
[[maybe_unused]] __fi static r128 r128_from_u32x4(u32 lo0, u32 lo1, u32 hi0, u32 hi1)
|
||||
{
|
||||
const u32 values[4] = {lo0, lo1, hi0, hi1};
|
||||
|
||||
@@ -59,10 +59,7 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
inline color_rgba()
|
||||
{
|
||||
static_assert(sizeof(*this) == 4, "sizeof(*this) != 4");
|
||||
}
|
||||
inline color_rgba() = default;
|
||||
|
||||
inline color_rgba(int y)
|
||||
{
|
||||
@@ -190,6 +187,8 @@ public:
|
||||
static color_rgba comp_max(const color_rgba& a, const color_rgba& b) { return color_rgba(std::max(a[0], b[0]), std::max(a[1], b[1]), std::max(a[2], b[2]), std::max(a[3], b[3])); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(color_rgba) == 4);
|
||||
|
||||
bool unpack_bc7(const void *pBlock, color_rgba *pPixels);
|
||||
|
||||
} // namespace bc7decomp
|
||||
|
||||
+10
-2
@@ -183,7 +183,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteV(const char* fmt, va_list list) const;
|
||||
bool WriteV(const char* fmt, va_list list) const
|
||||
{
|
||||
Console.FormatV(fmt, list);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WriteV(ConsoleColors color, const char* fmt, va_list list) const;
|
||||
bool WriteV(ConsoleColors color, const char* fmt, va_list list) const
|
||||
{
|
||||
Console.FormatV(color, fmt, list);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "common/Threading.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <process.h>
|
||||
#include <timeapi.h>
|
||||
|
||||
+39
-45
@@ -18,12 +18,15 @@ IF EXIST "%ProgramFiles%\Git\bin\git.exe" SET "GITPATH=%ProgramFiles%\Git\bin"
|
||||
IF EXIST "%ProgramW6432%\Git\bin\git.exe" SET "GITPATH=%ProgramW6432%\Git\bin"
|
||||
IF DEFINED GITPATH SET "PATH=%PATH%;%GITPATH%"
|
||||
|
||||
FOR /F "tokens=1-2" %%i IN ('"git show -s --format=%%%ci HEAD 2> NUL"') do (
|
||||
set REV3=%%i%%j
|
||||
)
|
||||
|
||||
FOR /F %%i IN ('"git describe 2> NUL"') do (
|
||||
set GIT_REV=%%i
|
||||
git describe --tags > NUL 2>NUL
|
||||
if !ERRORLEVEL! EQU 0 (
|
||||
FOR /F %%i IN ('"git describe --tags 2> NUL"') do (
|
||||
set GIT_REV=%%i
|
||||
)
|
||||
) else (
|
||||
FOR /F %%i IN ('"git rev-parse --short HEAD 2> NUL"') do (
|
||||
set GIT_REV=%%i
|
||||
)
|
||||
)
|
||||
|
||||
FOR /F "tokens=* USEBACKQ" %%i IN (`git tag --points-at HEAD`) DO (
|
||||
@@ -34,11 +37,11 @@ FOR /F "tokens=* USEBACKQ" %%i IN (`git rev-parse HEAD`) DO (
|
||||
set GIT_HASH=%%i
|
||||
)
|
||||
|
||||
set REV2=%REV3: =%
|
||||
set REV1=%REV2:-=%
|
||||
set REV=%REV1::=%
|
||||
FOR /F "tokens=* USEBACKQ" %%i IN (`git log -1 "--format=%%cd" "--date=local"`) DO (
|
||||
set GIT_DATE=%%i
|
||||
)
|
||||
|
||||
SET SIGNATURELINE=// H[%GIT_HASH%] T[%GIT_TAG%]
|
||||
SET SIGNATURELINE=// R[%GIT_REV%] H[%GIT_HASH%] T[%GIT_TAG%]
|
||||
SET /P EXISTINGLINE=<"%CD%\svnrev.h"
|
||||
|
||||
IF "%EXISTINGLINE%"=="%SIGNATURELINE%" (
|
||||
@@ -48,45 +51,36 @@ IF "%EXISTINGLINE%"=="%SIGNATURELINE%" (
|
||||
ECHO Updating "%CD%\svnrev.h"...
|
||||
echo %SIGNATURELINE%> "%CD%\svnrev.h"
|
||||
|
||||
git show -s > NUL 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Automatic version detection unavailable.
|
||||
echo If you want to have the version string print correctly,
|
||||
echo make sure your Git.exe is in the default installation directory,
|
||||
echo or in your PATH.
|
||||
echo You can safely ignore this message - a dummy string will be printed.
|
||||
echo #define GIT_HASH "%GIT_HASH%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG "%GIT_TAG%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_DATE "%GIT_DATE%" >> "%CD%\svnrev.h"
|
||||
|
||||
echo #define SVN_REV_UNKNOWN >> "%CD%\svnrev.h"
|
||||
echo #define SVN_REV 0ll >> "%CD%\svnrev.h"
|
||||
echo #define GIT_REV "" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_HASH "" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG "" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAGGED_COMMIT 0 >> "%CD%\svnrev.h"
|
||||
echo %GIT_TAG%|FINDSTR /R "^v[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$" > NUL
|
||||
if !ERRORLEVEL! EQU 0 (
|
||||
echo #define GIT_REV "%GIT_TAG%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAGGED_COMMIT 1 >> "%CD%\svnrev.h"
|
||||
FOR /F "tokens=1,2,3 delims=v." %%a in ("%GIT_TAG%") DO (
|
||||
echo #define GIT_TAG_HI %%a >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_MID %%b >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_LO %%c >> "%CD%\svnrev.h"
|
||||
)
|
||||
) else (
|
||||
:: Support New Tagged Release Model
|
||||
if [%GIT_TAG%] NEQ [] (
|
||||
echo Detected that the current commit is tagged, using that!
|
||||
echo #define SVN_REV %REV%ll >> "%CD%\svnrev.h"
|
||||
echo #define GIT_REV "" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_HASH "%GIT_HASH%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG "%GIT_TAG%" >> "%CD%\svnrev.h"
|
||||
|
||||
echo %GIT_TAG%|FINDSTR /R "^v[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$" > NUL
|
||||
if !ERRORLEVEL! EQU 0 (
|
||||
FOR /F "tokens=1,2,3 delims=v." %%a in ("%GIT_TAG%") DO (
|
||||
echo #define GIT_TAG_HI %%a >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_MID %%b >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_LO %%c >> "%CD%\svnrev.h"
|
||||
)
|
||||
:: Local branches
|
||||
echo #define GIT_REV "%GIT_REV%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAGGED_COMMIT 0 >> "%CD%\svnrev.h"
|
||||
echo %GIT_REV%|FINDSTR /R "^v[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]-*" > NUL
|
||||
if !ERRORLEVEL! EQU 0 (
|
||||
FOR /F "tokens=1,2,3 delims=v." %%a in ("%GIT_REV%") DO (
|
||||
echo #define GIT_TAG_HI %%a >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_MID %%b >> "%CD%\svnrev.h"
|
||||
FOR /F "tokens=1 delims=-" %%d in ("%%c%") DO (
|
||||
echo #define GIT_TAG_LO %%d >> "%CD%\svnrev.h"
|
||||
)
|
||||
)
|
||||
|
||||
echo #define GIT_TAGGED_COMMIT 1 >> "%CD%\svnrev.h"
|
||||
) else (
|
||||
echo #define SVN_REV %REV%ll >> "%CD%\svnrev.h"
|
||||
echo #define GIT_REV "%GIT_REV%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_HASH "%GIT_HASH%" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG "" >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAGGED_COMMIT 0 >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_HI 0 >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_MID 0 >> "%CD%\svnrev.h"
|
||||
echo #define GIT_TAG_LO 0 >> "%CD%\svnrev.h"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
pull_request_title: "translations: Syncing Crowdin translations"
|
||||
commit_message: "[ci skip]"
|
||||
pull_request_title: 'translations: Syncing Crowdin translations'
|
||||
commit_message: '[ci skip]'
|
||||
files:
|
||||
- source: pcsx2-qt/Translations/pcsx2-qt_en.ts
|
||||
translation: '/pcsx2-qt/Translations/pcsx2-qt_%locale%.ts'
|
||||
translation: /pcsx2-qt/Translations/pcsx2-qt_%locale%.ts
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "pcsx2/INISettingsInterface.h"
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/SIO/Pad/Pad.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
@@ -95,6 +94,8 @@ bool GSRunner::InitializeConfig()
|
||||
if (!VMManager::PerformEarlyHardwareChecks(&error))
|
||||
return false;
|
||||
|
||||
ImGuiManager::SetFontPathAndRange(Path::Combine(EmuFolders::Resources, "fonts" FS_OSPATH_SEPARATOR_STR "Roboto-Regular.ttf"), {});
|
||||
|
||||
// don't provide an ini path, or bother loading. we'll store everything in memory.
|
||||
MemorySettingsInterface& si = s_settings_interface;
|
||||
Host::Internal::SetBaseSettingsLayer(&si);
|
||||
@@ -440,7 +441,7 @@ void GSRunner::InitializeConsole()
|
||||
const char* var = std::getenv("PCSX2_NOCONSOLE");
|
||||
s_no_console = (var && StringUtil::FromChars<bool>(var).value_or(false));
|
||||
if (!s_no_console)
|
||||
LogSink::InitializeEarlyConsole();
|
||||
Log::SetConsoleOutputLevel(LOGLEVEL_DEBUG);
|
||||
}
|
||||
|
||||
bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params)
|
||||
@@ -566,7 +567,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
{
|
||||
// disable timestamps, since we want to be able to diff the logs
|
||||
Console.WriteLn("Logging to %s...", logfile);
|
||||
LogSink::SetFileLogPath(logfile);
|
||||
VMManager::Internal::SetFileLogPath(logfile);
|
||||
s_settings_interface.SetBoolValue("Logging", "EnableFileLogging", true);
|
||||
s_settings_interface.SetBoolValue("Logging", "EnableTimestamps", false);
|
||||
}
|
||||
@@ -696,7 +697,6 @@ int main(int argc, char* argv[])
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
GSRunner::DestroyPlatformWindow();
|
||||
LogSink::CloseFileLog();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "pcsx2/SysForwardDefs.h"
|
||||
#include "pcsx2/SupportURLs.h"
|
||||
|
||||
#include "AboutDialog.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/SmallString.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QString>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QTextBrowser>
|
||||
|
||||
static QString GetDocFileUrl(std::string_view name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Windows uses the docs directory in bin.
|
||||
const std::string path = Path::Combine(EmuFolders::AppRoot,
|
||||
TinyString::from_fmt("docs" FS_OSPATH_SEPARATOR_STR "{}", name));
|
||||
#else
|
||||
// Linux/Mac has this in the Resources directory.
|
||||
const std::string path = Path::Combine(EmuFolders::Resources,
|
||||
TinyString::from_fmt("docs" FS_OSPATH_SEPARATOR_STR "{}", name));
|
||||
#endif
|
||||
return QUrl::fromLocalFile(QString::fromStdString(path)).toString();
|
||||
}
|
||||
|
||||
AboutDialog::AboutDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
@@ -21,9 +45,8 @@ AboutDialog::AboutDialog(QWidget* parent)
|
||||
m_ui.scmversion->setText(QtHost::GetAppNameAndVersion());
|
||||
|
||||
m_ui.links->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
m_ui.links->setOpenExternalLinks(true);
|
||||
m_ui.links->setText(QStringLiteral(
|
||||
R"(<a href="%1">%2</a> | <a href="%3">%4</a> | <a href="%5">%6</a> | <a href="%7">%8</a>)")
|
||||
R"(<a href="%1">%2</a> | <a href="%3">%4</a> | <a href="%5">%6</a> | <a href="%7">%8</a> | <a href="%9">%10</a>)")
|
||||
.arg(getWebsiteUrl())
|
||||
.arg(tr("Website"))
|
||||
.arg(getSupportForumsUrl())
|
||||
@@ -31,8 +54,11 @@ AboutDialog::AboutDialog(QWidget* parent)
|
||||
.arg(getGitHubRepositoryUrl())
|
||||
.arg(tr("GitHub Repository"))
|
||||
.arg(getLicenseUrl())
|
||||
.arg(tr("License")));
|
||||
.arg(tr("License"))
|
||||
.arg(getThirdPartyLicensesUrl())
|
||||
.arg(tr("Third-Party Licenses")));
|
||||
|
||||
connect(m_ui.links, &QLabel::linkActivated, this, &AboutDialog::linksLinkActivated);
|
||||
connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
|
||||
}
|
||||
|
||||
@@ -55,10 +81,60 @@ QString AboutDialog::getGitHubRepositoryUrl()
|
||||
|
||||
QString AboutDialog::getLicenseUrl()
|
||||
{
|
||||
return QString::fromUtf8(PCSX2_LICENSE_URL);
|
||||
return GetDocFileUrl("GPL.html");
|
||||
}
|
||||
|
||||
QString AboutDialog::getThirdPartyLicensesUrl()
|
||||
{
|
||||
return GetDocFileUrl("ThirdPartyLicenses.html");
|
||||
}
|
||||
|
||||
QString AboutDialog::getDiscordServerUrl()
|
||||
{
|
||||
return QString::fromUtf8(PCSX2_DISCORD_URL);
|
||||
}
|
||||
|
||||
void AboutDialog::linksLinkActivated(const QString& link)
|
||||
{
|
||||
const QUrl url(link);
|
||||
if (!url.isValid())
|
||||
return;
|
||||
|
||||
if (!url.isLocalFile())
|
||||
{
|
||||
QDesktopServices::openUrl(url);
|
||||
return;
|
||||
}
|
||||
|
||||
showHTMLDialog(this, tr("View Document"), url.toLocalFile());
|
||||
}
|
||||
|
||||
void AboutDialog::showHTMLDialog(QWidget* parent, const QString& title, const QString& path)
|
||||
{
|
||||
QDialog dialog(parent);
|
||||
dialog.setMinimumSize(700, 400);
|
||||
dialog.setWindowTitle(title);
|
||||
dialog.setWindowIcon(QtHost::GetAppIcon());
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(&dialog);
|
||||
|
||||
QTextBrowser* tb = new QTextBrowser(&dialog);
|
||||
tb->setAcceptRichText(true);
|
||||
tb->setReadOnly(true);
|
||||
tb->setOpenExternalLinks(true);
|
||||
|
||||
QFile file(path);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if (const QByteArray data = file.readAll(); !data.isEmpty())
|
||||
tb->setText(QString::fromUtf8(data));
|
||||
else
|
||||
tb->setText(tr("File not found: %1").arg(path));
|
||||
|
||||
layout->addWidget(tb, 1);
|
||||
|
||||
QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, &dialog);
|
||||
connect(bb->button(QDialogButtonBox::Close), &QPushButton::clicked, &dialog, &QDialog::done);
|
||||
layout->addWidget(bb, 0);
|
||||
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,14 @@ public:
|
||||
static QString getSupportForumsUrl();
|
||||
static QString getGitHubRepositoryUrl();
|
||||
static QString getLicenseUrl();
|
||||
static QString getThirdPartyLicensesUrl();
|
||||
static QString getDiscordServerUrl();
|
||||
|
||||
static void showHTMLDialog(QWidget* parent, const QString& title, const QString& url);
|
||||
|
||||
private Q_SLOTS:
|
||||
void linksLinkActivated(const QString& link);
|
||||
|
||||
private:
|
||||
Ui::AboutDialog m_ui;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "AutoUpdaterDialog.h"
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/SysForwardDefs.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
#include "updater/UpdaterExtractor.h"
|
||||
@@ -16,8 +15,10 @@
|
||||
#include "common/Assertions.h"
|
||||
#include "common/CocoaTools.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/Error.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/HTTPDownloader.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "cpuinfo.h"
|
||||
@@ -38,12 +39,17 @@
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QProgressDialog>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
// Interval at which HTTP requests are polled.
|
||||
static constexpr u32 HTTP_POLL_INTERVAL = 10;
|
||||
|
||||
// Logic to detect whether we can use the auto updater.
|
||||
// We use tagged commit, because this gets set on nightly builds.
|
||||
#if (defined(_WIN32) || defined(__linux__) || defined(__APPLE__)) && defined(GIT_TAG_LO)
|
||||
#if (defined(_WIN32) || defined(__linux__) || defined(__APPLE__)) && GIT_TAGGED_COMMIT
|
||||
|
||||
#define AUTO_UPDATER_SUPPORTED 1
|
||||
|
||||
@@ -73,8 +79,13 @@ static constexpr u32 HTTP_POLL_INTERVAL = 10;
|
||||
// Available release channels.
|
||||
static const char* UPDATE_TAGS[] = {"stable", "nightly"};
|
||||
|
||||
// Bit annoying, because PCSX2_isReleaseVersion is a bool, but whatever.
|
||||
#define THIS_RELEASE_TAG (PCSX2_isReleaseVersion ? "stable" : "nightly")
|
||||
// TODO: Make manual releases create this file, and make it contain `#define DEFAULT_UPDATER_CHANNEL "stable"`.
|
||||
#if __has_include("DefaultUpdaterChannel.h")
|
||||
#include "DefaultUpdaterChannel.h"
|
||||
#endif
|
||||
#ifndef DEFAULT_UPDATER_CHANNEL
|
||||
#define DEFAULT_UPDATER_CHANNEL "nightly"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -129,7 +140,7 @@ QStringList AutoUpdaterDialog::getTagList()
|
||||
std::string AutoUpdaterDialog::getDefaultTag()
|
||||
{
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
return THIS_RELEASE_TAG;
|
||||
return DEFAULT_UPDATER_CHANNEL;
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
@@ -142,15 +153,13 @@ QString AutoUpdaterDialog::getCurrentVersion()
|
||||
|
||||
QString AutoUpdaterDialog::getCurrentVersionDate()
|
||||
{
|
||||
// 20220403235450ll
|
||||
const QDateTime current_build_date(QDateTime::fromString(QStringLiteral("%1").arg(SVN_REV), "yyyyMMddhhmmss"));
|
||||
return current_build_date.toString();
|
||||
return QStringLiteral(GIT_DATE);
|
||||
}
|
||||
|
||||
QString AutoUpdaterDialog::getCurrentUpdateTag() const
|
||||
{
|
||||
#ifdef AUTO_UPDATER_SUPPORTED
|
||||
return QString::fromStdString(Host::GetBaseStringSettingValue("AutoUpdater", "UpdateTag", THIS_RELEASE_TAG));
|
||||
return QString::fromStdString(Host::GetBaseStringSettingValue("AutoUpdater", "UpdateTag", DEFAULT_UPDATER_CHANNEL));
|
||||
#else
|
||||
return QString();
|
||||
#endif
|
||||
@@ -566,70 +575,74 @@ void AutoUpdaterDialog::remindMeLaterClicked()
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
bool AutoUpdaterDialog::doesUpdaterNeedElevation(const std::string& application_dir) const
|
||||
{
|
||||
// Try to create a dummy text file in the PCSX2 updater directory. If it fails, we probably won't have write permission.
|
||||
const std::string dummy_path = Path::Combine(application_dir, "update.txt");
|
||||
auto fp = FileSystem::OpenManagedCFile(dummy_path.c_str(), "wb");
|
||||
if (!fp)
|
||||
return true;
|
||||
|
||||
fp.reset();
|
||||
FileSystem::DeleteFilePath(dummy_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AutoUpdaterDialog::processUpdate(const std::vector<u8>& data, QProgressDialog&)
|
||||
{
|
||||
const QString update_directory = QCoreApplication::applicationDirPath();
|
||||
const QString update_zip_path = QStringLiteral("%1" FS_OSPATH_SEPARATOR_STR "%2").arg(update_directory).arg(UPDATER_ARCHIVE_NAME);
|
||||
const QString updater_path = QStringLiteral("%1" FS_OSPATH_SEPARATOR_STR "%2").arg(update_directory).arg(UPDATER_EXECUTABLE);
|
||||
const std::string& application_dir = EmuFolders::AppRoot;
|
||||
const std::string update_zip_path = Path::Combine(EmuFolders::DataRoot, UPDATER_ARCHIVE_NAME);
|
||||
const std::string updater_path = Path::Combine(EmuFolders::DataRoot, UPDATER_EXECUTABLE);
|
||||
|
||||
Q_ASSERT(!update_zip_path.isEmpty() && !updater_path.isEmpty() && !update_directory.isEmpty());
|
||||
if ((QFile::exists(update_zip_path) && !QFile::remove(update_zip_path)) ||
|
||||
(QFile::exists(updater_path) && !QFile::remove(updater_path)))
|
||||
if ((FileSystem::FileExists(update_zip_path.c_str()) && !FileSystem::DeleteFilePath(update_zip_path.c_str())))
|
||||
{
|
||||
reportError("Removing existing update zip/updater failed");
|
||||
reportError("Removing existing update zip failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FileSystem::WriteBinaryFile(update_zip_path.c_str(), data.data(), data.size()))
|
||||
{
|
||||
QFile update_zip_file(update_zip_path);
|
||||
if (!update_zip_file.open(QIODevice::WriteOnly) ||
|
||||
update_zip_file.write(reinterpret_cast<const char*>(data.data()), static_cast<qint64>(data.size())) != static_cast<qint64>(data.size()))
|
||||
{
|
||||
reportError("Writing update zip to '%s' failed", update_zip_path.toUtf8().constData());
|
||||
return false;
|
||||
}
|
||||
update_zip_file.close();
|
||||
reportError("Writing update zip to '%s' failed", update_zip_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string updater_extract_error;
|
||||
if (!ExtractUpdater(update_zip_path.toUtf8().constData(), updater_path.toUtf8().constData(), &updater_extract_error))
|
||||
if (!ExtractUpdater(update_zip_path.c_str(), updater_path.c_str(), &updater_extract_error))
|
||||
{
|
||||
reportError("Extracting updater failed: %s", updater_extract_error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!doUpdate(update_zip_path, updater_path, update_directory))
|
||||
{
|
||||
reportError("Launching updater failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return doUpdate(application_dir, update_zip_path, updater_path);
|
||||
}
|
||||
|
||||
bool AutoUpdaterDialog::doUpdate(const QString& zip_path, const QString& updater_path, const QString& destination_path)
|
||||
bool AutoUpdaterDialog::doUpdate(const std::string& application_dir, const std::string& zip_path, const std::string& updater_path)
|
||||
{
|
||||
const QString program_path = QCoreApplication::applicationFilePath();
|
||||
if (program_path.isEmpty())
|
||||
const std::string program_path = QDir::toNativeSeparators(QCoreApplication::applicationFilePath()).toStdString();
|
||||
if (program_path.empty())
|
||||
{
|
||||
reportError("Failed to get current application path");
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList arguments;
|
||||
arguments << QString::number(QCoreApplication::applicationPid());
|
||||
arguments << destination_path;
|
||||
arguments << zip_path;
|
||||
arguments << program_path;
|
||||
const std::wstring wupdater_path = StringUtil::UTF8StringToWideString(updater_path);
|
||||
const std::wstring wapplication_dir = StringUtil::UTF8StringToWideString(application_dir);
|
||||
const std::wstring arguments = StringUtil::UTF8StringToWideString(fmt::format("{} \"{}\" \"{}\" \"{}\"",
|
||||
QCoreApplication::applicationPid(), application_dir, zip_path, program_path));
|
||||
|
||||
// this will leak, but not sure how else to handle it...
|
||||
QProcess* updater_process = new QProcess();
|
||||
updater_process->setProgram(updater_path);
|
||||
updater_process->setArguments(arguments);
|
||||
updater_process->start(QIODevice::NotOpen);
|
||||
if (!updater_process->waitForStarted())
|
||||
const bool needs_elevation = doesUpdaterNeedElevation(application_dir);
|
||||
|
||||
SHELLEXECUTEINFOW sei = {};
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.lpVerb = needs_elevation ? L"runas" : nullptr; // needed to trigger elevation
|
||||
sei.lpFile = wupdater_path.c_str();
|
||||
sei.lpParameters = arguments.c_str();
|
||||
sei.lpDirectory = wapplication_dir.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
reportError("Failed to start updater");
|
||||
reportError("Failed to start %s: %s", needs_elevation ? "elevated updater" : "updater",
|
||||
Error::CreateWin32(GetLastError()).GetDescription().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -638,7 +651,19 @@ bool AutoUpdaterDialog::doUpdate(const QString& zip_path, const QString& updater
|
||||
|
||||
void AutoUpdaterDialog::cleanupAfterUpdate()
|
||||
{
|
||||
// Nothing to do on Windows for now, the updater stub cleans everything up.
|
||||
// If we weren't portable, then updater executable gets left in the application directory.
|
||||
if (EmuFolders::AppRoot == EmuFolders::DataRoot)
|
||||
return;
|
||||
|
||||
const std::string updater_path = Path::Combine(EmuFolders::DataRoot, UPDATER_EXECUTABLE);
|
||||
if (!FileSystem::FileExists(updater_path.c_str()))
|
||||
return;
|
||||
|
||||
if (!FileSystem::DeleteFilePath(updater_path.c_str()))
|
||||
{
|
||||
QMessageBox::critical(nullptr, tr("Updater Error"), tr("Failed to remove updater exe after update."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
@@ -60,7 +60,8 @@ private:
|
||||
|
||||
bool processUpdate(const std::vector<u8>& data, QProgressDialog& progress);
|
||||
#if defined(_WIN32)
|
||||
bool doUpdate(const QString& zip_path, const QString& updater_path, const QString& destination_path);
|
||||
bool doesUpdaterNeedElevation(const std::string& application_dir) const;
|
||||
bool doUpdate(const std::string& application_dir, const std::string& zip_path, const std::string& updater_path);
|
||||
#endif
|
||||
|
||||
Ui::AutoUpdaterDialog m_ui;
|
||||
|
||||
@@ -21,6 +21,8 @@ target_sources(pcsx2-qt PRIVATE
|
||||
DisplayWidget.cpp
|
||||
DisplayWidget.h
|
||||
EarlyHardwareCheck.cpp
|
||||
LogWindow.cpp
|
||||
LogWindow.h
|
||||
MainWindow.cpp
|
||||
MainWindow.h
|
||||
MainWindow.ui
|
||||
@@ -64,6 +66,7 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Settings/ControllerBindingWidget.ui
|
||||
Settings/ControllerBindingWidget_DualShock2.ui
|
||||
Settings/ControllerBindingWidget_Guitar.ui
|
||||
Settings/ControllerBindingWidget_Popn.ui
|
||||
Settings/ControllerBindingWidgets.cpp
|
||||
Settings/ControllerBindingWidgets.h
|
||||
Settings/ControllerLEDSettingsDialog.ui
|
||||
@@ -167,6 +170,8 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Debugger/Models/ThreadModel.h
|
||||
Debugger/Models/StackModel.cpp
|
||||
Debugger/Models/StackModel.h
|
||||
Debugger/Models/SavedAddressesModel.cpp
|
||||
Debugger/Models/SavedAddressesModel.h
|
||||
Tools/InputRecording/NewInputRecordingDlg.cpp
|
||||
Tools/InputRecording/NewInputRecordingDlg.h
|
||||
Tools/InputRecording/NewInputRecordingDlg.ui
|
||||
|
||||
+205
-32
@@ -7,6 +7,7 @@
|
||||
#include "BreakpointDialog.h"
|
||||
#include "Models/BreakpointModel.h"
|
||||
#include "Models/ThreadModel.h"
|
||||
#include "Models/SavedAddressesModel.h"
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
@@ -39,6 +40,7 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
||||
, m_bpModel(cpu)
|
||||
, m_threadModel(cpu)
|
||||
, m_stackModel(cpu)
|
||||
, m_savedAddressesModel(cpu)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
@@ -46,6 +48,7 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
||||
|
||||
connect(m_ui.registerWidget, &RegisterWidget::gotoInDisasm, m_ui.disassemblyWidget, &DisassemblyWidget::gotoAddress);
|
||||
connect(m_ui.memoryviewWidget, &MemoryViewWidget::gotoInDisasm, m_ui.disassemblyWidget, &DisassemblyWidget::gotoAddress);
|
||||
connect(m_ui.memoryviewWidget, &MemoryViewWidget::addToSavedAddresses, this, &CpuWidget::addAddressToSavedAddressesList);
|
||||
|
||||
connect(m_ui.registerWidget, &RegisterWidget::gotoInMemory, m_ui.memoryviewWidget, &MemoryViewWidget::gotoAddress);
|
||||
connect(m_ui.disassemblyWidget, &DisassemblyWidget::gotoInMemory, m_ui.memoryviewWidget, &MemoryViewWidget::gotoAddress);
|
||||
@@ -99,7 +102,11 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
||||
m_ui.listSearchResults->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_ui.btnSearch, &QPushButton::clicked, this, &CpuWidget::onSearchButtonClicked);
|
||||
connect(m_ui.btnFilterSearch, &QPushButton::clicked, this, &CpuWidget::onSearchButtonClicked);
|
||||
connect(m_ui.listSearchResults, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item) { m_ui.memoryviewWidget->gotoAddress(item->text().toUInt(nullptr, 16)); });
|
||||
connect(m_ui.listSearchResults, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item)
|
||||
{
|
||||
m_ui.tabWidget->setCurrentWidget(m_ui.tab_memory);
|
||||
m_ui.memoryviewWidget->gotoAddress(item->text().toUInt(nullptr, 16));
|
||||
});
|
||||
connect(m_ui.listSearchResults->verticalScrollBar(), &QScrollBar::valueChanged, this, &CpuWidget::onSearchResultsListScroll);
|
||||
connect(m_ui.listSearchResults, &QListView::customContextMenuRequested, this, &CpuWidget::onListSearchResultsContextMenu);
|
||||
connect(m_ui.cmbSearchType, &QComboBox::currentIndexChanged, [this](int i) {
|
||||
@@ -127,6 +134,18 @@ CpuWidget::CpuWidget(QWidget* parent, DebugInterface& cpu)
|
||||
m_resultsLoadTimer.setInterval(100);
|
||||
m_resultsLoadTimer.setSingleShot(true);
|
||||
connect(&m_resultsLoadTimer, &QTimer::timeout, this, &CpuWidget::loadSearchResults);
|
||||
|
||||
m_ui.savedAddressesList->setModel(&m_savedAddressesModel);
|
||||
m_ui.savedAddressesList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_ui.savedAddressesList, &QTableView::customContextMenuRequested, this, &CpuWidget::onSavedAddressesListContextMenu);
|
||||
for (std::size_t i = 0; auto mode : SavedAddressesModel::HeaderResizeModes)
|
||||
{
|
||||
m_ui.savedAddressesList->horizontalHeader()->setSectionResizeMode(i++, mode);
|
||||
}
|
||||
QTableView* savedAddressesTableView = m_ui.savedAddressesList;
|
||||
connect(m_ui.savedAddressesList->model(), &QAbstractItemModel::dataChanged, [savedAddressesTableView](const QModelIndex& topLeft) {
|
||||
savedAddressesTableView->resizeColumnToContents(topLeft.column());
|
||||
});
|
||||
}
|
||||
|
||||
CpuWidget::~CpuWidget() = default;
|
||||
@@ -396,6 +415,7 @@ void CpuWidget::contextBPListPasteCSV()
|
||||
QString matchedValue = match.captured(0);
|
||||
fields << matchedValue.mid(1, matchedValue.length() - 2);
|
||||
}
|
||||
|
||||
if (fields.size() != BreakpointModel::BreakpointColumns::COLUMN_COUNT)
|
||||
{
|
||||
Console.WriteLn("Debugger CSV Import: Invalid number of columns, skipping");
|
||||
@@ -403,7 +423,7 @@ void CpuWidget::contextBPListPasteCSV()
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int type = fields[BreakpointModel::BreakpointColumns::TYPE].toUInt(&ok);
|
||||
const int type = fields[BreakpointModel::BreakpointColumns::TYPE].toUInt(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
Console.WriteLn("Debugger CSV Import: Failed to parse type '%s', skipping", fields[BreakpointModel::BreakpointColumns::TYPE].toUtf8().constData());
|
||||
@@ -477,7 +497,7 @@ void CpuWidget::contextBPListPasteCSV()
|
||||
}
|
||||
|
||||
// Result
|
||||
int result = fields [BreakpointModel::BreakpointColumns::ENABLED].toUInt(&ok);
|
||||
const int result = fields [BreakpointModel::BreakpointColumns::ENABLED].toUInt(&ok);
|
||||
if (!ok)
|
||||
{
|
||||
Console.WriteLn("Debugger CSV Import: Failed to parse result flag '%s', skipping", fields [BreakpointModel::BreakpointColumns::ENABLED].toUtf8().constData());
|
||||
@@ -490,13 +510,135 @@ void CpuWidget::contextBPListPasteCSV()
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWidget::onSavedAddressesListContextMenu(QPoint pos)
|
||||
{
|
||||
QMenu* contextMenu = new QMenu("Saved Addresses List Context Menu", m_ui.savedAddressesList);
|
||||
|
||||
QAction* newAction = new QAction(tr("New"), m_ui.savedAddressesList);
|
||||
connect(newAction, &QAction::triggered, this, &CpuWidget::contextSavedAddressesListNew);
|
||||
contextMenu->addAction(newAction);
|
||||
|
||||
const QModelIndex indexAtPos = m_ui.savedAddressesList->indexAt(pos);
|
||||
const bool isIndexValid = indexAtPos.isValid();
|
||||
|
||||
if (isIndexValid)
|
||||
{
|
||||
if (m_cpu.isAlive())
|
||||
{
|
||||
QAction* goToAddressMemViewAction = new QAction(tr("Go to in Memory View"), m_ui.savedAddressesList);
|
||||
connect(goToAddressMemViewAction, &QAction::triggered, this, [this, indexAtPos]() {
|
||||
const QModelIndex rowAddressIndex = m_ui.savedAddressesList->model()->index(indexAtPos.row(), 0, QModelIndex());
|
||||
m_ui.memoryviewWidget->gotoAddress(m_ui.savedAddressesList->model()->data(rowAddressIndex, Qt::UserRole).toUInt());
|
||||
m_ui.tabWidget->setCurrentWidget(m_ui.tab_memory);
|
||||
});
|
||||
contextMenu->addAction(goToAddressMemViewAction);
|
||||
|
||||
QAction* goToAddressDisassemblyAction = new QAction(tr("Go to in Disassembly"), m_ui.savedAddressesList);
|
||||
connect(goToAddressDisassemblyAction, &QAction::triggered, this, [this, indexAtPos]() {
|
||||
const QModelIndex rowAddressIndex = m_ui.savedAddressesList->model()->index(indexAtPos.row(), 0, QModelIndex());
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.savedAddressesList->model()->data(rowAddressIndex, Qt::UserRole).toUInt());
|
||||
});
|
||||
contextMenu->addAction(goToAddressDisassemblyAction);
|
||||
}
|
||||
|
||||
QAction* copyAction = new QAction(indexAtPos.column() == 0 ? tr("Copy Address") : tr("Copy Text"), m_ui.savedAddressesList);
|
||||
connect(copyAction, &QAction::triggered, [this, indexAtPos]() {
|
||||
QGuiApplication::clipboard()->setText(m_ui.savedAddressesList->model()->data(indexAtPos, Qt::DisplayRole).toString());
|
||||
});
|
||||
contextMenu->addAction(copyAction);
|
||||
}
|
||||
|
||||
if (m_ui.savedAddressesList->model()->rowCount() > 0)
|
||||
{
|
||||
QAction* actionExportCSV = new QAction(tr("Copy all as CSV"), m_ui.savedAddressesList);
|
||||
connect(actionExportCSV, &QAction::triggered, [this]() {
|
||||
QGuiApplication::clipboard()->setText(QtUtils::AbstractItemModelToCSV(m_ui.savedAddressesList->model(), Qt::DisplayRole, true));
|
||||
});
|
||||
contextMenu->addAction(actionExportCSV);
|
||||
}
|
||||
|
||||
QAction* actionImportCSV = new QAction(tr("Paste from CSV"), m_ui.savedAddressesList);
|
||||
connect(actionImportCSV, &QAction::triggered, this, &CpuWidget::contextSavedAddressesListPasteCSV);
|
||||
contextMenu->addAction(actionImportCSV);
|
||||
|
||||
contextMenu->popup(m_ui.savedAddressesList->viewport()->mapToGlobal(pos));
|
||||
|
||||
if (isIndexValid)
|
||||
{
|
||||
QAction* deleteAction = new QAction(tr("Delete"), m_ui.savedAddressesList);
|
||||
connect(deleteAction, &QAction::triggered, this, [this, indexAtPos]() {
|
||||
m_ui.savedAddressesList->model()->removeRows(indexAtPos.row(), 1);
|
||||
});
|
||||
contextMenu->addAction(deleteAction);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWidget::contextSavedAddressesListPasteCSV()
|
||||
{
|
||||
QString csv = QGuiApplication::clipboard()->text();
|
||||
// Skip header
|
||||
csv = csv.mid(csv.indexOf('\n') + 1);
|
||||
|
||||
for (const QString& line : csv.split('\n'))
|
||||
{
|
||||
QStringList fields;
|
||||
// In order to handle text with commas in them we must wrap values in quotes to mark
|
||||
// where a value starts and end so that text commas aren't identified as delimiters.
|
||||
// So matches each quote pair, parse it out, and removes the quotes to get the value.
|
||||
QRegularExpression eachQuotePair(R"("([^"]|\\.)*")");
|
||||
QRegularExpressionMatchIterator it = eachQuotePair.globalMatch(line);
|
||||
while (it.hasNext())
|
||||
{
|
||||
QRegularExpressionMatch match = it.next();
|
||||
QString matchedValue = match.captured(0);
|
||||
fields << matchedValue.mid(1, matchedValue.length() - 2);
|
||||
}
|
||||
|
||||
if (fields.size() != SavedAddressesModel::HeaderColumns::COLUMN_COUNT)
|
||||
{
|
||||
Console.WriteLn("Debugger CSV Import: Invalid number of columns, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
const u32 address = fields[SavedAddressesModel::HeaderColumns::ADDRESS].toUInt(&ok, 16);
|
||||
if (!ok)
|
||||
{
|
||||
Console.WriteLn("Debugger CSV Import: Failed to parse address '%s', skipping", fields[SavedAddressesModel::HeaderColumns::ADDRESS].toUtf8().constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString label = fields[SavedAddressesModel::HeaderColumns::LABEL];
|
||||
const QString description = fields[SavedAddressesModel::HeaderColumns::DESCRIPTION];
|
||||
const SavedAddressesModel::SavedAddress importedAddress = {address, label, description};
|
||||
m_savedAddressesModel.addRow(importedAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWidget::contextSavedAddressesListNew()
|
||||
{
|
||||
qobject_cast<SavedAddressesModel*>(m_ui.savedAddressesList->model())->addRow();
|
||||
const u32 rowCount = m_ui.savedAddressesList->model()->rowCount();
|
||||
m_ui.savedAddressesList->edit(m_ui.savedAddressesList->model()->index(rowCount - 1, 0));
|
||||
}
|
||||
|
||||
void CpuWidget::addAddressToSavedAddressesList(u32 address)
|
||||
{
|
||||
qobject_cast<SavedAddressesModel*>(m_ui.savedAddressesList->model())->addRow();
|
||||
const u32 rowCount = m_ui.savedAddressesList->model()->rowCount();
|
||||
const QModelIndex addressIndex = m_ui.savedAddressesList->model()->index(rowCount - 1, 0);
|
||||
m_ui.tabWidget->setCurrentWidget(m_ui.tab_savedaddresses);
|
||||
m_ui.savedAddressesList->model()->setData(addressIndex, address, Qt::UserRole);
|
||||
m_ui.savedAddressesList->edit(m_ui.savedAddressesList->model()->index(rowCount - 1, 1));
|
||||
}
|
||||
|
||||
void CpuWidget::contextSearchResultGoToDisassembly()
|
||||
{
|
||||
const QItemSelectionModel* selModel = m_ui.listSearchResults->selectionModel();
|
||||
if (!selModel->hasSelection())
|
||||
return;
|
||||
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.listSearchResults->selectedItems().first()->data(256).toUInt());
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.listSearchResults->selectedItems().first()->data(Qt::UserRole).toUInt());
|
||||
}
|
||||
|
||||
void CpuWidget::contextRemoveSearchResult()
|
||||
@@ -506,8 +648,8 @@ void CpuWidget::contextRemoveSearchResult()
|
||||
return;
|
||||
|
||||
const int selectedResultIndex = m_ui.listSearchResults->row(m_ui.listSearchResults->selectedItems().first());
|
||||
auto* rowToRemove = m_ui.listSearchResults->takeItem(selectedResultIndex);
|
||||
if (m_searchResults.size() > static_cast<size_t>(selectedResultIndex) && m_searchResults.at(selectedResultIndex) == rowToRemove->data(256).toUInt())
|
||||
const auto* rowToRemove = m_ui.listSearchResults->takeItem(selectedResultIndex);
|
||||
if (m_searchResults.size() > static_cast<size_t>(selectedResultIndex) && m_searchResults.at(selectedResultIndex) == rowToRemove->data(Qt::UserRole).toUInt())
|
||||
{
|
||||
m_searchResults.erase(m_searchResults.begin() + selectedResultIndex);
|
||||
}
|
||||
@@ -548,7 +690,7 @@ void CpuWidget::updateFunctionList(bool whenEmpty)
|
||||
|
||||
item->setText(QString("%0 %1").arg(FilledQStringFromValue(symbol.address, 16)).arg(symbolName));
|
||||
|
||||
item->setData(256, symbol.address);
|
||||
item->setData(Qt::UserRole, symbol.address);
|
||||
|
||||
m_ui.listFunctions->addItem(item);
|
||||
}
|
||||
@@ -576,7 +718,7 @@ void CpuWidget::updateFunctionList(bool whenEmpty)
|
||||
symbolName = demangledName;
|
||||
}
|
||||
QTreeWidgetItem* functionItem = new QTreeWidgetItem(moduleItem, QStringList(QString("%0 %1").arg(FilledQStringFromValue(sym.address, 16)).arg(symbolName)));
|
||||
functionItem->setData(0, 256, sym.address);
|
||||
functionItem->setData(0, Qt::UserRole, sym.address);
|
||||
functions.append(functionItem);
|
||||
}
|
||||
moduleItem->addChildren(functions);
|
||||
@@ -653,7 +795,7 @@ void CpuWidget::onFuncListContextMenu(QPoint pos)
|
||||
else
|
||||
m_funclistContextMenu->clear();
|
||||
|
||||
if (m_ui.listFunctions->selectedItems().count() && m_ui.listFunctions->selectedItems().first()->data(256).isValid())
|
||||
if (m_ui.listFunctions->selectedItems().count() && m_ui.listFunctions->selectedItems().first()->data(Qt::UserRole).isValid())
|
||||
{
|
||||
QAction* copyName = new QAction(tr("Copy Function Name"), m_ui.listFunctions);
|
||||
connect(copyName, &QAction::triggered, [this] {
|
||||
@@ -661,14 +803,14 @@ void CpuWidget::onFuncListContextMenu(QPoint pos)
|
||||
// Resolve the function name by fetching the symbolmap and filtering the address
|
||||
|
||||
const QListWidgetItem* selectedItem = m_ui.listFunctions->selectedItems().first();
|
||||
const QString functionName = QString(m_cpu.GetSymbolMap().GetLabelName(selectedItem->data(256).toUInt()).c_str());
|
||||
const QString functionName = QString(m_cpu.GetSymbolMap().GetLabelName(selectedItem->data(Qt::UserRole).toUInt()).c_str());
|
||||
QApplication::clipboard()->setText(functionName);
|
||||
});
|
||||
m_funclistContextMenu->addAction(copyName);
|
||||
|
||||
QAction* copyAddress = new QAction(tr("Copy Function Address"), m_ui.listFunctions);
|
||||
connect(copyAddress, &QAction::triggered, [this] {
|
||||
const QString addressString = FilledQStringFromValue(m_ui.listFunctions->selectedItems().first()->data(256).toUInt(), 16);
|
||||
const QString addressString = FilledQStringFromValue(m_ui.listFunctions->selectedItems().first()->data(Qt::UserRole).toUInt(), 16);
|
||||
QApplication::clipboard()->setText(addressString);
|
||||
});
|
||||
|
||||
@@ -678,14 +820,14 @@ void CpuWidget::onFuncListContextMenu(QPoint pos)
|
||||
|
||||
QAction* gotoDisasm = new QAction(tr("Go to in Disassembly"), m_ui.listFunctions);
|
||||
connect(gotoDisasm, &QAction::triggered, [this] {
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.listFunctions->selectedItems().first()->data(256).toUInt());
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.listFunctions->selectedItems().first()->data(Qt::UserRole).toUInt());
|
||||
});
|
||||
|
||||
m_funclistContextMenu->addAction(gotoDisasm);
|
||||
|
||||
QAction* gotoMemory = new QAction(tr("Go to in Memory View"), m_ui.listFunctions);
|
||||
connect(gotoMemory, &QAction::triggered, [this] {
|
||||
m_ui.memoryviewWidget->gotoAddress(m_ui.listFunctions->selectedItems().first()->data(256).toUInt());
|
||||
m_ui.memoryviewWidget->gotoAddress(m_ui.listFunctions->selectedItems().first()->data(Qt::UserRole).toUInt());
|
||||
});
|
||||
|
||||
m_funclistContextMenu->addAction(gotoMemory);
|
||||
@@ -725,7 +867,7 @@ void CpuWidget::onFuncListContextMenu(QPoint pos)
|
||||
|
||||
void CpuWidget::onFuncListDoubleClick(QListWidgetItem* item)
|
||||
{
|
||||
m_ui.disassemblyWidget->gotoAddress(item->data(256).toUInt());
|
||||
m_ui.disassemblyWidget->gotoAddress(item->data(Qt::UserRole).toUInt());
|
||||
}
|
||||
|
||||
void CpuWidget::onModuleTreeContextMenu(QPoint pos)
|
||||
@@ -735,17 +877,17 @@ void CpuWidget::onModuleTreeContextMenu(QPoint pos)
|
||||
else
|
||||
m_moduleTreeContextMenu->clear();
|
||||
|
||||
if (m_ui.treeModules->selectedItems().count() && m_ui.treeModules->selectedItems().first()->data(0, 256).isValid())
|
||||
if (m_ui.treeModules->selectedItems().count() && m_ui.treeModules->selectedItems().first()->data(0, Qt::UserRole).isValid())
|
||||
{
|
||||
QAction* copyName = new QAction(tr("Copy Function Name"), m_ui.treeModules);
|
||||
connect(copyName, &QAction::triggered, [this] {
|
||||
QApplication::clipboard()->setText(m_cpu.GetSymbolMap().GetLabelName(m_ui.treeModules->selectedItems().first()->data(0, 256).toUInt()).c_str());
|
||||
QApplication::clipboard()->setText(m_cpu.GetSymbolMap().GetLabelName(m_ui.treeModules->selectedItems().first()->data(0, Qt::UserRole).toUInt()).c_str());
|
||||
});
|
||||
m_moduleTreeContextMenu->addAction(copyName);
|
||||
|
||||
QAction* copyAddress = new QAction(tr("Copy Function Address"), m_ui.treeModules);
|
||||
connect(copyAddress, &QAction::triggered, [this] {
|
||||
const QString addressString = FilledQStringFromValue(m_ui.treeModules->selectedItems().first()->data(0, 256).toUInt(), 16);
|
||||
const QString addressString = FilledQStringFromValue(m_ui.treeModules->selectedItems().first()->data(0, Qt::UserRole).toUInt(), 16);
|
||||
QApplication::clipboard()->setText(addressString);
|
||||
});
|
||||
m_moduleTreeContextMenu->addAction(copyAddress);
|
||||
@@ -754,13 +896,13 @@ void CpuWidget::onModuleTreeContextMenu(QPoint pos)
|
||||
|
||||
QAction* gotoDisasm = new QAction(tr("Go to in Disassembly"), m_ui.treeModules);
|
||||
connect(gotoDisasm, &QAction::triggered, [this] {
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.treeModules->selectedItems().first()->data(0, 256).toUInt());
|
||||
m_ui.disassemblyWidget->gotoAddress(m_ui.treeModules->selectedItems().first()->data(0, Qt::UserRole).toUInt());
|
||||
});
|
||||
m_moduleTreeContextMenu->addAction(gotoDisasm);
|
||||
|
||||
QAction* gotoMemory = new QAction(tr("Go to in Memory View"), m_ui.treeModules);
|
||||
connect(gotoMemory, &QAction::triggered, [this] {
|
||||
m_ui.memoryviewWidget->gotoAddress(m_ui.treeModules->selectedItems().first()->data(0, 256).toUInt());
|
||||
m_ui.memoryviewWidget->gotoAddress(m_ui.treeModules->selectedItems().first()->data(0, Qt::UserRole).toUInt());
|
||||
});
|
||||
m_moduleTreeContextMenu->addAction(gotoMemory);
|
||||
}
|
||||
@@ -798,9 +940,9 @@ void CpuWidget::onModuleTreeContextMenu(QPoint pos)
|
||||
|
||||
void CpuWidget::onModuleTreeDoubleClick(QTreeWidgetItem* item)
|
||||
{
|
||||
if (item->data(0, 256).isValid())
|
||||
if (item->data(0, Qt::UserRole).isValid())
|
||||
{
|
||||
m_ui.disassemblyWidget->gotoAddress(item->data(0, 256).toUInt());
|
||||
m_ui.disassemblyWidget->gotoAddress(item->data(0, Qt::UserRole).toUInt());
|
||||
}
|
||||
}
|
||||
void CpuWidget::updateStackFrames()
|
||||
@@ -812,6 +954,7 @@ void CpuWidget::onListSearchResultsContextMenu(QPoint pos)
|
||||
{
|
||||
QMenu* contextMenu = new QMenu(tr("Search Results List Context Menu"), m_ui.listSearchResults);
|
||||
const QItemSelectionModel* selModel = m_ui.listSearchResults->selectionModel();
|
||||
const auto listSearchResults = m_ui.listSearchResults;
|
||||
|
||||
if (selModel->hasSelection())
|
||||
{
|
||||
@@ -819,6 +962,12 @@ void CpuWidget::onListSearchResultsContextMenu(QPoint pos)
|
||||
connect(goToDisassemblyAction, &QAction::triggered, this, &CpuWidget::contextSearchResultGoToDisassembly);
|
||||
contextMenu->addAction(goToDisassemblyAction);
|
||||
|
||||
QAction* addToSavedAddressesAction = new QAction(tr("Add to Saved Memory Addresses"), m_ui.listSearchResults);
|
||||
connect(addToSavedAddressesAction, &QAction::triggered, this, [this, listSearchResults]() {
|
||||
addAddressToSavedAddressesList(listSearchResults->selectedItems().first()->data(Qt::UserRole).toUInt());
|
||||
});
|
||||
contextMenu->addAction(addToSavedAddressesAction);
|
||||
|
||||
QAction* removeResultAction = new QAction(tr("Remove Result"), m_ui.listSearchResults);
|
||||
connect(removeResultAction, &QAction::triggered, this, &CpuWidget::contextRemoveSearchResult);
|
||||
contextMenu->addAction(removeResultAction);
|
||||
@@ -1002,19 +1151,37 @@ std::vector<u32> searchWorker(DebugInterface* cpu, std::vector<u32> searchAddres
|
||||
return hitAddresses;
|
||||
}
|
||||
|
||||
static bool compareByteArrayAtAddress(DebugInterface* cpu, u32 addr, QByteArray value)
|
||||
static bool compareByteArrayAtAddress(DebugInterface* cpu, SearchComparison searchComparison, u32 addr, QByteArray value)
|
||||
{
|
||||
const bool isNotOperator = searchComparison == SearchComparison::NotEquals;
|
||||
for (qsizetype i = 0; i < value.length(); i++)
|
||||
{
|
||||
if (static_cast<char>(cpu->read8(addr + i)) != value[i])
|
||||
const char nextByte = cpu->read8(addr + i);
|
||||
switch (searchComparison)
|
||||
{
|
||||
return false;
|
||||
case SearchComparison::Equals:
|
||||
{
|
||||
if (nextByte != value[i])
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SearchComparison::NotEquals:
|
||||
{
|
||||
if (nextByte != value[i])
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Console.Error("Debugger: Unknown search comparison when doing memory search");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !isNotOperator;
|
||||
}
|
||||
|
||||
static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, std::vector<u32> searchAddresses, u32 start, u32 end, QByteArray value)
|
||||
static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, SearchComparison searchComparison, std::vector<u32> searchAddresses, u32 start, u32 end, QByteArray value)
|
||||
{
|
||||
std::vector<u32> hitAddresses;
|
||||
const bool isSearchingRange = searchAddresses.size() <= 0;
|
||||
@@ -1022,7 +1189,7 @@ static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, std::vector<u
|
||||
{
|
||||
for (u32 addr = start; addr < end; addr += 1)
|
||||
{
|
||||
if (compareByteArrayAtAddress(cpu, addr, value))
|
||||
if (compareByteArrayAtAddress(cpu, searchComparison, addr, value))
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
addr += value.length() - 1;
|
||||
@@ -1033,7 +1200,7 @@ static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, std::vector<u
|
||||
{
|
||||
for (u32 addr : searchAddresses)
|
||||
{
|
||||
if (compareByteArrayAtAddress(cpu, addr, value))
|
||||
if (compareByteArrayAtAddress(cpu, searchComparison, addr, value))
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
}
|
||||
@@ -1060,9 +1227,9 @@ std::vector<u32> startWorker(DebugInterface* cpu, const SearchType type, const S
|
||||
case SearchType::DoubleType:
|
||||
return searchWorker<double>(cpu, searchAddresses, searchComparison, start, end, value.toDouble());
|
||||
case SearchType::StringType:
|
||||
return searchWorkerByteArray(cpu, searchAddresses, start, end, value.toUtf8());
|
||||
return searchWorkerByteArray(cpu, searchComparison, searchAddresses, start, end, value.toUtf8());
|
||||
case SearchType::ArrayType:
|
||||
return searchWorkerByteArray(cpu, searchAddresses, start, end, QByteArray::fromHex(value.toUtf8()));
|
||||
return searchWorkerByteArray(cpu, searchComparison, searchAddresses, start, end, QByteArray::fromHex(value.toUtf8()));
|
||||
default:
|
||||
Console.Error("Debugger: Unknown type when doing memory search!");
|
||||
break;
|
||||
@@ -1107,7 +1274,13 @@ void CpuWidget::onSearchButtonClicked()
|
||||
unsigned long long value;
|
||||
|
||||
const bool isVariableSize = searchType == SearchType::ArrayType || searchType == SearchType::StringType;
|
||||
if (isVariableSize && searchComparison != SearchComparison::Equals)
|
||||
if (isVariableSize && !isFilterSearch && searchComparison == SearchComparison::NotEquals)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Debugger"), tr("Search types Array and String can use the Not Equals search comparison type with new searches."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVariableSize && searchComparison != SearchComparison::Equals && searchComparison != SearchComparison::NotEquals)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Debugger"), tr("Search types Array and String can only be used with Equals search comparisons."));
|
||||
return;
|
||||
@@ -1214,7 +1387,7 @@ void CpuWidget::loadSearchResults()
|
||||
{
|
||||
u32 address = m_searchResults.at(numLoaded + i);
|
||||
QListWidgetItem* item = new QListWidgetItem(QtUtils::FilledQStringFromValue(address, 16));
|
||||
item->setData(256, address);
|
||||
item->setData(Qt::UserRole, address);
|
||||
m_ui.listSearchResults->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Models/BreakpointModel.h"
|
||||
#include "Models/ThreadModel.h"
|
||||
#include "Models/StackModel.h"
|
||||
#include "Models/SavedAddressesModel.h"
|
||||
|
||||
#include "QtHost.h"
|
||||
#include <QtWidgets/QWidget>
|
||||
@@ -74,6 +75,11 @@ public slots:
|
||||
void contextBPListEdit();
|
||||
void contextBPListPasteCSV();
|
||||
|
||||
void onSavedAddressesListContextMenu(QPoint pos);
|
||||
void contextSavedAddressesListPasteCSV();
|
||||
void contextSavedAddressesListNew();
|
||||
void addAddressToSavedAddressesList(u32 address);
|
||||
|
||||
void updateThreads();
|
||||
void onThreadListDoubleClick(const QModelIndex& index);
|
||||
void onThreadListContextMenu(QPoint pos);
|
||||
@@ -128,6 +134,7 @@ private:
|
||||
ThreadModel m_threadModel;
|
||||
QSortFilterProxyModel m_threadProxyModel;
|
||||
StackModel m_stackModel;
|
||||
SavedAddressesModel m_savedAddressesModel;
|
||||
QTimer m_resultsLoadTimer;
|
||||
|
||||
bool m_demangleFunctions = true;
|
||||
|
||||
@@ -183,20 +183,6 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>End</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="txtSearchStart">
|
||||
<property name="text">
|
||||
<string notr="true">0x00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
@@ -207,20 +193,6 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="txtSearchValue"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="txtSearchEnd">
|
||||
<property name="text">
|
||||
<string notr="true">0x2000000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
@@ -340,6 +312,45 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="comparisonLabel">
|
||||
<property name="text">
|
||||
<string>Comparison</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" alignment="Qt::AlignLeft">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" alignment="Qt::AlignLeft">
|
||||
<widget class="QLineEdit" name="txtSearchStart">
|
||||
<property name="text">
|
||||
<string notr="true">0x00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>End</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="txtSearchEnd">
|
||||
<property name="text">
|
||||
<string notr="true">0x2000000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -582,6 +593,38 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_savedaddresses">
|
||||
<attribute name="title">
|
||||
<string>Saved Addresses</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="savedAddressesList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::NoPen</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -391,7 +391,7 @@ void MemoryViewWidget::customMenuRequested(QPoint pos)
|
||||
m_contextMenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, [this]() { QApplication::clipboard()->setText(QString::number(m_table.selectedAddress, 16).toUpper()); });
|
||||
|
||||
action = new QAction(tr("Go to in disassembly"));
|
||||
action = new QAction(tr("Go to in Disassembly"));
|
||||
m_contextMenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, [this]() { emit gotoInDisasm(m_table.selectedAddress); });
|
||||
|
||||
@@ -424,6 +424,10 @@ void MemoryViewWidget::customMenuRequested(QPoint pos)
|
||||
|
||||
m_contextMenu->addSeparator();
|
||||
|
||||
action = new QAction((tr("Add to Saved Memory Addresses")));
|
||||
m_contextMenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, [this]() { emit addToSavedAddresses(m_table.selectedAddress); });
|
||||
|
||||
action = new QAction(tr("Copy Byte"));
|
||||
m_contextMenu->addAction(action);
|
||||
connect(action, &QAction::triggered, this, [this]() { contextCopyByte(); });
|
||||
|
||||
@@ -104,6 +104,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void gotoInDisasm(u32 address, bool should_set_focus = true);
|
||||
void addToSavedAddresses(u32 address);
|
||||
void VMUpdate();
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "SavedAddressesModel.h"
|
||||
|
||||
SavedAddressesModel::SavedAddressesModel(DebugInterface& cpu, QObject* parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_cpu(cpu)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant SavedAddressesModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||
{
|
||||
SavedAddress savedAddress = m_savedAddresses.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case HeaderColumns::ADDRESS:
|
||||
return QString::number(savedAddress.address, 16).toUpper();
|
||||
case HeaderColumns::LABEL:
|
||||
return savedAddress.label;
|
||||
case HeaderColumns::DESCRIPTION:
|
||||
return savedAddress.description;
|
||||
}
|
||||
}
|
||||
if (role == Qt::UserRole)
|
||||
{
|
||||
SavedAddress savedAddress = m_savedAddresses.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case HeaderColumns::ADDRESS:
|
||||
return savedAddress.address;
|
||||
case HeaderColumns::LABEL:
|
||||
return savedAddress.label;
|
||||
case HeaderColumns::DESCRIPTION:
|
||||
return savedAddress.description;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SavedAddressesModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (role == Qt::EditRole)
|
||||
{
|
||||
SavedAddress addressToEdit = m_savedAddresses.at(index.row());
|
||||
if (index.column() == HeaderColumns::ADDRESS)
|
||||
{
|
||||
bool ok = false;
|
||||
const u32 address = value.toString().toUInt(&ok, 16);
|
||||
if (ok)
|
||||
addressToEdit.address = address;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (index.column() == HeaderColumns::DESCRIPTION)
|
||||
addressToEdit.description = value.toString();
|
||||
if (index.column() == HeaderColumns::LABEL)
|
||||
addressToEdit.label = value.toString();
|
||||
m_savedAddresses.at(index.row()) = addressToEdit;
|
||||
|
||||
emit dataChanged(index, index, QList<int>(role));
|
||||
return true;
|
||||
}
|
||||
else if (role == Qt::UserRole)
|
||||
{
|
||||
SavedAddress addressToEdit = m_savedAddresses.at(index.row());
|
||||
if (index.column() == HeaderColumns::ADDRESS)
|
||||
{
|
||||
const u32 address = value.toUInt();
|
||||
addressToEdit.address = address;
|
||||
}
|
||||
if (index.column() == HeaderColumns::DESCRIPTION)
|
||||
addressToEdit.description = value.toString();
|
||||
if (index.column() == HeaderColumns::LABEL)
|
||||
addressToEdit.label = value.toString();
|
||||
m_savedAddresses.at(index.row()) = addressToEdit;
|
||||
|
||||
emit dataChanged(index, index, QList<int>(role));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant SavedAddressesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if ((role != Qt::DisplayRole && role != Qt::EditRole) || orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
|
||||
switch (section)
|
||||
{
|
||||
case SavedAddressesModel::ADDRESS:
|
||||
return tr("MEMORY ADDRESS");
|
||||
case SavedAddressesModel::LABEL:
|
||||
return tr("LABEL");
|
||||
case SavedAddressesModel::DESCRIPTION:
|
||||
return tr("DESCRIPTION");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags SavedAddressesModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
void SavedAddressesModel::addRow()
|
||||
{
|
||||
const SavedAddress defaultNewAddress = {0, "Name", "Description"};
|
||||
addRow(defaultNewAddress);
|
||||
}
|
||||
|
||||
void SavedAddressesModel::addRow(SavedAddress addresstoSave)
|
||||
{
|
||||
const int newRowIndex = m_savedAddresses.size();
|
||||
beginInsertRows(QModelIndex(), newRowIndex, newRowIndex);
|
||||
m_savedAddresses.push_back(addresstoSave);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
bool SavedAddressesModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
if (row < 0 || count < 1 || static_cast<size_t>(row + count) > m_savedAddresses.size())
|
||||
return false;
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
m_savedAddresses.erase(m_savedAddresses.begin() + row, m_savedAddresses.begin() + row + count);
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
int SavedAddressesModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_savedAddresses.size();
|
||||
}
|
||||
|
||||
int SavedAddressesModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return HeaderColumns::COLUMN_COUNT;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtWidgets/QHeaderView>
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
|
||||
class SavedAddressesModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct SavedAddress
|
||||
{
|
||||
u32 address;
|
||||
QString label;
|
||||
QString description;
|
||||
};
|
||||
|
||||
enum HeaderColumns : int
|
||||
{
|
||||
ADDRESS = 0,
|
||||
LABEL,
|
||||
DESCRIPTION,
|
||||
COLUMN_COUNT
|
||||
};
|
||||
|
||||
static constexpr QHeaderView::ResizeMode HeaderResizeModes[HeaderColumns::COLUMN_COUNT] =
|
||||
{
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::Stretch,
|
||||
};
|
||||
|
||||
explicit SavedAddressesModel(DebugInterface& cpu, QObject* parent = nullptr);
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
void addRow();
|
||||
void addRow(SavedAddress addresstoSave);
|
||||
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
|
||||
|
||||
private:
|
||||
DebugInterface& m_cpu;
|
||||
std::vector<SavedAddress> m_savedAddresses;
|
||||
};
|
||||
@@ -272,7 +272,7 @@ void RegisterWidget::customMenuRequested(QPoint pos)
|
||||
m_contextMenu->addAction(action = new QAction(tr("Go to in Disassembly"), this));
|
||||
connect(action, &QAction::triggered, this, &RegisterWidget::contextGotoDisasm);
|
||||
|
||||
m_contextMenu->addAction(action = new QAction(tr("Go to in Memory"), this));
|
||||
m_contextMenu->addAction(action = new QAction(tr("Go to in Memory View"), this));
|
||||
connect(action, &QAction::triggered, this, &RegisterWidget::contextGotoMemory);
|
||||
|
||||
m_contextMenu->popup(this->mapToGlobal(pos));
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/ImGui/FullscreenUI.h"
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
@@ -323,8 +324,9 @@ bool DisplayWidget::event(QEvent* event)
|
||||
// don't toggle fullscreen when we're bound.. that wouldn't end well.
|
||||
if (event->type() == QEvent::MouseButtonDblClick &&
|
||||
static_cast<const QMouseEvent*>(event)->button() == Qt::LeftButton &&
|
||||
QtHost::IsVMValid() && !QtHost::IsVMPaused() &&
|
||||
!InputManager::HasAnyBindingsForKey(InputManager::MakePointerButtonKey(0, 0)) &&
|
||||
QtHost::IsVMValid() && !FullscreenUI::HasActiveWindow() &&
|
||||
((!QtHost::IsVMPaused() && !InputManager::HasAnyBindingsForKey(InputManager::MakePointerButtonKey(0, 0))) ||
|
||||
(QtHost::IsVMPaused() && !ImGuiManager::WantsMouseInput())) &&
|
||||
Host::GetBoolSettingValue("UI", "DoubleClickTogglesFullscreen", true))
|
||||
{
|
||||
g_emu_thread->toggleFullscreen();
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "LogWindow.h"
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
|
||||
#include <QtCore/QLatin1StringView>
|
||||
#include <QtCore/QUtf8StringView>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QScrollBar>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
// Need a lock so the other threads don't try to write to a deleting window.
|
||||
LogWindow* g_log_window;
|
||||
static std::mutex s_log_mutex;
|
||||
|
||||
static LOGLEVEL GetWindowLogLevel()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
return LOGLEVEL_DEBUG;
|
||||
#else
|
||||
return (IsDevBuild || Host::GetBaseBoolSettingValue("Logging", "EnableVerbose", false)) ? LOGLEVEL_DEV : LOGLEVEL_INFO;
|
||||
#endif
|
||||
}
|
||||
|
||||
LogWindow::LogWindow(bool attach_to_main)
|
||||
: QMainWindow()
|
||||
, m_attached_to_main_window(attach_to_main)
|
||||
{
|
||||
restoreSize();
|
||||
createUi();
|
||||
|
||||
Log::SetHostOutputLevel(GetWindowLogLevel(), &LogWindow::logCallback);
|
||||
}
|
||||
|
||||
LogWindow::~LogWindow()
|
||||
{
|
||||
Log::SetHostOutputLevel(LOGLEVEL_NONE, nullptr);
|
||||
}
|
||||
|
||||
void LogWindow::updateSettings()
|
||||
{
|
||||
std::unique_lock lock(s_log_mutex);
|
||||
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableLogWindow", false) && !QtHost::InNoGUIMode();
|
||||
const bool attach_to_main = Host::GetBaseBoolSettingValue("Logging", "AttachLogWindowToMainWindow", true);
|
||||
const bool curr_enabled = Log::IsHostOutputEnabled();
|
||||
|
||||
if (new_enabled == curr_enabled)
|
||||
{
|
||||
if (g_log_window && g_log_window->m_attached_to_main_window != attach_to_main)
|
||||
{
|
||||
g_log_window->m_attached_to_main_window = attach_to_main;
|
||||
if (attach_to_main)
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
// Update level.
|
||||
if (new_enabled)
|
||||
Log::SetHostOutputLevel(GetWindowLogLevel(), &LogWindow::logCallback);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_enabled)
|
||||
{
|
||||
g_log_window = new LogWindow(attach_to_main);
|
||||
if (attach_to_main && g_main_window && g_main_window->isVisible())
|
||||
g_log_window->reattachToMainWindow();
|
||||
|
||||
g_log_window->show();
|
||||
}
|
||||
else if (g_log_window)
|
||||
{
|
||||
g_log_window->m_destroying = true;
|
||||
g_log_window->close();
|
||||
g_log_window->deleteLater();
|
||||
g_log_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::destroy()
|
||||
{
|
||||
std::unique_lock lock(s_log_mutex);
|
||||
if (!g_log_window)
|
||||
return;
|
||||
|
||||
g_log_window->m_destroying = true;
|
||||
g_log_window->close();
|
||||
g_log_window->deleteLater();
|
||||
g_log_window = nullptr;
|
||||
}
|
||||
|
||||
void LogWindow::reattachToMainWindow()
|
||||
{
|
||||
// Skip when maximized.
|
||||
if (g_main_window->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen))
|
||||
return;
|
||||
|
||||
resize(width(), g_main_window->height());
|
||||
|
||||
const QPoint new_pos = g_main_window->pos() + QPoint(g_main_window->width() + 10, 0);
|
||||
if (pos() != new_pos)
|
||||
move(new_pos);
|
||||
}
|
||||
|
||||
void LogWindow::updateWindowTitle()
|
||||
{
|
||||
QString title;
|
||||
|
||||
const QString& serial = QtHost::GetCurrentGameSerial();
|
||||
|
||||
if (QtHost::IsVMValid() && !serial.isEmpty())
|
||||
{
|
||||
const QFileInfo fi(QtHost::GetCurrentGamePath());
|
||||
title = tr("Log Window - %1 [%2]").arg(serial).arg(fi.fileName());
|
||||
}
|
||||
else
|
||||
{
|
||||
title = tr("Log Window");
|
||||
}
|
||||
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
void LogWindow::createUi()
|
||||
{
|
||||
setWindowIcon(QtHost::GetAppIcon());
|
||||
updateWindowTitle();
|
||||
|
||||
QAction* action;
|
||||
|
||||
QMenuBar* menu = new QMenuBar(this);
|
||||
setMenuBar(menu);
|
||||
|
||||
QMenu* log_menu = menu->addMenu("&Log");
|
||||
action = log_menu->addAction(tr("&Clear"));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::onClearTriggered);
|
||||
action = log_menu->addAction(tr("&Save..."));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::onSaveTriggered);
|
||||
|
||||
log_menu->addSeparator();
|
||||
|
||||
action = log_menu->addAction(tr("Cl&ose"));
|
||||
connect(action, &QAction::triggered, this, &LogWindow::close);
|
||||
|
||||
QMenu* settings_menu = menu->addMenu(tr("&Settings"));
|
||||
|
||||
#if 0
|
||||
// TODO: These are duplicated with the main window...
|
||||
action = settings_menu->addAction(tr("Log To &System Console"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableSystemConsole", false);
|
||||
|
||||
action = settings_menu->addAction(tr("Log To &Debug Console"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableDebugConsole", false);
|
||||
|
||||
action = settings_menu->addAction(tr("Log To &File"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableFileLogging", false);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
#endif
|
||||
|
||||
action = settings_menu->addAction(tr("Attach To &Main Window"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "AttachLogWindowToMainWindow", true);
|
||||
|
||||
action = settings_menu->addAction(tr("Show &Timestamps"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableTimestamps", true);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
|
||||
// TODO: Log Level
|
||||
|
||||
m_text = new QPlainTextEdit(this);
|
||||
m_text->setReadOnly(true);
|
||||
m_text->setUndoRedoEnabled(false);
|
||||
m_text->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
m_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_text->setWordWrapMode(QTextOption::WrapAnywhere);
|
||||
|
||||
#if defined(_WIN32)
|
||||
QFont font("Consolas");
|
||||
font.setPointSize(10);
|
||||
#elif defined(__APPLE__)
|
||||
QFont font("Monaco");
|
||||
font.setPointSize(11);
|
||||
#else
|
||||
QFont font("Monospace");
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
#endif
|
||||
m_text->setFont(font);
|
||||
|
||||
setCentralWidget(m_text);
|
||||
}
|
||||
|
||||
void LogWindow::onClearTriggered()
|
||||
{
|
||||
m_text->clear();
|
||||
}
|
||||
|
||||
void LogWindow::onSaveTriggered()
|
||||
{
|
||||
const QString path = QFileDialog::getSaveFileName(this, tr("Select Log File"), QString(), tr("Log Files (*.txt)"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to open file for writing."));
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(m_text->toPlainText().toUtf8());
|
||||
file.close();
|
||||
|
||||
appendMessage(LOGLEVEL_INFO, Color_Default, tr("Log was written to %1.\n").arg(path));
|
||||
}
|
||||
|
||||
void LogWindow::logCallback(LOGLEVEL level, ConsoleColors color, std::string_view message)
|
||||
{
|
||||
std::unique_lock lock(s_log_mutex);
|
||||
if (!g_log_window)
|
||||
return;
|
||||
|
||||
// I don't like the memory allocations here either...
|
||||
QString qmessage;
|
||||
qmessage.reserve(message.length() + 1);
|
||||
qmessage.append(QUtf8StringView(message.data(), message.length()));
|
||||
qmessage.append(QChar('\n'));
|
||||
|
||||
if (g_emu_thread->isOnUIThread())
|
||||
{
|
||||
g_log_window->appendMessage(static_cast<u32>(level), static_cast<u32>(color), qmessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(g_log_window, "appendMessage", Qt::QueuedConnection,
|
||||
Q_ARG(quint32, static_cast<u32>(level)), Q_ARG(quint32, static_cast<u32>(color)),
|
||||
Q_ARG(const QString&, qmessage));
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
Log::SetHostOutputLevel(LOGLEVEL_NONE, nullptr);
|
||||
|
||||
// Save size when actually closing, disable ourselves if the user closed us.
|
||||
if (m_destroying)
|
||||
{
|
||||
saveSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::SetBaseBoolSettingValue("Logging", "EnableLogWindow", false);
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void LogWindow::appendMessage(quint32 level, quint32 color, const QString& message)
|
||||
{
|
||||
QTextCursor temp_cursor = m_text->textCursor();
|
||||
QScrollBar* scrollbar = m_text->verticalScrollBar();
|
||||
const bool cursor_at_end = temp_cursor.atEnd();
|
||||
const bool scroll_at_end = scrollbar->sliderPosition() == scrollbar->maximum();
|
||||
|
||||
temp_cursor.movePosition(QTextCursor::End);
|
||||
|
||||
{
|
||||
static constexpr const QColor qcolors[2][ConsoleColors_Count] = {
|
||||
// Light theme
|
||||
{
|
||||
QColor(0, 0, 0), // Color_Default
|
||||
QColor(0, 0, 0), // Color_Black
|
||||
QColor(128, 0, 0), // Color_Red
|
||||
QColor(0, 128, 0), // Color_Green
|
||||
QColor(0, 0, 128), // Color_Blue
|
||||
QColor(160, 0, 160), // Color_Magenta
|
||||
QColor(160, 120, 0), // Color_Orange
|
||||
QColor(108, 108, 108), // Color_Gray
|
||||
|
||||
QColor(128, 180, 180), // Color_Cyan
|
||||
QColor(180, 180, 128), // Color_Yellow
|
||||
QColor(160, 160, 160), // Color_White
|
||||
|
||||
QColor(0, 0, 0), // Color_StrongBlack
|
||||
QColor(128, 0, 0), // Color_StrongRed
|
||||
QColor(0, 128, 0), // Color_StrongGreen
|
||||
QColor(0, 0, 128), // Color_StrongBlue
|
||||
QColor(160, 0, 160), // Color_StrongMagenta
|
||||
QColor(160, 120, 0), // Color_StrongOrange
|
||||
QColor(108, 108, 108), // Color_StrongGray
|
||||
|
||||
QColor(128, 180, 180), // Color_StrongCyan
|
||||
QColor(180, 180, 128), // Color_StrongYellow
|
||||
QColor(160, 160, 160), // Color_StrongWhite
|
||||
},
|
||||
// Dark theme
|
||||
{
|
||||
QColor(208, 208, 208), // Color_Default
|
||||
QColor(255, 255, 255), // Color_Black
|
||||
QColor(180, 0, 0), // Color_Red
|
||||
QColor(0, 160, 0), // Color_Green
|
||||
QColor(32, 32, 204), // Color_Blue
|
||||
QColor(160, 0, 160), // Color_Magenta
|
||||
QColor(160, 120, 0), // Color_Orange
|
||||
QColor(128, 128, 128), // Color_Gray
|
||||
QColor(128, 180, 180), // Color_Cyan
|
||||
QColor(180, 180, 128), // Color_Yellow
|
||||
QColor(160, 160, 160), // Color_White
|
||||
QColor(255, 255, 255), // Color_StrongBlack
|
||||
QColor(180, 0, 0), // Color_StrongRed
|
||||
QColor(0, 160, 0), // Color_StrongGreen
|
||||
QColor(32, 32, 204), // Color_StrongBlue
|
||||
QColor(160, 0, 160), // Color_StrongMagenta
|
||||
QColor(160, 120, 0), // Color_StrongOrange
|
||||
QColor(128, 128, 128), // Color_StrongGray
|
||||
QColor(128, 180, 180), // Color_StrongCyan
|
||||
QColor(180, 180, 128), // Color_StrongYellow
|
||||
QColor(160, 160, 160), // Color_StrongWhite
|
||||
},
|
||||
};
|
||||
|
||||
static constexpr const QColor timestamp_color = QColor(0xcc, 0xcc, 0xcc);
|
||||
|
||||
QTextCharFormat format = temp_cursor.charFormat();
|
||||
|
||||
if (Log::AreTimestampsEnabled())
|
||||
{
|
||||
const float message_time = Log::GetCurrentMessageTime();
|
||||
const QString qtimestamp = QStringLiteral("[%1] ").arg(message_time, 10, 'f', 4);
|
||||
format.setForeground(QBrush(timestamp_color));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(qtimestamp);
|
||||
}
|
||||
|
||||
const bool dark = static_cast<u32>(QtHost::IsDarkApplicationTheme());
|
||||
|
||||
// message has \n already
|
||||
format.setForeground(QBrush(qcolors[static_cast<u32>(dark)][color]));
|
||||
temp_cursor.setCharFormat(format);
|
||||
temp_cursor.insertText(message);
|
||||
}
|
||||
|
||||
if (cursor_at_end)
|
||||
{
|
||||
if (scroll_at_end)
|
||||
{
|
||||
m_text->setTextCursor(temp_cursor);
|
||||
scrollbar->setSliderPosition(scrollbar->maximum());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't let changing the cursor affect the scroll bar...
|
||||
const int pos = scrollbar->sliderPosition();
|
||||
m_text->setTextCursor(temp_cursor);
|
||||
scrollbar->setSliderPosition(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::saveSize()
|
||||
{
|
||||
const int current_width = Host::GetBaseIntSettingValue("UI", "LogWindowWidth", DEFAULT_WIDTH);
|
||||
const int current_height = Host::GetBaseIntSettingValue("UI", "LogWindowHeight", DEFAULT_HEIGHT);
|
||||
const QSize wsize = size();
|
||||
|
||||
bool changed = false;
|
||||
if (current_width != wsize.width())
|
||||
{
|
||||
Host::SetBaseIntSettingValue("UI", "LogWindowWidth", wsize.width());
|
||||
changed = true;
|
||||
}
|
||||
if (current_height != wsize.height())
|
||||
{
|
||||
Host::SetBaseIntSettingValue("UI", "LogWindowHeight", wsize.height());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
|
||||
void LogWindow::restoreSize()
|
||||
{
|
||||
const int width = Host::GetBaseIntSettingValue("UI", "LogWindowWidth", DEFAULT_WIDTH);
|
||||
const int height = Host::GetBaseIntSettingValue("UI", "LogWindowHeight", DEFAULT_HEIGHT);
|
||||
resize(width, height);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Console.h"
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QPlainTextEdit>
|
||||
|
||||
class LogWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogWindow(bool attach_to_main);
|
||||
~LogWindow();
|
||||
|
||||
static void updateSettings();
|
||||
static void destroy();
|
||||
|
||||
__fi bool isAttachedToMainWindow() const { return m_attached_to_main_window; }
|
||||
void reattachToMainWindow();
|
||||
|
||||
void updateWindowTitle();
|
||||
|
||||
private:
|
||||
void createUi();
|
||||
|
||||
static void logCallback(LOGLEVEL level, ConsoleColors color, std::string_view message);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onClearTriggered();
|
||||
void onSaveTriggered();
|
||||
void appendMessage(quint32 level, quint32 color, const QString& message);
|
||||
|
||||
private:
|
||||
static constexpr int DEFAULT_WIDTH = 750;
|
||||
static constexpr int DEFAULT_HEIGHT = 400;
|
||||
|
||||
void saveSize();
|
||||
void restoreSize();
|
||||
|
||||
QPlainTextEdit* m_text;
|
||||
QMenu* m_level_menu;
|
||||
|
||||
bool m_attached_to_main_window = true;
|
||||
bool m_destroying = false;
|
||||
};
|
||||
|
||||
extern LogWindow* g_log_window;
|
||||
+130
-37
@@ -7,6 +7,7 @@
|
||||
#include "DisplayWidget.h"
|
||||
#include "GameList/GameListRefreshThread.h"
|
||||
#include "GameList/GameListWidget.h"
|
||||
#include "LogWindow.h"
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
#include "pcsx2/GSDumpReplayer.h"
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/Recording/InputRecording.h"
|
||||
@@ -91,6 +91,12 @@ static bool s_use_central_widget = false;
|
||||
// UI thread VM validity.
|
||||
static bool s_vm_valid = false;
|
||||
static bool s_vm_paused = false;
|
||||
static QString s_current_title;
|
||||
static QString s_current_elf_override;
|
||||
static QString s_current_disc_path;
|
||||
static QString s_current_disc_serial;
|
||||
static quint32 s_current_disc_crc;
|
||||
static quint32 s_current_running_crc;
|
||||
|
||||
MainWindow::MainWindow()
|
||||
{
|
||||
@@ -172,11 +178,8 @@ QWidget* MainWindow::getContentParent()
|
||||
|
||||
void MainWindow::setupAdditionalUi()
|
||||
{
|
||||
const bool show_advanced_settings = QtHost::ShouldShowAdvancedSettings();
|
||||
|
||||
makeIconsMasks(menuBar());
|
||||
|
||||
m_ui.menuDebug->menuAction()->setVisible(show_advanced_settings);
|
||||
updateAdvancedSettingsVisibility();
|
||||
|
||||
const bool toolbar_visible = Host::GetBaseBoolSettingValue("UI", "ShowToolbar", false);
|
||||
m_ui.actionViewToolbar->setChecked(toolbar_visible);
|
||||
@@ -250,7 +253,7 @@ void MainWindow::setupAdditionalUi()
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
if (Achievements::IsUsingRAIntegration())
|
||||
{
|
||||
QMenu* raMenu = new QMenu(QStringLiteral("RAIntegration"), m_ui.menu_Tools);
|
||||
QMenu* raMenu = new QMenu(QStringLiteral("RAIntegration"), m_ui.menuTools);
|
||||
connect(raMenu, &QMenu::aboutToShow, this, [this, raMenu]() {
|
||||
raMenu->clear();
|
||||
|
||||
@@ -274,7 +277,7 @@ void MainWindow::setupAdditionalUi()
|
||||
[id = id]() { Host::RunOnCPUThread([id]() { Achievements::RAIntegration::ActivateMenuItem(id); }, false); });
|
||||
}
|
||||
});
|
||||
m_ui.menu_Tools->insertMenu(m_ui.menuInput_Recording->menuAction(), raMenu);
|
||||
m_ui.menuTools->insertMenu(m_ui.menuInputRecording->menuAction(), raMenu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -361,6 +364,18 @@ void MainWindow::connectSignals()
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionViewStatusBarVerbose, "UI", "VerboseStatusBar", false);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableSystemConsole, "Logging", "EnableSystemConsole", false);
|
||||
|
||||
if (Log::IsDebugOutputAvailable())
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableDebugConsole, "Logging", "EnableDebugConsole", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.menuTools->removeAction(m_ui.actionEnableDebugConsole);
|
||||
m_ui.actionEnableDebugConsole->deleteLater();
|
||||
m_ui.actionEnableDebugConsole = nullptr;
|
||||
}
|
||||
|
||||
#ifndef PCSX2_DEVBUILD
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableVerboseLogging, "Logging", "EnableVerbose", false);
|
||||
#else
|
||||
@@ -370,6 +385,7 @@ void MainWindow::connectSignals()
|
||||
#endif
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogWindow, "Logging", "EnableLogWindow", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableFileLogging, "Logging", "EnableFileLogging", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogTimestamps, "Logging", "EnableTimestamps", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableCDVDVerboseReads, "EmuCore", "CdvdVerboseReads", false);
|
||||
@@ -503,6 +519,11 @@ void MainWindow::recreate()
|
||||
new_main_window->show();
|
||||
deleteLater();
|
||||
|
||||
// Recreate log window as well. Then make sure we're still on top.
|
||||
LogWindow::updateSettings();
|
||||
new_main_window->raise();
|
||||
new_main_window->activateWindow();
|
||||
|
||||
// Reload the sources we just closed.
|
||||
g_emu_thread->reloadInputSources();
|
||||
|
||||
@@ -574,6 +595,8 @@ void MainWindow::destroySubWindows()
|
||||
}
|
||||
|
||||
SettingsWindow::closeGamePropertiesDialogs();
|
||||
|
||||
LogWindow::destroy();
|
||||
}
|
||||
|
||||
void MainWindow::onScreenshotActionTriggered()
|
||||
@@ -591,13 +614,13 @@ void MainWindow::onBlockDumpActionToggled(bool checked)
|
||||
if (!checked)
|
||||
return;
|
||||
|
||||
std::string old_directory(Host::GetBaseStringSettingValue("EmuCore", "BlockDumpSaveDirectory", ""));
|
||||
std::string old_directory = Host::GetBaseStringSettingValue("EmuCore", "BlockDumpSaveDirectory", "");
|
||||
if (old_directory.empty())
|
||||
old_directory = FileSystem::GetWorkingDirectory();
|
||||
|
||||
// prompt for a location to save
|
||||
const QString new_dir(
|
||||
QFileDialog::getExistingDirectory(this, tr("Select location to save block dump:"), QString::fromStdString(old_directory)));
|
||||
const QString new_dir(QDir::toNativeSeparators(
|
||||
QFileDialog::getExistingDirectory(this, tr("Select location to save block dump:"), QString::fromStdString(old_directory))));
|
||||
if (new_dir.isEmpty())
|
||||
{
|
||||
// disable it again
|
||||
@@ -647,13 +670,25 @@ void MainWindow::onShowAdvancedSettingsToggled(bool checked)
|
||||
Host::SetBaseBoolSettingValue("UI", "ShowAdvancedSettings", checked);
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
m_ui.menuDebug->menuAction()->setVisible(checked);
|
||||
updateAdvancedSettingsVisibility();
|
||||
|
||||
// just recreate the entire settings window, it's easier.
|
||||
if (m_settings_window)
|
||||
recreateSettings();
|
||||
}
|
||||
|
||||
void MainWindow::updateAdvancedSettingsVisibility()
|
||||
{
|
||||
const bool enabled = QtHost::ShouldShowAdvancedSettings();
|
||||
|
||||
m_ui.menuDebug->menuAction()->setVisible(enabled);
|
||||
|
||||
m_ui.actionEnableSystemConsole->setVisible(enabled);
|
||||
if (m_ui.actionEnableDebugConsole)
|
||||
m_ui.actionEnableDebugConsole->setVisible(enabled);
|
||||
m_ui.actionEnableVerboseLogging->setVisible(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::onToolsVideoCaptureToggled(bool checked)
|
||||
{
|
||||
if (!s_vm_valid)
|
||||
@@ -899,9 +934,9 @@ void MainWindow::updateWindowTitle()
|
||||
{
|
||||
QString suffix(QtHost::GetAppConfigSuffix());
|
||||
QString main_title(QtHost::GetAppNameAndVersion() + suffix);
|
||||
QString display_title(m_current_title + suffix);
|
||||
QString display_title(s_current_title + suffix);
|
||||
|
||||
if (!s_vm_valid || m_current_title.isEmpty())
|
||||
if (!s_vm_valid || s_current_title.isEmpty())
|
||||
display_title = main_title;
|
||||
else if (isRenderingToMain())
|
||||
main_title = display_title;
|
||||
@@ -915,6 +950,9 @@ void MainWindow::updateWindowTitle()
|
||||
if (container->windowTitle() != display_title)
|
||||
container->setWindowTitle(display_title);
|
||||
}
|
||||
|
||||
if (g_log_window)
|
||||
g_log_window->updateWindowTitle();
|
||||
}
|
||||
|
||||
void MainWindow::updateWindowState(bool force_visible)
|
||||
@@ -1109,7 +1147,7 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
|
||||
return true;
|
||||
|
||||
// If we don't have a crc, we can't save state.
|
||||
allow_save_to_state &= (m_current_disc_crc != 0);
|
||||
allow_save_to_state &= (s_current_disc_crc != 0);
|
||||
bool save_state = allow_save_to_state && default_save_to_state;
|
||||
VMLock lock(pauseAndLockVM());
|
||||
|
||||
@@ -1187,6 +1225,8 @@ void MainWindow::checkForSettingChanges()
|
||||
updateDisplayWidgetCursor();
|
||||
|
||||
updateWindowState();
|
||||
|
||||
LogWindow::updateSettings();
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> MainWindow::getWindowInfo()
|
||||
@@ -1408,13 +1448,13 @@ void MainWindow::onChangeDiscMenuAboutToHide()
|
||||
void MainWindow::onLoadStateMenuAboutToShow()
|
||||
{
|
||||
m_ui.menuLoadState->clear();
|
||||
populateLoadStateMenu(m_ui.menuLoadState, m_current_disc_path, m_current_disc_serial, m_current_disc_crc);
|
||||
populateLoadStateMenu(m_ui.menuLoadState, s_current_disc_path, s_current_disc_serial, s_current_disc_crc);
|
||||
}
|
||||
|
||||
void MainWindow::onSaveStateMenuAboutToShow()
|
||||
{
|
||||
m_ui.menuSaveState->clear();
|
||||
populateSaveStateMenu(m_ui.menuSaveState, m_current_disc_serial, m_current_disc_crc);
|
||||
populateSaveStateMenu(m_ui.menuSaveState, s_current_disc_serial, s_current_disc_crc);
|
||||
}
|
||||
|
||||
void MainWindow::onStartFullscreenUITriggered()
|
||||
@@ -1476,36 +1516,36 @@ void MainWindow::onViewGamePropertiesActionTriggered()
|
||||
return;
|
||||
|
||||
// prefer to use a game list entry, if we have one, that way the summary is populated
|
||||
if (!m_current_disc_path.isEmpty() || !m_current_elf_override.isEmpty())
|
||||
if (!s_current_disc_path.isEmpty() || !s_current_elf_override.isEmpty())
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
const QString& path = (m_current_elf_override.isEmpty() ? m_current_disc_path : m_current_elf_override);
|
||||
const QString& path = (s_current_elf_override.isEmpty() ? s_current_disc_path : s_current_elf_override);
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(path.toUtf8().constData());
|
||||
if (entry)
|
||||
{
|
||||
SettingsWindow::openGamePropertiesDialog(
|
||||
entry, entry->title, m_current_elf_override.isEmpty() ? entry->serial : std::string(), entry->crc);
|
||||
entry, entry->title, s_current_elf_override.isEmpty() ? entry->serial : std::string(), entry->crc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// open properties for the current running file (isn't in the game list)
|
||||
if (m_current_disc_crc == 0)
|
||||
if (s_current_disc_crc == 0)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Game Properties"), tr("Game properties is unavailable for the current game."));
|
||||
return;
|
||||
}
|
||||
|
||||
// can't use serial for ELFs, because they might have a disc set
|
||||
if (m_current_elf_override.isEmpty())
|
||||
if (s_current_elf_override.isEmpty())
|
||||
{
|
||||
SettingsWindow::openGamePropertiesDialog(
|
||||
nullptr, m_current_title.toStdString(), m_current_disc_serial.toStdString(), m_current_disc_crc);
|
||||
nullptr, s_current_title.toStdString(), s_current_disc_serial.toStdString(), s_current_disc_crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsWindow::openGamePropertiesDialog(
|
||||
nullptr, m_current_title.toStdString(), std::string(), m_current_disc_crc);
|
||||
nullptr, s_current_title.toStdString(), std::string(), s_current_disc_crc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1607,10 +1647,10 @@ void MainWindow::onToolsCoverDownloaderTriggered()
|
||||
|
||||
void MainWindow::onToolsEditCheatsPatchesTriggered(bool cheats)
|
||||
{
|
||||
if (m_current_disc_serial.isEmpty() || m_current_running_crc == 0)
|
||||
if (s_current_disc_serial.isEmpty() || s_current_running_crc == 0)
|
||||
return;
|
||||
|
||||
const std::string path = Patch::GetPnachFilename(m_current_disc_serial.toStdString(), m_current_running_crc, cheats);
|
||||
const std::string path = Patch::GetPnachFilename(s_current_disc_serial.toStdString(), s_current_running_crc, cheats);
|
||||
if (!FileSystem::FileExists(path.c_str()))
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Confirm File Creation"),
|
||||
@@ -1644,7 +1684,10 @@ void MainWindow::reloadThemeSpecificImages()
|
||||
|
||||
void MainWindow::updateLanguage()
|
||||
{
|
||||
QtHost::InstallTranslator();
|
||||
// Remove the settings window, so it doesn't mess with any popups that happen (e.g. font download).
|
||||
destroySubWindows();
|
||||
|
||||
QtHost::InstallTranslator(this);
|
||||
recreate();
|
||||
}
|
||||
|
||||
@@ -1874,12 +1917,12 @@ void MainWindow::onVMStopped()
|
||||
void MainWindow::onGameChanged(const QString& title, const QString& elf_override, const QString& disc_path,
|
||||
const QString& serial, quint32 disc_crc, quint32 crc)
|
||||
{
|
||||
m_current_title = title;
|
||||
m_current_elf_override = elf_override;
|
||||
m_current_disc_path = disc_path;
|
||||
m_current_disc_serial = serial;
|
||||
m_current_disc_crc = disc_crc;
|
||||
m_current_running_crc = crc;
|
||||
s_current_title = title;
|
||||
s_current_elf_override = elf_override;
|
||||
s_current_disc_path = disc_path;
|
||||
s_current_disc_serial = serial;
|
||||
s_current_disc_crc = disc_crc;
|
||||
s_current_running_crc = crc;
|
||||
updateWindowTitle();
|
||||
updateGameDependentActions();
|
||||
}
|
||||
@@ -2033,6 +2076,22 @@ void MainWindow::dropEvent(QDropEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::moveEvent(QMoveEvent* event)
|
||||
{
|
||||
QMainWindow::moveEvent(event);
|
||||
|
||||
if (g_log_window && g_log_window->isAttachedToMainWindow())
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QMainWindow::resizeEvent(event);
|
||||
|
||||
if (g_log_window && g_log_window->isAttachedToMainWindow())
|
||||
g_log_window->reattachToMainWindow();
|
||||
}
|
||||
|
||||
void MainWindow::registerForDeviceNotifications()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -2643,8 +2702,8 @@ void MainWindow::loadSaveStateFile(const QString& filename, const QString& state
|
||||
{
|
||||
if (s_vm_valid)
|
||||
{
|
||||
if (!filename.isEmpty() && m_current_disc_path != filename)
|
||||
g_emu_thread->changeDisc(CDVD_SourceType::Iso, m_current_disc_path);
|
||||
if (!filename.isEmpty() && s_current_disc_path != filename)
|
||||
g_emu_thread->changeDisc(CDVD_SourceType::Iso, s_current_disc_path);
|
||||
g_emu_thread->loadState(state_filename);
|
||||
}
|
||||
else
|
||||
@@ -2769,13 +2828,13 @@ void MainWindow::populateSaveStateMenu(QMenu* menu, const QString& serial, quint
|
||||
|
||||
void MainWindow::updateGameDependentActions()
|
||||
{
|
||||
const bool valid_serial_and_crc = (s_vm_valid && !m_current_disc_serial.isEmpty() && m_current_disc_crc != 0);
|
||||
const bool valid_serial_and_crc = (s_vm_valid && !s_current_disc_serial.isEmpty() && s_current_disc_crc != 0);
|
||||
m_ui.menuLoadState->setEnabled(valid_serial_and_crc);
|
||||
m_ui.actionToolbarLoadState->setEnabled(valid_serial_and_crc);
|
||||
m_ui.menuSaveState->setEnabled(valid_serial_and_crc);
|
||||
m_ui.actionToolbarSaveState->setEnabled(valid_serial_and_crc);
|
||||
|
||||
const bool can_use_pnach = (s_vm_valid && !m_current_disc_serial.isEmpty() && m_current_running_crc != 0);
|
||||
const bool can_use_pnach = (s_vm_valid && !s_current_disc_serial.isEmpty() && s_current_running_crc != 0);
|
||||
m_ui.actionEditCheats->setEnabled(can_use_pnach);
|
||||
m_ui.actionEditPatches->setEnabled(can_use_pnach);
|
||||
m_ui.actionReloadPatches->setEnabled(s_vm_valid);
|
||||
@@ -2838,7 +2897,7 @@ void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
|
||||
if (reset_system)
|
||||
{
|
||||
// Clearing ELF override will reset the system.
|
||||
if (!m_current_elf_override.isEmpty())
|
||||
if (!s_current_elf_override.isEmpty())
|
||||
g_emu_thread->setELFOverride(QString());
|
||||
else
|
||||
g_emu_thread->resetVM();
|
||||
@@ -2885,6 +2944,12 @@ MainWindow::VMLock MainWindow::pauseAndLockVM()
|
||||
// Now we'll either have a borderless window, or a regular window (if we were exclusive fullscreen).
|
||||
QWidget* dialog_parent = getDisplayContainer();
|
||||
|
||||
// Ensure main window is visible.
|
||||
if (!g_main_window->isVisible())
|
||||
g_main_window->show();
|
||||
g_main_window->raise();
|
||||
g_main_window->activateWindow();
|
||||
|
||||
return VMLock(dialog_parent, was_paused, was_fullscreen);
|
||||
}
|
||||
|
||||
@@ -2922,6 +2987,19 @@ MainWindow::VMLock::~VMLock()
|
||||
g_emu_thread->setVMPaused(false);
|
||||
}
|
||||
|
||||
MainWindow::VMLock& MainWindow::VMLock::operator=(VMLock&& lock)
|
||||
{
|
||||
m_dialog_parent = lock.m_dialog_parent;
|
||||
m_was_paused = lock.m_was_paused;
|
||||
m_was_fullscreen = lock.m_was_fullscreen;
|
||||
|
||||
lock.m_dialog_parent = nullptr;
|
||||
lock.m_was_paused = true;
|
||||
lock.m_was_fullscreen = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MainWindow::VMLock::cancelResume()
|
||||
{
|
||||
m_was_paused = true;
|
||||
@@ -2938,3 +3016,18 @@ bool QtHost::IsVMPaused()
|
||||
{
|
||||
return s_vm_paused;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGameTitle()
|
||||
{
|
||||
return s_current_title;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGameSerial()
|
||||
{
|
||||
return s_current_disc_serial;
|
||||
}
|
||||
|
||||
const QString& QtHost::GetCurrentGamePath()
|
||||
{
|
||||
return s_current_disc_path;
|
||||
}
|
||||
|
||||
+6
-10
@@ -54,6 +54,9 @@ public:
|
||||
VMLock(const VMLock&) = delete;
|
||||
~VMLock();
|
||||
|
||||
VMLock& operator=(VMLock&& lock);
|
||||
VMLock& operator=(const VMLock&) = delete;
|
||||
|
||||
/// Returns the parent widget, which can be used for any popup dialogs.
|
||||
__fi QWidget* getDialogParent() const { return m_dialog_parent; }
|
||||
|
||||
@@ -194,15 +197,14 @@ protected:
|
||||
void changeEvent(QEvent* event) override;
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
void moveEvent(QMoveEvent* event) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
#ifdef _WIN32
|
||||
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static void setStyleFromSettings();
|
||||
static void setIconThemeFromStyle();
|
||||
|
||||
void setupAdditionalUi();
|
||||
void connectSignals();
|
||||
void createRendererSwitchMenu();
|
||||
@@ -220,6 +222,7 @@ private:
|
||||
void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
|
||||
void updateGameDependentActions();
|
||||
void updateStatusBarWidgetVisibility();
|
||||
void updateAdvancedSettingsVisibility();
|
||||
void updateWindowTitle();
|
||||
void updateWindowState(bool force_visible = false);
|
||||
void setProgressBar(int current, int total);
|
||||
@@ -290,13 +293,6 @@ private:
|
||||
|
||||
QMenu* m_settings_toolbar_menu = nullptr;
|
||||
|
||||
QString m_current_title;
|
||||
QString m_current_elf_override;
|
||||
QString m_current_disc_path;
|
||||
QString m_current_disc_serial;
|
||||
quint32 m_current_disc_crc;
|
||||
quint32 m_current_running_crc;
|
||||
|
||||
bool m_display_created = false;
|
||||
bool m_relative_mouse_mode = false;
|
||||
bool m_hide_mouse_cursor = false;
|
||||
|
||||
+24
-6
@@ -146,7 +146,7 @@
|
||||
<addaction name="actionEnableIOPConsoleLogging"/>
|
||||
<addaction name="actionEnableCDVDVerboseReads"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_View">
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
@@ -176,11 +176,11 @@
|
||||
<addaction name="actionGridViewZoomOut"/>
|
||||
<addaction name="actionGridViewRefreshCovers"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Tools">
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
<string>&Tools</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuInput_Recording">
|
||||
<widget class="QMenu" name="menuInputRecording">
|
||||
<property name="title">
|
||||
<string>Input Recording</string>
|
||||
</property>
|
||||
@@ -206,10 +206,12 @@
|
||||
<addaction name="actionReloadPatches"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionToggleSoftwareRendering"/>
|
||||
<addaction name="menuInput_Recording"/>
|
||||
<addaction name="menuInputRecording"/>
|
||||
<addaction name="actionToolsVideoCapture"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionEnableSystemConsole"/>
|
||||
<addaction name="actionEnableDebugConsole"/>
|
||||
<addaction name="actionEnableLogWindow"/>
|
||||
<addaction name="actionEnableFileLogging"/>
|
||||
<addaction name="actionEnableVerboseLogging"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -219,8 +221,8 @@
|
||||
</widget>
|
||||
<addaction name="menuSystem"/>
|
||||
<addaction name="menuSettings"/>
|
||||
<addaction name="menu_View"/>
|
||||
<addaction name="menu_Tools"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuDebug"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
@@ -901,6 +903,22 @@
|
||||
<string>Enable System Console</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnableDebugConsole">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Debug Console</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnableLogWindow">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Log Window</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnableVerboseLogging">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
||||
+138
-40
@@ -4,8 +4,10 @@
|
||||
#include "AutoUpdaterDialog.h"
|
||||
#include "DisplayWidget.h"
|
||||
#include "GameList/GameListWidget.h"
|
||||
#include "LogWindow.h"
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtProgressCallback.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SetupWizardDialog.h"
|
||||
#include "svnrev.h"
|
||||
@@ -25,16 +27,15 @@
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
#include "pcsx2/ImGui/ImGuiOverlays.h"
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/SysForwardDefs.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/HTTPDownloader.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/SettingsWrapper.h"
|
||||
#include "common/StringUtil.h"
|
||||
@@ -52,6 +53,8 @@
|
||||
#include <csignal>
|
||||
|
||||
static constexpr u32 SETTINGS_SAVE_DELAY = 1000;
|
||||
static constexpr const char* RUNTIME_RESOURCES_URL =
|
||||
"https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/runtime-resources/";
|
||||
|
||||
EmuThread* g_emu_thread = nullptr;
|
||||
|
||||
@@ -60,6 +63,7 @@ EmuThread* g_emu_thread = nullptr;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace QtHost
|
||||
{
|
||||
static void InitializeEarlyConsole();
|
||||
static void PrintCommandLineVersion();
|
||||
static void PrintCommandLineHelp(const std::string_view& progname);
|
||||
static std::shared_ptr<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParameters>& autoboot);
|
||||
@@ -69,6 +73,7 @@ namespace QtHost
|
||||
static void HookSignals();
|
||||
static void RegisterTypes();
|
||||
static bool RunSetupWizard();
|
||||
static std::optional<bool> DownloadFile(QWidget* parent, const QString& title, std::string url, std::vector<u8>* data);
|
||||
} // namespace QtHost
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -82,6 +87,7 @@ static bool s_start_fullscreen_ui = false;
|
||||
static bool s_start_fullscreen_ui_fullscreen = false;
|
||||
static bool s_test_config_and_exit = false;
|
||||
static bool s_run_setup_wizard = false;
|
||||
static bool s_cleanup_after_update = false;
|
||||
static bool s_boot_and_debug = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -96,11 +102,6 @@ EmuThread::EmuThread(QThread* ui_thread)
|
||||
|
||||
EmuThread::~EmuThread() = default;
|
||||
|
||||
bool EmuThread::isOnEmuThread() const
|
||||
{
|
||||
return QThread::currentThread() == this;
|
||||
}
|
||||
|
||||
void EmuThread::start()
|
||||
{
|
||||
pxAssertRel(!g_emu_thread, "Emu thread does not exist");
|
||||
@@ -496,7 +497,7 @@ void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
|
||||
MTGS::WaitGS();
|
||||
|
||||
// If we're using exclusive fullscreen, the refresh rate may have changed.
|
||||
UpdateVSyncRate(true);
|
||||
VMManager::UpdateTargetSpeed();
|
||||
}
|
||||
|
||||
void EmuThread::setSurfaceless(bool surfaceless)
|
||||
@@ -990,7 +991,7 @@ void EmuThread::updatePerformanceMetrics(bool force)
|
||||
QMetaObject::invokeMethod(g_main_window->getStatusVerboseWidget(), "setText", Qt::QueuedConnection, Q_ARG(const QString&, gs_stat));
|
||||
}
|
||||
|
||||
const GSRendererType renderer = GSConfig.Renderer;
|
||||
const GSRendererType renderer = GSGetCurrentRenderer(); // Reading from GS thread, therefore racey, but it's just visual.
|
||||
const float speed = std::round(PerformanceMetrics::GetSpeed());
|
||||
const float gfps = std::round(PerformanceMetrics::GetInternalFPS());
|
||||
const float vfps = std::round(PerformanceMetrics::GetFPS());
|
||||
@@ -1235,9 +1236,10 @@ bool QtHost::InitializeConfig()
|
||||
s_run_setup_wizard =
|
||||
s_run_setup_wizard || s_base_settings_interface->GetBoolValue("UI", "SetupWizardIncomplete", false);
|
||||
|
||||
LogSink::SetBlockSystemConsole(QtHost::InNoGUIMode());
|
||||
// TODO: -nogui console block?
|
||||
|
||||
VMManager::Internal::LoadStartupSettings();
|
||||
InstallTranslator();
|
||||
InstallTranslator(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1334,24 +1336,7 @@ bool Host::RequestResetSettings(bool folders, bool core, bool controllers, bool
|
||||
|
||||
QString QtHost::GetAppNameAndVersion()
|
||||
{
|
||||
QString ret;
|
||||
if constexpr (!PCSX2_isReleaseVersion && GIT_TAGGED_COMMIT)
|
||||
{
|
||||
ret = QStringLiteral("PCSX2 Nightly - " GIT_TAG);
|
||||
}
|
||||
else if constexpr (PCSX2_isReleaseVersion)
|
||||
{
|
||||
#define APPNAME_STRINGIZE(x) #x
|
||||
ret = QStringLiteral(
|
||||
"PCSX2 " APPNAME_STRINGIZE(PCSX2_VersionHi) "." APPNAME_STRINGIZE(PCSX2_VersionMid) "." APPNAME_STRINGIZE(PCSX2_VersionLo));
|
||||
#undef APPNAME_STRINGIZE
|
||||
}
|
||||
else
|
||||
{
|
||||
return QStringLiteral("PCSX2 " GIT_REV);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return QStringLiteral("PCSX2 " GIT_REV);
|
||||
}
|
||||
|
||||
QString QtHost::GetAppConfigSuffix()
|
||||
@@ -1365,11 +1350,99 @@ QString QtHost::GetAppConfigSuffix()
|
||||
#endif
|
||||
}
|
||||
|
||||
QIcon QtHost::GetAppIcon()
|
||||
{
|
||||
return QIcon(QStringLiteral(":/icons/AppIcon64.png"));
|
||||
}
|
||||
|
||||
QString QtHost::GetResourcesBasePath()
|
||||
{
|
||||
return QString::fromStdString(EmuFolders::Resources);
|
||||
}
|
||||
|
||||
std::string QtHost::GetRuntimeDownloadedResourceURL(std::string_view name)
|
||||
{
|
||||
return fmt::format("{}/{}", RUNTIME_RESOURCES_URL, HTTPDownloader::URLEncode(name));
|
||||
}
|
||||
|
||||
std::optional<bool> QtHost::DownloadFile(QWidget* parent, const QString& title, std::string url, std::vector<u8>* data)
|
||||
{
|
||||
static constexpr u32 HTTP_POLL_INTERVAL = 10;
|
||||
|
||||
std::unique_ptr<HTTPDownloader> http = HTTPDownloader::Create(Host::GetHTTPUserAgent());
|
||||
if (!http)
|
||||
{
|
||||
QMessageBox::critical(parent, qApp->translate("EmuThread", "Error"), qApp->translate("EmuThread", "Failed to create HTTPDownloader."));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<bool> download_result;
|
||||
const std::string::size_type url_file_part_pos = url.rfind('/');
|
||||
QtModalProgressCallback progress(parent);
|
||||
progress.GetDialog().setLabelText(
|
||||
qApp->translate("EmuThread", "Downloading %1...").arg(QtUtils::StringViewToQString(
|
||||
std::string_view(url).substr((url_file_part_pos != std::string::npos) ? (url_file_part_pos + 1) : 0))));
|
||||
progress.GetDialog().setWindowTitle(title);
|
||||
progress.GetDialog().setWindowIcon(GetAppIcon());
|
||||
progress.SetCancellable(true);
|
||||
|
||||
http->CreateRequest(
|
||||
std::move(url), [parent, data, &download_result](s32 status_code, const std::string&, std::vector<u8> hdata) {
|
||||
if (status_code == HTTPDownloader::HTTP_STATUS_CANCELLED)
|
||||
return;
|
||||
|
||||
if (status_code != HTTPDownloader::HTTP_STATUS_OK)
|
||||
{
|
||||
QMessageBox::critical(parent, qApp->translate("EmuThread", "Error"),
|
||||
qApp->translate("EmuThread", "Download failed with HTTP status code %1.").arg(status_code));
|
||||
download_result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hdata.empty())
|
||||
{
|
||||
QMessageBox::critical(parent, qApp->translate("EmuThread", "Error"),
|
||||
qApp->translate("EmuThread", "Download failed: Data is empty.").arg(status_code));
|
||||
|
||||
download_result = false;
|
||||
return;
|
||||
}
|
||||
|
||||
*data = std::move(hdata);
|
||||
download_result = true;
|
||||
},
|
||||
&progress);
|
||||
|
||||
// Block until completion.
|
||||
while (http->HasAnyRequests())
|
||||
{
|
||||
QApplication::processEvents(QEventLoop::AllEvents, HTTP_POLL_INTERVAL);
|
||||
http->PollRequests();
|
||||
}
|
||||
|
||||
return download_result;
|
||||
}
|
||||
|
||||
bool QtHost::DownloadFile(QWidget* parent, const QString& title, std::string url, const std::string& path)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
if (!DownloadFile(parent, title, std::move(url), &data).value_or(false) || data.empty())
|
||||
return false;
|
||||
|
||||
// Directory may not exist. Create it.
|
||||
const std::string directory(Path::GetDirectory(path));
|
||||
if ((!directory.empty() && !FileSystem::DirectoryExists(directory.c_str()) &&
|
||||
!FileSystem::CreateDirectoryPath(directory.c_str(), true)) ||
|
||||
!FileSystem::WriteBinaryFile(path.c_str(), data.data(), data.size()))
|
||||
{
|
||||
QMessageBox::critical(parent, qApp->translate("EmuThread", "Error"),
|
||||
qApp->translate("EmuThread", "Failed to write '%1'.").arg(QString::fromStdString(path)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Host::ReportErrorAsync(const std::string_view& title, const std::string_view& message)
|
||||
{
|
||||
if (!title.empty() && !message.empty())
|
||||
@@ -1482,12 +1555,27 @@ static void SignalHandler(int signal)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
if (dwCtrlType != CTRL_C_EVENT)
|
||||
return FALSE;
|
||||
|
||||
SignalHandler(SIGTERM);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void QtHost::HookSignals()
|
||||
{
|
||||
std::signal(SIGINT, SignalHandler);
|
||||
std::signal(SIGTERM, SignalHandler);
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(_WIN32)
|
||||
SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
|
||||
#elif defined(__linux__)
|
||||
// Ignore SIGCHLD by default on Linux, since we kick off aplay asynchronously.
|
||||
struct sigaction sa_chld = {};
|
||||
sigemptyset(&sa_chld.sa_mask);
|
||||
@@ -1496,9 +1584,14 @@ void QtHost::HookSignals()
|
||||
#endif
|
||||
}
|
||||
|
||||
void QtHost::InitializeEarlyConsole()
|
||||
{
|
||||
Log::SetConsoleOutputLevel(LOGLEVEL_DEBUG);
|
||||
}
|
||||
|
||||
void QtHost::PrintCommandLineVersion()
|
||||
{
|
||||
LogSink::InitializeEarlyConsole();
|
||||
InitializeEarlyConsole();
|
||||
std::fprintf(stderr, "%s\n", (GetAppNameAndVersion() + GetAppConfigSuffix()).toUtf8().constData());
|
||||
std::fprintf(stderr, "https://pcsx2.net/\n");
|
||||
std::fprintf(stderr, "\n");
|
||||
@@ -1622,7 +1715,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
}
|
||||
else if (CHECK_ARG_PARAM(QStringLiteral("-logfile")))
|
||||
{
|
||||
LogSink::SetFileLogPath((++it)->toStdString());
|
||||
VMManager::Internal::SetFileLogPath((++it)->toStdString());
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-bios")))
|
||||
@@ -1643,7 +1736,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-earlyconsolelog")))
|
||||
{
|
||||
LogSink::InitializeEarlyConsole();
|
||||
InitializeEarlyConsole();
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-bigpicture")))
|
||||
@@ -1668,9 +1761,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-updatecleanup")))
|
||||
{
|
||||
if (AutoUpdaterDialog::isSupported())
|
||||
AutoUpdaterDialog::cleanupAfterUpdate();
|
||||
|
||||
s_cleanup_after_update = AutoUpdaterDialog::isSupported();
|
||||
continue;
|
||||
}
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
@@ -1705,7 +1796,6 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
// or disc, we don't want to actually start.
|
||||
if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty())
|
||||
{
|
||||
LogSink::InitializeEarlyConsole();
|
||||
Console.Warning("Skipping autoboot due to no boot parameters.");
|
||||
autoboot.reset();
|
||||
}
|
||||
@@ -1802,9 +1892,16 @@ int main(int argc, char* argv[])
|
||||
if (s_test_config_and_exit)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
// Remove any previous-version remanants.
|
||||
if (s_cleanup_after_update)
|
||||
AutoUpdaterDialog::cleanupAfterUpdate();
|
||||
|
||||
// Set theme before creating any windows.
|
||||
QtHost::UpdateApplicationTheme();
|
||||
|
||||
// Start logging early.
|
||||
LogWindow::updateSettings();
|
||||
|
||||
// Start up the CPU thread.
|
||||
QtHost::HookSignals();
|
||||
EmuThread::start();
|
||||
@@ -1829,7 +1926,11 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Don't bother showing the window in no-gui mode.
|
||||
if (!s_nogui_mode)
|
||||
{
|
||||
g_main_window->show();
|
||||
g_main_window->raise();
|
||||
g_main_window->activateWindow();
|
||||
}
|
||||
|
||||
// Initialize big picture mode if requested.
|
||||
if (s_start_fullscreen_ui)
|
||||
@@ -1863,8 +1964,5 @@ shutdown_and_exit:
|
||||
if (s_base_settings_interface->IsDirty())
|
||||
s_base_settings_interface->Save();
|
||||
|
||||
// Ensure emulog is flushed.
|
||||
LogSink::CloseFileLog();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+25
-3
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
@@ -22,6 +24,8 @@
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
class SettingsInterface;
|
||||
|
||||
class DisplayWidget;
|
||||
@@ -59,7 +63,8 @@ public:
|
||||
__fi bool isSurfaceless() const { return m_is_surfaceless; }
|
||||
__fi bool isRunningFullscreenUI() const { return m_run_fullscreen_ui; }
|
||||
|
||||
bool isOnEmuThread() const;
|
||||
__fi bool isOnEmuThread() const { return (QThread::currentThread() == this); }
|
||||
__fi bool isOnUIThread() const { return (QThread::currentThread() == m_ui_thread); }
|
||||
bool shouldRenderToMain() const;
|
||||
|
||||
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
|
||||
@@ -233,6 +238,9 @@ namespace QtHost
|
||||
/// Sets application theme according to settings.
|
||||
void UpdateApplicationTheme();
|
||||
|
||||
/// Returns true if the application theme is using dark colours.
|
||||
bool IsDarkApplicationTheme();
|
||||
|
||||
/// Sets the icon theme, based on the current style (light/dark).
|
||||
void SetIconThemeFromStyle();
|
||||
|
||||
@@ -255,7 +263,7 @@ namespace QtHost
|
||||
std::vector<std::pair<QString, QString>> GetAvailableLanguageList();
|
||||
|
||||
/// Call when the language changes.
|
||||
void InstallTranslator();
|
||||
void InstallTranslator(QWidget* dialog_parent);
|
||||
|
||||
/// Returns the application name and version, optionally including debug/devel config indicator.
|
||||
QString GetAppNameAndVersion();
|
||||
@@ -263,13 +271,27 @@ namespace QtHost
|
||||
/// Returns the debug/devel config indicator.
|
||||
QString GetAppConfigSuffix();
|
||||
|
||||
/// Returns the main application icon.
|
||||
QIcon GetAppIcon();
|
||||
|
||||
/// Returns the base path for resources. This may be : prefixed, if we're using embedded resources.
|
||||
QString GetResourcesBasePath();
|
||||
|
||||
/// Returns the URL to a runtime-downloaded resource.
|
||||
std::string GetRuntimeDownloadedResourceURL(std::string_view name);
|
||||
|
||||
/// Downloads the specified URL to the provided path.
|
||||
bool DownloadFile(QWidget* parent, const QString& title, std::string url, const std::string& path);
|
||||
|
||||
/// VM state, safe to access on UI thread.
|
||||
bool IsVMValid();
|
||||
bool IsVMPaused();
|
||||
|
||||
/// Accessors for game information.
|
||||
const QString& GetCurrentGameTitle();
|
||||
const QString& GetCurrentGameSerial();
|
||||
const QString& GetCurrentGamePath();
|
||||
|
||||
/// Compare strings in the locale of the current UI language
|
||||
int LocaleSensitiveCompare(QStringView lhs, QStringView rhs);
|
||||
} // namespace QtHost
|
||||
|
||||
@@ -29,9 +29,10 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu0RoundingMode, "EmuCore/CPU", "VU0.Roundmode", 3);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu1RoundingMode, "EmuCore/CPU", "VU1.Roundmode", 3);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", static_cast<int>(FPRoundMode::ChopZero));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeDivRoundingMode, "EmuCore/CPU", "FPUDiv.Roundmode", static_cast<int>(FPRoundMode::Nearest));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu0RoundingMode, "EmuCore/CPU", "VU0.Roundmode", static_cast<int>(FPRoundMode::ChopZero));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vu1RoundingMode, "EmuCore/CPU", "VU1.Roundmode", static_cast<int>(FPRoundMode::ChopZero));
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(-1))));
|
||||
@@ -58,6 +59,7 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.eeRoundingMode, tr("Rounding Mode"), tr("Chop/Zero (Default)"), tr("Changes how PCSX2 handles rounding while emulating the Emotion Engine's Floating Point Unit (EE FPU). "
|
||||
"Because the various FPUs in the PS2 are non-compliant with international standards, some games may need different modes to do math correctly. The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>"));
|
||||
dialog->registerWidgetHelp(m_ui.eeDivRoundingMode, tr("Division Rounding Mode"), tr("Nearest (Default)"), tr("Determines how the results of floating-point division is rounded. Some games need specific settings; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>"));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.eeClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr("Changes how PCSX2 handles keeping floats in a standard x86 range. "
|
||||
"The default value handles the vast majority of games; <b>modifying this setting when a game is not having a visible problem can cause instability.</b>"));
|
||||
|
||||
@@ -95,13 +95,44 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string extracomment="Rounding refers here to the mathematical term.">Division Rounding Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="eeDivRoundingMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Nearest (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Negative</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Positive</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Chop/Zero</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string extracomment="Clamping: Forcing out of bounds things in bounds by changing them to the closest possible value. In this case, this refers to clamping large PS2 floating point values (which map to infinity or NaN in PCs' IEEE754 floats) to non-infinite ones.">Clamping Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="eeClampMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
@@ -125,7 +156,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="eeWaitLoopDetection">
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ControllerBindingWidget_Popn</class>
|
||||
<widget class="QWidget" name="ControllerBindingWidget_Popn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1232</width>
|
||||
<height>644</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_35">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="2" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>266</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/resources.qrc">:/images/Popn.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_27">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_21">
|
||||
<property name="title">
|
||||
<string extracomment="Leave this button name as-is or uppercase it entirely.">Select</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Select">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_22">
|
||||
<property name="title">
|
||||
<string>Yellow (Left)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="YellowL">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_24">
|
||||
<property name="title">
|
||||
<string>Yellow (Right)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="YellowR">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_26">
|
||||
<property name="title">
|
||||
<string>Blue (Right)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_26">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="BlueR">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_25">
|
||||
<property name="title">
|
||||
<string>Blue (Left)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_25">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="BlueL">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_23">
|
||||
<property name="title">
|
||||
<string extracomment="Leave this button name as-is or uppercase it entirely.">Start</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Start">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_32">
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_34">
|
||||
<property name="title">
|
||||
<string>Red</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_34">
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Red">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="5">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_28">
|
||||
<property name="title">
|
||||
<string>Green (Right)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_29">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="GreenR">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_27">
|
||||
<property name="title">
|
||||
<string>White (Left)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_28">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="WhiteL">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_29">
|
||||
<property name="title">
|
||||
<string>Green (Left)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_30">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="GreenL">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QGroupBox" name="groupBox_30">
|
||||
<property name="title">
|
||||
<string>White (Right)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_31">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="WhiteR">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -108,6 +108,10 @@ void ControllerBindingWidget::onTypeChanged()
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
|
||||
}
|
||||
else if (cinfo->type == Pad::ControllerType::Popn)
|
||||
{
|
||||
m_bindings_widget = ControllerBindingWidget_Popn::createInstance(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bindings_widget = new ControllerBindingWidget_Base(this);
|
||||
@@ -897,6 +901,27 @@ ControllerBindingWidget_Base* ControllerBindingWidget_Guitar::createInstance(Con
|
||||
return new ControllerBindingWidget_Guitar(parent);
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Popn::ControllerBindingWidget_Popn(ControllerBindingWidget* parent)
|
||||
: ControllerBindingWidget_Base(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
initBindingWidgets();
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Popn::~ControllerBindingWidget_Popn()
|
||||
{
|
||||
}
|
||||
|
||||
QIcon ControllerBindingWidget_Popn::getIcon() const
|
||||
{
|
||||
return QIcon::fromTheme("Popn-line");
|
||||
}
|
||||
|
||||
ControllerBindingWidget_Base* ControllerBindingWidget_Popn::createInstance(ControllerBindingWidget* parent)
|
||||
{
|
||||
return new ControllerBindingWidget_Popn(parent);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
USBDeviceWidget::USBDeviceWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "ui_ControllerBindingWidget.h"
|
||||
#include "ui_ControllerBindingWidget_DualShock2.h"
|
||||
#include "ui_ControllerBindingWidget_Guitar.h"
|
||||
#include "ui_ControllerBindingWidget_Popn.h"
|
||||
#include "ui_ControllerMacroWidget.h"
|
||||
#include "ui_ControllerMacroEditWidget.h"
|
||||
#include "ui_USBDeviceWidget.h"
|
||||
@@ -199,6 +200,22 @@ private:
|
||||
Ui::ControllerBindingWidget_Guitar m_ui;
|
||||
};
|
||||
|
||||
class ControllerBindingWidget_Popn final : public ControllerBindingWidget_Base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ControllerBindingWidget_Popn(ControllerBindingWidget* parent);
|
||||
~ControllerBindingWidget_Popn();
|
||||
|
||||
QIcon getIcon() const override;
|
||||
|
||||
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
|
||||
|
||||
private:
|
||||
Ui::ControllerBindingWidget_Popn m_ui;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class USBDeviceWidget final : public QWidget
|
||||
|
||||
@@ -17,12 +17,12 @@ GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
: m_dialog(dialog)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
QtUtils::ResizeColumnsForTreeView(m_ui.cheatList, {300, 100, -1});
|
||||
|
||||
reloadList();
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableCheats, "EmuCore", "EnableCheats", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.allCRCsCheckbox, "EmuCore", "ShowCheatsForAllCRCs", false);
|
||||
updateListEnabled();
|
||||
|
||||
connect(m_ui.enableCheats, &QCheckBox::stateChanged, this, &GameCheatSettingsWidget::updateListEnabled);
|
||||
@@ -31,6 +31,10 @@ GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
connect(m_ui.reloadCheats, &QPushButton::clicked, this, &GameCheatSettingsWidget::onReloadClicked);
|
||||
connect(m_ui.enableAll, &QPushButton::clicked, this, [this]() { setStateForAll(true); });
|
||||
connect(m_ui.disableAll, &QPushButton::clicked, this, [this]() { setStateForAll(false); });
|
||||
connect(m_ui.allCRCsCheckbox, &QCheckBox::stateChanged, this, &GameCheatSettingsWidget::onReloadClicked);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.allCRCsCheckbox, tr("Show Cheats For All CRCs"), tr("Checked"),
|
||||
tr("Toggles scanning patch files for all CRCs of the game. With this enabled available patches for the game serial with different CRCs will also be loaded."));
|
||||
}
|
||||
|
||||
GameCheatSettingsWidget::~GameCheatSettingsWidget() = default;
|
||||
@@ -78,6 +82,20 @@ void GameCheatSettingsWidget::updateListEnabled()
|
||||
m_ui.enableAll->setEnabled(cheats_enabled);
|
||||
m_ui.disableAll->setEnabled(cheats_enabled);
|
||||
m_ui.reloadCheats->setEnabled(cheats_enabled);
|
||||
m_ui.allCRCsCheckbox->setEnabled(cheats_enabled);
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::disableAllCheats()
|
||||
{
|
||||
SettingsInterface* si = m_dialog->getSettingsInterface();
|
||||
si->ClearSection(Patch::CHEATS_CONFIG_SECTION);
|
||||
si->Save();
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
QtUtils::ResizeColumnsForTreeView(m_ui.cheatList, {320, 100, -1});
|
||||
}
|
||||
|
||||
void GameCheatSettingsWidget::setCheatEnabled(std::string name, bool enabled, bool save_and_reload_settings)
|
||||
@@ -138,7 +156,8 @@ void GameCheatSettingsWidget::setStateRecursively(QTreeWidgetItem* parent, bool
|
||||
void GameCheatSettingsWidget::reloadList()
|
||||
{
|
||||
u32 num_unlabelled_codes = 0;
|
||||
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, &num_unlabelled_codes);
|
||||
bool showAllCRCS = m_ui.allCRCsCheckbox->isChecked();
|
||||
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, showAllCRCS, & num_unlabelled_codes);
|
||||
m_enabled_patches =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Patch::CHEATS_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
|
||||
@@ -30,11 +30,17 @@ public:
|
||||
GameCheatSettingsWidget(SettingsWindow* dialog, QWidget* parent);
|
||||
~GameCheatSettingsWidget();
|
||||
|
||||
void disableAllCheats();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCheatListItemDoubleClicked(QTreeWidgetItem* item, int column);
|
||||
void onCheatListItemChanged(QTreeWidgetItem* item, int column);
|
||||
void onReloadClicked();
|
||||
void updateListEnabled();
|
||||
void reloadList();
|
||||
|
||||
private:
|
||||
QTreeWidgetItem* getTreeWidgetParent(const std::string_view& parent);
|
||||
@@ -42,7 +48,6 @@ private:
|
||||
void setCheatEnabled(std::string name, bool enabled, bool save_and_reload_settings);
|
||||
void setStateForAll(bool enabled);
|
||||
void setStateRecursively(QTreeWidgetItem* parent, bool enabled);
|
||||
void reloadList();
|
||||
|
||||
Ui::GameCheatSettingsWidget m_ui;
|
||||
SettingsWindow* m_dialog;
|
||||
|
||||
@@ -84,6 +84,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="allCRCsCheckbox">
|
||||
<property name="text">
|
||||
<string>All CRCs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -18,7 +18,6 @@ GameFixSettingsWidget::GameFixSettingsWidget(SettingsWindow* dialog, QWidget* pa
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
|
||||
@@ -38,7 +37,6 @@ GameFixSettingsWidget::GameFixSettingsWidget(SettingsWindow* dialog, QWidget* pa
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.BlitInternalFPSHack, "EmuCore/Gamefixes", "BlitInternalFPSHack", false);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.FpuMulHack, tr("FPU Multiply Hack"), tr("Unchecked"), tr("For Tales of Destiny."));
|
||||
dialog->registerWidgetHelp(m_ui.FpuNegDivHack, tr("FPU Negative Divide Hack"), tr("Unchecked"), tr("For Gundam Games."));
|
||||
dialog->registerWidgetHelp(m_ui.GoemonTlbHack, tr("Preload TLB Hack"), tr("Unchecked"), tr("To avoid TLB miss on Goemon."));
|
||||
dialog->registerWidgetHelp(m_ui.SoftwareRendererFMVHack, tr("Use Software Renderer For FMVs"), tr("Unchecked"), tr("Needed for some games with complex FMV rendering."));
|
||||
dialog->registerWidgetHelp(m_ui.SkipMPEGHack, tr("Skip MPEG Hack"), tr("Unchecked"), tr("Skips videos/FMVs in games to avoid game hanging/freezes."));
|
||||
|
||||
@@ -56,13 +56,6 @@
|
||||
<string>Game Fixes (NOT recommended to change globally)</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="FpuNegDivHack">
|
||||
<property name="text">
|
||||
<string extracomment="FPU = Floating Point Unit. A part of the PS2's CPU. Do not translate.\nNegative Divide: mathematical term.\nGundam: a multimedia franchise name. Leave as-is or use an official translation.">FPU Negative Divide Hack</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="FpuMulHack">
|
||||
<property name="text">
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "Settings/GamePatchSettingsWidget.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "Settings/SettingsWindow.h"
|
||||
|
||||
#include "pcsx2/GameList.h"
|
||||
@@ -56,7 +57,14 @@ GamePatchSettingsWidget::GamePatchSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
|
||||
setUnlabeledPatchesWarningVisibility(false);
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.allCRCsCheckbox, "EmuCore", "ShowPatchesForAllCRCs", false);
|
||||
|
||||
connect(m_ui.reload, &QPushButton::clicked, this, &GamePatchSettingsWidget::onReloadClicked);
|
||||
connect(m_ui.allCRCsCheckbox, &QCheckBox::stateChanged, this, &GamePatchSettingsWidget::reloadList);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.allCRCsCheckbox, tr("Show Patches For All CRCs"), tr("Checked"),
|
||||
tr("Toggles scanning patch files for all CRCs of the game. With this enabled available patches for the game serial with different CRCs will also be loaded."));
|
||||
|
||||
reloadList();
|
||||
}
|
||||
@@ -71,11 +79,19 @@ void GamePatchSettingsWidget::onReloadClicked()
|
||||
g_emu_thread->reloadPatches();
|
||||
}
|
||||
|
||||
void GamePatchSettingsWidget::disableAllPatches()
|
||||
{
|
||||
SettingsInterface* si = m_dialog->getSettingsInterface();
|
||||
si->ClearSection(Patch::PATCHES_CONFIG_SECTION);
|
||||
si->Save();
|
||||
}
|
||||
|
||||
void GamePatchSettingsWidget::reloadList()
|
||||
{
|
||||
// Patches shouldn't have any unlabelled patch groups, because they're new.
|
||||
u32 number_of_unlabeled_patches = 0;
|
||||
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), false, &number_of_unlabeled_patches);
|
||||
bool showAllCRCS = m_ui.allCRCsCheckbox->isChecked();
|
||||
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), false, showAllCRCS, &number_of_unlabeled_patches);
|
||||
std::vector<std::string> enabled_list =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
@@ -121,6 +137,7 @@ void GamePatchSettingsWidget::reloadList()
|
||||
m_ui.scrollArea->setWidget(container);
|
||||
}
|
||||
|
||||
void GamePatchSettingsWidget::setUnlabeledPatchesWarningVisibility(bool visible) {
|
||||
void GamePatchSettingsWidget::setUnlabeledPatchesWarningVisibility(bool visible)
|
||||
{
|
||||
m_ui.unlabeledPatchWarning->setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class GamePatchSettingsWidget : public QWidget
|
||||
|
||||
public:
|
||||
GamePatchSettingsWidget(SettingsWindow* dialog, QWidget* parent);
|
||||
void disableAllPatches();
|
||||
~GamePatchSettingsWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
@@ -52,6 +52,19 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="allCRCsCheckbox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>All CRCs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -694,7 +694,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
"<b>If unsure, leave it on default.<b>"));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.videoCaptureBitrate, tr("Video Bitrate"), tr("6000 Kbps"), tr("Sets the video bitrate to be used."
|
||||
dialog->registerWidgetHelp(m_ui.videoCaptureBitrate, tr("Video Bitrate"), tr("6000 kbps"), tr("Sets the video bitrate to be used. "
|
||||
|
||||
"Larger bitrate generally yields better video quality at the cost of larger resulting file size."));
|
||||
|
||||
@@ -714,7 +714,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
"<b>If unsure, leave it on default.<b>"));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.audioCaptureBitrate, tr("Audio Bitrate"), tr("160 Kbps"), tr("Sets the audio bitrate to be used."));
|
||||
dialog->registerWidgetHelp(m_ui.audioCaptureBitrate, tr("Audio Bitrate"), tr("160 kbps"), tr("Sets the audio bitrate to be used."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.enableAudioCaptureArguments, tr("Enable Extra Audio Arguments"), tr("Unchecked"), tr("Allows you to pass arguments to the selected audio codec."));
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ void MemoryCardConvertDialog::ConvertCard()
|
||||
while (m_srcCardInfo.type == MemoryCardType::File ? FileSystem::DirectoryExists(Path::Combine(EmuFolders::MemoryCards, destName.toStdString()).c_str()) : FileSystem::FileExists(Path::Combine(EmuFolders::MemoryCards, destName.toStdString()).c_str()))
|
||||
{
|
||||
destName = baseName;
|
||||
destName.append(StringUtil::StdStringFromFormat("_%02d.ps2", ++num).c_str());
|
||||
destName.append(StringUtil::StdStringFromFormat("_%02zd.ps2", ++num).c_str());
|
||||
}
|
||||
|
||||
m_destCardName = destName;
|
||||
|
||||
@@ -314,6 +314,9 @@ void SettingsWindow::onClearSettingsClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
m_game_cheat_settings_widget->disableAllCheats();
|
||||
m_game_patch_settings_widget->disableAllPatches();
|
||||
|
||||
Pcsx2Config::ClearConfiguration(m_sif.get());
|
||||
m_sif->Save();
|
||||
g_emu_thread->reloadGameSettings();
|
||||
|
||||
@@ -203,7 +203,7 @@ void SetupWizardDialog::themeChanged()
|
||||
void SetupWizardDialog::languageChanged()
|
||||
{
|
||||
// Skip the recreation, since we don't have many dynamic UI elements.
|
||||
QtHost::InstallTranslator();
|
||||
QtHost::InstallTranslator(this);
|
||||
m_ui.retranslateUi(this);
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -476,9 +476,14 @@ void QtHost::SetStyleFromSettings()
|
||||
}
|
||||
}
|
||||
|
||||
void QtHost::SetIconThemeFromStyle()
|
||||
bool QtHost::IsDarkApplicationTheme()
|
||||
{
|
||||
QPalette palette = qApp->palette();
|
||||
bool dark = palette.windowText().color().value() > palette.window().color().value();
|
||||
return (palette.windowText().color().value() > palette.window().color().value());
|
||||
}
|
||||
|
||||
void QtHost::SetIconThemeFromStyle()
|
||||
{
|
||||
const bool dark = IsDarkApplicationTheme();
|
||||
QIcon::setThemeName(dark ? QStringLiteral("white") : QStringLiteral("black"));
|
||||
}
|
||||
|
||||
+93
-69
File diff suppressed because one or more lines are too long
+2044
-1624
File diff suppressed because it is too large
Load Diff
@@ -89,6 +89,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ColorPickerButton.cpp" />
|
||||
<ClCompile Include="EarlyHardwareCheck.cpp" />
|
||||
<ClCompile Include="LogWindow.cpp" />
|
||||
<ClCompile Include="QtProgressCallback.cpp" />
|
||||
<ClCompile Include="Settings\DebugSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\FolderSettingsWidget.cpp" />
|
||||
@@ -108,6 +109,7 @@
|
||||
<ClCompile Include="Debugger\Models\BreakpointModel.cpp" />
|
||||
<ClCompile Include="Debugger\Models\ThreadModel.cpp" />
|
||||
<ClCompile Include="Debugger\Models\StackModel.cpp" />
|
||||
<ClCompile Include="Debugger\Models\SavedAddressesModel.cpp" />
|
||||
<ClCompile Include="Settings\BIOSSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\ControllerBindingWidgets.cpp" />
|
||||
<ClCompile Include="Settings\ControllerGlobalSettingsWidget.cpp" />
|
||||
@@ -171,6 +173,7 @@
|
||||
<QtMoc Include="Settings\DEV9UiCommon.h" />
|
||||
<QtMoc Include="QtProgressCallback.h" />
|
||||
<QtMoc Include="ColorPickerButton.h" />
|
||||
<QtMoc Include="LogWindow.h" />
|
||||
<ClInclude Include="Settings\ControllerSettingWidgetBinder.h" />
|
||||
<QtMoc Include="Settings\FolderSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\DebugSettingsWidget.h" />
|
||||
@@ -196,6 +199,7 @@
|
||||
<QtMoc Include="Debugger\Models\BreakpointModel.h" />
|
||||
<QtMoc Include="Debugger\Models\ThreadModel.h" />
|
||||
<QtMoc Include="Debugger\Models\StackModel.h" />
|
||||
<QtMoc Include="Debugger\Models\SavedAddressesModel.h" />
|
||||
<QtMoc Include="Settings\ControllerBindingWidgets.h" />
|
||||
<QtMoc Include="Settings\ControllerGlobalSettingsWidget.h" />
|
||||
<ClInclude Include="Settings\MemoryCardConvertWorker.h" />
|
||||
@@ -251,6 +255,7 @@
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_BreakpointModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_ThreadModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_StackModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_SavedAddressesModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListModel.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListRefreshThread.cpp" />
|
||||
<ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" />
|
||||
@@ -259,6 +264,7 @@
|
||||
<ClCompile Include="$(IntDir)moc_ColorPickerButton.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_CoverDownloadDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_DisplayWidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_LogWindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_MainWindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_QtHost.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_QtProgressCallback.cpp" />
|
||||
@@ -419,9 +425,10 @@
|
||||
<QtUi Include="Settings\ControllerMacroWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<None Include="Settings\ControllerBindingWidget_Popn.ui" />
|
||||
<None Include="Settings\FolderSettingsWidget.ui" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(SolutionDir)common\vsprops\QtCompile.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -287,6 +287,9 @@
|
||||
<ClCompile Include="Debugger\Models\StackModel.cpp">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\Models\SavedAddressesModel.cpp">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)Debugger\moc_CpuWidget.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
@@ -314,6 +317,9 @@
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_StackModel.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)Debugger\Models\moc_SavedAddressesModel.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ColorPickerButton.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_ColorPickerButton.cpp">
|
||||
<Filter>moc</Filter>
|
||||
@@ -336,6 +342,10 @@
|
||||
<ClCompile Include="$(IntDir)moc_SetupWizardDialog.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LogWindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_LogWindow.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
|
||||
@@ -482,6 +492,9 @@
|
||||
<QtMoc Include="Debugger\Models\StackModel.h">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Debugger\Models\SavedAddressesModel.h">
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="ColorPickerButton.h" />
|
||||
<QtMoc Include="SetupWizardDialog.h" />
|
||||
<QtMoc Include="Settings\GameCheatSettingsWidget.h">
|
||||
@@ -490,6 +503,7 @@
|
||||
<QtMoc Include="Settings\GamePatchSettingsWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="LogWindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtResource Include="resources\resources.qrc">
|
||||
@@ -638,6 +652,9 @@
|
||||
<None Include="Settings\FolderSettingsWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</None>
|
||||
<None Include="Settings\ControllerBindingWidget_Popn.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtTs Include="Translations\pcsx2-qt_en.ts">
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="pop_icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 150 150" style="enable-background:new 0 0 150 150;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#1D1D1B;}
|
||||
</style>
|
||||
<g id="by_maxihplay">
|
||||
<path class="st0" d="M146.9,100.4l-0.1-0.3L131.5,43c-1.2-6.7-6.9-9.5-13.8-9.5H32.3c-6.8,0-12.6,2.8-13.8,9.5L3.3,99.8l-0.1,0.7
|
||||
c-0.6,4,0.6,8.1,3.2,11.2s6.5,4.9,10.6,4.9H133c4.1,0,7.9-1.8,10.6-4.9C146.3,108.6,147.5,104.5,146.9,100.4L146.9,100.4z M54.5,44
|
||||
c0.7-2.5,2.8-3.4,4.8-2.9s3.2,2.7,2.7,4.8c-0.8,2.9-6.2,7.8-6.2,7.8S53.7,47,54.5,44z M41.4,49c0.8-2.9,6.2-7.8,6.2-7.8
|
||||
s2.1,6.8,1.2,9.8c-0.7,2.5-2.8,3.4-4.8,2.9S40.8,51.1,41.4,49z M23.7,105.3c-5.5,0-10-4.5-10-10s4.5-10,10-10s10,4.5,10,10
|
||||
S29.2,105.3,23.7,105.3z M26.5,70.4c0-5.5,4.5-10,10-10s10,4.5,10,10s-4.5,10-10,10S26.5,76,26.5,70.4z M49.3,105.3
|
||||
c-5.5,0-10-4.5-10-10s4.5-10,10-10s10,4.5,10,10S54.9,105.3,49.3,105.3z M52.2,70.4c0-5.5,4.5-10,10-10s10,4.5,10,10s-4.5,10-10,10
|
||||
S52.2,76,52.2,70.4z M75,105.3c-5.5,0-10-4.5-10-10s4.5-10,10-10s10,4.5,10,10S80.5,105.3,75,105.3z M77.8,70.4c0-5.5,4.5-10,10-10
|
||||
s10,4.5,10,10s-4.5,10-10,10S77.8,76,77.8,70.4z M100.7,105.3c-5.5,0-10-4.5-10-10s4.5-10,10-10s10,4.5,10,10
|
||||
S106.2,105.3,100.7,105.3z M103.5,70.4c0-5.5,4.5-10,10-10s10,4.5,10,10s-4.5,10-10,10S103.5,76,103.5,70.4z M126.3,105.3
|
||||
c-5.5,0-10-4.5-10-10s4.5-10,10-10s10,4.5,10,10S131.9,105.3,126.3,105.3z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="pop_icon" data-name="pop icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="by_maxihplay" data-name="by maxihplay">
|
||||
<path class="cls-1" d="m146.87,100.43l-.05-.33-15.35-57.11c-1.2-6.7-6.93-9.52-13.77-9.52H32.3c-6.84,0-12.57,2.82-13.77,9.52L3.26,99.78l-.14.66c-.61,4.04.56,8.13,3.22,11.22,2.66,3.09,6.53,4.87,10.61,4.87h116.08c4.08,0,7.95-1.78,10.61-4.87,2.66-3.1,3.84-7.19,3.22-11.22h0ZM54.53,44.05c.72-2.55,2.75-3.39,4.82-2.86s3.25,2.68,2.66,4.78c-.83,2.93-6.23,7.85-6.23,7.85,0,0-2.08-6.83-1.25-9.77Zm-13.1,4.99c.83-2.93,6.23-7.85,6.23-7.85,0,0,2.08,6.83,1.25,9.77-.72,2.55-2.75,3.39-4.82,2.86s-3.25-2.68-2.66-4.78Zm-17.76,56.24c-5.52,0-10.01-4.49-10.01-10.01s4.49-10.01,10.01-10.01,10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01Zm2.83-34.83c0-5.52,4.49-10.01,10.01-10.01s10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01-10.01-4.49-10.01-10.01Zm22.84,34.83c-5.52,0-10.01-4.49-10.01-10.01s4.49-10.01,10.01-10.01,10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01Zm2.83-34.83c0-5.52,4.49-10.01,10.01-10.01s10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01-10.01-4.49-10.01-10.01Zm22.84,34.83c-5.52,0-10.01-4.49-10.01-10.01s4.49-10.01,10.01-10.01,10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01Zm2.83-34.83c0-5.52,4.49-10.01,10.01-10.01s10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01-10.01-4.49-10.01-10.01Zm22.84,34.83c-5.52,0-10.01-4.49-10.01-10.01s4.49-10.01,10.01-10.01,10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01Zm2.83-34.83c0-5.52,4.49-10.01,10.01-10.01s10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01-10.01-4.49-10.01-10.01Zm22.84,34.83c-5.52,0-10.01-4.49-10.01-10.01s4.49-10.01,10.01-10.01,10.01,4.49,10.01,10.01-4.49,10.01-10.01,10.01Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,198 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Musica_pop" data-name="Musica pop" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 550">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-2, .cls-3, .cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #ffcf1f;
|
||||
}
|
||||
|
||||
.cls-5, .cls-6, .cls-7, .cls-8, .cls-9, .cls-10, .cls-11, .cls-12, .cls-13, .cls-14, .cls-15, .cls-16, .cls-17 {
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
|
||||
.cls-5, .cls-8, .cls-9, .cls-10, .cls-12, .cls-13, .cls-14 {
|
||||
stroke: #4d4d4d;
|
||||
}
|
||||
|
||||
.cls-5, .cls-8, .cls-9, .cls-10, .cls-12, .cls-13, .cls-14, .cls-17 {
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.cls-18 {
|
||||
letter-spacing: -.02em;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
stroke: #ff553f;
|
||||
}
|
||||
|
||||
.cls-6, .cls-7, .cls-11, .cls-15, .cls-16 {
|
||||
stroke-width: 17px;
|
||||
}
|
||||
|
||||
.cls-6, .cls-7, .cls-11, .cls-15, .cls-16, .cls-17 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-19 {
|
||||
letter-spacing: -.06em;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
stroke: #109400;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #f40600;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
opacity: .24;
|
||||
}
|
||||
|
||||
.cls-20 {
|
||||
letter-spacing: -.01em;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #0028b4;
|
||||
}
|
||||
|
||||
.cls-21 {
|
||||
fill: #bdbdbd;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
stroke: #0052f4;
|
||||
}
|
||||
|
||||
.cls-12 {
|
||||
fill: #f0f0f0;
|
||||
}
|
||||
|
||||
.cls-22 {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.cls-13 {
|
||||
fill: #00741a;
|
||||
}
|
||||
|
||||
.cls-14 {
|
||||
fill: #f5f5f5;
|
||||
}
|
||||
|
||||
.cls-23 {
|
||||
letter-spacing: 0em;
|
||||
}
|
||||
|
||||
.cls-15 {
|
||||
stroke: #ffed9f;
|
||||
}
|
||||
|
||||
.cls-16 {
|
||||
stroke: #f5f5f5;
|
||||
}
|
||||
|
||||
.cls-24 {
|
||||
opacity: .36;
|
||||
}
|
||||
|
||||
.cls-25 {
|
||||
fill: #d1d1d1;
|
||||
stroke: #000;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 4px;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
opacity: .31;
|
||||
}
|
||||
|
||||
.cls-26 {
|
||||
fill: #7f001c;
|
||||
}
|
||||
|
||||
.cls-27 {
|
||||
font-family: Roboto-Black, Roboto;
|
||||
font-size: 13.24px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.cls-28 {
|
||||
letter-spacing: -.03em;
|
||||
}
|
||||
|
||||
.cls-17 {
|
||||
opacity: .49;
|
||||
stroke: #8a8a8a;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="By_Maxihplay" data-name="By Maxihplay">
|
||||
<path id="fundo_controle" data-name="fundo controle" class="cls-25" d="m732.99,503.41H107.01c-56.55,0-99.5-59.99-84.64-118.79L96.46,120.83c9.61-38.01,50.78-74.24,92.46-74.24h462.16c41.67,0,82.85,36.23,92.46,74.24l74.09,263.79c14.87,58.8-28.09,118.79-84.64,118.79Z"/>
|
||||
<g id="sombra_inferior" data-name="sombra inferior">
|
||||
<path class="cls-21" d="m757.16,177.42l40.52,186.36c8.83,58.35-28.4,86.84-82.82,86.84H125.3c-54.41,0-91.21-34.06-82.82-86.84l40.19-186.36-58.02,205.29c-14.78,57.64,27.99,116.64,84.22,116.64h622.4c56.24,0,99.01-58.99,84.22-116.64l-58.35-205.29Z"/>
|
||||
<line class="cls-17" x1="531.04" y1="451.07" x2="308.96" y2="451.07"/>
|
||||
</g>
|
||||
<g id="botoes_cores" data-name="botoes cores">
|
||||
<g id="baixo">
|
||||
<ellipse class="cls-13" cx="276.31" cy="363.27" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-8" cx="420" cy="363.27" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-13" cx="563.69" cy="363.27" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-12" cx="707.38" cy="363.27" rx="58.13" ry="58.86"/>
|
||||
<path class="cls-12" d="m132.62,304.41c-19.2,0-36.22,9.42-46.81,23.95-7.12,9.77-11.33,21.84-11.33,34.91,0,32.51,26.03,58.86,58.13,58.86s58.13-26.35,58.13-58.86-26.03-58.86-58.13-58.86Z"/>
|
||||
</g>
|
||||
<g id="cima">
|
||||
<ellipse class="cls-10" cx="348.16" cy="223.49" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-10" cx="491.84" cy="223.49" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-5" cx="635.53" cy="223.49" rx="58.13" ry="58.86"/>
|
||||
<ellipse class="cls-5" cx="204.47" cy="223.49" rx="58.13" ry="58.86"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="brilho">
|
||||
<g id="brilho_menor" data-name="brilho menor" class="cls-24">
|
||||
<ellipse class="cls-16" cx="157.67" cy="372.04" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-7" cx="301.63" cy="372.04" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-6" cx="445.59" cy="372.04" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-7" cx="589.55" cy="372.04" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-16" cx="733.5" cy="372.74" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-15" cx="661.52" cy="241.42" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-11" cx="517.57" cy="241.42" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-11" cx="373.61" cy="241.42" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-15" cx="229.65" cy="241.42" rx="9.35" ry="9.47"/>
|
||||
</g>
|
||||
<g id="brilho_maior" data-name="brilho maior" class="cls-22">
|
||||
<ellipse class="cls-1" cx="160.94" cy="374.24" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-3" cx="304.9" cy="374.24" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-3" cx="448.86" cy="374.24" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-3" cx="592.81" cy="374.24" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-1" cx="736.77" cy="374.95" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-2" cx="664.79" cy="243.62" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-4" cx="520.84" cy="243.62" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-4" cx="376.88" cy="243.62" rx="9.35" ry="9.47"/>
|
||||
<ellipse class="cls-2" cx="232.92" cy="243.62" rx="9.35" ry="9.47"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="botoes_gota" data-name="botoes gota">
|
||||
<g id="botao">
|
||||
<path id="B" class="cls-9" d="m319.86,101.2c-4.93-3.86-15.2-.94-20.32,6.55-4.61,6.75-7.36,23.1-8.33,29.84-.19,1.33,1.02,2.27,2.16,1.66,5.72-3.04,19.42-10.78,24.03-17.53,4.21-6.15,7.4-16.67,2.47-20.53Z"/>
|
||||
<path id="B-2" data-name="B" class="cls-14" d="m317.84,99.05c-4.93-3.86-11.46-3.28-16.58,4.21-4.02,5.88-6.62,19.05-7.87,26.8-.43,2.67,2.02,4.55,4.28,3.3,6.53-3.62,17.43-10.25,21.44-16.12,4.21-6.15,3.66-14.32-1.27-18.18Z"/>
|
||||
<path id="A" class="cls-9" d="m246.17,118.73c-4.21,6.15-3.66,14.32,1.27,18.18,4.93,3.86,11.46,3.28,16.58-4.21,4.76-6.97,7.54-24.16,8.42-30.46.14-1-.91-1.74-1.81-1.27-5.43,2.86-19.73,10.84-24.46,17.76Z"/>
|
||||
<path id="A-2" data-name="A" class="cls-14" d="m246.89,114.24c-4.21,6.15-3.66,14.32,1.27,18.18,4.93,3.86,11.46,3.28,16.58-4.21,4.35-6.36,7.04-21.23,8.15-28.57.29-1.89-1.44-3.22-3.05-2.35-6.21,3.36-18.61,10.6-22.95,16.95Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<text class="cls-27" transform="translate(202.5 90.95) scale(.99 1)"><tspan x="0" y="0">SELE</tspan><tspan class="cls-20" x="30.28" y="0">C</tspan><tspan class="cls-28" x="38.78" y="0">T</tspan></text>
|
||||
<text class="cls-27" transform="translate(325.6 142.14) scale(.99 1)"><tspan x="0" y="0">S</tspan><tspan class="cls-19" x="8.29" y="0">T</tspan><tspan class="cls-23" x="15.86" y="0">A</tspan><tspan class="cls-18" x="24.88" y="0">R</tspan><tspan class="cls-28" x="33.19" y="0">T</tspan></text>
|
||||
<path id="marca" class="cls-26" d="m634.86,89.41l-33.84,33.94c-5.57,5.59-14.02,8.85-22.96,8.85h-125.09l2-42.78h179.89Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
@@ -68,6 +68,7 @@
|
||||
<file>icons/black/svg/pause-line.svg</file>
|
||||
<file>icons/black/svg/play-line.svg</file>
|
||||
<file>icons/black/svg/plus-line.svg</file>
|
||||
<file>icons/black/svg/Popn-line.svg</file>
|
||||
<file>icons/black/svg/price-tag-3-line.svg</file>
|
||||
<file>icons/black/svg/printer-line.svg</file>
|
||||
<file>icons/black/svg/refresh-line.svg</file>
|
||||
@@ -161,6 +162,7 @@
|
||||
<file>icons/white/svg/pause-line.svg</file>
|
||||
<file>icons/white/svg/play-line.svg</file>
|
||||
<file>icons/white/svg/plus-line.svg</file>
|
||||
<file>icons/white/svg/Popn-line.svg</file>
|
||||
<file>icons/white/svg/price-tag-3-line.svg</file>
|
||||
<file>icons/white/svg/printer-line.svg</file>
|
||||
<file>icons/white/svg/refresh-line.svg</file>
|
||||
@@ -186,5 +188,6 @@
|
||||
<file>images/DualShock_2.svg</file>
|
||||
<file>images/GT_Force.svg</file>
|
||||
<file>images/Guitar.svg</file>
|
||||
<file>images/Popn.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1027,7 +1027,7 @@ void Achievements::DisplayAchievementSummary()
|
||||
|
||||
// Technically not going through the resource API, but since we're passing this to something else, we can't.
|
||||
if (EmuConfig.Achievements.SoundEffects)
|
||||
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, INFO_SOUND_NAME).c_str());
|
||||
Common::PlaySoundAsync(EmuFolders::GetOverridableResourcePath(INFO_SOUND_NAME).c_str());
|
||||
}
|
||||
|
||||
void Achievements::DisplayHardcoreDeferredMessage()
|
||||
@@ -1079,7 +1079,7 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
|
||||
}
|
||||
|
||||
if (EmuConfig.Achievements.SoundEffects)
|
||||
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, UNLOCK_SOUND_NAME).c_str());
|
||||
Common::PlaySoundAsync(EmuFolders::GetOverridableResourcePath(UNLOCK_SOUND_NAME).c_str());
|
||||
}
|
||||
|
||||
void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
|
||||
@@ -1170,7 +1170,7 @@ void Achievements::HandleLeaderboardSubmittedEvent(const rc_client_event_t* even
|
||||
}
|
||||
|
||||
if (EmuConfig.Achievements.SoundEffects)
|
||||
Common::PlaySoundAsync(Path::Combine(EmuFolders::Resources, LBSUBMIT_SOUND_NAME).c_str());
|
||||
Common::PlaySoundAsync(EmuFolders::GetOverridableResourcePath(LBSUBMIT_SOUND_NAME).c_str());
|
||||
}
|
||||
|
||||
void Achievements::HandleLeaderboardScoreboardEvent(const rc_client_event_t* event)
|
||||
|
||||
+1
-1
@@ -476,7 +476,7 @@ static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::strin
|
||||
if (value.empty() && (lineno == (lines.size() - 1)))
|
||||
{
|
||||
Console.Warning("(SYSTEM.CNF) Unusual or malformed entry in SYSTEM.CNF ignored:");
|
||||
Console.Indent().WriteLn(std::string(line));
|
||||
Console.WarningFmt(" {}", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@ bool DoCDVDopen(Error* error)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string dump_name(Path::StripExtension(m_SourceFilename[CurrentSourceType]));
|
||||
std::string dump_name(Path::GetFileTitle(m_SourceFilename[CurrentSourceType]));
|
||||
if (dump_name.empty())
|
||||
dump_name = "Untitled";
|
||||
|
||||
|
||||
@@ -260,14 +260,12 @@ bool InputIsoFile::Open(std::string srcfile, Error* error, bool testOnly)
|
||||
|
||||
Console.WriteLn(Color_StrongBlue, "isoFile open ok: %s", m_filename.c_str());
|
||||
|
||||
ConsoleIndentScope indent;
|
||||
|
||||
Console.WriteLn("Image type = %s", nameFromType(m_type));
|
||||
//Console.WriteLn("Fileparts = %u", m_numparts); // Pointless print, it's 1 unless it says otherwise above
|
||||
DevCon.WriteLn("blocks = %u", m_blocks);
|
||||
DevCon.WriteLn("offset = %d", m_offset);
|
||||
DevCon.WriteLn("blocksize = %u", m_blocksize);
|
||||
DevCon.WriteLn("blockoffset = %d", m_blockofs);
|
||||
Console.WriteLn(" Image type = %s", nameFromType(m_type));
|
||||
//Console.WriteLn(" Fileparts = %u", m_numparts); // Pointless print, it's 1 unless it says otherwise above
|
||||
DevCon.WriteLn(" blocks = %u", m_blocks);
|
||||
DevCon.WriteLn(" offset = %d", m_offset);
|
||||
DevCon.WriteLn(" blocksize = %u", m_blocksize);
|
||||
DevCon.WriteLn(" blockoffset = %d", m_blockofs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+15
-3
@@ -77,7 +77,6 @@ set(pcsx2Sources
|
||||
HwRead.cpp
|
||||
HwWrite.cpp
|
||||
LayeredSettingsInterface.cpp
|
||||
LogSink.cpp
|
||||
INISettingsInterface.cpp
|
||||
Interpreter.cpp
|
||||
IopBios.cpp
|
||||
@@ -169,7 +168,6 @@ set(pcsx2Headers
|
||||
IopHw.h
|
||||
IopMem.h
|
||||
LayeredSettingsInterface.h
|
||||
LogSink.h
|
||||
PINE.h
|
||||
Mdec.h
|
||||
MTGS.h
|
||||
@@ -195,8 +193,8 @@ set(pcsx2Headers
|
||||
SIO/Memcard/MemoryCardFolder.h
|
||||
SIO/Memcard/MemoryCardProtocol.h
|
||||
SPR.h
|
||||
SupportURLs.h
|
||||
StateWrapper.h
|
||||
SysForwardDefs.h
|
||||
Vif_Dma.h
|
||||
Vif.h
|
||||
Vif_Unpack.h
|
||||
@@ -442,6 +440,7 @@ set(pcsx2PADSources
|
||||
SIO/Pad/PadBase.cpp
|
||||
SIO/Pad/PadDualshock2.cpp
|
||||
SIO/Pad/PadGuitar.cpp
|
||||
SIO/Pad/PadPopn.cpp
|
||||
SIO/Pad/PadNotConnected.cpp
|
||||
)
|
||||
set(pcsx2PADHeaders
|
||||
@@ -449,6 +448,7 @@ set(pcsx2PADHeaders
|
||||
SIO/Pad/PadBase.h
|
||||
SIO/Pad/PadDualshock2.h
|
||||
SIO/Pad/PadGuitar.h
|
||||
SIO/Pad/PadPopn.h
|
||||
SIO/Pad/PadNotConnected.h
|
||||
SIO/Pad/PadTypes.h
|
||||
)
|
||||
@@ -1221,6 +1221,18 @@ function(setup_main_executable target)
|
||||
pcsx2_resource(${target} ${path} ${CMAKE_SOURCE_DIR}/bin/resources/)
|
||||
endforeach()
|
||||
|
||||
# Add docs to resources for not-Windows, since they don't use the bin directory.
|
||||
if(NOT WIN32)
|
||||
file(GLOB_RECURSE DOCS_FILES ${CMAKE_SOURCE_DIR}/bin/docs/*)
|
||||
foreach(path IN LISTS DOCS_FILES)
|
||||
get_filename_component(file ${path} NAME)
|
||||
if("${file}" MATCHES "^\\.") # Don't copy macOS garbage (mainly Finder's .DS_Store files) into application
|
||||
continue()
|
||||
endif()
|
||||
pcsx2_resource(${target} ${path} ${CMAKE_SOURCE_DIR}/bin/)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
get_property(PCSX2_SOURCE_DIR GLOBAL PROPERTY PCSX2_SOURCE_DIR)
|
||||
get_property(PCSX2_METAL_SHADERS GLOBAL PROPERTY PCSX2_METAL_SHADERS)
|
||||
|
||||
|
||||
+4
-9
@@ -14,15 +14,11 @@ namespace
|
||||
union alignas(64) CacheData
|
||||
{
|
||||
u8 bytes[64];
|
||||
|
||||
constexpr CacheData(): bytes{0} {}
|
||||
};
|
||||
|
||||
struct CacheTag
|
||||
{
|
||||
uptr rawValue = 0;
|
||||
|
||||
CacheTag() = default;
|
||||
uptr rawValue;
|
||||
|
||||
// The lower parts of a cache tags structure is as follows:
|
||||
// 31 - 12: The physical address cache tag.
|
||||
@@ -112,7 +108,7 @@ namespace
|
||||
pxAssertMsg(!tag.isDirtyAndValid(), "Loaded a value into cache without writing back the old one!");
|
||||
|
||||
tag.setAddr(ppf);
|
||||
data = *reinterpret_cast<CacheData*>(ppf & ~0x3FULL);
|
||||
std::memcpy(&data, reinterpret_cast<void*>(ppf & ~0x3FULL), sizeof(data));
|
||||
tag.setValid();
|
||||
tag.clearDirty();
|
||||
}
|
||||
@@ -120,7 +116,7 @@ namespace
|
||||
void clear()
|
||||
{
|
||||
tag.clear();
|
||||
data = CacheData();
|
||||
std::memset(&data, 0, sizeof(data));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,8 +141,7 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
static Cache cache;
|
||||
|
||||
static Cache cache = {};
|
||||
}
|
||||
|
||||
void resetCache()
|
||||
|
||||
+6
-4
@@ -153,7 +153,6 @@ enum GamefixId
|
||||
GamefixId_FIRST = 0,
|
||||
|
||||
Fix_FpuMultiply = GamefixId_FIRST,
|
||||
Fix_FpuNegDiv,
|
||||
Fix_GoemonTlbMiss,
|
||||
Fix_SoftwareRendererFMV,
|
||||
Fix_SkipMpeg,
|
||||
@@ -539,6 +538,7 @@ struct Pcsx2Config
|
||||
RecompilerOptions Recompiler;
|
||||
|
||||
FPControlRegister FPUFPCR;
|
||||
FPControlRegister FPUDivFPCR;
|
||||
FPControlRegister VU0FPCR;
|
||||
FPControlRegister VU1FPCR;
|
||||
|
||||
@@ -899,7 +899,6 @@ struct Pcsx2Config
|
||||
BITFIELD32()
|
||||
bool
|
||||
FpuMulHack : 1, // Tales of Destiny hangs.
|
||||
FpuNegDivHack : 1, // Gundam games messed up camera-view.
|
||||
GoemonTlbHack : 1, // Gomeon tlb miss hack. The game need to access unmapped virtual address. Instead to handle it as exception, tlb are preloaded at startup
|
||||
SoftwareRendererFMVHack : 1, // Switches to software renderer for FMVs
|
||||
SkipMPEGHack : 1, // Skips MPEG videos (Katamari and other games need this)
|
||||
@@ -1225,6 +1224,7 @@ namespace EmuFolders
|
||||
extern std::string Cheats;
|
||||
extern std::string Patches;
|
||||
extern std::string Resources;
|
||||
extern std::string UserResources;
|
||||
extern std::string Cache;
|
||||
extern std::string Covers;
|
||||
extern std::string GameSettings;
|
||||
@@ -1241,7 +1241,10 @@ namespace EmuFolders
|
||||
bool EnsureFoldersExist();
|
||||
|
||||
/// Opens the specified log file for writing.
|
||||
std::FILE* OpenLogFile(const std::string_view& name, const char* mode);
|
||||
std::FILE* OpenLogFile(std::string_view name, const char* mode);
|
||||
|
||||
/// Returns the path to a resource file, allowing the user to override it.
|
||||
std::string GetOverridableResourcePath(std::string_view name);
|
||||
} // namespace EmuFolders
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1260,7 +1263,6 @@ namespace EmuFolders
|
||||
//------------ SPECIAL GAME FIXES!!! ---------------
|
||||
#define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
|
||||
#define CHECK_FPUMULHACK (EmuConfig.Gamefixes.FpuMulHack) // Special Fix for Tales of Destiny hangs.
|
||||
#define CHECK_FPUNEGDIVHACK (EmuConfig.Gamefixes.FpuNegDivHack) // Special Fix for Gundam games messed up camera-view.
|
||||
#define CHECK_XGKICKHACK (EmuConfig.Gamefixes.XgKickHack) // Special Fix for Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics.
|
||||
#define CHECK_EETIMINGHACK (EmuConfig.Gamefixes.EETimingHack) // Fix all scheduled events to happen in 1 cycle.
|
||||
#define CHECK_INSTANTDMAHACK (EmuConfig.Gamefixes.InstantDMAHack) // Attempt to finish DMA's instantly, useful for games which rely on cache emulation.
|
||||
|
||||
+1
-1
@@ -417,7 +417,7 @@ void UpdateVSyncRate(bool force)
|
||||
Console.WriteLn(Color_Green, "(UpdateVSyncRate) Mode Changed to %s.", ReportVideoMode());
|
||||
|
||||
if (custom && video_mode_initialized)
|
||||
Console.Indent().WriteLn(Color_StrongGreen, "... with user configured refresh rate: %.02f Hz", vertical_frequency);
|
||||
Console.WriteLn(Color_StrongGreen, " ... with user configured refresh rate: %.02f Hz", vertical_frequency);
|
||||
|
||||
hsyncCounter.CycleT = (hsyncCounter.Mode == MODE_HBLANK) ? vSyncInfo.hBlank : vSyncInfo.hRender;
|
||||
vsyncCounter.CycleT = (vsyncCounter.Mode == MODE_GSBLANK) ?
|
||||
|
||||
+62
-38
@@ -32,15 +32,18 @@ void ATA::WritePaddedString(u8* data, int* index, const std::string& value, u32
|
||||
|
||||
void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
{
|
||||
//PS2 is limited to 32bit size HDD (2TB), however,
|
||||
//PS2 is limited to 48bit size HDD (2TB), however,
|
||||
//we don't yet support 48bit, so limit to 28bit size
|
||||
constexpr u32 maxSize = (1 << 28) - 1; // 128Gb
|
||||
sizeSectors = std::min<u32>(sizeSectors, maxSize);
|
||||
u64 maxSize = (1 << 28) - 1; // 128Gb
|
||||
const u32 nbSectors = std::min<u32>(sizeSectors, maxSize); // nbSectors will hold 28-bit size
|
||||
if (lba48Supported)
|
||||
maxSize = (1ULL << 48) - 1; // 128PiB
|
||||
|
||||
sizeSectors = std::min<u64>(sizeSectors, maxSize);
|
||||
|
||||
constexpr u16 sectorSize = 512;
|
||||
DevCon.WriteLn("DEV9: HddSize : %i", sizeSectors * sectorSize / (1024 * 1024));
|
||||
const u64 nbSectors = sizeSectors;
|
||||
DevCon.WriteLn("DEV9: nbSectors : %i", nbSectors);
|
||||
DevCon.WriteLn("DEV9: sizeSectors : %i", sizeSectors); // SizeSectors will keep 48-bit size
|
||||
|
||||
memset(&identifyData, 0, sizeof(identifyData));
|
||||
//Defualt CHS translation
|
||||
@@ -150,7 +153,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(curMultipleSectorsSetting | (1 << 8))); //word 59
|
||||
//Total number of user addressable logical sectors
|
||||
WriteUInt32(identifyData, &index, static_cast<u32>(nbSectors < 268435456 ? nbSectors : 268435456)); //word 60-61
|
||||
WriteUInt32(identifyData, &index, nbSectors); //word 60-61
|
||||
//DMA modes
|
||||
/*
|
||||
* bits 0-7: Singleword modes supported (0,1,2)
|
||||
@@ -165,19 +168,19 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bits 0-7: Multiword modes supported (0,1,2)
|
||||
* bits 8-15: Transfer mode active
|
||||
*/
|
||||
if (mdmaMode > 0)
|
||||
if (mdmaMode >= 0)
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(0x07 | (1 << (mdmaMode + 8)))); //word 63
|
||||
else
|
||||
WriteUInt16(identifyData, &index, 0x07); //word 63
|
||||
//Bit 0-7-PIO modes supported (0,1,2,3,4)
|
||||
WriteUInt16(identifyData, &index, 0x1F); //word 64 (pio3,4 supported) selection not reported here
|
||||
//Minimum Multiword DMA transfer cycle time per word
|
||||
WriteUInt16(identifyData, &index, 80); //word 65
|
||||
//Manufacturer’s recommended Multiword DMA transfer cycle time
|
||||
WriteUInt16(identifyData, &index, 80); //word 66
|
||||
//Minimum PIO transfer cycle time without flow control
|
||||
//Bits 0-1 PIO modes supported (3,4)
|
||||
WriteUInt16(identifyData, &index, 0x03); //word 64 (pio3,4 supported)
|
||||
//Minimum Multiword DMA transfer cycle time per word, 120ns
|
||||
WriteUInt16(identifyData, &index, 120); //word 65
|
||||
//Manufacturer’s recommended Multiword DMA transfer cycle time, 120ns
|
||||
WriteUInt16(identifyData, &index, 120); //word 66
|
||||
//Minimum PIO transfer cycle time without flow control, 120ns
|
||||
WriteUInt16(identifyData, &index, 120); //word 67
|
||||
//Minimum PIO transfer cycle time with IORDY flow control
|
||||
//Minimum PIO transfer cycle time with IORDY flow control, 120ns
|
||||
WriteUInt16(identifyData, &index, 120); //word 68
|
||||
//Reserved
|
||||
//69-70
|
||||
@@ -188,10 +191,10 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//Reserved
|
||||
//76-79
|
||||
index = 80 * 2;
|
||||
//Major revision number (1-3-Obsolete, 4-7-ATA4-7 supported)
|
||||
//Major revision number (1-3: Obsolete, 4-7: ATA/ATAPI 4-7 supported)
|
||||
WriteUInt16(identifyData, &index, 0x70); //word 80
|
||||
//Minor revision number
|
||||
WriteUInt16(identifyData, &index, 0); //word 81
|
||||
//Minor revision number, 0x18 - ATA/ATAPI-6 T13 1410D revision 0
|
||||
WriteUInt16(identifyData, &index, 0x18); //word 81
|
||||
//Supported Feature Sets (82)
|
||||
/*
|
||||
* bit 0: Smart
|
||||
@@ -211,7 +214,12 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: NOP
|
||||
* bit 15: (Obsolete)
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 5) | /*(1 << 1) | (1 << 10) |*/ 1)); //word 82
|
||||
// clang-format off
|
||||
WriteUInt16(identifyData, &index, ( //word 82
|
||||
(1 << 0) | //Implemented
|
||||
(1 << 5) | //Implemented
|
||||
(1 << 14) //Implemented
|
||||
/*| (1 << 1) | (1 << 10)*/));
|
||||
//Supported Feature Sets (83)
|
||||
/*
|
||||
* bit 0: DOWNLOAD MICROCODE
|
||||
@@ -230,7 +238,12 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 13: FLUSH CACHE EXT
|
||||
* bit 14: 1
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 13) | (1 << 12) /*| (1 << 8)*/ | ((lba48Supported ? 1 : 0) << 10))); //word 83
|
||||
WriteUInt16(identifyData, &index, ( //word 83
|
||||
(lba48Supported << 10) | //user defined
|
||||
(1 << 12) | //Implemented
|
||||
(1 << 13) | //Implemented
|
||||
(1 << 14) //Always one
|
||||
/*| (1 << 8)*/));
|
||||
//Supported Feature Sets (84)
|
||||
/*
|
||||
* bit 0: Smart error logging
|
||||
@@ -247,28 +260,35 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 13: IDLE IMMEDIATE with UNLOAD FEATURE
|
||||
* bit 14: 1
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 1) | 1)); //word 84
|
||||
WriteUInt16(identifyData, &index, ( //word 84
|
||||
(1 << 0) | //Implemented
|
||||
(1 << 1) | //Implemented
|
||||
(1 << 14))); //Always one
|
||||
//Command set/feature enabled/supported (See word 82)
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((fetSmartEnabled << 0) | (fetSecurityEnabled << 1) | (fetWriteCacheEnabled << 5) | (fetHostProtectedAreaEnabled << 10) | (1 << 14))); //Fixed //word 85
|
||||
WriteUInt16(identifyData, &index, ( //word 85
|
||||
(fetSmartEnabled << 0) | //Variable, implemented
|
||||
(fetSecurityEnabled << 1) | //Variable, not implemented
|
||||
(fetWriteCacheEnabled << 5) | //Variable, implemented
|
||||
(fetHostProtectedAreaEnabled << 10)|//Variable, not implemented
|
||||
(1 << 14))); //Always one
|
||||
//Command set/feature enabled/supported (See word 83)
|
||||
// clang-format off
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(
|
||||
WriteUInt16(identifyData, &index, ( //word 86
|
||||
/*(1 << 8) | //SET MAX */
|
||||
((lba48Supported ? 1 : 0) << 10) | //Fixed
|
||||
(1 << 12) | //Fixed
|
||||
(1 << 13))); //Fixed //word 86
|
||||
(lba48Supported << 10) | //user defined
|
||||
(1 << 12) | //Implemented
|
||||
(1 << 13))); //Implemented
|
||||
//Command set/feature enabled/supported (See word 84)
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 1) | 1));
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(
|
||||
(1) | //Fixed
|
||||
((1) << 1))); //Fixed //word 87
|
||||
WriteUInt16(identifyData, &index, ( //word 87
|
||||
(1 << 0) | //Implemented
|
||||
(1 << 1) | //Implemented
|
||||
(1 << 14))); //Fixed
|
||||
// clang-format on
|
||||
//UDMA modes
|
||||
/*
|
||||
* bits 0-7: ultraword modes supported (0,1,2,4,5,6,7)
|
||||
* bits 8-15: Transfer mode active
|
||||
*/
|
||||
if (udmaMode > 0)
|
||||
if (udmaMode >= 0)
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(0x7f | (1 << (udmaMode + 8)))); //word 88
|
||||
else
|
||||
WriteUInt16(identifyData, &index, 0x7f); //word 88
|
||||
@@ -297,7 +317,10 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: 1
|
||||
*/
|
||||
index = 93 * 2;
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(1 | (1 << 14) | 0x2000)); //word 93
|
||||
if (GetSelectedDevice())
|
||||
WriteUInt16(identifyData, &index, ((1 << 14) | (0x3 << 8))); //word 93, Device 1
|
||||
else
|
||||
WriteUInt16(identifyData, &index, ((1 << 14) | (1 << 3) | 0x3)); //word 93, Device 0
|
||||
//Vendor’s recommended acoustic management value.
|
||||
//94
|
||||
//Stream Minimum Request Size
|
||||
@@ -310,9 +333,10 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//98-99
|
||||
//Total Number of User Addressable Sectors for the 48-bit Address feature set.
|
||||
index = 100 * 2;
|
||||
WriteUInt64(identifyData, &index, static_cast<u16>(nbSectors));
|
||||
index -= 2;
|
||||
WriteUInt16(identifyData, &index, 0); //truncate to 48bits
|
||||
if (lba48Supported)
|
||||
WriteUInt64(identifyData, &index, sizeSectors);
|
||||
else
|
||||
WriteUInt64(identifyData, &index, 0); // for 28-bit only this area is empty
|
||||
//Streaming Transfer Time - PIO
|
||||
//104
|
||||
//Reserved
|
||||
@@ -325,7 +349,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: 1
|
||||
*/
|
||||
index = 106 * 2;
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | 0));
|
||||
WriteUInt16(identifyData, &index, ((1 << 14) | 0));
|
||||
//Inter-seek delay for ISO-7779acoustic testing in microseconds
|
||||
//107
|
||||
//WNN
|
||||
@@ -365,7 +389,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//15:8 Checksum, 7:0 Signature
|
||||
CreateHDDinfoCsum();
|
||||
}
|
||||
void ATA::CreateHDDinfoCsum() //Is this correct?
|
||||
void ATA::CreateHDDinfoCsum()
|
||||
{
|
||||
u8 counter = 0;
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ namespace Sessions
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to bind socket. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket == -1;
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -561,7 +561,7 @@ namespace Sessions
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to setsockopt IP_RECVERR. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket == -1;
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -571,7 +571,7 @@ namespace Sessions
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to set TTL. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket == -1;
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -585,7 +585,7 @@ namespace Sessions
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to get id. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket == -1;
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -621,7 +621,7 @@ namespace Sessions
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Send Error %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket == -1;
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+27
-16
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
@@ -7,8 +7,10 @@
|
||||
#include "Config.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// TODO: Purge emuLog and all this other nonsense, just go through Log with LOGLEVEL_TRACE.
|
||||
extern FILE *emuLog;
|
||||
extern std::string emuLogName;
|
||||
|
||||
extern char* disVU0MicroUF(u32 code, u32 pc);
|
||||
extern char* disVU0MicroLF(u32 code, u32 pc);
|
||||
@@ -214,23 +216,34 @@ class ConsoleLogFromVM : public BaseTraceLogSource
|
||||
public:
|
||||
ConsoleLogFromVM( const TraceLogDescriptor* desc ) : _parent( desc ) {}
|
||||
|
||||
bool Write( const char* msg ) const
|
||||
bool Write(std::string_view msg)
|
||||
{
|
||||
ConsoleColorScope cs(conColor);
|
||||
Console.WriteRaw(msg);
|
||||
|
||||
// Buffered output isn't compatible with the testsuite. The end of test
|
||||
// doesn't always get flushed. Let's just flush all the output if EE/IOP
|
||||
// print anything.
|
||||
fflush(NULL);
|
||||
for (const char ch : msg)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (!m_buffer.empty())
|
||||
{
|
||||
Console.WriteLn(conColor, m_buffer);
|
||||
m_buffer.clear();
|
||||
}
|
||||
}
|
||||
else if (ch < 0x20)
|
||||
{
|
||||
// Ignore control characters.
|
||||
// Otherwise you get fun bells going off.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer.push_back(ch);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Write(const std::string& msg) const
|
||||
{
|
||||
return Write(msg.c_str());
|
||||
}
|
||||
private:
|
||||
std::string m_buffer;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
@@ -304,7 +317,6 @@ struct SysConsoleLogPack
|
||||
{
|
||||
ConsoleLogSource ELF;
|
||||
ConsoleLogSource eeRecPerf;
|
||||
ConsoleLogSource sysoutConsole;
|
||||
ConsoleLogSource pgifLog;
|
||||
|
||||
ConsoleLogFromVM<Color_Cyan> eeConsole;
|
||||
@@ -374,7 +386,6 @@ extern void __Log( const char* fmt, ... );
|
||||
#define eeConLog SysConsole.eeConsole.IsActive() && SysConsole.eeConsole.Write
|
||||
#define eeDeci2Log SysConsole.deci2.IsActive() && SysConsole.deci2.Write
|
||||
#define iopConLog SysConsole.iopConsole.IsActive() && SysConsole.iopConsole.Write
|
||||
#define sysConLog SysConsole.sysoutConsole.IsActive() && SysConsole.sysoutConsole.Write
|
||||
#define pgifConLog SysConsole.pgifLog.IsActive() && SysConsole.pgifLog.Write
|
||||
#define recordingConLog SysConsole.recordingConsole.IsActive() && SysConsole.recordingConsole.Write
|
||||
#define controlLog SysConsole.controlInfo.IsActive() && SysConsole.controlInfo.Write
|
||||
|
||||
+2
-2
@@ -58,12 +58,12 @@ tDMA_TAG DMACh::dma_tag()
|
||||
|
||||
std::string DMACh::cmq_to_str() const
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("chcr = %lx, madr = %lx, qwc = %lx", chcr._u32, madr, qwc);
|
||||
return StringUtil::StdStringFromFormat("chcr = %x, madr = %x, qwc = %x", chcr._u32, madr, qwc);
|
||||
}
|
||||
|
||||
std::string DMACh::cmqt_to_str() const
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("chcr = %lx, madr = %lx, qwc = %lx, tadr = %1x", chcr._u32, madr, qwc, tadr);
|
||||
return StringUtil::StdStringFromFormat("chcr = %x, madr = %x, qwc = %x, tadr = %1x", chcr._u32, madr, qwc, tadr);
|
||||
}
|
||||
|
||||
__fi void throwBusError(const char *s)
|
||||
|
||||
+14
-2
@@ -83,7 +83,7 @@ union tDMA_TAG {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_TAG() {}
|
||||
tDMA_TAG() = default;
|
||||
|
||||
tDMA_TAG(u32 val) { _u32 = val; }
|
||||
u16 upper() const { return (_u32 >> 16); }
|
||||
@@ -121,6 +121,7 @@ union tDMA_CHCR {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_CHCR() = default;
|
||||
tDMA_CHCR( u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -143,6 +144,7 @@ union tDMA_SADR {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_SADR() = default;
|
||||
tDMA_SADR(u32 val) { _u32 = val; }
|
||||
|
||||
void reset() { _u32 = 0; }
|
||||
@@ -156,6 +158,7 @@ union tDMA_QWC {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMA_QWC() = default;
|
||||
tDMA_QWC(u32 val) { _u32 = val; }
|
||||
|
||||
void reset() { _u32 = 0; }
|
||||
@@ -264,6 +267,7 @@ union tDMAC_QUEUE
|
||||
};
|
||||
u16 _u16;
|
||||
|
||||
tDMAC_QUEUE() = default;
|
||||
tDMAC_QUEUE(u16 val) { _u16 = val; }
|
||||
void reset() { _u16 = 0; }
|
||||
bool empty() const { return (_u16 == 0); }
|
||||
@@ -322,6 +326,7 @@ union tDMAC_CTRL {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_CTRL() = default;
|
||||
tDMAC_CTRL(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -348,6 +353,7 @@ union tDMAC_STAT {
|
||||
u32 _u32;
|
||||
u16 _u16[2];
|
||||
|
||||
tDMAC_STAT() = default;
|
||||
tDMAC_STAT(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -372,6 +378,7 @@ union tDMAC_PCR {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_PCR() = default;
|
||||
tDMAC_PCR(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -390,6 +397,7 @@ union tDMAC_SQWC {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_SQWC() = default;
|
||||
tDMAC_SQWC(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -406,6 +414,7 @@ union tDMAC_RBSR {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_RBSR() = default;
|
||||
tDMAC_RBSR(u32 val) { _u32 = val; }
|
||||
|
||||
void reset() { _u32 = 0; }
|
||||
@@ -419,6 +428,7 @@ union tDMAC_RBOR {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_RBOR() = default;
|
||||
tDMAC_RBOR(u32 val) { _u32 = val; }
|
||||
|
||||
void reset() { _u32 = 0; }
|
||||
@@ -440,7 +450,7 @@ union tDMAC_ADDR
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tDMAC_ADDR() {}
|
||||
tDMAC_ADDR() = default;
|
||||
tDMAC_ADDR(u32 val) { _u32 = val; }
|
||||
|
||||
void clear() { _u32 = 0; }
|
||||
@@ -490,6 +500,7 @@ union tINTC_STAT {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tINTC_STAT() = default;
|
||||
tINTC_STAT(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
@@ -506,6 +517,7 @@ union tINTC_MASK {
|
||||
};
|
||||
u32 _u32;
|
||||
|
||||
tINTC_MASK() = default;
|
||||
tINTC_MASK(u32 val) { _u32 = val; }
|
||||
|
||||
bool test(u32 flags) const { return !!(_u32 & flags); }
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
"minimum": 0,
|
||||
"maximum": 3
|
||||
},
|
||||
"eeDivRoundMode": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 3
|
||||
},
|
||||
"vuRoundMode": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
@@ -97,7 +102,6 @@
|
||||
"DMABusyHack",
|
||||
"EETimingHack",
|
||||
"FpuMulHack",
|
||||
"FpuNegDivHack",
|
||||
"GIFFIFOHack",
|
||||
"GoemonTlbHack",
|
||||
"IbitHack",
|
||||
|
||||
+8
-3
@@ -171,7 +171,7 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail, bool
|
||||
GSConfig.OsdShowGPU = GSConfig.OsdShowGPU && g_gs_device->SetGPUTimingEnabled(true);
|
||||
|
||||
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", GSDevice::RenderAPIToString(new_api));
|
||||
Console.Indent().WriteLn(g_gs_device->GetDriverInfo());
|
||||
Console.WriteLn(g_gs_device->GetDriverInfo());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -188,6 +188,9 @@ static void CloseGSDevice(bool clear_state)
|
||||
|
||||
static bool OpenGSRenderer(GSRendererType renderer, u8* basemem)
|
||||
{
|
||||
// Must be done first, initialization routines in GSState use GSIsHardwareRenderer().
|
||||
GSCurrentRenderer = renderer;
|
||||
|
||||
if (renderer == GSRendererType::Null)
|
||||
{
|
||||
g_gs_renderer = std::make_unique<GSRendererNull>();
|
||||
@@ -205,7 +208,6 @@ static bool OpenGSRenderer(GSRendererType renderer, u8* basemem)
|
||||
g_gs_renderer->ResetPCRTC();
|
||||
g_gs_renderer->UpdateRenderFixes();
|
||||
g_perfmon.Reset();
|
||||
GSCurrentRenderer = renderer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -777,7 +779,10 @@ void GSSetSoftwareRendering(bool software_renderer, GSInterlaceMode new_interlac
|
||||
|
||||
if (!GSIsHardwareRenderer() != software_renderer)
|
||||
{
|
||||
if (!GSreopen(false, software_renderer ? GSRendererType::SW : GSConfig.Renderer, std::nullopt))
|
||||
// Config might be SW, and we're switching to HW -> use Auto.
|
||||
const GSRendererType renderer = (software_renderer ? GSRendererType::SW :
|
||||
(GSConfig.Renderer == GSRendererType::SW ? GSRendererType::Auto : GSConfig.Renderer));
|
||||
if (!GSreopen(false, renderer, std::nullopt))
|
||||
pxFailRel("Failed to reopen GS for renderer switch.");
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user