Compare commits

...

72 Commits

Author SHA1 Message Date
Gliniak 8197881803 [UI] Added detailed installation state to "Install Content" option 2025-04-19 21:13:46 +02:00
Gliniak 5ba6c2b840 [VFS] Improved initial loading time during "Install Content" 2025-04-19 16:54:25 +02:00
Gliniak 56703e52e2 [UI] Redesigned "Install Content" window
- Added ID for each ImGui window
- Added filesystem::CreateFolder function
2025-04-18 21:55:58 +02:00
Xphalnos 5d5eb03127 [GPU] Adding Registers from Xenon 2025-04-17 13:18:52 +02:00
Marco Rodolfi 066391fb59 [main ui] Properly handle XDG format specifications for Linux systems.
The issue was stemming from the fact that by default Xenia is running in portable mode, as in use the same root directory as the executable for its datafiles.

This default is an issue when using this software from a POSIX platform, since a lot of the times the location where the binary resides is not writable by default.

Therefore, force portable mode to be disabled on non Windows platforms.
2025-04-17 07:41:30 +02:00
Adrian bde7d5579a [Kernel] Fixed xex2_version 2025-04-15 20:37:20 +02:00
Gliniak 31d715d100 [Premake] Removed unused/unnecessary subprojects.
- Testing currently doesn't work
- VFS Dump is unused. You can use internal function for it
- Demos are only for fun
- Trace Dump & Trace Viewer (unsure, but ok)

You can re-enable them by changing values: enableTests and enableMiscSubprojects in main premake file.

In the future there should be xb command support to overwrite them
2025-04-15 09:04:16 +02:00
Gliniak 7298536d46 [HID] Added support for Xbox 360 Skylanders Portal
- This requires Zadig for installation of WinUSB driver for portal
2025-04-14 21:44:49 +02:00
Gliniak 7667958556 [3PP] Added Libusb 2025-04-14 21:44:49 +02:00
The-Little-Wolf d2b265e251 [XAM/NUI] - Implement More Functions
- Implement XamNuiIsDeviceReady, XamNuiIdentityGetSessionId, XamNuiHudGetInitializeFlags, XamIsNuiUIActive, XamUserNuiGetUserIndexForSignin and XamNuiHudGetVersions
- Stub XamIsNuiAutomationEnabled/XamIsNatalPlaybackEnabled, XamUserNuiGetUserIndex, XamUserNuiEnableBiometric, XamNuiGetDepthCalibration, XamNuiSkeletonGetBestSkeletonIndex, XamNuiIsChatMicEnabled, XamNuiPlayerEngagementUpdate, XamNuiCameraTiltGetStatus, XamNuiCameraElevationGetAngle, XamNuiCameraGetTiltControllerType, XamNuiCameraSetFlags,  XamShowNuiGuideUI, XamNuiHudIsEnabled, XamNuiIdentityEnrollForSignIn , XamNuiIdentityAbort and XamNuiHudSetEngagedTrackingID
- According to Xam XamIsNuiAutomationEnabled, and XamIsNatalPlaybackEnabled are the same function.
- Left Notes for future reference
2025-04-14 09:17:52 +02:00
Adrian 02c95bee06 [XAM] Implemented XamShowCreateProfileUI 2025-04-13 21:52:11 +02:00
Michael Oliver 1a356f7344 [Kernel] Add option to ignore incompatible title updates with mismatched signatures 2025-04-12 22:16:41 +02:00
Xphalnos 47f327e848 [Misc] Replaced const with constexpr where possible 2025-04-08 19:32:17 +02:00
Michael Oliver c4f1bf27ef [UI] Add paste functionality to keyboard input dialog 2025-04-06 18:08:06 +02:00
The-Little-Wolf 0771938db6 [Kernel] - Implemented SystemManagementController Class
- Added handling (partial or dummy) for SMC actions:
 - QUERY_TEMP_SENSOR, QUERY_TRAY, QUERY_AV_PACK, QUERY_SMC_VERSION, QUERY_IR_ADDRESS, QUERY_TILT_SENSOR
 - SET_FAN_SPEED_CPU, SET_FAN_SPEED_GPU, SET_DVD_TRAY, SET_IR_ADDRESS, SET_POWER_LED, SET_LEDS

- Stub HalOpenCloseODDTray, XamLoaderGetMediaInfo, XamLoaderGetMediaInfoEx
- Partially Implement HalSendSMCMessage
- Implement XamLoaderGetDvdTrayState
- HalOpenCloseODDTray is used by dash and HalSendSMCMessage can be used by custom dashboards
2025-04-06 17:30:56 +02:00
The-Little-Wolf 4b24f128f6 [XBOXKRNL & XAM] - Video, Hal, And XConfig
- Properly implement HalGetCurrentAVPack, and XGetAudioFlags.
- Return proper flags for AV Component, AV Composite, and VGA from xconfig.
- Set to HD to proper value.
- Correct wrong widescreen flag.
2025-04-01 07:59:22 +02:00
Gliniak 86a25791d0 [Base] Fixed possible compilation failure 2025-04-01 00:00:03 +02:00
Gliniak 30dcc09714 [3PP] Uplifted Premake to 5.0-beta6 and cleaned up premake file 2025-04-01 00:00:03 +02:00
Gliniak a0d199cd35 [XAM/UI] Fixed crashing on Titles & Achievements menu 2025-03-31 21:32:41 +02:00
Gliniak 7a2f53bf20 [XAM] Added default value for controller vibration.
- Added notification broadcast while changing controller vibration state
2025-03-30 21:36:47 +02:00
Xphalnos 7479ccc292 [Misc] Fix Some Warnings on Clang Build with Windows + Adding constexpr 2025-03-27 17:52:18 +01:00
Xphalnos 5f918ef28d [Misc] Replaced const with constexpr where possible 2025-03-25 19:50:37 +01:00
Margen67 d20620eb5e [CI] Linux: Add bat+ps1 2025-03-23 14:22:16 -07:00
Margen67 0ee39400fe [xb] Use WINDIR env var 2025-03-23 12:20:48 -07:00
Gliniak a45a9d8704 [UI] Resolved issues caused by ImGui uplift.
- Fixed size of default font size
- Added logic to not load nullptr texture to prevent unexpected issues
- Commited out some trace viewer UI logic for now. It should be redesigned with tables in mind
2025-03-19 22:51:04 +01:00
Gliniak f61d52dc46 [3PP] Uplifted ImGui 2025-03-19 22:47:20 +01:00
Gliniak 40bd0080f1 [Kernel] Fixed TU loading on Linux 2025-03-18 22:37:34 +01:00
Gliniak b7066c7a15 [VFS] Fixed "Install Content" option on Linux 2025-03-18 22:37:34 +01:00
Adrian 1e2f903a4a [XAM] Improved XContentQueryVolumeDeviceType 2025-03-16 20:55:39 +01:00
Gliniak 6ae45effd0 [XAM] Fixed issue with profile creation introduced in previous version 2025-03-16 20:05:12 +01:00
Gliniak 8926bdcdd6 [XAM] Fixed issue with achievements saving in Forza series.
Remove this ducktape asap and remove hardcodes
2025-03-15 23:59:34 +01:00
Gliniak 9132035a51 [UI] Fixed issue with games list UI crashing on close on Vulkan 2025-03-15 23:11:36 +01:00
Gliniak ae1c1e017d [UI] Fixed issue with font not being loaded in certain conditions 2025-03-15 23:10:46 +01:00
Gliniak d801e047dc [Kernel] Adjusted threshold of delay triggering for threads from all with Normal priority to Below Normal.
This should resolve slowdowns introduced in one of the latests build
2025-03-15 18:48:28 +01:00
Gliniak 23d1f7a308 [XAM] Added overlap to XamUserWriteProfileSettings
This fixes saving in Earthworm Jim

Additionally fixed issue with not setting xuid to -1 when not provided
2025-03-13 22:54:02 +01:00
Gliniak c4867250e4 [XAM] Fixed issue with invalid settings in UE games 2025-03-12 22:53:27 +01:00
Adrian 25b3540480 [XAM] Added XEnableGuestSignin 2025-03-12 15:10:35 +01:00
Gliniak 570d30f06d [XAM/Input] Fixed issue with abnormal input in Aurora 2025-03-10 23:56:14 +01:00
Gliniak 763a3da6ea [Threading] Change behaviour when provided timeout is 0 for Normal priority or less threads 2025-03-10 23:17:37 +01:00
Gliniak 27d9cb8cfc [XAM] Added missing nullptr check.
This partially fixes Fable 2 main menu crashes.
Figure out why game tries to save invalid data.
2025-03-10 19:25:00 +01:00
Gliniak f833effd07 [XAM] Implemented XamParseGamerTileKey 2025-03-10 18:33:45 +01:00
Gliniak b9ecfd5d78 [XAM] Fixed incorrect setting order being used.
Instead of: Title->Profile->Default
It used: Title->Default
2025-03-10 18:32:39 +01:00
Gliniak 0d06cdd649 [XAM] Removed overlap from XamUserReadProfileSettings. It currently breaks games for whatever reason.
- Updated params for: XamParseGamerTileKey, XamWriteGamerTile
2025-03-09 23:50:54 +01:00
Gliniak 1544349499 [XAM] Settings: Added specific default settings list 2025-03-09 23:33:13 +01:00
Gliniak 01fc219fc2 [HID] Fixed issue with controller spamming message.
This was caused by not ignoring cases when title provides unsupported flags.
For example support for big button controller.
2025-03-08 22:52:50 +01:00
The-Little-Wolf 34b7085ed3 [XAM/USER] - Implement XamUserCreateTitlesPlayedEnumerator
Implement of XamUserCreateTitlesPlayedEnumerator
2025-03-08 21:11:53 +01:00
Gliniak 5979274998 [HID/SDL] Return controller subtype instead of forcing gamepad 2025-03-08 20:44:43 +01:00
Gliniak 5af7e1540b [Emulator] Added extended logging on initialization 2025-03-08 19:20:08 +01:00
Gliniak d2f350d0d3 [XAM] UserTracker: Added option to return user specific list of contexts and properties 2025-03-08 18:12:36 +01:00
Gliniak da89b6a0c3 [XAM] Added missing is_empty check while reading setting data 2025-03-08 17:31:30 +01:00
Gliniak 6666b803fd [XAM] Added missing nullptr check during Spa loading 2025-03-07 20:58:45 +01:00
Gliniak 523a2dc6e3 [3PP] Uplifted SDL2 to 2.32.2. Possibly next update to 3.0 2025-03-07 18:39:45 +01:00
Gliniak 1110cdd372 [Kernel] Added support for writing/reading GPD files
This breaks settings in games that are using them and savefiles in games that use settings to store progress
2025-03-07 11:59:48 +01:00
The-Little-Wolf ccf7adf015 [XAM/APP] Recording more Xam app messages
- Recording more xam app messages for future reference
- Removed mistakes from messenger_app.h
- Added missing buffer_ptr, buffer_length to unknown message id logs
2025-03-06 18:32:16 +01:00
Adrian 60318a5db6 [Module] Include XEX_SYSTEM_FLAGS in the log 2025-02-26 19:22:43 +01:00
Michael Oliver 9555e7bde4 [Patcher] Ensure hash is checked when loading title plugins
Fixes bug where plugin loader would load all defined plugins if at least one was valid
2025-02-26 15:25:26 +01:00
The-Little-Wolf ac6692fc65 [Xbox] - More Notification IDs
- Removed unknown ids
- Removed assumed total
- Added notes
- Added kXNotificationSystemXLiveTitleUpdate
- Corrected multiple ids to include their version number
- Fixed Typo
2025-02-26 08:35:10 +01:00
Gliniak c373208c97 [UI] Disable showing notifications while making screenshot 2025-02-25 21:38:45 +01:00
Gliniak 78f97f8ff3 [Memory] Added allocation of 40k at the start of xex range.
Titles can access it and take value from it.
2025-02-22 19:32:10 +01:00
Gliniak b3d345610a [Premake] Added ASAN to Checked configuration.
There is issue with ImGui dialogs desctruction that always triggers ASAN
2025-02-17 18:47:49 +01:00
Margen67 75d49df2c5 [xb] Add Python 3.14 2025-02-13 00:28:55 -08:00
Radosław Gliński d0e6f3638e
Fixed incorrect link to releases in README file 2025-02-10 16:23:06 +01:00
The-Little-Wolf fbacd3c12d [Xam/Xam_NUI] - Implement XamShowNuiHardwareRequiredUI
- Implement XamShowNuiHardwareRequiredUI
- Add notes to XamShowNuiTroubleshooterUI
2025-02-07 09:02:45 +01:00
The-Little-Wolf 180be3664e [Xboxkrnl/Xconfig] - add xboxkrnl_xconfig.h
- Add xboxkrnl_xconfig.h to hold known Xconfig flags
- Implement more xeExGetXConfigSetting cases
2025-02-07 08:29:13 +01:00
Adrian b7b707ddd2 [3PP] Uplift utfcpp 2025-02-01 23:43:49 +01:00
Margen67 4cc074df63 [CI] Fix release title 2025-01-28 04:59:33 -08:00
Margen67 54610b939f [xb] Fall back to normal clone if shallow fails 2025-01-27 20:41:06 -08:00
Margen67 787c8d0edc [xb] "Fix" submodule update 2025-01-27 19:10:17 -08:00
nikolay-kyosev 9a0ed48168 A fix for the release build crash on linux. 2025-01-27 18:21:14 +01:00
Margen67 b7b6b860a9 [CI] Move releases to separate repository 2025-01-27 01:12:22 -08:00
Margen67 dbe645e16e [CI] Linux lint 2025-01-27 01:12:22 -08:00
Margen67 6f0a736c6c [xb] Print clang-format version 2025-01-27 01:12:22 -08:00
236 changed files with 9055 additions and 3403 deletions

59
.github/workflows/Create_release.yml vendored Normal file
View File

@ -0,0 +1,59 @@
name: Create release
on:
workflow_call:
inputs:
os:
required: true
type: string
secrets:
RELEASE_TOKEN:
required: true
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@main
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GH_REPO: ${{ github.repository_owner }}/xenia-canary-releases
notes: ${{ github.event.head_commit.message }}
run: |
rm -rf **/*.pdb
case ${{ inputs.os }} in
windows)
asset=xenia_canary_windows.zip
7z a $asset './xenia_canary_windows/*'
;;
linux)
asset=xenia_canary_linux.tar.gz
cd xenia_canary_linux
chmod +x xenia_canary
tar -cvpf ../$asset *
cd -
;;
esac
if [ ! -f $asset ]; then
echo "::error::$asset doesn't exist!"
exit 1
fi
if [ $(stat -c%s $asset) -lt 100000 ]; then
echo "::error::$asset is too small!"
exit 1
fi
create_or_edit_release() {
local tag=$1
local title=$2
if gh release view $tag; then
gh release edit $tag -t $title -n "$notes"
gh release upload $tag $asset --clobber
else
gh release create $tag $asset --target 925ed98d5dce604b651027c36fb522dc1ff0fa55 -t $title -n "$notes"
fi
}
tag=${GITHUB_SHA::7}
create_or_edit_release $tag ${tag}_$GITHUB_REF_NAME
create_or_edit_release $GITHUB_REF_NAME $tag

View File

@ -7,13 +7,14 @@ on:
- '.drone.star'
- '.gitattributes'
- '.gitignore'
- '.gdbinit'
- '.github/*'
- '.github/workflows/Windows_build.yml'
- '.github/*_TEMPLATE/**'
- '*.bat'
- '*.md'
- '*.yml'
- '*.ps1'
- '*.txt'
- '*.yml'
- 'docs/**'
- 'src/**/*_windows.*'
- 'src/**/*_android.*'
@ -25,13 +26,14 @@ on:
- '.drone.star'
- '.gitattributes'
- '.gitignore'
- '.gdbinit'
- '.github/*'
- '.github/workflows/Windows_build.yml'
- '.github/*_TEMPLATE/**'
- '*.bat'
- '*.md'
- '*.yml'
- '*.ps1'
- '*.txt'
- '*.yml'
- 'docs/**'
- 'src/**/*_windows.*'
- 'src/**/*_android.*'
@ -42,49 +44,68 @@ on:
jobs:
lint:
name: Lint
runs-on: windows-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@main
- name: Check Clang-Format Version
run: clang-format --version
- name: Setup
run: |
LLVM_VERSION=18 # Same as Windows
UBUNTU_BASE=jammy
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-$LLVM_VERSION main"
sudo apt-get -y update
sudo apt-get -y install clang-format-$LLVM_VERSION
- name: Lint
run: ./xb lint --all
build-linux:
name: Build (Linux) # runner.os can't be used here
build:
name: Build (LLVM ${{ matrix.LLVM_VERSION }})
needs: lint
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
LLVM_VERSION: [19]
steps:
- uses: actions/checkout@main
with:
fetch-depth: 0
- name: Set environment variables
run: |
LLVM_VERSION=19
echo "LLVM_VERSION=$LLVM_VERSION" >> $GITHUB_ENV
echo "UBUNTU_BASE=jammy" >> $GITHUB_ENV
echo "CC=clang-${LLVM_VERSION}" >> $GITHUB_ENV
echo "CXX=clang++-${LLVM_VERSION}" >> $GITHUB_ENV
echo "AR=llvm-ar-${LLVM_VERSION}" >> $GITHUB_ENV
- name: Setup
run: |
UBUNTU_BASE=jammy
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-$LLVM_VERSION main"
sudo apt-add-repository "deb http://apt.llvm.org/${UBUNTU_BASE}/ llvm-toolchain-${UBUNTU_BASE}-${{ matrix.LLVM_VERSION }} main"
sudo apt-get -y update
sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libgtk-3-dev libsdl2-dev libvulkan-dev libx11-dev libx11-xcb-dev clang-$LLVM_VERSION clang-format-$LLVM_VERSION llvm-$LLVM_VERSION ninja-build cmake
sudo apt-get -y install mesa-vulkan-drivers valgrind libc++-dev libc++abi-dev libgtk-3-dev libsdl2-dev libvulkan-dev libx11-xcb-dev clang-${{ matrix.LLVM_VERSION }} llvm-${{ matrix.LLVM_VERSION }} ninja-build
./xb setup
- name: Build
env:
CC: clang-${{ matrix.LLVM_VERSION }}
CXX: clang++-${{ matrix.LLVM_VERSION }}
AR: llvm-ar-${{ matrix.LLVM_VERSION }}
run: ./xb build --config=Release
- name: Prepare artifacts
id: prepare_artifacts
run: |
mkdir artifacts
cp build/bin/Linux/Release/xenia_canary artifacts/xenia_canary
mkdir -p artifacts
cp -r build/bin/Linux/Release/xenia_canary LICENSE artifacts
- name: Upload xenia canary artifacts
if: steps.prepare_artifacts.outcome == 'success'
id: upload_artifacts
uses: actions/upload-artifact@main
with:
name: xenia_canary_linux
path: artifacts/
if-no-files-found: error
path: artifacts
if-no-files-found: error
create-release:
name: Create release
needs: [lint, build]
if: |
github.repository == 'xenia-canary/xenia-canary' &&
github.event.action != 'pull_request' &&
github.ref == 'refs/heads/canary_experimental'
uses: ./.github/workflows/Create_release.yml
with:
os: linux
secrets:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}

View File

