Compare commits

..

No commits in common. "master" and "CI-24c4e3d" have entirely different histories.

289 changed files with 22687 additions and 33377 deletions

View File

@ -8,6 +8,7 @@ skip_commits:
- .github/*
- .github/*/*
- .azure-pipelines.yml
- .travis.yml
- CONTRIBUTORS
- COPYING
- README.md
@ -15,10 +16,7 @@ skip_commits:
- setup.bat
init:
- ps: |-
echo "This CI isn't tested against master, and therefore, isn't guaranteed to work. Pull requests are welcome."
echo "If it doesn't work and you'd rather not fix it, it's recommended to use GitHub Actions CI instead."
Update-AppveyorBuild -Version "$env:appveyor_repo_commit"
- ps: Update-AppveyorBuild -Version "$env:appveyor_repo_commit"
image: # If this is modified, please also update the build script
- Visual Studio 2019
@ -40,7 +38,9 @@ build_script:
on_success:
- ps: |-
If ($env:configuration -eq 'Release') {
cmake --install . --config $env:configuration --prefix artifacts
7z a "$env:configuration.zip" ./artifacts/bin/*
cd bin\$env:configuration
7z u "$env:configuration.zip" ..\..\..\COPYING ..\..\..\README.md
7z u "$env:configuration.zip" cxbx.exe cxbxr-ldr.exe cxbxr-emu.dll glew32.dll subhook.dll SDL2.dll
7z u "$env:configuration.zip" cxbxr-debugger.exe capstone.dll cs_x86.dll
Get-ChildItem .\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
}

View File

@ -3,13 +3,18 @@ trigger:
include:
- '*'
paths:
exclude: # Azure Pipelines doesn't support recursive wildcards, see
- '.github/*' # https://developercommunity.visualstudio.com/t/support-wildcards-in-trigger-path-filters-1/366363
- '.github/*/*'
- '*.bat'
- '.appveyor.yml'
- 'doc/*/*'
- 'doc/*'
exclude:
- doc/*
- doc/*/*
- .github/*
- .github/*/*
- .appveyor.yml
- .travis.yml
- CONTRIBUTORS
- COPYING
- README.md
- gen-msvc-project.bat
- setup.bat
pr:
branches:
@ -17,44 +22,63 @@ pr:
- '*'
paths:
exclude:
- '.github/*'
- '.github/*/*'
- '*.bat'
- '.appveyor.yml'
- 'doc/*/*'
- 'doc/*'
- doc/*
- doc/*/*
- .github/*
- .github/*/*
- .appveyor.yml
- .travis.yml
- CONTRIBUTORS
- COPYING
- README.md
- gen-msvc-project.bat
- setup.bat
pool:
vmImage: windows-latest
strategy:
matrix:
Release:
configuration: Release
Debug:
configuration: Debug
jobs:
- job:
pool:
vmImage: windows-latest
strategy:
matrix:
Release:
configuration: Release
Debug:
configuration: Debug
steps:
- pwsh: |
echo "This CI isn't tested against master, and therefore, isn't guaranteed to work. Pull requests are welcome."
echo "If it doesn't work and you'd rather not fix it, it's recommended to use GitHub Actions CI instead."
displayName: Third-Party CI Warning
steps:
- checkout: self
submodules: recursive
- checkout: self
submodules: recursive
- script: |
mkdir build
cd build
cmake .. -G "Visual Studio 16 2019" -A Win32
displayName: 'Before build'
- pwsh: cmake -B build -A Win32
displayName: Before build
- script: cmake --build . --config %configuration%
workingDirectory: build
displayName: 'Build'
- pwsh: cmake --build . --config $env:configuration
workingDirectory: build
displayName: Build
- task: CopyFiles@2
displayName: 'Copy files to $(Build.ArtifactStagingDirectory)'
condition: and(succeeded(), eq(variables['Agent.JobName'], 'Release'))
inputs:
Contents: |
COPYING
README.md
build\bin\$(configuration)\cxbx.exe
build\bin\$(configuration)\cxbxr-ldr.exe
build\bin\$(configuration)\cxbxr-emu.dll
build\bin\$(configuration)\glew32.dll
build\bin\$(configuration)\subhook.dll
build\bin\$(configuration)\SDL2.dll
build\bin\$(configuration)\cxbxr-debugger.exe
build\bin\$(configuration)\capstone.dll
build\bin\$(configuration)\cx_x86.dll
TargetFolder: '$(Build.ArtifactStagingDirectory)'
flattenFolders: true
- pwsh: cmake --install . --config $env:configuration --prefix $(Build.ArtifactStagingDirectory)
workingDirectory: build
condition: and(succeeded(), eq(variables['configuration'], 'Release'))
displayName: Prepare artifacts
- publish: $(Build.ArtifactStagingDirectory)
artifact: $(configuration)
condition: and(succeeded(), eq(variables['configuration'], 'Release'))
displayName: Publish artifacts
- publish: $(Build.ArtifactStagingDirectory)
artifact: $(configuration)
condition: and(succeeded(), eq(variables['Agent.JobName'], 'Release'))
displayName: Publish artifact(s)

3
.gitattributes vendored
View File

@ -20,6 +20,3 @@
*.hpp text eol=lf
*.unused-patches text eol=lf
*.rc text eol=lf
# All module imports are vendor, remove them from linguist stats chart for accurate stats.
import/* linguist-vendored

View File

@ -4,16 +4,14 @@ about: Issue template.
title: ''
labels: ''
assignees: ''
---
<!--
ISSUES NOT UTILIZING THE TEMPLATE BELOW WILL BE CLOSED!
-->
<!--
Please read https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/master/README.md and https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/wiki/Frequently-Asked-Questions-(FAQ) before opening an issue.
Remember, the GitHub Issue Tracker is not the place to ask for support. You must use our forum on Discord https://discord.gg/26Xjx23 for that.
Compatibility Reports should be submitted at the website: https://cxbx-reloaded.co.uk
Remember, the GitHub Issue Tracker is not the place to ask for support or to submit game compatibility https://github.com/Cxbx-Reloaded/game-compatibility/blob/master/README.md reports.
You must use our forum on Discord https://discord.gg/26Xjx23 for that.
Otherwise, for any other emulation/general issues like crashes when a controller is connected, or regressions across several titles, feel free to report your issue here.
-->
@ -42,4 +40,4 @@ Please provide your system configuration
### Additional Information (if any):
<!--
Anything else you deem to be important
-->
-->

111
.github/labeler.yml vendored
View File

@ -1,111 +0,0 @@
# Labels are in alphabetical order.
cmake:
- changed-files:
- any-glob-to-any-file:
- 'CMake*'
- '**/CMakeLists.txt'
- '**/*.cmake'
cpu-emulation:
- changed-files:
- any-glob-to-any-file:
- 'src/devices/x86/**'
deployment:
- changed-files:
- any-glob-to-any-file:
- '*.yml'
- '.github/workflows/CI.yml'
file-system:
- changed-files:
- any-glob-to-any-file:
- 'src/core/kernel/support/EmuFile*'
graphics:
- changed-files:
- any-glob-to-any-file:
- 'src/core/hle/D3D8/**'
- 'src/core/hle/XGRAPHIC/**'
- 'src/devices/video/**'
- 'src/gui/*Video*'
HLE:
- changed-files:
- any-glob-to-any-file:
- 'src/core/hle/**'
- 'src/core/kernel/**'
informational:
- changed-files:
- any-glob-to-any-file:
- '**/*Logging*'
- '**/*Logging*/**'
- '**/README.md'
input:
- changed-files:
- any-glob-to-any-file:
- 'src/common/input/**'
- 'src/core/hle/XAPI/input/**'
- 'src/devices/usb/**'
- 'src/gui/controllers/**'
- 'src/gui/*Input*'
kernel:
- changed-files:
- any-glob-to-any-file:
- 'src/core/kernel/**'
LLE:
- changed-files:
- any-glob-to-any-file:
- 'src/devices/**'
memory:
- changed-files:
- any-glob-to-any-file:
- 'src/core/kernel/memory-manager/**'
networking:
- changed-files:
- any-glob-to-any-file:
- 'src/core/hle/XONLINE/**'
- 'src/devices/network/**'
- 'src/gui/*Network*'
sound:
- changed-files:
- any-glob-to-any-file:
- 'src/common/audio/**'
- 'src/core/hle/DSOUND/**'
- 'src/core/hle/XACTENG/**'
- 'src/devices/audio/**'
- 'src/gui/*Audio*'
modules:
- changed-files:
- any-glob-to-any-file:
- 'import/**'
threading:
- changed-files:
- any-glob-to-any-file:
- 'src/core/kernel/support/EmuFS*'
timing:
- changed-files:
- any-glob-to-any-file:
- 'src/common/Timer*'
user interface:
- changed-files:
- any-glob-to-any-file:
- 'src/core/common/imgui/*'
- 'src/gui/**'
xbdm:
- changed-files:
- any-glob-to-any-file:
- 'src/common/xbdm/**'

View File

@ -3,79 +3,116 @@ name: GitHub CI
on:
push:
paths-ignore:
- '.gitattributes'
- '.github/*'
- '.github/*_TEMPLATE/**'
- '.gitignore'
- '*.bat'
- '*.yml'
- 'doc/**'
- '.github/CONTRIBUTING.md'
- '.github/FUNDING.md'
- '.github/ISSUE_TEMPLATE/*'
- 'doc/*'
- 'doc/*/*'
- '.appveyor.yml'
- '.azure-pipelines.yml'
- '.travis.yml'
- 'gen-msvc-project.bat'
- 'setup.bat'
pull_request:
paths-ignore:
- '.gitattributes'
- '.github/*'
- '.github/*_TEMPLATE/**'
- '.gitignore'
- '*.bat'
- '*.yml'
- 'doc/**'
- '.github/CONTRIBUTING.md'
- '.github/FUNDING.md'
- '.github/ISSUE_TEMPLATE/*'
- 'doc/*'
- 'doc/*/*'
- '.appveyor.yml'
- '.azure-pipelines.yml'
- '.travis.yml'
- 'gen-msvc-project.bat'
- 'setup.bat'
jobs:
build-windows:
name: Build (Windows, ${{ matrix.configuration }}, VS${{ matrix.vsver }}) # runner.os doesn't work here
runs-on: windows-${{ matrix.vsver }}
env:
POWERSHELL_TELEMETRY_OPTOUT: 1
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
configuration: [Release, Debug]
vsver: [2019]
winver: [7]
sdkver: [10.0.22621.0]
vsver: [VS2019, VS2017]
include:
- vsver: VS2019
os: windows-latest
- vsver: VS2017 # TODO: Remove VS2017 once WINE supports VS2019 runtimes;
os: windows-2016 # https://github.com/actions/virtual-environments/issues/68#issuecomment-602652021
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Generate CMake files
run: cmake -B build -A Win32,version=${{ matrix.sdkver }} -DCMAKE_SYSTEM_VERSION=${{ matrix.winver }} -DBUILD_CXBXR_DEBUGGER=ON
- name: Generate cmake files
run: |
mkdir build && cd build
cmake .. -A Win32
- name: Build
run: cmake --build build --config ${{ matrix.configuration }} -j $env:NUMBER_OF_PROCESSORS
working-directory: build
run: cmake --build . --config ${{ matrix.configuration }} -j $env:NUMBER_OF_PROCESSORS
- name: Prepare artifacts
if: matrix.configuration == 'Release'
run: cmake --install build --config ${{ matrix.configuration }} --prefix artifacts
- uses: actions/upload-artifact@v4
run: |
robocopy . artifacts COPYING README.md /r:0 /w:0
robocopy build\bin\${{ matrix.configuration }} artifacts `
cxbx.exe cxbxr-ldr.exe cxbxr-emu.dll glew32.dll subhook.dll SDL2.dll `
cxbxr-debugger.exe capstone.dll cs_x86.dll /r:0 /w:0
If ($LastExitCode -le 7) { $LastExitCode = 0 }
- uses: actions/upload-artifact@v1
if: matrix.configuration == 'Release'
with:
name: CxbxReloaded-${{ matrix.configuration }}-VS${{ matrix.vsver }}
path: artifacts/bin
if-no-files-found: error
name: CxbxReloaded-${{ matrix.configuration }}-${{ matrix.vsver }}
path: artifacts
release:
if: |
github.event.action != 'pull_request' &&
github.ref == 'refs/heads/master' &&
github.ref == 'refs/heads/master' &&
github.repository == 'Cxbx-Reloaded/Cxbx-Reloaded'
needs: build-windows
runs-on: ubuntu-latest
env:
artifact_1: CxbxReloaded-Release-VS2019
artifact_2: CxbxReloaded-Release-VS2017
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
- uses: actions/checkout@v2
- name: Download artifacts (1)
uses: actions/download-artifact@v1
with:
path: artifacts
- name: Re-zip artifacts
id: zip
run: |
for artifact in artifacts/*; do
7z a ${artifact}.zip "./${artifact}/*"
if [ $(stat -c %s ${artifact}.zip) -le 100000 ]; then
echo "Error: Archive ${artifact}.zip too small!"
exit 1
fi
done
echo "tag_name=CI-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
name: ${{ env.artifact_1 }}
- name: Download artifacts (2)
uses: actions/download-artifact@v1
with:
name: ${{ env.artifact_2 }}
- name: Prepare artifacts for release
run: | # download-artifact doesn't download a zip, so rezip it
echo "::set-env name=short_commit_sha::$(git rev-parse --short HEAD)"
7z a -mx1 "$env:artifact_1.zip" ".\$env:artifact_1\*"
7z a -mx1 "$env:artifact_2.zip" ".\$env:artifact_2\*"
- name: Create Release
id: create_release
uses: actions/create-release@v1.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create ${{ steps.zip.outputs.tag_name }} artifacts/*.zip -p --target $GITHUB_SHA --title '${{ steps.zip.outputs.tag_name }}'
with:
tag_name: CI-${{ env.short_commit_sha }}
release_name: CI-${{ env.short_commit_sha }}
prerelease: true
- name: Upload Release Asset (1)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ env.artifact_1 }}.zip
asset_name: ${{ env.artifact_1 }}.zip
asset_content_type: application/zip
- name: Upload Release Asset (2)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ env.artifact_2 }}.zip
asset_name: ${{ env.artifact_2 }}.zip
asset_content_type: application/zip

View File

@ -1,15 +1,15 @@
on:
issues:
types: opened
types: [opened]
jobs:
auto_close_issues:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v1
- name: Automatically close issues that don't follow the issue template
uses: ergo720/auto-close-issues@v1
uses: ergo720/auto-close-issues@v1.0.4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-close-message: "@${issue.user.login}: your issue has been automatically closed because it does not follow the issue template." # optional property

View File

@ -1,13 +0,0 @@
name: Pull Request Manager
on: pull_request_target
jobs:
pr_manager:
runs-on: ubuntu-latest
steps:
- name: Labeler
uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
sync-labels: true

4
.gitignore vendored
View File

@ -2,10 +2,6 @@
[Bb]uild/
[Bb]uild-*/
# CLion
.idea/
cmake-build-*/
# Visual Studio Cache
.vs/

40
.gitmodules vendored
View File

@ -1,49 +1,27 @@
[submodule "import/subhook"]
path = import/subhook
url = https://github.com/Cxbx-Reloaded/subhook.git
shallow = true
url = https://github.com/Zeex/subhook.git
[submodule "import/cs_x86"]
path = import/cs_x86
url = https://github.com/x1nixmzeng/cs_x86.git
url = https://github.com/x1nixmzeng/cs_x86
[submodule "import/XbSymbolDatabase"]
path = import/XbSymbolDatabase
url = https://github.com/Cxbx-Reloaded/XbSymbolDatabase.git
url = https://github.com/Cxbx-Reloaded/XbSymbolDatabase
[submodule "import/simpleini"]
path = import/simpleini
url = https://github.com/brofield/simpleini.git
shallow = true
url = https://github.com/brofield/simpleini
[submodule "import/libtommath"]
path = import/libtommath
url = https://github.com/libtom/libtommath.git
url = https://github.com/libtom/libtommath
branch = master
shallow = true
[submodule "import/libtomcrypt"]
path = import/libtomcrypt
url = https://github.com/libtom/libtomcrypt.git
url = https://github.com/libtom/libtomcrypt
branch = master
shallow = true
[submodule "import/SDL2"]
path = import/SDL2
url = https://github.com/SDL-mirror/SDL
[submodule "import/xxHash"]
path = import/xxHash
url = https://github.com/Cyan4973/xxHash.git
branch = release
shallow = true
[submodule "import/imgui"]
path = import/imgui
url = https://github.com/ocornut/imgui.git
shadow = true
[submodule "import/SDL2"]
path = import/SDL2
url = https://github.com/libsdl-org/SDL
shallow = true
[submodule "import/libusb"]
path = import/libusb
url = https://github.com/Cxbx-Reloaded/libusb
branch = deadlock_fix
shallow = true
[submodule "import/nv2a_vsh_cpu"]
path = import/nv2a_vsh_cpu
url = https://github.com/abaire/nv2a_vsh_cpu.git
[submodule "import/mio"]
path = import/mio
url = https://github.com/mandreyel/mio.git
shadow = true

42
.travis.yml Normal file
View File

@ -0,0 +1,42 @@
language: cpp
matrix:
include:
- os: windows
env: configuration=Debug
- os: windows
env: configuration=Release
before_script:
- if [ $TRAVIS_OS_NAME == 'windows' ]; then
mkdir build;
cd build;
cmake .. -G "Visual Studio 15 2017" -A Win32;
fi
script:
- if [ $TRAVIS_OS_NAME == 'windows' ]; then
cmake --build . --config $configuration;
fi
# Bug with the Windows builder requires us to not filter secrets
#filter_secrets: false
#before_deploy:
# - mkdir export
# - 7z u export/${configuration} COPYING README.md
# - cd build/win32/${configuration}
# - 7z u ../../../export/${configuration} cxbx.exe cxbxr-ldr.exe cxbxr-emu.dll glew32.dll subhook.dll SDL2.dll
# - 7z u ../../../export/${configuration} CxbxDebugger.exe capstone.dll cs_x86.dll
# - cd ../../../
#deploy:
# provider: releases
# api_key: $GH_TOKEN
# file: "export/${configuration}.7z"
# skip_cleanup: true
# on:
# # Can disable this to deploy all builds appears as "untagged-buildhash" on GH
# tags: true
# branch: develop
# condition: $configuration = Release

View File

@ -13,16 +13,18 @@ endif()
set(SUBHOOK_TESTS OFF)
set(SUBHOOK_INSTALL OFF)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/subhook" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/subhook")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/XbSymbolDatabase")
# Not require since only include a header file
#add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/simpleini")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/SDL2" EXCLUDE_FROM_ALL)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/SDL2")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/mio" EXCLUDE_FROM_ALL)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/cs_x86")
endif()
# Cxbx-Reloaded projects
set(CXBXR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR})
@ -33,16 +35,9 @@ add_custom_target(misc-batch
WORKING_DIRECTORY ${CXBXR_ROOT_DIR}
)
# Custom CMake projects since some import libraries doesn't have it.
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/libtom")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/imgui")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/libusb")
set(nv2a_vsh_cpu_UNIT_TEST OFF)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/nv2a_vsh_cpu" EXCLUDE_FROM_ALL)
#add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/vsbc")
# Split the files into group for which project is likely
# going to be used for both header and source files.
@ -54,31 +49,29 @@ add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/import/nv2a_vsh_cpu" EXCLUDE_FROM_AL
# Common (GUI and Emulator)
file (GLOB CXBXR_HEADER_COMMON
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuDes.h"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuRsa.h"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuSha.h"
"${CXBXR_ROOT_DIR}/src/common/crypto/LibRc4.h"
"${CXBXR_ROOT_DIR}/src/common/CxbxDebugger.h"
"${CXBXR_ROOT_DIR}/src/common/cxbxr.hpp"
"${CXBXR_ROOT_DIR}/src/common/EmuEEPROM.h"
"${CXBXR_ROOT_DIR}/src/common/Error.h"
"${CXBXR_ROOT_DIR}/src/common/FilePaths.hpp"
"${CXBXR_ROOT_DIR}/src/common/input/DInputKeyboardCodes.h"
"${CXBXR_ROOT_DIR}/src/common/input/DInputKeyboardMouse.h"
"${CXBXR_ROOT_DIR}/src/common/input/layout_xbox_device.h"
"${CXBXR_ROOT_DIR}/src/common/input/LibusbDevice.h"
"${CXBXR_ROOT_DIR}/src/common/input/layout_xbox_controller.h"
"${CXBXR_ROOT_DIR}/src/common/input/InputDevice.h"
"${CXBXR_ROOT_DIR}/src/common/input/InputManager.h"
"${CXBXR_ROOT_DIR}/src/common/input/SdlJoystick.h"
"${CXBXR_ROOT_DIR}/src/common/input/XInputPad.h"
"${CXBXR_ROOT_DIR}/src/common/input/RawDevice.h"
"${CXBXR_ROOT_DIR}/src/common/IPCHybrid.hpp"
"${CXBXR_ROOT_DIR}/src/common/Logging.h"
"${CXBXR_ROOT_DIR}/src/common/ReservedMemory.h"
"${CXBXR_ROOT_DIR}/src/common/Settings.hpp"
"${CXBXR_ROOT_DIR}/src/common/Timer.h"
"${CXBXR_ROOT_DIR}/src/common/util/cliConfig.hpp"
"${CXBXR_ROOT_DIR}/src/common/util/cliConverter.hpp"
"${CXBXR_ROOT_DIR}/src/common/util/CPUID.h"
"${CXBXR_ROOT_DIR}/src/common/util/crc32c.h"
"${CXBXR_ROOT_DIR}/src/common/util/CxbxUtil.h"
"${CXBXR_ROOT_DIR}/src/common/util/std_extend.hpp"
"${CXBXR_ROOT_DIR}/src/common/util/strConverter.hpp"
@ -86,20 +79,13 @@ file (GLOB CXBXR_HEADER_COMMON
"${CXBXR_ROOT_DIR}/src/common/win32/AlignPrefix1.h"
"${CXBXR_ROOT_DIR}/src/common/win32/EmuShared.h"
"${CXBXR_ROOT_DIR}/src/common/win32/Mutex.h"
"${CXBXR_ROOT_DIR}/src/common/win32/Util.h"
"${CXBXR_ROOT_DIR}/src/common/win32/WineEnv.h"
"${CXBXR_ROOT_DIR}/src/common/win32/Threads.h"
"${CXBXR_ROOT_DIR}/src/common/xbdm/CxbxXbdm.h"
"${CXBXR_ROOT_DIR}/src/common/xbe/Xbe.h"
"${CXBXR_ROOT_DIR}/src/common/xbe/XbePrinter.h"
"${CXBXR_ROOT_DIR}/src/common/xbox/Logging.hpp"
"${CXBXR_ROOT_DIR}/src/common/xbox/Types.hpp"
"${CXBXR_ROOT_DIR}/src/common/xbox_types.h"
"${CXBXR_ROOT_DIR}/src/common/xdvdfs-tools/buffered_io.h"
"${CXBXR_ROOT_DIR}/src/common/xdvdfs-tools/xdvdfs.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Types.h"
"${CXBXR_ROOT_DIR}/src/core/hle/XAPI/Xapi.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlLogging.h"
"${CXBXR_ROOT_DIR}/src/Cxbx.h"
"${CXBXR_ROOT_DIR}/src/CxbxVersion.h"
"${CXBXR_ROOT_DIR}/src/version.h"
@ -110,55 +96,36 @@ file (GLOB CXBXR_HEADER_GUIv1
"${CXBXR_ROOT_DIR}/src/common/input/Button.h"
"${CXBXR_ROOT_DIR}/src/common/input/EmuDevice.h"
"${CXBXR_ROOT_DIR}/src/common/input/InputWindow.h"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgDukeControllerConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgLibusbControllerConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgLightgunConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgSBControllerConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DbgConsole.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgAbout.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgAudioConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgInputConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgDukeControllerConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgEepromConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgLoggingConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgNetworkConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/DlgVideoConfig.h"
"${CXBXR_ROOT_DIR}/src/gui/ResCxbx.h"
"${CXBXR_ROOT_DIR}/src/gui/Wnd.h"
"${CXBXR_ROOT_DIR}/src/gui/WndMain.h"
)
# Emulator (module)
file (GLOB CXBXR_HEADER_EMU_IMPORT
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_dx9.h"
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_opengl3.h"
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_win32.h"
)
file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/audio/converter.hpp"
"${CXBXR_ROOT_DIR}/src/common/audio/XADPCM.h"
"${CXBXR_ROOT_DIR}/src/common/Timer.h"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/glextensions.h"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/gloffscreen.h"
"${CXBXR_ROOT_DIR}/src/common/win32/Threads.h"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/audio.hpp"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/ui.hpp"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/settings.h"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/video.hpp"
"${CXBXR_ROOT_DIR}/src/core/common/video/RenderBase.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/CxbxPixelShaderTemplate.hlsl"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/CxbxVertexShaderTemplate.hlsl"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/CxbxVertexShaderPassthrough.hlsl"
"${CXBXR_ROOT_DIR}/src/common/XADPCM.h"
"${CXBXR_ROOT_DIR}/src/common/xbox/Logging.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/Direct3D9.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsl"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/FixedFunctionPixelShader.hlsli"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShader.hlsl"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/FixedFunctionVertexShaderState.hlsli"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/PixelShader.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/Shader.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShader.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderCache.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderSource.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/WalkIndexBuffer.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/FixedFunctionState.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/ResourceTracker.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Logging.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Types.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbPixelShader.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbPushBuffer.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbState.h"
@ -177,15 +144,16 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/Intercept.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Patches.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XACTENG/XactEng.h"
"${CXBXR_ROOT_DIR}/src/core/hle/XAPI/Xapi.h"
"${CXBXR_ROOT_DIR}/src/core/hle/XAPI/XapiCxbxr.h"
"${CXBXR_ROOT_DIR}/src/core/hle/XGRAPHIC/XGraphic.h"
"${CXBXR_ROOT_DIR}/src/core/hle/XONLINE/XOnline.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/common/strings.hpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlAvModes.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlKe.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlKi.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlPs.hpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlLogging.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/init/CxbxKrnl.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/init/KrnlPatches.hpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/memory-manager/PhysicalMemory.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/memory-manager/PoolManager.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/memory-manager/VMManager.h"
@ -193,11 +161,9 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFile.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFS.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuNtDll.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/NativeHandle.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/PatchRdtsc.hpp"
"${CXBXR_ROOT_DIR}/src/devices/ADM1032Device.h"
"${CXBXR_ROOT_DIR}/src/devices/EEPROMDevice.h"
"${CXBXR_ROOT_DIR}/src/devices/network/NVNetDevice.h"
"${CXBXR_ROOT_DIR}/src/devices/EmuNVNet.h"
"${CXBXR_ROOT_DIR}/src/devices/LED.h"
"${CXBXR_ROOT_DIR}/src/devices/MCPXDevice.h"
"${CXBXR_ROOT_DIR}/src/devices/PCIBus.h"
@ -226,55 +192,41 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/devices/Xbox.h"
)
# filter hlsl files into its own list
# excluding hlsli file(s)
set(CXBXR_HEADER_HLSL ${CXBXR_HEADER_EMU})
list(FILTER CXBXR_HEADER_HLSL INCLUDE REGEX ".*\\.hlsl$")
# Common (GUI and Emulator)
file (GLOB CXBXR_SOURCE_COMMON
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuDes.cpp"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuRsa.cpp"
"${CXBXR_ROOT_DIR}/src/common/crypto/EmuSha.cpp"
"${CXBXR_ROOT_DIR}/src/common/crypto/LibRc4.cpp"
"${CXBXR_ROOT_DIR}/src/common/CxbxDebugger.cpp"
"${CXBXR_ROOT_DIR}/src/common/cxbxr.cpp"
"${CXBXR_ROOT_DIR}/src/common/EmuEEPROM.cpp"
"${CXBXR_ROOT_DIR}/src/common/Error.cpp"
"${CXBXR_ROOT_DIR}/src/common/FilePaths.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/DInputKeyboardMouse.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/InputDevice.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/InputManager.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/LibusbDevice.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/SdlJoystick.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/XInputPad.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/RawDevice.cpp"
"${CXBXR_ROOT_DIR}/src/common/Logging.cpp"
"${CXBXR_ROOT_DIR}/src/common/Settings.cpp"
"${CXBXR_ROOT_DIR}/src/common/Timer.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/cliConfig.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/cliConverter.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/crc32c.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/CxbxUtil.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/hasher.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/EmuShared.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/InlineFunc.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/IPCWindows.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/Mutex.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/Util.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/WineEnv.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/Threads.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbdm/CxbxXbdm.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbe/Xbe.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbe/XbePrinter.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbox/Logging.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbox/Types.cpp"
"${CXBXR_ROOT_DIR}/src/common/xdvdfs-tools/buffered_io.cpp"
"${CXBXR_ROOT_DIR}/src/common/xdvdfs-tools/xdvdfs.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XAPI/Xapi.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlLogging.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXbox.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXc.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXe.cpp"
"${CXBXR_ROOT_DIR}/src/CxbxVersion.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DbgConsole.cpp"
"${CXBXR_ROOT_DIR}/src/HighPerformanceGraphicsEnabler.c"
)
@ -283,13 +235,10 @@ file (GLOB CXBXR_SOURCE_GUIv1
"${CXBXR_ROOT_DIR}/src/common/input/Button.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/EmuDevice.cpp"
"${CXBXR_ROOT_DIR}/src/common/input/InputWindow.cpp"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgDukeControllerConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgLibusbControllerConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgLightgunConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/input/DlgSBControllerConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgAbout.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgAudioConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgInputConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgDukeControllerConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgEepromConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgLoggingConfig.cpp"
"${CXBXR_ROOT_DIR}/src/gui/DlgNetworkConfig.cpp"
@ -304,33 +253,23 @@ file (GLOB CXBXR_SOURCE_GUIv1
file (GLOB CXBXR_KRNL_CPP
"${CXBXR_ROOT_DIR}/src/core/kernel/init/CxbxKrnl.cpp"
)
file (GLOB CXBXR_SOURCE_EMU_IMPORT
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_dx9.cpp"
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_opengl3.cpp"
"${CXBXR_ROOT_DIR}/import/imgui/backends/imgui_impl_win32.cpp"
)
file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_KRNL_CPP}"
"${CXBXR_ROOT_DIR}/src/common/Timer.cpp"
"${CXBXR_ROOT_DIR}/HighPerformanceGraphicsEnabler.c"
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/VerifyAddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/glextensions.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/gloffscreen_common.cpp"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/gloffscreen_wgl.cpp"
"${CXBXR_ROOT_DIR}/src/common/VerifyAddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/win32/Threads.cpp"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/audio.cpp"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/ui.cpp"
"${CXBXR_ROOT_DIR}/src/core/common/imgui/video.cpp"
"${CXBXR_ROOT_DIR}/src/core/common/video/RenderBase.cpp"
"${CXBXR_ROOT_DIR}/src/common/xbox/Logging.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/PixelShader.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/RenderStates.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/Shader.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/TextureStates.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShader.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderCache.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderSource.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/WalkIndexBuffer.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/FixedFunctionState.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/ResourceTracker.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Logging.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbPixelShader.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbPushBuffer.cpp"
@ -348,9 +287,9 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/XbInternalDSVoice.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/XbInternalStruct.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Intercept.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/JVS/JVS.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Patches.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XACTENG/XactEng.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XAPI/Xapi.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XGRAPHIC/XGraphic.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnl.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlAv.cpp"
@ -362,12 +301,16 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlKd.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlKe.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlKi.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlLogging.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlMm.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlNt.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlOb.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlPhy.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlPs.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlRtl.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXbox.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXc.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/EmuKrnlXe.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/exports/KernelThunk.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/memory-manager/PhysicalMemory.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/memory-manager/PoolManager.cpp"
@ -376,13 +319,9 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFile.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFS.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuNtDll.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/NativeHandle.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/PatchRdtsc.cpp"
"${CXBXR_ROOT_DIR}/src/devices/ADM1032Device.cpp"
"${CXBXR_ROOT_DIR}/src/devices/Chihiro/JvsIO.cpp"
"${CXBXR_ROOT_DIR}/src/devices/Chihiro/MediaBoard.cpp"
"${CXBXR_ROOT_DIR}/src/devices/EEPROMDevice.cpp"
"${CXBXR_ROOT_DIR}/src/devices/network/NVNetDevice.cpp"
"${CXBXR_ROOT_DIR}/src/devices/EmuNVNet.cpp"
"${CXBXR_ROOT_DIR}/src/devices/MCPXDevice.cpp"
"${CXBXR_ROOT_DIR}/src/devices/PCIBus.cpp"
"${CXBXR_ROOT_DIR}/src/devices/PCIDevice.cpp"
@ -430,80 +369,41 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/common/ReserveAddressRanges.cpp"
)
option(BUILD_CXBXR_DEBUGGER "Build cxbxr-debugger tool (with cheat table support)")
if(BUILD_CXBXR_DEBUGGER)
message(DEPRECATION "The Cxbxr-Debugger tool will eventually be removed from the upstream branch.")
endif()
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/cxbx")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/cxbxr-ldr")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/cxbxr-emu")
set(cxbxr_INSTALL_files "COPYING" "README.md")
# Cxbx-Reloaded project with third-party libraries
set_target_properties(cxbx cxbxr-ldr cxbxr-emu misc-batch SDL2 subhook libXbSymbolDatabase libtommath libtomcrypt imgui libusb
PROPERTIES FOLDER Cxbx-Reloaded
)
set_target_properties(nv2a_vsh_emulator nv2a_vsh_disassembler nv2a_vsh_cpu
PROPERTIES FOLDER Cxbx-Reloaded/nv2a_vsh
)
# Issues with compile (the same with develop branch) and
# for some reason did not put the files into virtual folder?
# Might need to put the list in the source folder for workaround fix.
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
#add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/projects/debugger")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/src/CxbxDebugger")
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Configure startup project
set_property(DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" PROPERTY VS_STARTUP_PROJECT cxbx)
endif()
# Check if generator is Visual Studio then enable Cxbxr-Debugger project.
# Since C# is currently supported with Visual Studio for now.
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])" AND BUILD_CXBXR_DEBUGGER)
# Issues with compile (the same with develop branch) and
# for some reason did not put the files into virtual folder?
# Might need to put the list in the source folder for workaround fix.
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/src/CxbxDebugger")
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
# Refuse to exclude due to install is not set to optional
#set_target_properties(cstool
# PROPERTIES EXCLUDE_FROM_ALL TRUE
#)
set_target_properties(Tests_cs_x86
PROPERTIES EXCLUDE_FROM_ALL TRUE
)
set_target_properties(Tests_cs_x86
PROPERTIES EXCLUDE_FROM_ALL TRUE
)
# Cxbx-Debugger project with third-party libraries
set_target_properties(cxbxr-debugger cs_x86 Tests_cs_x86 capstone-shared
PROPERTIES FOLDER Cxbx-Reloaded/debugger
)
# Cxbx-Debugger project with third-party libraries
set_target_properties(cxbxr-debugger cs_x86 Tests_cs_x86 capstone-shared cstool
PROPERTIES FOLDER Cxbx-Reloaded/debugger
)
endif()
install(FILES ${cxbxr_INSTALL_files}
DESTINATION bin
)
# Copy HLSL files to the output directory, which are loaded at runtime
set(CXBXR_HLSL_FILES ${CXBXR_HEADER_EMU})
list(FILTER CXBXR_HLSL_FILES INCLUDE REGEX ".*/src/core/hle/D3D8/Direct3D9/[^/]+\.hlsli?")
add_custom_command(
TARGET misc-batch POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/hlsl
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CXBXR_HLSL_FILES} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/hlsl"
# These files can be edited.
# Create backup copies for convenience of restoring original shader behaviour.
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/hlsl/backup
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CXBXR_HLSL_FILES} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/hlsl/backup"
)
install(DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/hlsl DESTINATION bin)
set(cxbxr_GLEW_DLL "${CMAKE_SOURCE_DIR}/import/glew-2.0.0/bin/Release/Win32/glew32.dll")
install(PROGRAMS ${cxbxr_GLEW_DLL}
DESTINATION bin
)
install(PROGRAMS $<TARGET_FILE_DIR:cxbx>/${CMAKE_SHARED_LIBRARY_PREFIX}subhook${CMAKE_SHARED_LIBRARY_SUFFIX}
DESTINATION bin
)
install(PROGRAMS $<TARGET_FILE_DIR:cxbx>/${CMAKE_SHARED_LIBRARY_PREFIX}SDL2${CMAKE_SHARED_LIBRARY_SUFFIX}
DESTINATION bin
# Cxbx-Reloaded project with third-party libraries
set_target_properties(cxbx cxbxr-ldr cxbxr-emu misc-batch subhook libXbSymbolDatabase libtommath libtomcrypt
PROPERTIES FOLDER Cxbx-Reloaded
)

View File

@ -7,7 +7,7 @@ Cxbx was initiated by Caustik. Dxbx was initiated by shadowtj.
The following contributors are grouped per project and listed in alphabetical order,
based on sources like https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/graphs/contributors ,
http://www.caustik.com/cxbx/about.htm , https://emulation.gametechwiki.com/index.php/Cxbx ,
http://www.caustik.com/cxbx/about.htm , http://emulation.gametechwiki.com/index.php/Cxbx ,
and https://github.com/PatrickvL/Dxbx/graphs/contributors .
@ -34,7 +34,7 @@ Ernegien (Mike Davis)
ergo720
faha223 (Fred Hallock)
Fisherman166
gandalfthewhite19890404
gandalfthewhite19890404
gellis713
ggKismet
GXTX (wutno)
@ -46,15 +46,14 @@ JayFoxRox (Jannik Vogel)
literalmente-game
Luca1991 (Luca D'Amico) [Luca91]
LukeUsher (Luke Usher) [SoullessSentinel]
Margen67
Margen67
NZJenkins
PatrickvL (Patrick van Logchem)
phire (Scott Mansell)
RadWolfie
revel8n
Silent (CookiePLMonster)
StrikerX3 (Ivan Roberto de Oliveira)
TotalCaesar659
TotalCaesar659
Voxel9 (Voxel)
x1nixmzeng
@ -62,7 +61,7 @@ x1nixmzeng
Cxbx-Reloaded Supporters:
Cedric Wilson
Cisco Martinez
Cisco Martinez
Cody Dale Barton
Elijah Chondropoulos
Jacob Kelly
@ -73,7 +72,7 @@ Kenneth Edmonds
Kyle Lenhardt
Manny Calavera
Mark Knasiak
Marko V.
Marko V.
Matt Coady
Roman Guivan
Taylor Stock

View File

@ -1,5 +1,5 @@
# Cxbx-Reloaded - Original Xbox Emulator
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/master/COPYING)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://img.shields.io/badge/License-GPL%20v2-blue.svg)
[![GitHub Actions](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/workflows/GitHub%20CI/badge.svg?event=push)](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/actions?query=event%3Apush+workflow%3A%22GitHub+CI%22)
[![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?logo=discord)](https://discord.gg/26Xjx23)
@ -8,50 +8,40 @@ Cxbx-Reloaded is an emulator for running Microsoft Xbox (and eventually, Chihiro
## System Requirements
### Minimum
* OS: Windows 7+ x64, or x86-64 Linux with Wine. 32-bit is not supported.
* MacOS with Wine is known not to work, and BSD-based systems are untested.
* Also note that Wine is relatively unstable, and it might break compatibility with Cxbx-Reloaded at any time without warning.
* GPU: Direct3D 9.0c with Pixel Shader Model 2.x, and Vertex Shader Model 3.0.
## Prerequisites
### Windows
* [32-bit (x86) Visual C++ 2022 Redistributable](https://aka.ms/vs/17/release/vc_redist.x86.exe)
### Prerequisites
* [32-bit (x86) Visual C++ 2019 Redistributable](https://aka.ms/vs/16/release/vc_redist.x86.exe)
* [Npcap *(used for network emulation)*](https://nmap.org/npcap/#download)
* Make sure to enable winpcap compatibility mode.
* [WinUSB compliant driver](https://github.com/libusb/libusb/wiki/Windows#Driver_Installation)
* *Optional, only needed for USB pass-through of original Xbox and Steel Battalion controllers.*
### Wine
**Please use the latest stable release version of Wine. If it does not work for you, then roll back to Wine 7.0 which is the last known working version.**<br/>
**There also exists this known [issue](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/issues/2314) which currently prevents savings in some games with the most recent Wine 6.8 and later versions.**
* Winetricks
* `vcrun2019`
* Requires the latest winetricks script.
* `d3dcompiler_47`
* This may be subject to change.
* Winpcap is built-in, no installation is required.
* Make sure to enable winpcap compatibility mode!
## Automated Builds
Cxbx-Reloaded doesn't currently have stable builds, but you can obtain pre-release builds from our official website's download page, or the links below:
Cxbx-Reloaded doesn't currently have stable builds, but you can obtain pre-release builds from the Releases tab, or the links below:
* **[Release Builds](https://cxbx-reloaded.co.uk/download)**
* **[Release Builds](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/releases)**
* **Wine users will need to use `CxbxReloaded-Release-VS2017.zip` for it to run correctly.**
* *[Full build history](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/actions?query=workflow%3A%22GitHub+CI%22)*
## Compatibility
Cxbx-Reloaded has a [compatibility list](https://cxbx-reloaded.co.uk/compatibility).
Cxbx-Reloaded has a [compatibility list](https://github.com/Cxbx-Reloaded/game-compatibility#cxbx-reloaded-game-compatibility-project).
If you would like to submit compatibility reports, please request permission in our Discord server.
If you have something to report on a title, please create or update the issue for it there.
Please read the [Readme file](https://github.com/Cxbx-Reloaded/game-compatibility/blob/master/README.md) first!
## Bug Reports
Game or software specific issues can be reported in the [compatibility website](https://cxbx-reloaded.co.uk/compatibility).
Game or software specific issues can be reported in the [compatibility list](https://github.com/Cxbx-Reloaded/game-compatibility#cxbx-reloaded-game-compatibility-project).
For emulation issues that are not specific to any single piece of software, a bug report can be submitted at [the Cxbx-Reloaded issue tracker](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/issues).
<!--Make sure to follow the issue template and that it contains:
* The build tested with, error message displayed (if any)
* **You can copy and paste any popup messages. However, please keep it clean by pasting and trimming down to only the message itself.**
* Screenshots
* Optional unless there are graphic bugs for reference.
**Failure to follow the template will auto close your ticket.**-->
Make sure to follow the issue template and that it contains:
* The build tested with, error message displayed (if any)
* **(You can copy and paste any popup messages. However, please keep it clean by paste and trimming down to only the message itself.)**
* Screenshots
* (optional unless has any graphic bug for references)
**NOTICE: Failure to follow template will auto close your ticket.**
## Additional information
Cxbx-Reloaded has a [wiki](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/wiki) containing various subjects and background information.
@ -74,7 +64,8 @@ Please contact us before you start working on something, so we can make sure you
### Fetching the code
1. Run the following command in the command line:
<br>`git clone --recurse-submodules https://github.com/Cxbx-Reloaded/Cxbx-Reloaded.git`
`git clone --recurse-submodules https://github.com/Cxbx-Reloaded/Cxbx-Reloaded.git`
* Please note the `--recurse-submodules` parameter. This is required to fetch submodules.
* If Cxbx-Reloaded was checked out without submodules, they can be updated/fetched with the following command:
@ -83,13 +74,12 @@ Please contact us before you start working on something, so we can make sure you
### Compiling
#### Windows
Don't open `CMakeLists.txt` from Visual Studio, as it won't generate files in the `build` directory.
**NOTE:** Don't open `CMakeLists.txt` from Visual Studio, as it won't generate files in the `build` directory.
##### Prerequisites
1. [Visual Studio](https://visualstudio.microsoft.com/downloads/) 2022
1. [Visual Studio](https://visualstudio.microsoft.com/downloads/) 2017 or later
* C++ and C# desktop development
* Windows Universal CRT SDK
* Windows 11 SDK (10.0.22621.0) or later
* C++ CMake tools for Windows
* *Optional if CMake is installed*
* [Microsoft Child Process Debugging Power Tool](https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool)
@ -97,11 +87,11 @@ Don't open `CMakeLists.txt` from Visual Studio, as it won't generate files in th
##### Generate Visual Studio files
1. If you don't have CMake installed, open `___ Native Tools Command Prompt for VS 20##`.
2. `cd` to the Cxbx-Reloaded directory.
3. Run the following command: `cmake -B build -G "Visual Studio 17 2022" -A Win32` \
**NOTES**:
* VS2022 17.0 or later is required.
* To build the Cxbx-Reloaded Debugger tool, add the variable `-DBUILD_CXBXR_DEBUGGER=ON` to the above command.
* _This debugger tool is deprecated and will be eventually removed, please use the Visual Studio debugger instead._
3. Run these commands.
1. `mkdir build & cd build`
2. `cmake .. -G "Visual Studio 16 2019" -A Win32`
* Visual Studio 2019 16.1 or later has CMake 3.14 bundled, and is required for the Visual Studio 2019 generator.
* Use `cmake .. -G "Visual Studio 15 2017" -A Win32` for Visual Studio 2017.
4. Open `Cxbx-Reloaded.sln` from the `build` directory.
5. Select the Release configuration, then click Build.
* Debug builds are **significantly slower, and only for developers**.
@ -116,5 +106,3 @@ You can support [Luke Usher](https://github.com/LukeUsher), initiator of Cxbx-Re
* All contributors to the original Cxbx and [Dxbx](https://github.com/PatrickvL/Dxbx) projects. Without them Cxbx-Reloaded would not exist at all.
* [XQEMU](https://github.com/xqemu/xqemu) - While the majority of Cxbx-R is our own work (Kernel, HLE, etc), the NV2A LLE and NVNet implementation are primarily the work of the XQEMU developers.
* [XboxDev](https://github.com/xboxdev) - Providing Xbox hardware research & useful tooling.
* [XbSymbolDatabase](https://github.com/Cxbx-Reloaded/XbSymbolDatabase) - Providing support to detect symbols across XDK builds from reverse engineered retail titles.
* [Xbox Kernel Test Suite](https://github.com/Cxbx-Reloaded/xbox_kernel_test_suite) - Making accurate tests on hardware to compare against cxbxr's kernel implementation.

View File

@ -47,9 +47,6 @@ GOTO :helpInfo
)
:: Check second arg (Visual Studio version)
IF "%2"=="2022" (
SET msvc_compiler=Visual Studio 17 2022
)
IF "%2"=="2019" (
SET msvc_compiler=Visual Studio 16 2019
)
@ -57,7 +54,7 @@ IF "%2"=="2017" (
SET msvc_compiler=Visual Studio 15 2017
)
IF "%2"=="" (
SET msvc_compiler=Visual Studio 16 2019
SET msvc_compiler=Visual Studio 15 2017
)
IF NOT DEFINED msvc_compiler (
GOTO :helpInfo
@ -103,9 +100,8 @@ ECHO - ARM
ECHO - ARM64
ECHO ---
ECHO arg2
ECHO - 2022
ECHO - 2019
ECHO - 2017
ECHO - 2019
PAUSE
GOTO :end

@ -1 +1 @@
Subproject commit fa24d868ac2f8fd558e4e914c9863411245db8fd
Subproject commit c7b8b49ef8691ac85ad18298468f7e4a616290ed

@ -1 +1 @@
Subproject commit 774111351210e6f340246d6fb32741b09708f381
Subproject commit 78d06c0d9d8fe3b5d43e90312fc5910928c9c651

@ -1 +1 @@
Subproject commit f8a95b7afa963c90b01a9e7cd758346f95c90f50
Subproject commit 7c491b6ef7e49c7f35dcdd39f99f1f5943e48e9e

@ -1 +0,0 @@
Subproject commit 8ced41570e4692b0d556503683ae45f92416f5f1

@ -1 +0,0 @@
Subproject commit cf178f1fac38426990425cc034f7d4b8c9e1e388

@ -1 +0,0 @@
Subproject commit 3f86a95c0784d73ce6815237ec33ed25f233b643

@ -1 +0,0 @@
Subproject commit ead0af5dee49e408c005151393f8a7dbcd27026c

@ -1 +1 @@
Subproject commit 83d4e1ebef3588fae48b69a7352cc21801cb70bc
Subproject commit 29cb47ea7674b36cf2b742c11cf2568add1f47fc

View File

@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.12)
project(cxbx)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 17)
# Suppress extra stuff from generated solution
set(CMAKE_SUPPRESS_REGENERATION true)
@ -12,10 +12,9 @@ include_directories(
"${CXBXR_ROOT_DIR}/src/common"
"${CXBXR_ROOT_DIR}/src/common/Win32"
"${CXBXR_ROOT_DIR}/import/OpenXDK/include"
"${CXBXR_ROOT_DIR}/import/DirectX9/include"
"${CXBXR_ROOT_DIR}/import/distorm/include"
"${CXBXR_ROOT_DIR}/import/glew-2.0.0/include"
"${CXBXR_ROOT_DIR}/import/libusb/libusb"
"${CXBXR_ROOT_DIR}/import/DirectX9/include"
"${CXBXR_ROOT_DIR}/import/simpleini"
"${CXBXR_ROOT_DIR}/import/winpcap/Include"
"${CXBXR_ROOT_DIR}/import/xxHash"
@ -42,11 +41,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
LTC_NO_PRNGS
LTC_NO_MISC
LTC_NO_PROTOTYPES
# Enable Chihiro work
CHIHIRO_WORK
)
# Reference: https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically
add_compile_options(
# Catch synchronous (C++) exceptions only
@ -68,7 +64,7 @@ XXH_INLINE_ALL
)
file (GLOB RESOURCES
"${CXBXR_ROOT_DIR}/CONTRIBUTORS"
"${CXBXR_ROOT_DIR}/COPYING"
"${CXBXR_ROOT_DIR}/README.md"
@ -77,22 +73,19 @@ file (GLOB RESOURCES
"${CXBXR_ROOT_DIR}/src/gui/resource/Cxbx-R.ico"
"${CXBXR_ROOT_DIR}/src/gui/resource/Logo.bmp"
"${CXBXR_ROOT_DIR}/src/gui/resource/Logo-License-CC4.bmp"
"${CXBXR_ROOT_DIR}/src/gui/resource/ResCxbx.h"
"${CXBXR_ROOT_DIR}/src/.editorconfig"
)
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX header FILES
${CXBXR_HEADER_GUIv1}
${CXBXR_HEADER_COMMON}
${CXBXR_HEADER_EMU}
)
source_group(TREE ${CXBXR_ROOT_DIR}/import PREFIX import FILES
${CXBXR_SOURCE_EMU_IMPORT}
)
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX source FILES
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX source FILES
${CXBXR_SOURCE_GUIv1}
${CXBXR_SOURCE_COMMON}
${CXBXR_SOURCE_EMU}
)
source_group(TREE ${CXBXR_ROOT_DIR} FILES ${RESOURCES})
@ -100,8 +93,10 @@ source_group(TREE ${CXBXR_ROOT_DIR} FILES ${RESOURCES})
add_executable(cxbx WIN32 ${RESOURCES}
${CXBXR_HEADER_GUIv1}
${CXBXR_HEADER_COMMON}
${CXBXR_HEADER_EMU}
${CXBXR_SOURCE_GUIv1}
${CXBXR_SOURCE_COMMON}
${CXBXR_SOURCE_EMU}
${CXBXR_GIT_VERSION_H}
)
@ -111,17 +106,25 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Reference: https://docs.microsoft.com/en-us/cpp/build/reference/linker-options
set_target_properties(cxbx PROPERTIES
LINK_FLAGS "
/NODEFAULTLIB:libcmt \
/INCREMENTAL:NO
/LARGEADDRESSAWARE
/FIXED
/SAFESEH:NO
/DYNAMICBASE:NO
/BASE:0x10000
/STACK:65536,65536
/NODEFAULTLIB:libcmt
/DELAYLOAD:wpcap.dll
"
LINK_FLAGS_RELEASE "
/LTCG \
/DEBUG \
/LTCG
/DEBUG
"
)
# Reference: https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically
# /Zi = create a PDB file without affecting optimization
# /Ob3 = Controls inline expansion of functions.
# /Ob2 = Controls inline expansion of functions.
# /Oi = Generate intrinsic functions
# /Ot = In favor of using fast code than small code
# /GL = Whole program optimization
@ -130,19 +133,19 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# /Qpar = Enable automatic parallelize loops in the code
# Set optimization options for release build
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} \
/Zi \
/Ob3 \
/Oi \
/Ot \
/GL \
\
/GS- \
/Gy \
/Qpar \
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}
/Zi
/Ob2
/Oi
/Ot
/GL
/GS-
/Gy
/Qpar
"
)
# disable optimization for CxbxKrnl.cpp file
set_source_files_properties(
${CXBXR_KRNL_CPP} PROPERTIES COMPILE_FLAGS "/Od /GL-"
@ -150,11 +153,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
endif()
# Windows libraries
set(WINS_LIB
set(WINS_LIB
legacy_stdio_definitions
d3d9
d3dcompiler
delayimp
dinput8
dxguid
odbc32
@ -170,7 +172,7 @@ set(WINS_LIB
comctl32
XINPUT9_1_0
Iphlpapi
Dwmapi
wpcap
)
target_link_libraries(cxbx
@ -178,28 +180,12 @@ target_link_libraries(cxbx
subhook
libtomcrypt
SDL2
imgui
libusb
mio::mio_min_winapi
${WINS_LIB}
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])" AND BUILD_CXBXR_DEBUGGER)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
add_dependencies(cxbx cxbxr-debugger)
endif()
add_dependencies(cxbx cxbxr-ldr cxbxr-emu misc-batch)
# Try to stop cmake from building hlsl files
# Which are all currently loaded at runtime only
set_source_files_properties(
${CXBXR_HEADER_HLSL}
PROPERTIES
HEADER_FILE_ONLY TRUE
VS_TOOL_OVERRIDE "None"
)

View File

@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.12)
project(cxbxr-emu)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 17)
# Suppress extra stuff from generated solution
set(CMAKE_SUPPRESS_REGENERATION true)
@ -15,10 +15,9 @@ include_directories(
"${CXBXR_ROOT_DIR}/src/common"
"${CXBXR_ROOT_DIR}/src/common/Win32"
"${CXBXR_ROOT_DIR}/import/OpenXDK/include"
"${CXBXR_ROOT_DIR}/import/DirectX9/include"
"${CXBXR_ROOT_DIR}/import/distorm/include"
"${CXBXR_ROOT_DIR}/import/glew-2.0.0/include"
"${CXBXR_ROOT_DIR}/import/libusb/libusb"
"${CXBXR_ROOT_DIR}/import/DirectX9/include"
"${CXBXR_ROOT_DIR}/import/simpleini"
"${CXBXR_ROOT_DIR}/import/winpcap/Include"
"${CXBXR_ROOT_DIR}/import/xxHash"
@ -48,9 +47,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Use inline XXHash version
XXH_INLINE_ALL
# Enable Chihiro work
CHIHIRO_WORK
)
add_compile_options(
/EHs
@ -72,10 +68,6 @@ file (GLOB RESOURCES
"${CXBXR_ROOT_DIR}/README.md"
)
source_group(TREE ${CXBXR_ROOT_DIR}/import PREFIX import FILES
${CXBXR_HEADER_EMU_IMPORT}
)
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX header FILES
${CXBXR_HEADER_GUIv1}
${CXBXR_HEADER_COMMON}
@ -83,11 +75,7 @@ source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX header FILES
"${CXBXR_ROOT_DIR}/src/emulator/targetver.h"
)
source_group(TREE ${CXBXR_ROOT_DIR}/import PREFIX import FILES
${CXBXR_SOURCE_EMU_IMPORT}
)
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX source FILES
source_group(TREE ${CXBXR_ROOT_DIR}/src PREFIX source FILES
${CXBXR_SOURCE_GUIv1}
${CXBXR_SOURCE_COMMON}
${CXBXR_SOURCE_EMU}
@ -99,11 +87,9 @@ source_group(TREE ${CXBXR_ROOT_DIR} FILES ${RESOURCES})
add_library(cxbxr-emu SHARED ${RESOURCES}
${CXBXR_HEADER_COMMON}
${CXBXR_HEADER_EMU_IMPORT}
${CXBXR_HEADER_EMU}
"${CXBXR_ROOT_DIR}/src/emulator/targetver.h"
${CXBXR_SOURCE_COMMON}
${CXBXR_SOURCE_EMU_IMPORT}
${CXBXR_SOURCE_EMU}
${CXBXR_GIT_VERSION_H}
"${CXBXR_ROOT_DIR}/src/emulator/cxbxr-emu.cpp"
@ -115,40 +101,39 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set_target_properties(cxbxr-emu PROPERTIES
LINK_FLAGS "
/INCREMENTAL:NO \
/LARGEADDRESSAWARE \
/SAFESEH:NO \
/STACK:65536,65536 \
/NODEFAULTLIB:libcmt \
/DELAYLOAD:wpcap.dll \
/INCREMENTAL:NO
/LARGEADDRESSAWARE
/SAFESEH:NO
/STACK:65536,65536
/NODEFAULTLIB:libcmt
/DELAYLOAD:wpcap.dll
"
LINK_FLAGS_RELEASE "
/LTCG \
/DEBUG \
/LTCG
/DEBUG
"
)
# Set optimization options for release build
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} \
/Zi \
/Ob3 \
/Oi \
/Ot \
/GL \
\
/GS- \
/Gy \
/Qpar \
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}
/Zi
/Ob2
/Oi
/Ot
/GL
/GS-
/Gy
/Qpar
"
)
endif()
# Windows libraries
set(WINS_LIB
set(WINS_LIB
legacy_stdio_definitions
d3d9
d3dcompiler
delayimp
dinput8
dxguid
odbc32
@ -172,25 +157,8 @@ target_link_libraries(cxbxr-emu
subhook
libtomcrypt
SDL2
imgui
libusb
nv2a_vsh_emulator
mio::mio_min_winapi
${WINS_LIB}
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
add_dependencies(cxbxr-emu cxbxr-ldr misc-batch)
# Try to stop cmake from building hlsl files
# Which are all currently loaded at runtime only
set_source_files_properties(
${CXBXR_HEADER_HLSL}
PROPERTIES
HEADER_FILE_ONLY TRUE
VS_TOOL_OVERRIDE "None"
)

View File

@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.12)
project(cxbxr-ldr)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 17)
# Suppress extra stuff from generated solution
set(CMAKE_SUPPRESS_REGENERATION true)
@ -25,14 +25,11 @@ endif()
file (GLOB HEADERS
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/ReserveAddressRanges.h"
"${CXBXR_ROOT_DIR}/src/CxbxVersion.h"
"${CXBXR_ROOT_DIR}/src/version.h"
)
file (GLOB SOURCES
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/common/ReserveAddressRanges.cpp"
"${CXBXR_ROOT_DIR}/src/CxbxVersion.cpp"
"${CXBXR_ROOT_DIR}/src/loader/cxbxr-ldr.cpp"
)
@ -47,19 +44,19 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set_target_properties(cxbxr-ldr PROPERTIES
LINK_FLAGS "
/LARGEADDRESSAWARE \
/FIXED \
/DYNAMICBASE:NO \
/BASE:0x10000 \
/STACK:65536,65536 \
/NODEFAULTLIB \
/ENTRY:rawMain \
/LARGEADDRESSAWARE
/FIXED
/DYNAMICBASE:NO
/BASE:0x10000
/STACK:65536,65536
/NODEFAULTLIB
/ENTRY:rawMain
"
)
# Set optimization options for release build
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} \
/Oi \
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}
/Oi
"
)
endif()
@ -67,9 +64,3 @@ endif()
target_link_libraries(cxbxr-ldr
PUBLIC kernel32.lib
)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)
add_dependencies(cxbxr-ldr misc-batch)

View File

@ -1,42 +0,0 @@
cmake_minimum_required (VERSION 3.8)
project(imgui LANGUAGES CXX)
# Since imgui doesn't have CMake, we'll make an interface project here.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_compile_definitions(
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE
)
endif()
# Add any defines from imconfig.h file in here without need to edit import file directly.
add_compile_definitions(
IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
)
file (GLOB HEADERS
"${CXBXR_ROOT_DIR}/import/imgui/imconfig.h"
"${CXBXR_ROOT_DIR}/import/imgui/imgui.h"
"${CXBXR_ROOT_DIR}/import/imgui/imgui_internal.h"
"${CXBXR_ROOT_DIR}/import/imgui/imstb_rectpack.h"
"${CXBXR_ROOT_DIR}/import/imgui/imstb_textedit.h"
"${CXBXR_ROOT_DIR}/import/imgui/imstb_truetype.h"
)
file (GLOB SOURCES
"${CXBXR_ROOT_DIR}/import/imgui/imgui.cpp"
"${CXBXR_ROOT_DIR}/import/imgui/imgui_draw.cpp"
"${CXBXR_ROOT_DIR}/import/imgui/imgui_tables.cpp"
"${CXBXR_ROOT_DIR}/import/imgui/imgui_widgets.cpp"
)
source_group(TREE ${CXBXR_ROOT_DIR}/import/imgui PREFIX header FILES ${HEADERS})
source_group(TREE ${CXBXR_ROOT_DIR}/import/imgui PREFIX source FILES ${SOURCES})
add_library(${PROJECT_NAME} ${HEADERS} ${SOURCES})
target_include_directories(${PROJECT_NAME}
PUBLIC "${CXBXR_ROOT_DIR}/import/imgui"
)

View File

@ -1,51 +0,0 @@
cmake_minimum_required (VERSION 3.8)
project(libusb LANGUAGES CXX)
# Since libusb doesn't have CMake, we'll make an interface project here.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_compile_definitions(
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE
)
endif()
include_directories(
"${CXBXR_ROOT_DIR}/import/libusb/msvc"
"${CXBXR_ROOT_DIR}/import/libusb/libusb")
file (GLOB HEADERS
"${CXBXR_ROOT_DIR}/import/libusb/libusb/libusb.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/libusbi.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/version.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/version_nano.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/msvc/config.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/events_windows.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/threads_windows.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_common.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_usbdk.h"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_winusb.h"
)
file (GLOB SOURCES
"${CXBXR_ROOT_DIR}/import/libusb/libusb/core.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/descriptor.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/hotplug.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/io.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/strerror.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/sync.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/events_windows.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/threads_windows.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_common.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_usbdk.c"
"${CXBXR_ROOT_DIR}/import/libusb/libusb/os/windows_winusb.c"
)
source_group(TREE ${CXBXR_ROOT_DIR}/import/libusb/libusb PREFIX header FILES ${HEADERS})
source_group(TREE ${CXBXR_ROOT_DIR}/import/libusb/libusb PREFIX source FILES ${SOURCES})
add_library(${PROJECT_NAME} ${HEADERS} ${SOURCES})
target_include_directories(${PROJECT_NAME}
PUBLIC "${CXBXR_ROOT_DIR}/import/libusb"
)

View File

@ -0,0 +1,40 @@
cmake_minimum_required (VERSION 3.8)
project(vsbc)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
# Suppress extra stuff from generated solution
set(CMAKE_SUPPRESS_REGENERATION true)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_compile_definitions(_CRT_SECURE_NO_WARNINGS
)
endif()
add_compile_definitions(CXBXVSBC_EXPORTS
)
file (GLOB HEADERS
"${CXBXR_ROOT_DIR}/src/vsbc/CxbxVSBC.h"
"${CXBXR_ROOT_DIR}/src/vsbc/DlgVirtualSBCFeedback.h"
"${CXBXR_ROOT_DIR}/src/vsbc/stdafx.h"
"${CXBXR_ROOT_DIR}/src/vsbc/targetver.h"
)
file (GLOB SOURCES
"${CXBXR_ROOT_DIR}/src/vsbc/CxbxVSBC.cpp"
"${CXBXR_ROOT_DIR}/src/vsbc/DlgVirtualSBCFeedback.cpp"
"${CXBXR_ROOT_DIR}/src/vsbc/dllmain.cpp"
"${CXBXR_ROOT_DIR}/src/vsbc/stdafx.cpp"
)
source_group(TREE ${CXBXR_ROOT_DIR}/src/vsbc PREFIX header FILES ${HEADERS})
source_group(TREE ${CXBXR_ROOT_DIR}/src/vsbc PREFIX source FILES ${SOURCES})
add_library(vsbc SHARED ${HEADERS} ${SOURCES})
set_target_properties(vsbc PROPERTIES
OUTPUT_NAME CxbxVSBC
)

View File

@ -3,5 +3,5 @@ root = true
[*]
indent_size = 4
trim_trailing_whitespace = true
end_of_line = lf
end_of_line = crlf
insert_final_newline = true

View File

@ -61,14 +61,13 @@ enum DebugMode { DM_NONE, DM_CONSOLE, DM_FILE };
/*! debugger enable state */
enum DebuggerState { debuggerOff, debuggerOn };
/*! indicates emulation of a Chihiro system */
/*! indicates emulation of an Chihiro (arcade, instead of Xbox console) executable */
extern bool g_bIsChihiro;
/*! indicates emulation of a DevKit system */
/* Note: Our DevKit emulation lacks the kernel debugging interface and virtual dvd-rom emulator card, so this is actually a Debug Kit */
extern bool g_bIsDevKit;
/*! indicates emulation of a Debug xbe executable */
extern bool g_bIsDebug;
/*! indicates emulation of a Retail system */
/*! indicates emulation of a Retail xbe executable*/
extern bool g_bIsRetail;
/*! indicates ability to save on exit (needed for settings reset) */
@ -84,4 +83,6 @@ extern volatile bool g_bPrintfOn;
#define CxbxSetThreadName(Name)
#endif
#include <filesystem>
#endif

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.8" sku=".NETFramework,Version=v4.8"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>

View File

@ -13,12 +13,6 @@ add_compile_options(
/langversion:6
)
# First, we must define .NET Framework version before include cs_x86's projects.
# Which then will pass down version we want unified.
set(DOTNET_TARGET_FRAMEWORK_VERSION "v4.8")
add_subdirectory("${CXBXR_ROOT_DIR}/import/cs_x86" "${CMAKE_BINARY_DIR}/import/cs_x86")
set(CXBXR_DEBUGGER_SRC_DIR "${CXBXR_ROOT_DIR}/src/CxbxDebugger")
file (GLOB SOURCES
@ -43,13 +37,9 @@ file (GLOB SOURCES
"${CXBXR_DEBUGGER_SRC_DIR}/DebugOutputManager.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/FileEventManager.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/FileWatchManager.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/IDebugWindow.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.resx"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.resx"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.resx"
"${CXBXR_DEBUGGER_SRC_DIR}/PatchManager.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Program.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Resources/BreakpointDisable_16x_24.bmp"
@ -107,21 +97,16 @@ file (GLOB PROPERTIES
)
csharp_set_windows_forms_properties(
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.resx"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.resx"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.Designer.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/Form1.resx"
)
csharp_set_designer_cs_properties(
${PROPERTIES}
)
set_source_files_properties(
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerInstance.cs"
"${CXBXR_DEBUGGER_SRC_DIR}/CxbxDebuggerMain.cs"
set_source_files_properties("${CXBXR_DEBUGGER_SRC_DIR}/Form1.cs"
VS_CSHARP_SubType "Form"
)
@ -134,18 +119,15 @@ source_group(TREE ${CXBXR_ROOT_DIR} FILES ${SOURCES})
add_executable(cxbxr-debugger WIN32 ${SOURCES} ${PROPERTIES} #Test WIN32 like cxbx does if doesn't need compile option set
)
set_target_properties(cxbxr-debugger PROPERTIES
set_target_properties(cxbxr-debugger PROPERTIES
VS_DOTNET_REFERENCES
"Microsoft.CSharp;System;System.Core;System.Data;System.Data.DataSetExtensions;System.Deployment;System.Drawing;System.Windows;System.Windows.Forms;System.Xml;System.Xml.Linq;System.Net.Http"
VS_GLOBAL_ApplicationIcon "${CXBXR_ROOT_DIR}/src/gui/resource/Cxbx-R.ico"
VS_GLOBAL_ROOTNAMESPACE "CxbxDebugger"
DOTNET_TARGET_FRAMEWORK_VERSION ${DOTNET_TARGET_FRAMEWORK_VERSION}
)
set_property(TARGET cxbxr-debugger PROPERTY DOTNET_TARGET_FRAMEWORK_VERSION "v4.5")
target_link_libraries(cxbxr-debugger cs_x86)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)

View File

@ -1,201 +0,0 @@
namespace CxbxDebugger
{
partial class CxbxDebuggerMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CxbxDebuggerMain));
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.fileMenu = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.miStartDebugging = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.miSuspend = new System.Windows.Forms.ToolStripMenuItem();
this.miResume = new System.Windows.Forms.ToolStripMenuItem();
this.windowsMenu = new System.Windows.Forms.ToolStripMenuItem();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.lblStatusDeprecate = new System.Windows.Forms.ToolStripStatusLabel();
this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.menuStrip.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// menuStrip
//
this.menuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileMenu,
this.debugToolStripMenuItem,
this.windowsMenu});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.MdiWindowListItem = this.windowsMenu;
this.menuStrip.Name = "menuStrip";
this.menuStrip.Padding = new System.Windows.Forms.Padding(4, 1, 0, 1);
this.menuStrip.Size = new System.Drawing.Size(734, 24);
this.menuStrip.TabIndex = 0;
this.menuStrip.Text = "MenuStrip";
//
// fileMenu
//
this.fileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.exitToolStripMenuItem});
this.fileMenu.ImageTransparentColor = System.Drawing.SystemColors.ActiveBorder;
this.fileMenu.Name = "fileMenu";
this.fileMenu.Size = new System.Drawing.Size(37, 22);
this.fileMenu.Text = "&File";
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.ShortcutKeyDisplayString = "Alt+F4";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
this.exitToolStripMenuItem.Text = "E&xit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolsStripMenuItem_Click);
//
// debugToolStripMenuItem
//
this.debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miStartDebugging,
this.toolStripMenuItem1,
this.miSuspend,
this.miResume});
this.debugToolStripMenuItem.Name = "debugToolStripMenuItem";
this.debugToolStripMenuItem.Size = new System.Drawing.Size(54, 22);
this.debugToolStripMenuItem.Text = "Debug";
//
// miStartDebugging
//
this.miStartDebugging.Image = global::CxbxDebugger.Properties.Resources.run;
this.miStartDebugging.ImageTransparentColor = System.Drawing.Color.Magenta;
this.miStartDebugging.Name = "miStartDebugging";
this.miStartDebugging.ShortcutKeyDisplayString = "F5";
this.miStartDebugging.Size = new System.Drawing.Size(117, 22);
this.miStartDebugging.Text = "&Start";
this.miStartDebugging.Click += new System.EventHandler(this.startDebuggingToolStripMenuItem_Click);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(114, 6);
//
// miSuspend
//
this.miSuspend.Image = global::CxbxDebugger.Properties.Resources.pause;
this.miSuspend.ImageTransparentColor = System.Drawing.Color.Magenta;
this.miSuspend.Name = "miSuspend";
this.miSuspend.Size = new System.Drawing.Size(117, 22);
this.miSuspend.Text = "&Break";
this.miSuspend.Click += new System.EventHandler(this.suspendToolStripMenuItem_Click);
//
// miResume
//
this.miResume.Image = global::CxbxDebugger.Properties.Resources.run;
this.miResume.ImageTransparentColor = System.Drawing.Color.Magenta;
this.miResume.Name = "miResume";
this.miResume.Size = new System.Drawing.Size(117, 22);
this.miResume.Text = "&Resume";
this.miResume.Click += new System.EventHandler(this.resumeToolStripMenuItem_Click);
//
// windowsMenu
//
this.windowsMenu.Name = "windowsMenu";
this.windowsMenu.Size = new System.Drawing.Size(68, 22);
this.windowsMenu.Text = "&Windows";
//
// statusStrip1
//
this.statusStrip1.ImageScalingSize = new System.Drawing.Size(24, 24);
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.lblStatusDeprecate,
this.lblStatus});
this.statusStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.VerticalStackWithOverflow;
this.statusStrip1.Location = new System.Drawing.Point(0, 339);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 9, 0);
this.statusStrip1.Size = new System.Drawing.Size(734, 61);
this.statusStrip1.TabIndex = 2;
this.statusStrip1.Text = "statusStrip1";
//
// lblStatusDeprecate
//
this.lblStatusDeprecate.BackColor = System.Drawing.Color.Yellow;
this.lblStatusDeprecate.Name = "lblStatusDeprecate";
this.lblStatusDeprecate.Size = new System.Drawing.Size(723, 15);
this.lblStatusDeprecate.Spring = true;
this.lblStatusDeprecate.Text = "WARNING: cxbxr-debugger will eventually be removed from upstream branch.";
this.lblStatusDeprecate.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblStatus
//
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(723, 15);
this.lblStatus.Text = "Ready";
//
// CxbxDebuggerMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(734, 361);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.menuStrip);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.IsMdiContainer = true;
this.MainMenuStrip = this.menuStrip;
this.Name = "CxbxDebuggerMain";
this.Text = "cxbx-debugger";
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip;
private System.Windows.Forms.ToolStripMenuItem fileMenu;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem windowsMenu;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.ToolStripMenuItem debugToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem miStartDebugging;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem miSuspend;
private System.Windows.Forms.ToolStripMenuItem miResume;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel lblStatusDeprecate;
private System.Windows.Forms.ToolStripStatusLabel lblStatus;
}
}

View File

@ -1,156 +0,0 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CxbxDebugger
{
public partial class CxbxDebuggerMain : Form, IDebugContainerWindow
{
public CxbxDebuggerMain(string[] args)
{
InitializeComponent();
var StartupArgs = new string[args.Length - 1];
Array.Copy(args, 1, StartupArgs, 0, args.Length - 1);
// Setup session without initially running the game
AddDebugSession(StartupArgs, false);
#if FALSE
AddDebugSession(new string[] { }, false);
#endif
}
private void ExitToolsStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void startDebuggingToolStripMenuItem_Click(object sender, EventArgs e)
{
if (ActiveMdiChild is IDebugWindow)
{
(ActiveMdiChild as IDebugWindow).StartSession();
}
}
private void suspendToolStripMenuItem_Click(object sender, EventArgs e)
{
if (ActiveMdiChild is IDebugWindow)
{
(ActiveMdiChild as IDebugWindow).SuspendSession();
}
}
private void resumeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (ActiveMdiChild is IDebugWindow)
{
(ActiveMdiChild as IDebugWindow).ResumeSession();
}
}
public void AddDebugSession(string[] Arguments, bool StartAutomatically)
{
var SessionWindow = CreateNewSessionWindow(Arguments);
if (StartAutomatically)
{
SessionWindow.StartSession();
}
}
public void ReportGameTitle(string GameTitle)
{
Text = $"cxbx-debugger ({GameTitle})";
}
private IDebugWindow CreateNewSessionWindow(string[] Arguments)
{
var childForm = new CxbxDebuggerInstance(this, Arguments);
childForm.WindowState = FormWindowState.Maximized;
childForm.TextChanged += (sender, e) => { OnSessionWindowRenamed(sender as Form); };
childForm.Activated += (sender, e) => { OnSessionWindowActivated(sender as IDebugWindow); };
childForm.Show();
return childForm;
}
private void OnSessionWindowActivated(IDebugWindow child)
{
var state = child.GetDebugStateInfo();
RefreshStatusText(state);
}
private void OnSessionWindowRenamed(Form form)
{
// https://stackoverflow.com/questions/1347734/mdi-window-list-not-updating-child-title-bar-texts
ActivateMdiChild(null);
ActivateMdiChild(form);
}
public void ReportStatus(IDebugWindow Window, DebugState State, string Detail)
{
if (Window == ActiveMdiChild)
{
RefreshStatusText(new DebugStateInfo() { State = State, Detail = Detail });
}
}
private void RefreshStatusText(DebugStateInfo stateInfo)
{
var stateString = "";
var canSuspend = false;
var canResume = false;
var canRun = false;
switch (stateInfo.State)
{
case DebugState.Unknown:
stateString = "No valid Xbe was loaded. Invalid session.";
break;
case DebugState.Idle:
stateString = "Ready";
canRun = true;
break;
case DebugState.Suspended:
stateString = "Suspended";
canResume = true;
break;
case DebugState.Running:
stateString = "Running";
canSuspend = true;
break;
case DebugState.Terminated:
stateString = "Terminated";
//canRun = true; // Uncomment to allow restarted sessions
break;
}
if (!string.IsNullOrEmpty(stateInfo.Detail))
{
stateString += $" - {stateInfo.Detail}";
}
miStartDebugging.Enabled = canRun;
miSuspend.Enabled = canSuspend;
miResume.Enabled = canResume;
lblStatus.Text = stateString;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,6 @@ using WinDebug = VsChromium.Core.Win32.Debugging;
using System.Runtime.InteropServices;
using WinLowLevel = LowLevelDesign.Win32.Windows.NativeMethods;
using System.Threading;
using System.Threading.Tasks;
namespace CxbxDebugger
{
@ -33,18 +32,13 @@ namespace CxbxDebugger
string[] args = new string[] { };
string Target = "";
public string TargetPath
{
get { return Target; }
}
RunState State = RunState.NotLaunched;
DebuggerMessages.DebuggerInit InitParams = new DebuggerMessages.DebuggerInit();
DebuggerInstance DebugInstance;
List<IDebuggerSessionEvents> SessionEvents = new List<IDebuggerSessionEvents>();
List<IDebuggerGeneralEvents> GeneralEvents = new List<IDebuggerGeneralEvents>();
List<IDebuggerProcessEvents> ProcessEvents = new List<IDebuggerProcessEvents>();
List<IDebuggerThreadEvents> ThreadEvents = new List<IDebuggerThreadEvents>();
List<IDebuggerModuleEvents> ModuleEvents = new List<IDebuggerModuleEvents>();
@ -109,7 +103,7 @@ namespace CxbxDebugger
bpStall.Set();
// Remove all events
SessionEvents.Clear();
GeneralEvents.Clear();
ProcessEvents.Clear();
ThreadEvents.Clear();
ModuleEvents.Clear();
@ -178,9 +172,6 @@ namespace CxbxDebugger
if (CanLaunch() == false)
throw new Exception("Unable to launch in this state");
if (args.Length == 0)
return false;
var DebugCreationFlags =
WinProcesses.ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS |
WinProcesses.ProcessCreationFlags.CREATE_NEW_CONSOLE;
@ -206,7 +197,7 @@ namespace CxbxDebugger
// Store so they can be marshalled and closed correctly
hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess);
hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread);
bContinue = true;
State = RunState.Running;
@ -322,7 +313,10 @@ namespace CxbxDebugger
Thread.StartAddress = DebugInfo.lpStartAddress;
Thread.ThreadBase = DebugInfo.lpThreadLocalBase;
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(Thread));
foreach (IDebuggerThreadEvents Event in ThreadEvents )
{
Event.OnThreadCreate(Thread);
}
}
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent)
@ -339,7 +333,10 @@ namespace CxbxDebugger
{
uint ExitCode = DebugInfo.dwExitCode;
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadExit(TargetThread, ExitCode));
foreach (IDebuggerThreadEvents Event in ThreadEvents)
{
Event.OnThreadExit(TargetThread, ExitCode);
}
}
}
@ -372,17 +369,26 @@ namespace CxbxDebugger
DebugInstance = new DebuggerInstance(Process);
RegisterEventInterfaces(DebugInstance);
Parallel.ForEach(ProcessEvents, Event => Event.OnProcessCreate(Process));
foreach (IDebuggerProcessEvents Event in ProcessEvents)
{
Event.OnProcessCreate(Process);
}
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(MainThread));
foreach (IDebuggerThreadEvents Event in ThreadEvents)
{
Event.OnThreadCreate(MainThread);
}
var XboxModule = new DebuggerModule();
XboxModule.Path = Target;
XboxModule.ImageBase = DebugInfo.lpBaseOfImage;
XboxModule.Core = true;
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(XboxModule));
foreach (IDebuggerModuleEvents Event in ModuleEvents)
{
Event.OnModuleLoaded(XboxModule);
}
}
private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent)
@ -399,7 +405,10 @@ namespace CxbxDebugger
if (TargetProcess != null)
{
Parallel.ForEach(ProcessEvents, Event => Event.OnProcessExit(TargetProcess, ExitCode));
foreach (IDebuggerProcessEvents Event in ProcessEvents)
{
Event.OnProcessExit(TargetProcess, ExitCode);
}
}
}
@ -417,7 +426,10 @@ namespace CxbxDebugger
Module.Path = ResolveProcessPath(DebugInfo.hFile);
Module.ImageBase = DebugInfo.lpBaseOfDll;
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(Module));
foreach (IDebuggerModuleEvents Event in ModuleEvents)
{
Event.OnModuleLoaded(Module);
}
}
private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent)
@ -433,7 +445,10 @@ namespace CxbxDebugger
if (TargetModule != null)
{
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleUnloaded(TargetModule));
foreach (IDebuggerModuleEvents Event in ModuleEvents)
{
Event.OnModuleUnloaded(TargetModule);
}
}
}
@ -443,7 +458,10 @@ namespace CxbxDebugger
string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1);
Parallel.ForEach(OutputEvents, Event => Event.OnDebugOutput(debugString));
foreach(IDebuggerOutputEvents Event in OutputEvents)
{
Event.OnDebugOutput(debugString);
}
}
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent)
@ -464,28 +482,12 @@ namespace CxbxDebugger
}
break;
case ExceptionCode.PrivilegedInstruction:
{
// Seeing this frequently called in Win10
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
}
break;
case ExceptionCode.StatusHandleNotClosable:
{
// Seeing this frequently called in Win10
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
}
break;
case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION:
{
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
bool Handled = false;
foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
@ -504,7 +506,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetHLECacheReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetHLECacheReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
SetupHLECacheProvider(Report.FileName);
}
}
@ -515,7 +517,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetKernelPatchReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetKernelPatchReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
KernelSymbolProvider.AddKernelSymbolFromMessage(Report);
}
@ -527,9 +529,12 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetFileOpenedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetFileOpenedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
Parallel.ForEach(FileEvents, Event => Event.OnFileOpened(Report));
foreach (IDebuggerFileEvents Event in FileEvents)
{
Event.OnFileOpened(Report);
}
}
}
break;
@ -539,9 +544,12 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetFileReadReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetFileReadReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
Parallel.ForEach(FileEvents, Event => Event.OnFileRead(Report));
foreach (IDebuggerFileEvents Event in FileEvents)
{
Event.OnFileRead(Report);
}
}
}
break;
@ -551,9 +559,12 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetFileWriteReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetFileWriteReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
Parallel.ForEach(FileEvents, Event => Event.OnFileWrite(Report));
foreach (IDebuggerFileEvents Event in FileEvents)
{
Event.OnFileWrite(Report);
}
}
}
break;
@ -563,10 +574,13 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetFileClosedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetFileClosedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
if (Report != null)
{
Parallel.ForEach(FileEvents, Event => Event.OnFileClosed(Report));
foreach (IDebuggerFileEvents Event in FileEvents)
{
Event.OnFileClosed(Report);
}
}
}
}
@ -577,23 +591,14 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetDebuggerInitReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetDebuggerInitReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
InitParams = Report;
Parallel.ForEach(SessionEvents, Event => Event.OnDebugTitleLoaded(InitParams.Title));
}
}
break;
case (ExceptionCode)DebuggerMessages.ReportType.DEBUGGER_NEW_TARGET:
{
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetDebuggerNewTargetReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
Parallel.ForEach(SessionEvents, Event => Event.OnDebugTargetChanged(Report.CommandLine));
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
{
Event.OnDebugTitleLoaded(InitParams.Title);
}
}
}
break;
@ -603,7 +608,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetMSVCThreadName(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
var Report = DebuggerMessages.GetMSVCThreadName(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
if(Report != null)
{
// Resolve the ThreadId of an invalid ID to the current thread name
@ -618,7 +623,10 @@ namespace CxbxDebugger
// Update the resolved thread name
ResolvedThread.DebugName = Report.Name;
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadNamed(Thread));
foreach (IDebuggerThreadEvents Event in ThreadEvents)
{
Event.OnThreadNamed(Thread);
}
}
}
}
@ -636,7 +644,10 @@ namespace CxbxDebugger
bpStall.Reset();
Parallel.ForEach(ExceptionEvents, Event => Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance));
foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
{
Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance);
}
bpStall.WaitOne();
}
@ -663,7 +674,10 @@ namespace CxbxDebugger
WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT();
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE;
Parallel.ForEach(SessionEvents, Event => Event.OnDebugStart());
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
{
Event.OnDebugStart();
}
// Loop until told to stop
while (bContinue == true)
@ -720,7 +734,10 @@ namespace CxbxDebugger
State = RunState.Ended;
Parallel.ForEach(SessionEvents, Event => Event.OnDebugEnd());
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
{
Event.OnDebugEnd();
}
}
public DebuggerSymbol ResolveSymbol(uint Address)
@ -740,8 +757,8 @@ namespace CxbxDebugger
public void RegisterEventInterfaces(object EventClass)
{
IDebuggerSessionEvents SessionListener = EventClass as IDebuggerSessionEvents;
if(SessionListener != null ) SessionEvents.Add(SessionListener);
IDebuggerGeneralEvents GeneralListener = EventClass as IDebuggerGeneralEvents;
if(GeneralListener != null ) GeneralEvents.Add(GeneralListener);
IDebuggerProcessEvents ProcessListener = EventClass as IDebuggerProcessEvents;
if (ProcessListener != null) ProcessEvents.Add(ProcessListener);

View File

@ -5,12 +5,11 @@ using System;
namespace CxbxDebugger
{
public interface IDebuggerSessionEvents
public interface IDebuggerGeneralEvents
{
void OnDebugStart();
void OnDebugEnd();
void OnDebugTitleLoaded(string Title);
void OnDebugTargetChanged(string CommandLine);
}
public interface IDebuggerProcessEvents

View File

@ -9,20 +9,15 @@ namespace CxbxDebugger
{
public enum ReportType : uint
{
HLECACHE_FILE = 0x1000,
HLECACHE_FILE = 0x00deed00,
KERNEL_PATCH = 0x00deed01,
FILE_OPENED = 0x00deed02,
FILE_READ = 0x00deed03,
FILE_CLOSED = 0x00deed04,
DEBUGGER_INIT = 0x00deed05,
FILE_WRITE = 0x00deed06,
KERNEL_PATCH = 0x2000,
FILE_OPENED = 0x3000,
FILE_READ = 0x3001,
FILE_WRITE = 0x3002,
FILE_CLOSED = 0x3003,
DEBUGGER_INIT = 0x4000,
DEBUGGER_NEW_TARGET = 0x4001,
OVERRIDE_EXCEPTION = 0x5000,
OVERRIDE_EXCEPTION = 0x00ceed01,
// Exception code from https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
MS_VC_EXCEPTION = 0x406D1388,
@ -34,38 +29,22 @@ namespace CxbxDebugger
WCHAR,
};
public class DataProcessor
{
uint[] SourceData;
uint SourceIndex;
public DataProcessor(uint[] Data)
{
SourceData = Data;
SourceIndex = 0;
}
public uint Pop()
{
return SourceData[SourceIndex++];
}
}
public class HLECache
{
public string FileName { get; set; }
}
public static HLECache GetHLECacheReport(DebuggerThread Context, DataProcessor Data)
public static HLECache GetHLECacheReport(DebuggerThread Context, uint[] Data)
{
HLECache Report = new HLECache();
var Type = (StringType)Data.Pop();
StringType Type = (StringType)Data[0];
if (Type != StringType.CHAR)
throw new Exception("GetHLECacheReport expects a string message");
var Length = Data.Pop(); ;
var MessagePtr = new IntPtr(Data.Pop());
uint Length = Data[1];
IntPtr MessagePtr = new IntPtr(Data[2]);
Report.FileName = Context.OwningProcess.ReadString(MessagePtr, Length);
@ -78,19 +57,20 @@ namespace CxbxDebugger
public IntPtr Address { get; set; }
}
public static KernelPatch GetKernelPatchReport(DebuggerThread Context, DataProcessor Data)
public static KernelPatch GetKernelPatchReport(DebuggerThread Context, uint[] Data)
{
KernelPatch Report = new KernelPatch();
var Type = (StringType)Data.Pop();
StringType Type = (StringType)Data[0];
if (Type != StringType.CHAR)
throw new Exception("GetKernelPatchReport expects a string message");
var Length = Data.Pop();
var MessagePtr = new IntPtr(Data.Pop());
uint Length = Data[1];
IntPtr MessagePtr = new IntPtr(Data[2]);
Report.Name = Context.OwningProcess.ReadString(MessagePtr, Length);
Report.Address = new IntPtr(Data.Pop());
Report.Address = new IntPtr(Data[3]);
return Report;
}
@ -102,21 +82,23 @@ namespace CxbxDebugger
public bool Succeeded { get; set; }
}
public static FileOpened GetFileOpenedReport(DebuggerThread Context, DataProcessor Data)
public static FileOpened GetFileOpenedReport(DebuggerThread Context, uint[] Data)
{
FileOpened Report = new FileOpened();
Report.Handle = new IntPtr(Data.Pop());
Report.Handle = new IntPtr(Data[0]);
StringType Type = (StringType)Data[1];
var Type = (StringType)Data.Pop();
if (Type != StringType.WCHAR)
throw new Exception("GetFileOpenedReport expects a widestring message");
var Length = Data.Pop();
var MessagePtr = new IntPtr(Data.Pop());
uint Length = Data[2];
IntPtr MessagePtr = new IntPtr(Data[3]);
Report.FileName = Context.OwningProcess.ReadWString(MessagePtr, Length);
Report.Succeeded = Data.Pop() != 0;
Report.Succeeded = Data[4] != 0;
return Report;
}
@ -128,13 +110,13 @@ namespace CxbxDebugger
public uint Offset { get; set; }
}
public static FileRead GetFileReadReport(DebuggerThread Context, DataProcessor Data)
public static FileRead GetFileReadReport(DebuggerThread Context, uint[] Data)
{
FileRead Report = new FileRead();
Report.Handle = new IntPtr(Data.Pop());
Report.Length = Data.Pop();
Report.Offset = Data.Pop();
Report.Handle = new IntPtr(Data[0]);
Report.Length = Data[1];
Report.Offset = Data[2];
return Report;
}
@ -146,13 +128,13 @@ namespace CxbxDebugger
public uint Offset { get; set; }
}
public static FileWrite GetFileWriteReport(DebuggerThread Context, DataProcessor Data)
public static FileWrite GetFileWriteReport(DebuggerThread Context, uint[] Data)
{
FileWrite Report = new FileWrite();
Report.Handle = new IntPtr(Data.Pop());
Report.Length = Data.Pop();
Report.Offset = Data.Pop();
Report.Handle = new IntPtr(Data[0]);
Report.Length = Data[1];
Report.Offset = Data[2];
return Report;
}
@ -162,20 +144,18 @@ namespace CxbxDebugger
public IntPtr Handle { get; set; }
}
public static FileClosed GetFileClosedReport(DebuggerThread Context, DataProcessor Data)
public static FileClosed GetFileClosedReport(DebuggerThread Context, uint[] Data)
{
// TODO: Restructure this library
uint InvalidHandle = (uint)VsChromium.Core.Win32.Handles.NativeMethods.INVALID_HANDLE_VALUE;
var Handle = Data.Pop();
// Skip invalid file handles
if (Handle == InvalidHandle)
if (Data[0] == InvalidHandle)
return null;
FileClosed Report = new FileClosed();
Report.Handle = new IntPtr(Handle);
Report.Handle = new IntPtr(Data[0]);
return Report;
}
@ -189,78 +169,59 @@ namespace CxbxDebugger
public IntPtr ParameterBase { get; set; }
}
public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, DataProcessor Data)
public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, uint[] Data)
{
ExceptionHandledQuery Query = new ExceptionHandledQuery();
Query.ReponseAddr = new IntPtr(Data.Pop());
Query.ExceptionAddress = Data.Pop();
Query.ExceptionCode = Data.Pop();
Query.ParameterCount = Data.Pop();
Query.ParameterBase = new IntPtr(Data.Pop());
Query.ReponseAddr = new IntPtr(Data[0]);
Query.ExceptionAddress = Data[1];
Query.ExceptionCode = Data[2];
Query.ParameterCount = Data[3];
Query.ParameterBase = new IntPtr(Data[4]);
return Query;
}
public class DebuggerInit
{
public uint TitleID { get; set; }
public string Title { get; set; }
}
public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, DataProcessor Data)
public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, uint[] Data)
{
DebuggerInit Report = new DebuggerInit();
StringType Type = (StringType)Data.Pop();
Report.TitleID = Data[0];
StringType Type = (StringType)Data[1];
if (Type != StringType.CHAR)
throw new Exception("GetDebuggerInitReport expects a string message");
uint Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data.Pop());
uint Length = Data[2];
IntPtr MessagePtr = new IntPtr(Data[3]);
Report.Title = Context.OwningProcess.ReadString(MessagePtr, Length);
return Report;
}
public class DebuggerNewTarget
{
public string CommandLine { get; set; }
}
public static DebuggerNewTarget GetDebuggerNewTargetReport(DebuggerThread Context, DataProcessor Data)
{
var Report = new DebuggerNewTarget();
StringType Type = (StringType)Data.Pop();
if (Type != StringType.CHAR)
throw new Exception("GetDebuggerInitReport expects a string message");
uint Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data.Pop());
Report.CommandLine = Context.OwningProcess.ReadString(MessagePtr, Length);
return Report;
}
public class MSVCThreadName
{
public string Name { get; set; }
public uint ThreadId { get; set; }
}
public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, DataProcessor Data)
public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, uint[] Data)
{
var Type = Data.Pop();
uint Type = Data[0];
if (Type != 0x1000)
return null;
string ReportName = "";
IntPtr MessagePtr = new IntPtr(Data.Pop());
IntPtr MessagePtr = new IntPtr(Data[1]);
if (MessagePtr != IntPtr.Zero)
{
ReportName = Context.OwningProcess.ReadString(MessagePtr);
@ -269,7 +230,7 @@ namespace CxbxDebugger
MSVCThreadName Report = new MSVCThreadName();
Report.Name = ReportName;
Report.ThreadId = Data.Pop();
Report.ThreadId = Data[2];
return Report;
}

View File

@ -114,12 +114,6 @@ namespace CxbxDebugger
if (ebp == 0 || ReturnAddr == ebp)
break;
if ((ReturnAddr & 0x80000000) != 0)
break;
if ((ebp & 0x80000000) != 0)
break;
CallstackCache.AddFrame(new DebuggerStackFrame(new IntPtr(ReturnAddr), new IntPtr(ebp)));
}
while (CallstackCache.CanCollect);

View File

@ -1,6 +1,6 @@
namespace CxbxDebugger
{
partial class CxbxDebuggerInstance
partial class Form1
{
/// <summary>
/// Required designer variable.
@ -28,21 +28,22 @@
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CxbxDebuggerInstance));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.lbConsole = new System.Windows.Forms.ListBox();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.btnStart = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.btnSuspend = new System.Windows.Forms.ToolStripButton();
this.btnResume = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
this.cbThreads = new System.Windows.Forms.ToolStripComboBox();
this.toolStripLabel2 = new System.Windows.Forms.ToolStripLabel();
this.cbFrames = new System.Windows.Forms.ToolStripComboBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.statusBar = new System.Windows.Forms.StatusStrip();
this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.tabContainer = new System.Windows.Forms.TabControl();
this.tabSummary = new System.Windows.Forms.TabPage();
this.linkLabel3 = new System.Windows.Forms.LinkLabel();
this.linkLabel2 = new System.Windows.Forms.LinkLabel();
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
this.label9 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.tabDisassembly = new System.Windows.Forms.TabPage();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.btnToMemory = new System.Windows.Forms.Button();
@ -51,6 +52,7 @@
this.btnGo = new System.Windows.Forms.Button();
this.label6 = new System.Windows.Forms.Label();
this.cbDisAddr = new System.Windows.Forms.ComboBox();
this.txDisassembly = new CxbxDebugger.RicherTextBox();
this.tabBreakpoints = new System.Windows.Forms.TabPage();
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
this.groupBox4 = new System.Windows.Forms.GroupBox();
@ -110,11 +112,10 @@
this.lbDebug = new System.Windows.Forms.ListBox();
this.diagSaveMemory = new System.Windows.Forms.SaveFileDialog();
this.diagBrowseCT = new System.Windows.Forms.OpenFileDialog();
this.txDisassembly = new CxbxDebugger.RicherTextBox();
this.toolStrip1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.statusBar.SuspendLayout();
this.tabContainer.SuspendLayout();
this.tabSummary.SuspendLayout();
this.tabDisassembly.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
this.splitContainer2.Panel1.SuspendLayout();
@ -157,33 +158,73 @@
//
this.lbConsole.Dock = System.Windows.Forms.DockStyle.Fill;
this.lbConsole.FormattingEnabled = true;
this.lbConsole.Location = new System.Drawing.Point(3, 271);
this.lbConsole.Location = new System.Drawing.Point(3, 231);
this.lbConsole.Name = "lbConsole";
this.lbConsole.ScrollAlwaysVisible = true;
this.lbConsole.Size = new System.Drawing.Size(728, 62);
this.lbConsole.Size = new System.Drawing.Size(728, 51);
this.lbConsole.TabIndex = 2;
//
// toolStrip1
//
this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(24, 24);
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.btnStart,
this.toolStripSeparator1,
this.btnSuspend,
this.btnResume,
this.toolStripSeparator2,
this.toolStripLabel1,
this.cbThreads,
this.toolStripLabel2,
this.cbFrames});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Padding = new System.Windows.Forms.Padding(0, 0, 2, 0);
this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
this.toolStrip1.Size = new System.Drawing.Size(734, 25);
this.toolStrip1.TabIndex = 7;
this.toolStrip1.Text = "toolStrip1";
//
// btnStart
//
this.btnStart.Image = global::CxbxDebugger.Properties.Resources.run;
this.btnStart.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(51, 22);
this.btnStart.Text = "Start";
this.btnStart.Click += new System.EventHandler(this.toolStripButton1_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// btnSuspend
//
this.btnSuspend.Image = global::CxbxDebugger.Properties.Resources.pause;
this.btnSuspend.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnSuspend.Name = "btnSuspend";
this.btnSuspend.Size = new System.Drawing.Size(72, 22);
this.btnSuspend.Text = "Suspend";
this.btnSuspend.Click += new System.EventHandler(this.toolStripButton2_Click);
//
// btnResume
//
this.btnResume.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.btnResume.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnResume.Name = "btnResume";
this.btnResume.Size = new System.Drawing.Size(53, 22);
this.btnResume.Text = "Resume";
this.btnResume.Click += new System.EventHandler(this.toolStripButton3_Click);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25);
//
// toolStripLabel1
//
this.toolStripLabel1.Name = "toolStripLabel1";
this.toolStripLabel1.Size = new System.Drawing.Size(46, 22);
this.toolStripLabel1.Size = new System.Drawing.Size(47, 22);
this.toolStripLabel1.Text = "Thread:";
//
// cbThreads
@ -203,28 +244,45 @@
//
this.cbFrames.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbFrames.Name = "cbFrames";
this.cbFrames.Size = new System.Drawing.Size(135, 25);
this.cbFrames.Size = new System.Drawing.Size(200, 25);
this.cbFrames.SelectedIndexChanged += new System.EventHandler(this.cbFrames_SelectedIndexChanged);
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 1;
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Controls.Add(this.statusBar, 0, 2);
this.tableLayoutPanel3.Controls.Add(this.tabContainer, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.lbConsole, 0, 1);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 25);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 2;
this.tableLayoutPanel3.RowCount = 3;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 80F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(734, 336);
this.tableLayoutPanel3.Size = new System.Drawing.Size(734, 306);
this.tableLayoutPanel3.TabIndex = 9;
//
// statusBar
//
this.statusBar.Dock = System.Windows.Forms.DockStyle.Fill;
this.statusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.lblStatus});
this.statusBar.Location = new System.Drawing.Point(0, 285);
this.statusBar.Name = "statusBar";
this.statusBar.Size = new System.Drawing.Size(734, 21);
this.statusBar.TabIndex = 10;
this.statusBar.Text = "statusStrip1";
//
// lblStatus
//
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(39, 16);
this.lblStatus.Text = "Ready";
//
// tabContainer
//
this.tabContainer.Controls.Add(this.tabSummary);
this.tabContainer.Controls.Add(this.tabDisassembly);
this.tabContainer.Controls.Add(this.tabBreakpoints);
this.tabContainer.Controls.Add(this.tabWatch);
@ -236,82 +294,16 @@
this.tabContainer.Multiline = true;
this.tabContainer.Name = "tabContainer";
this.tabContainer.SelectedIndex = 0;
this.tabContainer.Size = new System.Drawing.Size(728, 262);
this.tabContainer.Size = new System.Drawing.Size(728, 222);
this.tabContainer.TabIndex = 3;
//
// tabSummary
//
this.tabSummary.Controls.Add(this.linkLabel3);
this.tabSummary.Controls.Add(this.linkLabel2);
this.tabSummary.Controls.Add(this.linkLabel1);
this.tabSummary.Controls.Add(this.label9);
this.tabSummary.Controls.Add(this.label7);
this.tabSummary.Location = new System.Drawing.Point(4, 22);
this.tabSummary.Name = "tabSummary";
this.tabSummary.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabSummary.Size = new System.Drawing.Size(654, 318);
this.tabSummary.TabIndex = 6;
this.tabSummary.Text = "Summary";
this.tabSummary.UseVisualStyleBackColor = true;
//
// linkLabel3
//
this.linkLabel3.AutoSize = true;
this.linkLabel3.Location = new System.Drawing.Point(11, 112);
this.linkLabel3.Name = "linkLabel3";
this.linkLabel3.Size = new System.Drawing.Size(89, 13);
this.linkLabel3.TabIndex = 5;
this.linkLabel3.TabStop = true;
this.linkLabel3.Text = "View disassembly";
this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel3_LinkClicked);
//
// linkLabel2
//
this.linkLabel2.AutoSize = true;
this.linkLabel2.Location = new System.Drawing.Point(11, 85);
this.linkLabel2.Name = "linkLabel2";
this.linkLabel2.Size = new System.Drawing.Size(69, 13);
this.linkLabel2.TabIndex = 4;
this.linkLabel2.TabStop = true;
this.linkLabel2.Text = "View memory";
this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked);
//
// linkLabel1
//
this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(11, 60);
this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(95, 13);
this.linkLabel1.TabIndex = 3;
this.linkLabel1.TabStop = true;
this.linkLabel1.Text = "View file resources";
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(9, 35);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(268, 13);
this.label9.TabIndex = 1;
this.label9.Text = "To get started, select Debug->Start from the main menu";
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(11, 6);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(155, 13);
this.label7.TabIndex = 0;
this.label7.Text = "Welcome to the cxbx-debugger";
//
// tabDisassembly
//
this.tabDisassembly.Controls.Add(this.splitContainer2);
this.tabDisassembly.Location = new System.Drawing.Point(4, 22);
this.tabDisassembly.Name = "tabDisassembly";
this.tabDisassembly.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabDisassembly.Size = new System.Drawing.Size(654, 318);
this.tabDisassembly.Padding = new System.Windows.Forms.Padding(3);
this.tabDisassembly.Size = new System.Drawing.Size(720, 196);
this.tabDisassembly.TabIndex = 0;
this.tabDisassembly.Text = "Disassembly";
this.tabDisassembly.UseVisualStyleBackColor = true;
@ -337,14 +329,14 @@
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.txDisassembly);
this.splitContainer2.Size = new System.Drawing.Size(648, 312);
this.splitContainer2.Size = new System.Drawing.Size(714, 190);
this.splitContainer2.SplitterDistance = 34;
this.splitContainer2.TabIndex = 2;
//
// btnToMemory
//
this.btnToMemory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnToMemory.Location = new System.Drawing.Point(386, 3);
this.btnToMemory.Location = new System.Drawing.Point(452, 3);
this.btnToMemory.Name = "btnToMemory";
this.btnToMemory.Size = new System.Drawing.Size(119, 23);
this.btnToMemory.TabIndex = 4;
@ -355,7 +347,7 @@
// btnNext
//
this.btnNext.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnNext.Location = new System.Drawing.Point(581, 3);
this.btnNext.Location = new System.Drawing.Point(647, 3);
this.btnNext.Name = "btnNext";
this.btnNext.Size = new System.Drawing.Size(64, 23);
this.btnNext.TabIndex = 3;
@ -366,7 +358,7 @@
// btnPrev
//
this.btnPrev.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnPrev.Location = new System.Drawing.Point(512, 3);
this.btnPrev.Location = new System.Drawing.Point(577, 3);
this.btnPrev.Name = "btnPrev";
this.btnPrev.Size = new System.Drawing.Size(64, 23);
this.btnPrev.TabIndex = 2;
@ -377,7 +369,7 @@
// btnGo
//
this.btnGo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnGo.Location = new System.Drawing.Point(261, 3);
this.btnGo.Location = new System.Drawing.Point(327, 3);
this.btnGo.Name = "btnGo";
this.btnGo.Size = new System.Drawing.Size(119, 23);
this.btnGo.TabIndex = 1;
@ -401,18 +393,33 @@
this.cbDisAddr.FormattingEnabled = true;
this.cbDisAddr.Location = new System.Drawing.Point(132, 5);
this.cbDisAddr.Name = "cbDisAddr";
this.cbDisAddr.Size = new System.Drawing.Size(124, 21);
this.cbDisAddr.Size = new System.Drawing.Size(189, 21);
this.cbDisAddr.TabIndex = 0;
this.cbDisAddr.SelectedIndexChanged += new System.EventHandler(this.cbDisAddr_SelectedIndexChanged);
this.cbDisAddr.KeyDown += new System.Windows.Forms.KeyEventHandler(this.comboBox1_KeyDown);
//
// txDisassembly
//
this.txDisassembly.BackColor = System.Drawing.SystemColors.Window;
this.txDisassembly.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txDisassembly.Cursor = System.Windows.Forms.Cursors.Default;
this.txDisassembly.Dock = System.Windows.Forms.DockStyle.Fill;
this.txDisassembly.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txDisassembly.Location = new System.Drawing.Point(0, 0);
this.txDisassembly.Name = "txDisassembly";
this.txDisassembly.ReadOnly = true;
this.txDisassembly.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedVertical;
this.txDisassembly.Size = new System.Drawing.Size(714, 152);
this.txDisassembly.TabIndex = 1;
this.txDisassembly.Text = "";
//
// tabBreakpoints
//
this.tabBreakpoints.Controls.Add(this.splitContainer3);
this.tabBreakpoints.Location = new System.Drawing.Point(4, 22);
this.tabBreakpoints.Name = "tabBreakpoints";
this.tabBreakpoints.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabBreakpoints.Size = new System.Drawing.Size(654, 318);
this.tabBreakpoints.Padding = new System.Windows.Forms.Padding(3);
this.tabBreakpoints.Size = new System.Drawing.Size(720, 196);
this.tabBreakpoints.TabIndex = 1;
this.tabBreakpoints.Text = "Breakpoints";
this.tabBreakpoints.UseVisualStyleBackColor = true;
@ -431,8 +438,8 @@
// splitContainer3.Panel2
//
this.splitContainer3.Panel2.Controls.Add(this.clbBreakpoints);
this.splitContainer3.Size = new System.Drawing.Size(648, 312);
this.splitContainer3.SplitterDistance = 214;
this.splitContainer3.Size = new System.Drawing.Size(714, 190);
this.splitContainer3.SplitterDistance = 237;
this.splitContainer3.TabIndex = 5;
//
// groupBox4
@ -444,7 +451,7 @@
this.groupBox4.Controls.Add(this.cbBreakpointCxbx);
this.groupBox4.Location = new System.Drawing.Point(2, 112);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(210, 196);
this.groupBox4.Size = new System.Drawing.Size(233, 75);
this.groupBox4.TabIndex = 5;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Interrupts";
@ -482,7 +489,7 @@
this.groupBox1.Controls.Add(this.tbFilter);
this.groupBox1.Location = new System.Drawing.Point(0, 0);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(211, 106);
this.groupBox1.Size = new System.Drawing.Size(234, 106);
this.groupBox1.TabIndex = 4;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "File Watch";
@ -495,7 +502,7 @@
this.cbAction.FormattingEnabled = true;
this.cbAction.Location = new System.Drawing.Point(89, 45);
this.cbAction.Name = "cbAction";
this.cbAction.Size = new System.Drawing.Size(115, 21);
this.cbAction.Size = new System.Drawing.Size(139, 21);
this.cbAction.TabIndex = 6;
//
// label5
@ -522,7 +529,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.btnAddFileBp.Location = new System.Drawing.Point(89, 72);
this.btnAddFileBp.Name = "btnAddFileBp";
this.btnAddFileBp.Size = new System.Drawing.Size(115, 23);
this.btnAddFileBp.Size = new System.Drawing.Size(139, 23);
this.btnAddFileBp.TabIndex = 4;
this.btnAddFileBp.Text = "Add";
this.btnAddFileBp.UseVisualStyleBackColor = true;
@ -534,7 +541,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.tbFilter.Location = new System.Drawing.Point(89, 19);
this.tbFilter.Name = "tbFilter";
this.tbFilter.Size = new System.Drawing.Size(115, 20);
this.tbFilter.Size = new System.Drawing.Size(139, 20);
this.tbFilter.TabIndex = 2;
//
// clbBreakpoints
@ -543,7 +550,7 @@
this.clbBreakpoints.FormattingEnabled = true;
this.clbBreakpoints.Location = new System.Drawing.Point(0, 0);
this.clbBreakpoints.Name = "clbBreakpoints";
this.clbBreakpoints.Size = new System.Drawing.Size(430, 312);
this.clbBreakpoints.Size = new System.Drawing.Size(473, 190);
this.clbBreakpoints.TabIndex = 0;
this.clbBreakpoints.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.clbBreakpoints_ItemCheck);
this.clbBreakpoints.KeyDown += new System.Windows.Forms.KeyEventHandler(this.clbBreakpoints_KeyDown);
@ -553,8 +560,8 @@
this.tabWatch.Controls.Add(this.splitContainer1);
this.tabWatch.Location = new System.Drawing.Point(4, 22);
this.tabWatch.Name = "tabWatch";
this.tabWatch.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabWatch.Size = new System.Drawing.Size(654, 318);
this.tabWatch.Padding = new System.Windows.Forms.Padding(3);
this.tabWatch.Size = new System.Drawing.Size(720, 196);
this.tabWatch.TabIndex = 2;
this.tabWatch.Text = "File Watcher";
this.tabWatch.UseVisualStyleBackColor = true;
@ -572,8 +579,8 @@
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.lbOpenedFiles);
this.splitContainer1.Size = new System.Drawing.Size(648, 312);
this.splitContainer1.SplitterDistance = 453;
this.splitContainer1.Size = new System.Drawing.Size(714, 190);
this.splitContainer1.SplitterDistance = 501;
this.splitContainer1.TabIndex = 3;
//
// lvFileDetails
@ -588,7 +595,7 @@
this.lvFileDetails.Location = new System.Drawing.Point(0, 0);
this.lvFileDetails.MultiSelect = false;
this.lvFileDetails.Name = "lvFileDetails";
this.lvFileDetails.Size = new System.Drawing.Size(453, 312);
this.lvFileDetails.Size = new System.Drawing.Size(501, 190);
this.lvFileDetails.TabIndex = 2;
this.lvFileDetails.UseCompatibleStateImageBehavior = false;
this.lvFileDetails.View = System.Windows.Forms.View.Details;
@ -614,7 +621,7 @@
this.lbOpenedFiles.FormattingEnabled = true;
this.lbOpenedFiles.Location = new System.Drawing.Point(0, 0);
this.lbOpenedFiles.Name = "lbOpenedFiles";
this.lbOpenedFiles.Size = new System.Drawing.Size(191, 312);
this.lbOpenedFiles.Size = new System.Drawing.Size(209, 190);
this.lbOpenedFiles.TabIndex = 0;
//
// tabMemory
@ -622,8 +629,8 @@
this.tabMemory.Controls.Add(this.splitContainer4);
this.tabMemory.Location = new System.Drawing.Point(4, 22);
this.tabMemory.Name = "tabMemory";
this.tabMemory.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabMemory.Size = new System.Drawing.Size(720, 236);
this.tabMemory.Padding = new System.Windows.Forms.Padding(3);
this.tabMemory.Size = new System.Drawing.Size(720, 196);
this.tabMemory.TabIndex = 4;
this.tabMemory.Text = "Memory Viewer";
this.tabMemory.UseVisualStyleBackColor = true;
@ -641,8 +648,8 @@
// splitContainer4.Panel2
//
this.splitContainer4.Panel2.Controls.Add(this.groupBox2);
this.splitContainer4.Size = new System.Drawing.Size(714, 230);
this.splitContainer4.SplitterDistance = 375;
this.splitContainer4.Size = new System.Drawing.Size(714, 190);
this.splitContainer4.SplitterDistance = 376;
this.splitContainer4.TabIndex = 7;
//
// txMemoryDump
@ -656,7 +663,7 @@
this.txMemoryDump.Name = "txMemoryDump";
this.txMemoryDump.ReadOnly = true;
this.txMemoryDump.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txMemoryDump.Size = new System.Drawing.Size(375, 230);
this.txMemoryDump.Size = new System.Drawing.Size(376, 190);
this.txMemoryDump.TabIndex = 0;
//
// groupBox2
@ -674,7 +681,7 @@
this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupBox2.Location = new System.Drawing.Point(0, 0);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(335, 230);
this.groupBox2.Size = new System.Drawing.Size(334, 190);
this.groupBox2.TabIndex = 8;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "View or Dump Memory";
@ -683,9 +690,9 @@
//
this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBox2.Location = new System.Drawing.Point(183, 129);
this.textBox2.Location = new System.Drawing.Point(213, 129);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(146, 20);
this.textBox2.Size = new System.Drawing.Size(115, 20);
this.textBox2.TabIndex = 10;
//
// label8
@ -699,11 +706,13 @@
//
// cbDataFormat
//
this.cbDataFormat.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cbDataFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbDataFormat.FormattingEnabled = true;
this.cbDataFormat.Location = new System.Drawing.Point(88, 130);
this.cbDataFormat.Name = "cbDataFormat";
this.cbDataFormat.Size = new System.Drawing.Size(89, 21);
this.cbDataFormat.Size = new System.Drawing.Size(119, 21);
this.cbDataFormat.TabIndex = 8;
this.cbDataFormat.SelectionChangeCommitted += new System.EventHandler(this.cbDataFormat_SelectionChangeCommitted);
//
@ -713,7 +722,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.btnAddWatch.Location = new System.Drawing.Point(88, 157);
this.btnAddWatch.Name = "btnAddWatch";
this.btnAddWatch.Size = new System.Drawing.Size(241, 23);
this.btnAddWatch.Size = new System.Drawing.Size(240, 23);
this.btnAddWatch.TabIndex = 7;
this.btnAddWatch.Text = "Add to Editor...";
this.btnAddWatch.UseVisualStyleBackColor = true;
@ -734,7 +743,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.btnDumpMemory.Location = new System.Drawing.Point(88, 100);
this.btnDumpMemory.Name = "btnDumpMemory";
this.btnDumpMemory.Size = new System.Drawing.Size(241, 23);
this.btnDumpMemory.Size = new System.Drawing.Size(240, 23);
this.btnDumpMemory.TabIndex = 6;
this.btnDumpMemory.Text = "Dump Memory to File...";
this.btnDumpMemory.UseVisualStyleBackColor = true;
@ -746,7 +755,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.txAddress.Location = new System.Drawing.Point(88, 18);
this.txAddress.Name = "txAddress";
this.txAddress.Size = new System.Drawing.Size(241, 20);
this.txAddress.Size = new System.Drawing.Size(240, 20);
this.txAddress.TabIndex = 1;
//
// label2
@ -764,7 +773,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.btnReadMemory.Location = new System.Drawing.Point(88, 71);
this.btnReadMemory.Name = "btnReadMemory";
this.btnReadMemory.Size = new System.Drawing.Size(241, 23);
this.btnReadMemory.Size = new System.Drawing.Size(240, 23);
this.btnReadMemory.TabIndex = 2;
this.btnReadMemory.Text = "Read Memory";
this.btnReadMemory.UseVisualStyleBackColor = true;
@ -776,7 +785,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.txSize.Location = new System.Drawing.Point(88, 45);
this.txSize.Name = "txSize";
this.txSize.Size = new System.Drawing.Size(241, 20);
this.txSize.Size = new System.Drawing.Size(240, 20);
this.txSize.TabIndex = 3;
this.txSize.Text = "32";
//
@ -785,8 +794,8 @@
this.tabTweaks.Controls.Add(this.tabCEContainer);
this.tabTweaks.Location = new System.Drawing.Point(4, 22);
this.tabTweaks.Name = "tabTweaks";
this.tabTweaks.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabTweaks.Size = new System.Drawing.Size(654, 318);
this.tabTweaks.Padding = new System.Windows.Forms.Padding(3);
this.tabTweaks.Size = new System.Drawing.Size(720, 196);
this.tabTweaks.TabIndex = 5;
this.tabTweaks.Text = "Memory Editor";
this.tabTweaks.UseVisualStyleBackColor = true;
@ -799,7 +808,7 @@
this.tabCEContainer.Location = new System.Drawing.Point(3, 3);
this.tabCEContainer.Name = "tabCEContainer";
this.tabCEContainer.SelectedIndex = 0;
this.tabCEContainer.Size = new System.Drawing.Size(648, 312);
this.tabCEContainer.Size = new System.Drawing.Size(714, 190);
this.tabCEContainer.TabIndex = 5;
//
// tabSubData
@ -807,8 +816,8 @@
this.tabSubData.Controls.Add(this.splitContainer6);
this.tabSubData.Location = new System.Drawing.Point(4, 22);
this.tabSubData.Name = "tabSubData";
this.tabSubData.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabSubData.Size = new System.Drawing.Size(640, 286);
this.tabSubData.Padding = new System.Windows.Forms.Padding(3);
this.tabSubData.Size = new System.Drawing.Size(706, 164);
this.tabSubData.TabIndex = 0;
this.tabSubData.Text = "Edit Data";
this.tabSubData.UseVisualStyleBackColor = true;
@ -830,8 +839,8 @@
// splitContainer6.Panel2
//
this.splitContainer6.Panel2.Controls.Add(this.lvCEMemory);
this.splitContainer6.Size = new System.Drawing.Size(634, 280);
this.splitContainer6.SplitterDistance = 57;
this.splitContainer6.Size = new System.Drawing.Size(700, 158);
this.splitContainer6.SplitterDistance = 34;
this.splitContainer6.TabIndex = 2;
//
// btnRefresh
@ -857,7 +866,7 @@
// btnApply
//
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnApply.Location = new System.Drawing.Point(508, 3);
this.btnApply.Location = new System.Drawing.Point(574, 3);
this.btnApply.Name = "btnApply";
this.btnApply.Size = new System.Drawing.Size(123, 23);
this.btnApply.TabIndex = 4;
@ -871,7 +880,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.txNewValue.Location = new System.Drawing.Point(261, 5);
this.txNewValue.Name = "txNewValue";
this.txNewValue.Size = new System.Drawing.Size(240, 20);
this.txNewValue.Size = new System.Drawing.Size(307, 20);
this.txNewValue.TabIndex = 2;
//
// lvCEMemory
@ -887,7 +896,7 @@
this.lvCEMemory.Location = new System.Drawing.Point(0, 0);
this.lvCEMemory.MultiSelect = false;
this.lvCEMemory.Name = "lvCEMemory";
this.lvCEMemory.Size = new System.Drawing.Size(634, 219);
this.lvCEMemory.Size = new System.Drawing.Size(700, 120);
this.lvCEMemory.TabIndex = 1;
this.lvCEMemory.UseCompatibleStateImageBehavior = false;
this.lvCEMemory.View = System.Windows.Forms.View.Details;
@ -917,8 +926,8 @@
this.tabSubAssembly.Controls.Add(this.lvCEAssembly);
this.tabSubAssembly.Location = new System.Drawing.Point(4, 22);
this.tabSubAssembly.Name = "tabSubAssembly";
this.tabSubAssembly.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabSubAssembly.Size = new System.Drawing.Size(640, 286);
this.tabSubAssembly.Padding = new System.Windows.Forms.Padding(3);
this.tabSubAssembly.Size = new System.Drawing.Size(706, 164);
this.tabSubAssembly.TabIndex = 1;
this.tabSubAssembly.Text = "Edit Assembly";
this.tabSubAssembly.UseVisualStyleBackColor = true;
@ -936,7 +945,7 @@
this.lvCEAssembly.Location = new System.Drawing.Point(3, 3);
this.lvCEAssembly.MultiSelect = false;
this.lvCEAssembly.Name = "lvCEAssembly";
this.lvCEAssembly.Size = new System.Drawing.Size(635, 280);
this.lvCEAssembly.Size = new System.Drawing.Size(700, 158);
this.lvCEAssembly.TabIndex = 4;
this.lvCEAssembly.UseCompatibleStateImageBehavior = false;
this.lvCEAssembly.View = System.Windows.Forms.View.Details;
@ -966,8 +975,8 @@
this.tabOutput.Controls.Add(this.splitContainer5);
this.tabOutput.Location = new System.Drawing.Point(4, 22);
this.tabOutput.Name = "tabOutput";
this.tabOutput.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
this.tabOutput.Size = new System.Drawing.Size(654, 318);
this.tabOutput.Padding = new System.Windows.Forms.Padding(3);
this.tabOutput.Size = new System.Drawing.Size(720, 196);
this.tabOutput.TabIndex = 3;
this.tabOutput.Text = "Debug Output";
this.tabOutput.UseVisualStyleBackColor = true;
@ -989,7 +998,7 @@
// splitContainer5.Panel2
//
this.splitContainer5.Panel2.Controls.Add(this.lbDebug);
this.splitContainer5.Size = new System.Drawing.Size(648, 312);
this.splitContainer5.Size = new System.Drawing.Size(714, 190);
this.splitContainer5.SplitterDistance = 26;
this.splitContainer5.TabIndex = 6;
//
@ -1000,7 +1009,7 @@
this.txFilter.Enabled = false;
this.txFilter.Location = new System.Drawing.Point(41, 3);
this.txFilter.Name = "txFilter";
this.txFilter.Size = new System.Drawing.Size(604, 20);
this.txFilter.Size = new System.Drawing.Size(670, 20);
this.txFilter.TabIndex = 4;
//
// label3
@ -1020,7 +1029,7 @@
this.lbDebug.Location = new System.Drawing.Point(0, 0);
this.lbDebug.Name = "lbDebug";
this.lbDebug.ScrollAlwaysVisible = true;
this.lbDebug.Size = new System.Drawing.Size(648, 282);
this.lbDebug.Size = new System.Drawing.Size(714, 160);
this.lbDebug.TabIndex = 3;
//
// diagSaveMemory
@ -1033,40 +1042,24 @@
this.diagBrowseCT.Filter = "Cheat Engine Tables (*.CT)|*.ct";
this.diagBrowseCT.Title = "Load cheat table";
//
// txDisassembly
// Form1
//
this.txDisassembly.BackColor = System.Drawing.SystemColors.Window;
this.txDisassembly.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.txDisassembly.Cursor = System.Windows.Forms.Cursors.Default;
this.txDisassembly.Dock = System.Windows.Forms.DockStyle.Fill;
this.txDisassembly.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txDisassembly.Location = new System.Drawing.Point(0, 0);
this.txDisassembly.Name = "txDisassembly";
this.txDisassembly.ReadOnly = true;
this.txDisassembly.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedVertical;
this.txDisassembly.Size = new System.Drawing.Size(648, 274);
this.txDisassembly.TabIndex = 1;
this.txDisassembly.Text = "";
//
// CxbxDebuggerInstance
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(734, 361);
this.ControlBox = false;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(734, 331);
this.Controls.Add(this.tableLayoutPanel3);
this.Controls.Add(this.toolStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimizeBox = false;
this.Name = "CxbxDebuggerInstance";
this.Text = "unnamed instance";
this.Name = "Form1";
this.Text = "Cxbx-Reloaded Debugger";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
this.statusBar.ResumeLayout(false);
this.statusBar.PerformLayout();
this.tabContainer.ResumeLayout(false);
this.tabSummary.ResumeLayout(false);
this.tabSummary.PerformLayout();
this.tabDisassembly.ResumeLayout(false);
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel1.PerformLayout();
@ -1118,6 +1111,11 @@
#endregion
private System.Windows.Forms.ListBox lbConsole;
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton btnStart;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripButton btnSuspend;
private System.Windows.Forms.ToolStripButton btnResume;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
private System.Windows.Forms.ToolStripComboBox cbThreads;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
private System.Windows.Forms.TabControl tabContainer;
@ -1137,6 +1135,8 @@
private System.Windows.Forms.TextBox txAddress;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TextBox tbFilter;
private System.Windows.Forms.StatusStrip statusBar;
private System.Windows.Forms.ToolStripStatusLabel lblStatus;
private RicherTextBox txDisassembly;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
@ -1192,11 +1192,6 @@
private System.Windows.Forms.Button btnLoadCT;
private System.Windows.Forms.Button btnRefresh;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.TabPage tabSummary;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.LinkLabel linkLabel3;
private System.Windows.Forms.LinkLabel linkLabel2;
private System.Windows.Forms.LinkLabel linkLabel1;
}
}

View File

@ -8,15 +8,15 @@ using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using cs_x86;
using System.Runtime.InteropServices;
namespace CxbxDebugger
{
public partial class CxbxDebuggerInstance : Form, IDebugWindow
public partial class Form1 : Form
{
Thread DebuggerWorkerThread;
Debugger DebuggerInst;
string[] StartupArgs;
string CachedTitle = "";
bool SuspendedOnBp = false;
DebuggerFormEvents DebugEvents;
@ -29,45 +29,29 @@ namespace CxbxDebugger
DebugOutputManager debugStrMan;
PatchManager patchMan;
IDebugContainerWindow DebugContainer
{
get
{
return MdiParent as IDebugContainerWindow;
}
}
DebugStateInfo StateInfo = new DebugStateInfo();
private void SetDebugState(DebugState State, string Detail = "")
{
DebugContainer.ReportStatus(this, State, Detail);
StateInfo.State = State;
StateInfo.Detail = Detail;
}
List<DebuggerMessages.FileOpened> FileHandles = new List<DebuggerMessages.FileOpened>();
public CxbxDebuggerInstance(Form Owner, string[] args)
public Form1()
{
InitializeComponent();
MdiParent = Owner;
// TODO: Cleanup arg handling
string[] args = Environment.GetCommandLineArgs();
#if !DEBUG
// Arguments are expected before the Form is created
if (args.Length < 2)
{
throw new Exception("Incorrect usage");
}
#endif
StartupArgs = args;
StartupArgs = new string[args.Length - 1];
Array.Copy(args, 1, StartupArgs, 0, args.Length - 1);
DebugEvents = new DebuggerFormEvents(this);
SetDebugState(DebugState.Unknown);
SetDebugProcessActive(false);
txDisassembly.InlineLinkClicked += OnDisassemblyNavigation;
@ -89,8 +73,6 @@ namespace CxbxDebugger
fileWatchMan = new FileWatchManager(clbBreakpoints);
debugStrMan = new DebugOutputManager(lbDebug);
patchMan = new PatchManager();
CreateDebuggerOnce();
}
private void OnDisassemblyNavigation(object sender, InlineLinkClickedEventArgs e)
@ -100,85 +82,38 @@ namespace CxbxDebugger
ShowDisassemblyAt(e.Link);
}
private void CreateDebuggerOnce()
private void StartDebugging()
{
if (DebuggerInst == null)
bool Create = false;
if (DebuggerWorkerThread == null)
{
// First launch
Create = true;
}
else if (DebuggerWorkerThread.ThreadState == ThreadState.Stopped)
{
// Further launches
Create = true;
}
if (Create)
{
// Create debugger instance
DebuggerInst = new Debugger(StartupArgs);
DebuggerInst.RegisterEventInterfaces(DebugEvents);
DebuggerInst.RegisterEventInterfaces(patchMan);
var TargetXbeName = ValidateXbeTargetName(DebuggerInst.TargetPath);
var TargetXbeValid = true;
if (string.IsNullOrEmpty(TargetXbeName))
{
TargetXbeName = "<unknown>";
TargetXbeValid = false;
}
if (InvokeRequired)
{
// Set form title based on this new process
Invoke(new MethodInvoker(delegate ()
{
Text = TargetXbeName;
}));
}
else
{
Text = TargetXbeName;
}
if (TargetXbeValid)
{
SetDebugState(DebugState.Idle, $"{TargetXbeName} is waiting to start");
}
}
}
private string ValidateXbeTargetName(string XbePath)
{
var XbeName = Path.GetFileName(XbePath);
if (File.Exists(XbePath))
{
return XbeName;
}
// Cxbx CLI will pass through the path as a list of parameters, "dir;name"
if (XbeName.StartsWith(";"))
{
var CleanedXbePath = XbePath.Remove(XbePath.Length - XbeName.Length, 1);
if (File.Exists(CleanedXbePath))
{
return XbeName.Substring(1);
}
}
return null;
}
private void StartDebugging()
{
if (GetSessionState() == SessionState.Inactive)
{
// Setup new debugger thread
DebuggerWorkerThread = new Thread(x =>
{
CreateDebuggerOnce();
if (DebuggerInst.Launch())
{
DebuggerInst.RunThreaded();
}
});
var ProcessName = Path.GetFileName(DebuggerInst.TargetPath);
DebuggerWorkerThread.Name = $"DebuggerFor_{ProcessName}";
DebuggerWorkerThread.Name = "CxbxDebugger";
DebuggerWorkerThread.Start();
}
}
@ -207,7 +142,7 @@ namespace CxbxDebugger
if (IsMainThread)
PrefixStr = "> ";
var DisplayStr = $"{PrefixStr}[{(uint)Thread.Handle}]";
string DisplayStr = string.Format("{0}[{1}] ", PrefixStr, (uint)Thread.Handle);
// Resolve thread name
@ -267,7 +202,7 @@ namespace CxbxDebugger
private void DebugLog(string Message)
{
var MessageStamped = $"[{DateTime.Now.ToLongTimeString()}] {Message}";
string MessageStamped = string.Format("[{0}] {1}", DateTime.Now.ToLongTimeString(), Message);
if (InvokeRequired)
{
@ -296,11 +231,11 @@ namespace CxbxDebugger
{
case FileEventType.Read:
case FileEventType.Write:
string text = $"{Event.Length} bytes";
string text = string.Format("{0} bytes", Event.Length.ToString());
if (Event.Offset != uint.MaxValue)
{
text += $" from offset {Event.Offset}";
text += string.Format(" from offset {0}", Event.Offset);
}
lvi.SubItems.Add(text);
@ -341,7 +276,7 @@ namespace CxbxDebugger
{
Invoke(new MethodInvoker(delegate ()
{
Suspend(DebugState.Breakpoint, "Hit file event");
Suspend("file open");
}));
}
}
@ -351,10 +286,12 @@ namespace CxbxDebugger
{
Invoke(new MethodInvoker(delegate ()
{
DebugContainer.ReportGameTitle(Title);
CachedTitle = Title;
Text = string.Format("{0} - Cxbx-Reloaded Debugger", CachedTitle);
// This is done too late - modules are already loaded
//LoadCheatTable($"{Title}.ct");
//LoadCheatTable(string.Format("{0}.ct", CachedTitle));
}));
}
@ -388,7 +325,7 @@ namespace CxbxDebugger
else
{
string module_name = Path.GetFileName(Module.Path);
Suspend(DebugState.Breakpoint, string.Format("Breakpoint hit in {0} at 0x{1:x}", module_name, Address));
Suspend(string.Format("Breakpoint hit in {0} at 0x{1:x}", module_name, Address));
// Forces a refresh at the breakpoint address (not the callstack trace)
DumpDisassembly(Address);
@ -403,21 +340,35 @@ namespace CxbxDebugger
{
Invoke(new MethodInvoker(delegate ()
{
SetDebugState(Active ? DebugState.Running : DebugState.Terminated);
// Disable when active
btnStart.Enabled = !Active;
// Enable when active
btnSuspend.Enabled = Active;
btnResume.Enabled = Active;
lblStatus.Text = (Active ? "Running" : "Inactive");
}));
}
else
{
SetDebugState(Active ? DebugState.Running : DebugState.Terminated);
// Disable when active
btnStart.Enabled = !Active;
// Enable when active
btnSuspend.Enabled = Active;
btnResume.Enabled = Active;
lblStatus.Text = (Active ? "Running" : "Inactive");
}
}
private void btnClearLog_Click(object sender, EventArgs e)
{
//lbConsole.Items.Clear();
lbConsole.Items.Clear();
}
class DebuggerFormEvents : IDebuggerSessionEvents,
class DebuggerFormEvents : IDebuggerGeneralEvents,
IDebuggerProcessEvents,
IDebuggerModuleEvents,
IDebuggerThreadEvents,
@ -425,12 +376,9 @@ namespace CxbxDebugger
IDebuggerExceptionEvents,
IDebuggerFileEvents
{
CxbxDebuggerInstance frm;
Form1 frm;
public DebuggerFormEvents(CxbxDebuggerInstance main)
public DebuggerFormEvents(Form1 main)
{
frm = main;
}
@ -445,8 +393,8 @@ namespace CxbxDebugger
{
int remainingThreads = Process.Threads.Count;
frm.DebugLog($"Process exited {Process.ProcessID} ({NtStatus.PrettyPrint(ExitCode)})");
frm.DebugLog($"{remainingThreads} child thread(s) remain open");
frm.DebugLog(string.Format("Process exited {0} ({1})", Process.ProcessID, NtStatus.PrettyPrint(ExitCode)));
frm.DebugLog(string.Format("{0} child thread(s) remain open", remainingThreads));
frm.DebugModules.Clear();
@ -474,70 +422,36 @@ namespace CxbxDebugger
public void OnDebugTitleLoaded(string Title)
{
frm.DebugLog($"Loaded title \"{Title}\"");
frm.DebugLog(string.Format("Loaded title \"{0}\"", Title));
frm.DebugTitle(Title);
}
// https://stackoverflow.com/a/749653
public static string[] CommandLineToArgs(string commandLine)
{
int argc;
var argv = VsChromium.Core.Win32.Processes.NativeMethods.CommandLineToArgvW(commandLine, out argc);
if (argv == IntPtr.Zero)
throw new System.ComponentModel.Win32Exception();
try
{
var args = new string[argc];
for (var i = 0; i < args.Length; i++)
{
var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
args[i] = Marshal.PtrToStringUni(p);
}
return args;
}
finally
{
Marshal.FreeHGlobal(argv);
}
}
public void OnDebugTargetChanged(string CommandLine)
{
frm.DebugLog($"New debug session started - {CommandLine}");
frm.Invoke(new MethodInvoker(delegate ()
{
frm.DebugContainer.AddDebugSession(CommandLineToArgs(CommandLine), true);
}));
}
public void OnThreadCreate(DebuggerThread Thread)
{
frm.DebugLog($"Thread created {Thread.ThreadID}");
frm.DebugLog(string.Format("Thread created {0}", Thread.ThreadID));
frm.DebugThreads.Add(Thread);
}
public void OnThreadExit(DebuggerThread Thread, uint ExitCode)
{
frm.DebugLog($"Thread exited {Thread.ThreadID} ({NtStatus.PrettyPrint(ExitCode)})");
frm.DebugLog(string.Format("Thread exited {0} ({1})", Thread.ThreadID, NtStatus.PrettyPrint(ExitCode)));
frm.DebugThreads.Remove(Thread);
}
public void OnThreadNamed(DebuggerThread Thread)
{
frm.DebugLog($"Thread {Thread.ThreadID} named {Thread.DebugName}");
frm.DebugLog(string.Format("Thread {0} named {1}", Thread.ThreadID, Thread.DebugName));
}
public void OnModuleLoaded(DebuggerModule Module)
{
frm.DebugLog($"Loaded module \"{Module.Path}\"");
frm.DebugLog(string.Format("Loaded module \"{0}\"", Module.Path));
frm.DebugModules.Add(Module);
}
public void OnModuleUnloaded(DebuggerModule Module)
{
frm.DebugLog($"Unloaded module \"{Module.Path}\"");
frm.DebugLog(string.Format("Unloaded module \"{0}\"", Module.Path));
frm.DebugModules.Remove(Module);
}
@ -557,7 +471,7 @@ namespace CxbxDebugger
}
// TODO Include GetLastError string
var ExceptionMessage = string.Format("Access violation thrown at 0x{0:X8} ({1})", Address, ProcessName);
string ExceptionMessage = string.Format("Access violation thrown at 0x{0:X8} ({1})", Address, ProcessName);
ExceptionMessage += string.Format("\n\nException code {0:X8}", Code);
@ -587,13 +501,13 @@ namespace CxbxDebugger
if (Info.Succeeded)
{
frm.FileHandles.Add(Info);
frm.DebugLog($"Opened file: \"{Info.FileName}\"");
frm.DebugLog(string.Format("Opened file: \"{0}\"", Info.FileName));
frm.DebugFileEvent(FileEvents.Opened(Info.FileName));
}
else
{
frm.DebugLog($"Opened file FAILED: \"{Info.FileName}\"");
frm.DebugLog(string.Format("Opened file FAILED: \"{0}\"", Info.FileName));
frm.DebugFileEvent(FileEvents.OpenedFailed(Info.FileName));
}
@ -604,7 +518,7 @@ namespace CxbxDebugger
var Found = frm.FileHandles.Find(FileInfo => FileInfo.Handle == Info.Handle);
if (Found != null)
{
frm.DebugLog($"Reading {Info.Length} byte(s) from: {Found.FileName}");
frm.DebugLog(string.Format("Reading {0} byte(s) from: {1}", Info.Length, Found.FileName));
frm.DebugFileEvent(FileEvents.Read(Found.FileName, Info.Length, Info.Offset));
}
}
@ -614,7 +528,7 @@ namespace CxbxDebugger
var Found = frm.FileHandles.Find(FileInfo => FileInfo.Handle == Info.Handle);
if (Found != null)
{
frm.DebugLog($"Writing {Info.Length} byte(s) to: {Found.FileName}");
frm.DebugLog(string.Format("Writing {0} byte(s) to: {1}", Info.Length, Found.FileName));
frm.DebugFileEvent(FileEvents.Write(Found.FileName, Info.Length, Info.Offset));
}
}
@ -628,12 +542,17 @@ namespace CxbxDebugger
frm.DebugFileEvent(FileEvents.Closed(Found.FileName));
frm.DebugLog($"Closed file: \"{Found.FileName}\"");
frm.DebugLog(string.Format("Closed file: \"{0}\"", Found.FileName));
}
}
}
private void Suspend(DebugState State, string Detail)
private void toolStripButton1_Click(object sender, EventArgs e)
{
StartDebugging();
}
private void Suspend(string Reason)
{
if (DebuggerInst != null)
{
@ -649,7 +568,7 @@ namespace CxbxDebugger
PopulateThreadList(cbThreads, null);
}
SetDebugState(State, Detail);
lblStatus.Text = string.Format("Suspended ({0})", Reason);
cbThreads.Enabled = true;
cbFrames.Enabled = true;
@ -670,12 +589,22 @@ namespace CxbxDebugger
}
}
SetDebugState(DebugState.Running);
lblStatus.Text = "Running";
cbThreads.Enabled = false;
cbFrames.Enabled = false;
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
Suspend("manually triggered");
}
private void toolStripButton3_Click(object sender, EventArgs e)
{
Resume();
}
struct CallstackInfo
{
public uint InstructionPointer;
@ -808,8 +737,8 @@ namespace CxbxDebugger
{
if (EP != 0)
{
var LinkName = string.Format("{0} +{1:x}", Name, Address - EP);
var Link = string.Format("0x{0:x8}", Address);
string LinkName = string.Format("{0} +{1:x}", Name, Address - EP);
string Link = string.Format("0x{0:x8}", Address);
tb.InsertLink(LinkName, Link);
}
@ -900,6 +829,9 @@ namespace CxbxDebugger
private void btnDumpMemory_Click(object sender, EventArgs e)
{
if (DebuggerInst == null)
return;
if (diagSaveMemory.ShowDialog() == DialogResult.OK)
{
byte[] data = ReadMemory();
@ -919,7 +851,7 @@ namespace CxbxDebugger
int Index = cbThreads.SelectedIndex;
if (Index == -1)
return;
CallstackDump.Clear();
cbFrames.Items.Clear();
@ -1038,6 +970,17 @@ namespace CxbxDebugger
fileWatchMan.SetEnabled(e.Index, e.NewValue == CheckState.Checked);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.F5)
{
StartDebugging();
return true;
}
return false;
}
private void HandleDisasmGo()
{
uint addr = 0;
@ -1098,7 +1041,7 @@ namespace CxbxDebugger
{
var li = lvCEMemory.Items.Add(string.Format("{0} 0x{1:x}", DataPatch.Module, DataPatch.Offset));
li.SubItems.Add(DataPatch.Name);
li.SubItems.Add($"{DataPatch.Patched.Length} byte(s)");
li.SubItems.Add(string.Format("{0} byte(s)", DataPatch.Patched.Length));
if (MainProcess != null)
{
li.SubItems.Add(patchMan.Read(MainProcess, DataPatch));
@ -1157,7 +1100,7 @@ namespace CxbxDebugger
if (File.Exists(filename))
{
DebugLog($"Attempting to load \"{filename}\"");
DebugLog(string.Format("Attempting to load \"{0}\"", filename));
CheatEngine.CheatTable ct_data = CheatEngine.CheatTableReader.FromFile(filename);
if (ct_data != null)
@ -1194,8 +1137,8 @@ namespace CxbxDebugger
patchMan.Assembly.Add(DataPatch);
}
DebugLog($"Loaded {ct_data.CodeEntires.Count} auto-assembler entries");
DebugLog($"Loaded {ct_data.CheatEntries.Count} cheat entries");
DebugLog(string.Format("Loaded {0} auto-assembler entries", ct_data.CodeEntires.Count));
DebugLog(string.Format("Loaded {0} cheat entries", ct_data.CheatEntries.Count));
RefreshPatches();
}
@ -1204,7 +1147,7 @@ namespace CxbxDebugger
private void button5_Click(object sender, EventArgs e)
{
var PatchType = (PatchType)cbDataFormat.SelectedIndex;
PatchType PatchType = (PatchType)cbDataFormat.SelectedIndex;
int PatchSize = PatchManager.PatchTypeLength(PatchType);
if (PatchSize == 0)
@ -1222,7 +1165,7 @@ namespace CxbxDebugger
Patch DataPatch = new Patch();
DataPatch.DisplayAs = PatchType;
DataPatch.Name = $"Patched {PatchType}";
DataPatch.Name = string.Format("Patched {0}", PatchType);
DataPatch.Module = "";
DataPatch.Offset = addr;
@ -1287,60 +1230,5 @@ namespace CxbxDebugger
}
}
}
public SessionState GetSessionState()
{
if (DebuggerWorkerThread == null)
{
return SessionState.Inactive;
}
else if (DebuggerWorkerThread.ThreadState == ThreadState.Stopped)
{
return SessionState.Ended;
}
return SessionState.Running;
}
public void StartSession()
{
if (GetSessionState() == SessionState.Inactive)
{
StartDebugging();
}
}
public void SuspendSession()
{
if (GetSessionState() == SessionState.Running)
{
Suspend(DebugState.Suspended, "By user");
}
}
public void ResumeSession()
{
Resume();
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
tabContainer.SelectedTab = tabWatch;
}
private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
tabContainer.SelectedTab = tabMemory;
}
private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
tabContainer.SelectedTab = tabDisassembly;
}
public DebugStateInfo GetDebugStateInfo()
{
return StateInfo;
}
}
}

View File

@ -118,13 +118,16 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>534, 17</value>
<value>17, 17</value>
</metadata>
<metadata name="statusBar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="diagSaveMemory.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>153, 17</value>
<value>238, 17</value>
</metadata>
<metadata name="diagBrowseCT.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>357, 17</value>
<value>384, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@ -1,51 +0,0 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
namespace CxbxDebugger
{
public enum SessionState
{
Inactive,
Running,
Ended,
}
public enum DebugState
{
Unknown,
Idle,
Suspended,
Breakpoint,
Running,
Terminated,
}
public struct DebugStateInfo
{
public DebugState State;
public string Detail;
}
public interface IDebugWindow
{
void StartSession();
void SuspendSession();
void ResumeSession();
SessionState GetSessionState();
DebugStateInfo GetDebugStateInfo();
}
public interface IDebugContainerWindow
{
void AddDebugSession(string[] Arguments, bool StartAutomatically);
void ReportGameTitle(string GameTitle);
void ReportStatus(IDebugWindow Window, DebugState Status, string Detail);
}
}

View File

@ -18,7 +18,6 @@ namespace CxbxDebugger
Application.SetCompatibleTextRenderingDefault(false);
string[] args = Environment.GetCommandLineArgs();
#if !DEBUG
if( args.Length == 1 )
{
// TODO: Valid usage message
@ -26,9 +25,8 @@ namespace CxbxDebugger
Application.Exit();
}
else
#endif
{
Application.Run(new CxbxDebuggerMain(args));
Application.Run(new Form1());
}
}
}

View File

@ -345,10 +345,6 @@ namespace CxbxDebugger
/// <summary>
///
/// </summary>
StatusHandleNotClosable = 0xC0000235,
/// <summary>
///
/// </summary>
GuardPageViolation = 0x80000001,
/// <summary>
///

View File

@ -0,0 +1,75 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2017-2019 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
// CxbxEmulator.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
#include "Cxbx.h"
DWORD WINAPI Emulate()
{
FUNC_EXPORTS
/*! verify Cxbx-Loader.exe is loaded to base address 0x00010000 */
if ((UINT_PTR)GetModuleHandle(nullptr) != CXBX_BASE_ADDR)
{
/*! CXBX_BASE_ADDR is defined as 0x00010000, which is the base address of
the Cxbx-Loader.exe host executable.
Set in Cxbx-Loader.exe Project options, Linker, Advanced, Base Address */
MessageBox(NULL, "Cxbx-Loader.exe was not loaded to base address 0x00010000 (which is a requirement for Xbox emulation)", "Cxbx-Reloaded", MB_OK);
return 1;
}
/* Initialize Cxbx File Paths */
CxbxInitFilePaths();
/*! initialize shared memory */
if (!EmuShared::Init()) {
MessageBox(NULL, "Could not map shared memory!", "Cxbx-Reloaded", MB_OK);
return 1;
}
LPSTR CommandLine = GetCommandLine();
int argc;
PCHAR *argv = CommandLineToArgvA(CommandLine, &argc);
CxbxKrnlMain(argc, argv);
LocalFree(argv);
/*! cleanup shared memory */
EmuShared::Cleanup();
return 0;
}

View File

@ -2,25 +2,10 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "Version.h"
#include "CxbxVersion.h"
#include <string>
/*! version string dependent on trace flag */
#ifndef _DEBUG_TRACE
const char* CxbxVersionStr = _GIT_VERSION " (" __DATE__ ")";
const char *CxbxrHashBuild = _GIT_VERSION;
#else
const char* CxbxVersionStr = _GIT_VERSION "-Trace (" __DATE__ ")";
const char *CxbxrHashBuild = _GIT_VERSION "-Trace";
#endif
static constexpr const char *GitVersionStr = _GIT_VERSION;
static constexpr size_t GitVersionLength = std::char_traits<char>::length(GitVersionStr);
static_assert(GitVersionLength < GitVersionMaxLength);
const char *const GetGitVersionStr() {
return GitVersionStr;
}
const size_t GetGitVersionLength() {
return GitVersionLength;
}

View File

@ -1,10 +1,5 @@
#pragma once
extern const char* CxbxVersionStr;
extern const char *CxbxrHashBuild;
#include "version.h"
// Note: GitVersionMaxLength should be large enough to accomodate the longest git version string we can practically expect to have. This is necessary
// to avoid possible mismatches in the string length which can happen if the user mixes different cxbxr versions
inline constexpr size_t GitVersionMaxLength = 80;
const char *const GetGitVersionStr();
const size_t GetGitVersionLength();
extern const char* CxbxVersionStr;

View File

@ -45,8 +45,8 @@ const _XboxAddressRanges XboxAddressRanges[] = {
#else
#define RANGE_ENTRY(START, END, SIZE, PROT, FLAGS, COMMENT) { START, SIZE, PROT, FLAGS }
#endif
// See https://xboxdevwiki.net/Memory
// and https://xboxdevwiki.net/Boot_Process#Paging
// See http://xboxdevwiki.net/Memory
// and http://xboxdevwiki.net/Boot_Process#Paging
// Entry : Start , End , Size , Protect , RangeFlags , Comment
RANGE_ENTRY(USER_ADDRESS1_BASE, USER_ADDRESS1_END, USER_ADDRESS1_SIZE, PROT_XRW, SYSTEM_ALL | MAY_FAIL, "MemLowVirtual (General Xbox type) lower 64 MiB Optional (already reserved via virtual_memory_placeholder)"),
RANGE_ENTRY(USER_ADDRESS2_BASE, USER_ADDRESS2_END, USER_ADDRESS2_SIZE, PROT_XRW, SYSTEM_128MB | MAY_FAIL, "MemLowVirtual (Chihiro / DevKit) ^ + upper 64 MiB"),
@ -65,24 +65,24 @@ const _XboxAddressRanges XboxAddressRanges[] = {
RANGE_ENTRY(NVNET_DEVICE_BASE , NVNET_DEVICE_END , NVNET_DEVICE_SIZE , PROT_NAC, SYSTEM_ALL , "DeviceNVNet"),
RANGE_ENTRY(FLASH_DEVICE1_BASE, FLASH_DEVICE1_END, FLASH_DEVICEN_SIZE, PROT_NAC, SYSTEM_ALL , "DeviceFlash_a (Flash mirror 1)"),
RANGE_ENTRY(FLASH_DEVICE2_BASE, FLASH_DEVICE2_END, FLASH_DEVICEN_SIZE, PROT_NAC, SYSTEM_ALL , "DeviceFlash_b (Flash mirror 2)"),
RANGE_ENTRY(FLASH_DEVICE3_BASE, FLASH_DEVICE3_END, FLASH_DEVICEN_SIZE, PROT_NAC, SYSTEM_ALL | MAY_FAIL, "DeviceFlash_c (Flash mirror 3)"), // this region fails reservation when running under Ubuntu with wine, so it must be allowed to fail
RANGE_ENTRY(FLASH_DEVICE3_BASE, FLASH_DEVICE3_END, FLASH_DEVICEN_SIZE, PROT_NAC, SYSTEM_ALL , "DeviceFlash_c (Flash mirror 3)"),
RANGE_ENTRY(FLASH_DEVICE4_BASE, FLASH_DEVICE4_END, FLASH_DEVICEN_SIZE, PROT_NAC, SYSTEM_ALL | MAY_FAIL, "DeviceFlash_d (Flash mirror 4) Optional (will probably fail reservation, which is acceptable - the 3 other mirrors work just fine"),
#undef RANGE_ENTRY
};
const size_t XboxAddressRanges_size = ARRAY_SIZE(XboxAddressRanges);
bool AddressRangeMatchesFlags(const size_t index, const unsigned int flags)
bool AddressRangeMatchesFlags(const int index, const unsigned int flags)
{
return XboxAddressRanges[index].RangeFlags & flags;
}
bool IsOptionalAddressRange(const size_t index)
bool IsOptionalAddressRange(const int index)
{
return AddressRangeMatchesFlags(index, MAY_FAIL);
}
unsigned int AddressRangeGetSystemFlags(const size_t index)
int AddressRangeGetSystemFlags(const int index)
{
return XboxAddressRanges[index].RangeFlags & SYSTEM_ALL;
}

View File

@ -115,6 +115,10 @@ inline constexpr uint32_t NVNET_DEVICE_BASE = 0xFEF00000;
inline constexpr uint32_t NVNET_DEVICE_SIZE = (KiB(1)); // = 0x00000400
inline constexpr uint32_t NVNET_DEVICE_END = (NVNET_DEVICE_BASE + NVNET_DEVICE_SIZE - 1); // 0xFEF003FF
#define XBOX_FLASH_ROM_BASE 0xFFF00000
#define XBOX_FLASH_ROM_SIZE (MiB(1)) // = 0x00100000
#define XBOX_FLASH_ROM_END (XBOX_FLASH_ROM_BASE + XBOX_FLASH_ROM_SIZE - 1) // - 0xFFFFFFF
inline constexpr uint32_t FLASH_DEVICEN_SIZE = (MiB(4)); // = 0x00400000
inline constexpr uint32_t FLASH_DEVICE1_BASE = 0xFF000000;
inline constexpr uint32_t FLASH_DEVICE1_END = (FLASH_DEVICE1_BASE + FLASH_DEVICEN_SIZE - 1); // 0xFF3FFFFF
@ -163,14 +167,6 @@ inline constexpr uint32_t FLASH_DEVICE4_END = (FLASH_DEVICE4_BASE - 1 + FLA
#define XBOX_MEMORY_SIZE (MiB(64))
#define CHIHIRO_MEMORY_SIZE (MiB(128))
// Common page calculations
#define ROUND_UP_4K(size) (((size) + PAGE_MASK) & (~PAGE_MASK))
#define ROUND_UP(size, alignment) (((size) + (alignment - 1)) & (~(alignment - 1)))
#define ROUND_DOWN_4K(size) ((size) & (~PAGE_MASK))
#define ROUND_DOWN(size, alignment) ((size) & (~(alignment - 1)))
#define CHECK_ALIGNMENT(size, alignment) (((size) % (alignment)) == 0)
#define PAGE_ALIGN(address) ROUND_DOWN_4K(address)
// Windows' address space allocation granularity;
// See https://blogs.msdn.microsoft.com/oldnewthing/20031008-00/?p=42223
const int BLOCK_SIZE = KiB(64);
@ -204,8 +200,8 @@ extern const struct _XboxAddressRanges {
extern const size_t XboxAddressRanges_size;
extern bool AddressRangeMatchesFlags(const size_t index, const unsigned int flags);
extern bool IsOptionalAddressRange(const size_t index);
extern unsigned int AddressRangeGetSystemFlags(const size_t index);
extern bool AddressRangeMatchesFlags(const int index, const unsigned int flags);
extern bool IsOptionalAddressRange(const int index);
extern int AddressRangeGetSystemFlags(const int index);
extern bool VerifyWow64();

View File

@ -37,19 +37,19 @@ namespace CxbxDebugger
// Note: Keep the top 3-bits empty as they are used internally
enum ReportType : DWORD
{
HLECACHE_FILE = 0x1000,
// Debugger report codes:
KERNEL_PATCH = 0x2000,
HLECACHE_FILE = 0x00deed00,
KERNEL_PATCH = 0x00deed01,
FILE_OPENED = 0x00deed02,
FILE_READ = 0x00deed03,
FILE_CLOSED = 0x00deed04,
DEBUGGER_INIT = 0x00deed05,
FILE_WRITE = 0x00deed06,
FILE_OPENED = 0x3000,
FILE_READ = 0x3001,
FILE_WRITE = 0x3002,
FILE_CLOSED = 0x3003,
// Debugger query codes:
DEBUGGER_INIT = 0x4000,
DEBUGGER_NEW_TARGET = 0x4001,
OVERRIDE_EXCEPTION = 0x5000,
OVERRIDE_EXCEPTION = 0x00ceed01,
};
bool IsAttached()
@ -128,10 +128,8 @@ namespace CxbxDebugger
case Internal::KERNEL_PATCH:
case Internal::FILE_OPENED:
case Internal::FILE_READ:
case Internal::FILE_WRITE:
case Internal::FILE_CLOSED:
case Internal::DEBUGGER_INIT:
case Internal::DEBUGGER_NEW_TARGET:
return true;
case Internal::OVERRIDE_EXCEPTION:
@ -150,20 +148,12 @@ namespace CxbxDebugger
{
Internal::ReportHelper Report(Internal::DEBUGGER_INIT);
Report.Add(0); // unused
Report.AddString(XbeTitle);
Report.Send();
}
void ReportNewTarget(const char* CommandLine)
{
Internal::ReportHelper Report(Internal::DEBUGGER_NEW_TARGET);
Report.AddString(CommandLine);
Report.Send();
}
void ReportHLECacheFile(const char* Filename)
{
Internal::ReportHelper Report(Internal::HLECACHE_FILE);

View File

@ -36,7 +36,6 @@ namespace CxbxDebugger
// Report helpers:
void ReportDebuggerInit(const char* XbeTitle);
void ReportNewTarget(const char* CommandLine);
void ReportHLECacheFile(const char* Filename);
void ReportKernelPatch(const char* ImportName, DWORD Address);

View File

@ -27,8 +27,8 @@
#define LOG_PREFIX CXBXR_MODULE::EEPR
#define LOG_PREFIX_INIT CXBXR_MODULE::INIT
#include <core\kernel\exports\xboxkrnl.h> // For XC_VALUE_INDEX and XBOX_EEPROM
#include "cxbxr.hpp" // For CxbxrAbort
#include <stdio.h> // For printf
#include <shlobj.h> // For HANDLE, CreateFile, CreateFileMapping, MapViewOfFile
#include <random>
@ -36,6 +36,7 @@
#include "EmuEEPROM.h" // For EEPROMInfo, EEPROMInfos
#include "core\kernel\support\Emu.h" // For EmuWarning
#include "..\..\src\devices\LED.h" // For SetLEDSequence
#include "..\core\kernel\init\CxbxKrnl.h"
xbox::XBOX_EEPROM *EEPROM = nullptr; // Set using CxbxRestoreEEPROM()
@ -89,7 +90,6 @@ void gen_section_CRCs(xbox::XBOX_EEPROM* eeprom) {
);
}
#ifdef CXBXR_EMU
xbox::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
{
xbox::XBOX_EEPROM *pEEPROM;
@ -141,8 +141,10 @@ xbox::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
LARGE_INTEGER len_li;
GetFileSizeEx(hFileEEPROM, &len_li);
unsigned int FileSize = len_li.u.LowPart;
if (FileSize != 256) {
CxbxrAbort("%s : EEPROM.bin file is not 256 bytes large!\n", __func__);
if (FileSize != 256)
{
CxbxKrnlCleanup("%s : EEPROM.bin file is not 256 bytes large!\n", __func__);
return nullptr;
}
// Map EEPROM.bin contents into memory :
@ -192,7 +194,6 @@ xbox::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin)
return pEEPROM;
}
#endif
void EmuEEPROMReset(xbox::XBOX_EEPROM* eeprom)
{

View File

@ -1,187 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx-Reloaded project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * All rights reserved
// *
// ******************************************************************
#define LOG_PREFIX CXBXR_MODULE::FILE
#define LOG_PREFIX_INIT CXBXR_MODULE::INIT
#include <filesystem>
#include "common/cxbxr.hpp"
#include "Settings.hpp"
#include "EmuShared.h"
#include "xxhash.h" // for XXH3_64bits
#include "core/kernel/common/xbox.h"
#include "Logging.h"
char szFilePath_CxbxReloaded_Exe[MAX_PATH] = { 0 };
char szFilePath_EEPROM_bin[MAX_PATH] = { 0 };
std::string g_DataFilePath;
std::string g_DiskBasePath;
std::string g_MuBasePath;
//TODO: Possible move CxbxResolveHostToFullPath inline function someplace else if become useful elsewhere.
// Let filesystem library clean it up for us, including resolve host's symbolic link path.
// Since internal kernel do translate to full path than preserved host symoblic link path.
void CxbxResolveHostToFullPath(std::filesystem::path& file_path, std::string_view finish_error_sentence) {
std::error_code error;
std::filesystem::path sanityPath = std::filesystem::canonical(file_path, error);
if (error) {
// The MS implementation of std::filesystem::canonical internally calls GetFinalPathNameByHandleW, which fails with ERROR_FILE_NOT_FOUND when called
// on a file inside a mounted xiso under Windows with the xbox-iso-vfs tool because of this known dokany bug https://github.com/dokan-dev/dokany/issues/343
EmuLogInit(LOG_LEVEL::WARNING, "Could not resolve to %s: %s, dokany in use? The error was: %s",
finish_error_sentence.data(), file_path.string().c_str(), error.message().c_str());
sanityPath = std::filesystem::absolute(std::filesystem::weakly_canonical(file_path, error), error);
if (error) {
CxbxrAbortEx(LOG_PREFIX_INIT, "Could not resolve to %s: %s. The error was: %s", finish_error_sentence.data(), file_path.string().c_str(), error.message().c_str());
}
}
file_path = sanityPath;
}
// TODO: Eventually, we should remove this function to start using std::filesystem::path method for all host paths.
void CxbxResolveHostToFullPath(std::string& file_path, std::string_view finish_error_sentence) {
std::filesystem::path sanityPath(file_path);
CxbxResolveHostToFullPath(sanityPath, finish_error_sentence);
file_path = sanityPath.string();
}
// NOTE: Do NOT modify g_<custom>BasePath variables after this call!
void CxbxrInitFilePaths()
{
if (g_Settings) {
g_DataFilePath = g_Settings->GetDataLocation();
}
else {
char dataLoc[MAX_PATH];
g_EmuShared->GetDataLocation(dataLoc);
g_DataFilePath = dataLoc;
}
// Make sure our data folder exists :
bool result = std::filesystem::exists(g_DataFilePath);
if (!result && !std::filesystem::create_directory(g_DataFilePath)) {
CxbxrAbort("%s : Couldn't create Cxbx-Reloaded's data folder!", __func__);
}
// Make sure the EmuDisk folder exists
g_DiskBasePath = g_DataFilePath + "\\EmuDisk";
result = std::filesystem::exists(g_DiskBasePath);
if (!result && !std::filesystem::create_directory(g_DiskBasePath)) {
CxbxrAbort("%s : Couldn't create Cxbx-Reloaded EmuDisk folder!", __func__);
}
CxbxResolveHostToFullPath(g_DiskBasePath, "Cxbx-Reloaded's EmuDisk directory");
g_DiskBasePath = std::filesystem::path(g_DiskBasePath).append("").string();
// Make sure the EmuDMu folder exists
g_MuBasePath = g_DataFilePath + "\\EmuMu";
result = std::filesystem::exists(g_MuBasePath);
if (!result && !std::filesystem::create_directory(g_MuBasePath)) {
CxbxrAbort("%s : Couldn't create Cxbx-Reloaded EmuMu folder!", __func__);
}
CxbxResolveHostToFullPath(g_MuBasePath, "Cxbx-Reloaded's EmuMu directory");
g_MuBasePath = std::filesystem::path(g_MuBasePath).append("").string();
snprintf(szFilePath_EEPROM_bin, MAX_PATH, "%s\\EEPROM.bin", g_DataFilePath.c_str());
GetModuleFileName(GetModuleHandle(nullptr), szFilePath_CxbxReloaded_Exe, MAX_PATH);
}
// Loads a keys.bin file as generated by dump-xbox
// See https://github.com/JayFoxRox/xqemu-tools/blob/master/dump-xbox.c
void LoadXboxKeys()
{
std::string keys_path = g_DataFilePath + "\\keys.bin";
// Attempt to open Keys.bin
FILE* fp = fopen(keys_path.c_str(), "rb");
if (fp != nullptr) {
// Determine size of Keys.bin
xbox::XBOX_KEY_DATA keys[2];
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
// If the size of Keys.bin is correct (two keys), read it
if (size == xbox::XBOX_KEY_LENGTH * 2) {
fread(keys, xbox::XBOX_KEY_LENGTH, 2, fp);
memcpy(xbox::XboxEEPROMKey, &keys[0], xbox::XBOX_KEY_LENGTH);
memcpy(xbox::XboxCertificateKey, &keys[1], xbox::XBOX_KEY_LENGTH);
}
else {
EmuLog(LOG_LEVEL::WARNING, "Keys.bin has an incorrect filesize. Should be %d bytes", xbox::XBOX_KEY_LENGTH * 2);
}
fclose(fp);
return;
}
// If we didn't already exit the function, keys.bin could not be loaded
EmuLog(LOG_LEVEL::WARNING, "Failed to load Keys.bin. Cxbx-Reloaded will be unable to read Save Data from a real Xbox");
}
static HANDLE hMapDataHash = nullptr;
bool CxbxrLockFilePath()
{
std::stringstream filePathHash("Local\\");
uint64_t hashValue = XXH3_64bits(g_DataFilePath.c_str(), g_DataFilePath.length() + 1);
if (!hashValue) {
CxbxrAbort("%s : Couldn't generate Cxbx-Reloaded's data folder hash!", __func__);
}
filePathHash << std::hex << hashValue;
hMapDataHash = CreateFileMapping(
INVALID_HANDLE_VALUE, // Paging file
nullptr, // default security attributes
PAGE_READONLY, // readonly access
0, // size: high 32 bits
/*Dummy size*/4, // size: low 32 bits
filePathHash.str().c_str() // name of map object
);
if (hMapDataHash == nullptr) {
return false;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
PopupError(nullptr, "Data path directory is currently in use.\nUse a different data path directory or stop emulation from another process.");
CloseHandle(hMapDataHash);
return false;
}
return true;
}
void CxbxrUnlockFilePath()
{
// Close opened file path lockdown shared memory.
if (hMapDataHash) {
CloseHandle(hMapDataHash);
hMapDataHash = nullptr;
}
}

View File

@ -1,53 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx-Reloaded project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
extern char szFilePath_CxbxReloaded_Exe[MAX_PATH];
extern char szFilePath_EEPROM_bin[MAX_PATH];
extern std::string g_DataFilePath;
extern std::string g_DiskBasePath;
extern std::string g_MuBasePath;
#include <filesystem>
//TODO: Possible move CxbxResolveHostToFullPath inline function someplace else if become useful elsewhere.
// Let filesystem library clean it up for us, including resolve host's symbolic link path.
// Since internal kernel do translate to full path than preserved host symoblic link path.
void CxbxResolveHostToFullPath(std::filesystem::path& file_path, std::string_view finish_error_sentence);
// TODO: Eventually, we should remove this function to start using std::filesystem::path method for all host paths.
void CxbxResolveHostToFullPath(std::string& file_path, std::string_view finish_error_sentence);
// NOTE: Do NOT modify g_<custom>BasePath variables after this call!
void CxbxrInitFilePaths();
// Loads a keys.bin file as generated by dump-xbox
// See https://github.com/JayFoxRox/xqemu-tools/blob/master/dump-xbox.c
void LoadXboxKeys();
bool CxbxrLockFilePath();
void CxbxrUnlockFilePath();

View File

@ -38,7 +38,6 @@ typedef enum class _IPC_UPDATE_GUI {
, XBOX_LED_COLOUR
, LOG_ENABLED
, KRNL_IS_READY
, OVERLAY
} IPC_UPDATE_GUI;
void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value);
@ -49,9 +48,8 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value);
// ******************************************************************
typedef enum class _IPC_UPDATE_KERNEL {
CONFIG_LOGGING_SYNC = 0,
CONFIG_INPUT_SYNC,
CONFIG_CHANGE_TIME
CONFIG_LOGGING_SYNC = 0
, CONFIG_INPUT_SYNC
} IPC_UPDATE_KERNEL;
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd);

View File

@ -80,9 +80,6 @@ const char* g_EnumModules2String[to_underlying(CXBXR_MODULE::MAX)] = {
"DSSTREAM",
"DS3DCALC",
"XMO ",
"RINP ",
"JVS ",
"LIBUSB ",
"KRNL ",
"LOG ",
"XBOX ",
@ -160,7 +157,7 @@ inline void EmuLogOutputEx(const CXBXR_MODULE cxbxr_module, const LOG_LEVEL leve
}
// print out a custom message to the console or kernel debug log file
void EmuLogEx(CXBXR_MODULE cxbxr_module, LOG_LEVEL level, const char *szWarningMessage, ...)
void NTAPI EmuLogEx(CXBXR_MODULE cxbxr_module, LOG_LEVEL level, const char *szWarningMessage, ...)
{
if (szWarningMessage == NULL) {
return;
@ -181,7 +178,7 @@ void EmuLogEx(CXBXR_MODULE cxbxr_module, LOG_LEVEL level, const char *szWarningM
}
}
void EmuLogInit(LOG_LEVEL level, const char *szWarningMessage, ...)
void NTAPI EmuLogInit(LOG_LEVEL level, const char *szWarningMessage, ...)
{
if (szWarningMessage == NULL) {
return;
@ -313,7 +310,7 @@ PopupReturn PopupCustomEx(const void* hwnd, const CXBXR_MODULE cxbxr_module, con
uType |= MB_OKCANCEL;
break;
case PopupButtons::AbortRetryIgnore:
uType |= MB_ABORTRETRYIGNORE;
uType |= MB_RETRYCANCEL;
break;
case PopupButtons::YesNoCancel:
uType |= MB_YESNOCANCEL;
@ -329,11 +326,11 @@ PopupReturn PopupCustomEx(const void* hwnd, const CXBXR_MODULE cxbxr_module, con
va_list argp;
va_start(argp, message);
// allocate predicted buffer size then write to buffer afterward.
std::string Buffer(1+std::vsnprintf(nullptr, 0, message, argp), '\0');
std::vector<char> Buffer(1+std::vsnprintf(nullptr, 0, message, argp));
vsnprintf(Buffer.data(), Buffer.size(), message, argp);
va_end(argp);
EmuLogOutputEx(cxbxr_module, level, "Popup : %s", Buffer.c_str());
EmuLogOutputEx(cxbxr_module, level, "Popup : %s", Buffer);
// If user is using exclusive fullscreen, we need to refrain all popups.
if (g_disablePopupMessages) {
@ -396,13 +393,8 @@ inline void output_wchar(std::ostream& os, wchar_t c)
default: os << "\\x" << std::setfill('0') << std::setw(4) << std::right << std::hex << std::uppercase << (wint_t)c;
}
}
else {
const wchar_t *wc = reinterpret_cast<const wchar_t *>(&c);
std::string dst(2, '\0');
std::mbstate_t ps{};
std::wcsrtombs(dst.data(), &wc, 1, &ps);
os << dst;
}
else
os << c;
}
LOG_SANITIZE_HEADER(hex1, uint8_t)

View File

@ -88,9 +88,6 @@ typedef enum class _CXBXR_MODULE: unsigned int {
DSSTREAM,
DS3DCALC,
XMO,
RINP,
JVS,
LIBUSB,
// kernel
KRNL,
LOG,
@ -122,8 +119,8 @@ extern std::atomic_int g_CurrentLogLevel;
extern std::atomic_bool g_CurrentLogPopupTestCase;
// print out a log message to the console or kernel debug log file if level is high enough
void EmuLogEx(CXBXR_MODULE cxbxr_module, LOG_LEVEL level, const char *szWarningMessage, ...);
void EmuLogInit(LOG_LEVEL level, const char *szWarningMessage, ...);
void NTAPI EmuLogEx(CXBXR_MODULE cxbxr_module, LOG_LEVEL level, const char *szWarningMessage, ...);
void NTAPI EmuLogInit(LOG_LEVEL level, const char *szWarningMessage, ...);
#define EmuLog(level, fmt, ...) EmuLogEx(LOG_PREFIX, level, fmt, ##__VA_ARGS__)
@ -186,6 +183,24 @@ PopupReturn PopupCustomEx(const void* hwnd, const CXBXR_MODULE cxbxr_module, con
// For LOG_TEST_CASE
extern inline void EmuLogOutputEx(const CXBXR_MODULE cxbxr_module, const LOG_LEVEL level, const char *szWarningMessage, ...);
// The reason of having EmuLogOutputEx in LOG_TEST_CASE is to allow dump to log directly for any test cases triggered.
// Which will make developers easier to note which applications has triggered quicker, easier, and doesn't require any individual log enabled to capture them.
#define LOG_TEST_CASE(message) do { \
static bool bTestCaseLogged = false; \
if (bTestCaseLogged) break; \
bTestCaseLogged = true; \
if (g_CurrentLogPopupTestCase) { \
LOG_CHECK_ENABLED(LOG_LEVEL::INFO) { \
PopupInfo(nullptr, "Please report that %s shows the following message:\nLOG_TEST_CASE: %s\nIn %s (%s line %d)", \
CxbxKrnl_Xbe->m_szAsciiTitle, message, __func__, __FILE__, __LINE__); \
continue; \
} \
} \
EmuLogOutputEx(LOG_PREFIX, LOG_LEVEL::INFO, "Please report that %s shows the following message:\nLOG_TEST_CASE: %s\nIn %s (%s line %d)", \
CxbxKrnl_Xbe->m_szAsciiTitle, message, __func__, __FILE__, __LINE__); \
} while (0)
// was g_pCertificate->wszTitleName
//
// __FILENAME__
//
@ -225,30 +240,9 @@ extern inline void output_wchar(std::ostream& os, wchar_t c);
// By default, sanitization functions simply return the given argument
// (type and value) which results in calls to standard output writers.
template<class T>
inline auto _log_sanitize(T value, int ignored_length = 0)
inline T _log_sanitize(T value, int ignored_length = 0)
{
// This is necessary because C++20 has deleted the overloaded operator<< of ostream for wchar_t, char8_t, char16_t and char32_t.
// The proper solution is to use wide strings in all our logging macros/functions, see https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/issues/743
if constexpr (std::is_same_v<xbox::wchar_xt, std::remove_cvref_t<std::remove_pointer_t<T>>>) {
if constexpr (std::is_pointer_v<T>) {
const wchar_t *wstr = reinterpret_cast<const wchar_t *>(value);
std::size_t len = std::wcslen(wstr);
std::string dst(len + 1, '\0');
std::mbstate_t ps{};
std::wcsrtombs(dst.data(), &wstr, len, &ps);
return dst;
}
else {
const wchar_t *wstr = reinterpret_cast<const wchar_t *>(&value);
std::string dst(2, '\0');
std::mbstate_t ps{};
std::wcsrtombs(dst.data(), &wstr, 1, &ps);
return dst;
}
}
else {
return value;
}
return value;
}
#if 0 // TODO FIXME : Disabled for now, as this is incorrectly called for INT types too
@ -315,8 +309,8 @@ constexpr const char* remove_prefix(const char* str, const char *prefix) {
return (str_skip_prefix(str, prefix) == str + str_length(prefix)) ? str_skip_prefix(str, prefix) : str;
}
static constexpr const char* xbox_prefix = "xbox::";
static constexpr const char* emupatch_prefix = "EmuPatch_"; // See #define EMUPATCH
static const char* xbox_prefix = "xbox::";
static const char* emupatch_prefix = "EmuPatch_"; // See #define EMUPATCH
constexpr const char* remove_emupatch_prefix(const char* str) {
// return an empty string when str isn't given

View File

@ -302,9 +302,9 @@ bool AttemptReserveAddressRanges(unsigned int* p_reserved_systems, blocks_reserv
// Some ranges are allowed to fail reserving
if (!IsOptionalAddressRange(i)) {
// If not, then let's free them and downgrade host's limitation.
clear_systems = AddressRangeGetSystemFlags(i);
iLast = i;
i = -1; // Reset index back to zero after for statement's increment.
clear_systems = AddressRangeGetSystemFlags(i);
continue;
}
}
@ -319,6 +319,12 @@ bool isSystemFlagSupport(unsigned int reserved_systems, unsigned int assign_syst
if (reserved_systems & assign_system) {
return true;
}
// TODO: Once host's standalone emulation is remove from GUI, remove below as well.
#ifndef CXBXR_EMU
if (reserved_systems == 0) {
return true;
}
#endif
return false;
}

View File

@ -0,0 +1,55 @@
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx is free software; you can redistribute it
// * and/or modify it under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2016 Patrick van Logchem <pvanlogchem@gmail.com>
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef RESERVEDMEMORY_H
#define RESERVEDMEMORY_H
#ifndef CXBXR_EMU
#if defined(__cplusplus)
extern "C"
{
#endif
#include "EmuShared.h" // For XBE_MAX_VA, XBE_IMAGE_BASE and CXBX_BASE_OF_CODE
// The following code reserves virtual addresses from 0x00011000 upwards;
#define VM_PLACEHOLDER_SIZE (XBE_MAX_VA - XBE_IMAGE_BASE - CXBX_BASE_OF_CODE)
// First, declare the '.text' section again :
#pragma section(".text") // Note : 'read,write,execute' would cause a warning
// Then place the following variable into the '.text' section :
__declspec(allocate(".text"))
// This variable *MUST* be this large, for it to take up address space
// so that all other code and data in this module are placed outside of the
// maximum virtual memory range.
unsigned char virtual_memory_placeholder[VM_PLACEHOLDER_SIZE]; // = { OPCODE_NOP_90 };
// TODO : Try to get the same result without enlarging our executable by 128 MB!
#if defined(__cplusplus)
}
#endif
#endif
#endif // RESERVEDMEMORY_H

View File

@ -33,7 +33,8 @@
#include "core\kernel\support\Emu.h"
#include "EmuShared.h"
#include <filesystem>
#include "common\input\layout_xbox_device.h"
#include "common\input\InputManager.h"
#include "common\input\layout_xbox_controller.h"
#include <fstream>
#include "common/util/cliConfig.hpp"
@ -52,12 +53,7 @@ static_assert(false, "Please implement support for cross-platform's user profile
uint16_t g_LibVersion_D3D8 = 0;
uint16_t g_LibVersion_DSOUND = 0;
// NOTE: Update settings_version when conversion to setting's structure is required.
// UPDATE: When settings are removed, use "if (use false && settings_version < {next_version}) {" statement
// until existing settings require replacement or conversion. next_version input is a hardcode number.
// Settings version 10 and later should consider as not backward compatible.
// TODO: Add read-only state when using an older build and add a notification for will not be able save to file.
// The sooner we do this, the better before version upgrade.
// NOTE: Update settings_version when add/edit/delete setting's structure.
///////////////////////////
// * History:
// * 2: (RadWolfie), initial version
@ -90,7 +86,6 @@ static struct {
const char* DataCustomLocation = "DataCustomLocation";
const char* IgnoreInvalidXbeSig = "IgnoreInvalidXbeSig";
const char *IgnoreInvalidXbeSec = "IgnoreInvalidXbeSec";
const char* ConsoleTypeToggle = "ConsoleTypeToggle";
} sect_gui_keys;
static const char* section_core = "core";
@ -102,6 +97,7 @@ static struct {
const char* AllowAdminPrivilege = "AllowAdminPrivilege";
const char* LoggedModules = "LoggedModules";
const char* LogLevel = "LogLevel";
const char* LoaderExecutable = "LoaderExecutable";
const char* LogPopupTestCase = "LogPopupTestCase";
} sect_core_keys;
@ -116,15 +112,6 @@ static struct {
const char* RenderResolution = "RenderResolution";
} sect_video_keys;
static const char* section_overlay = "overlay";
static struct {
const char* build_hash = "Build Hash";
const char* FPS = "FPS";
const char* hle_lle_stats = "HLE/LLE Stats";
const char* title_name = "Title Name";
const char* file_name = "File Name";
} sect_overlay_keys;
static const char* section_audio = "audio";
static struct {
const char* adapter = "adapter";
@ -144,7 +131,6 @@ static const char *section_input_general = "input-general";
static struct {
const char *mo_axis_range = "MouseAxisRange";
const char *mo_wheel_range = "MouseWheelRange";
const char *ignore_kbmo_unfocus = "IgnoreKbMoUnfocus";
} sect_input_general;
static const char* section_controller_dinput = "controller-dinput";
@ -155,8 +141,6 @@ static struct {
const char* type = "Type";
const char* device = "DeviceName";
const char* config = "ProfileName";
const char *top_slot = "TopSlot";
const char *bottom_slot = "BottomSlot";
} sect_input_port;
static const char* section_input_profiles = "input-profile-";
@ -343,8 +327,6 @@ bool Settings::LoadConfig()
m_gui.bIgnoreInvalidXbeSig = m_si.GetBoolValue(section_gui, sect_gui_keys.IgnoreInvalidXbeSig, /*Default=*/false);
m_gui.bIgnoreInvalidXbeSec = m_si.GetBoolValue(section_gui, sect_gui_keys.IgnoreInvalidXbeSec, /*Default=*/false);
m_gui.ConsoleTypeToggle = (EMU_CONSOLE_TYPE)m_si.GetLongValue(section_gui, sect_gui_keys.ConsoleTypeToggle, /*Default=*/EMU_CONSOLE_TYPE_AUTO);
// ==== GUI End =============
// ==== Core Begin ==========
@ -388,6 +370,8 @@ bool Settings::LoadConfig()
}
m_core.bLogPopupTestCase = m_si.GetBoolValue(section_core, sect_core_keys.LogPopupTestCase, /*Default=*/true);
m_core.bUseLoaderExec = m_si.GetBoolValue(section_core, sect_core_keys.LoaderExecutable, /*Default=*/true);
// ==== Core End ============
// Delete/update legacy configs from previous revisions
@ -467,70 +451,42 @@ bool Settings::LoadConfig()
m_input_general.MoAxisRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_axis_range, MO_AXIS_DEFAULT_RANGE);
m_input_general.MoWheelRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_wheel_range, MO_WHEEL_DEFAULT_RANGE);
m_input_general.IgnoreKbMoUnfocus = m_si.GetBoolValue(section_input_general, sect_input_general.ignore_kbmo_unfocus, true);
// ==== Input General End ==============
// ==== Input Port Begin ====
for (int port_num = 0; port_num < 4; port_num++) {
for (int slot = 0; slot < XBOX_CTRL_NUM_SLOTS; ++slot) {
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
int ret = m_si.GetLongValue(current_section.c_str(), sect_input_port.type, -2);
if (ret == -2) {
m_input_port[port_num].Type = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
m_input_port[port_num].SlotType[slot] = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
int ret = m_si.GetLongValue(current_section.c_str(), sect_input_port.type, -2);
if (ret == -2) {
continue;
}
m_input_port[port_num].Type = ret;
m_input_port[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input_port.device);
m_input_port[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input_port.config));
ret = m_si.GetLongValue(current_section.c_str(), slot == 0 ? sect_input_port.top_slot : sect_input_port.bottom_slot, -2);
if (ret == -2) {
continue;
}
m_input_port[port_num].SlotType[slot] = ret;
continue;
}
m_input_port[port_num].Type = ret;
m_input_port[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input_port.device);
m_input_port[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input_port.config));
}
// ==== Input Port End ==============
// ==== Input Profile Begin ====
std::array<std::vector<std::string>, to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)> control_names;
for (int device = 0; device < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX); device++) {
if (dev_num_buttons[device] == 0) {
continue;
}
const auto &lambda = [&control_names, &device](int num_buttons, const char *const ctrl_names[]) {
for (int i = 0; i < num_buttons; i++) {
char control_name[XBOX_BUTTON_NAME_LENGTH];
std::sprintf(control_name, sect_input_profiles.control, ctrl_names[i]);
control_names[device].push_back(control_name);
}
};
switch (device)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
lambda(dev_num_buttons[device], button_xbox_ctrl_names);
break;
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
lambda(dev_num_buttons[device], button_sbc_names);
break;
case to_underlying(XBOX_INPUT_DEVICE::LIGHTGUN):
lambda(dev_num_buttons[device], button_lightgun_names);
break;
for (int i = 0; i < dev_num_buttons[device]; i++) {
char control_name[30];
std::sprintf(control_name, sect_input_profiles.control, button_xbox_ctrl_names[i][0]);
control_names[device].push_back(control_name);
}
}
// TODO: add the control names of the other devices
index = 0;
while (true) {
std::string current_section = std::string(section_input_profiles) + std::to_string(index);
@ -551,16 +507,6 @@ bool Settings::LoadConfig()
// ==== Input Profile End ======
// ==== Overlay Begin =========
m_overlay.build_hash = m_si.GetBoolValue(section_overlay, sect_overlay_keys.build_hash, false);
m_overlay.fps = m_si.GetBoolValue(section_overlay, sect_overlay_keys.FPS, false);
m_overlay.hle_lle_stats = m_si.GetBoolValue(section_overlay, sect_overlay_keys.hle_lle_stats, false);
m_overlay.title_name = m_si.GetBoolValue(section_overlay, sect_overlay_keys.title_name, false);
m_overlay.file_name = m_si.GetBoolValue(section_overlay, sect_overlay_keys.file_name, false);
// ==== Overlay End ===========
return true;
}
@ -591,8 +537,6 @@ bool Settings::Save(std::string file_path)
m_si.SetBoolValue(section_gui, sect_gui_keys.IgnoreInvalidXbeSig, m_gui.bIgnoreInvalidXbeSig, nullptr, true);
m_si.SetBoolValue(section_gui, sect_gui_keys.IgnoreInvalidXbeSec, m_gui.bIgnoreInvalidXbeSec, nullptr, true);
m_si.SetLongValue(section_gui, sect_gui_keys.ConsoleTypeToggle, m_gui.ConsoleTypeToggle, nullptr, true, true);
// ==== GUI End =============
// ==== Core Begin ==========
@ -614,6 +558,8 @@ bool Settings::Save(std::string file_path)
}
m_si.SetBoolValue(section_core, sect_core_keys.LogPopupTestCase, m_core.bLogPopupTestCase, nullptr, true);
m_si.SetBoolValue(section_core, sect_core_keys.LoaderExecutable, m_core.bUseLoaderExec, nullptr, true);
// ==== Core End ============
// ==== Video Begin =========
@ -626,7 +572,6 @@ bool Settings::Save(std::string file_path)
m_si.SetBoolValue(section_video, sect_video_keys.FullScreen, m_video.bFullScreen, nullptr, true);
m_si.SetBoolValue(section_video, sect_video_keys.MaintainAspect, m_video.bMaintainAspect, nullptr, true);
m_si.SetLongValue(section_video, sect_video_keys.RenderResolution, m_video.renderScaleFactor, nullptr, false, true);
// ==== Video End ===========
// ==== Audio Begin =========
@ -656,7 +601,6 @@ bool Settings::Save(std::string file_path)
m_si.SetLongValue(section_input_general, sect_input_general.mo_axis_range, m_input_general.MoAxisRange, nullptr, false, true);
m_si.SetLongValue(section_input_general, sect_input_general.mo_wheel_range, m_input_general.MoWheelRange, nullptr, false, true);
m_si.SetBoolValue(section_input_general, sect_input_general.ignore_kbmo_unfocus, m_input_general.IgnoreKbMoUnfocus, nullptr, true);
// ==== Input General End =========
@ -669,8 +613,6 @@ bool Settings::Save(std::string file_path)
m_si.SetLongValue(current_section.c_str(), sect_input_port.type, m_input_port[port_num].Type, nullptr, false, true);
m_si.SetValue(current_section.c_str(), sect_input_port.device, m_input_port[port_num].DeviceName.c_str(), nullptr, true);
m_si.SetValue(current_section.c_str(), sect_input_port.config, quoted_prf_str.c_str(), nullptr, true);
m_si.SetLongValue(current_section.c_str(), sect_input_port.top_slot, m_input_port[port_num].SlotType[SLOT_TOP], nullptr, false, true);
m_si.SetLongValue(current_section.c_str(), sect_input_port.bottom_slot, m_input_port[port_num].SlotType[SLOT_BOTTOM], nullptr, false, true);
}
// ==== Input Port End ==============
@ -683,32 +625,15 @@ bool Settings::Save(std::string file_path)
continue;
}
const auto &lambda = [&control_names, &device](int num_buttons, const char *const ctrl_names[]) {
for (int i = 0; i < num_buttons; i++) {
char control_name[XBOX_BUTTON_NAME_LENGTH];
std::sprintf(control_name, sect_input_profiles.control, ctrl_names[i]);
control_names[device].push_back(control_name);
}
};
switch (device)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
lambda(dev_num_buttons[device], button_xbox_ctrl_names);
break;
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
lambda(dev_num_buttons[device], button_sbc_names);
break;
case to_underlying(XBOX_INPUT_DEVICE::LIGHTGUN):
lambda(dev_num_buttons[device], button_lightgun_names);
break;
for (int i = 0; i < dev_num_buttons[device]; i++) {
char control_name[30];
std::sprintf(control_name, sect_input_profiles.control, button_xbox_ctrl_names[i][0]);
control_names[device].push_back(control_name);
}
}
// TODO: add the control names of the other devices
int profile_num = 0;
for (int i = 0; i < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX); i++) {
size_t vec_size = m_input_profiles[i].size();
@ -744,16 +669,6 @@ bool Settings::Save(std::string file_path)
// ==== Input Profile End ======
// ==== Overlay Begin =======
m_si.SetBoolValue(section_overlay, sect_overlay_keys.build_hash, m_overlay.build_hash, nullptr, true);
m_si.SetBoolValue(section_overlay, sect_overlay_keys.FPS, m_overlay.fps, nullptr, true);
m_si.SetBoolValue(section_overlay, sect_overlay_keys.hle_lle_stats, m_overlay.hle_lle_stats, nullptr, true);
m_si.SetBoolValue(section_overlay, sect_overlay_keys.title_name, m_overlay.title_name, nullptr, true);
m_si.SetBoolValue(section_overlay, sect_overlay_keys.file_name, m_overlay.file_name, nullptr, true);
// ==== Overlay End =========
// ==== Hack Begin ==========
m_si.SetBoolValue(section_hack, sect_hack_keys.DisablePixelShaders, m_hacks.DisablePixelShaders, nullptr, true);
@ -791,7 +706,6 @@ void Settings::SyncToEmulator()
// register Video settings
g_EmuShared->SetVideoSettings(&m_video);
g_EmuShared->SetOverlaySettings(&m_overlay);
// register Audio settings
g_EmuShared->SetAudioSettings(&m_audio);
@ -799,43 +713,36 @@ void Settings::SyncToEmulator()
// register Network settings
g_EmuShared->SetNetworkSettings(&m_network);
// register xbox device input settings
// register input settings
for (int i = 0; i < 4; i++) {
g_EmuShared->SetInputDevTypeSettings(&m_input_port[i].Type, i);
g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].SlotType[SLOT_TOP], i, SLOT_TOP);
g_EmuShared->SetInputSlotTypeSettings(&m_input_port[i].SlotType[SLOT_BOTTOM], i, SLOT_BOTTOM);
if (m_input_port[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
g_EmuShared->SetInputDevNameSettings(m_input_port[i].DeviceName.c_str(), i);
if (m_input_port[i].Type < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)) {
auto it = std::find_if(m_input_profiles[m_input_port[i].Type].begin(),
m_input_profiles[m_input_port[i].Type].end(), [this, i](const auto &profile) {
if (profile.ProfileName == m_input_port[i].ProfileName) {
return true;
}
return false;
});
if (it != m_input_profiles[m_input_port[i].Type].end()) {
char controls_name[HIGHEST_NUM_BUTTONS][HOST_BUTTON_NAME_LENGTH];
for (int index = 0; index < dev_num_buttons[m_input_port[i].Type]; index++) {
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
auto it = std::find_if(m_input_profiles[m_input_port[i].Type].begin(),
m_input_profiles[m_input_port[i].Type].end(), [this, i](const auto& profile) {
if (profile.ProfileName == m_input_port[i].ProfileName) {
return true;
}
g_EmuShared->SetInputBindingsSettings(controls_name, dev_num_buttons[m_input_port[i].Type], i);
return false;
});
if (it != m_input_profiles[m_input_port[i].Type].end()) {
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
for (int index = 0; index < dev_num_buttons[m_input_port[i].Type]; index++) {
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
}
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, i);
}
}
}
// register Input general settings
g_EmuShared->SetInputGeneralSettings(&m_input_general);
g_EmuShared->SetInputMoAxisSettings(m_input_general.MoAxisRange);
g_EmuShared->SetInputMoWheelSettings(m_input_general.MoWheelRange);
// register Hacks settings
g_EmuShared->SetHackSettings(&m_hacks);
// register data location setting
g_EmuShared->SetDataLocation(GetDataLocation().c_str());
// reset title mount path
g_EmuShared->SetTitleMountPath("");
g_EmuShared->SetStorageLocation(GetDataLocation().c_str());
}
void verifyDebugFilePath(DebugMode& debug_mode, std::string& file_path)
@ -1014,9 +921,12 @@ void Settings::RemoveLegacyConfigs(unsigned int CurrentRevision)
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
std::string device_name = m_si.GetValue(current_section.c_str(), sect_input_port.device, "");
if (device_name.ends_with(kb_str)) {
device_name += "Mouse";
m_si.SetValue(current_section.c_str(), sect_input_port.device, device_name.c_str(), nullptr, true);
// NOTE: with C++20, this can be simplified by simply calling device_name.ends_with()
if (device_name.length() >= kb_str.length()) {
if (device_name.compare(device_name.length() - kb_str.length(), kb_str.length(), kb_str) == 0) {
device_name += "Mouse";
m_si.SetValue(current_section.c_str(), sect_input_port.device, device_name.c_str(), nullptr, true);
}
}
}
@ -1041,9 +951,4 @@ void Settings::RemoveLegacyConfigs(unsigned int CurrentRevision)
if(CurrentRevision < 9) {
m_si.Delete(section_video, "HardwareYUV", true);
}
// see settings_version for details.
if(false && CurrentRevision < 10) {
m_si.Delete(section_core, "LoaderExecutable", true);
}
}

View File

@ -26,15 +26,14 @@
// ******************************************************************
#ifndef SETTINGS_HPP
#define SETTINGS_HPP
#include "Cxbx.h"
#include "SimpleIni.h"
#include "common\input\InputManager.h"
#include "input\InputDevice.h"
#include "common\util\CxbxUtil.h"
#include <string>
#include <array>
#include "core/common/imgui/settings.h"
extern std::string g_exec_filepath;
// Individual library version
@ -46,14 +45,6 @@ extern uint16_t g_LibVersion_DSOUND;
"Invalid "#type" size, please verify structure is align, not adding new member, or is using placeholder reserves." \
" Otherwise, please perform versioning upgrade and update "#type" sizeof check."
// Toggle emulation console mode.
typedef enum _EMU_CONSOLE_TYPE {
EMU_CONSOLE_TYPE_AUTO = 0,
EMU_CONSOLE_TYPE_RETAIL = 1,
EMU_CONSOLE_TYPE_DEVKIT = 2,
EMU_CONSOLE_TYPE_CHIHIRO = 3,
} EMU_CONSOLE_TYPE;
// Cxbx-Reloaded's data storage location.
typedef enum _CXBX_DATA {
CXBX_DATA_INVALID = -1,
@ -65,7 +56,7 @@ typedef enum _CXBX_DATA {
// ******************************************************************
// * Define number of integers required to store logging settings
// ******************************************************************
#define NUM_INTEGERS_LOG 3
#define NUM_INTEGERS_LOG 2
enum {
LLE_NONE = 0,
@ -99,7 +90,6 @@ public:
std::string szCustomLocation = "";
bool bIgnoreInvalidXbeSig;
bool bIgnoreInvalidXbeSec;
unsigned int ConsoleTypeToggle;
} m_gui;
// Core settings
@ -108,16 +98,16 @@ public:
unsigned int FlagsLLE;
DebugMode KrnlDebugMode;
char szKrnlDebug[MAX_PATH] = "";
char szStorageLocation[xbox::max_path] = "";
char szStorageLocation[MAX_PATH] = "";
unsigned int LoggedModules[NUM_INTEGERS_LOG];
int LogLevel = 1;
bool bUnused_WasUseLoaderExec;
bool bUseLoaderExec;
bool allowAdminPrivilege;
bool bLogPopupTestCase;
bool Reserved4 = 0;
int Reserved99[10] = { 0 };
} m_core;
static_assert(sizeof(s_core) == 0x250, assert_check_shared_memory(s_core));
static_assert(sizeof(s_core) == 0x24C, assert_check_shared_memory(s_core));
// Video settings
struct s_video {
@ -144,18 +134,14 @@ public:
} m_audio;
static_assert(sizeof(s_audio) == 0x4C, assert_check_shared_memory(s_audio));
// Input general settings
struct s_input_general {
long MoAxisRange;
long MoWheelRange;
bool IgnoreKbMoUnfocus;
bool Reserved1[3];
} m_input_general;
static_assert(sizeof(s_input_general) == 0xC, assert_check_shared_memory(s_input_general));
};
s_input_general m_input_general;
struct s_input_port {
int Type;
int SlotType[XBOX_CTRL_NUM_SLOTS];
std::string DeviceName;
std::string ProfileName;
};
@ -192,8 +178,6 @@ public:
} m_hacks;
static_assert(sizeof(s_hack) == 0x28, assert_check_shared_memory(s_hack));
overlay_settings m_overlay;
private:
void RemoveLegacyConfigs(unsigned int CurrentRevision);
std::string m_file_path = "";

View File

@ -25,164 +25,148 @@
// *
// ******************************************************************
#include <core\kernel\exports\xboxkrnl.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include <thread>
#include <vector>
#include <mutex>
#include <array>
#include "Timer.h"
#include "common\util\CxbxUtil.h"
#include "core\kernel\support\EmuFS.h"
#include "core\kernel\exports\EmuKrnlPs.hpp"
#include "core\kernel\exports\EmuKrnl.h"
#include "devices\Xbox.h"
#include "devices\usb\OHCI.h"
#include "core\hle\DSOUND\DirectSound\DirectSoundGlobal.hpp"
#include "core\kernel\init\CxbxKrnl.h"
#ifdef __linux__
#include <time.h>
#endif
static std::atomic_uint64_t last_qpc; // last time when QPC was called
static std::atomic_uint64_t exec_time; // total execution time in us since the emulation started
static uint64_t pit_last; // last time when the pit time was updated
static uint64_t pit_last_qpc; // last QPC time of the pit
// The frequency of the high resolution clock of the host, and the start time
int64_t HostQPCFrequency, HostQPCStartTime;
// Virtual clocks will probably become useful once LLE CPU is implemented, but for now we don't need them.
// See the QEMUClockType QEMU_CLOCK_VIRTUAL of XQEMU for more info.
#define CLOCK_REALTIME 0
//#define CLOCK_VIRTUALTIME 1
void timer_init()
// Vector storing all the timers created
static std::vector<TimerObject*> TimerList;
// The frequency of the high resolution clock of the host
uint64_t HostClockFrequency;
// Lock to acquire when accessing TimerList
std::mutex TimerMtx;
// Returns the current time of the timer
uint64_t GetTime_NS(TimerObject* Timer)
{
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&HostQPCFrequency));
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&HostQPCStartTime));
pit_last_qpc = last_qpc = HostQPCStartTime;
pit_last = get_now();
// Synchronize xbox system time with host time
LARGE_INTEGER HostSystemTime;
GetSystemTimeAsFileTime((LPFILETIME)&HostSystemTime);
xbox::KeSystemTime.High2Time = HostSystemTime.u.HighPart;
xbox::KeSystemTime.LowPart = HostSystemTime.u.LowPart;
xbox::KeSystemTime.High1Time = HostSystemTime.u.HighPart;
#ifdef _WIN32
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
uint64_t Ret = Muldiv64(li.QuadPart, SCALE_S_IN_NS, (uint32_t)HostClockFrequency);
#elif __linux__
static struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
uint64_t Ret = Muldiv64(ts.tv_sec, SCALE_S_IN_NS, 1) + ts.tv_nsec;
#else
#error "Unsupported OS"
#endif
return Ret;
}
// More precise sleep, but with increased CPU usage
void SleepPrecise(std::chrono::steady_clock::time_point targetTime)
// Calculates the next expire time of the timer
static inline uint64_t GetNextExpireTime(TimerObject* Timer)
{
using namespace std::chrono;
// If we don't need to wait, return right away
// TODO use waitable timers?
// TODO fetch the timer resolution to determine the sleep threshold?
// TODO adaptive wait? https://blat-blatnik.github.io/computerBear/making-accurate-sleep-function/
// Try to sleep for as much of the wait as we can
// to save CPU usage / power
// We expect sleep to overshoot, so give ourselves some extra time
// Note currently we ask Windows to give us 1ms timer resolution
constexpr auto sleepThreshold = 2ms; // Minimum remaining time before we attempt to use sleep
auto sleepFor = (targetTime - sleepThreshold) - steady_clock::now();
auto sleepMs = duration_cast<milliseconds>(sleepFor).count();
// Sleep if required
if (sleepMs >= 0) {
Sleep((DWORD)sleepMs);
}
// Spin wait
while (steady_clock::now() < targetTime) {
;
}
return GetTime_NS(Timer) + Timer->ExpireTime_MS.load();
}
// NOTE: the pit device is not implemented right now, so we put this here
static uint64_t pit_next(uint64_t now)
// Deallocates the memory of the timer
void Timer_Destroy(TimerObject* Timer)
{
constexpr uint64_t pit_period = 1000;
uint64_t next = pit_last + pit_period;
if (now >= next) {
xbox::KiClockIsr(now - pit_last);
pit_last = get_now();
return pit_period;
}
return pit_last + pit_period - now; // time remaining until next clock interrupt
}
static void update_non_periodic_events()
{
// update dsound
dsound_worker();
// check for hw interrupts
for (int i = 0; i < MAX_BUS_INTERRUPT_LEVEL; i++) {
// If the interrupt is pending and connected, process it
if (g_bEnableAllInterrupts && HalSystemInterrupts[i].IsPending() && EmuInterruptList[i] && EmuInterruptList[i]->Connected) {
HalSystemInterrupts[i].Trigger(EmuInterruptList[i]);
unsigned int index, i;
std::lock_guard<std::mutex>lock(TimerMtx);
index = TimerList.size();
for (i = 0; i < index; i++) {
if (Timer == TimerList[i]) {
index = i;
}
}
assert(index != TimerList.size());
delete Timer;
TimerList.erase(TimerList.begin() + index);
}
uint64_t get_now()
// Thread that runs the timer
void ClockThread(TimerObject* Timer)
{
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
uint64_t elapsed_us = now.QuadPart - last_qpc;
last_qpc = now.QuadPart;
elapsed_us *= 1000000;
elapsed_us /= HostQPCFrequency;
exec_time += elapsed_us;
return exec_time;
}
uint64_t NewExpireTime;
static uint64_t get_next(uint64_t now)
{
std::array<uint64_t, 5> next = {
pit_next(now),
g_NV2A->vblank_next(now),
g_NV2A->ptimer_next(now),
g_USB0->m_HostController->OHCI_next(now),
dsound_next(now)
};
return *std::min_element(next.begin(), next.end());
}
xbox::void_xt NTAPI system_events(xbox::PVOID arg)
{
// Testing shows that, if this thread has the same priority of the other xbox threads, it can take tens, even hundreds of ms to complete a single loop.
// So we increase its priority to above normal, so that it scheduled more often
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
// Always run this thread at dpc level to prevent it from ever executing APCs/DPCs
xbox::KeRaiseIrqlToDpcLevel();
if (!Timer->Name.empty()) {
CxbxSetThreadName(Timer->Name.c_str());
}
if (Timer->CpuAffinity != nullptr) {
InitXboxThread(*Timer->CpuAffinity);
}
NewExpireTime = GetNextExpireTime(Timer);
while (true) {
const uint64_t last_time = get_now();
const uint64_t nearest_next = get_next(last_time);
while (true) {
update_non_periodic_events();
uint64_t elapsed_us = get_now() - last_time;
if (elapsed_us >= nearest_next) {
break;
if (GetTime_NS(Timer) > NewExpireTime) {
if (Timer->Exit.load()) {
Timer_Destroy(Timer);
return;
}
std::this_thread::yield();
Timer->Callback(Timer->Opaque);
NewExpireTime = GetNextExpireTime(Timer);
}
Sleep(1); // prevent burning the cpu
}
}
int64_t Timer_GetScaledPerformanceCounter(int64_t Period)
// Changes the expire time of a timer
void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms)
{
LARGE_INTEGER currentQPC;
QueryPerformanceCounter(&currentQPC);
// Scale frequency with overflow avoidance, like in std::chrono
// https://github.com/microsoft/STL/blob/6d2f8b0ed88ea6cba26cc2151f47f678442c1663/stl/inc/chrono#L703
const int64_t currentTime = currentQPC.QuadPart - HostQPCStartTime;
const int64_t whole = (currentTime / HostQPCFrequency) * Period;
const int64_t part = (currentTime % HostQPCFrequency) * Period / HostQPCFrequency;
return whole + part;
Timer->ExpireTime_MS.store(Expire_ms);
}
// Destroys the timer
void Timer_Exit(TimerObject* Timer)
{
Timer->Exit.store(true);
}
// Allocates the memory for the timer object
TimerObject* Timer_Create(TimerCB Callback, void* Arg, std::string Name, unsigned long* Affinity)
{
std::lock_guard<std::mutex>lock(TimerMtx);
TimerObject* pTimer = new TimerObject;
pTimer->Type = CLOCK_REALTIME;
pTimer->Callback = Callback;
pTimer->ExpireTime_MS.store(0);
pTimer->Exit.store(false);
pTimer->Opaque = Arg;
Name.empty() ? pTimer->Name = "Unnamed thread" : pTimer->Name = Name;
pTimer->CpuAffinity = Affinity;
TimerList.emplace_back(pTimer);
return pTimer;
}
// Starts the timer
// Expire_MS must be expressed in NS
void Timer_Start(TimerObject* Timer, uint64_t Expire_MS)
{
Timer->ExpireTime_MS.store(Expire_MS);
std::thread(ClockThread, Timer).detach();
}
// Retrives the frequency of the high resolution clock of the host
void Timer_Init()
{
#ifdef _WIN32
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
HostClockFrequency = freq.QuadPart;
#elif __linux__
ClockFrequency = 0;
#else
#error "Unsupported OS"
#endif
}

View File

@ -29,7 +29,6 @@
#define TIMER_H
#include <atomic>
#include <mutex>
#define SCALE_S_IN_NS 1000000000
#define SCALE_MS_IN_NS 1000000
@ -40,12 +39,28 @@
#define SCALE_MS_IN_US 1000
#define SCALE_US_IN_US 1
/* typedef of the timer object and the callback function */
typedef void(*TimerCB)(void*);
typedef struct _TimerObject
{
int Type; // timer type
std::atomic_uint64_t ExpireTime_MS; // when the timer expires (ms)
std::atomic_bool Exit; // indicates that the timer should be destroyed
TimerCB Callback; // function to call when the timer expires
void* Opaque; // opaque argument to pass to the callback
std::string Name; // the name of the timer thread (if any)
unsigned long* CpuAffinity; // the cpu affinity of the timer thread (if any)
}
TimerObject;
extern int64_t HostQPCFrequency;
extern uint64_t HostClockFrequency;
void timer_init();
uint64_t get_now();
int64_t Timer_GetScaledPerformanceCounter(int64_t Period);
void SleepPrecise(std::chrono::steady_clock::time_point targetTime);
/* Timer exported functions */
TimerObject* Timer_Create(TimerCB Callback, void* Arg, std::string Name, unsigned long* Affinity);
void Timer_Start(TimerObject* Timer, uint64_t Expire_MS);
void Timer_Exit(TimerObject* Timer);
void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms);
uint64_t GetTime_NS(TimerObject* Timer);
void Timer_Init();
#endif

View File

@ -1,169 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx-Reloaded project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * All rights reserved
// *
// ******************************************************************
#define LOG_PREFIX CXBXR_MODULE::FILE
#ifdef CXBXR_EMU
#include "core/kernel/support/EmuFile.h" // For g_io_mu_metadata
#include "common/Timer.h" // For Timer_Shutdown
#include "core/common/video/RenderBase.hpp" // For g_renderbase
#include "core/kernel/memory-manager/VMManager.h"
extern void CxbxrKrnlSuspendThreads();
#endif
#include "cxbxr.hpp"
#include "EmuShared.h"
#include "Settings.hpp"
#include "Logging.h"
#include "win32/WineEnv.h"
#include "Settings.hpp"
volatile bool g_bPrintfOn = true;
bool CreateSettings()
{
g_Settings = new Settings();
if (g_Settings == nullptr) {
PopupError(nullptr, szSettings_alloc_error);
return false;
}
if (!g_Settings->Init()) {
return false;
}
log_get_settings();
return true;
}
bool HandleFirstLaunch()
{
bool bFirstLaunch;
g_EmuShared->GetIsFirstLaunch(&bFirstLaunch);
/* check if process is launch with elevated access then prompt for continue on or not. */
if (!bFirstLaunch) {
if (!CreateSettings()) {
return false;
}
// Wine will always run programs as administrator by default, it can be safely disregard.
// Since Wine doesn't use root permission. Unless user is running Wine as root.
bool bElevated = CxbxrIsElevated();
if (bElevated && !isWineEnv() && !g_Settings->m_core.allowAdminPrivilege) {
PopupReturn ret = PopupWarningEx(nullptr, PopupButtons::YesNo, PopupReturn::No,
"Cxbx-Reloaded has detected that it has been launched with Administrator rights.\n"
"\nThis is dangerous, as a maliciously modified Xbox titles could take control of your system.\n"
"\nAre you sure you want to continue?");
if (ret != PopupReturn::Yes) {
return false;
}
}
g_EmuShared->SetIsFirstLaunch(true);
}
return true;
}
[[noreturn]] void CxbxrShutDown(bool is_reboot)
{
if (!is_reboot) {
// Clear all kernel boot flags. These (together with the shared memory) persist until Cxbx-Reloaded is closed otherwise.
int BootFlags = 0;
g_EmuShared->SetBootFlags(&BootFlags);
}
// NOTE: This causes a hang when exiting while NV2A is processing
// This is okay for now: It won't leak memory or resources since TerminateProcess will free everything
// delete g_NV2A; // TODO : g_pXbox
// Shutdown the input device manager
g_InputDeviceManager.Shutdown();
#ifdef CXBXR_EMU
// NOTE: this code causes freezes/crashes at shutdown, so avoid for now
// This is very important process to prevent false positive report and allow IDEs to continue debug multiple reboots.
//CxbxrKrnlSuspendThreads();
if (g_io_mu_metadata) {
delete g_io_mu_metadata;
g_io_mu_metadata = nullptr;
}
// Shutdown the render manager
if (g_renderbase != nullptr) {
g_renderbase->Shutdown();
g_renderbase = nullptr;
}
// NOTE: Require to be after g_renderbase's shutdown process.
// NOTE: Must be last step of shutdown process and before CxbxUnlockFilePath call!
// Shutdown the memory manager
g_VMManager.Shutdown();
CxbxrUnlockFilePath();
if (CxbxKrnl_hEmuParent != NULL && !is_reboot) {
SendMessage(CxbxKrnl_hEmuParent, WM_PARENTNOTIFY, WM_DESTROY, 0);
}
#endif
EmuShared::Cleanup();
TerminateProcess(GetCurrentProcess(), 0);
}
[[noreturn]] void CxbxrAbortEx(CXBXR_MODULE cxbxr_module, const char* szErrorMessage, ...)
{
// print out error message (if exists)
if (szErrorMessage != NULL)
{
char szBuffer2[1024];
va_list argp;
va_start(argp, szErrorMessage);
vsprintf(szBuffer2, szErrorMessage, argp);
va_end(argp);
(void)PopupCustomEx(nullptr, cxbxr_module, LOG_LEVEL::FATAL, PopupIcon::Error, PopupButtons::Ok, PopupReturn::Ok, "Received Fatal Message:\n\n* %s\n", szBuffer2); // Will also EmuLogEx
}
EmuLogInit(LOG_LEVEL::INFO, "MAIN: Terminating Process");
fflush(stdout);
// cleanup debug output
{
FreeConsole();
char buffer[16];
if (GetConsoleTitle(buffer, 16) != NULL)
freopen("nul", "w", stdout);
}
CxbxrShutDown();
}

View File

@ -1,58 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx-Reloaded project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include <string>
#include <optional>
#include "Logging.h"
bool CreateSettings();
bool HandleFirstLaunch();
// TODO: Eventually, we should remove this function to start using std::filesystem::path method for all host paths.
void CxbxResolveHostToFullPath(std::string& file_path, std::string_view finish_error_sentence);
// Loads a keys.bin file as generated by dump-xbox
// See https://github.com/JayFoxRox/xqemu-tools/blob/master/dump-xbox.c
void LoadXboxKeys();
bool CxbxrLockFilePath();
void CxbxrUnlockFilePath();
// Hybrid functions depending on specific platforms
bool CxbxrIsElevated();
std::optional<std::string> CxbxrExec(bool useDebugger, void** hProcess, bool requestHandleProcess);
/*! cleanup emulation */
[[noreturn]] void CxbxrAbortEx(CXBXR_MODULE cxbxr_module, const char* szErrorMessage, ...);
#define CxbxrAbort(fmt, ...) CxbxrAbortEx(LOG_PREFIX, fmt, ##__VA_ARGS__)
/*! terminate gracefully the emulation */
[[noreturn]] void CxbxrShutDown(bool is_reboot = false);

View File

@ -27,7 +27,7 @@
#include "Button.h"
#include "InputWindow.h"
#include "layout_xbox_device.h" // TODO: Needs a better fix for custom input device support.
#include "layout_xbox_controller.h" // TODO: Needs a better fix for custom input device support.
#include "gui/resource/ResCxbx.h"
@ -51,41 +51,27 @@ void Button::GetText(char* const text, size_t size) const
SendMessage(m_button_hwnd, WM_GETTEXT, size, reinterpret_cast<LPARAM>(text));
}
void Button::AddTooltip(HWND hwnd, HWND tooltip_hwnd, std::string_view text) const
std::string Button::GetName(int api, int idx) const
{
assert((hwnd != NULL) && (tooltip_hwnd != NULL));
std::string tooltip_text(text);
TOOLINFO tool = { 0 };
tool.cbSize = sizeof(tool);
tool.hwnd = hwnd;
tool.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
tool.uId = reinterpret_cast<UINT_PTR>(m_button_hwnd);
tool.lpszText = tooltip_text.data();
SendMessage(tooltip_hwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&tool));
assert(api == XINPUT_DEFAULT || api == DINPUT_DEFAULT);
return button_xbox_ctrl_names[idx][api];
}
LRESULT CALLBACK ButtonDukeSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
LRESULT CALLBACK ButtonSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
// Remove the window subclass when this window is destroyed
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, ButtonDukeSubclassProc, uIdSubclass);
RemoveWindowSubclass(hWnd, ButtonSubclassProc, uIdSubclass);
}
break;
case WM_RBUTTONDOWN: {
Button *button = reinterpret_cast<Button *>(dwRefData);
if (wParam & MK_SHIFT) {
static_cast<DukeInputWindow *>(button->GetWnd())->SwapMoCursorAxis(button);
}
else if (!(wParam & ~MK_RBUTTON)) {
button->ClearText();
static_cast<DukeInputWindow *>(button->GetWnd())->UpdateProfile(std::string(), BUTTON_CLEAR);
if (button->GetId() == IDC_SET_MOTOR) {
static_cast<DukeInputWindow *>(button->GetWnd())->UpdateProfile(std::string(), RUMBLE_CLEAR);
}
reinterpret_cast<Button*>(dwRefData)->ClearText();
g_InputWindow->UpdateProfile(std::string(), BUTTON_CLEAR);
if (reinterpret_cast<Button*>(dwRefData)->GetId() == IDC_SET_MOTOR) {
g_InputWindow->UpdateProfile(std::string(), RUMBLE_CLEAR);
}
}
break;
@ -94,47 +80,3 @@ LRESULT CALLBACK ButtonDukeSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPA
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK ButtonSbcSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
// Remove the window subclass when this window is destroyed
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, ButtonSbcSubclassProc, uIdSubclass);
}
break;
case WM_RBUTTONDOWN: {
Button *button = reinterpret_cast<Button *>(dwRefData);
button->ClearText();
static_cast<SbcInputWindow *>(button->GetWnd())->UpdateProfile(std::string(), BUTTON_CLEAR);
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK ButtonLightgunSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
// Remove the window subclass when this window is destroyed
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, ButtonLightgunSubclassProc, uIdSubclass);
}
break;
case WM_RBUTTONDOWN: {
Button *button = reinterpret_cast<Button *>(dwRefData);
button->ClearText();
static_cast<LightgunInputWindow *>(button->GetWnd())->UpdateProfile(std::string(), BUTTON_CLEAR);
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

View File

@ -31,36 +31,27 @@
#include <Commctrl.h>
#include <string>
#define LIGHTGUN_NUM_BUTTONS 17
#define XBOX_CTRL_NUM_BUTTONS 25
#define SBC_NUM_BUTTONS 56
#define HIGHEST_NUM_BUTTONS SBC_NUM_BUTTONS
#define XBOX_BUTTON_NAME_LENGTH 30
#define HOST_BUTTON_NAME_LENGTH 30
/* Represents the gui buttons of the xbox device currently being configured */
class Button
{
public:
Button(int id, int index, HWND hwnd, void *wnd) : m_id(id), m_index(index), m_button_hwnd(GetDlgItem(hwnd, m_id)), m_wnd(wnd) {};
Button(int id, int index, HWND hwnd) : m_id(id), m_index(index), m_button_hwnd(GetDlgItem(hwnd, m_id)) {};
void EnableButton(bool enable) const;
void UpdateText(const char* text) const;
void ClearText() const;
void GetText(char* const text, size_t size) const;
std::string GetName(int api, int idx) const;
int GetId() const { return m_id; }
int GetIndex() const { return m_index; }
void *GetWnd() const { return m_wnd; }
void AddTooltip(HWND hwnd, HWND tooltip_hwnd, std::string_view text) const;
private:
int m_id;
int m_index;
HWND m_button_hwnd;
void *m_wnd;
};
LRESULT CALLBACK ButtonDukeSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
LRESULT CALLBACK ButtonSbcSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
LRESULT CALLBACK ButtonLightgunSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
LRESULT CALLBACK ButtonSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

View File

@ -37,7 +37,6 @@
#include "DInputKeyboardMouse.h"
#include "InputManager.h"
#include "core\kernel\support\Emu.h"
#include <algorithm>
// Unfortunately, sdl doesn't seem to be able to capture keyboard/mouse input from windows it didn't create (we currently use
// win32 for that). So unless we create sdl windows, we will have to keep dinput around to handle keyboard/mouse input.
@ -138,12 +137,6 @@ namespace DInput
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_neg : mo_axis_range_neg));
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_pos : mo_axis_range_pos));
}
// mouse cursor
AddInput(new Cursor(0, m_state_in.cursor.x, -1.0));
AddInput(new Cursor(0, m_state_in.cursor.x, 1.0));
AddInput(new Cursor(1, m_state_in.cursor.y, -1.0));
AddInput(new Cursor(1, m_state_in.cursor.y, 1.0));
}
KeyboardMouse::~KeyboardMouse()
@ -159,7 +152,7 @@ namespace DInput
bool KeyboardMouse::UpdateInput()
{
if (static_cast<uint8_t>(mo_leave_wnd) & static_cast<uint8_t>(IgnoreKbMoUnfocus)) {
if (mo_leave_wnd) {
std::memset(&m_state_in, 0, sizeof(m_state_in));
return true;
}
@ -185,7 +178,6 @@ namespace DInput
}
std::memcpy(m_state_in.mouse.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.mouse.rgbButtons));
UpdateCursorPosition();
return true;
}
@ -193,21 +185,6 @@ namespace DInput
return false;
}
void KeyboardMouse::UpdateCursorPosition()
{
POINT point = {};
GetCursorPos(&point);
ScreenToClient(m_hwnd, &point);
RECT rect;
GetClientRect(m_hwnd, &rect);
const auto width = std::max(rect.right - rect.left, 1l);
const auto height = std::max(rect.bottom - rect.top, 1l);
// Convert the window client coordinates to normalized device coordinates
m_state_in.cursor.x = ((2 * static_cast<ControlState>(point.x)) / width) - 1;
m_state_in.cursor.y = ((-2 * static_cast<ControlState>(point.y)) / height) + 1;
}
std::string KeyboardMouse::GetDeviceName() const
{
return "KeyboardMouse";
@ -236,14 +213,6 @@ namespace DInput
return tmpstr;
}
std::string KeyboardMouse::Cursor::GetName() const
{
static char tmpstr[] = "Cursor ..";
tmpstr[7] = (char)('X' + m_index);
tmpstr[8] = (m_range == 1.0 ? '+' : '-');
return tmpstr;
}
ControlState KeyboardMouse::Key::GetState() const
{
return (m_key != 0);
@ -258,9 +227,4 @@ namespace DInput
{
return std::clamp(ControlState(m_axis) / m_range, 0.0, 1.0);
}
ControlState KeyboardMouse::Cursor::GetState() const
{
return std::max(0.0, m_cursor / m_range);
}
}

View File

@ -36,7 +36,6 @@ namespace DInput
{
inline bool bKbMoEnumerated = false;
inline bool mo_leave_wnd = false;
inline bool IgnoreKbMoUnfocus = true;
inline LONG mo_axis_range_pos = 0;
inline LONG mo_axis_range_neg = 0;
inline LONG mo_wheel_range_pos = 0;
@ -52,7 +51,6 @@ namespace DInput
std::string GetDeviceName() const override;
std::string GetAPI() const override;
bool UpdateInput() override;
void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
private:
@ -80,7 +78,6 @@ namespace DInput
const uint8_t m_index;
};
// gives mouse input based on relative motion
class Axis : public Input
{
public:
@ -94,37 +91,14 @@ namespace DInput
const uint8_t m_index;
};
// gives mouse input based on cursor position relative to the rendering window
class Cursor : public Input
{
public:
Cursor(uint8_t index, const ControlState &cursor, const ControlState range)
: m_cursor(cursor), m_index(index), m_range(range) {}
std::string GetName() const override;
ControlState GetState() const override;
bool IsDetectable() const override { return false; }
private:
const ControlState &m_cursor;
const ControlState m_range;
const uint8_t m_index;
};
struct State
{
BYTE keyboard[256];
DIMOUSESTATE2 mouse;
struct
{
ControlState x, y;
} cursor;
};
void UpdateCursorPosition();
const LPDIRECTINPUTDEVICE8 m_kb_device;
const LPDIRECTINPUTDEVICE8 m_mo_device;
State m_state_in;
HWND m_hwnd;
};
}

View File

@ -25,64 +25,35 @@
// *
// ******************************************************************
#include <algorithm>
#include "Button.h"
#include"Button.h"
#include "InputManager.h"
#include "layout_xbox_device.h"
#include "layout_xbox_controller.h"
#include "gui/resource/ResCxbx.h"
static const char *tooltip_text_toggle = "Left-click: start input detection\nRight-click: clear binding\nShift + right-click: toggle mouse input mode";
static const char *tooltip_text_no_toggle = "Left-click: start input detection\nRight-click: clear binding";
EmuDevice::EmuDevice(int type, HWND hwnd, void *wnd)
EmuDevice::EmuDevice(int type, HWND hwnd)
{
m_hwnd = hwnd;
CreateTooltipWindow();
switch (type)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK): {
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
m_hwnd = hwnd;
for (size_t i = 0; i < ARRAY_SIZE(button_xbox_ctrl_id); i++) {
m_buttons.push_back(new Button(button_xbox_ctrl_id[i], i, hwnd, wnd));
m_buttons.back()->AddTooltip(m_hwnd, m_tooltip_hwnd, tooltip_text_toggle);
m_buttons.push_back(new Button(button_xbox_ctrl_id[i], i, hwnd));
// Install the subclass for the button control
SetWindowSubclass(GetDlgItem(hwnd, button_xbox_ctrl_id[i]), ButtonDukeSubclassProc, 0, reinterpret_cast<DWORD_PTR>(m_buttons[i]));
}
}
break;
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
for (size_t i = 0; i < ARRAY_SIZE(button_sbc_id); i++) {
m_buttons.push_back(new Button(button_sbc_id[i], i, hwnd, wnd));
m_buttons.back()->AddTooltip(m_hwnd, m_tooltip_hwnd, tooltip_text_no_toggle);
// Install the subclass for the button control
SetWindowSubclass(GetDlgItem(hwnd, button_sbc_id[i]), ButtonSbcSubclassProc, 0, reinterpret_cast<DWORD_PTR>(m_buttons[i]));
}
}
break;
case to_underlying(XBOX_INPUT_DEVICE::LIGHTGUN): {
for (size_t i = 0; i < ARRAY_SIZE(button_lightgun_id); i++) {
m_buttons.push_back(new Button(button_lightgun_id[i], i, hwnd, wnd));
m_buttons.back()->AddTooltip(m_hwnd, m_tooltip_hwnd, tooltip_text_no_toggle);
// Install the subclass for the button control
SetWindowSubclass(GetDlgItem(hwnd, button_lightgun_id[i]), ButtonLightgunSubclassProc, 0, reinterpret_cast<DWORD_PTR>(m_buttons[i]));
SetWindowSubclass(GetDlgItem(hwnd, button_xbox_ctrl_id[i]), ButtonSubclassProc, 0, reinterpret_cast<DWORD_PTR>(m_buttons[i]));
}
}
break;
default:
break;
}
}
EmuDevice::~EmuDevice()
{
DestroyWindow(m_tooltip_hwnd);
for (auto button : m_buttons) {
delete button;
}
@ -105,11 +76,10 @@ Button* EmuDevice::FindButtonByIndex(int index)
return m_buttons[index];
}
template<size_t size>
void EmuDevice::BindDefault(const std::array<const char *, size> &arr)
void EmuDevice::BindDefault(int api)
{
std::for_each(m_buttons.begin(), m_buttons.end(), [&arr](const auto button) {
button->UpdateText(arr[button->GetIndex()]);
std::for_each(m_buttons.begin(), m_buttons.end(), [&api](const auto button) {
button->UpdateText(button->GetName(api, button->GetIndex()).c_str());
});
}
@ -119,20 +89,3 @@ void EmuDevice::ClearButtons()
button->ClearText();
});
}
void EmuDevice::CreateTooltipWindow()
{
m_tooltip_hwnd = CreateWindow(TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
m_hwnd, NULL,
GetModuleHandle(NULL), NULL);
SendMessage(m_tooltip_hwnd, TTM_ACTIVATE, TRUE, 0);
SendMessage(m_tooltip_hwnd, TTM_SETMAXTIPWIDTH, 0, 500);
SendMessage(m_tooltip_hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, 15000);
}
template void EmuDevice::BindDefault(const std::array<const char*, XBOX_CTRL_NUM_BUTTONS>& arr);
template void EmuDevice::BindDefault(const std::array<const char *, LIGHTGUN_NUM_BUTTONS> &arr);

View File

@ -29,29 +29,21 @@
#include "Button.h"
#include "common\util\CxbxUtil.h"
#include <array>
/* Represents the guest device currently being configured in the gui */
class EmuDevice
{
public:
EmuDevice(int type, HWND hwnd, void *wnd);
EmuDevice(int type, HWND hwnd);
~EmuDevice();
Button* FindButtonById(int id);
Button* FindButtonByIndex(int index);
template<size_t size>
void BindDefault(const std::array<const char *, size> &arr);
void BindDefault(int api);
void ClearButtons();
private:
void CreateTooltipWindow();
std::vector<Button*> m_buttons;
HWND m_hwnd;
HWND m_tooltip_hwnd;
};
extern template void EmuDevice::BindDefault(const std::array<const char *, XBOX_CTRL_NUM_BUTTONS> &arr);
extern template void EmuDevice::BindDefault(const std::array<const char *, LIGHTGUN_NUM_BUTTONS> &arr);

View File

@ -33,10 +33,8 @@
// https://github.com/dolphin-emu/dolphin
#include "InputDevice.h"
#include "InputManager.h"
#include "common\util\CxbxUtil.h"
#include <algorithm>
#include <charconv>
std::string GetInputDeviceName(int dev_type)
@ -45,53 +43,46 @@ std::string GetInputDeviceName(int dev_type)
switch (dev_type)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE): {
str = "MS Gamepad Duke";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
str = "MS Gamepad S";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::LIGHTGUN):
str = "EMS TopGun II";
break;
case to_underlying(XBOX_INPUT_DEVICE::LIGHT_GUN): {
str = "Light gun";
}
break;
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL):
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL): {
str = "Steering wheel";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT): {
str = "Memory unit";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE):
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE): {
str = "IR dongle";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
str = "Steel battalion controller";
break;
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
str = "Arcade joystick";
break;
case to_underlying(XBOX_INPUT_DEVICE::HW_STEEL_BATTALION_CONTROLLER):
str = "Passthrough steel battalion controller";
break;
case to_underlying(XBOX_INPUT_DEVICE::HW_XBOX_CONTROLLER):
str = "Passthrough original xbox gamepad";
break;
}
break;
case to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID):
str = "None";
break;
case to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX):
case to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX): {
str = "Invalid";
break;
}
break;
default:
str = "Unknown";
@ -100,33 +91,6 @@ std::string GetInputDeviceName(int dev_type)
return str;
}
std::string PortUserFormat(std::string_view port)
{
int port_num, slot;
PortStr2Int(port, &port_num, &slot);
++port_num;
if (slot != PORT_INVALID) {
++slot;
return std::to_string(port_num) + "." + std::to_string(slot);
}
else {
return std::to_string(port_num);
}
}
void PortStr2Int(std::string_view port, int *port_num, int *slot)
{
*slot = PORT_INVALID;
auto ret = std::from_chars(port.data(), port.data() + port.size(), *port_num);
assert(ret.ec != std::errc::invalid_argument);
if (ret.ptr != port.data() + port.size()) {
++ret.ptr;
ret = std::from_chars(ret.ptr, port.data() + port.size(), *slot);
assert(ret.ec != std::errc::invalid_argument);
assert(ret.ptr == port.data() + port.size());
}
}
// Destructor, delete all inputs/outputs on device destruction
InputDevice::~InputDevice()
{
@ -167,31 +131,3 @@ const std::vector<InputDevice::IoControl*> InputDevice::GetIoControls()
});
return vec;
}
const auto InputDevice::FindPort(std::string_view Port) const
{
return std::find_if(m_XboxPort.begin(), m_XboxPort.end(), [Port](std::string_view CurrPort) {
if (CurrPort == Port) {
return true;
}
return false;
});
}
void InputDevice::SetPort2(std::string_view Port, bool Connect)
{
if (Connect) {
m_XboxPort.emplace_back(Port);
}
else {
const auto &it = FindPort(Port);
if (it != m_XboxPort.end()) {
m_XboxPort.erase(it);
}
}
}
bool InputDevice::GetPort(std::string_view Port) const
{
return FindPort(Port) != m_XboxPort.end() ? true : false;
}

View File

@ -36,6 +36,15 @@
#include <condition_variable>
#include "SDL.h"
#define PORT_INVALID -1
#define PORT_1 0
#define PORT_2 1
#define PORT_3 2
#define PORT_4 3
#define PORT_INC(port) ((port) + 1)
#define PORT_DEC(port) ((port) - 1)
#define DIRECTION_IN 0
#define DIRECTION_OUT 1
@ -49,16 +58,12 @@ typedef enum class _XBOX_INPUT_DEVICE : int {
DEVICE_INVALID = -1,
MS_CONTROLLER_DUKE,
MS_CONTROLLER_S,
LIGHTGUN,
LIGHT_GUN,
STEERING_WHEEL,
MEMORY_UNIT,
IR_DONGLE,
STEEL_BATTALION_CONTROLLER,
ARCADE_STICK,
DEVICE_MAX,
// Devices with the HW_ prefix (= hardware) indicate a real xbox device. Always add these after DEVICE_MAX
HW_STEEL_BATTALION_CONTROLLER,
HW_XBOX_CONTROLLER,
}
XBOX_INPUT_DEVICE;
@ -66,13 +71,11 @@ XBOX_INPUT_DEVICE;
inline bool g_bIsTrackingMoLeave = false;
inline bool g_bIsTrackingMoMove = false;
// Lookup array used to translate a gui port to an xbox usb port and vice versa
extern int Gui2XboxPortArray[4];
// Retrieves the printable name of a xid type
// Global function used to retrieve the printable name of a xid type
std::string GetInputDeviceName(int dev_type);
// Converts the port number in the user format
std::string PortUserFormat(std::string_view);
// Extracts port and slot number from a port formatted as a string
void PortStr2Int(std::string_view port, int *port_num, int *slot);
/* Abstract class which represents a host device usable for input/output */
class InputDevice
@ -90,7 +93,6 @@ public:
{
public:
virtual ControlState GetState() const = 0;
virtual bool IsDetectable() const { return true; };
};
class Output : public IoControl
@ -120,12 +122,9 @@ public:
// sets the ID of this device
void SetId(int ID) { m_ID = ID; }
// retrieves the port this device is attached to
bool GetPort(std::string_view Port) const;
bool GetPort(int Port) const { return m_XboxPort[Port]; }
// sets the port this device is attached to
// NOTE: using SetPort2 to avoid a collision with the SetPort macro provided by Windows headers
void SetPort2(std::string_view Port, bool Connect);
// retuns true if it is a libusb device, false otherwise
virtual bool IsLibusb() const { return false; };
void SetPort(int Port, bool Connect) { m_XboxPort[Port] = Connect; }
protected:
@ -133,8 +132,6 @@ protected:
void AddInput(Input* const In);
// adds an output control to the device
void AddOutput(Output* const Out);
// searches for a port
const auto FindPort(std::string_view Port) const;
// indicates that the device has new input data available
bool m_bDirty;
// lock for the bindings map
@ -142,32 +139,27 @@ protected:
public:
// retrieves the map of input bindings
const std::map<int, IoControl*> GetBindings(const std::string &Port) const {
const std::map<int, IoControl*> GetBindings() const {
std::lock_guard<std::mutex> lck(m_BindingsMtx);
return m_Bindings.find(Port)->second;
return m_Bindings;
}
// sets a pair in the map of the input bindings
void SetBindings(int XButton, IoControl* Control, const std::string &Port) {
void SetBindings(int XButton, IoControl* Control) {
std::lock_guard<std::mutex> lck(m_BindingsMtx);
m_Bindings[Port][XButton] = Control;
}
// clears all input bindings for the specified xbox port
void ClearBindings(const std::string &Port) {
std::lock_guard<std::mutex> lck(m_BindingsMtx);
m_Bindings[Port].clear();
m_Bindings[XButton] = Control;
}
private:
// arbitrary ID assigned to the device
// arbitrary ID assigned by to the device
int m_ID;
// all the input controls detected and usable on this device
std::vector<Input*> m_Inputs;
// all the output controls detected and usable on this device
std::vector<Output*> m_Outputs;
// xbox port(s) this device is attached to
std::vector<std::string> m_XboxPort;
// per xbox port button bindings to the xbox device buttons
std::unordered_map<std::string, std::map<int, IoControl*>> m_Bindings;
bool m_XboxPort[4] = { false };
// button bindings to the xbox device buttons
std::map<int, IoControl*> m_Bindings;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -31,62 +31,17 @@
#include <thread>
#include "InputDevice.h"
#include "EmuDevice.h"
#include <imgui.h>
#define PORT_INVALID -1
#define PORT_1 0
#define PORT_2 1
#define PORT_3 2
#define PORT_4 3
#define XBOX_NUM_PORTS 4
#define SLOT_TOP 0
#define SLOT_BOTTOM 1
#define XBOX_CTRL_NUM_SLOTS 2
#define CTRL_OFFSET 0
#define MU_OFFSET 4
#define MAX_DEVS (XBOX_NUM_PORTS + XBOX_CTRL_NUM_SLOTS * XBOX_NUM_PORTS)
#define XID_PACKET_HEADER 2
#define LIGHTGUN_GRIP_DELAY 30
// Prevent a collision with the SetPort provided by Windows
#ifdef WIN32
#undef SetPort
#endif
extern int dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)];
inline XBOX_INPUT_DEVICE input_support_list[] = {
XBOX_INPUT_DEVICE::DEVICE_INVALID,
XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE,
XBOX_INPUT_DEVICE::MS_CONTROLLER_S,
XBOX_INPUT_DEVICE::LIGHTGUN,
XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER,
XBOX_INPUT_DEVICE::ARCADE_STICK,
XBOX_INPUT_DEVICE::HW_XBOX_CONTROLLER,
XBOX_INPUT_DEVICE::HW_STEEL_BATTALION_CONTROLLER,
};
inline XBOX_INPUT_DEVICE slot_support_list[] = {
XBOX_INPUT_DEVICE::DEVICE_INVALID,
XBOX_INPUT_DEVICE::MEMORY_UNIT,
// Microphone
// Phantasy star online keyboard
};
#pragma pack(1)
// Class-specific xid descriptor, used by libusb
struct XidDesc {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdXid;
uint8_t bType;
uint8_t bSubType;
uint8_t bMaxInputReportSize;
uint8_t bMaxOutputReportSize;
uint16_t wAlternateProductIds[4];
};
// xpad in/out buffers stripped of the first two bytes as used by xinput
// xpad in/out buffers stripped of the first two bytes
struct XpadInput {
uint16_t wButtons;
uint8_t bAnalogButtons[8];
@ -101,119 +56,16 @@ struct XpadOutput {
uint16_t right_actuator_strength;
};
// xpad in/out buffers as used by xid
struct XidGamepadInput {
uint8_t bReportId;
uint8_t bLength;
XpadInput InBuffer;
};
struct XidGamepadOutput {
uint8_t bReportId;
uint8_t bLength;
XpadOutput OutBuffer;
};
// same as above, but for the SBC
struct SBCInput {
uint16_t wButtons[3];
uint8_t bPad1;
uint8_t sAimingX;
uint8_t bPad2;
uint8_t sAimingY;
uint8_t bPad3;
int8_t sRotationLever;
uint8_t bPad4;
int8_t sSightChangeX;
uint8_t bPad5;
int8_t sSightChangeY;
uint8_t bPad6;
uint8_t wLeftPedal;
uint8_t bPad7;
uint8_t wMiddlePedal;
uint8_t bPad8;
uint8_t wRightPedal;
uint8_t ucTunerDial;
uint8_t ucGearLever;
};
struct SBCOutput {
uint8_t LedState[20];
};
struct XidSBCInput {
uint8_t bReportId;
uint8_t bLength;
SBCInput InBuffer;
};
struct XidSBCOutput {
uint8_t bReportId;
uint8_t bLength;
SBCOutput OutBuffer;
};
#pragma pack()
struct LightGunData {
xbox::short_xt offset_x;
xbox::short_xt offset_y;
xbox::short_xt offset_upp_x;
xbox::short_xt offset_upp_y;
uint8_t last_in_state;
uint8_t last_turbo;
uint8_t turbo_delay;
uint8_t turbo;
uint8_t laser;
};
struct SbcData {
uint16_t last_in_state;
};
union InputBuff {
XidGamepadInput ctrl;
XidSBCInput sbc;
};
struct DeviceInfo {
xbox::HANDLE hHandle; // device handle returned by xapi
bool bAutoPoll; // autopoll on/off, as instructed by the title in XInputOpen
bool bAutoPollDefault; // default autopoll value, depending on device type
uint8_t ucType; // xapi type
uint8_t ucSubType; // xapi subtype
uint8_t ucInputStateSize; // input state size in bytes, does not include dwPacketNumber
uint8_t ucFeedbackSize; // feedback size in bytes, does not include FeedbackHeader
uint32_t dwPacketNumber; // increases by one when the input state changes
InputBuff buff; // input buffer
// device-specific additional data
union {
LightGunData ligthgun;
SbcData sbc;
};
};
struct DeviceState {
std::string port;
int port_idx;
XBOX_INPUT_DEVICE type;
bool bPendingRemoval;
bool bSignaled;
DeviceInfo info;
DeviceState *slots[XBOX_CTRL_NUM_SLOTS];
DeviceState *upstream;
};
extern DeviceState g_devs[MAX_DEVS];
class InputDeviceManager
{
public:
void Initialize(bool is_gui, HWND hwnd);
void Initialize(bool is_gui);
void Shutdown();
// read/write the input/output from/to the device attached to the supplied xbox port
bool UpdateXboxPortInput(int port, void *buffer, int direction, int type);
bool UpdateXboxPortInput(int usb_port, void* Buffer, int Direction, int xid_type);
// add the device to the list of availble devices
void AddDevice(std::shared_ptr<InputDevice> Device);
// remove the device from the list of availble devices
@ -221,38 +73,28 @@ public:
// update device list
void RefreshDevices();
// get the name of the devices currently detected
std::vector<std::string> GetDeviceList(std::function<bool(const InputDevice *)> Callback) const;
std::vector<std::string> GetDeviceList() const;
// find device from its gui name
std::shared_ptr<InputDevice> FindDevice(const std::string& QualifiedName) const;
// find device from its sdl id
std::shared_ptr<InputDevice> FindDevice(SDL_JoystickID id) const;
// find device from its xbox port
std::shared_ptr<InputDevice> FindDevice(std::string_view port) const;
std::shared_ptr<InputDevice> FindDevice(int usb_port, int dummy) const;
// attach/detach guest devices to the emulated machine
void UpdateDevices(std::string_view port, bool ack);
void UpdateDevices(int port, bool ack);
// update input options
void UpdateOpt(bool is_gui);
// device hotplug event handler
void HotplugHandler(bool is_sdl);
// converts xinput -> screen coordinates to display the lightgun laser on the rendering window
ImVec2 CalcLaserPos(int port);
private:
// update input for an xbox controller
bool UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, const std::string &Port);
// update input for a lightgun
bool UpdateInputLightgun(std::shared_ptr<InputDevice> &Device, void *Buffer, int Direction, int Port_num, const std::string &Port);
// update input for a Steel Battalion controller
bool UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port_num, const std::string &Port);
// update input for a passthrough xbox device
bool UpdateInputHw(std::shared_ptr<InputDevice> &Device, void *Buffer, int Direction);
bool UpdateInputXpad(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction);
// bind a host device to an emulated device
void BindHostDevice(int type, std::string_view port);
void BindHostDevice(int port, int usb_port, int type);
// connect a device to the emulated machine
void ConnectDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port);
void ConnectDevice(int port, int usb_port, int type);
// disconnect a device from the emulated machine
void DisconnectDevice(DeviceState *dev, std::string_view port, bool ack);
void DisconnectDevice(int port, int usb_port, bool ack);
// all enumerated devices currently detected and supported
std::vector<std::shared_ptr<InputDevice>> m_Devices;
@ -264,14 +106,12 @@ private:
std::thread m_PollingThread;
// used to indicate that the manager is shutting down
bool m_bPendingShutdown;
// handle of the rendering or the input gui window
HWND m_hwnd;
};
extern InputDeviceManager g_InputDeviceManager;
// hle input functions
void ConstructHleInputDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port);
void DestructHleInputDevice(DeviceState *dev);
bool ConstructHleInputDevice(int Type, int Port);
void DestructHleInputDevice(int Port);
#endif

View File

@ -34,8 +34,73 @@
#include "Logging.h"
#include <future>
#define INPUT_TIMEOUT 5000
#define OUTPUT_TIMEOUT 3000
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.35; // NOTE: this should probably be made user configurable
InputWindow* g_InputWindow = nullptr;
void InputWindow::Initialize(HWND hwnd, int port_num, int dev_type)
{
// Save window/device specific variables
m_hwnd_window = hwnd;
m_hwnd_device_list = GetDlgItem(m_hwnd_window, IDC_DEVICE_LIST);
m_hwnd_profile_list = GetDlgItem(m_hwnd_window, IDC_XID_PROFILE_NAME);
m_hwnd_default = GetDlgItem(m_hwnd_window, IDC_XID_DEFAULT);
m_dev_type = dev_type;
m_max_num_buttons = dev_num_buttons[dev_type];
m_port_num = port_num;
m_bHasChanges = false;
m_bIsBinding = false;
// Set window icon
SetClassLong(m_hwnd_window, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_CXBX)));
// Set window title
std::string title;
switch (m_dev_type)
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE): {
title += "Xbox Controller Duke at port ";
}
break;
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
title += "Xbox Controller S at port ";
}
break;
default:
break;
}
SendMessage(m_hwnd_window, WM_SETTEXT, 0,
reinterpret_cast<LPARAM>((title + std::to_string(PORT_INC(m_port_num))).c_str()));
// Set the maximum profile name lenght the user can enter in the profile combobox
SendMessage(m_hwnd_profile_list, CB_LIMITTEXT, 49, 0);
// construct emu device
m_DeviceConfig = new EmuDevice(m_dev_type, m_hwnd_window);
// Enumerate devices
UpdateDeviceList();
// Load currently saved profile for this port/device type
LoadDefaultProfile();
// Load currently selected host device
UpdateCurrentDevice();
// Load rumble binding
char rumble[30];
m_DeviceConfig->FindButtonByIndex(m_max_num_buttons - 1)->GetText(rumble, sizeof(rumble));
m_rumble = rumble;
// Install the subclass for the profile combobox
SetWindowSubclass(GetWindow(m_hwnd_profile_list, GW_CHILD), ProfileNameSubclassProc, 0, 0);
}
InputWindow::~InputWindow()
{
@ -69,7 +134,6 @@ bool InputWindow::IsProfileSaved()
}
}
return true;
}
@ -78,22 +142,16 @@ void InputWindow::UpdateDeviceList()
g_InputDeviceManager.RefreshDevices();
// Populate device list
for (int i = 0; i < m_num_devices; i++) {
LRESULT num_devices = SendMessage(m_hwnd_device_list, CB_GETCOUNT, 0, 0);
for (int i = 0; i < num_devices; i++) {
SendMessage(m_hwnd_device_list, CB_DELETESTRING, 0, 0);
}
// Add everything but libusb devices
std::vector<std::string> dev_list = g_InputDeviceManager.GetDeviceList([](const auto &Device) {
if (Device->IsLibusb()) {
return false;
}
return true;
});
std::vector<std::string> dev_list = g_InputDeviceManager.GetDeviceList();
for (const auto& str : dev_list) {
SendMessage(m_hwnd_device_list, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str.c_str()));
++m_num_devices;
}
if (m_num_devices) {
if (!dev_list.empty()) {
SendMessage(m_hwnd_device_list, CB_SETCURSEL, 0, 0);
}
@ -128,7 +186,7 @@ InputDevice::Input* InputWindow::DetectInput(InputDevice* const Device, int ms)
Device->UpdateInput();
std::vector<bool>::iterator state = initial_states.begin();
for (; i != e && s == e; i++, state++) {
if ((*i)->IsDetectable() && ((*i)->GetState() > INPUT_DETECT_THRESHOLD)) {
if ((*i)->GetState() > INPUT_DETECT_THRESHOLD) {
if (*state == false) {
// input was not initially pressed or it was but released afterwards
s = i;
@ -150,6 +208,56 @@ InputDevice::Input* InputWindow::DetectInput(InputDevice* const Device, int ms)
return nullptr; // no input
}
void InputWindow::BindButton(int ControlID)
{
// Check if binding thread is still active
// testcase: spacebar and enter keys; without this fix will cause repeat binding result.
if (m_bIsBinding) {
return;
}
auto dev = g_InputDeviceManager.FindDevice(m_host_dev);
if (dev != nullptr) {
m_bIsBinding = true;
// Don't block the message processing loop
std::thread([this, dev, ControlID]() {
EnableWindow(m_hwnd_window, FALSE);
char current_text[30];
Button* xbox_button = m_DeviceConfig->FindButtonById(ControlID);
xbox_button->GetText(current_text, sizeof(current_text));
xbox_button->UpdateText("...");
std::future<InputDevice::Input*> fut = std::async(std::launch::async, &InputWindow::DetectInput, this, dev.get(), INPUT_TIMEOUT);
InputDevice::Input* dev_button = fut.get();
if (dev_button) {
xbox_button->UpdateText(dev_button->GetName().c_str());
m_bHasChanges = true;
}
else {
xbox_button->UpdateText(current_text);
}
m_bIsBinding = false;
EnableWindow(m_hwnd_window, TRUE);
}).detach();
}
}
void InputWindow::BindDefault()
{
int api = EnableDefaultButton();
if (api != -1) {
m_DeviceConfig->BindDefault(api);
m_bHasChanges = true;
}
}
void InputWindow::ClearBindings()
{
m_DeviceConfig->ClearButtons();
m_rumble = std::string();
m_bHasChanges = true;
}
int InputWindow::EnableDefaultButton()
{
if (std::strncmp(m_host_dev.c_str(), "XInput", std::strlen("XInput")) == 0) {
@ -166,65 +274,6 @@ int InputWindow::EnableDefaultButton()
}
}
void InputWindow::BindButton(int ControlID, bool auto_swap)
{
// Check if binding thread is still active
// testcase: spacebar and enter keys; without this fix will cause repeat binding result.
if (m_bIsBinding) {
return;
}
auto dev = g_InputDeviceManager.FindDevice(m_host_dev);
if (dev != nullptr) {
m_bIsBinding = true;
// Don't block the message processing loop
std::thread([this, dev, ControlID, auto_swap]() {
EnableWindow(m_hwnd_window, FALSE);
char current_text[HOST_BUTTON_NAME_LENGTH];
Button* xbox_button = m_DeviceConfig->FindButtonById(ControlID);
xbox_button->GetText(current_text, sizeof(current_text));
xbox_button->UpdateText("...");
std::future<InputDevice::Input*> fut = std::async(std::launch::async, &InputWindow::DetectInput, this, dev.get(), INPUT_TIMEOUT);
InputDevice::Input* dev_button = fut.get();
if (dev_button) {
xbox_button->UpdateText(dev_button->GetName().c_str());
if (auto_swap) {
SwapMoCursorAxis(xbox_button);
}
m_bHasChanges = true;
}
else {
xbox_button->UpdateText(current_text);
}
m_bIsBinding = false;
EnableWindow(m_hwnd_window, TRUE);
}).detach();
}
}
void InputWindow::UpdateProfile(const std::string &name, int command)
{
switch (command)
{
case PROFILE_LOAD:
LoadProfile(name);
break;
case PROFILE_SAVE:
SaveProfile(name);
break;
case PROFILE_DELETE:
DeleteProfile(name);
break;
case BUTTON_CLEAR:
m_bHasChanges = true;
break;
}
}
InputWindow::ProfileIt InputWindow::FindProfile(const std::string& name)
{
auto it = std::find_if(g_Settings->m_input_profiles[m_dev_type].begin(),
@ -234,6 +283,40 @@ InputWindow::ProfileIt InputWindow::FindProfile(const std::string& name)
return it;
}
void InputWindow::UpdateProfile(const std::string& name, int command)
{
switch (command)
{
case PROFILE_LOAD: {
LoadProfile(name);
}
break;
case PROFILE_SAVE: {
SaveProfile(name);
}
break;
case PROFILE_DELETE: {
DeleteProfile(name);
}
break;
case RUMBLE_CLEAR: {
m_rumble = std::string();
}
break;
case BUTTON_CLEAR: {
m_bHasChanges = true;
}
break;
default:
break;
}
}
void InputWindow::LoadProfile(const std::string& name)
{
ProfileIt profile = FindProfile(name);
@ -266,7 +349,7 @@ bool InputWindow::SaveProfile(const std::string& name)
return false;
}
if (m_host_dev == std::string()) {
PopupError(m_hwnd_window, "Cannot save. No input devices detected.", "Cxbx-Reloaded");
PopupError(m_hwnd_window, "Cannot save. No input devices detected", "Cxbx-Reloaded");
return false;
}
OverwriteProfile(name);
@ -275,7 +358,7 @@ bool InputWindow::SaveProfile(const std::string& name)
profile.ProfileName = name;
profile.DeviceName = m_host_dev;
for (int index = 0; index < m_max_num_buttons; index++) {
char dev_button[HOST_BUTTON_NAME_LENGTH];
char dev_button[30];
m_DeviceConfig->FindButtonByIndex(index)->GetText(dev_button, sizeof(dev_button));
profile.ControlList.push_back(dev_button);
}
@ -284,7 +367,6 @@ bool InputWindow::SaveProfile(const std::string& name)
g_Settings->m_input_port[m_port_num].DeviceName = profile.DeviceName;
g_Settings->m_input_port[m_port_num].ProfileName = profile.ProfileName;
g_Settings->m_input_profiles[m_dev_type].push_back(std::move(profile));
m_bHasChanges = false;
return true;
}
@ -334,80 +416,79 @@ void InputWindow::LoadDefaultProfile()
void InputWindow::UpdateCurrentDevice()
{
if (m_num_devices) {
char device_name[50];
SendMessage(m_hwnd_device_list, WM_GETTEXT, sizeof(device_name), reinterpret_cast<LPARAM>(device_name));
m_host_dev = device_name;
}
else {
m_host_dev = "";
}
char device_name[50];
SendMessage(m_hwnd_device_list, WM_GETTEXT, sizeof(device_name), reinterpret_cast<LPARAM>(device_name));
m_host_dev = device_name;
EnableDefaultButton();
}
void InputWindow::SwapMoCursorAxis(Button *button)
void InputWindow::InitRumble(HWND hwnd)
{
// Axis X+ <-> Cursor X+
// Axis X- <-> Cursor X-
// Axis Y+ <-> Cursor Y-
// Axis Y- <-> Cursor Y+
if (m_host_dev.ends_with("KeyboardMouse")) {
assert(button != nullptr);
char control_name[HOST_BUTTON_NAME_LENGTH];
button->GetText(control_name, sizeof(control_name));
if (std::string_view(control_name).starts_with("Axis")) {
switch (control_name[5])
{
case 'X':
if (control_name[6] == '+') {
button->UpdateText("Cursor X+");
}
else {
button->UpdateText("Cursor X-");
}
m_bHasChanges = true;
break;
case 'Y':
if (control_name[6] == '+') {
button->UpdateText("Cursor Y-");
}
else {
button->UpdateText("Cursor Y+");
}
m_bHasChanges = true;
break;
}
return;
}
if (std::string_view(control_name).starts_with("Cursor")) {
switch (control_name[7])
{
case 'X':
if (control_name[8] == '+') {
button->UpdateText("Axis X+");
}
else {
button->UpdateText("Axis X-");
}
m_bHasChanges = true;
break;
case 'Y':
if (control_name[8] == '+') {
button->UpdateText("Axis Y-");
}
else {
button->UpdateText("Axis Y+");
}
m_bHasChanges = true;
break;
}
m_hwnd_rumble = hwnd;
m_hwnd_rumble_list = GetDlgItem(m_hwnd_rumble, IDC_RUMBLE_LIST);
SendMessage(m_hwnd_rumble_list, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(""));
auto dev = g_InputDeviceManager.FindDevice(m_host_dev);
if (dev != nullptr) {
auto outputs = dev->GetOutputs();
for (const auto out : outputs) {
SendMessage(m_hwnd_rumble_list, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(out->GetName().c_str()));
}
}
SendMessage(m_hwnd_rumble_list, CB_SETCURSEL, SendMessage(m_hwnd_rumble_list, CB_FINDSTRINGEXACT, 1,
reinterpret_cast<LPARAM>(m_rumble.c_str())), 0);
}
void InputWindow::UpdateRumble(int command)
{
switch (command)
{
case RUMBLE_SET: {
char rumble[30];
SendMessage(m_hwnd_rumble_list, WM_GETTEXT, sizeof(rumble), reinterpret_cast<LPARAM>(rumble));
m_rumble = rumble;
}
break;
case RUMBLE_UPDATE: {
m_DeviceConfig->FindButtonByIndex(m_max_num_buttons - 1)->UpdateText(m_rumble.c_str());
}
break;
case RUMBLE_TEST: {
DetectOutput(OUTPUT_TIMEOUT);
}
break;
default:
break;
}
}
void InputWindow::DetectOutput(int ms)
{
if (m_rumble == std::string()) {
return;
}
auto dev = g_InputDeviceManager.FindDevice(m_host_dev);
if (dev != nullptr) {
// Don't block the message processing loop
std::thread([this, dev, ms]() {
EnableWindow(m_hwnd_rumble, FALSE);
SendMessage(m_hwnd_rumble_list, WM_SETTEXT, 0, reinterpret_cast<LPARAM>("..."));
auto outputs = dev->GetOutputs();
for (const auto out : outputs) {
if (out->GetName() == m_rumble) {
out->SetState(1.0, 1.0);
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
for (const auto out : outputs) {
if (out->GetName() == m_rumble) {
out->SetState(0.0, 0.0);
}
}
SendMessage(m_hwnd_rumble_list, WM_SETTEXT, 0, reinterpret_cast<LPARAM>("Test"));
EnableWindow(m_hwnd_rumble, TRUE);
}).detach();
}
}

View File

@ -40,11 +40,8 @@
#define RUMBLE_CLEAR 7
#define BUTTON_CLEAR 8
#define XINPUT_DEFAULT 0
#define DINPUT_DEFAULT 1
#define INPUT_TIMEOUT 5000
#define OUTPUT_TIMEOUT 3000
#define XINPUT_DEFAULT 1
#define DINPUT_DEFAULT 2
LRESULT CALLBACK ProfileNameSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
@ -52,28 +49,30 @@ LRESULT CALLBACK ProfileNameSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
class InputWindow
{
public:
virtual void Initialize(HWND hwnd, int port_num, int dev_type) = 0;
void Initialize(HWND hwnd, int port_num, int dev_type);
void InitRumble(HWND hwnd);
~InputWindow();
virtual void UpdateDeviceList();
void BindButton(int ControlID, bool auto_swap = false);
virtual void ClearBindings() = 0;
virtual void UpdateProfile(const std::string& name, int command);
void UpdateDeviceList();
void BindButton(int ControlID);
void BindDefault();
void ClearBindings();
void UpdateProfile(const std::string& name, int command);
void UpdateRumble(int command);
void UpdateCurrentDevice();
bool IsProfileSaved();
void SwapMoCursorAxis(Button *button);
protected:
private:
typedef std::vector<Settings::s_input_profiles>::iterator ProfileIt;
InputDevice::Input* DetectInput(InputDevice* const Device, int ms);
void DetectOutput(int ms);
ProfileIt FindProfile(const std::string& name);
void LoadProfile(const std::string& name);
bool SaveProfile(const std::string& name);
void DeleteProfile(const std::string& name);
void OverwriteProfile(const std::string& name);
void LoadDefaultProfile();
virtual int EnableDefaultButton();
int EnableDefaultButton();
// xbox device under configuration
EmuDevice* m_DeviceConfig;
@ -83,10 +82,12 @@ protected:
HWND m_hwnd_device_list;
// handle of the profile list combobox
HWND m_hwnd_profile_list;
// handle of the rumble window
HWND m_hwnd_rumble;
// handle of the rumble combobox
HWND m_hwnd_rumble_list;
// handle of the default bindings button
HWND m_hwnd_default;
// number of devices displayed in the device list combobox
int m_num_devices;
// type of the device
int m_dev_type;
// num of buttons of device under configuration
@ -95,71 +96,12 @@ protected:
int m_port_num;
// host device under configuration
std::string m_host_dev;
// currently selected rumble control
std::string m_rumble;
// indicates if the current profile has unsaved changes
bool m_bHasChanges;
// prevent current input attempt to set the previous input at same time
std::atomic<bool> m_bIsBinding;
};
class DukeInputWindow : public InputWindow
{
public:
void Initialize(HWND hwnd, int port_num, int dev_type) override;
void InitRumble(HWND hwnd);
void UpdateRumble(int command);
void BindDefault();
void ClearBindings() override;
void UpdateProfile(const std::string &name, int command) override;
void SaveSlotConfig();
private:
void DetectOutput(int ms);
// handle of the rumble window
HWND m_hwnd_rumble;
// handle of the rumble combobox
HWND m_hwnd_rumble_list;
// handles of the slot combobox
HWND m_hwnd_slot_list[XBOX_CTRL_NUM_SLOTS];
// currently selected rumble control
std::string m_rumble;
};
class SbcInputWindow : public InputWindow
{
public:
void Initialize(HWND hwnd, int port_num, int dev_type) override;
~SbcInputWindow();
void ClearBindings() override;
private:
int EnableDefaultButton() override;
};
class LibusbInputWindow : public InputWindow
{
public:
void Initialize(HWND hwnd, int port_num, int dev_type) override;
~LibusbInputWindow();
void ClearBindings() override;
void UpdateDeviceList() override;
void TestInput();
private:
int EnableDefaultButton() override;
// handle of the test button
HWND m_hwnd_device_test;
};
class LightgunInputWindow : public InputWindow
{
public:
void Initialize(HWND hwnd, int port_num, int dev_type) override;
~LightgunInputWindow();
void BindDefault();
void ClearBindings() override;
};
extern InputWindow* g_InputWindow;

View File

@ -1,325 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#define LOG_PREFIX CXBXR_MODULE::LIBUSB
#include "LibusbDevice.h"
#include "InputManager.h"
#include "core\kernel\support\Emu.h"
#include "core\hle\XAPI\Xapi.h"
// Sanity check: ensure that our libusb version is high enough for libusb_get_device_descriptor to succeed and to pass nullptr to libusb_interrupt_transfer
static_assert(LIBUSB_API_VERSION >= 0x01000105);
namespace Libusb
{
int InitStatus = NOT_INIT;
// These come from here https://github.com/xboxdrv/xboxdrv/blob/ac6ebb1228962220482ea03743cadbe18754246c/src/xpad_device.cpp#L29
static constexpr uint16_t SupportedDevices_VidPid[][2] = { // vid, pid
0x0d2f, 0x0002,
0x045e, 0x0202,
0x045e, 0x0285,
0x045e, 0x0287,
0x045e, 0x0289,
0x046d, 0xca84,
0x046d, 0xca88,
0x05fd, 0x1007,
0x05fd, 0x107a,
0x0738, 0x4516,
0x0738, 0x4522,
0x0738, 0x4526,
0x0738, 0x4536,
0x0738, 0x4556,
0x0c12, 0x8802,
0x0c12, 0x8810,
0x0c12, 0x9902,
0x0e4c, 0x1097,
0x0e4c, 0x2390,
0x0e6f, 0x0003,
0x0e6f, 0x0005,
0x0e6f, 0x0006,
0x0f30, 0x0202,
0x0f30, 0x8888,
0x102c, 0xff0c,
0x044f, 0x0f07,
0x0e8f, 0x3008,
};
static constexpr const char *SupportedDevices_Name[] = {
"Andamiro Pump It Up pad",
"Microsoft X-Box pad v1 (US)",
"Microsoft X-Box pad (Japan)",
"Microsoft Xbox Controller S",
"Microsoft X-Box pad v2 (US)",
"Logitech Xbox Cordless Controller",
"Logitech Compact Controller for Xbox",
"Mad Catz Controller (unverified)",
"InterAct 'PowerPad Pro' X-Box pad (Germany)",
"Mad Catz Control Pad",
"Mad Catz LumiCON",
"Mad Catz Control Pad Pro",
"Mad Catz MicroCON",
"Mad Catz Lynx Wireless Controller",
"Zeroplus Xbox Controller",
"Zeroplus Xbox Controller",
"HAMA VibraX - *FAULTY HARDWARE*",
"Radica Gamester Controller",
"Radica Games Jtech Controller",
"Logic3 Freebird wireless Controller",
"Eclipse wireless Controller",
"Edge wireless Controller",
"Joytech Advanced Controller",
"BigBen XBMiniPad Controller",
"Joytech Wireless Advanced Controller",
"Thrustmaster, Inc. Controller",
"Generic xbox control (dealextreme)",
};
static_assert(ARRAY_SIZE(SupportedDevices_VidPid) == ARRAY_SIZE(SupportedDevices_Name));
void Init(std::mutex &Mtx)
{
std::unique_lock<std::mutex> lck(Mtx);
// We only use a single libusb session per cxbxr process, so we do not need to use a libusb context
if (libusb_init(nullptr) != 0) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to initialize Libusb!");
InitStatus = INIT_ERROR;
return;
}
InitStatus = INIT_SUCCESS;
}
void DeInit()
{
InitStatus = NOT_INIT;
libusb_exit(nullptr);
}
void PopulateDevices()
{
// NOTE: the libusb docs say that the list is always appended with a NULL element at the end
libusb_device **List;
ssize_t DevicesConnected = libusb_get_device_list(nullptr, &List) - 1;
if (DevicesConnected < 0) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to enumerate devices. The error was: %s", libusb_strerror(DevicesConnected));
return;
}
for (ssize_t i = 0; i < DevicesConnected; ++i) {
libusb_device *LibusbDev = List[i];
libusb_device_descriptor Desc;
libusb_get_device_descriptor(LibusbDev, &Desc); // always succeeds when LIBUSB_API_VERSION >= 0x01000102
auto Device = std::make_shared<LibusbDevice>(&Desc, LibusbDev);
if (Device->IsLibusb()) {
g_InputDeviceManager.AddDevice(std::move(Device));
}
}
libusb_free_device_list(List, 1);
}
void GetDeviceChanges()
{
g_InputDeviceManager.RemoveDevice([](const auto &Device) {
return Device->IsLibusb();
});
PopulateDevices();
}
LibusbDevice::LibusbDevice(libusb_device_descriptor *Desc, libusb_device *Dev)
{
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
// The SBC's VID and PID are taken from https://xboxdevwiki.net/Xbox_Input_Devices#Steel_Battalion_Controller
if ((Desc->idVendor == 0x0a7b) && (Desc->idProduct == 0xd000)) {
m_Type = XBOX_INPUT_DEVICE::HW_STEEL_BATTALION_CONTROLLER;
m_UcType = XINPUT_DEVTYPE_STEELBATTALION;
m_UcSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
m_Name = "Steel battalion controller";
m_BufferInSize = sizeof(XidSBCInput);
m_BufferOutSize = sizeof(XidSBCOutput);
assert(Desc->bcdUSB == 0x110); // must be a usb 1.1 device
}
else {
for (size_t i = 0; i < ARRAY_SIZE(SupportedDevices_VidPid); ++i) {
if ((Desc->idVendor == SupportedDevices_VidPid[i][0]) && (Desc->idProduct == SupportedDevices_VidPid[i][1])) {
m_Type = XBOX_INPUT_DEVICE::HW_XBOX_CONTROLLER;
m_UcType = XINPUT_DEVTYPE_GAMEPAD;
m_UcSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
m_Name = SupportedDevices_Name[i];
m_BufferInSize = sizeof(XidGamepadInput);
m_BufferOutSize = sizeof(XidGamepadOutput);
assert(Desc->bcdUSB == 0x110); // must be a usb 1.1 device
break;
}
}
}
if (m_Type == XBOX_INPUT_DEVICE::DEVICE_INVALID) { return; }
// check if we are able to open device through libusb
if (int err = libusb_open(Dev, &m_hDev)) {
// Couldn't open device, create an error log report then don't use it.
EmuLog(LOG_LEVEL::ERROR2, "Unable to open original xbox device \"%s\" (%hX:%hX), libusb's error was: %s",
m_Name.c_str(), Desc->idVendor, Desc->idProduct, libusb_strerror(err));
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
return;
}
// If we are able to open device, continue with query process.
else {
// Duke, S and SBC have 1 configuration, 1 interface and 2 endpoints (input and output) and use the default alternate setting zero.
// The code below assumes that third-party controllers follow suit.
libusb_config_descriptor *ConfDesc;
if (libusb_get_active_config_descriptor(Dev, &ConfDesc) == 0) {
if (ConfDesc->bNumInterfaces == 1) {
auto Iface = ConfDesc->interface[0];
if (Iface.num_altsetting == 1) {
auto Setting = Iface.altsetting[0];
m_IfaceNum = Setting.bInterfaceNumber;
if (Setting.bNumEndpoints >= 1) {
m_HasEndpointOut = false;
for (uint8_t i = 0; i < Setting.bNumEndpoints; ++i) {
auto Endpoint = Setting.endpoint[i];
if (Endpoint.bEndpointAddress & 0x80) {
m_EndpointIn = Endpoint.bEndpointAddress;
m_IntervalIn = Endpoint.bInterval;
}
else {
// third-party controllers that don't support rumble probably won't have an out endpoint
m_EndpointOut = Endpoint.bEndpointAddress;
m_IntervalOut = Endpoint.bInterval;
m_HasEndpointOut = true;
}
}
EmuLog(LOG_LEVEL::INFO, "Out endpoint %s", m_HasEndpointOut ? "present" : "not present");
if (int err = libusb_claim_interface(m_hDev, m_IfaceNum)) {
EmuLog(LOG_LEVEL::INFO, "Rejected device %s because libusb could not claim its interface. The error was: %s",
m_Name.c_str(), libusb_strerror(err));
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
}
else {
// Grab the xid descriptor so that we can report real type/subtype values back to the title when it calls XInputGetCapabilities
XidDesc XidDesc;
if (libusb_control_transfer(m_hDev, 0xC1, 6, 0x4200, m_IfaceNum, reinterpret_cast<uint8_t *>(&XidDesc), sizeof(XidDesc), m_IntervalIn)
== sizeof(XidDesc)) { // submit a GET_DESCRIPTOR request
// Dump the xid descriptor to the log
EmuLog(LOG_LEVEL::INFO, "Xid descriptor dump:\nbLength: %#010X\nbDescriptorType: %#010X\nbcdXid: %#010X\nbType: %#010X\n"
"bSubType: %#010X\nbMaxInputReportSize: %#010X\nbMaxOutputReportSize: %#010X\nwAlternateProductIds[0]: %#010X\n"
"wAlternateProductIds[1]: %#010X\nwAlternateProductIds[2]: %#010X\nwAlternateProductIds[3]: %#010X\n",
XidDesc.bLength, XidDesc.bDescriptorType, XidDesc.bcdXid, XidDesc.bType, XidDesc.bSubType, XidDesc.bMaxInputReportSize, XidDesc.bMaxOutputReportSize,
XidDesc.wAlternateProductIds[0], XidDesc.wAlternateProductIds[1], XidDesc.wAlternateProductIds[2], XidDesc.wAlternateProductIds[3]);
if (XidDesc.bDescriptorType == 0x42) {
m_UcType = XidDesc.bType;
m_UcSubType = XidDesc.bSubType;
}
else {
EmuLog(LOG_LEVEL::INFO, "The xid descriptor for device %s reported an unexpected descriptor type, assuming a default subtype", m_Name);
}
}
else {
EmuLog(LOG_LEVEL::INFO, "Could not retrieve the xid descriptor for device %s, assuming a default subtype", m_Name);
}
}
}
else {
EmuLog(LOG_LEVEL::INFO, "Rejected device %s because of unexpected number of endpoints, bNumEndpoints: %d",
m_Name.c_str(), Setting.bNumEndpoints);
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
}
}
else {
EmuLog(LOG_LEVEL::INFO, "Rejected device %s because of unexpected number of alternative settings, num_altsetting: %d",
m_Name.c_str(), Iface.num_altsetting);
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
}
}
else {
EmuLog(LOG_LEVEL::INFO, "Rejected device %s because of unexpected number of interfaces, bNumInterfaces: %d",
m_Name.c_str(), ConfDesc->bNumInterfaces);
m_Type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
}
libusb_free_config_descriptor(ConfDesc);
}
}
if (m_Type == XBOX_INPUT_DEVICE::DEVICE_INVALID) { libusb_close(m_hDev); }
}
LibusbDevice::~LibusbDevice()
{
if (m_Type != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
libusb_release_interface(m_hDev, m_IfaceNum);
libusb_close(m_hDev);
}
}
bool LibusbDevice::UpdateInput()
{
// Dummy, it should never be called. It's only here to override the pure function UpdateInput in InputDevice
assert(0);
return false;
}
bool LibusbDevice::ExecuteIo(void *Buffer, int Direction)
{
// NOTE: a SET_REPORT control transfer to the SBC doesn't seem to work, the parameters might not be appropriate for it... So, we use
// the interrupt pipes for everything instead
*static_cast<uint8_t *>(Buffer) = 0; // write bReportId
if (Direction == DIRECTION_IN) {
*(static_cast<uint8_t *>(Buffer) + 1) = m_BufferInSize; // write bLength
if (libusb_interrupt_transfer(m_hDev, m_EndpointIn, static_cast<uint8_t *>(Buffer), m_BufferInSize, nullptr, m_IntervalIn) != 0) {
return false;
}
}
else {
if (m_HasEndpointOut) {
*(static_cast<uint8_t *>(Buffer) + 1) = m_BufferOutSize; // write bLength
if (libusb_interrupt_transfer(m_hDev, m_EndpointOut, static_cast<uint8_t *>(Buffer), m_BufferOutSize, nullptr, m_IntervalOut) != 0) {
return false;
}
}
}
return true;
}
std::string LibusbDevice::GetDeviceName() const
{
return m_Name;
}
std::string LibusbDevice::GetAPI() const
{
return "Libusb";
}
}

View File

@ -1,91 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include "InputDevice.h"
// Suppress warning in libusb about zero sized array
#pragma warning(push)
#pragma warning(disable: 4200)
#include "libusb.h"
#pragma warning(pop)
namespace Libusb
{
typedef enum _INIT_STATUS : int
{
NOT_INIT = -2,
INIT_ERROR,
INIT_SUCCESS,
}
INIT_STATUS;
extern int InitStatus;
// initialize Libusb
void Init(std::mutex &Mtx);
// shutdown Libusb
void DeInit();
// refresh the device list in response to a refresh command from the input GUI
void PopulateDevices();
// update the device list
void GetDeviceChanges();
class LibusbDevice : public InputDevice
{
public:
~LibusbDevice();
bool UpdateInput() override;
bool ExecuteIo(void *Buffer, int Direction);
LibusbDevice(libusb_device_descriptor *Desc, libusb_device *Dev);
std::string GetDeviceName() const override;
std::string GetAPI() const override;
bool IsLibusb() const override { return m_Type != XBOX_INPUT_DEVICE::DEVICE_INVALID; }
XBOX_INPUT_DEVICE GetLibusbType() const { return m_Type; }
uint8_t GetUcType() { return m_UcType; }
uint8_t GetUcSubType() { return m_UcSubType; }
private:
XBOX_INPUT_DEVICE m_Type;
uint8_t m_UcType;
uint8_t m_UcSubType;
std::string m_Name;
libusb_device_handle *m_hDev;
unsigned char m_EndpointIn;
unsigned char m_EndpointOut;
uint8_t m_IntervalIn;
uint8_t m_IntervalOut;
uint8_t m_BufferInSize;
uint8_t m_BufferOutSize;
uint8_t m_IfaceNum;
bool m_HasEndpointOut;
};
}

View File

@ -1,84 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#define LOG_PREFIX CXBXR_MODULE::RINP
#include "RawDevice.h"
#include "Logging.h"
#include <array>
// NOTE: we don't implement host input devices controlled by rawinput, we only use the api to detect device changes for xinput
namespace RawInput
{
int InitStatus = NOT_INIT;
bool IgnoreHotplug = true;
void Init(std::mutex &Mtx, bool is_gui, HWND hwnd)
{
std::unique_lock<std::mutex> lck(Mtx);
if (is_gui) {
// We don't need to monitor xinput device changes from the gui, because there we have the refresh button to detect changes
InitStatus = INIT_SUCCESS;
return;
}
std::array<RAWINPUTDEVICE, 3> devices;
// joystick devices
devices[0].usUsagePage = 0x01;
devices[0].usUsage = 0x04;
devices[0].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
devices[0].hwndTarget = hwnd;
// gamepad devices
devices[1].usUsagePage = 0x01;
devices[1].usUsage = 0x05;
devices[1].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
devices[1].hwndTarget = hwnd;
// multi axis controller devices
devices[2].usUsagePage = 0x01;
devices[2].usUsage = 0x08;
devices[2].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
devices[2].hwndTarget = hwnd;
if (!RegisterRawInputDevices(devices.data(), static_cast<UINT>(devices.size()),
static_cast<UINT>(sizeof(decltype(devices)::value_type))))
{
EmuLog(LOG_LEVEL::ERROR2, "RegisterRawInputDevices failed: %i", GetLastError());
InitStatus = INIT_ERROR;
return;
}
InitStatus = INIT_SUCCESS;
}
void DeInit()
{
InitStatus = NOT_INIT;
IgnoreHotplug = true;
}
}

View File

@ -1,51 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include "Windows.h"
#include <mutex>
namespace RawInput
{
typedef enum _INIT_STATUS : int
{
NOT_INIT = -2,
INIT_ERROR,
INIT_SUCCESS,
}
INIT_STATUS;
extern int InitStatus;
extern bool IgnoreHotplug;
// initialize RawInput
void Init(std::mutex &Mtx, bool is_gui, HWND hwnd);
// shutdown RawInput
void DeInit();
}

View File

@ -35,13 +35,12 @@
#define LOG_PREFIX CXBXR_MODULE::SDL
#include <assert.h>
#include <algorithm>
#include <thread>
#include "core\kernel\support\Emu.h"
#include "core\kernel\init\CxbxKrnl.h"
#include "SdlJoystick.h"
#include "XInputPad.h"
#include "DInputKeyboardMouse.h"
#include "LibusbDevice.h"
#include "InputManager.h"
// These values are those used by Dolphin!
@ -55,8 +54,8 @@ namespace Sdl
uint32_t PopulateEvent_t;
uint32_t UpdateInputEvent_t;
uint32_t DeviceRemoveAck_t;
int InitStatus = NOT_INIT;
bool PopulateOK = false;
int SdlInitStatus = SDL_NOT_INIT;
bool SdlPopulateOK = false;
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui)
{
@ -66,7 +65,7 @@ namespace Sdl
if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC) < 0) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to initialize SDL subsystem! The error was: %s", SDL_GetError());
InitStatus = INIT_ERROR;
SdlInitStatus = SDL_INIT_ERROR;
lck.unlock();
Cv.notify_one();
return;
@ -75,7 +74,7 @@ namespace Sdl
if (CustomEvent_t == (uint32_t)-1) {
SDL_Quit();
EmuLog(LOG_LEVEL::ERROR2, "Failed to create SDL custom events!");
InitStatus = INIT_ERROR;
SdlInitStatus = SDL_INIT_ERROR;
lck.unlock();
Cv.notify_one();
return;
@ -85,6 +84,8 @@ namespace Sdl
UpdateInputEvent_t = CustomEvent_t + 2;
DeviceRemoveAck_t = CustomEvent_t + 3;
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
// Drain all joystick add/remove events to avoid creating duplicated
// devices when we call PopulateDevices
while (SDL_PollEvent(&Event))
@ -97,7 +98,7 @@ namespace Sdl
break;
}
}
InitStatus = INIT_SUCCESS;
SdlInitStatus = SDL_INIT_SUCCESS;
lck.unlock();
Cv.notify_one();
@ -105,7 +106,6 @@ namespace Sdl
{
if (Event.type == SDL_JOYDEVICEADDED) {
OpenSdlDevice(Event.jdevice.which);
g_InputDeviceManager.HotplugHandler(true);
}
else if (Event.type == SDL_JOYDEVICEREMOVED) {
CloseSdlDevice(Event.jdevice.which);
@ -134,6 +134,10 @@ namespace Sdl
case SDL_JOYBUTTONUP:
id = Event.jbutton.which;
break;
default: {
// unreachable
}
}
auto dev = g_InputDeviceManager.FindDevice(id);
if (dev != nullptr) {
@ -144,7 +148,7 @@ namespace Sdl
for (int i = 0; i < SDL_NumJoysticks(); i++) {
OpenSdlDevice(i);
}
PopulateOK = true;
SdlPopulateOK = true;
Cv.notify_one();
}
else if (Event.type == ExitEvent_t) {
@ -157,23 +161,15 @@ namespace Sdl
else {
XInput::GetDeviceChanges();
DInput::GetDeviceChanges();
Libusb::GetDeviceChanges();
std::string port = std::to_string(*static_cast<int *>(Event.user.data1));
int port_num, slot;
PortStr2Int(port, &port_num, &slot);
g_InputDeviceManager.UpdateDevices(port, false);
// Force an update of the entire slot connectivity of this port
g_InputDeviceManager.UpdateDevices(port + ".0", false);
g_InputDeviceManager.UpdateDevices(port + ".1", false);
g_InputDeviceManager.UpdateDevices(*static_cast<int *>(Event.user.data1), false);
}
delete static_cast<int *>(Event.user.data1);
delete Event.user.data1;
Event.user.data1 = nullptr;
}
else if (Event.type == DeviceRemoveAck_t) {
g_InputDeviceManager.UpdateDevices(*static_cast<std::string *>(Event.user.data1), true);
delete static_cast<std::string *>(Event.user.data1);
g_InputDeviceManager.UpdateDevices(*static_cast<int*>(Event.user.data1), true);
delete Event.user.data1;
Event.user.data1 = nullptr;
}
}
@ -183,7 +179,7 @@ namespace Sdl
void DeInit(std::thread& Thr)
{
InitStatus = NOT_INIT;
SdlInitStatus = SDL_NOT_INIT;
if (!Thr.joinable()) {
return;
}

View File

@ -35,20 +35,20 @@
namespace Sdl
{
typedef enum _INIT_STATUS : int
typedef enum _SDL_INIT_STATUS : int
{
NOT_INIT = -2,
INIT_ERROR,
INIT_SUCCESS,
SDL_NOT_INIT = -2,
SDL_INIT_ERROR,
SDL_INIT_SUCCESS,
}
INIT_STATUS;
SDL_INIT_STATUS;
extern uint32_t ExitEvent_t;
extern uint32_t PopulateEvent_t;
extern uint32_t UpdateInputEvent_t;
extern uint32_t DeviceRemoveAck_t;
extern int InitStatus;
extern bool PopulateOK;
extern int SdlInitStatus;
extern bool SdlPopulateOK;
// initialize SDL
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui);

View File

@ -70,7 +70,7 @@ namespace XInput
static XInputGetState_t PXInputGetState = nullptr;
static bool haveGuideButton = false;
int InitStatus = NOT_INIT;
int XInputInitStatus = XINPUT_NOT_INIT;
uint8_t DevicesConnected = 0;
static const struct
@ -118,7 +118,7 @@ namespace XInput
hXInput = ::LoadLibrary(TEXT(xinput_dll_name.c_str()));
if (!hXInput) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to initialize XInput subsystem!");
InitStatus = INIT_ERROR;
XInputInitStatus = XINPUT_INIT_ERROR;
return;
}
}
@ -147,15 +147,15 @@ namespace XInput
::FreeLibrary(hXInput);
hXInput = nullptr;
EmuLog(LOG_LEVEL::ERROR2, "Failed to find XInput functions!");
InitStatus = INIT_ERROR;
XInputInitStatus = XINPUT_INIT_ERROR;
return;
}
InitStatus = INIT_SUCCESS;
XInputInitStatus = XINPUT_INIT_SUCCESS;
}
void DeInit()
{
InitStatus = NOT_INIT;
XInputInitStatus = XINPUT_NOT_INIT;
if (hXInput)
{
::FreeLibrary(hXInput);

View File

@ -34,15 +34,15 @@
namespace XInput
{
typedef enum _INIT_STATUS : int
typedef enum _XINPUT_INIT_STATUS : int
{
NOT_INIT = -2,
INIT_ERROR,
INIT_SUCCESS,
XINPUT_NOT_INIT = -2,
XINPUT_INIT_ERROR,
XINPUT_INIT_SUCCESS,
}
INIT_STATUS;
XINPUT_INIT_STATUS;
extern int InitStatus;
extern int XInputInitStatus;
extern uint8_t DevicesConnected;
// initialize XInput

View File

@ -0,0 +1,88 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2019 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#ifndef CXBXR_EMU_EXPORTS
#include "gui/resource/ResCxbx.h"
static int button_xbox_ctrl_id[XBOX_CTRL_NUM_BUTTONS] = {
IDC_SET_DPAD_UP,
IDC_SET_DPAD_DOWN,
IDC_SET_DPAD_LEFT,
IDC_SET_DPAD_RIGHT,
IDC_SET_START,
IDC_SET_BACK,
IDC_SET_LTHUMB,
IDC_SET_RTHUMB,
IDC_SET_A,
IDC_SET_B,
IDC_SET_X,
IDC_SET_Y,
IDC_SET_BLACK,
IDC_SET_WHITE,
IDC_SET_LTRIGGER,
IDC_SET_RTRIGGER,
IDC_SET_LEFT_POSX,
IDC_SET_LEFT_NEGX,
IDC_SET_LEFT_POSY,
IDC_SET_LEFT_NEGY,
IDC_SET_RIGHT_POSX,
IDC_SET_RIGHT_NEGX,
IDC_SET_RIGHT_POSY,
IDC_SET_RIGHT_NEGY,
IDC_SET_MOTOR,
};
#endif
static const char* button_xbox_ctrl_names[XBOX_CTRL_NUM_BUTTONS][3] = {
"D Pad Up", "Pad N", "UP",
"D Pad Down", "Pad S", "DOWN",
"D Pad Left", "Pad W", "LEFT",
"D Pad Right", "Pad E", "RIGHT",
"Start", "Start", "RETURN",
"Back", "Back", "SPACE",
"L Thumb", "Thumb L", "B",
"R Thumb", "Thumb R", "M",
"A", "Button A", "S",
"B", "Button B", "D",
"X", "Button X", "W",
"Y", "Button Y", "E",
"Black", "Shoulder R", "C",
"White", "Shoulder L", "X",
"L Trigger", "Trigger L", "Q",
"R Trigger", "Trigger R", "R",
"Left Axis X+", "Left X+", "H",
"Left Axis X-", "Left X-", "F",
"Left Axis Y+", "Left Y+", "T",
"Left Axis Y-", "Left Y-", "G",
"Right Axis X+", "Right X+", "L",
"Right Axis X-", "Right X-", "J",
"Right Axis Y+", "Right Y+", "I",
"Right Axis Y-", "Right Y-", "K",
"Motor", "LeftRight", "",
};

View File

@ -1,282 +0,0 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2019 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#ifndef CXBXR_EMU_EXPORTS
#include "gui/resource/ResCxbx.h"
// Must have the same button order as defined in XINPUT_GAMEPAD
inline int button_xbox_ctrl_id[XBOX_CTRL_NUM_BUTTONS] = {
IDC_SET_DPAD_UP,
IDC_SET_DPAD_DOWN,
IDC_SET_DPAD_LEFT,
IDC_SET_DPAD_RIGHT,
IDC_SET_START,
IDC_SET_BACK,
IDC_SET_LTHUMB,
IDC_SET_RTHUMB,
IDC_SET_A,
IDC_SET_B,
IDC_SET_X,
IDC_SET_Y,
IDC_SET_BLACK,
IDC_SET_WHITE,
IDC_SET_LTRIGGER,
IDC_SET_RTRIGGER,
IDC_SET_LEFT_POSX,
IDC_SET_LEFT_NEGX,
IDC_SET_LEFT_POSY,
IDC_SET_LEFT_NEGY,
IDC_SET_RIGHT_POSX,
IDC_SET_RIGHT_NEGX,
IDC_SET_RIGHT_POSY,
IDC_SET_RIGHT_NEGY,
IDC_SET_MOTOR,
};
// Must have the same button order as defined in SBC_GAMEPAD
inline int button_sbc_id[SBC_NUM_BUTTONS] = {
IDC_BTN_MAIN_WEAPON,
IDC_BTN_SUB_WEAPON,
IDC_BTN_LOCK_ON,
IDC_BTN_EJECT,
IDC_BTN_COCKPIT_HATCH,
IDC_BTN_IGNITION,
IDC_BTN_START,
IDC_BTN_OPEN_CLOSE,
IDC_BTN_MAP_ZOOM_IN_OUT,
IDC_BTN_MODE_SELECT,
IDC_BTN_SUB_MONITOR_MODE_SELECT,
IDC_BTN_ZOOM_IN,
IDC_BTN_ZOOM_OUT,
IDC_BTN_FSS,
IDC_BTN_MANIPULATOR,
IDC_BTN_LINE_COLOR_CHANGE,
IDC_BTN_WASHING,
IDC_BTN_EXTINGUISHER,
IDC_BTN_CHAFF,
IDC_BTN_TANK_DETACH,
IDC_BTN_OVERRIDE,
IDC_BTN_NIGHT_SCOPE,
IDC_BTN_FUNC1,
IDC_BTN_FUNC2,
IDC_BTN_FUNC3,
IDC_BTN_MAIN_WEAPON_CONTROL,
IDC_BTN_SUB_WEAPON_CONTROL,
IDC_BTN_MAGAZINE_CHANGE,
IDC_BTN_COM1,
IDC_BTN_COM2,
IDC_BTN_COM3,
IDC_BTN_COM4,
IDC_BTN_COM5,
IDC_BTN_SIGHT_CHANGE,
IDC_FILT_CONTROL_SYSTEM,
IDC_OXYGEN_SUPPLY_SYSTEM,
IDC_FUEL_FLOW_RATE,
IDC_BUFFER_MATERIAL,
IDC_VT_LOCATION_MEASUREMENT,
IDC_AIMING_POSX,
IDC_AIMING_NEGX,
IDC_AIMING_POSY,
IDC_AIMING_NEGY,
IDC_LEVER_LEFT,
IDC_LEVER_RIGHT,
IDC_SIGHT_CHANGE_POSX,
IDC_SIGHT_CHANGE_NEGX,
IDC_SIGHT_CHANGE_POSY,
IDC_SIGHT_CHANGE_NEGY,
IDC_BTN_LEFT_PEDAL,
IDC_BTN_MIDDLE_PEDAL,
IDC_BTN_RIGHT_PEDAL,
IDC_RADIO_TD_UP,
IDC_RADIO_TD_DOWN,
IDC_GEAR_UP,
IDC_GEAR_DOWN,
};
// Must have the same button order as defined in button_lightgun_names
inline int button_lightgun_id[LIGHTGUN_NUM_BUTTONS] = {
IDC_LG_STICK_UP,
IDC_LG_STICK_DOWN,
IDC_LG_STICK_LEFT,
IDC_LG_STICK_RIGHT,
IDC_LG_START,
IDC_LG_SEBA,
IDC_LG_TRIGGER,
IDC_LG_GRIP,
IDC_LG_A,
IDC_LG_B,
IDC_LG_AIM_POSX,
IDC_LG_AIM_NEGX,
IDC_LG_AIM_POSY,
IDC_LG_AIM_NEGY,
IDC_TURBO_LEFT,
IDC_TURBO_RIGHT,
IDC_LASER,
};
#endif
inline constexpr const char* button_xbox_ctrl_names[XBOX_CTRL_NUM_BUTTONS] = {
"D Pad Up",
"D Pad Down",
"D Pad Left",
"D Pad Right",
"Start",
"Back",
"L Thumb",
"R Thumb",
"A",
"B",
"X",
"Y",
"Black",
"White",
"L Trigger",
"R Trigger",
"Left Axis X+",
"Left Axis X-",
"Left Axis Y+",
"Left Axis Y-",
"Right Axis X+",
"Right Axis X-",
"Right Axis Y+",
"Right Axis Y-",
"Motor",
};
inline constexpr const char *button_sbc_names[SBC_NUM_BUTTONS] = {
"RightJoyMainWeapon",
"RightJoyFire",
"RightJoyLockOn",
"Eject",
"CockpitHatch",
"Ignition",
"Start",
"MultiMonOpenClose",
"MultiMonMapZoomInOut",
"MultiMonModeSelect",
"MultiMonSubMonitor",
"MainMonZoomIn",
"MainMonZoomOut",
"FunctionFSS",
"FunctionManipulator",
"FunctionLineColorChange",
"Washing",
"Extinguisher",
"Chaff",
"FunctionTankDetach",
"FunctionOverride",
"FunctionNightScope",
"FunctionF1",
"FunctionF2",
"FunctionF3",
"WeaponConMain",
"WeaponConSub",
"WeaponConMagazine",
"Comm1",
"Comm2",
"Comm3",
"Comm4",
"Comm5",
"LeftJoySightChange",
"ToggleFilterControl",
"ToggleOxygenSupply",
"ToggleFuelFlowRate",
"ToggleBufferMaterial",
"ToggleVTLocation",
"Aiming X+",
"Aiming X-",
"Aiming Y+",
"Aiming Y-",
"LeverLeft",
"LeverRight",
"SightChange X+",
"SightChange X-",
"SightChange Y+",
"SightChange Y-",
"LeftPedal",
"MiddlePedal",
"RightPedal",
"TunerDial Up",
"TunerDial Down",
"GearLever Up",
"GearLever Down",
};
inline constexpr const char *button_lightgun_names[LIGHTGUN_NUM_BUTTONS] = {
"Stick Up",
"Stick Down",
"Stick Left",
"Stick Right",
"START",
"SE/BA",
"Trigger",
"Grip",
"A",
"B",
"Aim X+",
"Aim X-",
"Aim Y+",
"Aim Y-",
"Turbo Left",
"Turbo Right",
"Laser",
};
constexpr bool check_button_name_size(unsigned max_num_buttons)
{
switch (max_num_buttons)
{
case XBOX_CTRL_NUM_BUTTONS: {
for (unsigned i = 0; i < max_num_buttons; i++) {
if (std::char_traits<char>::length(button_xbox_ctrl_names[i]) > (XBOX_BUTTON_NAME_LENGTH - 1)) {
return false;
}
}
}
break;
case SBC_NUM_BUTTONS: {
for (unsigned i = 0; i < max_num_buttons; i++) {
if (std::char_traits<char>::length(button_sbc_names[i]) > (XBOX_BUTTON_NAME_LENGTH - 1)) {
return false;
}
}
}
break;
default:
return false;
}
return true;
}
// Sanity checks: the button buffers used in the input system are 30 bytes large, so ensure that we do not exceed them
static_assert(check_button_name_size(XBOX_CTRL_NUM_BUTTONS));
static_assert(check_button_name_size(SBC_NUM_BUTTONS));

View File

@ -52,6 +52,7 @@
#include <cstring> // For memcpy
#include "common\util\CxbxUtil.h"
#include "core\kernel\init\CxbxKrnl.h"
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))

View File

@ -26,15 +26,12 @@
#ifndef CXBXUTIL_H
#define CXBXUTIL_H
#include <algorithm>
#include <stdexcept>
#include "xbox_types.h"
#include "Cxbx.h"
#include <stdint.h>
#include <assert.h>
#include <string>
#include <type_traits>
#include <vector>
#include "std_extend.hpp" // for ARRAY_SIZE
/* This is a linux struct for vectored I/O. See readv() and writev() */
@ -93,17 +90,4 @@ static uint32_t RoundUp(uint32_t dwValue, uint32_t dwMult)
return dwValue + dwMult - remainder;
}
constexpr std::size_t longest_str(const std::vector<std::string_view> &vec)
{
if (!vec.empty()) {
return std::max_element(vec.begin(), vec.end(),
[](const auto &a, const auto &b) {
return a.length() < b.length();
})->length();
}
else {
throw std::logic_error("No strings to compare!");
}
}
#endif

View File

@ -60,15 +60,6 @@ bool hasKey(std::string key)
return false;
}
// Delete the key if it exist
void DeleteKey(std::string key)
{
auto found = g_cli_configs.find(key);
if (found != g_cli_configs.end()) {
g_cli_configs.erase(found);
}
}
// Generic getter
bool GetValue(const std::string key, std::string* value)
{
@ -188,12 +179,4 @@ void SetSystemType(const std::string value)
}
}
void ClearSystemType()
{
// Clear any system types key existence.
DeleteKey(cli_config::system_retail);
DeleteKey(cli_config::system_devkit);
DeleteKey(cli_config::system_chihiro);
}
}

View File

@ -57,6 +57,5 @@ long long GetSessionID();
void SetLoad(const std::string value);
void SetSystemType(const std::string value);
void ClearSystemType();
}

335
src/common/util/crc32c.cpp Normal file
View File

@ -0,0 +1,335 @@
/*
Copyright (c) 2013 - 2014, 2016 Mark Adler, Robert Vazan, Max Vysokikh
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "crc32c.h"
#include <intrin.h>
#include <algorithm>
#define POLY 0x82f63b78
#define LONG_SHIFT 8192
#define SHORT_SHIFT 256
typedef const uint8_t *buffer;
static uint32_t table[16][256];
static uint32_t long_shifts[4][256];
static uint32_t short_shifts[4][256];
static bool _tableInitialized;
void calculate_table();
/* Table-driven software version as a fall-back. This is about 15 times slower
than using the hardware instructions. This assumes little-endian integers,
as is the case on Intel processors that the assembler code here is for. */
extern "C" CRC32C_API uint32_t crc32c_append_sw(uint32_t crci, buffer input, size_t length)
{
buffer next = input;
#ifdef _M_X64
uint64_t crc;
#else
uint32_t crc;
#endif
crc = crci ^ 0xffffffff;
#ifdef _M_X64
while (length && ((uintptr_t)next & 7) != 0)
{
crc = table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
--length;
}
while (length >= 16)
{
crc ^= *(uint64_t *)next;
uint64_t high = *(uint64_t *)(next + 8);
crc = table[15][crc & 0xff]
^ table[14][(crc >> 8) & 0xff]
^ table[13][(crc >> 16) & 0xff]
^ table[12][(crc >> 24) & 0xff]
^ table[11][(crc >> 32) & 0xff]
^ table[10][(crc >> 40) & 0xff]
^ table[9][(crc >> 48) & 0xff]
^ table[8][crc >> 56]
^ table[7][high & 0xff]
^ table[6][(high >> 8) & 0xff]
^ table[5][(high >> 16) & 0xff]
^ table[4][(high >> 24) & 0xff]
^ table[3][(high >> 32) & 0xff]
^ table[2][(high >> 40) & 0xff]
^ table[1][(high >> 48) & 0xff]
^ table[0][high >> 56];
next += 16;
length -= 16;
}
#else
while (length && ((uintptr_t)next & 3) != 0)
{
crc = table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
--length;
}
while (length >= 12)
{
crc ^= *(uint32_t *)next;
uint32_t high = *(uint32_t *)(next + 4);
uint32_t high2 = *(uint32_t *)(next + 8);
crc = table[11][crc & 0xff]
^ table[10][(crc >> 8) & 0xff]
^ table[9][(crc >> 16) & 0xff]
^ table[8][crc >> 24]
^ table[7][high & 0xff]
^ table[6][(high >> 8) & 0xff]
^ table[5][(high >> 16) & 0xff]
^ table[4][high >> 24]
^ table[3][high2 & 0xff]
^ table[2][(high2 >> 8) & 0xff]
^ table[1][(high2 >> 16) & 0xff]
^ table[0][high2 >> 24];
next += 12;
length -= 12;
}
#endif
while (length)
{
crc = table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
--length;
}
return (uint32_t)crc ^ 0xffffffff;
}
/* Apply the zeros operator table to crc. */
static inline uint32_t shift_crc(uint32_t shift_table[][256], uint32_t crc)
{
return shift_table[0][crc & 0xff]
^ shift_table[1][(crc >> 8) & 0xff]
^ shift_table[2][(crc >> 16) & 0xff]
^ shift_table[3][crc >> 24];
}
/* Compute CRC-32C using the Intel hardware instruction. */
extern "C" CRC32C_API uint32_t crc32c_append_hw(uint32_t crc, buffer buf, size_t len)
{
buffer next = buf;
buffer end;
#ifdef _M_X64
uint64_t crc0, crc1, crc2; /* need to be 64 bits for crc32q */
#else
uint32_t crc0, crc1, crc2;
#endif
/* pre-process the crc */
crc0 = crc ^ 0xffffffff;
/* compute the crc for up to seven leading bytes to bring the data pointer
to an eight-byte boundary */
while (len && ((uintptr_t)next & 7) != 0)
{
crc0 = _mm_crc32_u8(static_cast<uint32_t>(crc0), *next);
++next;
--len;
}
#ifdef _M_X64
/* compute the crc on sets of LONG_SHIFT*3 bytes, executing three independent crc
instructions, each on LONG_SHIFT bytes -- this is optimized for the Nehalem,
Westmere, Sandy Bridge, and Ivy Bridge architectures, which have a
throughput of one crc per cycle, but a latency of three cycles */
while (len >= 3 * LONG_SHIFT)
{
crc1 = 0;
crc2 = 0;
end = next + LONG_SHIFT;
do
{
crc0 = _mm_crc32_u64(crc0, *reinterpret_cast<const uint64_t *>(next));
crc1 = _mm_crc32_u64(crc1, *reinterpret_cast<const uint64_t *>(next + LONG_SHIFT));
crc2 = _mm_crc32_u64(crc2, *reinterpret_cast<const uint64_t *>(next + 2 * LONG_SHIFT));
next += 8;
} while (next < end);
crc0 = shift_crc(long_shifts, static_cast<uint32_t>(crc0)) ^ crc1;
crc0 = shift_crc(long_shifts, static_cast<uint32_t>(crc0)) ^ crc2;
next += 2 * LONG_SHIFT;
len -= 3 * LONG_SHIFT;
}
/* do the same thing, but now on SHORT_SHIFT*3 blocks for the remaining data less
than a LONG_SHIFT*3 block */
while (len >= 3 * SHORT_SHIFT)
{
crc1 = 0;
crc2 = 0;
end = next + SHORT_SHIFT;
do
{
crc0 = _mm_crc32_u64(crc0, *reinterpret_cast<const uint64_t *>(next));
crc1 = _mm_crc32_u64(crc1, *reinterpret_cast<const uint64_t *>(next + SHORT_SHIFT));
crc2 = _mm_crc32_u64(crc2, *reinterpret_cast<const uint64_t *>(next + 2 * SHORT_SHIFT));
next += 8;
} while (next < end);
crc0 = shift_crc(short_shifts, static_cast<uint32_t>(crc0)) ^ crc1;
crc0 = shift_crc(short_shifts, static_cast<uint32_t>(crc0)) ^ crc2;
next += 2 * SHORT_SHIFT;
len -= 3 * SHORT_SHIFT;
}
/* compute the crc on the remaining eight-byte units less than a SHORT_SHIFT*3
block */
end = next + (len - (len & 7));
while (next < end)
{
crc0 = _mm_crc32_u64(crc0, *reinterpret_cast<const uint64_t *>(next));
next += 8;
}
#else
/* compute the crc on sets of LONG_SHIFT*3 bytes, executing three independent crc
instructions, each on LONG_SHIFT bytes -- this is optimized for the Nehalem,
Westmere, Sandy Bridge, and Ivy Bridge architectures, which have a
throughput of one crc per cycle, but a latency of three cycles */
while (len >= 3 * LONG_SHIFT)
{
crc1 = 0;
crc2 = 0;
end = next + LONG_SHIFT;
do
{
crc0 = _mm_crc32_u32(crc0, *reinterpret_cast<const uint32_t *>(next));
crc1 = _mm_crc32_u32(crc1, *reinterpret_cast<const uint32_t *>(next + LONG_SHIFT));
crc2 = _mm_crc32_u32(crc2, *reinterpret_cast<const uint32_t *>(next + 2 * LONG_SHIFT));
next += 4;
} while (next < end);
crc0 = shift_crc(long_shifts, static_cast<uint32_t>(crc0)) ^ crc1;
crc0 = shift_crc(long_shifts, static_cast<uint32_t>(crc0)) ^ crc2;
next += 2 * LONG_SHIFT;
len -= 3 * LONG_SHIFT;
}
/* do the same thing, but now on SHORT_SHIFT*3 blocks for the remaining data less
than a LONG_SHIFT*3 block */
while (len >= 3 * SHORT_SHIFT)
{
crc1 = 0;
crc2 = 0;
end = next + SHORT_SHIFT;
do
{
crc0 = _mm_crc32_u32(crc0, *reinterpret_cast<const uint32_t *>(next));
crc1 = _mm_crc32_u32(crc1, *reinterpret_cast<const uint32_t *>(next + SHORT_SHIFT));
crc2 = _mm_crc32_u32(crc2, *reinterpret_cast<const uint32_t *>(next + 2 * SHORT_SHIFT));
next += 4;
} while (next < end);
crc0 = shift_crc(short_shifts, static_cast<uint32_t>(crc0)) ^ crc1;
crc0 = shift_crc(short_shifts, static_cast<uint32_t>(crc0)) ^ crc2;
next += 2 * SHORT_SHIFT;
len -= 3 * SHORT_SHIFT;
}
/* compute the crc on the remaining eight-byte units less than a SHORT_SHIFT*3
block */
end = next + (len - (len & 7));
while (next < end)
{
crc0 = _mm_crc32_u32(crc0, *reinterpret_cast<const uint32_t *>(next));
next += 4;
}
#endif
len &= 7;
/* compute the crc for up to seven trailing bytes */
while (len)
{
crc0 = _mm_crc32_u8(static_cast<uint32_t>(crc0), *next);
++next;
--len;
}
/* return a post-processed crc */
return static_cast<uint32_t>(crc0) ^ 0xffffffff;
}
extern "C" CRC32C_API int crc32c_hw_available()
{
int info[4];
__cpuid(info, 1);
return (info[2] & (1 << 20)) != 0;
}
void calculate_table()
{
for(int i = 0; i < 256; i++)
{
uint32_t res = (uint32_t)i;
for(int t = 0; t < 16; t++) {
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? POLY ^ (res >> 1) : (res >> 1);
table[t][i] = res;
}
}
_tableInitialized = true;
}
void calculate_table_hw()
{
for(int i = 0; i < 256; i++)
{
uint32_t res = (uint32_t)i;
for (int k = 0; k < 8 * (SHORT_SHIFT - 4); k++) res = (res & 1) == 1 ? POLY ^ (res >> 1) : (res >> 1);
for(int t = 0; t < 4; t++) {
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? POLY ^ (res >> 1) : (res >> 1);
short_shifts[3 - t][i] = res;
}
for (int k = 0; k < 8 * (LONG_SHIFT - 4 - SHORT_SHIFT); k++) res = (res & 1) == 1 ? POLY ^ (res >> 1) : (res >> 1);
for(int t = 0; t < 4; t++) {
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? POLY ^ (res >> 1) : (res >> 1);
long_shifts[3 - t][i] = res;
}
}
}
uint32_t (*append_func)(uint32_t, buffer, size_t);
void __crc32_init()
{
if (append_func == NULL)
{
// somebody can call sw version directly, so, precalculate table for this version
calculate_table();
if (crc32c_hw_available()) {
calculate_table_hw();
append_func = crc32c_append_hw;
} else {
append_func = crc32c_append_sw;
}
}
}
extern "C" CRC32C_API uint32_t crc32c_append(uint32_t crc, buffer input, size_t length)
{
if (append_func == NULL) {
__crc32_init();
}
return append_func(crc, input, length);
}

35
src/common/util/crc32c.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef CRC32C_H
#define CRC32C_H
#define CRC32C_API
#include <stdint.h>
/*
Computes CRC-32C (Castagnoli) checksum. Uses Intel's CRC32 instruction if it is available.
Otherwise it uses a very fast software fallback.
*/
extern "C" CRC32C_API uint32_t crc32c_append(
uint32_t crc, // Initial CRC value. Typically it's 0.
// You can supply non-trivial initial value here.
// Initial value can be used to chain CRC from multiple buffers.
const uint8_t *input, // Data to be put through the CRC algorithm.
size_t length); // Length of the data in the input buffer.
/*
Software fallback version of CRC-32C (Castagnoli) checksum.
*/
extern "C" CRC32C_API uint32_t crc32c_append_sw(uint32_t crc, const uint8_t *input, size_t length);
/*
Hardware version of CRC-32C (Castagnoli) checksum. Will fail, if CPU does not support related instructions. Use a crc32c_append version instead of.
*/
extern "C" CRC32C_API uint32_t crc32c_append_hw(uint32_t crc, const uint8_t *input, size_t length);
/*
Checks is hardware version of CRC-32C is available.
*/
extern "C" CRC32C_API int crc32c_hw_available();
#endif

View File

@ -0,0 +1,42 @@
#include "hasher.h"
#include "xxhash.h"
#include "crc32c.h"
#include <cstdio>
enum {
HASH_NONE = 0,
HASH_XXH3,
HASH_CRC32C
};
static int g_HashAlgorithm = HASH_NONE;
void InitHasher()
{
// Detect the best hashing algorithm to use for the host machine
// TODO/Future Improvement: This could be expanded to support even more hash algorithims
// And we could hash a random buffer to calculate the fastest hash to use on a given host
printf("Selecting hash algorithm: ");
if (crc32c_hw_available()) {
printf("CRC32C\n");
g_HashAlgorithm = HASH_CRC32C;
} else {
printf("XXH3\n");
g_HashAlgorithm = HASH_XXH3;
}
}
uint64_t ComputeHash(void* data, size_t len)
{
if (g_HashAlgorithm == HASH_NONE) {
InitHasher();
}
switch (g_HashAlgorithm) {
case HASH_XXH3: return XXH3_64bits(data, len);
case HASH_CRC32C: return crc32c_append(0, (uint8_t*)data, len);
}
return 0;
}

View File

@ -27,7 +27,8 @@
#ifndef _HASHER_H
#define _HASHER_H
#include "xxhash.h"
#define ComputeHash XXH3_64bits
#include <stdint.h>
uint64_t ComputeHash(void* data, size_t len);
#endif

View File

@ -25,8 +25,7 @@
// *
// ******************************************************************
#include "cxbxr.hpp"
#include "core\kernel\init\CxbxKrnl.h"
#include "core\kernel\support\Emu.h"
#include "EmuShared.h"
@ -84,9 +83,8 @@ bool EmuShared::Init(long long sessionID)
emuSharedStr.c_str() // name of map object
);
if (hMapObject == NULL) {
CxbxrAbortEx(CXBXR_MODULE::INIT, "Could not map shared memory!");
}
if(hMapObject == NULL)
return false; // CxbxKrnlCleanupEx(CXBXR_MODULE::INIT, "Could not map shared memory!");
if(GetLastError() == ERROR_ALREADY_EXISTS)
bRequireConstruction = false;
@ -107,7 +105,7 @@ bool EmuShared::Init(long long sessionID)
if (g_EmuShared == nullptr) {
CloseHandle(hMapObject);
CxbxrAbortEx(CXBXR_MODULE::INIT, "Could not map view of shared memory!");
return false; // CxbxKrnlCleanupEx(CXBXR_MODULE::INIT, "Could not map view of shared memory!");
}
}
@ -154,18 +152,19 @@ EmuShared::EmuShared()
m_bEmulating_status = false;
m_bFirstLaunch = false;
m_bClipCursor = false;
m_LightgunLaser = 0xF; // laser on by default on all ports
// Reserve space (default to 0)
m_bReserved3 = false;
m_bReserved4 = false;
m_Reserved5 = 0;
m_Reserved6 = 0.0f;
std::memset(m_Reserved7, 0, sizeof(m_Reserved7));
std::memset(m_Reserved99, 0, sizeof(m_Reserved99));
std::memset(m_DeviceControlNames, '\0', sizeof(m_DeviceControlNames));
std::memset(m_DeviceName, '\0', sizeof(m_DeviceName));
m_imgui_general.ini_size = IMGUI_INI_SIZE_MAX;
std::memset(&m_imgui_general.ini_settings, 0, sizeof(m_imgui_general.ini_settings));
std::memset(&m_imgui_audio_windows, 0, sizeof(m_imgui_audio_windows));
std::memset(&m_imgui_video_windows, 0, sizeof(m_imgui_video_windows));
for (auto& i : m_DeviceType) {
i = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
}
std::strncpy(m_git_version, GetGitVersionStr(), GetGitVersionLength());
}
// ******************************************************************

View File

@ -30,9 +30,7 @@
#include "Mutex.h"
#include "common\IPCHybrid.hpp"
#include "common\input\Button.h"
#include "common/xbox_types.h"
#include "CxbxVersion.h"
#include "core/common/imgui/settings.h"
#include <memory.h>
extern HMODULE hActiveModule; // Equals EXE Module handle in (GUI) Cxbx.exe / cxbxr.exe, equals DLL Module handle in cxbxr-emu.dll
@ -67,11 +65,6 @@ class EmuShared : public Mutex
// ******************************************************************
unsigned int m_size;
// ******************************************************************
// * Git version string of the executable that first launched
// ******************************************************************
char m_git_version[GitVersionMaxLength];
// ******************************************************************
// * Each process needs to call this to initialize shared memory
// ******************************************************************
@ -135,25 +128,23 @@ class EmuShared : public Mutex
// ******************************************************************
void GetInputDevTypeSettings(int* type, int port) { Lock(); *type = m_DeviceType[port]; Unlock(); }
void SetInputDevTypeSettings(const int* type, int port) { Lock(); m_DeviceType[port] = *type; Unlock(); }
void GetInputSlotTypeSettings(int *type, int port, int slot) { Lock(); *type = m_SlotDeviceType[port][slot]; Unlock(); }
void SetInputSlotTypeSettings(const int *type, int port, int slot) { Lock(); m_SlotDeviceType[port][slot] = *type; Unlock(); }
void GetInputDevNameSettings(char* name, int port) { Lock(); strncpy(name, m_DeviceName[port], 50); Unlock(); }
void SetInputDevNameSettings(const char* name, int port) { Lock(); strncpy(m_DeviceName[port], name, 50); Unlock(); }
void GetInputBindingsSettings(char button_str[][HOST_BUTTON_NAME_LENGTH], int max_num_buttons, int port)
void GetInputBindingsSettings(char button_str[][30], int max_num_buttons, int port)
{
assert(max_num_buttons <= HIGHEST_NUM_BUTTONS);
assert(max_num_buttons <= XBOX_CTRL_NUM_BUTTONS);
Lock();
for (int i = 0; i < max_num_buttons; i++) {
strncpy(button_str[i], m_DeviceControlNames[port][i], HOST_BUTTON_NAME_LENGTH);
strncpy(button_str[i], m_DeviceControlNames[port][i], 30);
}
Unlock();
}
void SetInputBindingsSettings(const char button_str[][HOST_BUTTON_NAME_LENGTH], int max_num_buttons, int port)
void SetInputBindingsSettings(const char button_str[][30], int max_num_buttons, int port)
{
assert(max_num_buttons <= HIGHEST_NUM_BUTTONS);
assert(max_num_buttons <= XBOX_CTRL_NUM_BUTTONS);
Lock();
for (int i = 0; i < max_num_buttons; i++) {
strncpy(m_DeviceControlNames[port][i], button_str[i], HOST_BUTTON_NAME_LENGTH);
strncpy(m_DeviceControlNames[port][i], button_str[i], 30);
}
Unlock();
}
@ -161,8 +152,10 @@ class EmuShared : public Mutex
// ******************************************************************
// * Input option Accessors
// ******************************************************************
void GetInputGeneralSettings(Settings::s_input_general *input_general) { Lock(); *input_general = m_input_general; Unlock(); }
void SetInputGeneralSettings(const Settings::s_input_general *input_general) { Lock(); m_input_general = *input_general; Unlock(); }
void GetInputMoAxisSettings(long *axis) { Lock(); *axis = m_MoAxisRange; Unlock(); }
void SetInputMoAxisSettings(const long axis) { Lock(); m_MoAxisRange = axis; Unlock(); }
void GetInputMoWheelSettings(long *wheel) { Lock(); *wheel = m_MoWheelRange; Unlock(); }
void SetInputMoWheelSettings(const long wheel) { Lock(); m_MoWheelRange = wheel; Unlock(); }
// ******************************************************************
// * LLE Flags Accessors
@ -205,7 +198,7 @@ class EmuShared : public Mutex
// * Debugging flag Accessors
// ******************************************************************
void GetDebuggingFlag(bool *value) { Lock(); *value = m_bDebugging; Unlock(); }
void SetDebuggingFlag(const bool value) { Lock(); m_bDebugging = value; Unlock(); }
void SetDebuggingFlag(const bool *value) { Lock(); m_bDebugging = *value; Unlock(); }
#ifndef CXBX_LOADER // Temporary usage for cxbx.exe's emu
// ******************************************************************
// * Previous Memory Layout value Accessors
@ -246,85 +239,16 @@ class EmuShared : public Mutex
void SetLogPopupTestCase(const bool value) { Lock(); m_core.bLogPopupTestCase = value; Unlock(); }
// ******************************************************************
// * Data location path
// * File storage location
// ******************************************************************
void GetDataLocation(char *path) { Lock(); strncpy(path, m_core.szStorageLocation, xbox::max_path); Unlock(); }
void SetDataLocation(const char *path) { Lock(); strncpy(m_core.szStorageLocation, path, xbox::max_path); Unlock(); }
void GetStorageLocation(char *path) { Lock(); strncpy(path, m_core.szStorageLocation, MAX_PATH); Unlock(); }
void SetStorageLocation(const char *path) { Lock(); strncpy(m_core.szStorageLocation, path, MAX_PATH); Unlock(); }
// ******************************************************************
// * ClipCursor flag Accessors
// ******************************************************************
void GetClipCursorFlag(bool *value) { Lock(); *value = m_bClipCursor; Unlock(); }
void SetClipCursorFlag(const bool value) { Lock(); m_bClipCursor = value; Unlock(); }
// ******************************************************************
// * LightgunLaser flag Accessors
// ******************************************************************
void GetLightgunLaser(uint8_t *value, int port) { Lock(); *value = (m_LightgunLaser >> port) & 1; Unlock(); }
void SetLightgunLaser(const uint8_t *value, int port) { Lock(); (m_LightgunLaser &= ~(1 << port)) |= ((*value) << port); Unlock(); }
// ******************************************************************
// * ImGui Accessors
// ******************************************************************
void GetImGuiFocusFlag(bool *value) { Lock(); *value = m_imgui_general.is_focus; Unlock(); }
void SetImGuiFocusFlag(const bool value) { Lock(); m_imgui_general.is_focus = value; Unlock(); }
void GetImGuiIniSettings(char value[IMGUI_INI_SIZE_MAX]) {
Lock();
if (m_imgui_general.ini_size < IMGUI_INI_SIZE_MAX) {
value[0] = '\0';
return;
}
strcpy_s(value, IMGUI_INI_SIZE_MAX, m_imgui_general.ini_settings);
Unlock();
}
void SetImGuiIniSettings(const char value[IMGUI_INI_SIZE_MAX]) {
Lock();
// Do not save if external size is less than internal limit
if (m_imgui_general.ini_size < IMGUI_INI_SIZE_MAX) {
return;
}
strcpy_s(m_imgui_general.ini_settings, IMGUI_INI_SIZE_MAX, value);
Unlock();
}
void GetImGuiAudioWindows(imgui_audio_windows *value) { Lock(); *value = m_imgui_audio_windows; Unlock(); }
void SetImGuiAudioWindows(const imgui_audio_windows* value) { Lock(); m_imgui_audio_windows = *value; Unlock(); }
void GetImGuiVideoWindows(imgui_video_windows*value) { Lock(); *value = m_imgui_video_windows; Unlock(); }
void SetImGuiVideoWindows(const imgui_video_windows* value) { Lock(); m_imgui_video_windows = *value; Unlock(); }
// ******************************************************************
// * Overlay Accessors
// ******************************************************************
void GetOverlaySettings(overlay_settings *value) { Lock(); *value = m_imgui_overlay_settings; Unlock(); }
void SetOverlaySettings(const overlay_settings* value) { Lock(); m_imgui_overlay_settings = *value; Unlock(); }
// ******************************************************************
// * Git version Accessor (only the get method is provided because it should not be changed)
// ******************************************************************
void GetGitVersion(char *value)
{
Lock();
std::strncpy(value, m_git_version, GetGitVersionLength() + 1);
Unlock();
}
// ******************************************************************
// * TitleMountPath Accessor
// ******************************************************************
void GetTitleMountPath(char *value)
{
Lock();
std::strncpy(value, m_TitleMountPath, sizeof(m_TitleMountPath));
Unlock();
}
void SetTitleMountPath(const char* value)
{
Lock();
std::strncpy(m_TitleMountPath, value, sizeof(m_TitleMountPath) - 1);
Unlock();
}
void SetClipCursorFlag(const bool *value) { Lock(); m_bClipCursor = *value; Unlock(); }
// ******************************************************************
// * Reset specific variables to default for kernel mode.
@ -360,6 +284,8 @@ class EmuShared : public Mutex
// * Shared configuration
// ******************************************************************
int m_BootFlags_status;
unsigned int m_Reserved5;
float m_Reserved6;
float m_FPS_status; // NOTE: If move into ipc_send_gui_update will spam GUI's message system (one message per frame)
bool m_Krnl_Log_enabled; // Is require in order to preserve previous set for support multi-xbe.
bool m_bDebugging;
@ -367,18 +293,21 @@ class EmuShared : public Mutex
bool m_bEmulating_status;
#ifndef CXBX_LOADER // Temporary usage for cxbx.exe's emu
unsigned int m_PreviousMmLayout;
int m_Reserved7[3];
#else
unsigned int m_Reserved;
int m_Reserved7[4];
#endif
uint8_t m_LightgunLaser;
bool m_bFirstLaunch;
bool m_bClipCursor;
bool m_bReserved3;
bool m_bReserved4;
unsigned int m_dwKrnlProcID; // Only used for kernel mode level.
int m_DeviceType[XBOX_NUM_PORTS];
int m_SlotDeviceType[XBOX_NUM_PORTS][XBOX_CTRL_NUM_SLOTS];
char m_DeviceControlNames[XBOX_NUM_PORTS][HIGHEST_NUM_BUTTONS][HOST_BUTTON_NAME_LENGTH];
char m_DeviceName[XBOX_NUM_PORTS][50];
char m_TitleMountPath[xbox::max_path];
int m_DeviceType[4];
char m_DeviceControlNames[4][XBOX_CTRL_NUM_BUTTONS][30]; // macro should be num of buttons of dev with highest num buttons
char m_DeviceName[4][50];
long m_MoAxisRange;
long m_MoWheelRange;
int m_Reserved99[26]; // Reserve space
// Settings class in memory should not be tampered by third-party.
// Third-party program should only be allow to edit settings.ini file.
@ -386,12 +315,7 @@ class EmuShared : public Mutex
Settings::s_video m_video;
Settings::s_audio m_audio;
Settings::s_network m_network;
Settings::s_input_general m_input_general;
Settings::s_hack m_hacks;
imgui_general m_imgui_general;
overlay_settings m_imgui_overlay_settings;
imgui_audio_windows m_imgui_audio_windows;
imgui_video_windows m_imgui_video_windows;
};
// ******************************************************************

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