@ -51,21 +51,17 @@ jobs:
lint:
name: Lint
runs-on: windows-latest
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
steps:
- uses: actions/checkout@main
- name: Check Clang-Format Version
run: clang-format --version
- name: Lint
run: .\xb lint --all
build-windows:
name: Build (Windows, VS${{ matrix.vsver }}) # runner.os can't be used here
build:
name: Build
needs: lint
strategy:
fail-fast: false
matrix:
vsver: [2022]
runs-on: windows-${{ matrix.vsver }}
runs-on: windows-2025
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
steps:
@ -84,34 +80,21 @@ jobs:
If ($LastExitCode -le 7) { echo "LastExitCode = $LastExitCode";$LastExitCode = 0 }
- name: Upload xenia canary artifacts
if: steps.prepare_artifacts.outcome == 'success'
id: upload_artifacts
uses: actions/upload-artifact@main
with:
name: xenia_canary_vs${{ matrix.vsver }}
name: xenia_canary_windows
path: artifacts\xenia_canary
if-no-files-found: error
- name: Create release
if: |
github.repository == 'xenia-canary/xenia-canary' &&
github.event.action != 'pull_request' &&
github.ref == 'refs/heads/canary_experimental' &&
steps.upload_artifacts.outcome == 'success'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$asset="xenia_canary.zip"
rm -recurse -force artifacts\xenia_canary\*.pdb # Ideally this would use xr, but I can't get it to work
7z a $asset .\artifacts\xenia_canary\*
If ($(Get-Item $asset).length -le 100000) {
Throw "Error: Archive $asset too small!"
}
$tag=$env:GITHUB_SHA.SubString(0,7)
$branch=$($env:GITHUB_REF -replace 'refs/heads/')
$title="${tag}_$branch"
gh release create $tag $asset --target $env:GITHUB_SHA -t $title
# Remove canary_ to prevent conflicts from tag
$tag=$($branch -replace 'canary_')
gh release delete $tag -y
git push --delete origin $tag
git tag -d $tag
gh release create $tag $asset --target $env:GITHUB_SHA -t $branch
create-release:
name: Create release
needs: [lint, build]
if: |
github.repository == 'xenia-canary/xenia-canary' &&
github.event.action != 'pull_request' &&
github.ref == 'refs/heads/canary_experimental'
uses: ./.github/workflows/Create_release.yml
with:
os: windows
secrets:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}

5
.gitmodules vendored
View File

@ -42,7 +42,7 @@
url = https://github.com/libsdl-org/SDL.git
[submodule "third_party/utfcpp"]
path = third_party/utfcpp
url = https://github.com/xenia-project/utfcpp.git
url = https://github.com/nemtrif/utfcpp.git
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/fmtlib/fmt.git
@ -103,3 +103,6 @@
[submodule "third_party/pugixml"]
path = third_party/pugixml
url = https://github.com/zeux/pugixml.git
[submodule "third_party/libusb"]
path = third_party/libusb
url = https://github.com/libusb/libusb.git

View File

@ -20,7 +20,7 @@ Discussing illegal activities will get you banned.
Buildbot | Status | Releases
-------- | ------ | --------
Windows | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/cd506034fd8148309a45034925648499)](https://app.codacy.com/gh/xenia-canary/xenia-canary/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) | [Latest](https://github.com/xenia-canary/xenia-canary/releases/latest) ◦ [All](https://github.com/xenia-canary/xenia-canary/releases)
Windows | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/cd506034fd8148309a45034925648499)](https://app.codacy.com/gh/xenia-canary/xenia-canary/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) | [Latest](https://github.com/xenia-canary/xenia-canary-releases/releases/latest) ◦ [All](https://github.com/xenia-canary/xenia-canary-releases/releases) ◦ [Old](https://github.com/xenia-canary/xenia-canary/releases)
Linux | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Linux_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Linux_build.yml)
Netplay Build | | [Latest](https://github.com/AdrianCassar/xenia-canary/releases/latest)

View File

@ -7,6 +7,11 @@ location(build_root)
targetdir(build_bin)
objdir(build_obj)
-- Define variables for enabling specific submodules
-- Todo: Add changing from xb command
enableTests = false
enableMiscSubprojects = false
-- Define an ARCH variable
-- Only use this to enable architecture-specific functionality.
if os.istarget("linux") then
@ -30,6 +35,8 @@ cppdialect("C++20")
exceptionhandling("On")
rtti("On")
symbols("On")
characterset("Unicode")
fatalwarnings("All")
-- TODO(DrChat): Find a way to disable this on other architectures.
if ARCH ~= "ppc64" then
@ -38,11 +45,6 @@ if ARCH ~= "ppc64" then
filter({})
end
characterset("Unicode")
flags({
"FatalWarnings", -- Treat warnings as errors.
})
filter("kind:StaticLib")
defines({
"_LIB",
@ -50,23 +52,24 @@ filter("kind:StaticLib")
filter("configurations:Checked")
runtime("Debug")
sanitize("Address")
flags("NoIncrementalLink")
editandcontinue("Off")
staticruntime("Off")
optimize("Off")
defines({
"DEBUG",
})
filter({"configurations:Checked", "platforms:Windows"})
buildoptions({
"/RTCsu", -- Full Run-Time Checks.
})
filter({"configurations:Checked", "platforms:Linux"})
defines({
"_GLIBCXX_DEBUG", -- libstdc++ debug mode
})
filter({"configurations:Release", "platforms:Windows"})
buildoptions({
"/Gw",
"/Ob3",
})
filter("configurations:Debug")
runtime("Release")
@ -75,6 +78,7 @@ filter("configurations:Debug")
"DEBUG",
"_NO_DEBUG_HEAP=1",
})
filter({"configurations:Debug", "platforms:Linux"})
defines({
"_GLIBCXX_DEBUG", -- make dbg symbols work on some distros
@ -88,19 +92,28 @@ filter("configurations:Release")
})
optimize("Speed")
inlining("Auto")
flags({
"LinkTimeOptimization",
"NoBufferSecurityCheck",
})
editandcontinue("Off")
-- Not using floatingpoint("Fast") - NaN checks are used in some places
-- (though rarely), overall preferable to avoid any functional differences
-- between debug and release builds, and to have calculations involved in GPU
-- (especially anything that may affect vertex position invariance) and CPU
-- (such as constant propagation) emulation as predictable as possible,
-- including handling of specials since games make assumptions about them.
filter({"configurations:Release", "platforms:Windows"})
linktimeoptimization("On")
flags({
"NoBufferSecurityCheck"
})
buildoptions({
"/Gw",
"/Ob3",
})
filter("platforms:Linux")
system("linux")
toolset("clang")
vectorextensions("AVX2")
buildoptions({
-- "-mlzcnt", -- (don't) Assume lzcnt is supported.
})
@ -113,9 +126,6 @@ filter("platforms:Linux")
"rt",
})
filter({"platforms:Linux"})
vectorextensions("AVX2")
filter({"platforms:Linux", "kind:*App"})
linkgroups("On")
@ -147,9 +157,6 @@ filter({"platforms:Linux", "language:C++", "toolset:clang"})
"deprecated-enum-enum-conversion",
"attributes",
})
removeflags({
"FatalWarnings"
})
filter({"platforms:Linux", "language:C++", "toolset:clang", "files:*.cc or *.cpp"})
buildoptions({
"-stdlib=libstdc++",
@ -178,16 +185,8 @@ filter("platforms:Windows")
toolset("msc")
buildoptions({
"/utf-8", -- 'build correctly on systems with non-Latin codepages'.
-- Mark warnings as severe
"/w14839", -- non-standard use of class 'type' as an argument to a variadic function
"/w14840", -- non-portable use of class 'type' as an argument to a variadic function
-- Disable warnings
"/wd4100", -- Unreferenced parameters are ok.
"/wd4201", -- Nameless struct/unions are ok.
"/wd4512", -- 'assignment operator was implicitly defined as deleted'.
"/wd4127", -- 'conditional expression is constant'.
"/wd4324", -- 'structure was padded due to alignment specifier'.
"/wd4189", -- 'local variable is initialized but not referenced'.
})
flags({
"MultiProcessorCompile", -- Multiprocessor compilation.
@ -279,6 +278,10 @@ workspace("xenia")
include("third_party/zlib.lua")
include("third_party/pugixml.lua")
if os.istarget("windows") then
include("third_party/libusb.lua")
end
if not os.istarget("android") then
-- SDL2 requires sdl2-config, and as of November 2020 isn't high-quality on
-- Android yet, most importantly in game controllers - the keycode and axis
@ -296,9 +299,7 @@ workspace("xenia")
removefiles({
"src/xenia/base/app_win32.manifest"
})
removeflags({
"FatalWarnings",
})
removefatalwarnings("All")
end
include("src/xenia")
@ -315,6 +316,7 @@ workspace("xenia")
include("src/xenia/gpu/vulkan")
include("src/xenia/hid")
include("src/xenia/hid/nop")
include("src/xenia/hid/skylander")
include("src/xenia/kernel")
include("src/xenia/patcher")
include("src/xenia/ui")

View File

@ -167,8 +167,8 @@ using xe::ui::UIEvent;
using namespace xe::hid;
using namespace xe::gpu;
const std::string kRecentlyPlayedTitlesFilename = "recent.toml";
const std::string kBaseTitle = "Xenia-canary";
constexpr std::string_view kRecentlyPlayedTitlesFilename = "recent.toml";
constexpr std::string_view kBaseTitle = "Xenia-canary";
EmulatorWindow::EmulatorWindow(Emulator* emulator,
ui::WindowedAppContext& app_context,
@ -181,7 +181,7 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator,
std::make_unique<ui::ImGuiDrawer>(window_.get(), kZOrderImGui)),
display_config_game_config_load_callback_(
new DisplayConfigGameConfigLoadCallback(*emulator, *this)) {
base_title_ = kBaseTitle +
base_title_ = std::string(kBaseTitle) +
#ifdef DEBUG
#if _NO_DEBUG_HEAP == 1
" DEBUG"
@ -569,6 +569,96 @@ void EmulatorWindow::DisplayConfigDialog::OnDraw(ImGuiIO& io) {
}
}
void EmulatorWindow::ContentInstallDialog::OnDraw(ImGuiIO& io) {
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(20, 20), ImGuiCond_FirstUseEver);
bool dialog_open = true;
if (!ImGui::Begin(
fmt::format("Installation Progress###{}", window_id_).c_str(),
&dialog_open,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_HorizontalScrollbar)) {
Close();
ImGui::End();
return;
}
bool is_everything_installed = true;
for (const auto& entry : *installation_entries_) {
ImGui::BeginTable(fmt::format("table_{}", entry.name_).c_str(), 2);
ImGui::TableNextRow(0);
ImGui::TableSetColumnIndex(0);
if (entry.icon_) {
ImGui::Image(reinterpret_cast<ImTextureID>(entry.icon_.get()),
ui::default_image_icon_size);
} else {
ImGui::Dummy(ui::default_image_icon_size);
}
ImGui::TableNextColumn();
ImGui::Text("Name: %s", entry.name_.c_str());
ImGui::Text("Installation Path:");
ImGui::SameLine();
if (ImGui::TextLink(
xe::path_to_utf8(entry.data_installation_path_).c_str())) {
LaunchFileExplorer(emulator_window_.emulator_->content_root() /
entry.data_installation_path_);
}
if (entry.content_type_ != xe::XContentType::kInvalid) {
ImGui::Text("Content Type: %s",
XContentTypeMap.at(entry.content_type_).c_str());
}
std::string result = fmt::format(
"Status: {}", xe::Emulator::installStateStringName[static_cast<uint8_t>(
entry.installation_state_)]);
if (entry.installation_state_ == xe::Emulator::InstallState::failed) {
result += fmt::format(" - {} ({:08X})",
entry.installation_error_message_.c_str(),
entry.installation_result_);
}
ImGui::Text("%s", result.c_str());
ImGui::EndTable();
if (entry.content_size_ > 0) {
ImGui::ProgressBar(static_cast<float>(entry.currently_installed_size_) /
entry.content_size_);
if (entry.currently_installed_size_ != entry.content_size_ &&
entry.installation_result_ == X_ERROR_SUCCESS) {
is_everything_installed = false;
}
} else {
ImGui::ProgressBar(0.0f);
}
if (installation_entries_->size() > 1) {
ImGui::Separator();
}
}
ImGui::Spacing();
ImGui::BeginDisabled(!is_everything_installed);
if (ImGui::Button("Close")) {
ImGui::EndDisabled();
Close();
ImGui::End();
return;
}
ImGui::EndDisabled();
if (!dialog_open && is_everything_installed) {
Close();
ImGui::End();
return;
}
ImGui::End();
}
bool EmulatorWindow::Initialize() {
window_->AddListener(&window_listener_);
window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput);
@ -935,11 +1025,16 @@ void EmulatorWindow::OnMouseUp(const ui::MouseEvent& e) {
void EmulatorWindow::TakeScreenshot() {
xe::ui::RawImage image;
imgui_drawer_->EnableNotifications(false);
if (!GetGraphicsSystemPresenter()->CaptureGuestOutput(image) ||
GetGraphicsSystemPresenter() == nullptr) {
XELOGE("Failed to capture guest output for screenshot");
return;
}
imgui_drawer_->EnableNotifications(true);
ExportScreenshot(image);
}
@ -1006,9 +1101,9 @@ void EmulatorWindow::ToggleFullscreenOnDoubleClick() {
// this function tests if user has double clicked.
// if double click was achieved the fullscreen gets toggled
const auto now = steady_clock::now(); // current mouse event time
const int16_t mouse_down_max_threshold = 250;
const int16_t mouse_up_max_threshold = 250;
const int16_t mouse_up_down_max_delta = 100;
constexpr int16_t mouse_down_max_threshold = 250;
constexpr int16_t mouse_up_max_threshold = 250;
constexpr int16_t mouse_up_down_max_delta = 100;
// max delta to prevent 'chaining' of double clicks with next mouse events
const auto last_mouse_down_delta = diff_in_ms(now, last_mouse_down);
@ -1083,62 +1178,27 @@ void EmulatorWindow::InstallContent() {
return;
}
using content_installation_data =
std::tuple<X_STATUS, std::string, std::string>;
std::map<XContentType, std::vector<content_installation_data>>
content_installation_details;
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>>
content_installation_status =
std::make_shared<std::vector<Emulator::ContentInstallEntry>>();
for (const auto& path : paths) {
// Normalize the path and make absolute.
auto abs_path = std::filesystem::absolute(path);
Emulator::ContentInstallationInfo installation_info;
auto result = emulator_->InstallContentPackage(abs_path, installation_info);
auto entry =
content_installation_details.find(installation_info.content_type);
// There is no entry with that specific type of XContent, so we must add it.
if (entry == content_installation_details.end()) {
content_installation_details.insert({installation_info.content_type, {}});
entry = content_installation_details.find(installation_info.content_type);
};
entry->second.push_back({result, installation_info.content_name,
installation_info.installation_path});
content_installation_status->push_back({path});
}
// Prepare installation process summary message
std::string summary = "Installation result: \n";
for (auto& entry : *content_installation_status) {
emulator_->ProcessContentPackageHeader(entry.path_, entry);
}
for (const auto& content_type : content_installation_details) {
if (XContentTypeMap.find(content_type.first) != XContentTypeMap.cend()) {
summary += XContentTypeMap.at(content_type.first) + ":\n";
} else {
summary += "Unknown:\n";
auto installationThread = std::thread([this, content_installation_status] {
for (auto& entry : *content_installation_status) {
emulator_->InstallContentPackage(entry.path_, entry);
}
});
installationThread.detach();
for (const auto& content_installation_entry : content_type.second) {
const std::string status =
std::get<0>(content_installation_entry) == X_STATUS_SUCCESS
? "Success"
: fmt::format("Failed (0x{:08X})",
std::get<0>(content_installation_entry));
summary += fmt::format("\t{} - {} => {}\n", status,
std::get<1>(content_installation_entry),
std::get<2>(content_installation_entry));
}
summary += "\n";
}
if (content_installation_details.count(XContentType::kProfile)) {
emulator_->kernel_state()->xam_state()->profile_manager()->ReloadProfiles();
}
xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(),
"Content Installation Summary", summary);
new ContentInstallDialog(imgui_drawer_.get(), *this,
content_installation_status);
}
void EmulatorWindow::ExtractZarchive() {
@ -1424,6 +1484,12 @@ void EmulatorWindow::ToggleControllerVibration() {
auto input_lock = input_sys->lock();
input_sys->ToggleVibration();
if (emulator_->kernel_state()) {
emulator_->kernel_state()->BroadcastNotification(
kXNotificationSystemProfileSettingChanged,
static_cast<uint32_t>(input_sys->GetConnectedSlots().count()));
}
}
}
@ -1624,7 +1690,7 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
}
// Hotkey cool-down to prevent toggling too fast
const std::chrono::milliseconds delay(75);
constexpr std::chrono::milliseconds delay(75);
// If the Xbox Gamebar is enabled or the Guide button is disabled then
// replace the Guide button with the Back button without redeclaring the key
@ -1794,10 +1860,11 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
}
if (!notificationTitle.empty()) {
app_context_.CallInUIThread([=]() {
new xe::ui::HostNotificationWindow(imgui_drawer(), notificationTitle,
notificationDesc, 0);
});
app_context_.CallInUIThread(
[imgui_drawer = imgui_drawer(), notificationTitle, notificationDesc]() {
new xe::ui::HostNotificationWindow(imgui_drawer, notificationTitle,
notificationDesc, 0);
});
}
xe::threading::Sleep(delay);
@ -1808,7 +1875,7 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
void EmulatorWindow::VibrateController(xe::hid::InputSystem* input_sys,
uint32_t user_index,
bool toggle_rumble) {
const std::chrono::milliseconds rumble_duration(100);
constexpr std::chrono::milliseconds rumble_duration(100);
// Hold lock while sleeping this thread for the duration of the rumble,
// otherwise the rumble may fail.
@ -1830,7 +1897,7 @@ void EmulatorWindow::VibrateController(xe::hid::InputSystem* input_sys,
void EmulatorWindow::GamepadHotKeys() {
X_INPUT_STATE state;
const std::chrono::milliseconds thread_delay(75);
constexpr std::chrono::milliseconds thread_delay(75);
auto input_sys = emulator_->input_system();

View File

@ -167,6 +167,34 @@ class EmulatorWindow {
EmulatorWindow& emulator_window_;
};
class ContentInstallDialog final : public ui::ImGuiDialog {
public:
ContentInstallDialog(
ui::ImGuiDrawer* imgui_drawer, EmulatorWindow& emulator_window,
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>> entries)
: ui::ImGuiDialog(imgui_drawer),
emulator_window_(emulator_window),
installation_entries_(entries) {
window_id_ = GetWindowId();
}
~ContentInstallDialog() {
for (auto& entry : *installation_entries_) {
entry.icon_.release();
}
}
protected:
void OnDraw(ImGuiIO& io) override;
private:
uint64_t window_id_;
EmulatorWindow& emulator_window_;
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>>
installation_entries_;
};
class DisplayConfigDialog final : public ui::ImGuiDialog {
public:
DisplayConfigDialog(ui::ImGuiDrawer* imgui_drawer,

View File

@ -54,11 +54,13 @@ project("xenia-app")
-- Unified library containing all apps as StaticLibs, not just the main
-- emulator windowed app.
kind("SharedLib")
links({
"xenia-gpu-vulkan-trace-viewer",
"xenia-hid-demo",
"xenia-ui-window-vulkan-demo",
})
if enableMiscSubprojects then
links({
"xenia-gpu-vulkan-trace-viewer",
"xenia-hid-demo",
"xenia-ui-window-vulkan-demo",
})
end
filter(NOT_SINGLE_LIBRARY_FILTER)
kind("WindowedApp")
@ -114,15 +116,13 @@ project("xenia-app")
"xenia-ui-d3d12",
})
filter({"platforms:Windows", SINGLE_LIBRARY_FILTER})
links({
"xenia-gpu-d3d12-trace-viewer",
"xenia-ui-window-d3d12-demo",
})
-- filter({"configurations:Release", "platforms:Windows"})
-- buildoptions({
-- "/O1",
-- })
if enableMiscSubprojects then
filter({"platforms:Windows", SINGLE_LIBRARY_FILTER})
links({
"xenia-gpu-d3d12-trace-viewer",
"xenia-ui-window-d3d12-demo",
})
end
filter("platforms:Windows")
-- Only create the .user file if it doesn't already exist.

View File

@ -95,9 +95,15 @@ UPDATE_from_bool(mount_cache, 2024, 8, 31, 20, false);
DEFINE_transient_path(target, "",
"Specifies the target .xex or .iso to execute.",
"General");
#ifndef XE_PLATFORM_WIN32
DEFINE_transient_bool(portable, false,
"Specifies if Xenia should run in portable mode.",
"General");
#else
DEFINE_transient_bool(portable, true,
"Specifies if Xenia should run in portable mode.",
"General");
#endif
DECLARE_bool(debug);
@ -421,7 +427,7 @@ bool EmulatorApp::OnInitialize() {
if (!cvars::portable &&
!std::filesystem::exists(storage_root / "portable.txt")) {
storage_root = xe::filesystem::GetUserFolder();
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_GNU_LINUX)
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_LINUX)
storage_root = storage_root / "Xenia";
#else
// TODO(Triang3l): Point to the app's external storage "files" directory

View File

@ -18,12 +18,12 @@ namespace apu {
class AudioDriver {
public:
static const uint32_t kFrameFrequencyDefault = 48000;
static const uint32_t kFrameChannelsDefault = 6;
static const uint32_t kChannelSamplesDefault = 256;
static const uint32_t kFrameSamplesMax =
static constexpr uint32_t kFrameFrequencyDefault = 48000;
static constexpr uint32_t kFrameChannelsDefault = 6;
static constexpr uint32_t kChannelSamplesDefault = 256;
static constexpr uint32_t kFrameSamplesMax =
kFrameChannelsDefault * kChannelSamplesDefault;
static const uint32_t kFrameSizeMax = sizeof(float) * kFrameSamplesMax;
static constexpr uint32_t kFrameSizeMax = sizeof(float) * kFrameSamplesMax;
virtual ~AudioDriver();

View File

@ -32,7 +32,7 @@ class AudioSystem {
public:
// TODO(gibbed): respect XAUDIO2_MAX_QUEUED_BUFFERS somehow (ie min(64,
// XAUDIO2_MAX_QUEUED_BUFFERS))
static const size_t kMaximumQueuedFrames = 64;
static constexpr size_t kMaximumQueuedFrames = 64;
virtual ~AudioSystem();
@ -81,7 +81,7 @@ class AudioSystem {
kernel::object_ref<kernel::XHostThread> worker_thread_;
xe::global_critical_region global_critical_region_;
static const size_t kMaximumClientCount = 8;
static constexpr size_t kMaximumClientCount = 8;
struct {
AudioDriver* driver;
uint32_t callback;

View File

@ -137,10 +137,10 @@ bool XAudio2AudioDriver::InitializeObjects(Objects& objects) {
api::XAUDIO2_DEBUG_CONFIGURATION config;
config.TraceMask = api::XE_XAUDIO2_LOG_ERRORS | api::XE_XAUDIO2_LOG_WARNINGS;
config.BreakMask = 0;
config.LogThreadID = FALSE;
config.LogTiming = TRUE;
config.LogFunctionName = TRUE;
config.LogFileline = TRUE;
config.LogThreadID = false;
config.LogTiming = true;
config.LogFunctionName = true;
config.LogFileline = true;
objects.audio->SetDebugConfiguration(&config);
hr = objects.audio->CreateMasteringVoice(&objects.mastering_voice);
@ -165,7 +165,7 @@ bool XAudio2AudioDriver::InitializeObjects(Objects& objects) {
waveformat.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample;
static const DWORD kChannelMasks[] = {
static constexpr DWORD kChannelMasks[] = {
0,
0,
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT,

View File

@ -106,7 +106,7 @@ class XAudio2AudioDriver : public AudioDriver {
uint32_t frame_size_;
bool need_format_conversion_;
static const uint32_t frame_count_ = api::XE_XAUDIO2_MAX_QUEUED_BUFFERS;
static constexpr uint32_t frame_count_ = api::XE_XAUDIO2_MAX_QUEUED_BUFFERS;
float frames_[frame_count_][kFrameSamplesMax];
uint32_t current_frame_ = 0;

View File

@ -18,7 +18,7 @@ namespace xe {
namespace apu {
namespace xma {
static const uint32_t kMaxFrameLength = 0x7FFF;
static constexpr uint32_t kMaxFrameLength = 0x7FFF;
// Get number of frames that /begin/ in this packet. This is valid only for XMA2
// packets

View File

@ -32,7 +32,7 @@ class XmaRegisterFile {
static const XmaRegisterInfo* GetRegisterInfo(uint32_t index);
static const size_t kRegisterCount = (0xFFFF + 1) / 4;
static constexpr size_t kRegisterCount = (0xFFFF + 1) / 4;
uint32_t values[kRegisterCount];
uint32_t operator[](uint32_t reg) const { return values[reg]; }

View File

@ -46,8 +46,8 @@ class BitMap {
std::vector<uint64_t>& data() { return data_; }
private:
const static size_t kDataSize = 8;
const static size_t kDataSizeBits = kDataSize * 8;
constexpr static size_t kDataSize = 8;
constexpr static size_t kDataSizeBits = kDataSize * 8;
std::vector<uint64_t> data_;
inline size_t TryAcquireAt(size_t i);
};

View File

@ -30,7 +30,7 @@ std::pair<size_t, size_t> NextUnsetRange(const Block* bits, size_t first,
return std::make_pair(size_t(first), size_t(0));
}
size_t last = first + length - 1;
const size_t block_bits = sizeof(Block) * CHAR_BIT;
constexpr size_t block_bits = sizeof(Block) * CHAR_BIT;
size_t block_first = first / block_bits;
size_t block_last = last / block_bits;
size_t range_start = SIZE_MAX;
@ -80,7 +80,7 @@ void SetRange(Block* bits, size_t first, size_t length) {
return;
}
size_t last = first + length - 1;
const size_t block_bits = sizeof(Block) * CHAR_BIT;
constexpr size_t block_bits = sizeof(Block) * CHAR_BIT;
size_t block_first = first / block_bits;
size_t block_last = last / block_bits;
Block set_first = ~((Block(1) << (first & (block_bits - 1))) - 1);

View File

@ -9,7 +9,7 @@
#include "xenia/base/cvar.h"
#include <iostream>
#define UTF_CPP_CPLUSPLUS 201703L
#define UTF_CPP_CPLUSPLUS 202002L
#include "third_party/utfcpp/source/utf8.h"
#include "xenia/base/console.h"
@ -125,9 +125,9 @@ std::string EscapeBasicString(const std::string_view view) {
result += "\\\\";
} else if (c < 0x20 || c == 0x7F) {
if (c <= 0xFFFF) {
result += fmt::format("\\u{:04X}", c);
result += fmt::format("\\u{:04X}", static_cast<uint32_t>(c));
} else {
result += fmt::format("\\u{:08X}", c);
result += fmt::format("\\u{:08X}", static_cast<uint32_t>(c));
}
} else {
utfcpp::append(static_cast<char32_t>(c), result);
@ -159,7 +159,7 @@ std::string EscapeMultilineBasicString(const std::string_view view) {
if (c == '\b') {
result += "\\b";
} else if (c == '\t' || c == '\n') {
result += c;
result += static_cast<uint32_t>(c);
} else if (c == '\f') {
result += "\\f";
} else if (c == '\r') {
@ -171,9 +171,9 @@ std::string EscapeMultilineBasicString(const std::string_view view) {
result += "\\\\";
} else if (c < 0x20 || c == 0x7F) {
if (c <= 0xFFFF) {
result += fmt::format("\\u{:04X}", c);
result += fmt::format("\\u{:04X}", static_cast<uint32_t>(c));
} else {
result += fmt::format("\\u{:08X}", c);
result += fmt::format("\\u{:08X}", static_cast<uint32_t>(c));
}
} else {
utfcpp::append(static_cast<char32_t>(c), result);
@ -189,8 +189,8 @@ std::string EscapeMultilineBasicString(const std::string_view view) {
}
std::string EscapeString(const std::string_view view) {
const auto multiline_chars = std::string_view("\r\n");
const auto escape_chars = std::string_view(
constexpr auto multiline_chars = std::string_view("\r\n");
constexpr auto escape_chars = std::string_view(
"\0\b\v\f"
"\x01\x02\x03\x04\x05\x06\x07\x0E\x0F"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"

View File

@ -168,7 +168,7 @@ static void ExceptionHandlerCallback(int signal_number, siginfo_t* signal_info,
mcontext.gregs[REG_EFL] = greg_t(thread_context.eflags);
uint32_t modified_register_index;
// The order must match the order in X64Register.
static const size_t kIntRegisterMap[] = {
static constexpr size_t kIntRegisterMap[] = {
REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP,
REG_RSI, REG_RDI, REG_R8, REG_R9, REG_R10, REG_R11,
REG_R12, REG_R13, REG_R14, REG_R15,

View File

@ -24,6 +24,19 @@ bool CreateParentFolder(const std::filesystem::path& path) {
return true;
}
std::error_code CreateFolder(const std::filesystem::path& path) {
if (std::filesystem::exists(path)) {
return {};
}
std::error_code ec;
if (std::filesystem::create_directories(path, ec)) {
return {};
}
return ec;
}
std::vector<FileInfo> ListDirectories(const std::filesystem::path& path) {
std::vector<FileInfo> files = ListFiles(path);
std::vector<FileInfo> directories = {};

View File

@ -45,6 +45,10 @@ std::filesystem::path GetUserFolder();
// attempting to create it.
bool CreateParentFolder(const std::filesystem::path& path);
// Creates folder on specified path.
// If folder already exists it returns success (no error).
std::error_code CreateFolder(const std::filesystem::path& path);
// Creates an empty file at the given path, overwriting if it exists.
bool CreateEmptyFile(const std::filesystem::path& path);
@ -65,14 +69,14 @@ bool TruncateStdioFile(FILE* file, uint64_t length);
struct FileAccess {
// Implies kFileReadData.
static const uint32_t kGenericRead = 0x80000000;
static constexpr uint32_t kGenericRead = 0x80000000;
// Implies kFileWriteData.
static const uint32_t kGenericWrite = 0x40000000;
static const uint32_t kGenericExecute = 0x20000000;
static const uint32_t kGenericAll = 0x10000000;
static const uint32_t kFileReadData = 0x00000001;
static const uint32_t kFileWriteData = 0x00000002;
static const uint32_t kFileAppendData = 0x00000004;
static constexpr uint32_t kGenericWrite = 0x40000000;
static constexpr uint32_t kGenericExecute = 0x20000000;
static constexpr uint32_t kGenericAll = 0x10000000;
static constexpr uint32_t kFileReadData = 0x00000001;
static constexpr uint32_t kFileWriteData = 0x00000002;
static constexpr uint32_t kFileAppendData = 0x00000004;
};
class FileHandle {

View File

@ -214,7 +214,7 @@ bool IsAndroidContentUri(const std::string_view source) {
// still including // in the comparison to distinguish from a file with a name
// starting from content: (as this is the main purpose of this code -
// separating URIs from file paths) more clearly.
static const char kContentSchema[] = "content://";
static constexpr char kContentSchema[] = "content://";
constexpr size_t kContentSchemaLength = xe::countof(kContentSchema) - 1;
return source.size() >= kContentSchemaLength &&
!xe_strncasecmp(source.data(), kContentSchema, kContentSchemaLength);

View File

@ -14,23 +14,23 @@
namespace xe::literals {
constexpr size_t operator""_KiB(unsigned long long int x) {
constexpr size_t operator""_KiB(const unsigned long long int x) {
return 1024ULL * x;
}
constexpr size_t operator""_MiB(unsigned long long int x) {
constexpr size_t operator""_MiB(const unsigned long long int x) {
return 1024_KiB * x;
}
constexpr size_t operator""_GiB(unsigned long long int x) {
constexpr size_t operator""_GiB(const unsigned long long int x) {
return 1024_MiB * x;
}
constexpr size_t operator""_TiB(unsigned long long int x) {
constexpr size_t operator""_TiB(const unsigned long long int x) {
return 1024_GiB * x;
}
constexpr size_t operator""_PiB(unsigned long long int x) {
constexpr size_t operator""_PiB(const unsigned long long int x) {
return 1024_TiB * x;
}

View File

@ -244,12 +244,12 @@ class Logger {
}
private:
static const size_t kBufferSize = 8_MiB;
static constexpr size_t kBufferSize = 8_MiB;
uint8_t buffer_[kBufferSize];
static const size_t kBlockSize = 256;
static const size_t kBlockCount = kBufferSize / kBlockSize;
static const size_t kBlockIndexMask = kBlockCount - 1;
static constexpr size_t kBlockSize = 256;
static constexpr size_t kBlockCount = kBufferSize / kBlockSize;
static constexpr size_t kBlockIndexMask = kBlockCount - 1;
static const size_t kClaimStrategyFootprint =
sizeof(std::atomic<dp::sequence_t>[kBlockCount]);
@ -353,14 +353,14 @@ class Logger {
? line_range.second[line_range.second_length - 1]
: line_range.first[line_range.first_length - 1];
if (last_char != '\n') {
const char suffix[1] = {'\n'};
constexpr char suffix[1] = {'\n'};
Write(suffix, 1);
}
rb.EndRead(std::move(line_range));
} else {
// Always ensure there is a newline.
const char suffix[1] = {'\n'};
constexpr char suffix[1] = {'\n'};
Write(suffix, 1);
}

View File

@ -60,7 +60,7 @@ static void RequestWin32HighResolutionTimer() {
ULONG minimum_resolution, maximum_resolution, current_resolution;
nt_query_timer_resolution(&minimum_resolution, &maximum_resolution,
&current_resolution);
nt_set_timer_resolution(maximum_resolution, TRUE, &current_resolution);
nt_set_timer_resolution(maximum_resolution, true, &current_resolution);
}
static void RequestWin32MMCSS() {
@ -74,7 +74,7 @@ static void RequestWin32MMCSS() {
dwm_enable_mmcss = reinterpret_cast<decltype(dwm_enable_mmcss)>(
GetProcAddress(dwmapi_module, "DwmEnableMMCSS"));
if (dwm_enable_mmcss) {
dwm_enable_mmcss(TRUE);
dwm_enable_mmcss(true);
}
FreeLibrary(dwmapi_module);
}

View File

@ -29,7 +29,7 @@ class Win32MappedMemory : public MappedMemory {
public:
// CreateFile returns INVALID_HANDLE_VALUE in case of failure.
// chrispy: made inline const to get around clang error
static inline const HANDLE kFileHandleInvalid = INVALID_HANDLE_VALUE;
static inline constexpr HANDLE kFileHandleInvalid = INVALID_HANDLE_VALUE;
// CreateFileMapping returns nullptr in case of failure.
static constexpr HANDLE kMappingHandleInvalid = nullptr;

View File

@ -473,7 +473,7 @@ void copy_and_swap_16_unaligned(void* dst_ptr, const void* src_ptr,
auto dst = reinterpret_cast<uint8_t*>(dst_ptr);
auto src = reinterpret_cast<const uint8_t*>(src_ptr);
const uint8x16_t tbl_idx =
constexpr uint8x16_t tbl_idx =
vcombine_u8(vcreate_u8(UINT64_C(0x0607040502030001)),
vcreate_u8(UINT64_C(0x0E0F0C0D0A0B0809)));
@ -507,7 +507,7 @@ void copy_and_swap_32_unaligned(void* dst_ptr, const void* src_ptr,
auto dst = reinterpret_cast<uint8_t*>(dst_ptr);
auto src = reinterpret_cast<const uint8_t*>(src_ptr);
const uint8x16_t tbl_idx =
constexpr uint8x16_t tbl_idx =
vcombine_u8(vcreate_u8(UINT64_C(0x405060700010203)),
vcreate_u8(UINT64_C(0x0C0D0E0F08090A0B)));
@ -539,7 +539,7 @@ void copy_and_swap_64_unaligned(void* dst_ptr, const void* src_ptr,
auto dst = reinterpret_cast<uint8_t*>(dst_ptr);
auto src = reinterpret_cast<const uint8_t*>(src_ptr);
const uint8x16_t tbl_idx =
constexpr uint8x16_t tbl_idx =
vcombine_u8(vcreate_u8(UINT64_C(0x0001020304050607)),
vcreate_u8(UINT64_C(0x08090A0B0C0D0E0F)));

View File

@ -813,12 +813,12 @@ template <unsigned Size>
static void smallset_const(void* destination, unsigned char fill_value) {
#if XE_ARCH_AMD64 == 1 && XE_COMPILER_MSVC == 1
if constexpr ((Size & 7) == 0) {
unsigned long long fill =
static unsigned long long fill =
static_cast<unsigned long long>(fill_value) * 0x0101010101010101ULL;
__stosq((unsigned long long*)destination, fill, Size / 8);
} else if constexpr ((Size & 3) == 0) {
static constexpr unsigned long fill =
static unsigned long fill =
static_cast<unsigned long>(fill_value) * 0x01010101U;
__stosd((unsigned long*)destination, fill, Size / 4);
// dont even bother with movsw, i think the operand size override prefix

View File

@ -181,12 +181,12 @@
namespace xe {
#if XE_PLATFORM_WIN32
const char kPathSeparator = '\\';
constexpr char kPathSeparator = '\\';
#else
const char kPathSeparator = '/';
constexpr char kPathSeparator = '/';
#endif // XE_PLATFORM_WIN32
const char kGuestPathSeparator = '\\';
constexpr char kGuestPathSeparator = '\\';
} // namespace xe
#if XE_ARCH_AMD64 == 1

View File

@ -17,4 +17,6 @@ project("xenia-base")
"debug_visualizers.natvis",
})
include("testing")
if enableTests then
include("testing")
end

View File

@ -96,7 +96,7 @@ class Win32Socket : public Socket {
// Keepalive for a looong time, as we may be paused by the debugger/etc.
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.onoff = true;
alive.keepalivetime = 7200000;
alive.keepaliveinterval = 6000;
DWORD bytes_returned;
@ -209,7 +209,7 @@ class Win32SocketServer : public SocketServer {
SOCKET socket = socket_;
socket_ = INVALID_SOCKET;
linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_onoff = true;
so_linger.l_linger = 30;
setsockopt(socket, SOL_SOCKET, SO_LINGER,
reinterpret_cast<const char*>(&so_linger), sizeof(so_linger));
@ -231,7 +231,7 @@ class Win32SocketServer : public SocketServer {
return false;
}
struct tcp_keepalive alive;
alive.onoff = TRUE;
alive.onoff = true;
alive.keepalivetime = 7200000;
alive.keepaliveinterval = 6000;
DWORD bytes_returned;

View File

@ -22,7 +22,7 @@
#include <strings.h>
#endif // !XE_PLATFORM_WIN32
#define UTF_CPP_CPLUSPLUS 201703L
#define UTF_CPP_CPLUSPLUS 202002L
#include "third_party/utfcpp/source/utf8.h"
namespace utfcpp = utf8;

View File

@ -16,6 +16,7 @@
#include <cstring>
#include <regex>
#include <string>
#include <variant>
#include "third_party/fmt/include/fmt/format.h"
#include "xenia/base/assert.h"
@ -428,6 +429,28 @@ inline vec128_t from_string<vec128_t>(const std::string_view value,
return v;
}
inline std::u16string read_u16string_and_swap(const char16_t* string_ptr) {
std::u16string input_str = std::u16string(string_ptr);
std::u16string output_str = {};
output_str.resize(input_str.size() + 1);
copy_and_swap_truncating(output_str.data(), input_str, input_str.size() + 1);
return output_str;
}
inline size_t size_in_bytes(std::variant<std::string, std::u16string> string,
bool include_terminator = true) {
if (std::holds_alternative<std::string>(string)) {
return std::get<std::string>(string).size() + include_terminator;
} else if (std::holds_alternative<std::u16string>(string)) {
return (std::get<std::u16string>(string).size() + include_terminator) *
sizeof(char16_t);
} else {
assert_always();
}
return 0;
}
} // namespace string_util
} // namespace xe

View File

@ -65,8 +65,8 @@ bool SetProcessPriorityClass(const uint32_t priority_class) {
}
bool IsUseNexusForGameBarEnabled() {
const LPCWSTR reg_path = L"SOFTWARE\\Microsoft\\GameBar";
const LPCWSTR key = L"UseNexusForGameBarEnabled";
constexpr LPCWSTR reg_path = L"SOFTWARE\\Microsoft\\GameBar";
constexpr LPCWSTR key = L"UseNexusForGameBarEnabled";
DWORD value = 0;
DWORD dataSize = sizeof(value);

View File

@ -516,7 +516,7 @@ TEST_CASE("create_and_close_file_mapping", "Virtual Memory Mapping") {
TEST_CASE("map_view", "[virtual_memory_mapping]") {
auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount());
const size_t length = 0x100;
constexpr size_t length = 0x100;
auto memory = xe::memory::CreateFileMappingHandle(
path, length, xe::memory::PageAccess::kReadWrite, true);
REQUIRE(memory != xe::memory::kFileMappingHandleInvalid);
@ -532,7 +532,7 @@ TEST_CASE("map_view", "[virtual_memory_mapping]") {
}
TEST_CASE("read_write_view", "[virtual_memory_mapping]") {
const size_t length = 0x100;
constexpr size_t length = 0x100;
auto path = fmt::format("xenia_test_{}", Clock::QueryHostTickCount());
auto memory = xe::memory::CreateFileMappingHandle(
path, length, xe::memory::PageAccess::kReadWrite, true);

View File

@ -404,19 +404,19 @@ class Timer : public WaitHandle {
#if XE_PLATFORM_WIN32
struct ThreadPriority {
static const int32_t kLowest = -2;
static const int32_t kBelowNormal = -1;
static const int32_t kNormal = 0;
static const int32_t kAboveNormal = 1;
static const int32_t kHighest = 2;
static constexpr int32_t kLowest = -2;
static constexpr int32_t kBelowNormal = -1;
static constexpr int32_t kNormal = 0;
static constexpr int32_t kAboveNormal = 1;
static constexpr int32_t kHighest = 2;
};
#else
struct ThreadPriority {
static const int32_t kLowest = 1;
static const int32_t kBelowNormal = 8;
static const int32_t kNormal = 16;
static const int32_t kAboveNormal = 24;
static const int32_t kHighest = 32;
static constexpr int32_t kLowest = 1;
static constexpr int32_t kBelowNormal = 8;
static constexpr int32_t kNormal = 16;
static constexpr int32_t kAboveNormal = 24;
static constexpr int32_t kHighest = 32;
};
#endif

View File

@ -170,7 +170,7 @@ void Sleep(std::chrono::microseconds duration) {
}
SleepResult AlertableSleep(std::chrono::microseconds duration) {
if (SleepEx(static_cast<DWORD>(duration.count() / 1000), TRUE) ==
if (SleepEx(static_cast<DWORD>(duration.count() / 1000), true) ==
WAIT_IO_COMPLETION) {
return SleepResult::kAlerted;
}
@ -211,7 +211,7 @@ WaitResult Wait(WaitHandle* wait_handle, bool is_alertable,
HANDLE handle = wait_handle->native_handle();
DWORD result;
DWORD timeout_dw = DWORD(timeout.count());
BOOL bAlertable = is_alertable ? TRUE : FALSE;
BOOL bAlertable = is_alertable ? true : false;
// todo: we might actually be able to use NtWaitForSingleObject even if its
// alertable, just need to study whether
// RtlDeactivateActivationContextUnsafeFast/RtlActivateActivationContext are
@ -251,7 +251,7 @@ WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
HANDLE handle_to_wait_on = wait_handle_to_wait_on->native_handle();
DWORD result =
SignalObjectAndWait(handle_to_signal, handle_to_wait_on,
DWORD(timeout.count()), is_alertable ? TRUE : FALSE);
DWORD(timeout.count()), is_alertable ? true : false);
switch (result) {
case WAIT_OBJECT_0:
return WaitResult::kSuccess;
@ -278,8 +278,8 @@ std::pair<WaitResult, size_t> WaitMultiple(WaitHandle* wait_handles[],
handles[i] = wait_handles[i]->native_handle();
}
DWORD result = WaitForMultipleObjectsEx(
static_cast<DWORD>(wait_handle_count), handles, wait_all ? TRUE : FALSE,
DWORD(timeout.count()), is_alertable ? TRUE : FALSE);
static_cast<DWORD>(wait_handle_count), handles, wait_all ? true : false,
DWORD(timeout.count()), is_alertable ? true : false);
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + wait_handle_count) {
return std::pair<WaitResult, size_t>(WaitResult::kSuccess,
result - WAIT_OBJECT_0);
@ -339,7 +339,7 @@ class Win32Event : public Win32Handle<Event> {
std::unique_ptr<Event> Event::CreateManualResetEvent(bool initial_state) {
HANDLE handle =
CreateEvent(nullptr, TRUE, initial_state ? TRUE : FALSE, nullptr);
CreateEvent(nullptr, true, initial_state ? true : false, nullptr);
if (handle) {
return std::make_unique<Win32Event>(handle);
} else {
@ -351,7 +351,7 @@ std::unique_ptr<Event> Event::CreateManualResetEvent(bool initial_state) {
std::unique_ptr<Event> Event::CreateAutoResetEvent(bool initial_state) {
HANDLE handle =
CreateEvent(nullptr, FALSE, initial_state ? TRUE : FALSE, nullptr);
CreateEvent(nullptr, false, initial_state ? true : false, nullptr);
if (handle) {
return std::make_unique<Win32Event>(handle);
} else {
@ -397,7 +397,7 @@ class Win32Mutant : public Win32Handle<Mutant> {
};
std::unique_ptr<Mutant> Mutant::Create(bool initial_owner) {
HANDLE handle = CreateMutex(nullptr, initial_owner ? TRUE : FALSE, nullptr);
HANDLE handle = CreateMutex(nullptr, initial_owner ? true : false, nullptr);
if (handle) {
return std::make_unique<Win32Mutant>(handle);
} else {
@ -433,7 +433,7 @@ class Win32Timer : public Win32Handle<Timer> {
callback_ ? reinterpret_cast<PTIMERAPCROUTINE>(CompletionRoutine)
: NULL;
return SetWaitableTimer(handle_, &due_time_li, 0, completion_routine, this,
FALSE)
false)
? true
: false;
}
@ -461,7 +461,7 @@ class Win32Timer : public Win32Handle<Timer> {
callback_ ? reinterpret_cast<PTIMERAPCROUTINE>(CompletionRoutine)
: NULL;
return SetWaitableTimer(handle_, &due_time_li, int32_t(period.count()),
completion_routine, this, FALSE)
completion_routine, this, false)
? true
: false;
}
@ -490,7 +490,7 @@ class Win32Timer : public Win32Handle<Timer> {
};
std::unique_ptr<Timer> Timer::CreateManualResetTimer() {
HANDLE handle = CreateWaitableTimer(NULL, TRUE, NULL);
HANDLE handle = CreateWaitableTimer(NULL, true, NULL);
if (handle) {
return std::make_unique<Win32Timer>(handle);
} else {
@ -500,7 +500,7 @@ std::unique_ptr<Timer> Timer::CreateManualResetTimer() {
}
std::unique_ptr<Timer> Timer::CreateSynchronizationTimer() {
HANDLE handle = CreateWaitableTimer(NULL, FALSE, NULL);
HANDLE handle = CreateWaitableTimer(NULL, false, NULL);
if (handle) {
return std::make_unique<Win32Timer>(handle);
} else {

View File

@ -15,7 +15,7 @@
#include <numeric>
#include <tuple>
#define UTF_CPP_CPLUSPLUS 201703L
#define UTF_CPP_CPLUSPLUS 202002L
#include "third_party/utfcpp/source/utf8.h"
namespace utfcpp = utf8;
@ -82,10 +82,10 @@ std::string upper_ascii(const std::string_view view) {
template <bool LOWER>
inline size_t hash_fnv1a(const std::string_view view) {
const size_t offset_basis = 0xCBF29CE484222325ull;
constexpr size_t offset_basis = 0xCBF29CE484222325ull;
// chrispy: constant capture errors on clang
auto work = [](size_t hash, uint8_t byte_of_data) {
const size_t prime = 0x00000100000001B3ull;
constexpr size_t prime = 0x00000100000001B3ull;
hash ^= byte_of_data;
hash *= prime;
return hash;

View File

@ -206,7 +206,7 @@ void SaveConfig() {
line_count = xe::utf8::count(*last);
}
const size_t value_alignment = 50;
constexpr size_t value_alignment = 50;
const auto& description = config_var->description();
if (!description.empty()) {
if (line_count < value_alignment) {

View File

@ -636,7 +636,7 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
_code_offsets code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
@ -681,13 +681,10 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
// rsp + 0 = return address
mov(qword[rsp + 8 * 3], rdx);
mov(qword[rsp + 8 * 2], rsi);
mov(qword[rsp + 8 * 1], rdi);
sub(rsp, stack_size);
code_offsets.prolog_stack_alloc = getSize();
@ -707,9 +704,6 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
code_offsets.epilog = getSize();
add(rsp, stack_size);
mov(rdi, qword[rsp + 8 * 1]);
mov(rsi, qword[rsp + 8 * 2]);
mov(rdx, qword[rsp + 8 * 3]);
ret();
#else
assert_always("Unknown platform ABI in host to guest thunk!");
@ -741,7 +735,7 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
_code_offsets code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
@ -787,7 +781,7 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
@ -844,7 +838,7 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
_code_offsets code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
@ -884,7 +878,7 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
size_t epilog;
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
constexpr size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
@ -1743,7 +1737,7 @@ void X64Backend::PrepareForReentry(void* ctx) {
bctx->current_stackpoint_depth = 0;
}
const uint32_t mxcsr_table[8] = {
constexpr uint32_t mxcsr_table[8] = {
0x1F80, 0x7F80, 0x5F80, 0x3F80, 0x9F80, 0xFF80, 0xDF80, 0xBF80,
};

View File

@ -120,7 +120,7 @@ constexpr unsigned int DEFAULT_FPU_MXCSR = 0x1F80;
extern const uint32_t mxcsr_table[8];
class X64Backend : public Backend {
public:
static const uint32_t kForceReturnAddress = 0x9FFF0000u;
static constexpr uint32_t kForceReturnAddress = 0x9FFF0000u;
explicit X64Backend();
~X64Backend() override;

View File

@ -79,13 +79,13 @@ class X64CodeCache : public CodeCache {
protected:
// All executable code falls within 0x80000000 to 0x9FFFFFFF, so we can
// only map enough for lookups within that range.
static const size_t kIndirectionTableSize = 0x1FFFFFFF;
static const uintptr_t kIndirectionTableBase = 0x80000000;
static constexpr size_t kIndirectionTableSize = 0x1FFFFFFF;
static constexpr uintptr_t kIndirectionTableBase = 0x80000000;
// The code range is 512MB, but we know the total code games will have is
// pretty small (dozens of mb at most) and our expansion is reasonablish
// so 256MB should be more than enough.
static const size_t kGeneratedCodeSize = 0x0FFFFFFF;
static const uintptr_t kGeneratedCodeExecuteBase = 0xA0000000;
static constexpr size_t kGeneratedCodeSize = 0x0FFFFFFF;
static constexpr uintptr_t kGeneratedCodeExecuteBase = 0xA0000000;
// Used for writing when PageAccess::kExecuteReadWrite is not supported.
static const uintptr_t kGeneratedCodeWriteBase =
kGeneratedCodeExecuteBase + kGeneratedCodeSize + 1;
@ -95,7 +95,7 @@ class X64CodeCache : public CodeCache {
// in analysis triggering.
// chrispy: raised this, some games that were compiled with low optimization
// levels can exceed this
static const size_t kMaximumFunctionCount = 1000000;
static constexpr size_t kMaximumFunctionCount = 1000000;
struct UnwindReservation {
size_t data_size = 0;

View File

@ -92,7 +92,7 @@ typedef struct _UNWIND_INFO {
// Size of unwind info per function.
// TODO(benvanik): move this to emitter.
static const uint32_t kUnwindInfoSize =
static constexpr uint32_t kUnwindInfoSize =
sizeof(UNWIND_INFO) + (sizeof(UNWIND_CODE) * (6 - 1));
class Win32X64CodeCache : public X64CodeCache {

View File

@ -72,17 +72,17 @@ using xe::cpu::hir::HIRBuilder;
using xe::cpu::hir::Instr;
using namespace xe::literals;
static const size_t kMaxCodeSize = 1_MiB;
static constexpr size_t kMaxCodeSize = 1_MiB;
// static const size_t kStashOffsetHigh = 32 + 32;
const uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
constexpr uint32_t X64Emitter::gpr_reg_map_[X64Emitter::GPR_COUNT] = {
Xbyak::Operand::RBX, Xbyak::Operand::R10, Xbyak::Operand::R11,
Xbyak::Operand::R12, Xbyak::Operand::R13, Xbyak::Operand::R14,
Xbyak::Operand::R15,
};
const uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
constexpr uint32_t X64Emitter::xmm_reg_map_[X64Emitter::XMM_COUNT] = {
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
};
@ -1242,11 +1242,11 @@ void* X64Emitter::FindQwordConstantOffset(uint64_t qwordvalue) {
return nullptr;
}
// First location to try and place constants.
static const uintptr_t kConstDataLocation = 0x20000000;
static const uintptr_t kConstDataSize = sizeof(xmm_consts);
static constexpr uintptr_t kConstDataLocation = 0x20000000;
static constexpr uintptr_t kConstDataSize = sizeof(xmm_consts);
// Increment the location by this amount for every allocation failure.
static const uintptr_t kConstDataIncrement = 0x00001000;
static constexpr uintptr_t kConstDataIncrement = 0x00001000;
// This function places constant data that is used by the emitter later on.
// Only called once and used by multiple instances of the emitter.

View File

@ -227,8 +227,8 @@ class X64Emitter : public Xbyak::CodeGenerator {
// xmm0-2
// Available: rbx, r10-r15
// xmm4-xmm15 (save to get xmm3)
static const int GPR_COUNT = 7;
static const int XMM_COUNT = 12;
static constexpr int GPR_COUNT = 7;
static constexpr int XMM_COUNT = 12;
static constexpr size_t kStashOffset = 32;
static void SetupReg(const hir::Value* v, Xbyak::Reg8& r) {
auto idx = gpr_reg_map_[v->reg.index];

View File

@ -123,7 +123,7 @@ struct OpBase {};
template <typename T, KeyType KEY_TYPE>
struct Op : OpBase {
static const KeyType key_type = KEY_TYPE;
static constexpr KeyType key_type = KEY_TYPE;
};
struct VoidOp : Op<VoidOp, KEY_TYPE_X> {
@ -298,7 +298,7 @@ struct I;
template <hir::Opcode OPCODE, typename DEST>
struct I<OPCODE, DEST> : DestField<DEST> {
typedef DestField<DEST> BASE;
static const hir::Opcode opcode = OPCODE;
static constexpr hir::Opcode opcode = OPCODE;
static const uint32_t key =
InstrKey::Construct<OPCODE, DEST::key_type>::value;
static const KeyType dest_type = DEST::key_type;
@ -318,7 +318,7 @@ struct I<OPCODE, DEST> : DestField<DEST> {
template <hir::Opcode OPCODE, typename DEST, typename SRC1>
struct I<OPCODE, DEST, SRC1> : DestField<DEST> {
typedef DestField<DEST> BASE;
static const hir::Opcode opcode = OPCODE;
static constexpr hir::Opcode opcode = OPCODE;
static const uint32_t key =
InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type>::value;
static const KeyType dest_type = DEST::key_type;
@ -341,7 +341,7 @@ struct I<OPCODE, DEST, SRC1> : DestField<DEST> {
template <hir::Opcode OPCODE, typename DEST, typename SRC1, typename SRC2>
struct I<OPCODE, DEST, SRC1, SRC2> : DestField<DEST> {
typedef DestField<DEST> BASE;
static const hir::Opcode opcode = OPCODE;
static constexpr hir::Opcode opcode = OPCODE;
static const uint32_t key =
InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type,
SRC2::key_type>::value;
@ -369,7 +369,7 @@ template <hir::Opcode OPCODE, typename DEST, typename SRC1, typename SRC2,
typename SRC3>
struct I<OPCODE, DEST, SRC1, SRC2, SRC3> : DestField<DEST> {
typedef DestField<DEST> BASE;
static const hir::Opcode opcode = OPCODE;
static constexpr hir::Opcode opcode = OPCODE;
static const uint32_t key =
InstrKey::Construct<OPCODE, DEST::key_type, SRC1::key_type,
SRC2::key_type, SRC3::key_type>::value;

View File

@ -95,7 +95,7 @@ class StackLayout {
});
static_assert(sizeof(Thunk) % 16 == 0,
"sizeof(Thunk) must be a multiple of 16!");
static const size_t THUNK_STACK_SIZE = sizeof(Thunk) + 8;
static constexpr size_t THUNK_STACK_SIZE = sizeof(Thunk) + 8;
/**
*
@ -121,16 +121,16 @@ class StackLayout {
* +------------------+
*
*/
static const size_t GUEST_STACK_SIZE = 104;
static constexpr size_t GUEST_STACK_SIZE = 104;
// was GUEST_CTX_HOME, can't remove because that'd throw stack alignment off.
// instead, can be used as a temporary in sequences
static const size_t GUEST_SCRATCH = 0;
static constexpr size_t GUEST_SCRATCH = 0;
// when profiling is on, this stores the nanosecond time at the start of the
// function
static const size_t GUEST_PROFILER_START = 80;
static const size_t GUEST_RET_ADDR = 88;
static const size_t GUEST_CALL_RET_ADDR = 96;
static constexpr size_t GUEST_PROFILER_START = 80;
static constexpr size_t GUEST_RET_ADDR = 88;
static constexpr size_t GUEST_CALL_RET_ADDR = 96;
};
} // namespace x64

View File

@ -48,7 +48,7 @@ bool ControlFlowSimplificationPass::Run(HIRBuilder* builder) {
block = builder->last_block();
while (block) {
auto prev_block = block->prev;
const uint32_t expected = Edge::DOMINATES | Edge::UNCONDITIONAL;
constexpr uint32_t expected = Edge::DOMINATES | Edge::UNCONDITIONAL;
if (block->incoming_edge_head &&
(block->incoming_edge_head->flags & expected) == expected) {
// Dominated by the incoming block.

View File

@ -2100,7 +2100,7 @@ Value* HIRBuilder::CountLeadingZeros(Value* value) {
ASSERT_INTEGER_TYPE(value);
if (value->IsConstantZero()) {
static const uint8_t zeros[] = {
static constexpr uint8_t zeros[] = {
8,
16,
32,

View File

@ -14,7 +14,7 @@ namespace cpu {
namespace hir {
#define DEFINE_OPCODE(num, name, sig, flags) \
const OpcodeInfo num##_info = { \
constexpr OpcodeInfo num##_info = { \
num, \
flags, \
sig, \

View File

@ -20,8 +20,8 @@ namespace cpu {
namespace ppc {
constexpr size_t kNamePad = 11;
const uint8_t kSpaces[kNamePad] = {0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20};
constexpr uint8_t kSpaces[kNamePad] = {0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20};
void PadStringBuffer(StringBuffer* str, size_t base, size_t pad);
void PrintDisasm_bcx(const PPCDecodeData& d, StringBuffer* str);

View File

@ -44,7 +44,7 @@ using namespace xe::literals;
typedef std::vector<std::pair<std::string, std::string>> AnnotationList;
const uint32_t START_ADDRESS = 0x80000000;
constexpr uint32_t START_ADDRESS = 0x80000000;
struct TestCase {
TestCase(uint32_t address, std::string& name)

View File

@ -43,7 +43,7 @@ struct Context {
typedef std::vector<std::pair<std::string, std::string>> AnnotationList;
const uint32_t START_ADDRESS = 0x00000000;
constexpr uint32_t START_ADDRESS = 0x00000000;
struct TestCase {
TestCase(uint32_t address, std::string& name)

View File

@ -17,6 +17,7 @@ project("xenia-cpu-ppc-tests")
"xenia-base",
"xenia-kernel",
"xenia-patcher",
"xenia-hid-skylander",
})
files({
"ppc_testing_main.cc",

View File

@ -21,9 +21,7 @@ project("xenia-cpu")
local_platform_files("hir")
local_platform_files("ppc")
include("testing")
include("ppc/testing")
-- filter({"configurations:Release", "platforms:Windows"})
-- buildoptions({
-- "/O1",
-- })
if enableTests then
include("testing")
include("ppc/testing")
end

View File

@ -104,7 +104,7 @@ bool InitializeStackWalker() {
options |= SYMOPT_LOAD_LINES;
options |= SYMOPT_FAIL_CRITICAL_ERRORS;
sym_set_options_(options);
if (!sym_initialize_(GetCurrentProcess(), nullptr, TRUE)) {
if (!sym_initialize_(GetCurrentProcess(), nullptr, true)) {
XELOGE("Unable to initialize symbol services - already in use?");
return false;
}
@ -192,7 +192,7 @@ class Win32StackWalker : public StackWalker {
}
// Setup the frame for walking.
STACKFRAME64 stack_frame = {0};
STACKFRAME64 stack_frame = {};
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrPC.Offset = thread_context.Rip;
stack_frame.AddrFrame.Mode = AddrModeFlat;

View File

@ -10,6 +10,7 @@ test_suite("xenia-cpu-tests", project_root, ".", {
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-hid-skylander",
-- TODO(benvanik): cut these dependencies?
"xenia-kernel",

View File

@ -50,10 +50,10 @@ DEFINE_bool(
DECLARE_bool(allow_plugins);
static const uint8_t xe_xex2_retail_key[16] = {
static constexpr uint8_t xe_xex2_retail_key[16] = {
0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3,
0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91};
static const uint8_t xe_xex2_devkit_key[16] = {
static constexpr uint8_t xe_xex2_devkit_key[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -1505,13 +1505,13 @@ std::vector<uint32_t> XexModule::PreanalyzeCode() {
uint32_t* range_end = (uint32_t*)memory()->TranslateVirtual(
high_8_aligned); // align down to multiple of 8
const uint8_t mfspr_r12_lr[4] = {0x7D, 0x88, 0x02, 0xA6};
constexpr uint8_t mfspr_r12_lr[4] = {0x7D, 0x88, 0x02, 0xA6};
// a blr instruction, with 4 zero bytes afterwards to pad the next address
// to 8 byte alignment
// if we see this prior to our address, we can assume we are a function
// start
const uint8_t blr[4] = {0x4E, 0x80, 0x0, 0x20};
constexpr uint8_t blr[4] = {0x4E, 0x80, 0x0, 0x20};
uint32_t blr32 = *reinterpret_cast<const uint32_t*>(&blr[0]);
@ -1631,7 +1631,7 @@ bool XexModule::FindSaveRest() {
// special codegen.
// __savegprlr_14 to __savegprlr_31
// __restgprlr_14 to __restgprlr_31
static const uint32_t gprlr_code_values[] = {
static constexpr uint32_t gprlr_code_values[] = {
0x68FFC1F9, // __savegprlr_14
0x70FFE1F9, // __savegprlr_15
0x78FF01FA, // __savegprlr_16
@ -1673,7 +1673,7 @@ bool XexModule::FindSaveRest() {
};
// __savefpr_14 to __savefpr_31
// __restfpr_14 to __restfpr_31
static const uint32_t fpr_code_values[] = {
static constexpr uint32_t fpr_code_values[] = {
0x70FFCCD9, // __savefpr_14
0x78FFECD9, // __savefpr_15
0x80FF0CDA, // __savefpr_16
@ -1717,7 +1717,7 @@ bool XexModule::FindSaveRest() {
// __savevmx_64 to __savevmx_127
// __restvmx_14 to __restvmx_31
// __restvmx_64 to __restvmx_127
static const uint32_t vmx_code_values[] = {
static constexpr uint32_t vmx_code_values[] = {
0xE0FE6039, // __savevmx_14
0xCE61CB7D, 0xF0FE6039, 0xCE61EB7D, 0x00FF6039, 0xCE610B7E, 0x10FF6039,
0xCE612B7E, 0x20FF6039, 0xCE614B7E, 0x30FF6039, 0xCE616B7E, 0x40FF6039,

View File

@ -55,7 +55,7 @@ void DebugWindow::DebugDialog::OnDraw(ImGuiIO& io) {
debug_window_.DrawFrame(io);
}
static const std::string kBaseTitle = "Xenia Debugger";
static constexpr std::string_view kBaseTitle = "Xenia Debugger";
DebugWindow::DebugWindow(Emulator* emulator,
xe::ui::WindowedAppContext& app_context)
@ -1460,7 +1460,7 @@ void DebugWindow::UpdateCache() {
auto object_table = kernel_state->object_table();
app_context_.CallInUIThread([this]() {
std::string title = kBaseTitle;
std::string title = std::string(kBaseTitle);
switch (processor_->execution_state()) {
case cpu::ExecutionState::kEnded:
title += " (ended)";

View File

@ -137,8 +137,8 @@ class DebugWindow : public cpu::DebugListener {
// The current state of the UI. Use this to synchronize multiple parts of the
// UI.
struct ImState {
static const int kRightPaneThreads = 0;
static const int kRightPaneMemory = 1;
static constexpr int kRightPaneThreads = 0;
static constexpr int kRightPaneMemory = 1;
int right_pane_tab = kRightPaneThreads;
cpu::ThreadDebugInfo* thread_info = nullptr;

View File

@ -41,9 +41,9 @@
#include "xenia/hid/input_system.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/xdbf_utils.h"
#include "xenia/kernel/xam/achievement_manager.h"
#include "xenia/kernel/xam/xam_module.h"
#include "xenia/kernel/xam/xdbf/spa_info.h"
#include "xenia/kernel/xbdm/xbdm_module.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include "xenia/memory.h"
@ -215,12 +215,15 @@ X_STATUS Emulator::Setup(
// logical processors.
xe::threading::EnableAffinityConfiguration();
XELOGI("{}: Initializing Memory...", __func__);
// Create memory system first, as it is required for other systems.
memory_ = std::make_unique<Memory>();
if (!memory_->Initialize()) {
return false;
XELOGE("{}: Cannot initalize memory!", __func__);
return result;
}
XELOGI("{}: Initializing Exports...", __func__);
// Shared export resolver used to attach and query for HLE exports.
export_resolver_ = std::make_unique<xe::cpu::ExportResolver>();
@ -241,30 +244,38 @@ X_STATUS Emulator::Setup(
backend.reset(new xe::cpu::backend::NullBackend());
}
XELOGI("{}: Initializing Processor...", __func__);
// Initialize the CPU.
processor_ = std::make_unique<xe::cpu::Processor>(memory_.get(),
export_resolver_.get());
if (!processor_->Setup(std::move(backend))) {
XELOGE("{}: Cannot initalize processor!", __func__);
return X_STATUS_UNSUCCESSFUL;
}
XELOGI("{}: Initializing Audio...", __func__);
// Initialize the APU.
if (audio_system_factory) {
audio_system_ = audio_system_factory(processor_.get());
if (!audio_system_) {
XELOGE("{}: Cannot initalize audio_system!", __func__);
return X_STATUS_NOT_IMPLEMENTED;
}
}
XELOGI("{}: Initializing Graphics...", __func__);
// Initialize the GPU.
graphics_system_ = graphics_system_factory();
if (!graphics_system_) {
XELOGE("{}: Cannot initalize graphics_system!", __func__);
return X_STATUS_NOT_IMPLEMENTED;
}
XELOGI("{}: Initializing HID...", __func__);
// Initialize the HID.
input_system_ = std::make_unique<xe::hid::InputSystem>(display_window_);
if (!input_system_) {
XELOGE("{}: Cannot initalize input_system!", __func__);
return X_STATUS_NOT_IMPLEMENTED;
}
if (input_driver_factory) {
@ -282,11 +293,13 @@ X_STATUS Emulator::Setup(
return result;
}
XELOGI("{}: Initializing VFS...", __func__);
// Bring up the virtual filesystem used by the kernel.
file_system_ = std::make_unique<xe::vfs::VirtualFileSystem>();
patcher_ = std::make_unique<xe::patcher::Patcher>(storage_root_);
XELOGI("{}: Initializing Kernel...", __func__);
// Shared kernel state.
kernel_state_ = std::make_unique<xe::kernel::KernelState>(this);
#define LOAD_KERNEL_MODULE(t) \
@ -299,18 +312,22 @@ X_STATUS Emulator::Setup(
plugin_loader_ = std::make_unique<xe::patcher::PluginLoader>(
kernel_state_.get(), storage_root() / "plugins");
XELOGI("{}: Starting graphics_system...", __func__);
// Setup the core components.
result = graphics_system_->Setup(
processor_.get(), kernel_state_.get(),
display_window_ ? &display_window_->app_context() : nullptr,
display_window_ != nullptr);
if (result) {
XELOGE("{}: Failed to setup graphics_system!", __func__);
return result;
}
if (audio_system_) {
XELOGI("{}: Starting audio_system...", __func__);
result = audio_system_->Setup(kernel_state_.get());
if (result) {
XELOGE("{}: Failed to setup audio_system!", __func__);
return result;
}
audio_media_player_ = std::make_unique<apu::AudioMediaPlayer>(
@ -444,7 +461,7 @@ Emulator::FileSignatureType Emulator::GetFileSignature(
}
const uint64_t file_size = std::filesystem::file_size(path);
const int64_t header_size = 4;
constexpr int64_t header_size = 4;
if (file_size < header_size) {
return FileSignatureType::Unknown;
@ -768,53 +785,93 @@ X_STATUS Emulator::DataMigration(const uint64_t xuid) {
return X_STATUS_SUCCESS;
}
X_STATUS Emulator::InstallContentPackage(
const std::filesystem::path& path,
ContentInstallationInfo& installation_info) {
std::unique_ptr<vfs::Device> device =
vfs::XContentContainerDevice::CreateContentDevice("", path);
X_STATUS Emulator::ProcessContentPackageHeader(
const std::filesystem::path& path, ContentInstallEntry& installation_info) {
installation_info.name_ = "Invalid Content Package!";
installation_info.content_type_ = XContentType::kInvalid;
installation_info.data_installation_path_ = xe::path_to_utf8(path.filename());
installation_info.content_name = "Invalid Content Package!";
installation_info.content_type = static_cast<XContentType>(0);
installation_info.installation_path = xe::path_to_utf8(path.filename());
const auto header = vfs::XContentContainerDevice::ReadContainerHeader(path);
if (!device || !device->Initialize()) {
if (!header || !header->content_header.is_magic_valid()) {
installation_info.installation_state_ = InstallState::failed;
installation_info.installation_result_ = X_STATUS_INVALID_PARAMETER;
installation_info.installation_error_message_ = "Invalid Package Type!";
XELOGE("Failed to initialize device");
return X_STATUS_INVALID_PARAMETER;
}
const vfs::XContentContainerDevice* dev =
(vfs::XContentContainerDevice*)device.get();
// Always install savefiles to user signed to slot 0.
const auto profile =
kernel_state_->xam_state()->profile_manager()->GetProfile(
static_cast<uint8_t>(0));
uint64_t xuid = dev->xuid();
if (dev->content_type() == static_cast<uint32_t>(XContentType::kSavedGame) &&
uint64_t xuid = header->content_metadata.profile_id;
if (header->content_metadata.content_type == XContentType::kSavedGame &&
profile) {
xuid = profile->xuid();
}
std::filesystem::path installation_path =
content_root() / fmt::format("{:016X}", xuid) /
fmt::format("{:08X}", dev->title_id()) /
fmt::format("{:08X}", dev->content_type()) / path.filename();
installation_info.data_installation_path_ = fmt::format(
"{:016X}/{:08X}/{:08X}/{}", xuid,
header->content_metadata.execution_info.title_id.get(),
static_cast<uint32_t>(header->content_metadata.content_type.get()),
path.filename());
std::filesystem::path header_path =
content_root() / fmt::format("{:016X}", xuid) /
fmt::format("{:08X}", dev->title_id()) / "Headers" /
fmt::format("{:08X}", dev->content_type()) / path.filename();
installation_info.header_installation_path_ = fmt::format(
"{:016X}/{:08X}/Headers/{:08X}/{}", xuid,
header->content_metadata.execution_info.title_id.get(),
static_cast<uint32_t>(header->content_metadata.content_type.get()),
path.filename());
installation_info.installation_path =
fmt::format("{:016X}/{:08X}/{:08X}/{}", xuid, dev->title_id(),
dev->content_type(), path.filename());
installation_info.name_ =
xe::to_utf8(header->content_metadata.display_name(XLanguage::kEnglish));
installation_info.content_type_ =
static_cast<XContentType>(header->content_metadata.content_type);
installation_info.content_size_ = header->content_metadata.content_size;
installation_info.installation_state_ = InstallState::pending;
installation_info.content_name =
xe::to_utf8(dev->content_header().display_name());
installation_info.content_type =
static_cast<XContentType>(dev->content_type());
installation_info.icon_ = imgui_drawer_->LoadImGuiIcon(
std::span<const uint8_t>(header->content_metadata.title_thumbnail,
header->content_metadata.title_thumbnail_size));
return X_STATUS_SUCCESS;
}
X_STATUS Emulator::InstallContentPackage(
const std::filesystem::path& path, ContentInstallEntry& installation_info) {
installation_info.installation_state_ = InstallState::preparing;
std::unique_ptr<vfs::XContentContainerDevice> device =
vfs::XContentContainerDevice::CreateContentDevice("", path);
if (!device || !device->Initialize()) {
XELOGE("Failed to initialize device");
return X_STATUS_INVALID_PARAMETER;
}
const std::filesystem::path installation_path =
content_root() / installation_info.data_installation_path_;
const std::filesystem::path header_path =
content_root() / installation_info.header_installation_path_;
if (!std::filesystem::exists(content_root())) {
const std::error_code ec = xe::filesystem::CreateFolder(content_root());
if (ec) {
installation_info.installation_state_ = InstallState::failed;
installation_info.installation_error_message_ = ec.message();
installation_info.installation_result_ = X_STATUS_ACCESS_DENIED;
return X_STATUS_ACCESS_DENIED;
}
}
const auto disk_space = std::filesystem::space(content_root());
if (disk_space.available < installation_info.content_size_ * 1.1f) {
installation_info.installation_state_ = InstallState::failed;
installation_info.installation_error_message_ = "Insufficient disk space!";
installation_info.installation_result_ = X_STATUS_DISK_FULL;
return X_STATUS_DISK_FULL;
}
if (std::filesystem::exists(installation_path)) {
// TODO(Gliniak): Popup
@ -823,21 +880,35 @@ X_STATUS Emulator::InstallContentPackage(
std::error_code error_code;
std::filesystem::create_directories(installation_path, error_code);
if (error_code) {
installation_info.content_name = "Cannot Create Content Directory!";
installation_info.installation_state_ = InstallState::failed;
installation_info.installation_error_message_ =
"Cannot Create Content Directory!";
installation_info.installation_result_ = error_code.value();
return error_code.value();
}
}
installation_info.content_size_ = device->data_size();
installation_info.installation_state_ = InstallState::installing;
vfs::VirtualFileSystem::ExtractContentHeader(device.get(), header_path);
X_STATUS error_code = vfs::VirtualFileSystem::ExtractContentFiles(
device.get(), installation_path);
device.get(), installation_path,
installation_info.currently_installed_size_);
if (error_code != X_ERROR_SUCCESS) {
installation_info.installation_state_ = InstallState::failed;
return error_code;
}
installation_info.installation_state_ = InstallState::installed;
installation_info.currently_installed_size_ = installation_info.content_size_;
kernel_state()->BroadcastNotification(kXNotificationLiveContentInstalled, 0);
if (installation_info.content_type_ == XContentType::kProfile) {
kernel_state_->xam_state()->profile_manager()->ReloadProfiles();
}
return error_code;
}
@ -862,7 +933,9 @@ X_STATUS Emulator::ExtractZarchivePackage(
}
}
return vfs::VirtualFileSystem::ExtractContentFiles(device.get(), extract_dir);
uint64_t progress = 0;
return vfs::VirtualFileSystem::ExtractContentFiles(device.get(), extract_dir,
progress);
}
X_STATUS Emulator::CreateZarchivePackage(
@ -1316,19 +1389,9 @@ std::string Emulator::FindLaunchModule() {
}
static std::string format_version(xex2_version version) {
// fmt::format doesn't like bit fields
uint32_t major, minor, build, qfe;
major = version.major;
minor = version.minor;
build = version.build;
qfe = version.qfe;
if (qfe) {
return fmt::format("{}.{}.{}.{}", major, minor, build, qfe);
}
if (build) {
return fmt::format("{}.{}.{}", major, minor, build);
}
return fmt::format("{}.{}", major, minor);
// fmt::format doesn't like bit fields we use + to bypass it
return fmt::format("{}.{}.{}.{}", +version.major, +version.minor,
+version.build, +version.qfe);
}
X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
@ -1427,9 +1490,13 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
}
game_config_load_callback_loop_next_index_ = SIZE_MAX;
const kernel::util::XdbfGameData db = kernel_state_->module_xdbf(module);
const auto db = kernel_state_->module_xdbf(module);
game_info_database_ = std::make_unique<kernel::util::GameInfoDatabase>(&db);
game_info_database_ =
std::make_unique<kernel::util::GameInfoDatabase>(db.get());
kernel_state_->xam_state()->LoadSpaInfo(db.get());
kernel_state_->xam_state()->user_tracker()->AddTitleToPlayedList();
if (game_info_database_->IsValid()) {
title_name_ = game_info_database_->GetTitleName(
@ -1490,17 +1557,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
if (!icon_block.empty()) {
display_window_->SetIcon(icon_block.data(), icon_block.size());
}
for (uint8_t slot = 0; slot < XUserMaxUserCount; slot++) {
auto user =
kernel_state_->xam_state()->profile_manager()->GetProfile(slot);
if (user) {
kernel_state_->xam_state()
->achievement_manager()
->LoadTitleAchievements(user->xuid(), db);
}
}
}
}
@ -1526,7 +1582,8 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
if (cvars::allow_plugins) {
if (plugin_loader_->IsAnyPluginForTitleAvailable(title_id_.value(),
module->hash().value())) {
plugin_loader_->LoadTitlePlugins(title_id_.value());
plugin_loader_->LoadTitlePlugins(title_id_.value(),
module->hash().value());
}
}

View File

@ -26,6 +26,7 @@
#include "xenia/memory.h"
#include "xenia/patcher/patcher.h"
#include "xenia/patcher/plugin_loader.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/vfs/device.h"
#include "xenia/vfs/virtual_file_system.h"
#include "xenia/xbox.h"
@ -55,8 +56,8 @@ class Window;
namespace xe {
constexpr fourcc_t kEmulatorSaveSignature = make_fourcc("XSAV");
static const std::string kDefaultGameSymbolicLink = "GAME:";
static const std::string kDefaultPartitionSymbolicLink = "D:";
static constexpr std::string_view kDefaultGameSymbolicLink = "GAME:";
static constexpr std::string_view kDefaultPartitionSymbolicLink = "D:";
// The main type that runs the whole emulator.
// This is responsible for initializing and managing all the various subsystems.
@ -171,6 +172,9 @@ class Emulator {
patcher::PluginLoader* plugin_loader() const { return plugin_loader_.get(); }
kernel::util::GameInfoDatabase* game_info_database() const {
return game_info_database_.get();
}
// Initializes the emulator and configures all components.
// The given window is used for display and the provided functions are used
// to create subsystems as required.
@ -231,18 +235,45 @@ class Emulator {
X_STATUS LaunchDefaultModule(const std::filesystem::path& path);
struct ContentInstallationInfo {
XContentType content_type;
std::string installation_path;
std::string content_name;
enum class InstallState : uint8_t {
preparing,
pending,
installing,
installed,
failed
};
constexpr static std::string_view installStateStringName[5] = {
"Preparing", "Pending", "Installing", "Success", "Failed"};
struct ContentInstallEntry {
ContentInstallEntry(std::filesystem::path path) : path_(path) {};
std::string name_{};
std::filesystem::path path_;
std::filesystem::path data_installation_path_;
std::filesystem::path header_installation_path_;
uint64_t content_size_ = 0;
uint64_t currently_installed_size_ = 0;
XContentType content_type_{};
InstallState installation_state_{};
X_STATUS installation_result_{};
std::string installation_error_message_{};
std::unique_ptr<ui::ImmediateTexture> icon_;
};
// Migrates data from content to content/xuid with respect to common data.
X_STATUS DataMigration(const uint64_t xuid);
X_STATUS ProcessContentPackageHeader(const std::filesystem::path& path,
ContentInstallEntry& installation_info);
// Extract content of package to content specific directory.
X_STATUS InstallContentPackage(const std::filesystem::path& path,
ContentInstallationInfo& installation_info);
ContentInstallEntry& installation_info);
// Extract content of zar package to desired directory.
X_STATUS ExtractZarchivePackage(const std::filesystem::path& path,

View File

@ -285,7 +285,7 @@ void CommandProcessor::WorkerThreadMain() {
do {
// If we spin around too much, revert to a "low-power" state.
if (loop_count > 500) {
const int wait_time_ms = 2;
constexpr int wait_time_ms = 2;
xe::threading::Wait(write_ptr_index_event_.get(), true,
std::chrono::milliseconds(wait_time_ms));
} else {

View File

@ -810,7 +810,7 @@ bool D3D12CommandProcessor::SetupContext() {
ID3D12Device* device = provider.GetDevice();
ID3D12CommandQueue* direct_queue = provider.GetDirectQueue();
fence_completion_event_ = CreateEvent(nullptr, FALSE, FALSE, nullptr);
fence_completion_event_ = CreateEvent(nullptr, false, false, nullptr);
if (fence_completion_event_ == nullptr) {
XELOGE("Failed to create the fence completion event");
return false;

View File

@ -109,7 +109,7 @@ namespace shaders {
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_scaled_cs.h"
} // namespace shaders
const D3D12RenderTargetCache::ResolveCopyShaderCode
constexpr D3D12RenderTargetCache::ResolveCopyShaderCode
D3D12RenderTargetCache::kResolveCopyShaders[size_t(
draw_util::ResolveCopyShaderIndex::kCount)] = {
{shaders::resolve_fast_32bpp_1x2xmsaa_cs,
@ -146,7 +146,7 @@ const D3D12RenderTargetCache::ResolveCopyShaderCode
sizeof(shaders::resolve_full_128bpp_scaled_cs)},
};
const uint32_t D3D12RenderTargetCache::kTransferUsedRootParameters[size_t(
constexpr uint32_t D3D12RenderTargetCache::kTransferUsedRootParameters[size_t(
TransferRootSignatureIndex::kCount)] = {
// kColor
kTransferUsedRootParameterColorSRVBit |
@ -184,7 +184,7 @@ const uint32_t D3D12RenderTargetCache::kTransferUsedRootParameters[size_t(
kTransferUsedRootParameterHostDepthAddressConstantBit,
};
const D3D12RenderTargetCache::TransferModeInfo
constexpr D3D12RenderTargetCache::TransferModeInfo
D3D12RenderTargetCache::kTransferModes[size_t(TransferMode::kCount)] = {
// kColorToDepth
{TransferOutput::kDepth, TransferRootSignatureIndex::kColor,
@ -467,7 +467,7 @@ bool D3D12RenderTargetCache::Initialize() {
// instead.
if (cvars::native_2x_msaa) {
msaa_2x_supported_ = true;
static const DXGI_FORMAT kRenderTargetDXGIFormats[] = {
static constexpr DXGI_FORMAT kRenderTargetDXGIFormats[] = {
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_SNORM,
DXGI_FORMAT_R32G32_FLOAT,
@ -969,7 +969,7 @@ bool D3D12RenderTargetCache::Initialize() {
D3D12_FILL_MODE_SOLID;
uint32_rtv_clear_pipeline_desc.RasterizerState.CullMode =
D3D12_CULL_MODE_NONE;
uint32_rtv_clear_pipeline_desc.RasterizerState.DepthClipEnable = TRUE;
uint32_rtv_clear_pipeline_desc.RasterizerState.DepthClipEnable = true;
uint32_rtv_clear_pipeline_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
uint32_rtv_clear_pipeline_desc.NumRenderTargets = 1;
@ -4327,12 +4327,12 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
}
pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
pipeline_desc.RasterizerState.DepthClipEnable = TRUE;
pipeline_desc.RasterizerState.DepthClipEnable = true;
pipeline_desc.InputLayout.pInputElementDescs = &pipeline_input_element_desc;
pipeline_desc.InputLayout.NumElements = 1;
pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
if (dest_is_stencil_bit) {
pipeline_desc.DepthStencilState.StencilEnable = TRUE;
pipeline_desc.DepthStencilState.StencilEnable = true;
pipeline_desc.DepthStencilState.FrontFace.StencilFailOp =
D3D12_STENCIL_OP_KEEP;
pipeline_desc.DepthStencilState.FrontFace.StencilDepthFailOp =
@ -4375,14 +4375,14 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
pipeline_desc.RTVFormats[0] =
GetColorOwnershipTransferDXGIFormat(dest_color_format);
} else {
pipeline_desc.DepthStencilState.DepthEnable = TRUE;
pipeline_desc.DepthStencilState.DepthEnable = true;
pipeline_desc.DepthStencilState.DepthWriteMask =
D3D12_DEPTH_WRITE_MASK_ALL;
pipeline_desc.DepthStencilState.DepthFunc =
cvars::depth_transfer_not_equal_test ? D3D12_COMPARISON_FUNC_NOT_EQUAL
: D3D12_COMPARISON_FUNC_ALWAYS;
if (use_stencil_reference_output_) {
pipeline_desc.DepthStencilState.StencilEnable = TRUE;
pipeline_desc.DepthStencilState.StencilEnable = true;
pipeline_desc.DepthStencilState.StencilWriteMask = UINT8_MAX;
pipeline_desc.DepthStencilState.FrontFace.StencilFailOp =
D3D12_STENCIL_OP_KEEP;
@ -4804,7 +4804,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
are_current_command_list_render_targets_valid_ = false;
if (dest_rt_key.is_depth) {
auto handle = dest_d3d12_rt.descriptor_draw().GetHandle();
command_list.D3DOMSetRenderTargets(0, nullptr, FALSE, &handle);
command_list.D3DOMSetRenderTargets(0, nullptr, false, &handle);
if (!use_stencil_reference_output_) {
command_processor_.SetStencilReference(UINT8_MAX);
}
@ -4812,7 +4812,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
auto handle = dest_d3d12_rt.descriptor_load_separate().IsValid()
? dest_d3d12_rt.descriptor_load_separate().GetHandle()
: dest_d3d12_rt.descriptor_draw().GetHandle();
command_list.D3DOMSetRenderTargets(1, &handle, FALSE, nullptr);
command_list.D3DOMSetRenderTargets(1, &handle, false, nullptr);
}
uint32_t dest_pitch_tiles = dest_rt_key.GetPitchTiles();
@ -5432,7 +5432,7 @@ void D3D12RenderTargetCache::PerformTransfersAndResolveClears(
? dest_d3d12_rt.descriptor_load_separate().GetHandle()
: dest_d3d12_rt.descriptor_draw().GetHandle());
command_list.D3DOMSetRenderTargets(1, &handle, FALSE, nullptr);
command_list.D3DOMSetRenderTargets(1, &handle, false, nullptr);
are_current_command_list_render_targets_valid_ = true;
D3D12_VIEWPORT clear_viewport;
clear_viewport.TopLeftX = float(clear_rect.left);
@ -5553,7 +5553,7 @@ void D3D12RenderTargetCache::SetCommandListRenderTargets(
: d3d12_rt.descriptor_draw().GetHandle();
}
command_processor_.GetDeferredCommandList().D3DOMSetRenderTargets(
rtv_count, rtv_handles, FALSE,
rtv_count, rtv_handles, false,
depth_and_color_render_targets[0] ? &dsv_handle : nullptr);
are_current_command_list_render_targets_valid_ = true;
}

View File

@ -394,7 +394,7 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange(
region_start_coordinates.Subresource = 0;
D3D12_TILE_REGION_SIZE region_size;
region_size.NumTiles = length_bytes / D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES;
region_size.UseBox = FALSE;
region_size.UseBox = false;
D3D12_TILE_RANGE_FLAGS range_flags = D3D12_TILE_RANGE_FLAG_NONE;
UINT heap_range_start_offset = 0;
direct_queue->UpdateTileMappings(

View File

@ -758,7 +758,7 @@ void D3D12TextureCache::WriteSampler(SamplerParameters parameters,
D3D12_FILTER_REDUCTION_TYPE_STANDARD);
desc.MaxAnisotropy = 1;
}
static const D3D12_TEXTURE_ADDRESS_MODE kAddressModeMap[] = {
static constexpr D3D12_TEXTURE_ADDRESS_MODE kAddressModeMap[] = {
/* kRepeat */ D3D12_TEXTURE_ADDRESS_MODE_WRAP,
/* kMirroredRepeat */ D3D12_TEXTURE_ADDRESS_MODE_MIRROR,
/* kClampToEdge */ D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
@ -968,7 +968,7 @@ bool D3D12TextureCache::EnsureScaledResolveMemoryCommitted(
D3D12_TILE_REGION_SIZE region_size;
region_size.NumTiles =
kScaledResolveHeapSize / D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES;
region_size.UseBox = FALSE;
region_size.UseBox = false;
D3D12_TILE_RANGE_FLAGS range_flags = D3D12_TILE_RANGE_FLAG_NONE;
UINT heap_range_start_offset = 0;
UINT range_tile_count =

View File

@ -144,7 +144,7 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
*reinterpret_cast<const D3DOMSetRenderTargetsArguments*>(stream);
command_list->OMSetRenderTargets(
args.num_render_target_descriptors, args.render_target_descriptors,
args.rts_single_handle_to_descriptor_range ? TRUE : FALSE,
args.rts_single_handle_to_descriptor_range ? true : false,
args.depth_stencil ? &args.depth_stencil_descriptor : nullptr);
} break;
case Command::kD3DOMSetStencilRef: {

View File

@ -269,7 +269,7 @@ class DeferredCommandList {
return;
}
static_assert(alignof(D3D12_RESOURCE_BARRIER) <= alignof(uintmax_t));
const size_t header_size =
constexpr size_t header_size =
xe::align(sizeof(UINT), alignof(D3D12_RESOURCE_BARRIER));
uint8_t* args = reinterpret_cast<uint8_t*>(WriteCommand(
Command::kD3DResourceBarrier,

View File

@ -272,7 +272,7 @@ void PipelineCache::InitializeShaderStorage(
}
pipeline_storage_file_flush_needed_ = false;
// 'XEPS'.
const uint32_t pipeline_storage_magic = 0x53504558;
constexpr uint32_t pipeline_storage_magic = 0x53504558;
// 'DXRO' or 'DXRT'.
const uint32_t pipeline_storage_magic_api =
edram_rov_used ? 0x4F525844 : 0x54525844;
@ -367,7 +367,7 @@ void PipelineCache::InitializeShaderStorage(
uint32_t version_swapped;
} shader_storage_file_header;
// 'XESH'.
const uint32_t shader_storage_magic = 0x48534558;
constexpr uint32_t shader_storage_magic = 0x48534558;
if (fread(&shader_storage_file_header, sizeof(shader_storage_file_header), 1,
shader_storage_file_) &&
shader_storage_file_header.magic == shader_storage_magic &&
@ -1577,7 +1577,7 @@ bool PipelineCache::GetCurrentStateDescription(
// Render targets and blending state. 32 because of 0x1F mask, for safety
// (all unknown to zero).
static const PipelineBlendFactor kBlendFactorMap[32] = {
static constexpr PipelineBlendFactor kBlendFactorMap[32] = {
/* 0 */ PipelineBlendFactor::kZero,
/* 1 */ PipelineBlendFactor::kOne,
/* 2 */ PipelineBlendFactor::kZero, // ?
@ -1603,7 +1603,7 @@ bool PipelineCache::GetCurrentStateDescription(
// Like kBlendFactorMap, but with color modes changed to alpha. Some
// pipelines aren't created in 545407E0 because a color mode is used for
// alpha.
static const PipelineBlendFactor kBlendFactorAlphaMap[32] = {
static constexpr PipelineBlendFactor kBlendFactorAlphaMap[32] = {
/* 0 */ PipelineBlendFactor::kZero,
/* 1 */ PipelineBlendFactor::kOne,
/* 2 */ PipelineBlendFactor::kZero, // ?
@ -3029,7 +3029,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
break;
}
state_desc.RasterizerState.FrontCounterClockwise =
description.front_counter_clockwise ? TRUE : FALSE;
description.front_counter_clockwise ? true : false;
state_desc.RasterizerState.DepthBias = description.depth_bias;
state_desc.RasterizerState.DepthBiasClamp = 0.0f;
// With non-square resolution scaling, make sure the worst-case impact is
@ -3041,7 +3041,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
float(std::max(render_target_cache_.draw_resolution_scale_x(),
render_target_cache_.draw_resolution_scale_y()));
state_desc.RasterizerState.DepthClipEnable =
description.depth_clip ? TRUE : FALSE;
description.depth_clip ? true : false;
uint32_t msaa_sample_count = uint32_t(1)
<< uint32_t(description.host_msaa_samples);
if (edram_rov_used) {
@ -3082,7 +3082,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
// Depth/stencil.
if (description.depth_func != xenos::CompareFunction::kAlways ||
description.depth_write) {
state_desc.DepthStencilState.DepthEnable = TRUE;
state_desc.DepthStencilState.DepthEnable = true;
state_desc.DepthStencilState.DepthWriteMask =
description.depth_write ? D3D12_DEPTH_WRITE_MASK_ALL
: D3D12_DEPTH_WRITE_MASK_ZERO;
@ -3093,7 +3093,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
uint32_t(description.depth_func));
}
if (description.stencil_enable) {
state_desc.DepthStencilState.StencilEnable = TRUE;
state_desc.DepthStencilState.StencilEnable = true;
state_desc.DepthStencilState.StencilReadMask =
description.stencil_read_mask;
state_desc.DepthStencilState.StencilWriteMask =
@ -3131,8 +3131,8 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
}
// Render targets and blending.
state_desc.BlendState.IndependentBlendEnable = TRUE;
static const D3D12_BLEND kBlendFactorMap[] = {
state_desc.BlendState.IndependentBlendEnable = true;
static constexpr D3D12_BLEND kBlendFactorMap[] = {
D3D12_BLEND_ZERO, D3D12_BLEND_ONE,
D3D12_BLEND_SRC_COLOR, D3D12_BLEND_INV_SRC_COLOR,
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA,
@ -3142,7 +3142,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
D3D12_BLEND_SRC_ALPHA_SAT,
};
// 8 entries for safety since 3 bits from the guest are passed directly.
static const D3D12_BLEND_OP kBlendOpMap[] = {
static constexpr D3D12_BLEND_OP kBlendOpMap[] = {
D3D12_BLEND_OP_ADD, D3D12_BLEND_OP_SUBTRACT, D3D12_BLEND_OP_MIN,
D3D12_BLEND_OP_MAX, D3D12_BLEND_OP_REV_SUBTRACT, D3D12_BLEND_OP_ADD,
D3D12_BLEND_OP_ADD, D3D12_BLEND_OP_ADD};
@ -3169,7 +3169,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
rt.src_blend_alpha != PipelineBlendFactor::kOne ||
rt.dest_blend_alpha != PipelineBlendFactor::kZero ||
rt.blend_op_alpha != xenos::BlendOp::kAdd) {
blend_desc.BlendEnable = TRUE;
blend_desc.BlendEnable = true;
blend_desc.SrcBlend = kBlendFactorMap[uint32_t(rt.src_blend)];
blend_desc.DestBlend = kBlendFactorMap[uint32_t(rt.dest_blend)];
blend_desc.BlendOp = kBlendOpMap[uint32_t(rt.blend_op)];
@ -3196,8 +3196,8 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
if (description.cull_mode == PipelineCullMode::kDisableRasterization) {
state_desc.PS.pShaderBytecode = nullptr;
state_desc.PS.BytecodeLength = 0;
state_desc.DepthStencilState.DepthEnable = FALSE;
state_desc.DepthStencilState.StencilEnable = FALSE;
state_desc.DepthStencilState.DepthEnable = false;
state_desc.DepthStencilState.StencilEnable = false;
}
// Create the D3D12 pipeline state object.

View File

@ -19,106 +19,110 @@ project("xenia-gpu-d3d12")
"../shaders/bytecode/d3d12_5_1/*.h",
})
group("src")
project("xenia-gpu-d3d12-trace-viewer")
uuid("7b5b9fcb-7bf1-43ff-a774-d4c41c8706be")
single_library_windowed_app_kind()
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
"xenia-hid-nop",
"xenia-kernel",
"xenia-patcher",
"xenia-ui",
"xenia-ui-d3d12",
"xenia-vfs",
})
links({
"aes_128",
"capstone",
"dxbc",
"fmt",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
files({
"d3d12_trace_viewer_main.cc",
"../../ui/windowed_app_main_"..platform_suffix..".cc",
})
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-viewer.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-viewer.txt",
})
end
filter("architecture:x86_64")
if enableMiscSubprojects then
group("src")
project("xenia-gpu-d3d12-trace-viewer")
uuid("7b5b9fcb-7bf1-43ff-a774-d4c41c8706be")
single_library_windowed_app_kind()
language("C++")
links({
"xenia-cpu-backend-x64",
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
"xenia-hid-nop",
"xenia-hid-skylander",
"xenia-kernel",
"xenia-patcher",
"xenia-ui",
"xenia-ui-d3d12",
"xenia-vfs",
})
group("src")
project("xenia-gpu-d3d12-trace-dump")
uuid("686b859c-0046-44c4-a02c-41fc3fb75698")
kind("ConsoleApp")
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
"xenia-hid-nop",
"xenia-kernel",
"xenia-ui",
"xenia-ui-d3d12",
"xenia-vfs",
"xenia-patcher",
})
links({
"aes_128",
"capstone",
"dxbc",
"fmt",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
files({
"d3d12_trace_dump_main.cc",
"../../base/console_app_main_"..platform_suffix..".cc",
})
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-dump.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-dump.txt",
})
end
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
"aes_128",
"capstone",
"dxbc",
"fmt",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
files({
"d3d12_trace_viewer_main.cc",
"../../ui/windowed_app_main_"..platform_suffix..".cc",
})
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-viewer.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-viewer.txt",
})
end
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
group("src")
project("xenia-gpu-d3d12-trace-dump")
uuid("686b859c-0046-44c4-a02c-41fc3fb75698")
kind("ConsoleApp")
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-d3d12",
"xenia-hid",
"xenia-hid-nop",
"xenia-hid-skylander",
"xenia-kernel",
"xenia-ui",
"xenia-ui-d3d12",
"xenia-vfs",
"xenia-patcher",
})
links({
"aes_128",
"capstone",
"dxbc",
"fmt",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
files({
"d3d12_trace_dump_main.cc",
"../../base/console_app_main_"..platform_suffix..".cc",
})
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-dump.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-dump.txt",
})
end
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
end

View File

@ -77,8 +77,8 @@ reg::RB_DEPTHCONTROL GetNormalizedDepthControl(const RegisterFile& regs) {
}
// https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
const int8_t kD3D10StandardSamplePositions2x[2][2] = {{4, 4}, {-4, -4}};
const int8_t kD3D10StandardSamplePositions4x[4][2] = {
constexpr int8_t kD3D10StandardSamplePositions2x[2][2] = {{4, 4}, {-4, -4}};
constexpr int8_t kD3D10StandardSamplePositions4x[4][2] = {
{-2, -6}, {6, -2}, {-6, 2}, {2, 6}};
void GetPreferredFacePolygonOffset(const RegisterFile& regs,
@ -907,7 +907,7 @@ void GetResolveEdramTileSpan(ResolveEdramInfo edram_info,
rows_out = y1 - y0;
}
const ResolveCopyShaderInfo
constexpr ResolveCopyShaderInfo
resolve_copy_shader_info[size_t(ResolveCopyShaderIndex::kCount)] = {
{"Resolve Copy Fast 32bpp 1x/2xMSAA", false, 4, 4, 6, 3},
{"Resolve Copy Fast 32bpp 4xMSAA", false, 4, 4, 6, 3},

View File

@ -2051,7 +2051,7 @@ void DxbcShaderTranslator::ProcessAllocInstruction(
}
}
const DxbcShaderTranslator::ShaderRdefType
constexpr DxbcShaderTranslator::ShaderRdefType
DxbcShaderTranslator::rdef_types_[size_t(
DxbcShaderTranslator::ShaderRdefTypeIndex::kCount)] = {
// kFloat
@ -2104,7 +2104,7 @@ const DxbcShaderTranslator::ShaderRdefType
dxbc::RdefVariableType::kUInt, 1, 4, 0, ShaderRdefTypeIndex::kUint4},
};
const DxbcShaderTranslator::SystemConstantRdef
constexpr DxbcShaderTranslator::SystemConstantRdef
DxbcShaderTranslator::system_constant_rdef_[size_t(
DxbcShaderTranslator::SystemConstants::Index::kCount)] = {
{"xe_flags", ShaderRdefTypeIndex::kUint, sizeof(uint32_t)},

View File

@ -585,7 +585,7 @@ uint32_t DxbcShaderTranslator::FindOrAddSamplerBinding(
name << "xe_sampler" << fetch_constant;
if (aniso_filter == xenos::AnisoFilter::kDisabled ||
aniso_filter == xenos::AnisoFilter::kUseFetchConst) {
static const char kFilterSuffixes[] = {'p', 'l', 'b', 'f'};
static constexpr char kFilterSuffixes[] = {'p', 'l', 'b', 'f'};
name << '_' << kFilterSuffixes[uint32_t(mag_filter)]
<< kFilterSuffixes[uint32_t(min_filter)]
<< kFilterSuffixes[uint32_t(mip_filter)];
@ -762,7 +762,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// sampling apparently round differently, so `mul` gives a value that would
// be floored as expected, but the left/upper pixel is still sampled
// instead.
const float rounding_offset = 1.5f / 1024.0f;
constexpr float rounding_offset = 1.5f / 1024.0f;
switch (instr.dimension) {
case xenos::FetchOpDimension::k1D:
offsets[0] = instr.attributes.offset_x + rounding_offset;

View File

@ -173,7 +173,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
: 1.0;
uint64_t last_frame_time = Clock::QueryGuestTickCount();
// Sleep for 90% of the vblank duration, spin for 10%
const double duration_scalar = 0.90;
constexpr double duration_scalar = 0.90;
while (frame_limiter_worker_running_) {
register_file()->values[XE_GPU_REG_D1MODE_V_COUNTER] +=

View File

@ -47,8 +47,8 @@ PacketCategory PacketDisassembler::GetPacketCategory(const uint8_t* base_ptr) {
bool PacketDisassembler::DisasmPacketType0(const uint8_t* base_ptr,
uint32_t packet,
PacketInfo* out_info) {
static const PacketTypeInfo type_0_info = {PacketCategory::kGeneric,
"PM4_TYPE0"};
static constexpr PacketTypeInfo type_0_info = {PacketCategory::kGeneric,
"PM4_TYPE0"};
out_info->type_info = &type_0_info;
uint32_t count = ((packet >> 16) & 0x3FFF) + 1;
@ -72,8 +72,8 @@ bool PacketDisassembler::DisasmPacketType0(const uint8_t* base_ptr,
bool PacketDisassembler::DisasmPacketType1(const uint8_t* base_ptr,
uint32_t packet,
PacketInfo* out_info) {
static const PacketTypeInfo type_1_info = {PacketCategory::kGeneric,
"PM4_TYPE1"};
static constexpr PacketTypeInfo type_1_info = {PacketCategory::kGeneric,
"PM4_TYPE1"};
out_info->type_info = &type_1_info;
out_info->count = 1 + 2;
@ -94,8 +94,8 @@ bool PacketDisassembler::DisasmPacketType1(const uint8_t* base_ptr,
bool PacketDisassembler::DisasmPacketType2(const uint8_t* base_ptr,
uint32_t packet,
PacketInfo* out_info) {
static const PacketTypeInfo type_2_info = {PacketCategory::kGeneric,
"PM4_TYPE2"};
static constexpr PacketTypeInfo type_2_info = {PacketCategory::kGeneric,
"PM4_TYPE2"};
out_info->type_info = &type_2_info;
out_info->count = 1;
@ -106,8 +106,8 @@ bool PacketDisassembler::DisasmPacketType2(const uint8_t* base_ptr,
bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
uint32_t packet,
PacketInfo* out_info) {
static const PacketTypeInfo type_3_unknown_info = {PacketCategory::kGeneric,
"PM4_TYPE3_UNKNOWN"};
static constexpr PacketTypeInfo type_3_unknown_info = {
PacketCategory::kGeneric, "PM4_TYPE3_UNKNOWN"};
out_info->type_info = &type_3_unknown_info;
uint32_t opcode = (packet >> 8) & 0x7F;
@ -127,8 +127,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
switch (opcode) {
case PM4_ME_INIT: {
// initialize CP's micro-engine
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_ME_INIT"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_ME_INIT"};
out_actions.emplace_back(PacketAction::MeInit((uint32_t*)ptr, count));
@ -138,15 +138,15 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
case PM4_NOP: {
// skip N 32-bit words to get to the next packet
// No-op, ignore some data.
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_NOP"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_NOP"};
out_info->type_info = &op_info;
break;
}
case PM4_INTERRUPT: {
// generate interrupt from the command stream
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INTERRUPT"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INTERRUPT"};
out_info->type_info = &op_info;
PacketAction intaction;
@ -160,8 +160,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
// VdSwap will post this to tell us we need to swap the screen/fire an
// interrupt.
// 63 words here, but only the first has any data.
static const PacketTypeInfo op_info = {PacketCategory::kSwap,
"PM4_XE_SWAP"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kSwap,
"PM4_XE_SWAP"};
out_info->type_info = &op_info;
PacketAction xsa;
@ -175,8 +175,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
case PM4_INDIRECT_BUFFER:
case PM4_INDIRECT_BUFFER_PFD: {
// indirect buffer dispatch
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INDIRECT_BUFFER"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INDIRECT_BUFFER"};
out_info->type_info = &op_info;
PacketAction iba;
@ -189,8 +189,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_WAIT_REG_MEM: {
// wait until a register or memory location is a specific value
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_WAIT_REG_MEM"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_WAIT_REG_MEM"};
out_info->type_info = &op_info;
PacketAction wait_action;
@ -209,8 +209,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
case PM4_REG_RMW: {
// register read/modify/write
// ? (used during shader upload and edram setup)
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_REG_RMW"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_REG_RMW"};
out_info->type_info = &op_info;
PacketAction rmw_action;
rmw_action.type = PacketAction::Type::kRegRmw;
@ -227,8 +227,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_COND_WRITE: {
// conditional write to memory or register
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_COND_WRITE"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_COND_WRITE"};
out_info->type_info = &op_info;
PacketAction cwr_action;
cwr_action.type = PacketAction::Type::kCondWrite;
@ -247,8 +247,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_EVENT_WRITE: {
// generate an event that creates a write to memory when completed
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE"};
out_info->type_info = &op_info;
PacketAction evw_action;
evw_action.type = Type::kEventWrite;
@ -260,8 +260,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_EVENT_WRITE_SHD: {
// generate a VS|PS_done event
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE_SHD"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE_SHD"};
out_info->type_info = &op_info;
PacketAction evws_action;
evws_action.type = Type::kEventWriteSHD;
@ -276,8 +276,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_EVENT_WRITE_EXT: {
// generate a screen extent event
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE_EXT"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_EVENT_WRITE_EXT"};
out_info->type_info = &op_info;
PacketAction eve_action;
@ -295,8 +295,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
case PM4_DRAW_INDX: {
// initiate fetch of index buffer and draw
// dword0 = viz query info
static const PacketTypeInfo op_info = {PacketCategory::kDraw,
"PM4_DRAW_INDX"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kDraw,
"PM4_DRAW_INDX"};
out_info->type_info = &op_info;
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4);
@ -337,8 +337,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_DRAW_INDX_2: {
// draw using supplied indices in packet
static const PacketTypeInfo op_info = {PacketCategory::kDraw,
"PM4_DRAW_INDX_2"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kDraw,
"PM4_DRAW_INDX_2"};
out_info->type_info = &op_info;
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t index_count = dword0 >> 16;
@ -372,8 +372,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
// load constant into chip and to memory
// PM4_REG(reg) ((0x4 << 16) | (GSL_HAL_SUBBLOCK_OFFSET(reg)))
// reg - 0x2000
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_CONSTANT"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_CONSTANT"};
out_info->type_info = &op_info;
uint32_t offset_type = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t index = offset_type & 0x7FF;
@ -407,8 +407,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_CONSTANT2: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_CONSTANT2"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_CONSTANT2"};
out_info->type_info = &op_info;
uint32_t offset_type = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t index = offset_type & 0xFFFF;
@ -424,8 +424,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_LOAD_ALU_CONSTANT: {
// load constants from memory
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_LOAD_ALU_CONSTANT"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_LOAD_ALU_CONSTANT"};
out_info->type_info = &op_info;
uint32_t address = xe::load_and_swap<uint32_t>(ptr + 0);
address &= 0x3FFFFFFF;
@ -465,8 +465,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_SHADER_CONSTANTS: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_SHADER_CONSTANTS"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_SHADER_CONSTANTS"};
out_info->type_info = &op_info;
uint32_t offset_type = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t index = offset_type & 0xFFFF;
@ -481,8 +481,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_IM_LOAD: {
// load sequencer instruction memory (pointer-based)
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_IM_LOAD"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_IM_LOAD"};
out_info->type_info = &op_info;
uint32_t addr_type = xe::load_and_swap<uint32_t>(ptr + 0);
auto shader_type = static_cast<xenos::ShaderType>(addr_type & 0x3);
@ -506,8 +506,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_IM_LOAD_IMMEDIATE: {
// load sequencer instruction memory (code embedded in packet)
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_IM_LOAD_IMMEDIATE"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_IM_LOAD_IMMEDIATE"};
out_info->type_info = &op_info;
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4);
@ -534,8 +534,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
}
case PM4_INVALIDATE_STATE: {
// selective invalidation of state pointers
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INVALIDATE_STATE"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_INVALIDATE_STATE"};
out_info->type_info = &op_info;
uint32_t mask = xe::load_and_swap<uint32_t>(ptr + 0);
@ -547,8 +547,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_BIN_MASK_LO: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_MASK_LO"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_MASK_LO"};
out_info->type_info = &op_info;
uint32_t value = xe::load_and_swap<uint32_t>(ptr);
// bin_mask_ = (bin_mask_ & 0xFFFFFFFF00000000ull) | value;
@ -561,8 +561,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_BIN_MASK_HI: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_MASK_HI"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_MASK_HI"};
out_info->type_info = &op_info;
uint32_t value = xe::load_and_swap<uint32_t>(ptr);
@ -573,8 +573,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_BIN_SELECT_LO: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_SELECT_LO"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_SELECT_LO"};
out_info->type_info = &op_info;
uint32_t value = xe::load_and_swap<uint32_t>(ptr);
PacketAction action;
@ -585,8 +585,8 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
break;
}
case PM4_SET_BIN_SELECT_HI: {
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_SELECT_HI"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_SET_BIN_SELECT_HI"};
out_info->type_info = &op_info;
uint32_t value = xe::load_and_swap<uint32_t>(ptr);
@ -670,14 +670,14 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
// Ignored packets - useful if breaking on the default handler below.
case 0x50: { // 0xC0015000 usually 2 words, 0xFFFFFFFF / 0x00000000
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_TYPE3_0x50"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_TYPE3_0x50"};
out_info->type_info = &op_info;
break;
}
case 0x51: { // 0xC0015100 usually 2 words, 0xFFFFFFFF / 0xFFFFFFFF
static const PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_TYPE3_0x51"};
static constexpr PacketTypeInfo op_info = {PacketCategory::kGeneric,
"PM4_TYPE3_0x51"};
out_info->type_info = &op_info;
break;
}

View File

@ -902,7 +902,8 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_SHD(
data_value = GpuSwap(data_value, endianness);
uint8_t* write_destination = memory_->TranslatePhysical(address);
if (address > 0x1FFFFFFF) {
uint32_t writeback_base = register_file_->values[XE_GPU_REG_WRITEBACK_BASE];
uint32_t writeback_base =
register_file_->values[XE_GPU_REG_WRITEBACK_START];
uint32_t writeback_size = register_file_->values[XE_GPU_REG_WRITEBACK_SIZE];
uint32_t writeback_offset = address - writeback_base;
// check whether the guest has written writeback base. if they haven't, skip

File diff suppressed because it is too large Load Diff

View File

@ -13,14 +13,14 @@ namespace xe {
namespace gpu {
namespace reg {
const Register RB_COLOR_INFO::rt_register_indices[4] = {
constexpr Register RB_COLOR_INFO::rt_register_indices[4] = {
XE_GPU_REG_RB_COLOR_INFO,
XE_GPU_REG_RB_COLOR1_INFO,
XE_GPU_REG_RB_COLOR2_INFO,
XE_GPU_REG_RB_COLOR3_INFO,
};
const Register RB_BLENDCONTROL::rt_register_indices[4] = {
constexpr Register RB_BLENDCONTROL::rt_register_indices[4] = {
XE_GPU_REG_RB_BLENDCONTROL0,
XE_GPU_REG_RB_BLENDCONTROL1,
XE_GPU_REG_RB_BLENDCONTROL2,

View File

@ -121,11 +121,11 @@ constexpr SwizzleSource GetSwizzledAluSourceComponent(
component_index));
}
inline char GetCharForComponentIndex(uint32_t i) {
const static char kChars[] = {'x', 'y', 'z', 'w'};
constexpr static char kChars[] = {'x', 'y', 'z', 'w'};
return kChars[i];
}
inline char GetCharForSwizzle(SwizzleSource swizzle_source) {
const static char kChars[] = {'x', 'y', 'z', 'w', '0', '1'};
constexpr static char kChars[] = {'x', 'y', 'z', 'w', '0', '1'};
return kChars[static_cast<uint32_t>(swizzle_source)];
}

View File

@ -144,7 +144,7 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
EnsureBuildPointAvailable();
// Lookup table for variants of instructions with similar structure.
static const unsigned int kOps[] = {
static constexpr unsigned int kOps[] = {
static_cast<unsigned int>(spv::OpNop), // kAdd
static_cast<unsigned int>(spv::OpNop), // kMul
static_cast<unsigned int>(spv::OpFOrdGreaterThanEqual), // kMax
@ -883,7 +883,7 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
EnsureBuildPointAvailable();
// Lookup table for variants of instructions with similar structure.
static const unsigned int kOps[] = {
static constexpr unsigned int kOps[] = {
static_cast<unsigned int>(spv::OpFAdd), // kAdds
static_cast<unsigned int>(spv::OpFAdd), // kAddsPrev
static_cast<unsigned int>(spv::OpNop), // kMuls

View File

@ -763,7 +763,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
// multiplication in texture sampling apparently round differently, so
// `mul` gives a value that would be floored as expected, but the
// left/upper pixel is still sampled instead.
const float kRoundingOffset = 1.5f / 1024.0f;
constexpr float kRoundingOffset = 1.5f / 1024.0f;
switch (instr.dimension) {
case xenos::FetchOpDimension::k1D:
offset_values[0] = instr.attributes.offset_x + kRoundingOffset;
@ -2333,7 +2333,7 @@ size_t SpirvShaderTranslator::FindOrAddSamplerBinding(
new_sampler_binding.mip_filter = mip_filter;
new_sampler_binding.aniso_filter = aniso_filter;
std::ostringstream name;
static const char kFilterSuffixes[] = {'p', 'l', 'b', 'f'};
static constexpr char kFilterSuffixes[] = {'p', 'l', 'b', 'f'};
name << "xe_sampler" << fetch_constant << '_'
<< kFilterSuffixes[uint32_t(mag_filter)]
<< kFilterSuffixes[uint32_t(min_filter)]

View File

@ -566,7 +566,7 @@ void SpirvShaderTranslator::CompleteFragmentShaderInMain() {
spv::Id alpha_test_result_non_not_equal;
{
// Function other than "not equal".
static const spv::Op kAlphaTestOps[] = {
static constexpr spv::Op kAlphaTestOps[] = {
spv::OpFOrdLessThan, spv::OpFOrdEqual, spv::OpFOrdGreaterThan};
for (uint32_t i = 0; i < 3; ++i) {
spv::Id alpha_test_comparison_result = builder_->createBinOp(

View File

@ -60,7 +60,7 @@ void ConvertTexelCTX1ToR8G8(xenos::Endian endian, void* output,
} block;
static_assert(sizeof(block) == 8, "CTX1 block mismatch");
const uint32_t bytes_per_block = 8;
constexpr uint32_t bytes_per_block = 8;
CopySwapBlock(endian, block.data, input, bytes_per_block);
uint8_t cr[4] = {
@ -84,7 +84,7 @@ void ConvertTexelCTX1ToR8G8(xenos::Endian endian, void* output,
void ConvertTexelDXT3AToDXT3(xenos::Endian endian, void* output,
const void* input, size_t length) {
const uint32_t bytes_per_block = 16;
constexpr uint32_t bytes_per_block = 16;
auto output_bytes = static_cast<uint8_t*>(output);
CopySwapBlock(endian, &output_bytes[0], input, 8);
std::memset(&output_bytes[8], 0, 8);

View File

@ -100,7 +100,7 @@ void TextureDump(const TextureInfo& src, void* buffer, size_t length) {
FILE* handle = filesystem::OpenFile(path, "wb");
if (handle) {
const char signature[4] = {'D', 'D', 'S', ' '};
constexpr char signature[4] = {'D', 'D', 'S', ' '};
fwrite(&signature, sizeof(signature), 1, handle);
fwrite(&dds_header, sizeof(dds_header), 1, handle);
fwrite(buffer, 1, length, handle);

View File

@ -19,7 +19,7 @@ using namespace xe::gpu::xenos;
#define FORMAT_INFO(texture_format, format, block_width, block_height, bits_per_pixel) \
{xenos::TextureFormat::texture_format, FormatType::format, block_width, block_height, bits_per_pixel}
const FormatInfo* FormatInfo::Get(uint32_t gpu_format) {
static const FormatInfo format_infos[64] = {
static constexpr FormatInfo format_infos[64] = {
#include "texture_info_formats.inl"
};
return &format_infos[gpu_format];

View File

@ -16,7 +16,7 @@ namespace xe {
namespace gpu {
// Trace file extension.
static const char kTraceExtension[] = "xtr";
static constexpr char kTraceExtension[] = "xtr";
// Any byte changes to the files should bump this version.
// Only builds with matching versions will work.

View File

@ -47,11 +47,11 @@ namespace gpu {
using namespace xe::gpu::xenos;
static const ImVec4 kColorError =
static constexpr ImVec4 kColorError =
ImVec4(255 / 255.0f, 0 / 255.0f, 0 / 255.0f, 255 / 255.0f);
static const ImVec4 kColorComment =
static constexpr ImVec4 kColorComment =
ImVec4(42 / 255.0f, 179 / 255.0f, 0 / 255.0f, 255 / 255.0f);
static const ImVec4 kColorIgnored =
static constexpr ImVec4 kColorIgnored =
ImVec4(100 / 255.0f, 100 / 255.0f, 100 / 255.0f, 255 / 255.0f);
TraceViewer::TraceViewer(xe::ui::WindowedAppContext& app_context,
@ -815,10 +815,11 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
}
ImGui::BeginChild("#indices", ImVec2(0, 300));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 0));
int display_start, display_end;
ImGui::CalcListClipping(vertex_count, ImGui::GetTextLineHeight(),
&display_start, &display_end);
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
int display_start = 0;
int display_end = 0;
// ImGui::CalcListClipping(vertex_count, ImGui::GetTextLineHeight(),
// &display_start, &display_end);
// ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(column_count);
if (display_start <= 1) {
for (size_t el_index = 0; el_index < vertex_binding.attributes.size();
@ -1641,11 +1642,12 @@ void TraceViewer::DrawStateUI() {
ImGui::BeginChild("#vsvertices", ImVec2(0, 300));
int display_start, display_end;
ImGui::CalcListClipping(int(vertices.size() / 4),
ImGui::GetTextLineHeight(), &display_start,
&display_end);
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
int display_start = 0;
int display_end = 0;
// ImGui::CalcListClipping(int(vertices.size() / 4),
// ImGui::GetTextLineHeight(), &display_start,
// &display_end);
// ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(int(el_size), "#vsvertices", true);
for (size_t i = display_start; i < display_end; i++) {
@ -1706,11 +1708,12 @@ void TraceViewer::DrawStateUI() {
}
ImGui::BeginChild("#indices", ImVec2(0, 300));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
int display_start, display_end;
ImGui::CalcListClipping(1 + draw_info.index_count,
ImGui::GetTextLineHeight(), &display_start,
&display_end);
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
int display_start = 0;
int display_end = 0;
// ImGui::CalcListClipping(1 + draw_info.index_count,
// ImGui::GetTextLineHeight(), &display_start,
// &display_end);
// ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(2, "#indices", true);
ImGui::SetColumnOffset(1, 60);
if (display_start <= 1) {

View File

@ -13,7 +13,7 @@ namespace xe {
namespace gpu {
namespace ucode {
const AluScalarOpcodeInfo kAluScalarOpcodeInfos[64] = {
constexpr AluScalarOpcodeInfo kAluScalarOpcodeInfos[64] = {
{"adds", 1, true, kAluOpChangedStateNone},
{"adds_prev", 1, false, kAluOpChangedStateNone},
{"muls", 1, true, kAluOpChangedStateNone},
@ -80,7 +80,7 @@ const AluScalarOpcodeInfo kAluScalarOpcodeInfos[64] = {
{"opcode_63", 0, false, kAluOpChangedStateNone},
};
const AluVectorOpcodeInfo kAluVectorOpcodeInfos[32] = {
constexpr AluVectorOpcodeInfo kAluVectorOpcodeInfos[32] = {
{"add", {0b1111, 0b1111}, kAluOpChangedStateNone},
{"mul", {0b1111, 0b1111}, kAluOpChangedStateNone},
{"max", {0b1111, 0b1111}, kAluOpChangedStateNone},

View File

@ -306,7 +306,7 @@ class DeferredCommandBuffer {
void CmdVkSetScissor(uint32_t first_scissor, uint32_t scissor_count,
const VkRect2D* scissors) {
const size_t header_size =
constexpr size_t header_size =
xe::align(sizeof(ArgsVkSetScissor), alignof(VkRect2D));
uint8_t* args_ptr = reinterpret_cast<uint8_t*>(
WriteCommand(Command::kVkSetScissor,
@ -345,7 +345,7 @@ class DeferredCommandBuffer {
void CmdVkSetViewport(uint32_t first_viewport, uint32_t viewport_count,
const VkViewport* viewports) {
const size_t header_size =
constexpr size_t header_size =
xe::align(sizeof(ArgsVkSetViewport), alignof(VkViewport));
uint8_t* args_ptr = reinterpret_cast<uint8_t*>(
WriteCommand(Command::kVkSetViewport,

View File

@ -23,130 +23,134 @@ project("xenia-gpu-vulkan")
"../shaders/bytecode/vulkan_spirv/*.h",
})
group("src")
project("xenia-gpu-vulkan-trace-viewer")
uuid("86a1dddc-a26a-4885-8c55-cf745225d93e")
single_library_windowed_app_kind()
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
"xenia-hid-nop",
"xenia-kernel",
"xenia-patcher",
"xenia-ui",
"xenia-ui-vulkan",
"xenia-vfs",
})
links({
"aes_128",
"capstone",
"fmt",
"glslang-spirv",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
includedirs({
project_root.."/third_party/Vulkan-Headers/include",
})
files({
"vulkan_trace_viewer_main.cc",
"../../ui/windowed_app_main_"..platform_suffix..".cc",
})
filter("architecture:x86_64")
if enableMiscSubprojects then
group("src")
project("xenia-gpu-vulkan-trace-viewer")
uuid("86a1dddc-a26a-4885-8c55-cf745225d93e")
single_library_windowed_app_kind()
language("C++")
links({
"xenia-cpu-backend-x64",
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
"xenia-hid-nop",
"xenia-hid-skylander",
"xenia-kernel",
"xenia-patcher",
"xenia-ui",
"xenia-ui-vulkan",
"xenia-vfs",
})
links({
"aes_128",
"capstone",
"fmt",
"glslang-spirv",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
includedirs({
project_root.."/third_party/Vulkan-Headers/include",
})
files({
"vulkan_trace_viewer_main.cc",
"../../ui/windowed_app_main_"..platform_suffix..".cc",
})
filter("platforms:Linux")
links({
"X11",
"xcb",
"X11-xcb",
})
filter("platforms:Windows")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-viewer.txt",
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
end
group("src")
project("xenia-gpu-vulkan-trace-dump")
uuid("0dd0dd1c-b321-494d-ab9a-6c062f0c65cc")
kind("ConsoleApp")
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
"xenia-hid-nop",
"xenia-kernel",
"xenia-ui",
"xenia-ui-vulkan",
"xenia-vfs",
"xenia-patcher",
})
links({
"aes_128",
"capstone",
"fmt",
"glslang-spirv",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
includedirs({
project_root.."/third_party/Vulkan-Headers/include",
})
files({
"vulkan_trace_dump_main.cc",
"../../base/console_app_main_"..platform_suffix..".cc",
})
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
filter("platforms:Linux")
links({
"X11",
"xcb",
"X11-xcb",
})
filter("platforms:Windows")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-dump.txt",
filter("platforms:Linux")
links({
"X11",
"xcb",
"X11-xcb",
})
end
filter("platforms:Windows")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-viewer.txt",
})
end
group("src")
project("xenia-gpu-vulkan-trace-dump")
uuid("0dd0dd1c-b321-494d-ab9a-6c062f0c65cc")
kind("ConsoleApp")
language("C++")
links({
"xenia-apu",
"xenia-apu-nop",
"xenia-base",
"xenia-core",
"xenia-cpu",
"xenia-gpu",
"xenia-gpu-vulkan",
"xenia-hid",
"xenia-hid-nop",
"xenia-hid-skylander",
"xenia-kernel",
"xenia-ui",
"xenia-ui-vulkan",
"xenia-vfs",
"xenia-patcher",
})
links({
"aes_128",
"capstone",
"fmt",
"glslang-spirv",
"imgui",
"libavcodec",
"libavutil",
"mspack",
"snappy",
"xxhash",
})
includedirs({
project_root.."/third_party/Vulkan-Headers/include",
})
files({
"vulkan_trace_dump_main.cc",
"../../base/console_app_main_"..platform_suffix..".cc",
})
filter("architecture:x86_64")
links({
"xenia-cpu-backend-x64",
})
filter("platforms:Linux")
links({
"X11",
"xcb",
"X11-xcb",
})
filter("platforms:Windows")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user"
if not os.isfile(user_file) then
debugdir(project_root)
debugargs({
"2>&1",
"1>scratch/stdout-trace-dump.txt",
})
end
end

View File

@ -54,18 +54,18 @@ namespace shaders {
#include "xenia/gpu/shaders/bytecode/vulkan_spirv/fullscreen_cw_vs.h"
} // namespace shaders
const VkDescriptorPoolSize
constexpr VkDescriptorPoolSize
VulkanCommandProcessor::kDescriptorPoolSizeUniformBuffer = {
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
SpirvShaderTranslator::kConstantBufferCount*
kLinkedTypeDescriptorPoolSetCount};
const VkDescriptorPoolSize
constexpr VkDescriptorPoolSize
VulkanCommandProcessor::kDescriptorPoolSizeStorageBuffer = {
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, kLinkedTypeDescriptorPoolSetCount};
// 2x descriptors for texture images because of unsigned and signed bindings.
const VkDescriptorPoolSize
constexpr VkDescriptorPoolSize
VulkanCommandProcessor::kDescriptorPoolSizeTextures[2] = {
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
2 * kLinkedTypeDescriptorPoolSetCount},
@ -962,7 +962,7 @@ bool VulkanCommandProcessor::SetupContext() {
swap_apply_gamma_pipeline_color_blend_state.pAttachments =
&swap_apply_gamma_pipeline_color_blend_attachment_state;
static const VkDynamicState kSwapApplyGammaPipelineDynamicStates[] = {
static constexpr VkDynamicState kSwapApplyGammaPipelineDynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};

View File

@ -442,7 +442,7 @@ void VulkanPipelineCache::WritePipelineRenderTargetDescription(
if (write_mask) {
assert_zero(write_mask & ~uint32_t(0b1111));
// 32 because of 0x1F mask, for safety (all unknown to zero).
static const PipelineBlendFactor kBlendFactorMap[32] = {
static constexpr PipelineBlendFactor kBlendFactorMap[32] = {
/* 0 */ PipelineBlendFactor::kZero,
/* 1 */ PipelineBlendFactor::kOne,
/* 2 */ PipelineBlendFactor::kZero, // ?
@ -2148,7 +2148,7 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
uint32_t color_rts_used =
description.render_pass_key.depth_and_color_used >> 1;
{
static const VkBlendFactor kBlendFactorMap[] = {
static constexpr VkBlendFactor kBlendFactorMap[] = {
VK_BLEND_FACTOR_ZERO,
VK_BLEND_FACTOR_ONE,
VK_BLEND_FACTOR_SRC_COLOR,
@ -2166,14 +2166,14 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
};
// 8 entries for safety since 3 bits from the guest are passed directly.
static const VkBlendOp kBlendOpMap[] = {VK_BLEND_OP_ADD,
VK_BLEND_OP_SUBTRACT,
VK_BLEND_OP_MIN,
VK_BLEND_OP_MAX,
VK_BLEND_OP_REVERSE_SUBTRACT,
VK_BLEND_OP_ADD,
VK_BLEND_OP_ADD,
VK_BLEND_OP_ADD};
static constexpr VkBlendOp kBlendOpMap[] = {VK_BLEND_OP_ADD,
VK_BLEND_OP_SUBTRACT,
VK_BLEND_OP_MIN,
VK_BLEND_OP_MAX,
VK_BLEND_OP_REVERSE_SUBTRACT,
VK_BLEND_OP_ADD,
VK_BLEND_OP_ADD,
VK_BLEND_OP_ADD};
uint32_t color_rts_remaining = color_rts_used;
uint32_t color_rt_index;
while (xe::bit_scan_forward(color_rts_remaining, &color_rt_index)) {

View File

@ -556,7 +556,7 @@ bool VulkanRenderTargetCache::Initialize(uint32_t shared_memory_binding_count) {
Shutdown();
return false;
}
const std::pair<const uint32_t*, size_t> host_depth_store_shaders[] = {
constexpr std::pair<const uint32_t*, size_t> host_depth_store_shaders[] = {
{shaders::host_depth_store_1xmsaa_cs,
sizeof(shaders::host_depth_store_1xmsaa_cs)},
{shaders::host_depth_store_2xmsaa_cs,

View File

@ -88,7 +88,7 @@ namespace shaders {
static_assert(VK_FORMAT_UNDEFINED == VkFormat(0),
"Assuming that skipping a VkFormat in an initializer results in "
"VK_FORMAT_UNDEFINED");
const VulkanTextureCache::HostFormatPair
constexpr VulkanTextureCache::HostFormatPair
VulkanTextureCache::kBestHostFormats[64] = {
// k_1_REVERSE
{{kLoadShaderIndexUnknown},
@ -408,14 +408,14 @@ const VulkanTextureCache::HostFormatPair
// Always decompressing them to RGBA8, which is required to be linear-filterable
// as UNORM and SNORM.
const VulkanTextureCache::HostFormatPair
constexpr VulkanTextureCache::HostFormatPair
VulkanTextureCache::kHostFormatGBGRUnaligned = {
{kLoadShaderIndexGBGR8ToRGB8, VK_FORMAT_R8G8B8A8_UNORM, false, true},
{kLoadShaderIndexGBGR8ToRGB8, VK_FORMAT_R8G8B8A8_SNORM, false, true},
xenos::XE_GPU_TEXTURE_SWIZZLE_RGBB,
true};
const VulkanTextureCache::HostFormatPair
constexpr VulkanTextureCache::HostFormatPair
VulkanTextureCache::kHostFormatBGRGUnaligned = {
{kLoadShaderIndexBGRG8ToRGB8, VK_FORMAT_R8G8B8A8_UNORM, false, true},
{kLoadShaderIndexBGRG8ToRGB8, VK_FORMAT_R8G8B8A8_SNORM, false, true},
@ -773,7 +773,7 @@ VkSampler VulkanTextureCache::UseSampler(SamplerParameters parameters,
sampler_create_info.mipmapMode = parameters.mag_linear
? VK_SAMPLER_MIPMAP_MODE_LINEAR
: VK_SAMPLER_MIPMAP_MODE_NEAREST;
static const VkSamplerAddressMode kAddressModeMap[] = {
static constexpr VkSamplerAddressMode kAddressModeMap[] = {
// kRepeat
VK_SAMPLER_ADDRESS_MODE_REPEAT,
// kMirroredRepeat

View File

@ -221,7 +221,7 @@ bool HidDemoApp::OnInitialize() {
void HidDemoApp::HidDemoDialog::OnDraw(ImGuiIO& io) { app_.Draw(io); }
void HidDemoApp::Draw(ImGuiIO& io) {
const ImGuiWindowFlags wflags =
constexpr ImGuiWindowFlags wflags =
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoScrollbar;
@ -383,7 +383,7 @@ void HidDemoApp::DrawUserInputGetKeystroke(uint32_t user_index, bool poll,
{ui::VirtualKey::kXInputPadRThumbDownLeft, "R Thumb down & left"},
};
const size_t maxLog = 128;
constexpr size_t maxLog = 128;
static std::array<std::forward_list<std::string>, MAX_USERS> event_logs;
static std::array<uint64_t, MAX_USERS> last_event_times = {};

View File

@ -16,6 +16,11 @@
#include "xenia/hid/input_driver.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/hid/skylander/skylander_emulated.h"
#ifdef XE_PLATFORM_WIN32
#include "xenia/hid/skylander/skylander_hardware.h"
#endif // XE_PLATFORM_WIN32
namespace xe {
namespace hid {
@ -28,7 +33,13 @@ DEFINE_double(
right_stick_deadzone_percentage, 0.0,
"Defines deadzone level for right stick. Allowed range [0.0-1.0].", "HID");
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {}
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {
skylander_portal_ = std::make_unique<SkylanderPortalEmulated>();
#ifdef XE_PLATFORM_WIN32
skylander_portal_ = std::make_unique<SkylanderPortalLibusb>();
#endif // XE_PLATFORM_WIN32
}
InputSystem::~InputSystem() = default;
@ -109,6 +120,9 @@ X_RESULT InputSystem::GetState(uint32_t user_index, uint32_t flags,
SCOPE_profile_cpu_f("hid");
std::vector<InputDriver*> filtered_drivers = FilterDrivers(flags);
if (filtered_drivers.empty()) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
for (auto& driver : filtered_drivers) {
X_RESULT result = driver->GetState(user_index, out_state);

View File

@ -16,6 +16,7 @@
#include "xenia/base/mutex.h"
#include "xenia/hid/input.h"
#include "xenia/hid/input_driver.h"
#include "xenia/hid/skylander/skylander_portal.h"
#include "xenia/xbox.h"
namespace xe {
@ -55,6 +56,8 @@ class InputSystem {
uint32_t GetLastUsedSlot() const { return last_used_slot; }
SkylanderPortal* GetSkylanderPortal() { return skylander_portal_.get(); }
std::unique_lock<xe_unlikely_mutex> lock();
private:
@ -74,6 +77,8 @@ class InputSystem {
std::vector<std::unique_ptr<InputDriver>> drivers_;
std::unique_ptr<SkylanderPortal> skylander_portal_;
std::bitset<XUserMaxUserCount> connected_slots = {};
std::array<std::pair<joystick_value, joystick_value>, XUserMaxUserCount>
controllers_max_joystick_value = {};

View File

@ -8,6 +8,7 @@ project("xenia-hid")
language("C++")
links({
"xenia-base",
"xenia-hid-skylander",
})
defines({
})

Some files were not shown because too many files have changed in this diff Show More