Compare commits
282 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4bfe3668f0 | |||
| 13aa88c3c4 | |||
| 439a78d12c | |||
| c7c49ab286 | |||
| 3972b176cd | |||
| 2a4f38959a | |||
| b01e460863 | |||
| 93c0a0aa35 | |||
| 74834527eb | |||
| 9b9ac3ca62 | |||
| db83113316 | |||
| d66e56392e | |||
| 17ce5d9117 | |||
| e2439e962c | |||
| 84103b69cf | |||
| 5b5f2d4240 | |||
| 956ae17876 | |||
| a6fb6c865d | |||
| 06fc4233d2 | |||
| c21fa2d8bc | |||
| f6b0b31e8b | |||
| cd9bfba790 | |||
| 6001808174 | |||
| 6b95d52ba3 | |||
| f290555e68 | |||
| e8bae00f57 | |||
| 00cfe003f7 | |||
| 3e4d12ccf1 | |||
| 46dd7084f7 | |||
| 6f8e1f648c | |||
| d322a81bd1 | |||
| 6275636ada | |||
| a226524e92 | |||
| 13b3be3e7f | |||
| 71c47734fb | |||
| 55821041bf | |||
| e7537cded5 | |||
| ea8bdda9a3 | |||
| eeb6e29e39 | |||
| b9cca71c47 | |||
| 2821915eae | |||
| 68143bc47c | |||
| f4e5bfbdf7 | |||
| 70fe0cc224 | |||
| 9d079ede85 | |||
| 4f7d3e5dc1 | |||
| 33bcdd476c | |||
| 2e04dceaf0 | |||
| 648fc92184 | |||
| c05d164eee | |||
| d37aa466ff | |||
| cd8e97a7c6 | |||
| a27e2db455 | |||
| bb5bdb2e8c | |||
| 9614fef4b9 | |||
| 74a175401a | |||
| b9c10a186d | |||
| c8965564e4 | |||
| a9c26b40dd | |||
| efe6a6cf53 | |||
| 2f414f96bf | |||
| cc0d7c5985 | |||
| 4f01794713 | |||
| 3d9e3a16f1 | |||
| ab17b49e15 | |||
| fcd702c8a6 | |||
| 743928b379 | |||
| f908daf323 | |||
| 49e64b9e82 | |||
| 6828fbf658 | |||
| 0a2992839b | |||
| 1a6e53ec98 | |||
| 9ec2337192 | |||
| cbc8bf01a1 | |||
| 54fbde0de1 | |||
| d238791b7d | |||
| 42f56e357c | |||
| fbac1c304a | |||
| 609c25f3e4 | |||
| 71f69d1d48 | |||
| 34c49c77b2 | |||
| cc02ef64a5 | |||
| ff26bf411b | |||
| 7aa1707c2c | |||
| d6c4d8eec0 | |||
| dc1cb2a7bc | |||
| c5755b3633 | |||
| 24e97b9e03 | |||
| 5848864f55 | |||
| ec41483e9b | |||
| 28a96f1543 | |||
| 435ea8d553 | |||
| 14ddeb07a5 | |||
| 15d0bdb7cf | |||
| d216398596 | |||
| 0477f8ed3c | |||
| 7ca2c444cc | |||
| c5074ba81f | |||
| ac53fc54dc | |||
| 3cbb0262c9 | |||
| a1688e342c | |||
| d5c879e8e7 | |||
| 2053de0885 | |||
| ef6a36241e | |||
| fbde1818a2 | |||
| 155f7a7d76 | |||
| 9b4868f017 | |||
| c951601fa4 | |||
| fb3dee0f3e | |||
| dbd7c70ffd | |||
| 5959411aeb | |||
| fbceec47b8 | |||
| 51a2b43d81 | |||
| 4231ea2eb6 | |||
| 8ee0ed84e4 | |||
| 32468adb53 | |||
| d770a42349 | |||
| 97c6d8407a | |||
| e66005149a | |||
| b12a2f7ea5 | |||
| 19d181fa4c | |||
| 83b541ea9d | |||
| af3e1fc580 | |||
| 7050575fdb | |||
| ee009ec99c | |||
| 198e9dce1d | |||
| 383c501a35 | |||
| 7c64c2f703 | |||
| d64e79bd9f | |||
| 489ded43b1 | |||
| d40aaf0391 | |||
| 6baba2875d | |||
| 1ea5e7404a | |||
| 55c324e062 | |||
| d496dbecad | |||
| 4872be9de3 | |||
| 688569e5c8 | |||
| 90f825aa49 | |||
| 78f7020ce6 | |||
| a92bf39efa | |||
| e836c33f37 | |||
| f271b650da | |||
| 14929a1497 | |||
| e768bdc80f | |||
| a605919729 | |||
| 39a3ed2d03 | |||
| 0a89f1db39 | |||
| 3cf0fb60a4 | |||
| fc2ef5529d | |||
| 8a3759f479 | |||
| a6208d2bd7 | |||
| 58d8d12665 | |||
| 8b31a9448a | |||
| 4819847c46 | |||
| d6bc6ec2c1 | |||
| 320fb5f94c | |||
| 4a0c4259f0 | |||
| cb627a6bd7 | |||
| e9364bd87b | |||
| 5e04a5f21d | |||
| 106de04485 | |||
| 8eb8755aea | |||
| 1b13b94095 | |||
| 69283accd0 | |||
| 2dd8a1afdb | |||
| 114dd2a723 | |||
| 6891371a79 | |||
| a285409f59 | |||
| a08e79f426 | |||
| f24491de84 | |||
| 83da7f9b63 | |||
| 1ae8850b3f | |||
| 140a581d23 | |||
| d3198ddf60 | |||
| 6d34dcd75f | |||
| 4aee4ed6d7 | |||
| 61de20a633 | |||
| de5dab35e0 | |||
| 47060cdc5f | |||
| 7dd349ae8e | |||
| 4e80858bed | |||
| e89a035e8b | |||
| f7c52d3bb7 | |||
| 6f8dd20f03 | |||
| b1a1c0251f | |||
| 0d0821e914 | |||
| 6891323c18 | |||
| 71c8885678 | |||
| 7c7cd4153e | |||
| ff0f1510e5 | |||
| 3338fdb936 | |||
| 6dfe32c6d2 | |||
| 95966a467e | |||
| ac0022483a | |||
| 17bfb3beaf | |||
| a122924c8e | |||
| 04d6c80da5 | |||
| a1fa10ac70 | |||
| 6e9b064a0f | |||
| 42c2df877f | |||
| c2ae7ee402 | |||
| 50f2be57f7 | |||
| b4a97c99d8 | |||
| 3aefd14b3d | |||
| 60f5929f81 | |||
| 6b323d7e2e | |||
| d7881c6714 | |||
| d0013679c0 | |||
| 0b3fbf1d4c | |||
| 69eb483089 | |||
| a2b4cf22b5 | |||
| d8ae94df5b | |||
| 03814e8d02 | |||
| 970d2a06e0 | |||
| 9853027f72 | |||
| 90c2324e47 | |||
| f5145943b2 | |||
| 960f26f84e | |||
| cdd4fd9867 | |||
| bfb3144f34 | |||
| 8f314c5101 | |||
| 2ec4f66427 | |||
| 7165001b68 | |||
| c077426e95 | |||
| c870bbb885 | |||
| 3fbc960c44 | |||
| 896c8991de | |||
| bec6c1a939 | |||
| fe9090bd39 | |||
| 44e34064de | |||
| a18ae0f6ac | |||
| 08b829dc22 | |||
| 9d27ac359b | |||
| 6c9c300fe0 | |||
| 17340c44cc | |||
| 90a3f3af30 | |||
| da1e97618b | |||
| 89bc333295 | |||
| 3350e7ee55 | |||
| ddebc334bf | |||
| 145ecb00fc | |||
| 75d0ff177d | |||
| 4d75e98647 | |||
| 3bfdcf698d | |||
| 51891039dd | |||
| 07fe5f87ae | |||
| de5a4fe083 | |||
| 5cf2d774f3 | |||
| ccc0383f75 | |||
| 680ca1d12a | |||
| c926868758 | |||
| 30269e5bad | |||
| 07f61db24a | |||
| 63f261a66d | |||
| 33f3a3e014 | |||
| 8646f51fa3 | |||
| 0aaae000b3 | |||
| db58cd7513 | |||
| d17093e65b | |||
| 34e01ba3d8 | |||
| 8b476b5bfa | |||
| ad97780c4f | |||
| 17cf24d0ed | |||
| c424652b43 | |||
| 3a9ae2df9e | |||
| 8276d29d4f | |||
| b9b06143d2 | |||
| 853c3f9e39 | |||
| c04c23f33d | |||
| 25a1d86986 | |||
| c2379b8337 | |||
| ae643135b5 | |||
| 91fd1465f2 | |||
| a4de495093 | |||
| 2cd551a222 | |||
| dd4ccb059e | |||
| 5810b29298 | |||
| 6702c14b88 | |||
| 8901cc9ae6 | |||
| 17ff1e41a5 | |||
| 782156b26f | |||
| 4f5e93bd09 |
@@ -59,7 +59,6 @@ rpcs3/git-version.h
|
||||
|
||||
# Visual Studio Files
|
||||
.vs/*
|
||||
*.ipch
|
||||
*.vspx
|
||||
*.psess
|
||||
*.VC.*
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
ignore = dirty
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
url = https://github.com/llvm-mirror/llvm
|
||||
branch = release_50
|
||||
url = https://github.com/RPCS3/llvm
|
||||
branch = release_60
|
||||
[submodule "GSL"]
|
||||
path = 3rdparty/GSL
|
||||
url = https://github.com/Microsoft/GSL.git
|
||||
[submodule "libpng"]
|
||||
path = 3rdparty/libpng
|
||||
url = https://github.com/Zangetsu38/libpng
|
||||
url = https://github.com/RPCS3/libpng
|
||||
ignore = dirty
|
||||
[submodule "Vulkan/glslang"]
|
||||
path = Vulkan/glslang
|
||||
@@ -33,8 +33,9 @@
|
||||
url = https://github.com/madler/zlib
|
||||
[submodule "3rdparty/hidapi"]
|
||||
path = 3rdparty/hidapi
|
||||
url = https://github.com/Zangetsu38/hidapi
|
||||
url = https://github.com/RPCS3/hidapi
|
||||
branch = master
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/Optional"]
|
||||
path = 3rdparty/Optional
|
||||
url = https://github.com/akrzemi1/Optional.git
|
||||
|
||||
@@ -22,12 +22,10 @@ matrix:
|
||||
compiler: gcc
|
||||
|
||||
git:
|
||||
depth: false # Unshallow clone to obtain proper GIT_VERSION
|
||||
submodules: false
|
||||
|
||||
before_install:
|
||||
- if [ "$CC" = "clang" ]; then
|
||||
export CXX="clang++-4.0" CC="clang-4.0";
|
||||
fi;
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$CXX" = "g++" ]; then
|
||||
export CXX="g++-5" CC="gcc-5" CXXFLAGS="-Wno-format-security";
|
||||
fi;
|
||||
@@ -35,16 +33,16 @@ before_install:
|
||||
wget http://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run ;
|
||||
chmod a+x ./qt-unified-linux-x64-online.run ;
|
||||
export QT_QPA_PLATFORM=minimal ;
|
||||
./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations ;
|
||||
travis_wait 60 ./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations --verbose ;
|
||||
fi;
|
||||
|
||||
# Install updated libglew-dev since the version provided by trusty is outdated
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew-dev_1.13.0-2_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew1.13_1.13.0-2_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
sudo dpkg -i libglew1.13_1.13.0-2_amd64.deb libglew-dev_1.13.0-2_amd64.deb libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/g/glew/libglew-dev_2.0.0-5_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/g/glew/libglew2.0_2.0.0-5_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
wget https://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
sudo dpkg -i libglew2.0_2.0.0-5_amd64.deb libglew-dev_2.0.0-5_amd64.deb libvulkan1_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.61.1+dfsg1-1ubuntu1~16.04.1_amd64.deb;
|
||||
else
|
||||
brew update;
|
||||
brew install ccache glew llvm40;
|
||||
@@ -54,30 +52,32 @@ before_script:
|
||||
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal 3rdparty/hidapi 3rdparty/Optional Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
- mkdir build
|
||||
- cd build
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.9.2/gcc_64/lib/cmake
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.10.0/gcc_64/lib/cmake
|
||||
- export CXXFLAGS="$CXXFLAGS -DTRAVIS=true";
|
||||
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
|
||||
else
|
||||
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/#$TRAVIS_PULL_REQUEST";
|
||||
fi;
|
||||
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
|
||||
- make -j 3
|
||||
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr -G Ninja;
|
||||
- ninja
|
||||
- # AppImage generation
|
||||
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.9.2/gcc_64/lib;
|
||||
make DESTDIR=appdir install ; find appdir/ ;
|
||||
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.10.0/gcc_64/lib;
|
||||
DESTDIR=appdir ninja install ; find appdir/ ;
|
||||
find ../bin ;
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
|
||||
chmod a+x linuxdeployqt*.AppImage ;
|
||||
export PATH=~/Qt/5.9.2/gcc_64/bin/:${PATH} ;
|
||||
export PATH=~/Qt/5.10.0/gcc_64/bin/:${PATH} ;
|
||||
./linuxdeployqt*.AppImage --appimage-extract ;
|
||||
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
|
||||
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
mkdir ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.10.0/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
rm ./appdir/usr/lib/libfreetype.so.6 ;
|
||||
export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ;
|
||||
./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ;
|
||||
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq ;
|
||||
@@ -99,6 +99,7 @@ addons:
|
||||
packages:
|
||||
- binutils
|
||||
- cmake
|
||||
- ninja-build
|
||||
- libasound2-dev
|
||||
- libopenal-dev
|
||||
- freeglut3-dev
|
||||
@@ -108,14 +109,15 @@ addons:
|
||||
- libc6-dev
|
||||
- llvm-4.0
|
||||
- llvm-4.0-dev
|
||||
- clang-4.0
|
||||
# Clang 5.0 is now bundled in travis, so we no longer need the ppa version.
|
||||
#- clang-4.0
|
||||
- libedit-dev
|
||||
- g++-5
|
||||
- gcc-5
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
# We need to install qt 5.9.2 manually because the version trusty provides is too old.
|
||||
# We need to install qt 5.10.0 manually because the version trusty provides is too old.
|
||||
#- qtbase5-dev
|
||||
- libudev-dev
|
||||
- libevdev-dev
|
||||
|
||||
@@ -20,11 +20,11 @@ If you want to contribute please take a look at the [Coding Style](https://githu
|
||||
## Dependencies
|
||||
|
||||
### Windows
|
||||
* [Visual Studio 2017](https://www.visualstudio.com/en/downloads/)
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2017](https://go.microsoft.com/fwlink/?LinkId=746572)
|
||||
* [Visual Studio 2015](https://www.visualstudio.com/vs/older-downloads/)
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
||||
* [Cmake 3.1.0+](https://www.cmake.org/download/) (required; add to PATH)
|
||||
* [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
|
||||
* [Qt 5.9.2](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.9.1\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
|
||||
* [Qt 5.8+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.8\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
|
||||
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
|
||||
|
||||
### Linux
|
||||
@@ -33,6 +33,7 @@ If you want to contribute please take a look at the [Coding Style](https://githu
|
||||
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git qt5-default`
|
||||
* Arch: `sudo pacman -S glew openal cmake llvm qt5-base`
|
||||
* Fedora: `sudo dnf install cmake glew glew-devel libatomic libudev-devel openal-devel qt5-devel vulkan-devel`
|
||||
* OpenSUSE: `sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libevdev-devel`
|
||||
**If you have a NVIDIA GPU, you may need to install the libglvnd package.**
|
||||
|
||||
### MacOS
|
||||
@@ -47,14 +48,14 @@ To initialize the repository don't forget to execute `git submodule update --ini
|
||||
### Configuring Qt
|
||||
|
||||
*If you're using Visual Studio 2017 without Qt plugin support (or simply dont want to use it):*
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.9.2\msvc2017_64\` </br>
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.8\msvc2015_64\` </br>
|
||||
|
||||
|
||||
Open `rpcs3.sln`
|
||||
|
||||
|
||||
*If you wish to use the Visual Studio plugin for Qt:* </br>
|
||||
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.9.2\msvc2015_64`. </br>
|
||||
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.8\msvc2015_64`. </br>
|
||||
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
### Building the projects
|
||||
|
||||
@@ -470,7 +470,7 @@ struct se_storage<T, 16, 16>
|
||||
|
||||
static inline v128 swap(const v128& src)
|
||||
{
|
||||
return v128::fromV(_mm_shuffle_epi8(src.vi, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)));
|
||||
return v128::from64(se_storage<u64>::swap(src._u64[1]), se_storage<u64>::swap(src._u64[0]));
|
||||
}
|
||||
|
||||
static inline v128 to(const T& src)
|
||||
|
||||
@@ -202,9 +202,12 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
||||
out << YAML::EndMap;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out << rhs.to_string();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out << rhs.to_string();
|
||||
}
|
||||
|
||||
void cfg::decode(const YAML::Node& data, cfg::_base& rhs)
|
||||
|
||||
@@ -1034,7 +1034,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
|
||||
const auto result = ::lseek(m_fd, offset, mode);
|
||||
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
g_tls_error = to_error(errno);
|
||||
@@ -1258,7 +1258,12 @@ bool fs::dir::open(const std::string& path)
|
||||
}
|
||||
|
||||
struct ::stat file_info;
|
||||
verify("dir::read" HERE), ::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) == 0;
|
||||
|
||||
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
|
||||
{
|
||||
//failed metadata (broken symlink?), ignore and skip to next file
|
||||
return read(info);
|
||||
}
|
||||
|
||||
info.name = found->d_name;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -1358,7 +1363,7 @@ std::string fs::get_data_dir(const std::string& prefix, const std::string& locat
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
buf.push_back(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ static void* s_next = s_memory;
|
||||
#ifdef _WIN32
|
||||
static std::deque<std::vector<RUNTIME_FUNCTION>> s_unwater;
|
||||
static std::vector<std::vector<RUNTIME_FUNCTION>> s_unwind; // .pdata
|
||||
#else
|
||||
static std::deque<std::tuple<u8*, u64, std::size_t>> s_unfire;
|
||||
#endif
|
||||
|
||||
// Reset memory manager
|
||||
@@ -87,7 +89,30 @@ extern void jit_finalize()
|
||||
|
||||
s_unwind.clear();
|
||||
#else
|
||||
// TODO: unregister EH frames if necessary
|
||||
struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
{
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} mem;
|
||||
|
||||
for (auto&& t : s_unfire)
|
||||
{
|
||||
mem.deregisterEHFrames(std::get<0>(t), std::get<1>(t), std::get<2>(t));
|
||||
}
|
||||
|
||||
s_unfire.clear();
|
||||
#endif
|
||||
|
||||
utils::memory_decommit(s_memory, s_memory_size);
|
||||
@@ -171,7 +196,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return {addr, llvm::JITSymbolFlags::Exported};
|
||||
}
|
||||
|
||||
virtual u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
@@ -192,7 +217,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
}
|
||||
|
||||
virtual u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
@@ -217,7 +242,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
}
|
||||
|
||||
virtual bool finalizeMemory(std::string* = nullptr) override
|
||||
bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
@@ -234,7 +259,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Lock memory manager
|
||||
@@ -261,16 +286,15 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
{
|
||||
s_unwind.emplace_back(std::move(pdata));
|
||||
}
|
||||
#else
|
||||
s_unfire.push_front(std::make_tuple(addr, load_addr, size));
|
||||
#endif
|
||||
|
||||
return RTDyldMemoryManager::registerEHFrames(addr, load_addr, size);
|
||||
}
|
||||
|
||||
virtual void deregisterEHFrames() override
|
||||
void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
LOG_ERROR(GENERAL, "deregisterEHFrames() called"); // Not expected
|
||||
|
||||
return RTDyldMemoryManager::deregisterEHFrames();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -284,7 +308,7 @@ struct EventListener : llvm::JITEventListener
|
||||
{
|
||||
}
|
||||
|
||||
virtual void NotifyObjectEmitted(const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
|
||||
void NotifyObjectEmitted(const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (auto it = obj.section_begin(), end = obj.section_end(); it != end; ++it)
|
||||
@@ -380,7 +404,7 @@ public:
|
||||
};
|
||||
|
||||
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, std::string _cpu)
|
||||
: m_link(std::move(_link))
|
||||
: m_link(_link)
|
||||
, m_cpu(std::move(_cpu))
|
||||
{
|
||||
if (m_cpu.empty())
|
||||
|
||||
@@ -45,6 +45,7 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
case logs::level::warning: return "Warning";
|
||||
case logs::level::notice: return "Notice";
|
||||
case logs::level::trace: return "Trace";
|
||||
case logs::level::_uninit: return unknown;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
@@ -588,6 +589,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
case level::warning: text = u8"·W "; break;
|
||||
case level::notice: text = u8"·! "; break;
|
||||
case level::trace: text = u8"·T "; break;
|
||||
case level::_uninit: text = u8"· "; break;
|
||||
}
|
||||
|
||||
// Print miscosecond timestamp
|
||||
|
||||
@@ -24,6 +24,12 @@ inline void strcpy_trunc(char (&dst)[N], const char (&src)[N2])
|
||||
dst[count] = '\0';
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
inline bool ends_with(const std::string& src, const char (&end)[N])
|
||||
{
|
||||
return src.size() >= N - 1 && src.compare(src.size() - (N - 1), N - 1, end, N - 1) == 0;
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include "Emu/Cell/lv2/sys_mmapper.h"
|
||||
#include "Emu/Cell/lv2/sys_event.h"
|
||||
#include "Thread.h"
|
||||
#include "sysinfo.h"
|
||||
#include <typeinfo>
|
||||
#include <thread>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
@@ -963,8 +965,8 @@ bool put_x64_reg_value(x64_context* context, x64_reg_t reg, size_t d_size, u64 v
|
||||
// save the value into x64 register
|
||||
switch (d_size)
|
||||
{
|
||||
case 1: *X64REG(context, reg - X64R_RAX) = value & 0xff | *X64REG(context, reg - X64R_RAX) & 0xffffff00; return true;
|
||||
case 2: *X64REG(context, reg - X64R_RAX) = value & 0xffff | *X64REG(context, reg - X64R_RAX) & 0xffff0000; return true;
|
||||
case 1: *X64REG(context, reg - X64R_RAX) = (value & 0xff) | (*X64REG(context, reg - X64R_RAX) & 0xffffff00); return true;
|
||||
case 2: *X64REG(context, reg - X64R_RAX) = (value & 0xffff) | (*X64REG(context, reg - X64R_RAX) & 0xffff0000); return true;
|
||||
case 4: *X64REG(context, reg - X64R_RAX) = value & 0xffffffff; return true;
|
||||
case 8: *X64REG(context, reg - X64R_RAX) = value; return true;
|
||||
}
|
||||
@@ -1547,6 +1549,8 @@ thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
|
||||
|
||||
extern thread_local std::string(*g_tls_log_prefix)();
|
||||
|
||||
DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined };
|
||||
|
||||
void thread_ctrl::start(const std::shared_ptr<thread_ctrl>& ctrl, task_stack task)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -1853,6 +1857,98 @@ void thread_ctrl::test()
|
||||
}
|
||||
}
|
||||
|
||||
void thread_ctrl::detect_cpu_layout()
|
||||
{
|
||||
if (!g_native_core_layout.compare_and_swap_test(native_core_arrangement::undefined, native_core_arrangement::generic))
|
||||
return;
|
||||
|
||||
const auto system_id = utils::get_system_info();
|
||||
if (system_id.find("Ryzen") != std::string::npos)
|
||||
{
|
||||
g_native_core_layout.store(native_core_arrangement::amd_ccx);
|
||||
}
|
||||
else if (system_id.find("i3") != std::string::npos || system_id.find("i7") != std::string::npos)
|
||||
{
|
||||
g_native_core_layout.store(native_core_arrangement::intel_ht);
|
||||
}
|
||||
}
|
||||
|
||||
u16 thread_ctrl::get_affinity_mask(thread_class group)
|
||||
{
|
||||
detect_cpu_layout();
|
||||
|
||||
if (const auto thread_count = std::thread::hardware_concurrency())
|
||||
{
|
||||
const u16 all_cores_mask = thread_count < 16 ? (u16)(~(UINT16_MAX << thread_count)): UINT16_MAX;
|
||||
|
||||
switch (g_native_core_layout)
|
||||
{
|
||||
default:
|
||||
case native_core_arrangement::generic:
|
||||
{
|
||||
return all_cores_mask;
|
||||
}
|
||||
case native_core_arrangement::amd_ccx:
|
||||
{
|
||||
u16 spu_mask, ppu_mask, rsx_mask;
|
||||
if (thread_count >= 16)
|
||||
{
|
||||
// Threadripper, R7
|
||||
// Assign threads 8-16
|
||||
// It appears some windows code is bound to lower core addresses, binding 8-16 is alot faster than 0-7
|
||||
ppu_mask = spu_mask = 0b1111111100000000;
|
||||
rsx_mask = all_cores_mask;
|
||||
}
|
||||
else if (thread_count == 12)
|
||||
{
|
||||
// 1600/2600 (x)
|
||||
ppu_mask = spu_mask = 0b111111000000;
|
||||
rsx_mask = all_cores_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// R5 & R3 don't seem to improve performance no matter how these are shuffled
|
||||
ppu_mask = spu_mask = rsx_mask = 0b11111111 & all_cores_mask;
|
||||
}
|
||||
|
||||
switch (group)
|
||||
{
|
||||
default:
|
||||
case thread_class::general:
|
||||
return all_cores_mask;
|
||||
case thread_class::rsx:
|
||||
return rsx_mask;
|
||||
case thread_class::ppu:
|
||||
return ppu_mask;
|
||||
case thread_class::spu:
|
||||
return spu_mask;
|
||||
}
|
||||
}
|
||||
case native_core_arrangement::intel_ht:
|
||||
{
|
||||
if (thread_count <= 4)
|
||||
{
|
||||
//i3 or worse
|
||||
switch (group)
|
||||
{
|
||||
case thread_class::rsx:
|
||||
case thread_class::ppu:
|
||||
return (0b0101 & all_cores_mask);
|
||||
case thread_class::spu:
|
||||
return (0b1010 & all_cores_mask);
|
||||
case thread_class::general:
|
||||
return all_cores_mask;
|
||||
}
|
||||
}
|
||||
|
||||
return all_cores_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return UINT16_MAX;
|
||||
}
|
||||
|
||||
void thread_ctrl::set_native_priority(int priority)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -1886,24 +1982,31 @@ void thread_ctrl::set_native_priority(int priority)
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_ctrl::set_ideal_processor_core(int core)
|
||||
void thread_ctrl::set_thread_affinity_mask(u16 mask)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE _this_thread = GetCurrentThread();
|
||||
SetThreadIdealProcessor(_this_thread, core);
|
||||
SetThreadAffinityMask(_this_thread, (DWORD_PTR)mask);
|
||||
#elif __APPLE__
|
||||
thread_affinity_policy_data_t policy = { static_cast<integer_t>(core) };
|
||||
thread_affinity_policy_data_t policy = { static_cast<integer_t>(mask) };
|
||||
thread_port_t mach_thread = pthread_mach_thread_np(pthread_self());
|
||||
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1);
|
||||
#elif defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
cpu_set_t cs;
|
||||
CPU_ZERO(&cs);
|
||||
CPU_SET(core, &cs);
|
||||
|
||||
for (u32 core = 0; core < 16u; ++core)
|
||||
{
|
||||
if ((u32)mask & (1u << core))
|
||||
{
|
||||
CPU_SET(core, &cs);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
named_thread::named_thread()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -16,6 +16,23 @@
|
||||
// Will report exception and call std::abort() if put in catch(...)
|
||||
[[noreturn]] void catch_all_exceptions();
|
||||
|
||||
// Hardware core layout
|
||||
enum class native_core_arrangement : u32
|
||||
{
|
||||
undefined,
|
||||
generic,
|
||||
intel_ht,
|
||||
amd_ccx
|
||||
};
|
||||
|
||||
enum class thread_class : u32
|
||||
{
|
||||
general,
|
||||
rsx,
|
||||
spu,
|
||||
ppu
|
||||
};
|
||||
|
||||
// Simple list of void() functors
|
||||
class task_stack
|
||||
{
|
||||
@@ -91,6 +108,9 @@ class thread_ctrl final
|
||||
// Current thread
|
||||
static thread_local thread_ctrl* g_tls_this_thread;
|
||||
|
||||
// Target cpu core layout
|
||||
static atomic_t<native_core_arrangement> g_native_core_layout;
|
||||
|
||||
// Self pointer
|
||||
std::shared_ptr<thread_ctrl> m_self;
|
||||
|
||||
@@ -234,8 +254,17 @@ public:
|
||||
thread_ctrl::start(out, std::forward<F>(func));
|
||||
}
|
||||
|
||||
// Detect layout
|
||||
static void detect_cpu_layout();
|
||||
|
||||
// Returns a core affinity mask. Set whether to generate the high priority set or not
|
||||
static u16 get_affinity_mask(thread_class group);
|
||||
|
||||
// Sets the native thread priority
|
||||
static void set_native_priority(int priority);
|
||||
static void set_ideal_processor_core(int core);
|
||||
|
||||
// Sets the preferred affinity mask for this thread
|
||||
static void set_thread_affinity_mask(u16 mask);
|
||||
};
|
||||
|
||||
class named_thread
|
||||
|
||||
@@ -32,13 +32,23 @@ void patch_engine::append(const std::string& patch)
|
||||
{
|
||||
if (fs::file f{patch})
|
||||
{
|
||||
auto root = YAML::Load(f.to_string());
|
||||
YAML::Node root;
|
||||
|
||||
try
|
||||
{
|
||||
root = YAML::Load(f.to_string());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_FATAL(GENERAL, "Failed to load patch file %s\n%s thrown: %s", patch, typeid(e).name(), e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto pair : root)
|
||||
{
|
||||
auto& name = pair.first.Scalar();
|
||||
auto& data = m_map[name];
|
||||
|
||||
|
||||
for (auto patch : pair.second)
|
||||
{
|
||||
u64 type64 = 0;
|
||||
@@ -91,7 +101,7 @@ void patch_engine::append(const std::string& patch)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data.emplace_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ rem // A copy of the GPL 2.0 should have been included with the program.
|
||||
rem // If not, see http://www.gnu.org/licenses/
|
||||
|
||||
rem // Official git repository and contact information can be found at
|
||||
rem // https://github.com/RPCS3/rpcs3 and http://rpcs3.net/.
|
||||
rem // https://github.com/RPCS3/rpcs3 and https://rpcs3.net/.
|
||||
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
setlocal ENABLEEXTENSIONS
|
||||
@@ -55,33 +55,31 @@ if errorlevel 1 (
|
||||
goto done
|
||||
)
|
||||
|
||||
rem // Get commit count from HEAD by default
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set GIT_VERSION=%%I
|
||||
|
||||
rem // If we're in AppVeyor and we're building for master: Get commit count from unshallowed upstream
|
||||
if defined APPVEYOR (
|
||||
if not defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
|
||||
call %GIT% remote add upstream https://github.com/RPCS3/RPCS3.git
|
||||
call %GIT% fetch --unshallow upstream
|
||||
for /F %%I IN ('call %GIT% rev-list --count upstream/master') do set GIT_VERSION=%%I
|
||||
)
|
||||
)
|
||||
rem // Get commit count from (unshallowed) HEAD
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set COMMIT_COUNT=%%I
|
||||
|
||||
rem // If we're in AppVeyor, building a non-master, pull request artifact
|
||||
if defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
|
||||
|
||||
if "%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"=="master" (
|
||||
rem // If pull request comes from a master branch, GIT_BRANCH = username/branch in order to distinguish from upstream/master
|
||||
for /f "tokens=1* delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set user=%%a
|
||||
set "GIT_BRANCH=!user!/%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"
|
||||
) else (
|
||||
rem // Otherwise, GIT_BRANCH=branch
|
||||
set GIT_BRANCH=%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%
|
||||
)
|
||||
|
||||
rem // Make GIT_VERSION the last commit (shortened); Don't include commit count on non-master builds
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%%I
|
||||
|
||||
) else (
|
||||
rem // Get last commit (shortened) and concat after commit count in GIT_VERSION
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%COMMIT_COUNT%-%%I
|
||||
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
)
|
||||
|
||||
rem // Get last commit (shortened) and concat after commit count in GIT_VERSION
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%GIT_VERSION%-%%I
|
||||
|
||||
rem // Echo obtained GIT_VERSION for debug purposes if needed
|
||||
echo %GIT_VERSION%
|
||||
|
||||
|
||||
@@ -19,6 +19,12 @@ bool utils::has_avx()
|
||||
return g_value;
|
||||
}
|
||||
|
||||
bool utils::has_avx2()
|
||||
{
|
||||
static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && get_cpuid(7, 0)[1] & 0x20;
|
||||
return g_value;
|
||||
}
|
||||
|
||||
bool utils::has_rtm()
|
||||
{
|
||||
// Check RTM and MPX extensions in order to filter out TSX on Haswell CPUs
|
||||
@@ -26,6 +32,19 @@ bool utils::has_rtm()
|
||||
return g_value;
|
||||
}
|
||||
|
||||
bool utils::has_512()
|
||||
{
|
||||
// Check AVX512F, AVX512CD, AVX512DQ, AVX512BW, AVX512VL extensions (Skylake-X level support)
|
||||
static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0xd0030000) == 0xd0030000;
|
||||
return g_value;
|
||||
}
|
||||
|
||||
bool utils::has_xop()
|
||||
{
|
||||
static const bool g_value = has_avx() && get_cpuid(0x80000001, 0)[2] & 0x800;
|
||||
return g_value;
|
||||
}
|
||||
|
||||
std::string utils::get_system_info()
|
||||
{
|
||||
std::string result;
|
||||
@@ -68,7 +87,22 @@ std::string utils::get_system_info()
|
||||
|
||||
if (has_avx())
|
||||
{
|
||||
result += " | AVX+";
|
||||
result += " | AVX";
|
||||
|
||||
if (has_avx2())
|
||||
{
|
||||
result += '+';
|
||||
}
|
||||
|
||||
if (has_512())
|
||||
{
|
||||
result += '+';
|
||||
}
|
||||
|
||||
if (has_xop())
|
||||
{
|
||||
result += 'x';
|
||||
}
|
||||
}
|
||||
|
||||
if (has_rtm())
|
||||
|
||||
@@ -8,11 +8,11 @@ namespace utils
|
||||
inline std::array<u32, 4> get_cpuid(u32 func, u32 subfunc)
|
||||
{
|
||||
int regs[4];
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
__cpuidex(regs, func, subfunc);
|
||||
#else
|
||||
#else
|
||||
__asm__ volatile("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (func), "c" (subfunc));
|
||||
#endif
|
||||
#endif
|
||||
return {0u+regs[0], 0u+regs[1], 0u+regs[2], 0u+regs[3]};
|
||||
}
|
||||
|
||||
@@ -20,8 +20,14 @@ namespace utils
|
||||
|
||||
bool has_avx();
|
||||
|
||||
bool has_avx2();
|
||||
|
||||
bool has_rtm();
|
||||
|
||||
bool has_512();
|
||||
|
||||
bool has_xop();
|
||||
|
||||
inline bool transaction_enter()
|
||||
{
|
||||
while (true)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "recursive_wrapper.hpp"
|
||||
#include "variant_visitor.hpp"
|
||||
|
||||
// clang-format off
|
||||
// [[deprecated]] is only available in C++14, use this for the time being
|
||||
@@ -849,6 +850,22 @@ namespace std {
|
||||
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
|
||||
}
|
||||
|
||||
// match
|
||||
// unary
|
||||
template <typename... Fs>
|
||||
auto VARIANT_INLINE match(Fs&&... fs) const
|
||||
-> decltype(variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...)))
|
||||
{
|
||||
return variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...));
|
||||
}
|
||||
// non-const
|
||||
template <typename... Fs>
|
||||
auto VARIANT_INLINE match(Fs&&... fs)
|
||||
-> decltype(variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...)))
|
||||
{
|
||||
return variant::visit(*this, ::std::make_visitor(std::forward<Fs>(fs)...));
|
||||
}
|
||||
|
||||
~variant() noexcept // no-throw destructor
|
||||
{
|
||||
helper_type::destroy(type_index, &data);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||
#define MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
//namespace mapbox {
|
||||
//namespace util {
|
||||
namespace std {
|
||||
|
||||
template <typename... Fns>
|
||||
struct visitor;
|
||||
|
||||
template <typename Fn>
|
||||
struct visitor<Fn> : Fn
|
||||
{
|
||||
using Fn::operator();
|
||||
|
||||
template<typename T>
|
||||
visitor(T&& fn) : Fn(std::forward<T>(fn)) {}
|
||||
};
|
||||
|
||||
template <typename Fn, typename... Fns>
|
||||
struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
|
||||
{
|
||||
using Fn::operator();
|
||||
using visitor<Fns...>::operator();
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
visitor(T&& fn, Ts&&... fns)
|
||||
: Fn(std::forward<T>(fn))
|
||||
, visitor<Fns...>(std::forward<Ts>(fns)...) {}
|
||||
};
|
||||
|
||||
template <typename... Fns>
|
||||
visitor<typename std::decay<Fns>::type...> make_visitor(Fns&&... fns)
|
||||
{
|
||||
return visitor<typename std::decay<Fns>::type...>
|
||||
(std::forward<Fns>(fns)...);
|
||||
}
|
||||
|
||||
}
|
||||
//} // namespace util
|
||||
//} // namespace mapbox
|
||||
|
||||
#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||
@@ -19,7 +19,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -39,20 +39,24 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeBuildCommandLine>start /W /B pre-build.bat
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeReBuildCommandLine>start /W /B pre-build.bat
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
|
||||
</NMakeReBuildCommandLine>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeBuildCommandLine>start /W /B pre-build.bat
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeReBuildCommandLine>start /W /B pre-build.bat
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Setting up dummy git helper
|
||||
MKDIR ..\Vulkan-LoaderAndValidationLayers\external\glslang\External\spirv-tools
|
||||
SET header="@ECHO off"
|
||||
SET content="ECHO unused"
|
||||
ECHO %header:"=% > git.bat
|
||||
ECHO %content:"=% >> git.bat
|
||||
COPY /Y git.bat ..\Vulkan-LoaderAndValidationLayers\external\glslang\External\spirv-tools\git.bat
|
||||
|
||||
REM Set up gitignore
|
||||
SET ignored="*"
|
||||
ECHO %ignored:"=% > ..\Vulkan-LoaderAndValidationLayers\external\glslang\External\spirv-tools\.gitignore
|
||||
@@ -19,12 +19,12 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -39,24 +39,24 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<NMakeBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,82 +1,100 @@
|
||||
#---------------------------------#
|
||||
# general configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# version format
|
||||
version: '0.0.4-{build}'
|
||||
version: '{build}'
|
||||
|
||||
#---------------------------------#
|
||||
# environment configuration #
|
||||
#---------------------------------#
|
||||
image: Visual Studio 2015
|
||||
|
||||
# Build worker image (VM template)
|
||||
image: Visual Studio 2017
|
||||
|
||||
# clone directory
|
||||
clone_folder: c:\projects\rpcs3
|
||||
|
||||
# set clone depth
|
||||
clone_depth: 3 # clone entire repository history if not defined
|
||||
|
||||
# environment variables
|
||||
environment:
|
||||
QTDIR: C:\Qt\5.9\msvc2017_64
|
||||
QTDIR: C:\Qt\5.10.0\msvc2015_64
|
||||
LLVMLIBS: https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8
|
||||
VULKAN: https://drive.google.com/uc?export=download&id=1A2eOMmCO714i0U7J0qI4aEMKnuWl8l_R
|
||||
COMPATDB: https://rpcs3.net/compatibility?api=v1&export
|
||||
|
||||
# build cache to preserve files/folders between builds
|
||||
cache:
|
||||
- llvmlibs.7z -> appveyor.yml
|
||||
- vulkan.7z -> appveyor.yml
|
||||
- llvmlibs.7z -> appveyor.yml
|
||||
- vulkan.7z -> appveyor.yml
|
||||
- compat_database.dat
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
- git submodule update --init 3rdparty/cereal 3rdparty/ffmpeg 3rdparty/GSL 3rdparty/hidapi 3rdparty/libpng 3rdparty/Optional 3rdparty/pugixml 3rdparty/zlib asmjit Utilities/yaml-cpp Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
- ps: | # set env vars for versioning
|
||||
$commDate = $env:APPVEYOR_REPO_COMMIT_TIMESTAMP.Substring(0,10)
|
||||
$commSha = $env:APPVEYOR_REPO_COMMIT.Substring(0,8)
|
||||
$commTag = $(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
|
||||
$env:AVVER = "{0}-{1}" -f $commTag.TrimStart("v"), $env:APPVEYOR_BUILD_NUMBER
|
||||
$env:BUILD = "rpcs3-{0}-{1}-{2}_win64.7z" -f $commTag, $commDate, $commSha
|
||||
|
||||
#---------------------------------#
|
||||
# build configuration #
|
||||
#---------------------------------#
|
||||
- ps: | # used for experimental build warnings for pr builds
|
||||
$env:BRANCH = "{0}/{1}/#{2}" -f $env:APPVEYOR_REPO_NAME, `
|
||||
$env:APPVEYOR_REPO_BRANCH, $env:APPVEYOR_PULL_REQUEST_NUMBER
|
||||
$env:BRANCH = $env:BRANCH -replace "/#$"
|
||||
|
||||
- ps: | # misc global settings
|
||||
$env:PATH += $env:QTDIR
|
||||
[net.servicepointmanager]::securityprotocol = "tls12, tls11, tls"
|
||||
|
||||
- ps: | # update and init submodules
|
||||
git submodule -q update --init `
|
||||
3rdparty/cereal `
|
||||
3rdparty/ffmpeg `
|
||||
3rdparty/GSL `
|
||||
3rdparty/hidapi `
|
||||
3rdparty/libpng `
|
||||
3rdparty/Optional `
|
||||
3rdparty/pugixml `
|
||||
3rdparty/zlib `
|
||||
asmjit `
|
||||
Utilities/yaml-cpp `
|
||||
Vulkan/glslang `
|
||||
Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
|
||||
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
|
||||
platform: x64
|
||||
|
||||
# build Configuration, i.e. Debug, Release, etc.
|
||||
configuration: Release - LLVM
|
||||
|
||||
build:
|
||||
parallel: true # enable MSBuild parallel builds
|
||||
project: rpcs3.sln # path to Visual Studio solution or project
|
||||
# MSBuild verbosity level
|
||||
parallel: true
|
||||
project: rpcs3.sln
|
||||
verbosity: normal
|
||||
|
||||
# scripts to run before build
|
||||
before_build:
|
||||
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
|
||||
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
|
||||
- set PATH=%PATH%;%QTDIR%
|
||||
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
|
||||
- 7z x llvmlibs.7z -aos -o%APPVEYOR_BUILD_FOLDER% > null
|
||||
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
|
||||
- 7z x vulkan.7z -aos -o"%APPVEYOR_BUILD_FOLDER%\lib\%CONFIGURATION%-%PLATFORM%" > null
|
||||
- ps: | # fetch precompiled build dependencies
|
||||
if (!(test-path llvmlibs.7z)) { irm $env:LLVMLIBS -outfile llvmlibs.7z }
|
||||
if (!(test-path vulkan.7z)) { irm $env:VULKAN -outfile vulkan.7z }
|
||||
7z x llvmlibs.7z -aos -o"." | out-null
|
||||
7z x vulkan.7z -aos -o".\lib\$env:CONFIGURATION-$env:PLATFORM" | out-null
|
||||
|
||||
# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)
|
||||
before_package:
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.exp
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.lib
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.pdb
|
||||
- set COMMIT_DATE=%APPVEYOR_REPO_COMMIT_TIMESTAMP:~0,10%
|
||||
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
|
||||
after_build:
|
||||
- ps: | # remove unnecessary files
|
||||
rm .\bin\rpcs3.exp, .\bin\rpcs3.lib, .\bin\rpcs3.pdb
|
||||
|
||||
#---------------------------------#
|
||||
# tests configuration #
|
||||
#---------------------------------#
|
||||
- ps: | # prepare compatibility database for packaging
|
||||
$db = irm $env:COMPATDB -erroraction silentlycontinue
|
||||
if ($db -and $db.return_code -eq 0) {
|
||||
$db | convertto-json -compress | out-file compat_database.dat -encoding utf8
|
||||
}
|
||||
copy-item compat_database.dat .\bin\GuiConfigs\compat_database.dat
|
||||
|
||||
- ps: | # package artifacts
|
||||
7z a -m0=LZMA2 -mx9 $env:BUILD .\bin\*
|
||||
7z a -m0=LZMA2 -mx9 openssl_win64.7z C:\OpenSSL-Win64\bin\libeay32.dll `
|
||||
C:\OpenSSL-Win64\bin\ssleay32.dll
|
||||
|
||||
- ps: | # generate sha256 hashes
|
||||
(Get-FileHash $env:BUILD -Algorithm SHA256).Hash | Out-File -encoding ASCII "$($env:BUILD).sha256"
|
||||
(Get-FileHash openssl_win64.7z -Algorithm SHA256).Hash | Out-File -encoding ASCII "openssl_win64.7z.sha256"
|
||||
|
||||
# to disable automatic tests
|
||||
test: off
|
||||
|
||||
#---------------------------------#
|
||||
# artifacts configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# pushing entire folder as a zip archive
|
||||
artifacts:
|
||||
- path: bin
|
||||
name: 'rpcs3-v0.0.4-$(COMMIT_DATE)-$(COMMIT_SHA)_win64'
|
||||
- path: $(BUILD)
|
||||
name: rpcs3
|
||||
- path: $(BUILD).sha256
|
||||
name: rpcs3 sha256 hash
|
||||
- path: openssl_win64.7z
|
||||
name: openssl
|
||||
- path: openssl_win64.7z.sha256
|
||||
name: openssl sha256 hash
|
||||
|
||||
on_finish:
|
||||
- ps: | # update appveyor build version, done last to prevent webhook breakage
|
||||
update-appveyorbuild -version $env:AVVER
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
TheMitoSan Dark-Theme for RPCS3
|
||||
Based on Kuroi (Dark) by Ani
|
||||
by themitosan @ twitter.com/themitosan
|
||||
Ani @ https://github.com/AniLeo
|
||||
(2017.11.14)
|
||||
*/
|
||||
|
||||
/* Every widget */
|
||||
QWidget {
|
||||
background-color: #131313;
|
||||
color: #FFF;
|
||||
alternate-background-color: #212121;
|
||||
}
|
||||
|
||||
/* Mouse tooltips */
|
||||
QToolTip {
|
||||
padding: 0.125em;
|
||||
border: 0.0625em #444;
|
||||
background-color: #222;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Table headers */
|
||||
QHeaderView::section {
|
||||
background-color: #010101;
|
||||
color: #ecf0f1;
|
||||
padding-left: 0.25em;
|
||||
border: 0.0525em solid #FFF;
|
||||
}
|
||||
|
||||
/* Settings Dialog: Tabs */
|
||||
QTabBar::tab {
|
||||
color: #ecf0f1;
|
||||
border: 0.0625em solid #444;
|
||||
border-bottom-style: none;
|
||||
background-color: #353535;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
margin-right: -0.125em;
|
||||
border-top-left-radius: 0.25em;
|
||||
border-top-right-radius: 0.25em;
|
||||
}
|
||||
QTabBar::tab:last {
|
||||
margin-right: 0em;
|
||||
}
|
||||
QTabBar::tab:!selected {
|
||||
color: #888;
|
||||
border-bottom-style: solid;
|
||||
margin-top: 0.1875em;
|
||||
background-color: #111;
|
||||
}
|
||||
QTabBar::tab:hover {
|
||||
background-color: #353535;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Checkboxes */
|
||||
QCheckBox::indicator {
|
||||
border-radius: 0.125em;
|
||||
border-top-right-radius: 0em;
|
||||
border-bottom-left-radius: 0em;
|
||||
border: 0.0625em solid #FFF;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
margin-top: 0.0625em;
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
background-color: #FFF; /* White */
|
||||
}
|
||||
QCheckBox::indicator:unchecked {
|
||||
background-color: #000; /* Black */
|
||||
}
|
||||
QCheckBox::indicator::disabled {
|
||||
background-color: #af4949; /* Red */
|
||||
}
|
||||
|
||||
/* Radio Buttons */
|
||||
QRadioButton::indicator {
|
||||
border: 0.0625em solid #FFF;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
margin-top: 0.0625em;
|
||||
border-radius: 0.270em;
|
||||
}
|
||||
QRadioButton::indicator:checked {
|
||||
background-color: #FFF; /* Green */
|
||||
}
|
||||
QRadioButton::indicator:unchecked {
|
||||
background-color: #000; /* Red */
|
||||
}
|
||||
QRadioButton::indicator::disabled {
|
||||
background-color: #af4949; /* Gray */
|
||||
}
|
||||
|
||||
/* Combo Boxes */
|
||||
QComboBox {
|
||||
background-color: #404040;
|
||||
color: #fff;
|
||||
border: 0.0625em solid #1e1e1e;
|
||||
border-radius: 0.25em;
|
||||
padding-bottom: 0.125em;
|
||||
padding-left: 0.25em;
|
||||
}
|
||||
QComboBox::disabled {
|
||||
background-color: #252525;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Group Boxes (Settings Dialog) */
|
||||
QGroupBox {
|
||||
margin-top: 1em;
|
||||
font-size: 8pt;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top;
|
||||
padding: 0.3em 0.5em 0.3em 0.5em;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
QPushButton {
|
||||
background-color: #404040;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
QPushButton::disabled {
|
||||
background-color: #353535;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
QPushButton::pressed {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
/* Log and Debugger borders */
|
||||
QTextEdit {
|
||||
border: 0.05em solid #353535;
|
||||
}
|
||||
|
||||
/* For dock buttons to be visible */
|
||||
QDockWidget::close-button, QDockWidget::float-button {
|
||||
background-color: #bdc3c7;
|
||||
border: 0.05em solid #000;
|
||||
border-radius: 0.25em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Disable ugly borders */
|
||||
QTabWidget::pane {
|
||||
border: 0em solid #353535;
|
||||
}
|
||||
|
||||
/* Top menu bar */
|
||||
QMenuBar::item:selected {
|
||||
background: #454545;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
QMenu::item {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 0.75em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
margin-bottom: 0.125em;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background: #444;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
QMenu::item:disabled {
|
||||
background-color: #313131;
|
||||
color: #888888;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Libraries list */
|
||||
QListWidget::item:selected {
|
||||
background-color: #3d3d3d;
|
||||
color: #ecf0f1;
|
||||
border-radius: 0.125em;
|
||||
}
|
||||
QListWidget::item:hover {
|
||||
background-color: #4c4b4b;
|
||||
color: #ecf0f1;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Pad Settings: Controller Image */
|
||||
QLabel#l_controller {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QLabel#gamegrid_font {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Slider on toolbar */
|
||||
QWidget#sizeSliderContainer {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Debug UI Settings buttons */
|
||||
QLabel#color_button {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Seachbar on main toolbar */
|
||||
QLineEdit#mw_searchbar {
|
||||
margin-left: 0.7em;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
/* Uniform colors in Toolbar */
|
||||
QToolButton {
|
||||
background: transparent;
|
||||
color: transparent;
|
||||
border-radius: 0.125em;
|
||||
padding: 0.09375em;
|
||||
margin-left: 0.125em;
|
||||
margin-top: 0.125em;
|
||||
margin-bottom: 0.125em;
|
||||
min-width: 0.063em;
|
||||
width: auto;
|
||||
}
|
||||
QToolButton::disabled {
|
||||
background-color: #353535;
|
||||
}
|
||||
QToolButton::hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
/* Set Theme UI colors */
|
||||
QLabel#gamelist_icon_background_color {
|
||||
color: transparent;
|
||||
}
|
||||
QLabel#gamelist_toolbar_icon_color {
|
||||
color: #828790;
|
||||
}
|
||||
|
||||
/* Set Windows Taskbar Thumbnail colors */
|
||||
QLabel#thumbnail_icon_color {
|
||||
color: #262626;
|
||||
}
|
||||
|
||||
/* Set Log colors */
|
||||
QTextEdit#log_frame {
|
||||
background-color: #000; /* Black */
|
||||
}
|
||||
QLabel#log_level_always {
|
||||
color: #00ffff; /* Cyan */
|
||||
}
|
||||
QLabel#log_level_fatal {
|
||||
color: #ff00ff; /* Fuchsia */
|
||||
}
|
||||
QLabel#log_level_error {
|
||||
color: #ff0000; /* Red */
|
||||
}
|
||||
QLabel#log_level_todo {
|
||||
color: #ff6000; /* Orange */
|
||||
}
|
||||
QLabel#log_level_success {
|
||||
color: #00ff00; /* Green */
|
||||
}
|
||||
QLabel#log_level_warning {
|
||||
color: #ffff00; /* Yellow */
|
||||
}
|
||||
QLabel#log_level_notice {
|
||||
color: #ffffff; /* White */
|
||||
}
|
||||
QLabel#log_level_trace {
|
||||
color: #808080; /* Gray */
|
||||
}
|
||||
QLabel#log_stack {
|
||||
color: #ffffff; /* White */
|
||||
}
|
||||
|
||||
/* Set TTY colors */
|
||||
QTextEdit#tty_frame {
|
||||
background-color: #000; /* Black */
|
||||
}
|
||||
QLabel#tty_text {
|
||||
color: #fff; /* White */
|
||||
}
|
||||
|
||||
/* RSX Debugger */
|
||||
QLabel#rsx_debugger_display_buffer {
|
||||
background-color: #131313;
|
||||
}
|
||||
|
||||
/* Kernel Explorer */
|
||||
QDialog#kernel_explorer {
|
||||
background-color: #131313;
|
||||
}
|
||||
|
||||
/* Memory Viewer */
|
||||
QDialog#memory_viewer {
|
||||
background-color: #131313;
|
||||
color: #FFF;
|
||||
}
|
||||
QLabel#memory_viewer_address_panel {
|
||||
color: #00cbff; /* Font Color: Blue */
|
||||
background-color: #131313;
|
||||
}
|
||||
QLabel#memory_viewer_hex_panel {
|
||||
color: #FFF; /* Font Color: White */
|
||||
background-color: #131313;
|
||||
}
|
||||
QLabel#memory_viewer_ascii_panel {
|
||||
color: #FFF; /* Font Color: White */
|
||||
background-color: #131313;
|
||||
}
|
||||
|
||||
/* Debugger colors */
|
||||
QLabel#debugger_frame_breakpoint {
|
||||
color: #000; /* Font Color: Black */
|
||||
background-color: #ffff00; /* Yellow */
|
||||
}
|
||||
QLabel#debugger_frame_pc {
|
||||
color: #000; /* Font Color: Black */
|
||||
background-color: #00ff00; /* Green */
|
||||
}
|
||||
@@ -241,10 +241,10 @@ QToolButton::hover {
|
||||
|
||||
/* Set Theme UI colors */
|
||||
QLabel#gamelist_icon_background_color {
|
||||
background-color: #323232;
|
||||
color: transparent;
|
||||
}
|
||||
QLabel#gamelist_toolbar_icon_color {
|
||||
background-color: #e3e3e3;
|
||||
color: #828790;
|
||||
}
|
||||
|
||||
/* Set Windows Taskbar Thumbnail colors */
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
ModernBlue Theme for RPCS3
|
||||
by themitosan @ twitter.com/themitosan
|
||||
(2017.12.12)
|
||||
*/
|
||||
|
||||
/* Every widget */
|
||||
QWidget {
|
||||
background-color: #232e3a;
|
||||
color: #fff;
|
||||
alternate-background-color: #141e28;
|
||||
}
|
||||
|
||||
/* Mouse tooltips */
|
||||
QToolTip {
|
||||
padding: 0.125em;
|
||||
border: 0.0625em #444;
|
||||
background-color: #181d24;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Table headers */
|
||||
QHeaderView::section {
|
||||
background-color: #333b44;
|
||||
color: #ecf0f1;
|
||||
padding-left: 0.25em;
|
||||
border: 0.0425em solid #fff;
|
||||
}
|
||||
|
||||
/* Settings Dialog: Tabs */
|
||||
QTabBar::tab {
|
||||
color: #ecf0f1;
|
||||
border: 0.0625em solid #feffff;
|
||||
border-bottom-style: none;
|
||||
background-color: #232e3a;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
margin-right: -0.125em;
|
||||
border-top-left-radius: 0.25em;
|
||||
border-top-right-radius: 0.25em;
|
||||
}
|
||||
QTabBar::tab:last {
|
||||
margin-right: 0em;
|
||||
}
|
||||
QTabBar::tab:!selected {
|
||||
color: #666;
|
||||
border-bottom-style: solid;
|
||||
margin-top: 0.1875em;
|
||||
background-color: #1b242f;
|
||||
}
|
||||
QTabBar::tab:hover {
|
||||
background-color: #232e3a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Checkboxes */
|
||||
QCheckBox::indicator {
|
||||
border-radius: 0.125em;
|
||||
border-top-right-radius: 0em;
|
||||
border-bottom-left-radius: 0em;
|
||||
border: 0.0625em solid #fff;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
margin-top: 0.0625em;
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
background-color: #849ad2; /* Green */
|
||||
}
|
||||
QCheckBox::indicator:unchecked {
|
||||
background-color: #203042; /* Red */
|
||||
}
|
||||
QCheckBox::indicator::disabled {
|
||||
background-color: red; /* Gray */
|
||||
}
|
||||
|
||||
/* Radio Buttons */
|
||||
QRadioButton::indicator {
|
||||
border: 0.0625em solid #fff;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
margin-top: 0.0625em;
|
||||
border-radius: 0.270em;
|
||||
}
|
||||
QRadioButton::indicator:checked {
|
||||
background-color: #849ad2; /* Green */
|
||||
}
|
||||
QRadioButton::indicator:unchecked {
|
||||
background-color: #203042; /* Red */
|
||||
}
|
||||
QRadioButton::indicator::disabled {
|
||||
background-color: red; /* Gray */
|
||||
}
|
||||
|
||||
/* Combo Boxes */
|
||||
QComboBox {
|
||||
background-color: #323c47;
|
||||
color: #fff;
|
||||
border: 0.0625em solid #ddd;
|
||||
border-radius: 0.25em;
|
||||
padding-bottom: 0.125em;
|
||||
padding-left: 0.25em;
|
||||
}
|
||||
QComboBox::disabled {
|
||||
background-color: #11182b;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Group Boxes (Settings Dialog) */
|
||||
QGroupBox {
|
||||
margin-top: 1em;
|
||||
font-size: 8pt;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top;
|
||||
padding: 0.3em 0.5em 0.3em 0.5em;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
QPushButton {
|
||||
background-color: #46598b;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
QPushButton::disabled {
|
||||
background-color: #20283c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
QPushButton::pressed {
|
||||
background-color: #172038;
|
||||
}
|
||||
|
||||
/* Log and Debugger borders */
|
||||
QTextEdit {
|
||||
border: 0.05em solid #ddd;
|
||||
}
|
||||
|
||||
/* For dock buttons to be visible */
|
||||
QDockWidget::close-button, QDockWidget::float-button {
|
||||
background-color: #bdc3c7;
|
||||
border: 0.05em solid #777;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Disable ugly borders */
|
||||
QTabWidget::pane {
|
||||
border: 0em solid #333b44;
|
||||
}
|
||||
|
||||
/* Top menu bar */
|
||||
QMenuBar::item:selected {
|
||||
background: #353e48;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
QMenu::item {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 0.75em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
margin-bottom: 0.125em;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background: #354454;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
QMenu::item:disabled {
|
||||
background-color: #181d24;
|
||||
color: #fff;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Libraries list */
|
||||
QListWidget::item:selected {
|
||||
background-color: #3d3d3d;
|
||||
color: #ecf0f1;
|
||||
border-radius: 0.125em;
|
||||
}
|
||||
QListWidget::item:hover {
|
||||
background-color: #4c4b4b;
|
||||
color: #ecf0f1;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Pad Settings: Controller Image */
|
||||
QLabel#l_controller {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QLabel#gamegrid_font {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Slider on toolbar */
|
||||
QWidget#sizeSliderContainer {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Debug UI Settings buttons */
|
||||
QLabel#color_button {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Seachbar on main toolbar */
|
||||
QLineEdit#mw_searchbar {
|
||||
margin-left: 0.7em;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
/* Uniform colors in Toolbar */
|
||||
QToolButton {
|
||||
background: transparent;
|
||||
color: transparent;
|
||||
border-radius: 0.125em;
|
||||
padding: 0.09375em;
|
||||
margin-left: 0.125em;
|
||||
margin-top: 0.125em;
|
||||
margin-bottom: 0.125em;
|
||||
min-width: 0.063em;
|
||||
width: auto;
|
||||
}
|
||||
QToolButton::disabled {
|
||||
background-color: #11182b;
|
||||
}
|
||||
QToolButton::hover {
|
||||
background-color: #3d475e;
|
||||
}
|
||||
|
||||
/* Set Theme UI colors */
|
||||
QLabel#gamelist_icon_background_color {
|
||||
color: transparent;
|
||||
}
|
||||
QLabel#gamelist_toolbar_icon_color {
|
||||
color: #828790;
|
||||
}
|
||||
|
||||
/* Set Windows Taskbar Thumbnail colors */
|
||||
QLabel#thumbnail_icon_color {
|
||||
color: #262626;
|
||||
}
|
||||
|
||||
/* Set Log colors */
|
||||
QTextEdit#log_frame {
|
||||
background-color: #181d24; /* Black */
|
||||
}
|
||||
QLabel#log_level_always {
|
||||
color: #74ffda; /* Cyan */
|
||||
}
|
||||
QLabel#log_level_fatal {
|
||||
color: #ff35ff; /* Fuchsia */
|
||||
}
|
||||
QLabel#log_level_error {
|
||||
color: #ff2424; /* Red */
|
||||
}
|
||||
QLabel#log_level_todo {
|
||||
color: #ff8c46; /* Orange */
|
||||
}
|
||||
QLabel#log_level_success {
|
||||
color: #7aff7a; /* Green */
|
||||
}
|
||||
QLabel#log_level_warning {
|
||||
color: #f7ff74; /* Yellow */
|
||||
}
|
||||
QLabel#log_level_notice {
|
||||
color: #fff; /* White */
|
||||
}
|
||||
QLabel#log_level_trace {
|
||||
color: #808080; /* Gray */
|
||||
}
|
||||
QLabel#log_stack {
|
||||
color: #fff; /* White */
|
||||
}
|
||||
|
||||
/* Set TTY colors */
|
||||
QTextEdit#tty_frame {
|
||||
background-color: #181d24; /* Black */
|
||||
}
|
||||
QLabel#tty_text {
|
||||
color: #fff; /* White */
|
||||
}
|
||||
|
||||
/* RSX Debugger */
|
||||
QLabel#rsx_debugger_display_buffer {
|
||||
background-color: #181d24;
|
||||
}
|
||||
|
||||
/* Kernel Explorer */
|
||||
QDialog#kernel_explorer {
|
||||
background-color: #333b44;
|
||||
}
|
||||
|
||||
/* Memory Viewer */
|
||||
QDialog#memory_viewer {
|
||||
background-color: #333b44;
|
||||
color: #fff;
|
||||
}
|
||||
QLabel#memory_viewer_address_panel {
|
||||
color: #00cbff; /* Font Color: Blue */
|
||||
background-color: #333b44;
|
||||
}
|
||||
QLabel#memory_viewer_hex_panel {
|
||||
color: #fff; /* Font Color: Grey */
|
||||
background-color: #333b44;
|
||||
}
|
||||
QLabel#memory_viewer_ascii_panel {
|
||||
color: #fff; /* Font Color: Grey */
|
||||
background-color: #333b44;
|
||||
}
|
||||
|
||||
/* Debugger colors */
|
||||
QLabel#debugger_frame_breakpoint {
|
||||
color: #000; /* Font Color: Black */
|
||||
background-color: #333b44; /* Yellow */
|
||||
}
|
||||
QLabel#debugger_frame_pc {
|
||||
color: #000; /* Font Color: Black */
|
||||
background-color: #333b44; /* Green */
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
@@ -18,12 +18,12 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -39,30 +39,30 @@
|
||||
<NMakePreprocessorDefinitions>
|
||||
</NMakePreprocessorDefinitions>
|
||||
<NMakeBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NMakePreprocessorDefinitions />
|
||||
<NMakeBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -9,7 +9,8 @@ function Controller() {
|
||||
}
|
||||
|
||||
Controller.prototype.WelcomePageCallback = function() {
|
||||
gui.clickButton(buttons.NextButton);
|
||||
// Wait 10 seconds to load licenses and such.
|
||||
gui.clickButton(buttons.NextButton, 10000);
|
||||
}
|
||||
|
||||
Controller.prototype.CredentialsPageCallback = function() {
|
||||
@@ -32,7 +33,7 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
widget.deselectAll();
|
||||
widget.selectComponent("qt.592.gcc_64");
|
||||
widget.selectComponent("qt.qt5.5100.gcc_64");
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjitsrc\asmjit.vcxproj", "{AC40FF01-426E-4838-A317-66354CEFAE88}"
|
||||
EndProject
|
||||
@@ -243,7 +243,4 @@ Global
|
||||
{FDC361C5-7734-493B-8CFB-037308B35122} = {DDF904CA-2771-441A-8629-5DF2EB922A79}
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {FA1E6C16-CA63-45F8-8D52-E21DF396BE36}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -3,48 +3,46 @@ cmake_minimum_required(VERSION 3.1)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules")
|
||||
set(RES_FILES "")
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
# Qt section
|
||||
find_package(Qt5 5.9 COMPONENTS Widgets)
|
||||
if (WIN32)
|
||||
find_package(Qt5WinExtras REQUIRED)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::WinExtras)
|
||||
include_directories(${Qt5Widgets_INCLUDE_DIRS} ${Qt5WinExtras_INCLUDE_DIRS})
|
||||
find_package(Qt5 5.7 COMPONENTS Widgets Network)
|
||||
if(WIN32)
|
||||
find_package(Qt5 5.7 COMPONENTS WinExtras REQUIRED)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::WinExtras Qt5::Network)
|
||||
else()
|
||||
find_package(Qt5DBus)
|
||||
if (Qt5DBus_FOUND)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus)
|
||||
find_package(Qt5 5.7 COMPONENTS DBus Gui)
|
||||
if(Qt5DBus_FOUND)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus Qt5::Network)
|
||||
add_definitions(-DHAVE_QTDBUS)
|
||||
else()
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::Network)
|
||||
endif()
|
||||
include_directories(${Qt5Widgets_INCLUDE_DIRS})
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Let's make sure we have Qt before we continue
|
||||
if (NOT Qt5Widgets_FOUND)
|
||||
if (Qt5Widgets_VERSION VERSION_LESS 5.9.0)
|
||||
message("Minimum supported Qt5 version is 5.9! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
|
||||
if ("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
if(NOT Qt5Widgets_FOUND)
|
||||
if(Qt5Widgets_VERSION VERSION_LESS 5.7.0)
|
||||
message("Minimum supported Qt5 version is 5.7! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
|
||||
if("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
|
||||
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install an up-to-date qt5 version.
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-trusty
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt593-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt593-trusty
|
||||
just make sure to run
|
||||
source /opt/qt59/bin/qt59-env.sh
|
||||
before re-running cmake")
|
||||
elseif(WIN32)
|
||||
elseif(WIN32)
|
||||
message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/")
|
||||
else()
|
||||
message(FATAL_ERROR "Look online for instructions on installing an up-to-date Qt5 on ${CMAKE_SYSTEM}.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
message("CMake was unable to find Qt5!")
|
||||
if (WIN32)
|
||||
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.9\\msvc2017_64\\)")
|
||||
endif()
|
||||
|
||||
message("CMake was unable to find Qt5!")
|
||||
if(WIN32)
|
||||
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.8\\msvc2017_64\\)")
|
||||
elseif("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
|
||||
else()
|
||||
@@ -57,14 +55,16 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
# To make UI files on cmake 3.7 or less work
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
if(CMAKE_VERION VERSION_LESS 3.8)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
endif()
|
||||
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if(UNIX)
|
||||
# Cotire needs this set for some reason
|
||||
SET(CMAKE_CXX_COMPILE_OPTIONS_PIE -fPIC)
|
||||
endif()
|
||||
if(Qt5_POSITION_INDEPENDENT_CODE)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if(UNIX)
|
||||
# Cotire needs this set for some reason
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIE -fPIC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(cotire)
|
||||
@@ -101,14 +101,18 @@ if(NOT MSVC)
|
||||
set(CMAKE_RC_COMPILER_INIT windres)
|
||||
enable_language(RC)
|
||||
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
|
||||
|
||||
|
||||
# Workaround for mingw64 (MSYS2)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--allow-multiple-definition")
|
||||
endif()
|
||||
|
||||
add_compile_options(-msse -msse2 -mcx16 -mssse3 -mrtm)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
|
||||
add_compile_options(-msse -msse2 -mcx16 -mrtm)
|
||||
|
||||
if(NOT DEFINED ENV{TRAVIS})
|
||||
add_compile_options(-march=native)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# This fixes 'some' of the st11range issues. See issue #2516
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-image_base,0x10000 -Wl,-pagezero_size,0x10000")
|
||||
@@ -116,13 +120,13 @@ if(NOT MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -image-base=0x10000")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# Some distros have the compilers set to use PIE by default, but RPCS3 doesn't work with PIE, so we need to disable it.
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie")
|
||||
else()
|
||||
CHECK_C_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
|
||||
CHECK_C_COMPILER_FLAG("-nopie" HAS_NOPIE)
|
||||
CHECK_CXX_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
|
||||
CHECK_CXX_COMPILER_FLAG("-nopie" HAS_NOPIE)
|
||||
|
||||
if(HAS_NO_PIE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
|
||||
@@ -130,12 +134,11 @@ if(NOT MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nopie")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(GLEW REQUIRED)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /D _CRT_SECURE_NO_DEPRECATE=1 /D _CRT_NON_CONFORMING_SWPRINTFS=1 /D _SCL_SECURE_NO_WARNINGS=1")
|
||||
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /DYNAMICBASE:NO /BASE:0x10000 /FIXED")
|
||||
endif()
|
||||
@@ -151,44 +154,49 @@ elseif(NOT MSVC AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} "X11")
|
||||
find_package(Wayland)
|
||||
if (WAYLAND_FOUND)
|
||||
include_directories(${WAYLAND_INCLUDE_DIR})
|
||||
add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT RPCS3_SRC_DIR)
|
||||
SET(RPCS3_SRC_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
Message("-- Initializing RPCS3_SRC_DIR=${RPCS3_SRC_DIR}")
|
||||
set(RPCS3_SRC_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
message("-- Initializing RPCS3_SRC_DIR=${RPCS3_SRC_DIR}")
|
||||
else()
|
||||
Message("-- Using Custom RPCS3_SRC_DIR=${RPCS3_SRC_DIR}")
|
||||
message("-- Using Custom RPCS3_SRC_DIR=${RPCS3_SRC_DIR}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH "${RPCS3_SRC_DIR}/cmake_modules")
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
if (NOT WITHOUT_LLVM)
|
||||
if(NOT WITHOUT_LLVM)
|
||||
find_package(LLVM 4.0 CONFIG)
|
||||
if (NOT LLVM_FOUND)
|
||||
message("System LLVM was not found, LLVM will be built from the submodule.")
|
||||
if(NOT LLVM_FOUND)
|
||||
message("System LLVM was not found, LLVM will be built from the submodule.")
|
||||
|
||||
set(LLVM_TARGETS_TO_BUILD "X86" CACHE INTERNAL "")
|
||||
option(LLVM_BUILD_RUNTIME OFF)
|
||||
option(LLVM_BUILD_TOOLS OFF)
|
||||
option(LLVM_INCLUDE_DOCS OFF)
|
||||
option(LLVM_INCLUDE_EXAMPLES OFF)
|
||||
option(LLVM_INCLUDE_TESTS OFF)
|
||||
option(LLVM_INCLUDE_TOOLS OFF)
|
||||
option(LLVM_INCLUDE_UTILS OFF)
|
||||
option(WITH_POLLY OFF)
|
||||
set(LLVM_TARGETS_TO_BUILD "X86" CACHE INTERNAL "")
|
||||
option(LLVM_BUILD_RUNTIME OFF)
|
||||
option(LLVM_BUILD_TOOLS OFF)
|
||||
option(LLVM_INCLUDE_DOCS OFF)
|
||||
option(LLVM_INCLUDE_EXAMPLES OFF)
|
||||
option(LLVM_INCLUDE_TESTS OFF)
|
||||
option(LLVM_INCLUDE_TOOLS OFF)
|
||||
option(LLVM_INCLUDE_UTILS OFF)
|
||||
option(WITH_POLLY OFF)
|
||||
|
||||
# LLVM needs to be built out-of-tree
|
||||
add_subdirectory(../llvm ../llvm_build)
|
||||
set(LLVM_DIR "${CMAKE_CURRENT_BINARY_DIR}/../llvm_build/lib/cmake/llvm/")
|
||||
# LLVM needs to be built out-of-tree
|
||||
add_subdirectory(../llvm ../llvm_build)
|
||||
set(LLVM_DIR "${CMAKE_CURRENT_BINARY_DIR}/../llvm_build/lib/cmake/llvm/")
|
||||
|
||||
# now tries to find LLVM again
|
||||
find_package(LLVM 4.0 CONFIG)
|
||||
if (NOT LLVM_FOUND)
|
||||
message(WARNING "Couldn't build LLVM from the submodule. You might need to run `git submodule update --init`")
|
||||
endif()
|
||||
endif()
|
||||
# now tries to find LLVM again
|
||||
find_package(LLVM 4.0 CONFIG)
|
||||
if(NOT LLVM_FOUND)
|
||||
message(WARNING "Couldn't build LLVM from the submodule. You might need to run `git submodule update --init`")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -199,18 +207,17 @@ elseif(WIN32)
|
||||
else()
|
||||
set(PLATFORM_ARCH "linux/x86_64")
|
||||
option(USE_ALSA "ALSA audio backend" ON)
|
||||
option(USE_PULSE "PulseAudio audio backend" ON)
|
||||
option(USE_PULSE "PulseAudio audio backend" ON)
|
||||
option(USE_LIBEVDEV "libevdev-based joystick support" ON)
|
||||
option(USE_VULKAN "Vulkan render backend" ON)
|
||||
endif()
|
||||
|
||||
if(USE_ALSA)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(ALSA alsa)
|
||||
find_package(ALSA)
|
||||
if(ALSA_FOUND)
|
||||
add_definitions(-DHAVE_ALSA)
|
||||
include_directories(SYSTEM ${ALSA_INCLUDE_DIRS})
|
||||
list(APPEND ADDITIONAL_LIBS ${ALSA_LDFLAGS})
|
||||
list(APPEND ADDITIONAL_LIBS ${ALSA_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
if(USE_PULSE)
|
||||
@@ -236,6 +243,9 @@ if(NOT WIN32 AND USE_VULKAN)
|
||||
if(VULKAN_FOUND)
|
||||
add_definitions(-DHAVE_VULKAN)
|
||||
list(APPEND ADDITIONAL_LIBS ${VULKAN_LIBRARY})
|
||||
if(VULKAN_PREBUILT)
|
||||
list(APPEND ADDITIONAL_LIBS glslang HLSL OGLCompiler SPIRV OSDependent)
|
||||
endif()
|
||||
else()
|
||||
message("WARNING! USE_VULKAN was enabled, but libvulkan was not found. RPCS3 will be compiled without Vulkan support.")
|
||||
endif()
|
||||
@@ -262,8 +272,6 @@ else()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
"${RPCS3_SRC_DIR}/../3rdparty/pugixml/src"
|
||||
@@ -292,17 +300,17 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(NOT LLVM_FOUND)
|
||||
Message("LLVM 4.0 not found. RPCS3 will be compiled without LLVM support.")
|
||||
message("LLVM 4.0 not found. RPCS3 will be compiled without LLVM support.")
|
||||
else()
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
add_definitions(-DLLVM_AVAILABLE)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
llvm_map_components_to_libnames(LLVM_LIBS core support executionengine object runtimedyld x86desc x86info scalaropts mcjit vectorize ipo x86codegen x86disassembler)
|
||||
else()
|
||||
llvm_map_components_to_libnames(LLVM_LIBS core support executionengine object runtimedyld x86desc x86info scalaropts mcjit vectorize ipo x86codegen x86disassembler mcdisassembler)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
if(NOT MSVC)
|
||||
set_source_files_properties(${RPCS3_SRC_DIR}/../Utilities/JIT.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
|
||||
set_source_files_properties(${RPCS3_SRC_DIR}/Emu/Cell/PPUTranslator.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
|
||||
endif()
|
||||
@@ -321,7 +329,7 @@ if(NOT USE_SYSTEM_FFMPEG)
|
||||
endif()
|
||||
|
||||
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
foreach(dir ${dirs})
|
||||
foreach (dir ${dirs})
|
||||
message(STATUS "dir='${dir}'")
|
||||
endforeach()
|
||||
|
||||
@@ -333,7 +341,7 @@ RPCS3_SRC
|
||||
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit/*.cpp"
|
||||
)
|
||||
|
||||
if (NOT WIN32 AND VULKAN_FOUND)
|
||||
if(NOT WIN32 AND VULKAN_FOUND)
|
||||
# Compile glslang and SPIRV modules needed for glsl compilation
|
||||
file(
|
||||
GLOB_RECURSE
|
||||
@@ -344,26 +352,26 @@ if (NOT WIN32 AND VULKAN_FOUND)
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/OGLCompilersDLL/*.cpp"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/SPIRV/*.cpp"
|
||||
)
|
||||
|
||||
set (RPCS3_SRC ${RPCS3_SRC} ${UNIX_GLSLANG})
|
||||
|
||||
set(RPCS3_SRC ${RPCS3_SRC} ${UNIX_GLSLANG})
|
||||
endif()
|
||||
|
||||
#File exclusion section
|
||||
|
||||
if(NOT WIN32 AND NOT VULKAN_FOUND)
|
||||
set (EXCLUDE_FILES "/RSX/VK/")
|
||||
set(EXCLUDE_FILES "/RSX/VK/")
|
||||
endif()
|
||||
|
||||
# Ignore autogenerated moc_* files if present
|
||||
set (EXCLUDE_FILES ${EXCLUDE_FILES} "moc_")
|
||||
set (EXCLUDE_FILES ${EXCLUDE_FILES} "rpcs3_automoc")
|
||||
set (EXCLUDE_FILES ${EXCLUDE_FILES} "qrc_resources.cpp")
|
||||
set(EXCLUDE_FILES ${EXCLUDE_FILES} "moc_")
|
||||
set(EXCLUDE_FILES ${EXCLUDE_FILES} "rpcs3_automoc")
|
||||
set(EXCLUDE_FILES ${EXCLUDE_FILES} "qrc_resources.cpp")
|
||||
|
||||
foreach (TMP_PATH ${RPCS3_SRC})
|
||||
foreach (EXCLUDE_PATH ${EXCLUDE_FILES})
|
||||
string (FIND ${TMP_PATH} ${EXCLUDE_PATH} EXCLUDE_FILE_FOUND)
|
||||
if (NOT ${EXCLUDE_FILE_FOUND} EQUAL -1)
|
||||
list (REMOVE_ITEM RPCS3_SRC ${TMP_PATH})
|
||||
string(FIND ${TMP_PATH} ${EXCLUDE_PATH} EXCLUDE_FILE_FOUND)
|
||||
if(NOT ${EXCLUDE_FILE_FOUND} EQUAL -1)
|
||||
list(REMOVE_ITEM RPCS3_SRC ${TMP_PATH})
|
||||
endif ()
|
||||
endforeach(EXCLUDE_PATH)
|
||||
endforeach(TMP_PATH)
|
||||
@@ -372,24 +380,29 @@ endforeach(TMP_PATH)
|
||||
file(GLOB_RECURSE TMP_MOC "${RPCS3_SRC_DIR}/moc_*.cpp" "${RPCS3_SRC_DIR}/rpcs3_automoc.cpp" "${RPCS3_SRC_DIR}/qrc_resources.cpp")
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${TMP_MOC}")
|
||||
|
||||
if (WIN32)
|
||||
add_executable(rpcs3 WIN32 ${RPCS3_SRC} ${RES_FILES} resources.qrc)
|
||||
if(WIN32)
|
||||
add_executable(rpcs3 WIN32 ${RPCS3_SRC} ${RES_FILES} resources.qrc)
|
||||
else()
|
||||
add_executable(rpcs3 ${RPCS3_SRC} ${RES_FILES} resources.qrc)
|
||||
add_executable(rpcs3 ${RPCS3_SRC} ${RES_FILES} resources.qrc)
|
||||
endif()
|
||||
|
||||
add_dependencies(rpcs3 GitVersion)
|
||||
|
||||
if(NOT MSVC)
|
||||
find_package(GLEW 1.13.0 REQUIRED)
|
||||
target_link_libraries(rpcs3 GLEW::GLEW)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib Psapi.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV HLSL setupapi.lib hidapi-hid Shlwapi.lib)
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} opengl32.lib glu32.lib libpthread)
|
||||
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} opengl32.lib glu32.lib libpthread)
|
||||
else()
|
||||
target_link_libraries(rpcs3 dxgi.lib d2d1.lib dwrite.lib)
|
||||
target_link_libraries(rpcs3 dxgi.lib d2d1.lib dwrite.lib)
|
||||
endif()
|
||||
target_link_libraries(rpcs3 avformat.lib avcodec.lib avutil.lib swresample.lib swscale.lib png16_static ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
|
||||
target_link_libraries(rpcs3 avformat.lib avcodec.lib avutil.lib swscale.lib png16_static ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
|
||||
else()
|
||||
target_link_libraries(rpcs3 ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
|
||||
target_link_libraries(rpcs3 ${OPENAL_LIBRARY} ${OPENGL_LIBRARIES})
|
||||
if(APPLE)
|
||||
target_link_libraries(rpcs3 hidapi-mac "-framework CoreFoundation" "-framework IOKit")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
@@ -400,50 +413,57 @@ else()
|
||||
if(VULKAN_FOUND)
|
||||
target_link_libraries(rpcs3 ${VULKAN_LIBRARIES})
|
||||
endif()
|
||||
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS} -lpthread ${ZLIB_LIBRARIES} ${ADDITIONAL_LIBS})
|
||||
if (USE_SYSTEM_FFMPEG)
|
||||
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS} -lpthread ZLIB::ZLIB ${ADDITIONAL_LIBS})
|
||||
if(USE_SYSTEM_FFMPEG)
|
||||
link_libraries(${FFMPEG_LIBRARY_DIR})
|
||||
target_link_libraries(rpcs3 libavformat.so libavcodec.so libavutil.so libswresample.so libswscale.so)
|
||||
target_link_libraries(rpcs3 libavformat.so libavcodec.so libavutil.so libswscale.so)
|
||||
else()
|
||||
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a)
|
||||
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswscale.a)
|
||||
endif()
|
||||
if (USE_SYSTEM_LIBPNG)
|
||||
target_link_libraries(rpcs3 ${PNG_LIBRARIES})
|
||||
if(USE_SYSTEM_LIBPNG)
|
||||
target_link_libraries(rpcs3 ${PNG_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(rpcs3 png16_static)
|
||||
target_link_libraries(rpcs3 png16_static)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# For some reason GCC 7 requires manually linking with -latomic
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7))
|
||||
if(CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7))
|
||||
target_link_libraries(rpcs3 -latomic)
|
||||
endif()
|
||||
|
||||
if(LLVM_FOUND)
|
||||
target_link_libraries(rpcs3 ${LLVM_LIBS})
|
||||
target_link_libraries(rpcs3 ${LLVM_LIBS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(rpcs3 ${RPCS3_QT_LIBS})
|
||||
|
||||
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
|
||||
|
||||
if (MSVC)
|
||||
# Under Windows, some QT DLLs need to be in the same directory of the compiled
|
||||
# RPCS3 binary, so call the windeployqt tool that will take care of copying
|
||||
# them from the local QT installation at the end of the build.
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||
COMMAND $ENV{QTDIR}/bin/windeployqt --no-angle --no-opengl-sw --no-svg --no-translations --debug ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
else()
|
||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||
COMMAND $ENV{QTDIR}/bin/windeployqt --no-angle --no-opengl-sw --no-svg --no-translations ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
endif()
|
||||
if(MSVC)
|
||||
# Under Windows, some QT DLLs need to be in the same directory of the compiled
|
||||
# RPCS3 binary, so call the windeployqt tool that will take care of copying
|
||||
# them from the local QT installation at the end of the build.
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||
COMMAND $ENV{QTDIR}/bin/windeployqt --no-angle --no-opengl-sw --no-svg --no-translations --debug ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
else()
|
||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||
COMMAND $ENV{QTDIR}/bin/windeployqt --no-angle --no-opengl-sw --no-svg --no-translations ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cotire(rpcs3)
|
||||
|
||||
if (UNIX)
|
||||
# Copy icons to executable directory
|
||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons)
|
||||
endif()
|
||||
|
||||
# Unix installation
|
||||
if(UNIX AND NOT APPLE)
|
||||
# Install the binary
|
||||
@@ -455,4 +475,9 @@ if(UNIX AND NOT APPLE)
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps)
|
||||
install(FILES rpcs3.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||
# Install other files
|
||||
install(DIRECTORY ../bin/Icons
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/rpcs3)
|
||||
install(DIRECTORY ../bin/GuiConfigs
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/rpcs3)
|
||||
endif()
|
||||
|
||||
@@ -148,20 +148,40 @@ void WriteEhdr(const fs::file& f, Elf32_Ehdr& ehdr)
|
||||
Write8(f, ehdr.e_data);
|
||||
Write8(f, ehdr.e_curver);
|
||||
Write8(f, ehdr.e_os_abi);
|
||||
Write64(f, ehdr.e_abi_ver);
|
||||
Write16(f, ehdr.e_type);
|
||||
Write16(f, ehdr.e_machine);
|
||||
Write32(f, ehdr.e_version);
|
||||
Write32(f, ehdr.e_entry);
|
||||
Write32(f, ehdr.e_phoff);
|
||||
Write32(f, ehdr.e_shoff);
|
||||
Write32(f, ehdr.e_flags);
|
||||
Write16(f, ehdr.e_ehsize);
|
||||
Write16(f, ehdr.e_phentsize);
|
||||
Write16(f, ehdr.e_phnum);
|
||||
Write16(f, ehdr.e_shentsize);
|
||||
Write16(f, ehdr.e_shnum);
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
if (ehdr.e_data == 1)
|
||||
{
|
||||
Write64LE(f, ehdr.e_abi_ver);
|
||||
Write16LE(f, ehdr.e_type);
|
||||
Write16LE(f, ehdr.e_machine);
|
||||
Write32LE(f, ehdr.e_version);
|
||||
Write32LE(f, ehdr.e_entry);
|
||||
Write32LE(f, ehdr.e_phoff);
|
||||
Write32LE(f, ehdr.e_shoff);
|
||||
Write32LE(f, ehdr.e_flags);
|
||||
Write16LE(f, ehdr.e_ehsize);
|
||||
Write16LE(f, ehdr.e_phentsize);
|
||||
Write16LE(f, ehdr.e_phnum);
|
||||
Write16LE(f, ehdr.e_shentsize);
|
||||
Write16LE(f, ehdr.e_shnum);
|
||||
Write16LE(f, ehdr.e_shstrndx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write64(f, ehdr.e_abi_ver);
|
||||
Write16(f, ehdr.e_type);
|
||||
Write16(f, ehdr.e_machine);
|
||||
Write32(f, ehdr.e_version);
|
||||
Write32(f, ehdr.e_entry);
|
||||
Write32(f, ehdr.e_phoff);
|
||||
Write32(f, ehdr.e_shoff);
|
||||
Write32(f, ehdr.e_flags);
|
||||
Write16(f, ehdr.e_ehsize);
|
||||
Write16(f, ehdr.e_phentsize);
|
||||
Write16(f, ehdr.e_phnum);
|
||||
Write16(f, ehdr.e_shentsize);
|
||||
Write16(f, ehdr.e_shnum);
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
}
|
||||
}
|
||||
|
||||
void WritePhdr(const fs::file& f, Elf32_Phdr& phdr)
|
||||
@@ -190,6 +210,32 @@ void WriteShdr(const fs::file& f, Elf32_Shdr& shdr)
|
||||
Write32(f, shdr.sh_entsize);
|
||||
}
|
||||
|
||||
void WritePhdrLE(const fs::file& f, Elf32_Phdr& phdr)
|
||||
{
|
||||
Write32LE(f, phdr.p_type);
|
||||
Write32LE(f, phdr.p_offset);
|
||||
Write32LE(f, phdr.p_vaddr);
|
||||
Write32LE(f, phdr.p_paddr);
|
||||
Write32LE(f, phdr.p_filesz);
|
||||
Write32LE(f, phdr.p_memsz);
|
||||
Write32LE(f, phdr.p_flags);
|
||||
Write32LE(f, phdr.p_align);
|
||||
}
|
||||
|
||||
void WriteShdrLE(const fs::file& f, Elf32_Shdr& shdr)
|
||||
{
|
||||
Write32LE(f, shdr.sh_name);
|
||||
Write32LE(f, shdr.sh_type);
|
||||
Write32LE(f, shdr.sh_flags);
|
||||
Write32LE(f, shdr.sh_addr);
|
||||
Write32LE(f, shdr.sh_offset);
|
||||
Write32LE(f, shdr.sh_size);
|
||||
Write32LE(f, shdr.sh_link);
|
||||
Write32LE(f, shdr.sh_info);
|
||||
Write32LE(f, shdr.sh_addralign);
|
||||
Write32LE(f, shdr.sh_entsize);
|
||||
}
|
||||
|
||||
|
||||
void AppInfo::Load(const fs::file& f)
|
||||
{
|
||||
@@ -200,6 +246,15 @@ void AppInfo::Load(const fs::file& f)
|
||||
padding = Read64(f);
|
||||
}
|
||||
|
||||
void AppInfo::LoadLE(const fs::file& f)
|
||||
{
|
||||
authid = Read64LE(f);
|
||||
vendor_id = Read32LE(f);
|
||||
self_type = Read32LE(f);
|
||||
version = Read64(f);
|
||||
padding = Read64(f);
|
||||
}
|
||||
|
||||
void AppInfo::Show()
|
||||
{
|
||||
LOG_NOTICE(LOADER, "AuthID: 0x%llx", authid);
|
||||
@@ -218,6 +273,16 @@ void SectionInfo::Load(const fs::file& f)
|
||||
encrypted = Read32(f);
|
||||
}
|
||||
|
||||
void SectionInfo::LoadLE(const fs::file& f)
|
||||
{
|
||||
offset = Read64LE(f);
|
||||
size = Read64LE(f);
|
||||
compressed = Read32LE(f);
|
||||
unknown1 = Read32LE(f);
|
||||
unknown2 = Read32LE(f);
|
||||
encrypted = Read32LE(f);
|
||||
}
|
||||
|
||||
void SectionInfo::Show()
|
||||
{
|
||||
LOG_NOTICE(LOADER, "Offset: 0x%llx", offset);
|
||||
@@ -236,6 +301,14 @@ void SCEVersionInfo::Load(const fs::file& f)
|
||||
unknown = Read32(f);
|
||||
}
|
||||
|
||||
void SCEVersionInfo::LoadLE(const fs::file& f)
|
||||
{
|
||||
subheader_type = Read32LE(f);
|
||||
present = Read32LE(f);
|
||||
size = Read32LE(f);
|
||||
unknown = Read32LE(f);
|
||||
}
|
||||
|
||||
void SCEVersionInfo::Show()
|
||||
{
|
||||
LOG_NOTICE(LOADER, "Sub-header type: 0x%08x", subheader_type);
|
||||
@@ -290,6 +363,65 @@ void ControlInfo::Load(const fs::file& f)
|
||||
}
|
||||
}
|
||||
|
||||
void ControlInfo::LoadLE(const fs::file& f)
|
||||
{
|
||||
type = Read32LE(f);
|
||||
size = Read32LE(f);
|
||||
next = Read64LE(f);
|
||||
|
||||
if (type == 1)
|
||||
{
|
||||
control_flags.ctrl_flag1 = Read32LE(f);
|
||||
control_flags.unknown1 = Read32LE(f);
|
||||
control_flags.unknown2 = Read32LE(f);
|
||||
control_flags.unknown3 = Read32LE(f);
|
||||
control_flags.unknown4 = Read32LE(f);
|
||||
control_flags.unknown5 = Read32LE(f);
|
||||
control_flags.unknown6 = Read32LE(f);
|
||||
control_flags.unknown7 = Read32LE(f);
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
if (size == 0x30)
|
||||
{
|
||||
f.read(file_digest_30.digest, 20);
|
||||
file_digest_30.unknown = Read64LE(f);
|
||||
}
|
||||
else if (size == 0x40)
|
||||
{
|
||||
f.read(file_digest_40.digest1, 20);
|
||||
f.read(file_digest_40.digest2, 20);
|
||||
file_digest_40.unknown = Read64LE(f);
|
||||
}
|
||||
}
|
||||
else if (type == 3)
|
||||
{
|
||||
npdrm.magic = Read32LE(f);
|
||||
npdrm.unknown1 = Read32LE(f);
|
||||
npdrm.license = Read32LE(f);
|
||||
npdrm.type = Read32LE(f);
|
||||
f.read(npdrm.content_id, 48);
|
||||
f.read(npdrm.digest, 16);
|
||||
f.read(npdrm.invdigest, 16);
|
||||
f.read(npdrm.xordigest, 16);
|
||||
npdrm.unknown2 = Read64LE(f);
|
||||
npdrm.unknown3 = Read64LE(f);
|
||||
}
|
||||
else if (type == 5)
|
||||
{
|
||||
f.read(type5.unk, 0x100);
|
||||
}
|
||||
else if (type == 6)
|
||||
{
|
||||
type6.unknown1 = Read32LE(f);
|
||||
f.read(type6.unk, 0xFC);
|
||||
}
|
||||
else if (type == 7)
|
||||
{
|
||||
f.read(type7.unk, 0x40);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlInfo::Show()
|
||||
{
|
||||
LOG_NOTICE(LOADER, "Type: 0x%08x", type);
|
||||
@@ -634,6 +766,19 @@ void SceHeader::Load(const fs::file& f)
|
||||
se_esize = Read64(f);
|
||||
}
|
||||
|
||||
void SceHeader::LoadLE(const fs::file& f)
|
||||
{
|
||||
se_magic = Read32(f);
|
||||
se_hver = Read32LE(f);
|
||||
se_flags = Read16LE(f);
|
||||
se_type = Read16LE(f);
|
||||
se_meta = Read32LE(f);
|
||||
se_hsize = Read64LE(f);
|
||||
se_esize = Read64LE(f);
|
||||
Read64LE(f);
|
||||
Read64LE(f);
|
||||
}
|
||||
|
||||
void SelfHeader::Load(const fs::file& f)
|
||||
{
|
||||
se_htype = Read64(f);
|
||||
@@ -648,6 +793,11 @@ void SelfHeader::Load(const fs::file& f)
|
||||
pad = Read64(f);
|
||||
}
|
||||
|
||||
void SelfHeader::LoadLE(const fs::file& f)
|
||||
{
|
||||
f.read(this, sizeof(*this));
|
||||
}
|
||||
|
||||
SCEDecrypter::SCEDecrypter(const fs::file& s)
|
||||
: sce_f(s)
|
||||
, data_buf_length(0)
|
||||
@@ -885,11 +1035,22 @@ SELFDecrypter::SELFDecrypter(const fs::file& s)
|
||||
{
|
||||
}
|
||||
|
||||
static bool isVita(const SceHeader hdr)
|
||||
{
|
||||
return (hdr.se_hver == 3);
|
||||
}
|
||||
|
||||
bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
{
|
||||
// Read SCE header.
|
||||
self_f.seek(0);
|
||||
sce_hdr.Load(self_f);
|
||||
sce_hdr.LoadLE(self_f);
|
||||
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
self_f.seek(0);
|
||||
sce_hdr.Load(self_f);
|
||||
}
|
||||
|
||||
// Check SCE magic.
|
||||
if (!sce_hdr.CheckMagic())
|
||||
@@ -899,11 +1060,26 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
}
|
||||
|
||||
// Read SELF header.
|
||||
self_hdr.Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
self_hdr.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
self_hdr.LoadLE(self_f);
|
||||
}
|
||||
|
||||
// Read the APP INFO.
|
||||
self_f.seek(self_hdr.se_appinfooff);
|
||||
app_info.Load(self_f);
|
||||
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
app_info.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
app_info.LoadLE(self_f);
|
||||
}
|
||||
|
||||
// Read ELF header.
|
||||
self_f.seek(self_hdr.se_elfoff);
|
||||
@@ -926,7 +1102,14 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
{
|
||||
phdr32_arr.emplace_back();
|
||||
phdr32_arr.back().Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
phdr32_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
phdr32_arr.back().LoadLE(self_f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -956,12 +1139,26 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < ((isElf32) ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
|
||||
{
|
||||
secinfo_arr.emplace_back();
|
||||
secinfo_arr.back().Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
secinfo_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
secinfo_arr.back().LoadLE(self_f);
|
||||
}
|
||||
}
|
||||
|
||||
// Read SCE version info.
|
||||
self_f.seek(self_hdr.se_sceveroff);
|
||||
scev_info.Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
scev_info.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
scev_info.LoadLE(self_f);
|
||||
}
|
||||
|
||||
// Read control info.
|
||||
ctrlinfo_arr.clear();
|
||||
@@ -972,7 +1169,14 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
{
|
||||
ctrlinfo_arr.emplace_back();
|
||||
ControlInfo &cinfo = ctrlinfo_arr.back();
|
||||
cinfo.Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
cinfo.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.LoadLE(self_f);
|
||||
}
|
||||
i += cinfo.size;
|
||||
}
|
||||
|
||||
@@ -992,7 +1196,14 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
{
|
||||
shdr32_arr.emplace_back();
|
||||
shdr32_arr.back().Load(self_f);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
shdr32_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
shdr32_arr.back().LoadLE(self_f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1157,6 +1368,8 @@ bool SELFDecrypter::LoadMetadata(u8* klic_key)
|
||||
memcpy(metadata_iv, keyset.riv, 0x10);
|
||||
|
||||
// Check DEBUG flag.
|
||||
if (sce_hdr.se_flags == 0x00c0)
|
||||
return true;
|
||||
if ((sce_hdr.se_flags & 0x8000) != 0x8000)
|
||||
{
|
||||
// Decrypt the NPDRM layer.
|
||||
@@ -1219,6 +1432,14 @@ bool SELFDecrypter::DecryptData()
|
||||
}
|
||||
}
|
||||
|
||||
if (meta_hdr.section_count == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < secinfo_arr.size(); i++)
|
||||
{
|
||||
data_buf_length += secinfo_arr[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a buffer to store decrypted data.
|
||||
data_buf = std::make_unique<u8[]>(data_buf_length);
|
||||
|
||||
@@ -1266,6 +1487,16 @@ bool SELFDecrypter::DecryptData()
|
||||
}
|
||||
}
|
||||
|
||||
if (meta_hdr.section_count == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < secinfo_arr.size(); i++)
|
||||
{
|
||||
self_f.seek(secinfo_arr[i].offset);
|
||||
self_f.read(data_buf.get() + data_buf_offset, secinfo_arr[i].size);
|
||||
data_buf_offset += secinfo_arr[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1285,20 +1516,75 @@ fs::file SELFDecrypter::MakeElf(bool isElf32)
|
||||
// Write program headers.
|
||||
for (u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
{
|
||||
WritePhdr(e, phdr32_arr[i]);
|
||||
if (elf32_hdr.e_data == 1)
|
||||
{
|
||||
WritePhdrLE(e, phdr32_arr[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePhdr(e, phdr32_arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
if (meta_hdr.section_count != 0)
|
||||
{
|
||||
// PHDR type.
|
||||
if (meta_shdr[i].type == 2)
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
{
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset);
|
||||
e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size);
|
||||
// PHDR type.
|
||||
if (meta_shdr[i].type == 2)
|
||||
{
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset);
|
||||
e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size);
|
||||
|
||||
// Advance the data buffer offset by data size.
|
||||
data_buf_offset += meta_shdr[i].data_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < phdr32_arr.size(); i++)
|
||||
{
|
||||
// Decompress if necessary.
|
||||
if (secinfo_arr[i].compressed == 2)
|
||||
{
|
||||
// Store the length in writeable memory space.
|
||||
std::unique_ptr<uLongf> decomp_buf_length(new uLongf);
|
||||
memcpy(decomp_buf_length.get(), &phdr32_arr[i].p_filesz, sizeof(uLongf));
|
||||
/// Create a pointer to a buffer for decompression.
|
||||
std::unique_ptr<u8[]> decomp_buf(new u8[phdr32_arr[i].p_filesz]);
|
||||
|
||||
// Create a buffer separate from data_buf to uncompress.
|
||||
std::unique_ptr<u8[]> zlib_buf(new u8[data_buf_length]);
|
||||
memcpy(zlib_buf.get(), data_buf.get(), data_buf_length);
|
||||
|
||||
// Use zlib uncompress on the new buffer.
|
||||
// decomp_buf_length changes inside the call to uncompress, so it must be a pointer to correct type (in writeable mem space).
|
||||
int rv = uncompress(decomp_buf.get(), decomp_buf_length.get(), zlib_buf.get() + data_buf_offset, data_buf_length);
|
||||
|
||||
// Check for errors (TODO: Probably safe to remove this once these changes have passed testing.)
|
||||
switch (rv)
|
||||
{
|
||||
case Z_MEM_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_MEM_ERROR!"); break;
|
||||
case Z_BUF_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_BUF_ERROR!"); break;
|
||||
case Z_DATA_ERROR: LOG_ERROR(LOADER, "MakeELF encountered a Z_DATA_ERROR!"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr32_arr[i].p_offset);
|
||||
e.write(decomp_buf.get(), phdr32_arr[i].p_filesz);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr32_arr[i].p_offset);
|
||||
e.write(data_buf.get() + data_buf_offset, secinfo_arr[i].size);
|
||||
}
|
||||
|
||||
// Advance the data buffer offset by data size.
|
||||
data_buf_offset += meta_shdr[i].data_size;
|
||||
data_buf_offset += secinfo_arr[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1309,7 +1595,14 @@ fs::file SELFDecrypter::MakeElf(bool isElf32)
|
||||
|
||||
for (u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
{
|
||||
WriteShdr(e, shdr32_arr[i]);
|
||||
if (elf32_hdr.e_data == 1)
|
||||
{
|
||||
WriteShdrLE(e, shdr32_arr[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteShdr(e, shdr32_arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1424,8 +1717,20 @@ static bool IsSelfElf32(const fs::file& f)
|
||||
|
||||
SceHeader hdr;
|
||||
SelfHeader sh;
|
||||
hdr.Load(f);
|
||||
sh.Load(f);
|
||||
|
||||
hdr.LoadLE(f);
|
||||
|
||||
if (!isVita(hdr))
|
||||
{
|
||||
f.seek(0);
|
||||
hdr.Load(f);
|
||||
sh.Load(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
sh.LoadLE(f);
|
||||
}
|
||||
|
||||
|
||||
// Locate the class byte and check it.
|
||||
u8 elf_class[0x8];
|
||||
@@ -1451,13 +1756,23 @@ static bool CheckDebugSelf(fs::file& s)
|
||||
// Check for DEBUG version.
|
||||
if (key_version == 0x80 || key_version == 0xc0)
|
||||
{
|
||||
LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header...");
|
||||
|
||||
s.seek(0x04);
|
||||
const u16 version = s.read<le_t<u16>>();
|
||||
|
||||
if (version == 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header...");
|
||||
|
||||
// Get the real elf offset.
|
||||
s.seek(0x10);
|
||||
|
||||
const u64 realoffset = key_version == 0x80 ? +s.read<be_t<u64>>() : +s.read<le_t<u64>>();
|
||||
// Start at the real elf offset.
|
||||
s.seek(key_version == 0x80 ? +s.read<be_t<u64>>() : +s.read<le_t<u64>>());
|
||||
s.seek(realoffset);
|
||||
|
||||
// Write the real ELF file back.
|
||||
fs::file e = fs::make_stream<std::vector<u8>>();
|
||||
@@ -1560,4 +1875,4 @@ std::array<u8, 0x10> get_default_self_klic()
|
||||
std::array<u8, 0x10> key;
|
||||
std::copy(std::begin(NP_KLIC_FREE), std::end(NP_KLIC_FREE), std::begin(key));
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ struct AppInfo
|
||||
u64 padding;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -24,6 +25,7 @@ struct SectionInfo
|
||||
u32 encrypted;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -35,6 +37,7 @@ struct SCEVersionInfo
|
||||
u32 unknown;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -92,9 +95,33 @@ struct ControlInfo
|
||||
u64 unknown3;
|
||||
|
||||
} npdrm;
|
||||
|
||||
// type 5 0x110 bytes
|
||||
struct
|
||||
{
|
||||
u32 pad;
|
||||
u8 unk[0x100];
|
||||
} type5;
|
||||
|
||||
// type 6 0x110 bytes
|
||||
struct
|
||||
{
|
||||
u32 pad;
|
||||
u32 unknown1;
|
||||
u8 unk[0xFC];
|
||||
} type6;
|
||||
|
||||
// type 7 0x50 bytes
|
||||
struct
|
||||
{
|
||||
u32 pad;
|
||||
u8 unk[0x40];
|
||||
} type7;
|
||||
|
||||
};
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -317,6 +344,7 @@ struct SceHeader
|
||||
u64 se_esize;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show(){}
|
||||
bool CheckMagic() const { return se_magic == 0x53434500; }
|
||||
};
|
||||
@@ -335,6 +363,7 @@ struct SelfHeader
|
||||
u64 pad;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show(){}
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -82,6 +82,8 @@ ALSAThread::ALSAThread()
|
||||
if (!check(snd_pcm_sw_params_current(s_tls_handle, s_tls_sw_params), "snd_pcm_sw_params_current"))
|
||||
return;
|
||||
|
||||
period_frames *= g_cfg.audio.startt;
|
||||
|
||||
if (!check(snd_pcm_sw_params_set_start_threshold(s_tls_handle, s_tls_sw_params, period_frames), "snd_pcm_sw_params_set_start_threshold"))
|
||||
return;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void XAudio2Thread::xa27_open()
|
||||
return;
|
||||
}
|
||||
|
||||
s_tls_source_voice->SetVolume(g_cfg.audio.downmix_to_2ch ? 1.0 : 4.0);
|
||||
s_tls_source_voice->SetVolume(g_cfg.audio.downmix_to_2ch ? 1.0f : 4.0f);
|
||||
}
|
||||
|
||||
void XAudio2Thread::xa27_add(const void* src, int size)
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
#ifdef LLVM_AVAILABLE
|
||||
|
||||
#include "CPUTranslator.h"
|
||||
|
||||
cpu_translator::cpu_translator(llvm::LLVMContext& context, llvm::Module* module, bool is_be)
|
||||
: m_context(context)
|
||||
, m_module(module)
|
||||
, m_is_be(is_be)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1 +1,750 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef LLVM_AVAILABLE
|
||||
|
||||
#include "restore_new.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
#include "../Utilities/types.h"
|
||||
#include "../Utilities/StrFmt.h"
|
||||
#include "../Utilities/BEType.h"
|
||||
#include "../Utilities/BitField.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
template <typename T = void>
|
||||
struct llvm_value_t
|
||||
{
|
||||
static_assert(std::is_same<T, void>::value, "llvm_value_t<> error: unknown type");
|
||||
|
||||
using type = void;
|
||||
static constexpr uint esize = 0;
|
||||
static constexpr bool is_int = false;
|
||||
static constexpr bool is_sint = false;
|
||||
static constexpr bool is_uint = false;
|
||||
static constexpr bool is_float = false;
|
||||
static constexpr uint is_vector = false;
|
||||
static constexpr uint is_pointer = false;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getVoidTy(context);
|
||||
}
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
llvm::Value* value;
|
||||
|
||||
// llvm_value_t() = default;
|
||||
|
||||
// llvm_value_t(llvm::Value* value)
|
||||
// : value(value)
|
||||
// {
|
||||
// }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<bool> : llvm_value_t<void>
|
||||
{
|
||||
using type = bool;
|
||||
using base = llvm_value_t<void>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 1;
|
||||
static constexpr uint is_int = true;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getInt1Ty(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<char> : llvm_value_t<void>
|
||||
{
|
||||
using type = char;
|
||||
using base = llvm_value_t<void>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 8;
|
||||
static constexpr bool is_int = true;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getInt8Ty(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<s8> : llvm_value_t<char>
|
||||
{
|
||||
using type = s8;
|
||||
using base = llvm_value_t<char>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_sint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<u8> : llvm_value_t<char>
|
||||
{
|
||||
using type = u8;
|
||||
using base = llvm_value_t<char>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_uint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<s16> : llvm_value_t<s8>
|
||||
{
|
||||
using type = s16;
|
||||
using base = llvm_value_t<s8>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 16;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getInt16Ty(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<u16> : llvm_value_t<s16>
|
||||
{
|
||||
using type = u16;
|
||||
using base = llvm_value_t<s16>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_sint = false;
|
||||
static constexpr bool is_uint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<s32> : llvm_value_t<s8>
|
||||
{
|
||||
using type = s32;
|
||||
using base = llvm_value_t<s8>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 32;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getInt32Ty(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<u32> : llvm_value_t<s32>
|
||||
{
|
||||
using type = u32;
|
||||
using base = llvm_value_t<s32>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_sint = false;
|
||||
static constexpr bool is_uint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<s64> : llvm_value_t<s8>
|
||||
{
|
||||
using type = s64;
|
||||
using base = llvm_value_t<s8>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 64;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getInt64Ty(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<u64> : llvm_value_t<s64>
|
||||
{
|
||||
using type = u64;
|
||||
using base = llvm_value_t<s64>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_sint = false;
|
||||
static constexpr bool is_uint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<s128> : llvm_value_t<s8>
|
||||
{
|
||||
using type = s128;
|
||||
using base = llvm_value_t<s8>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 128;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getIntNTy(context, 128);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<u128> : llvm_value_t<s128>
|
||||
{
|
||||
using type = u128;
|
||||
using base = llvm_value_t<s128>;
|
||||
using base::base;
|
||||
|
||||
static constexpr bool is_sint = false;
|
||||
static constexpr bool is_uint = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<f32> : llvm_value_t<void>
|
||||
{
|
||||
using type = f32;
|
||||
using base = llvm_value_t<void>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 32;
|
||||
static constexpr bool is_float = true;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getFloatTy(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct llvm_value_t<f64> : llvm_value_t<void>
|
||||
{
|
||||
using type = f64;
|
||||
using base = llvm_value_t<void>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint esize = 64;
|
||||
static constexpr bool is_float = true;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::Type::getDoubleTy(context);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct llvm_value_t<T*> : llvm_value_t<T>
|
||||
{
|
||||
static_assert(!std::is_void<T>::value, "llvm_value_t<> error: invalid pointer to void type");
|
||||
|
||||
using type = T*;
|
||||
using base = llvm_value_t<T>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint is_pointer = llvm_value_t<T>::is_pointer + 1;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm_value_t<T>::get_type(context)->getPointerTo();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, uint N>
|
||||
struct llvm_value_t<T[N]> : llvm_value_t<T>
|
||||
{
|
||||
static_assert(!llvm_value_t<T>::is_vector, "llvm_value_t<> error: invalid multidimensional vector");
|
||||
static_assert(!llvm_value_t<T>::is_pointer, "llvm_value_t<>: vector of pointers is not allowed");
|
||||
|
||||
using type = T[N];
|
||||
using base = llvm_value_t<T>;
|
||||
using base::base;
|
||||
|
||||
static constexpr uint is_vector = N;
|
||||
static constexpr uint is_pointer = 0;
|
||||
|
||||
static llvm::Type* get_type(llvm::LLVMContext& context)
|
||||
{
|
||||
return llvm::VectorType::get(llvm_value_t<T>::get_type(context), N);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_add_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint || llvm_value_t<T>::is_float, "llvm_add_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateAdd(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_float)
|
||||
{
|
||||
return ir->CreateFAdd(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_add_t<typename T1::type, T1, T2> operator +(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_sub_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint || llvm_value_t<T>::is_float, "llvm_sub_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateSub(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_float)
|
||||
{
|
||||
return ir->CreateFSub(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_sub_t<typename T1::type, T1, T2> operator -(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_mul_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint || llvm_value_t<T>::is_float, "llvm_mul_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateMul(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_float)
|
||||
{
|
||||
return ir->CreateFMul(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_mul_t<typename T1::type, T1, T2> operator *(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_div_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint || llvm_value_t<T>::is_float, "llvm_div_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_sint)
|
||||
{
|
||||
return ir->CreateSDiv(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_uint)
|
||||
{
|
||||
return ir->CreateUDiv(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_float)
|
||||
{
|
||||
return ir->CreateFDiv(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_div_t<typename T1::type, T1, T2> operator /(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T, typename A1>
|
||||
struct llvm_neg_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint || llvm_value_t<T>::is_float, "llvm_neg_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateNeg(v1);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_float)
|
||||
{
|
||||
return ir->CreateFNeg(v1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::esize>>
|
||||
inline llvm_neg_t<typename T1::type, T1> operator -(T1 a1)
|
||||
{
|
||||
return {a1};
|
||||
}
|
||||
|
||||
// Constant int helper
|
||||
struct llvm_int_t
|
||||
{
|
||||
u64 value;
|
||||
|
||||
u64 eval(llvm::IRBuilder<>*) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_shl_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint, "llvm_shl_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_sint)
|
||||
{
|
||||
return ir->CreateShl(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_uint)
|
||||
{
|
||||
return ir->CreateShl(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_shl_t<typename T1::type, T1, T2> operator <<(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_shl_t<typename T1::type, T1, llvm_int_t> operator <<(T1 a1, u64 a2)
|
||||
{
|
||||
return {a1, llvm_int_t{a2}};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_shr_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_sint || llvm_value_t<T>::is_uint, "llvm_shr_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_sint)
|
||||
{
|
||||
return ir->CreateAShr(v1, v2);
|
||||
}
|
||||
|
||||
if (llvm_value_t<T>::is_uint)
|
||||
{
|
||||
return ir->CreateLShr(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_shr_t<typename T1::type, T1, T2> operator >>(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_shr_t<typename T1::type, T1, llvm_int_t> operator >>(T1 a1, u64 a2)
|
||||
{
|
||||
return {a1, llvm_int_t{a2}};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_and_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_int, "llvm_and_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateAnd(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_and_t<typename T1::type, T1, T2> operator &(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_and_t<typename T1::type, T1, llvm_int_t> operator &(T1 a1, u64 a2)
|
||||
{
|
||||
return {a1, llvm_int_t{a2}};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_or_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_int, "llvm_or_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateOr(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_or_t<typename T1::type, T1, T2> operator |(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_or_t<typename T1::type, T1, llvm_int_t> operator |(T1 a1, u64 a2)
|
||||
{
|
||||
return {a1, llvm_int_t{a2}};
|
||||
}
|
||||
|
||||
template <typename T, typename A1, typename A2>
|
||||
struct llvm_xor_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
A2 a2;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_int, "llvm_xor_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
const auto v2 = a2.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateXor(v1, v2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<std::is_same<typename T1::type, typename T2::type>::value>>
|
||||
inline llvm_xor_t<typename T1::type, T1, T2> operator ^(T1 a1, T2 a2)
|
||||
{
|
||||
return {a1, a2};
|
||||
}
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_xor_t<typename T1::type, T1, llvm_int_t> operator ^(T1 a1, u64 a2)
|
||||
{
|
||||
return {a1, llvm_int_t{a2}};
|
||||
}
|
||||
|
||||
template <typename T, typename A1>
|
||||
struct llvm_not_t
|
||||
{
|
||||
using type = T;
|
||||
|
||||
A1 a1;
|
||||
|
||||
static_assert(llvm_value_t<T>::is_int, "llvm_not_t<>: invalid type");
|
||||
|
||||
llvm::Value* eval(llvm::IRBuilder<>* ir) const
|
||||
{
|
||||
const auto v1 = a1.eval(ir);
|
||||
|
||||
if (llvm_value_t<T>::is_int)
|
||||
{
|
||||
return ir->CreateNot(v1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename = decltype(std::declval<T1>().eval(0)), typename = std::enable_if_t<llvm_value_t<typename T1::type>::is_int>>
|
||||
inline llvm_not_t<typename T1::type, T1> operator ~(T1 a1)
|
||||
{
|
||||
return {a1};
|
||||
}
|
||||
|
||||
class cpu_translator
|
||||
{
|
||||
protected:
|
||||
cpu_translator(llvm::LLVMContext& context, llvm::Module* module, bool is_be);
|
||||
|
||||
// LLVM context
|
||||
llvm::LLVMContext& m_context;
|
||||
|
||||
// Module to which all generated code is output to
|
||||
llvm::Module* const m_module;
|
||||
|
||||
// Endianness, affects vector element numbering (TODO)
|
||||
const bool m_is_be;
|
||||
|
||||
// IR builder
|
||||
llvm::IRBuilder<>* m_ir;
|
||||
|
||||
public:
|
||||
// Convert a C++ type to an LLVM type (TODO: remove)
|
||||
template <typename T>
|
||||
llvm::Type* GetType()
|
||||
{
|
||||
return llvm_value_t<T>::get_type(m_context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::Type* get_type()
|
||||
{
|
||||
return llvm_value_t<T>::get_type(m_context);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using value_t = llvm_value_t<T>;
|
||||
|
||||
template <typename T>
|
||||
auto eval(T expr)
|
||||
{
|
||||
value_t<typename T::type> result;
|
||||
result.value = expr.eval(m_ir);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get unsigned addition carry into the sign bit (s = a + b)
|
||||
template <typename T>
|
||||
static inline auto ucarry(T a, T b, T s)
|
||||
{
|
||||
return ((a ^ b) & ~s) | (a & b);
|
||||
}
|
||||
|
||||
// Get signed addition overflow into the sign bit (s = a + b)
|
||||
template <typename T>
|
||||
static inline auto scarry(T a, T b, T s)
|
||||
{
|
||||
return (b ^ s) & ~(a ^ b);
|
||||
}
|
||||
|
||||
// Get signed subtraction overflow into the sign bit (d = a - b)
|
||||
template <typename T>
|
||||
static inline auto sborrow(T a, T b, T d)
|
||||
{
|
||||
return (a ^ b) & (a ^ d);
|
||||
}
|
||||
|
||||
// Bitwise select (c ? a : b)
|
||||
template <typename T>
|
||||
static inline auto merge(T c, T a, T b)
|
||||
{
|
||||
return (a & c) | (b & ~c);
|
||||
}
|
||||
|
||||
// Average: (a + b + 1) >> 1
|
||||
template <typename T>
|
||||
static inline auto avg(T a, T b)
|
||||
{
|
||||
return (a >> 1) + (b >> 1) + ((a | b) & 1);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
#include "Emu/System.h"
|
||||
#include "MFC.h"
|
||||
|
||||
const bool s_use_rtm = utils::has_rtm();
|
||||
@@ -50,6 +51,13 @@ void fmt_class_string<MFC>::format(std::string& out, u64 arg)
|
||||
case MFC_BARRIER_CMD: return "BARRIER";
|
||||
case MFC_EIEIO_CMD: return "EIEIO";
|
||||
case MFC_SYNC_CMD: return "SYNC";
|
||||
|
||||
case MFC_BARRIER_MASK:
|
||||
case MFC_FENCE_MASK:
|
||||
case MFC_LIST_MASK:
|
||||
case MFC_START_MASK:
|
||||
case MFC_RESULT_MASK:
|
||||
break;
|
||||
}
|
||||
|
||||
return unknown;
|
||||
@@ -135,107 +143,142 @@ void mfc_thread::cpu_task()
|
||||
|
||||
if (queue_size)
|
||||
{
|
||||
auto& cmd = spu.mfc_queue[0];
|
||||
|
||||
if ((cmd.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) == MFC_PUTQLLUC_CMD)
|
||||
u32 fence_mask = 0; // Using this instead of stall_mask to avoid a possible race condition
|
||||
u32 barrier_mask = 0;
|
||||
bool first = true;
|
||||
for (u32 i = 0; i < spu.mfc_queue.size(); i++, first = false)
|
||||
{
|
||||
auto& data = vm::ps3::_ref<decltype(spu.rdata)>(cmd.eal);
|
||||
const auto to_write = spu._ref<decltype(spu.rdata)>(cmd.lsa & 0x3ffff);
|
||||
auto& cmd = spu.mfc_queue[i];
|
||||
|
||||
cmd.size = 0;
|
||||
no_updates = 0;
|
||||
// this check all revolves around a potential 'stalled list' in the queue as its the one thing that can cause out of order mfc list execution currently
|
||||
// a list with barrier hard blocks that tag until it's been dealt with
|
||||
// and a new command that has a fence cant be executed until the stalled list has been dealt with
|
||||
if ((cmd.size != 0) && ((barrier_mask & (1u << cmd.tag)) || ((cmd.cmd & MFC_FENCE_MASK) && ((1 << cmd.tag) & fence_mask))))
|
||||
continue;
|
||||
|
||||
vm::reservation_acquire(cmd.eal, 128);
|
||||
|
||||
// Store unconditionally
|
||||
if (s_use_rtm && utils::transaction_enter())
|
||||
if ((cmd.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) == MFC_PUTQLLUC_CMD)
|
||||
{
|
||||
if (!vm::reader_lock{vm::try_to_lock})
|
||||
{
|
||||
_xabort(0);
|
||||
}
|
||||
auto& data = vm::ps3::_ref<decltype(spu.rdata)>(cmd.eal);
|
||||
const auto to_write = spu._ref<decltype(spu.rdata)>(cmd.lsa & 0x3ffff);
|
||||
|
||||
data = to_write;
|
||||
vm::reservation_update(cmd.eal, 128);
|
||||
vm::notify(cmd.eal, 128);
|
||||
_xend();
|
||||
}
|
||||
else
|
||||
{
|
||||
vm::writer_lock lock(0);
|
||||
data = to_write;
|
||||
vm::reservation_update(cmd.eal, 128);
|
||||
vm::notify(cmd.eal, 128);
|
||||
}
|
||||
}
|
||||
else if (cmd.cmd & MFC_LIST_MASK)
|
||||
{
|
||||
struct list_element
|
||||
{
|
||||
be_t<u16> sb; // Stall-and-Notify bit (0x8000)
|
||||
be_t<u16> ts; // List Transfer Size
|
||||
be_t<u32> ea; // External Address Low
|
||||
};
|
||||
|
||||
if (cmd.size && (spu.ch_stall_mask & (1u << cmd.tag)) == 0)
|
||||
{
|
||||
cmd.lsa &= 0x3fff0;
|
||||
|
||||
const list_element item = spu._ref<list_element>(cmd.eal & 0x3fff8);
|
||||
|
||||
const u32 size = item.ts;
|
||||
const u32 addr = item.ea;
|
||||
|
||||
if (size)
|
||||
{
|
||||
spu_mfc_cmd transfer;
|
||||
transfer.eal = addr;
|
||||
transfer.eah = 0;
|
||||
transfer.lsa = cmd.lsa | (addr & 0xf);
|
||||
transfer.tag = cmd.tag;
|
||||
transfer.cmd = MFC(cmd.cmd & ~MFC_LIST_MASK);
|
||||
transfer.size = size;
|
||||
|
||||
spu.do_dma_transfer(transfer);
|
||||
cmd.lsa += std::max<u32>(size, 16);
|
||||
}
|
||||
|
||||
cmd.eal += 8;
|
||||
cmd.size -= 8;
|
||||
cmd.size = 0;
|
||||
no_updates = 0;
|
||||
|
||||
if (item.sb & 0x8000)
|
||||
vm::reservation_acquire(cmd.eal, 128);
|
||||
|
||||
// Store unconditionally
|
||||
if (s_use_rtm && utils::transaction_enter())
|
||||
{
|
||||
spu.ch_stall_stat.push_or(spu, 1 << cmd.tag);
|
||||
|
||||
const u32 evt = spu.ch_event_stat.fetch_or(SPU_EVENT_SN);
|
||||
|
||||
if (evt & SPU_EVENT_WAITING)
|
||||
if (!vm::reader_lock{ vm::try_to_lock })
|
||||
{
|
||||
spu.notify();
|
||||
}
|
||||
else if (evt & SPU_EVENT_INTR_ENABLED)
|
||||
{
|
||||
spu.state += cpu_flag::suspend;
|
||||
_xabort(0);
|
||||
}
|
||||
|
||||
data = to_write;
|
||||
vm::reservation_update(cmd.eal, 128);
|
||||
vm::notify(cmd.eal, 128);
|
||||
_xend();
|
||||
}
|
||||
else
|
||||
{
|
||||
vm::writer_lock lock(0);
|
||||
data = to_write;
|
||||
vm::reservation_update(cmd.eal, 128);
|
||||
vm::notify(cmd.eal, 128);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (LIKELY(cmd.size))
|
||||
{
|
||||
spu.do_dma_transfer(cmd);
|
||||
cmd.size = 0;
|
||||
}
|
||||
else if (UNLIKELY((cmd.cmd & ~0xc) == MFC_BARRIER_CMD))
|
||||
{
|
||||
// TODO (MFC_BARRIER_CMD, MFC_EIEIO_CMD, MFC_SYNC_CMD)
|
||||
_mm_mfence();
|
||||
}
|
||||
else if (cmd.cmd & MFC_LIST_MASK && LIKELY(cmd.cmd != MFC_SYNC_CMD))
|
||||
{
|
||||
struct list_element
|
||||
{
|
||||
be_t<u16> sb; // Stall-and-Notify bit (0x8000)
|
||||
be_t<u16> ts; // List Transfer Size
|
||||
be_t<u32> ea; // External Address Low
|
||||
};
|
||||
|
||||
if (!cmd.size)
|
||||
{
|
||||
spu.mfc_queue.end_pop();
|
||||
no_updates = 0;
|
||||
if (cmd.size && (spu.ch_stall_mask & (1u << cmd.tag)) == 0)
|
||||
{
|
||||
cmd.lsa &= 0x3fff0;
|
||||
|
||||
// try to get the whole list done in one go
|
||||
while (cmd.size != 0)
|
||||
{
|
||||
const list_element item = spu._ref<list_element>(cmd.eal & 0x3fff8);
|
||||
|
||||
const u32 size = item.ts;
|
||||
const u32 addr = item.ea;
|
||||
|
||||
if (size)
|
||||
{
|
||||
spu_mfc_cmd transfer;
|
||||
transfer.eal = addr;
|
||||
transfer.eah = 0;
|
||||
transfer.lsa = cmd.lsa | (addr & 0xf);
|
||||
transfer.tag = cmd.tag;
|
||||
transfer.cmd = MFC(cmd.cmd & ~MFC_LIST_MASK);
|
||||
transfer.size = size;
|
||||
|
||||
spu.do_dma_transfer(transfer);
|
||||
cmd.lsa += std::max<u32>(size, 16);
|
||||
}
|
||||
|
||||
cmd.eal += 8;
|
||||
cmd.size -= 8;
|
||||
no_updates = 0;
|
||||
|
||||
// dont stall for last 'item' in list
|
||||
if ((item.sb & 0x8000) && (cmd.size != 0))
|
||||
{
|
||||
spu.ch_stall_mask |= (1 << cmd.tag);
|
||||
spu.ch_stall_stat.push_or(spu, 1 << cmd.tag);
|
||||
|
||||
const u32 evt = spu.ch_event_stat.fetch_or(SPU_EVENT_SN);
|
||||
|
||||
if (evt & SPU_EVENT_WAITING)
|
||||
{
|
||||
spu.notify();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd.size != 0 && (cmd.cmd & MFC_BARRIER_MASK))
|
||||
barrier_mask |= (1 << cmd.tag);
|
||||
else if (cmd.size != 0)
|
||||
fence_mask |= (1 << cmd.tag);
|
||||
}
|
||||
else if (UNLIKELY((cmd.cmd & ~0xc) == MFC_BARRIER_CMD))
|
||||
{
|
||||
// Raw barrier commands / sync commands are tag agnostic and hard sync the mfc list
|
||||
// Need to gaurentee everything ahead of it has processed before this
|
||||
if (first)
|
||||
cmd.size = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if (LIKELY(cmd.size))
|
||||
{
|
||||
spu.do_dma_transfer(cmd);
|
||||
cmd.size = 0;
|
||||
}
|
||||
if (!cmd.size && first)
|
||||
{
|
||||
spu.mfc_queue.end_pop();
|
||||
no_updates = 0;
|
||||
break;
|
||||
}
|
||||
else if (!cmd.size && i == 1)
|
||||
{
|
||||
// nasty hack, shoving stalled list down one
|
||||
// this *works* from the idea that the only thing that could have been passed over in position 0 is a stalled list
|
||||
// todo: this can still create a situation where we say the mfc queue is full when its actually not, which will cause a rough deadlock between spu and mfc
|
||||
// which will causes a situation where the spu is waiting for the queue to open up but hasnt signaled the stall yet
|
||||
spu.mfc_queue[1] = spu.mfc_queue[0];
|
||||
spu.mfc_queue.end_pop();
|
||||
no_updates = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,26 +288,21 @@ void mfc_thread::cpu_task()
|
||||
{
|
||||
// Mask incomplete transfers
|
||||
u32 completed = spu.ch_tag_mask;
|
||||
|
||||
for (u32 i = 0; i < spu.mfc_queue.size(); i++)
|
||||
{
|
||||
const auto& _cmd = spu.mfc_queue[i];
|
||||
|
||||
if (_cmd.size)
|
||||
for (u32 i = 0; i < spu.mfc_queue.size(); i++)
|
||||
{
|
||||
if (spu.ch_tag_upd == 1)
|
||||
{
|
||||
const auto& _cmd = spu.mfc_queue[i];
|
||||
if (_cmd.size)
|
||||
completed &= ~(1u << _cmd.tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (completed && spu.ch_tag_upd.exchange(0))
|
||||
if (completed && spu.ch_tag_upd.compare_and_swap_test(1, 0))
|
||||
{
|
||||
spu.ch_tag_stat.push(spu, completed);
|
||||
no_updates = 0;
|
||||
}
|
||||
else if (spu.ch_tag_mask == completed && spu.ch_tag_upd.compare_and_swap_test(2, 0))
|
||||
{
|
||||
spu.ch_tag_stat.push(spu, completed);
|
||||
no_updates = 0;
|
||||
@@ -273,7 +311,6 @@ void mfc_thread::cpu_task()
|
||||
|
||||
test_state();
|
||||
}
|
||||
|
||||
if (no_updates++)
|
||||
{
|
||||
if (no_updates >= 3)
|
||||
@@ -339,3 +376,12 @@ void mfc_thread::add_spu(spu_ptr _spu)
|
||||
|
||||
run();
|
||||
}
|
||||
|
||||
void mfc_thread::on_spawn()
|
||||
{
|
||||
if (g_cfg.core.thread_scheduler_enabled)
|
||||
{
|
||||
// Bind to same set with the SPUs
|
||||
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(thread_class::spu));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +113,6 @@ public:
|
||||
virtual void cpu_task() override;
|
||||
|
||||
virtual void add_spu(spu_ptr _spu);
|
||||
|
||||
virtual void on_spawn() override;
|
||||
};
|
||||
|
||||
@@ -164,6 +164,8 @@ s32 cellCameraInit()
|
||||
camera->attr[CELL_CAMERA_AGCHIGH] = { 64 };
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cellCamera.todo("Trying to init cellCamera with un-researched camera type.");
|
||||
}
|
||||
|
||||
// TODO: Some other default attributes? Need to check the actual behaviour on a real PS3.
|
||||
|
||||
@@ -554,7 +554,7 @@ s32 cellFontExtend(u32 a1, u32 a2, u32 a3)
|
||||
//Something happens
|
||||
}
|
||||
//Something happens?
|
||||
return -1;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellFontRenderCharGlyphImageVertical()
|
||||
|
||||
@@ -115,7 +115,7 @@ s32 cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName, u32 e
|
||||
|
||||
if (dir.size() != 9)
|
||||
{
|
||||
return CELL_HDDGAME_ERROR_PARAM;
|
||||
return (s32)CELL_HDDGAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
vm::var<CellHddGameCBResult> result;
|
||||
@@ -144,7 +144,7 @@ s32 cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName, u32 e
|
||||
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
|
||||
const auto& psf = psf::load_object(fs::file(local_dir +"/PARAM.SFO"));
|
||||
|
||||
// Some following fields may be zero in old FW 1.00 version PARAM.SFO
|
||||
// Some following fields may be zero in old FW 1.00 version PARAM.SFO
|
||||
if (psf.count("PARENTAL_LEVEL") != 0) get->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer();
|
||||
if (psf.count("ATTRIBUTE") != 0) get->getParam.attribute = psf.at("ATTRIBUTE").as_integer();
|
||||
if (psf.count("RESOLUTION") != 0) get->getParam.resolution = psf.at("RESOLUTION").as_integer();
|
||||
@@ -165,7 +165,7 @@ s32 cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName, u32 e
|
||||
|
||||
if (result->result != CELL_HDDGAME_CBRESULT_OK && result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
|
||||
{
|
||||
return CELL_HDDGAME_ERROR_CBRESULT;
|
||||
return (s32)CELL_HDDGAME_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
// TODO ?
|
||||
@@ -186,7 +186,7 @@ s32 cellHddGameGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
if (!fs::is_dir(local_dir))
|
||||
{
|
||||
return CELL_HDDGAME_ERROR_FAILURE;
|
||||
return (s32)CELL_HDDGAME_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*size = ::narrow<u32>(fs::get_dir_size(local_dir) / 1024);
|
||||
@@ -196,7 +196,8 @@ s32 cellHddGameGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
s32 cellHddGameSetSystemVer()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(cellGame);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellHddGameExitBroken()
|
||||
@@ -223,7 +224,8 @@ s32 cellGameDataGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
s32 cellGameDataSetSystemVer()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(cellGame);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellGameDataExitBroken()
|
||||
@@ -246,51 +248,43 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
// According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist.
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO")));
|
||||
if (!type)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const std::string& category = psf::get_string(sfo, "CATEGORY");
|
||||
|
||||
if (category == "DG")
|
||||
if (Emu.GetCat() == "DG")
|
||||
{
|
||||
*type = CELL_GAME_GAMETYPE_DISC;
|
||||
*attributes = 0; // TODO
|
||||
// TODO: dirName might be a read only string when BootCheck is called on a disc game. (e.g. Ben 10 Ultimate Alien: Cosmic Destruction)
|
||||
|
||||
if (!fxm::make<content_permission>("", std::move(sfo)))
|
||||
if (!fxm::make<content_permission>("", psf::load_object(fs::file(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")))))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else if (category == "AP" || category == "AV" || category == "HG" || category == "AT" || category == "AM" || category == "SF")
|
||||
{
|
||||
*type = CELL_GAME_GAMETYPE_HDD;
|
||||
*attributes = 0; // TODO
|
||||
if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID());
|
||||
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), std::move(sfo)))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else if (category == "GD")
|
||||
else if (Emu.GetCat() == "GD")
|
||||
{
|
||||
*type = CELL_GAME_GAMETYPE_DISC;
|
||||
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
||||
if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); // ???
|
||||
|
||||
if (!fxm::make<content_permission>("", std::move(sfo)))
|
||||
if (!fxm::make<content_permission>("", psf::load_object(fs::file(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")))))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hack: When there is no (or unknown) CATEGORY returned, instead of throwing an exception
|
||||
// we assume it's a disk game.
|
||||
*type = CELL_GAME_GAMETYPE_DISC;
|
||||
*attributes = 0;
|
||||
cellGame.error("cellGameBootCheck(): Unknown CATEGORY: %s", category);
|
||||
*type = CELL_GAME_GAMETYPE_HDD;
|
||||
*attributes = 0; // TODO
|
||||
if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID());
|
||||
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), psf::load_object(fs::file(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")))))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@@ -310,18 +304,16 @@ error_code cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> r
|
||||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO")));
|
||||
|
||||
if (psf::get_string(sfo, "CATEGORY") != "GD")
|
||||
if (Emu.GetCat() != "GD")
|
||||
{
|
||||
return CELL_GAME_ERROR_NOTPATCH;
|
||||
}
|
||||
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), std::move(sfo)))
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), psf::load_object(fs::file(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")))))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -329,9 +321,9 @@ error_code cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameC
|
||||
{
|
||||
cellGame.warning("cellGameDataCheck(type=%d, dirName=%s, size=*0x%x)", type, dirName, size);
|
||||
|
||||
if ((type - 1) >= 3)
|
||||
if ((type - 1) >= 3 || (type != CELL_GAME_GAMETYPE_DISC && !dirName))
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
return {CELL_GAME_ERROR_PARAM, type};
|
||||
}
|
||||
|
||||
if (size)
|
||||
@@ -375,7 +367,7 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
|
||||
}
|
||||
|
||||
const auto prm = fxm::get<content_permission>();
|
||||
|
||||
|
||||
if (!prm)
|
||||
{
|
||||
return CELL_GAME_ERROR_FAILURE;
|
||||
@@ -412,7 +404,7 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
|
||||
strcpy_trunc(*contentInfoPath, dir);
|
||||
strcpy_trunc(*usrdirPath, dir + "/USRDIR");
|
||||
verify(HERE), fxm::remove<content_permission>();
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -420,7 +412,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||
{
|
||||
cellGame.error("cellGameDataCheckCreate2(version=0x%x, dirName=%s, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
||||
|
||||
//older sdk. it might not care about game type.
|
||||
//older sdk. it might not care about game type.
|
||||
|
||||
if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1)
|
||||
{
|
||||
@@ -429,7 +421,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||
|
||||
// TODO: output errors (errDialog)
|
||||
|
||||
const std::string& dir = "/dev_hdd0/game/"s + dirName.get_ptr();
|
||||
const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr();
|
||||
|
||||
vm::var<CellGameDataCBResult> cbResult;
|
||||
vm::var<CellGameDataStatGet> cbGet;
|
||||
@@ -439,7 +431,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
|
||||
cbGet->hddFreeSizeKB = 40000000; //40 GB
|
||||
|
||||
|
||||
|
||||
strcpy_trunc(cbGet->contentInfoPath, dir);
|
||||
strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR");
|
||||
|
||||
@@ -452,7 +444,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||
cbGet->sizeKB = CELL_GAMEDATA_SIZEKB_NOTCALC;
|
||||
cbGet->sysSizeKB = 0;
|
||||
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO")));
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get(Emu.GetCat() == "DG" ? "/dev_bdvd/PS3_GAME/PARAM.SFO"s : "/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")));
|
||||
|
||||
cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL;
|
||||
cbGet->getParam.parentalLevel = psf::get_integer(sfo, "PARENTAL_LEVEL", 0);
|
||||
@@ -464,52 +456,58 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||
strcpy_trunc(cbGet->getParam.titleLang[i], psf::get_string(sfo, fmt::format("TITLE_%02d", i)));
|
||||
}
|
||||
|
||||
|
||||
funcStat(ppu, cbResult, cbGet, cbSet);
|
||||
|
||||
|
||||
switch ((s32)cbResult->result)
|
||||
{
|
||||
case CELL_GAMEDATA_CBRESULT_OK_CANCEL:
|
||||
{
|
||||
// TODO: do not process game data(directory)
|
||||
cellGame.warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
case CELL_GAMEDATA_CBRESULT_OK:
|
||||
{
|
||||
// Game confirmed that it wants to create directory
|
||||
const std::string usrdir = dir + "/USRDIR";
|
||||
const std::string vusrdir = vfs::get(usrdir);
|
||||
|
||||
if (!fs::is_dir(vusrdir) && !fs::create_path(vusrdir))
|
||||
{
|
||||
return {CELL_GAME_ERROR_ACCESS_ERROR, usrdir};
|
||||
}
|
||||
|
||||
|
||||
case CELL_GAMEDATA_CBRESULT_OK:
|
||||
//game confirmed that it wants to create directory
|
||||
if (!fs::is_dir(vfs::get(dir + "/USRDIR")) && !fs::create_path(vfs::get(dir + "/USRDIR")))
|
||||
{
|
||||
cellGame.error("cellGameDataCheckCreate2(): folder creation failed");
|
||||
return CELL_GAME_ERROR_NOSPACE; //don't know which error. picked one at random
|
||||
}
|
||||
if (cbSet->setParam)
|
||||
{
|
||||
const auto vdir = vfs::get(dir);
|
||||
psf::assign(sfo, "CATEGORY", psf::string(3, "GD"));
|
||||
psf::assign(sfo, "TITLE_ID", psf::string(CELL_GAME_SYSP_TITLEID_SIZE, cbSet->setParam->titleId));
|
||||
psf::assign(sfo, "TITLE", psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->title));
|
||||
psf::assign(sfo, "VERSION", psf::string(CELL_GAME_SYSP_VERSION_SIZE, cbSet->setParam->dataVersion));
|
||||
psf::assign(sfo, "PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value());
|
||||
|
||||
//older SDK does not define not settable values, hopefully it doesn't just change some values(overwrite)
|
||||
psf::registry sfo_write =
|
||||
{
|
||||
{ "TITLE_ID", psf::string(CELL_GAME_SYSP_TITLEID_SIZE, cbSet->setParam->titleId) },
|
||||
{ "TITLE", psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->title) },
|
||||
{ "VERSION", psf::string(CELL_GAME_SYSP_VERSION_SIZE, cbSet->setParam->dataVersion) },
|
||||
{ "PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value() }
|
||||
};
|
||||
//sfo_write.emplace("PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value()); // I don't care about age restrictions.
|
||||
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
|
||||
{
|
||||
sfo_write.emplace(fmt::format("TITLE_%02d", i), psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->titleLang[i]));
|
||||
if (!cbSet->setParam->titleLang[i][0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
psf::assign(sfo, fmt::format("TITLE_%02d", i), psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->titleLang[i]));
|
||||
}
|
||||
|
||||
const auto vdir = vfs::get(dir);
|
||||
|
||||
if (!fs::is_dir(vdir))
|
||||
{
|
||||
cellGame.fatal("directory where param.sfo is to be created does not exist");
|
||||
return CELL_GAME_ERROR_INTERNAL;
|
||||
return {CELL_GAME_ERROR_INTERNAL, dir};
|
||||
}
|
||||
psf::save_object(fs::file(vdir + "/PARAM.SFO", fs::rewrite), sfo_write);
|
||||
|
||||
psf::save_object(fs::file(vdir + "/PARAM.SFO", fs::rewrite), sfo);
|
||||
}
|
||||
return CELL_OK;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result
|
||||
cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE");
|
||||
return CELL_GAMEDATA_ERROR_CBRESULT;
|
||||
@@ -719,7 +717,7 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
|
||||
case CELL_GAME_PARAMID_APP_VER: max_size = CELL_GAME_SYSP_APP_VER_SIZE; break;
|
||||
}
|
||||
|
||||
prm->sfo.emplace(key, psf::string(max_size, buf.get_ptr()));
|
||||
psf::assign(prm->sfo, key, psf::string(max_size, buf.get_ptr()));
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode)
|
||||
((led&(CELL_KB_LED_CAPS_LOCK)) ? 0 : 0x20) :
|
||||
((led&(CELL_KB_LED_CAPS_LOCK)) ? 0x20 : 0);
|
||||
return rawcode + 0x5D;
|
||||
}
|
||||
}
|
||||
if (rawcode >= 0x1E && rawcode <= 0x26) return rawcode + 0x13; // '1' - '9'
|
||||
if (rawcode == 0x27) return 0x30; // '0'
|
||||
if (rawcode == 0x28) return 0x0A; // '\n'
|
||||
@@ -136,7 +136,7 @@ error_code cellKbGetInfo(vm::ptr<CellKbInfo> info)
|
||||
{
|
||||
info->status[i] = current_info.status[i];
|
||||
}
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
|
||||
}
|
||||
|
||||
current_data.len = 0;
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ error_code cellKbSetCodeType(u32 port_no, u32 type)
|
||||
|
||||
if (port_no >= handler->GetKeyboards().size())
|
||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||
|
||||
|
||||
KbConfig& current_config = handler->GetConfig(port_no);
|
||||
current_config.code_type = type;
|
||||
return CELL_OK;
|
||||
@@ -203,7 +203,7 @@ error_code cellKbSetReadMode(u32 port_no, u32 rmode)
|
||||
|
||||
if (port_no >= handler->GetKeyboards().size())
|
||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||
|
||||
|
||||
KbConfig& current_config = handler->GetConfig(port_no);
|
||||
current_config.read_mode = rmode;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
#include "cellMsgDialog.h"
|
||||
@@ -60,13 +61,6 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
|
||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
|
||||
if (_type.se_mute_on)
|
||||
{
|
||||
// TODO
|
||||
@@ -81,6 +75,33 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
|
||||
cellSysutil.error(msgString.get_ptr());
|
||||
}
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (auto dlg = rsxthr->shell_open_message_dialog())
|
||||
{
|
||||
dlg->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
callback(ppu, status, userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
|
||||
|
||||
if (!dlg)
|
||||
{
|
||||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
|
||||
dlg->type = _type;
|
||||
|
||||
dlg->on_close = [callback, userData, wptr = std::weak_ptr<MsgDialogBase>(dlg)](s32 status)
|
||||
@@ -213,6 +234,33 @@ s32 cellMsgDialogClose(f32 delay)
|
||||
{
|
||||
cellSysutil.warning("cellMsgDialogClose(delay=%f)", delay);
|
||||
|
||||
extern u64 get_system_time();
|
||||
const u64 wait_until = get_system_time() + static_cast<s64>(std::max<float>(delay, 0.0f) * 1000);
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (auto dlg = rsxthr->shell_get_current_dialog())
|
||||
{
|
||||
thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]
|
||||
{
|
||||
while (get_system_time() < wait_until)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
return;
|
||||
|
||||
if (rsxthr->shell_get_current_dialog() != dlg)
|
||||
return;
|
||||
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
dlg->close();
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
@@ -220,10 +268,6 @@ s32 cellMsgDialogClose(f32 delay)
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
const u64 wait_until = get_system_time() + static_cast<s64>(std::max<float>(delay, 0.0f) * 1000);
|
||||
|
||||
thread_ctrl::spawn("cellMsgDialogClose() Thread", [=]()
|
||||
{
|
||||
while (dlg->state == MsgDialogState::Open && get_system_time() < wait_until)
|
||||
@@ -243,6 +287,14 @@ s32 cellMsgDialogAbort()
|
||||
{
|
||||
cellSysutil.warning("cellMsgDialogAbort()");
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (rsxthr->shell_close_dialog())
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
@@ -263,6 +315,20 @@ s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::cptr<char> msgStrin
|
||||
{
|
||||
cellSysutil.warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString=%s)", progressBarIndex, msgString);
|
||||
|
||||
if (!msgString)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (auto dlg2 = rsxthr->shell_get_current_dialog())
|
||||
{
|
||||
if (auto casted = dynamic_cast<rsx::overlays::message_dialog*>(dlg2))
|
||||
return casted->progress_bar_set_message(progressBarIndex, msgString.get_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
@@ -270,7 +336,7 @@ s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::cptr<char> msgStrin
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (progressBarIndex >= dlg->type.progress_bar_count || !msgString)
|
||||
if (progressBarIndex >= dlg->type.progress_bar_count)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
@@ -287,6 +353,15 @@ s32 cellMsgDialogProgressBarReset(u32 progressBarIndex)
|
||||
{
|
||||
cellSysutil.warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex);
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (auto dlg2 = rsxthr->shell_get_current_dialog())
|
||||
{
|
||||
if (auto casted = dynamic_cast<rsx::overlays::message_dialog*>(dlg2))
|
||||
return casted->progress_bar_reset(progressBarIndex);
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
@@ -311,6 +386,15 @@ s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
|
||||
{
|
||||
cellSysutil.warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta);
|
||||
|
||||
if (auto rsxthr = fxm::get<GSRender>())
|
||||
{
|
||||
if (auto dlg2 = rsxthr->shell_get_current_dialog())
|
||||
{
|
||||
if (auto casted = dynamic_cast<rsx::overlays::message_dialog*>(dlg2))
|
||||
return casted->progress_bar_increment(progressBarIndex, (f32)delta);
|
||||
}
|
||||
}
|
||||
|
||||
const auto dlg = fxm::get<MsgDialogBase>();
|
||||
|
||||
if (!dlg)
|
||||
|
||||
@@ -84,6 +84,7 @@ public:
|
||||
virtual ~MsgDialogBase();
|
||||
virtual void Create(const std::string& msg) = 0;
|
||||
virtual void CreateOsk(const std::string& msg, char16_t* osk_text, u32 charlimit) = 0;
|
||||
virtual void SetMsg(const std::string& msg) = 0;
|
||||
virtual void ProgressBarSetMsg(u32 progressBarIndex, const std::string& msg) = 0;
|
||||
virtual void ProgressBarReset(u32 progressBarIndex) = 0;
|
||||
virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0;
|
||||
|
||||
@@ -202,7 +202,7 @@ error_code cellNetCtlGetNatInfo(vm::ptr<CellNetCtlNatInfo> natInfo)
|
||||
cellNetCtl.error("cellNetCtlGetNatInfo : CELL_NET_CTL_ERROR_INVALID_SIZE");
|
||||
return CELL_NET_CTL_ERROR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -266,21 +266,37 @@ error_code cellGameUpdateTerm()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartAsync(vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartAsync(ppu_thread& ppu, vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartAsync(param=*0x%x, cb_func=*0x%x, userdata=*0x%x)", param, cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, CELL_OK, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckFinishAsync(vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckFinishAsync(ppu_thread& ppu, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckFinishAsync(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
const u32 PROCESSING_COMPLETE = 5;
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, PROCESSING_COMPLETE, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsync(vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsync(ppu_thread& ppu, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartWithoutDialogAsync(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, CELL_OK, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -290,21 +306,37 @@ error_code cellGameUpdateCheckAbort()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartAsyncEx(vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartAsyncEx(ppu_thread& ppu, vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartAsyncEx(param=*0x%x, cb_func=*0x%x, userdata=*0x%x)", param, cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ CELL_OK, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckFinishAsyncEx(vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckFinishAsyncEx(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckFinishAsyncEx(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
const s32 PROCESSING_COMPLETE = 5;
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ PROCESSING_COMPLETE, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsyncEx(vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsyncEx(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
{
|
||||
cellNetCtl.todo("cellGameUpdateCheckStartWithoutDialogAsyncEx(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata);
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb_func(ppu, vm::make_var(CellGameUpdateResult{ CELL_OK, CELL_OK, 0x0, 0x0}), userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,15 @@ s32 cellPadClearBuf(u32 port_no)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
//Set 'm_buffer_cleared' to force a resend of everything
|
||||
//might as well also reset everything in our pad 'buffer' to nothing as well
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
auto pad = pads[port_no];
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
pad->m_buffer_cleared = true;
|
||||
pad->m_analog_left_x = pad->m_analog_left_y = pad->m_analog_right_x = pad->m_analog_right_y = 128;
|
||||
@@ -65,7 +66,7 @@ s32 cellPadClearBuf(u32 port_no)
|
||||
//~399 on sensor y is a level non moving controller
|
||||
pad->m_sensor_y = 399;
|
||||
pad->m_sensor_x = pad->m_sensor_z = pad->m_sensor_g = 512;
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -78,18 +79,17 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
if (!handler)
|
||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
const PadInfo& rinfo = handler->GetInfo();
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
//We have a choice here of NO_DEVICE or READ_FAILED...lets try no device for now
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
auto pad = pads[port_no];
|
||||
//We have a choice here of NO_DEVICE or READ_FAILED...lets try no device for now
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
u16 d1Initial, d2Initial;
|
||||
d1Initial = pad->m_digital_1;
|
||||
@@ -107,21 +107,21 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
|
||||
switch (button.m_outKeyCode)
|
||||
{
|
||||
case CELL_PAD_CTRL_LEFT:
|
||||
case CELL_PAD_CTRL_LEFT:
|
||||
if (pad->m_press_left != button.m_value) btnChanged = true;
|
||||
pad->m_press_left = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_DOWN:
|
||||
case CELL_PAD_CTRL_DOWN:
|
||||
if (pad->m_press_down != button.m_value) btnChanged = true;
|
||||
pad->m_press_down = button.m_value;
|
||||
pad->m_press_down = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_RIGHT:
|
||||
case CELL_PAD_CTRL_RIGHT:
|
||||
if (pad->m_press_right != button.m_value) btnChanged = true;
|
||||
pad->m_press_right = button.m_value;
|
||||
pad->m_press_right = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_UP:
|
||||
case CELL_PAD_CTRL_UP:
|
||||
if (pad->m_press_up != button.m_value) btnChanged = true;
|
||||
pad->m_press_up = button.m_value;
|
||||
pad->m_press_up = button.m_value;
|
||||
break;
|
||||
//These arent pressure btns
|
||||
case CELL_PAD_CTRL_R3:
|
||||
@@ -144,9 +144,9 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
break;
|
||||
case CELL_PAD_CTRL_CROSS:
|
||||
if (pad->m_press_cross != button.m_value) btnChanged = true;
|
||||
pad->m_press_cross = button.m_value;
|
||||
pad->m_press_cross = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_CIRCLE:
|
||||
case CELL_PAD_CTRL_CIRCLE:
|
||||
if (pad->m_press_circle != button.m_value) btnChanged = true;
|
||||
pad->m_press_circle = button.m_value;
|
||||
break;
|
||||
@@ -154,21 +154,21 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
if (pad->m_press_triangle != button.m_value) btnChanged = true;
|
||||
pad->m_press_triangle = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_R1:
|
||||
case CELL_PAD_CTRL_R1:
|
||||
if (pad->m_press_R1 != button.m_value) btnChanged = true;
|
||||
pad->m_press_R1 = button.m_value;
|
||||
pad->m_press_R1 = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_L1:
|
||||
case CELL_PAD_CTRL_L1:
|
||||
if (pad->m_press_L1 != button.m_value) btnChanged = true;
|
||||
pad->m_press_L1 = button.m_value;
|
||||
pad->m_press_L1 = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_R2:
|
||||
case CELL_PAD_CTRL_R2:
|
||||
if (pad->m_press_R2 != button.m_value) btnChanged = true;
|
||||
pad->m_press_R2 = button.m_value;
|
||||
pad->m_press_R2 = button.m_value;
|
||||
break;
|
||||
case CELL_PAD_CTRL_L2:
|
||||
case CELL_PAD_CTRL_L2:
|
||||
if (pad->m_press_L2 != button.m_value) btnChanged = true;
|
||||
pad->m_press_L2 = button.m_value;
|
||||
pad->m_press_L2 = button.m_value;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -186,21 +186,21 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
{
|
||||
switch (stick.m_offset)
|
||||
{
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
|
||||
if (pad->m_analog_left_x != stick.m_value) btnChanged = true;
|
||||
pad->m_analog_left_x = stick.m_value;
|
||||
pad->m_analog_left_x = stick.m_value;
|
||||
break;
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
|
||||
if (pad->m_analog_left_y != stick.m_value) btnChanged = true;
|
||||
pad->m_analog_left_y = stick.m_value;
|
||||
pad->m_analog_left_y = stick.m_value;
|
||||
break;
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
|
||||
if (pad->m_analog_right_x != stick.m_value) btnChanged = true;
|
||||
pad->m_analog_right_x = stick.m_value;
|
||||
pad->m_analog_right_x = stick.m_value;
|
||||
break;
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
|
||||
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
|
||||
if (pad->m_analog_right_y != stick.m_value) btnChanged = true;
|
||||
pad->m_analog_right_y = stick.m_value;
|
||||
pad->m_analog_right_y = stick.m_value;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -235,7 +235,6 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
btnChanged = true;
|
||||
}
|
||||
|
||||
|
||||
// the real hardware only fills the buffer up to "len" elements (16 bit each)
|
||||
if (pad->m_port_setting & CELL_PAD_SETTING_SENSOR_ON)
|
||||
{
|
||||
@@ -266,7 +265,7 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
|
||||
}
|
||||
|
||||
pad->m_buffer_cleared = false;
|
||||
|
||||
|
||||
// only update parts of the output struct depending on the controller setting
|
||||
if (data->len > CELL_PAD_LEN_NO_CHANGE)
|
||||
{
|
||||
@@ -328,7 +327,7 @@ s32 cellPadPeriphGetInfo(vm::ptr<CellPadPeriphInfo> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
// TODO: Support other types of controllers
|
||||
for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; ++i)
|
||||
@@ -337,6 +336,7 @@ s32 cellPadPeriphGetInfo(vm::ptr<CellPadPeriphInfo> info)
|
||||
break;
|
||||
|
||||
info->port_status[i] = pads[i]->m_port_status;
|
||||
pads[i]->m_port_status &= ~CELL_PAD_STATUS_ASSIGN_CHANGES;
|
||||
info->port_setting[i] = pads[i]->m_port_setting;
|
||||
info->device_capability[i] = pads[i]->m_device_capability;
|
||||
info->device_type[i] = pads[i]->m_device_type;
|
||||
@@ -359,7 +359,11 @@ s32 cellPadPeriphGetData(u32 port_no, vm::ptr<CellPadPeriphData> data)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
// todo: support for 'unique' controllers, which goes in offsets 24+ in padData
|
||||
@@ -386,7 +390,11 @@ s32 cellPadGetDataExtra(u32 port_no, vm::ptr<u32> device_type, vm::ptr<CellPadDa
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
// TODO: This is used just to get data from a BD/CEC remote,
|
||||
@@ -414,7 +422,11 @@ s32 cellPadSetActDirect(u32 port_no, vm::ptr<CellPadActParam> param)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
handler->SetRumble(port_no, param->motor[1], param->motor[0] > 0);
|
||||
@@ -438,7 +450,7 @@ s32 cellPadGetInfo(vm::ptr<CellPadInfo> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
for (u32 i=0; i<CELL_MAX_PADS; ++i)
|
||||
{
|
||||
@@ -470,7 +482,7 @@ s32 cellPadGetInfo2(vm::ptr<CellPadInfo2> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
for (u32 i=0; i<CELL_PAD_MAX_PORT_NUM; ++i)
|
||||
{
|
||||
@@ -500,13 +512,15 @@ s32 cellPadGetCapabilityInfo(u32 port_no, vm::ptr<CellCapabilityInfo> info)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
//Should return the same as device capability mask, psl1ght has it backwards in pad->h
|
||||
info->info[0] = pads[port_no]->m_device_capability;
|
||||
info->info[0] = pad->m_device_capability;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -524,11 +538,14 @@ s32 cellPadSetPortSetting(u32 port_no, u32 port_setting)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
pads[port_no]->m_port_setting = port_setting;
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
pad->m_port_setting = port_setting;
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -546,12 +563,14 @@ s32 cellPadInfoPressMode(u32 port_no)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
return (pads[port_no]->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) > 0;
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return (pad->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) > 0;
|
||||
}
|
||||
|
||||
s32 cellPadInfoSensorMode(u32 port_no)
|
||||
@@ -567,12 +586,14 @@ s32 cellPadInfoSensorMode(u32 port_no)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
return (pads[port_no]->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) > 0;
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return (pad->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) > 0;
|
||||
}
|
||||
|
||||
s32 cellPadSetPressMode(u32 port_no, u32 mode)
|
||||
@@ -591,15 +612,17 @@ s32 cellPadSetPressMode(u32 port_no, u32 mode)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (mode)
|
||||
pads[port_no]->m_port_setting |= CELL_PAD_SETTING_PRESS_ON;
|
||||
pad->m_port_setting |= CELL_PAD_SETTING_PRESS_ON;
|
||||
else
|
||||
pads[port_no]->m_port_setting &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||
pad->m_port_setting &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -620,15 +643,17 @@ s32 cellPadSetSensorMode(u32 port_no, u32 mode)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (mode)
|
||||
pads[port_no]->m_port_setting |= CELL_PAD_SETTING_SENSOR_ON;
|
||||
pad->m_port_setting |= CELL_PAD_SETTING_SENSOR_ON;
|
||||
else
|
||||
pads[port_no]->m_port_setting &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||
pad->m_port_setting &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -661,12 +686,16 @@ s32 cellPadLddGetPortNo(s32 handle)
|
||||
{
|
||||
sys_io.todo("cellPadLddGetPortNo(handle=%d)", handle);
|
||||
|
||||
if (handle < 0)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto handler = fxm::get<pad_thread>();
|
||||
|
||||
if (!handler)
|
||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||
|
||||
return CELL_OK;
|
||||
// CELL_OK would return port 0 (Nascar [BLUS30932] stopped looking for custom controllers after a few seconds, fixing normal input)
|
||||
return CELL_PAD_ERROR_EBUSY;
|
||||
}
|
||||
|
||||
s32 cellPadLddUnregisterController(s32 handle)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
@@ -20,6 +21,16 @@ enum
|
||||
CELL_PHOTO_EXPORT_UTIL_ERROR_INITIALIZE = 0x8002c20a,
|
||||
};
|
||||
|
||||
struct CellPhotoExportSetParam
|
||||
{
|
||||
vm::bptr<char> photo_title;
|
||||
vm::bptr<char> game_title;
|
||||
vm::bptr<char> game_comment;
|
||||
vm::bptr<void> reserved;
|
||||
};
|
||||
|
||||
using CellPhotoExportUtilFinishCallback = void(s32 result, vm::ptr<void> userdata);
|
||||
|
||||
s32 cellPhotoInitialize()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
@@ -38,39 +49,81 @@ s32 cellPhotoRegistFromFile()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportInitialize()
|
||||
error_code cellPhotoExportInitialize(u32 version, u32 container, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportInitialize(version=0x%x, container=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, container, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportInitialize2()
|
||||
error_code cellPhotoExportInitialize2(u32 version, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportInitialize2(version=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportFinalize()
|
||||
error_code cellPhotoExportFinalize(vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportFinalize(funcFinish=*0x%x, userdata=*0x%x)", funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportFromFile()
|
||||
error_code cellPhotoExportFromFile(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellPhotoExportSetParam> param, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportFromFile(srcHddDir=%s, srcHddFile=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", srcHddDir, srcHddFile, param, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportFromFileWithCopy()
|
||||
error_code cellPhotoExportFromFileWithCopy(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellPhotoExportSetParam> param, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportFromFileWithCopy(srcHddDir=%s, srcHddFile=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", srcHddDir, srcHddFile, param, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPhotoExportProgress()
|
||||
error_code cellPhotoExportProgress(vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
cellPhotoExport.todo("cellPhotoExportProgress(funcFinish=*0x%x, userdata=*0x%x)", funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, 0xFFFF, userdata); // 0-0xFFFF where 0xFFFF = 100%
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel cellRec("cellRec");
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_REC_STATUS_UNLOAD = 0,
|
||||
CELL_REC_STATUS_OPEN = 1,
|
||||
CELL_REC_STATUS_START = 2,
|
||||
CELL_REC_STATUS_STOP = 3,
|
||||
CELL_REC_STATUS_CLOSE = 4,
|
||||
CELL_REC_STATUS_ERR = 10
|
||||
};
|
||||
|
||||
struct CellRecSpursParam
|
||||
{
|
||||
vm::bptr<struct CellSpurs> pSpurs;
|
||||
@@ -46,15 +58,40 @@ struct CellRecParam
|
||||
|
||||
using CellRecCallback = void(s32 recStatus, s32 recError, vm::ptr<void> userdata);
|
||||
|
||||
s32 cellRecOpen(vm::cptr<char> pDirName, vm::cptr<char> pFileName, vm::cptr<CellRecParam> pParam, u32 container, vm::ptr<CellRecCallback> cb, vm::ptr<void> cbUserData)
|
||||
struct rec_t
|
||||
{
|
||||
vm::ptr<CellRecCallback> cb;
|
||||
vm::ptr<void> cbUserData;
|
||||
};
|
||||
|
||||
error_code cellRecOpen(vm::cptr<char> pDirName, vm::cptr<char> pFileName, vm::cptr<CellRecParam> pParam, u32 container, vm::ptr<CellRecCallback> cb, vm::ptr<void> cbUserData)
|
||||
{
|
||||
cellRec.todo("cellRecOpen(pDirName=%s, pFileName=%s, pParam=*0x%x, container=0x%x, cb=*0x%x, cbUserData=*0x%x)", pDirName, pFileName, pParam, container, cb, cbUserData);
|
||||
|
||||
const auto rec = fxm::make_always<rec_t>();
|
||||
rec->cb = cb;
|
||||
rec->cbUserData = cbUserData;
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
cb(ppu, CELL_REC_STATUS_OPEN, CELL_OK, cbUserData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellRecClose(s32 isDiscard)
|
||||
error_code cellRecClose(s32 isDiscard)
|
||||
{
|
||||
cellRec.todo("cellRecClose(isDiscard=0x%x)", isDiscard);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto rec = fxm::get_always<rec_t>();
|
||||
rec->cb(ppu, CELL_REC_STATUS_CLOSE, CELL_OK, rec->cbUserData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -63,15 +100,31 @@ void cellRecGetInfo(s32 info, vm::ptr<u64> pValue)
|
||||
cellRec.todo("cellRecGetInfo(info=0x%x, pValue=*0x%x)", info, pValue);
|
||||
}
|
||||
|
||||
s32 cellRecStop()
|
||||
error_code cellRecStop()
|
||||
{
|
||||
cellRec.todo("cellRecStop()");
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto rec = fxm::get_always<rec_t>();
|
||||
rec->cb(ppu, CELL_REC_STATUS_STOP, CELL_OK, rec->cbUserData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellRecStart()
|
||||
error_code cellRecStart()
|
||||
{
|
||||
cellRec.todo("cellRecStart()");
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto rec = fxm::get_always<rec_t>();
|
||||
rec->cb(ppu, CELL_REC_STATUS_START, CELL_OK, rec->cbUserData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -81,7 +134,7 @@ u32 cellRecQueryMemSize(vm::cptr<CellRecParam> pParam)
|
||||
return 1 * 1024 * 1024; // dummy memory size
|
||||
}
|
||||
|
||||
s32 cellRecSetInfo(s32 setInfo, u64 value)
|
||||
error_code cellRecSetInfo(s32 setInfo, u64 value)
|
||||
{
|
||||
cellRec.todo("cellRecSetInfo(setInfo=0x%x, value=0x%x)", setInfo, value);
|
||||
return CELL_OK;
|
||||
|
||||
@@ -152,7 +152,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
if (fs::is_file(base_dir + entry.name + "/ICON0.PNG"))
|
||||
{
|
||||
fs::file icon = fs::file(base_dir + entry.name + "/ICON0.PNG");
|
||||
u32 iconSize = icon.size();
|
||||
u64 iconSize = icon.size();
|
||||
std::vector<uchar> iconData;
|
||||
icon.read(iconData, iconSize);
|
||||
save_entry2.iconBuf = iconData;
|
||||
@@ -355,18 +355,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
while (funcList)
|
||||
{
|
||||
// Display Save Data List asynchronously in the GUI thread.
|
||||
atomic_t<bool> dlg_result(false);
|
||||
|
||||
Emu.CallAfter([&]()
|
||||
{
|
||||
selected = Emu.GetCallbacks().get_save_dialog()->ShowSaveDataList(save_entries, focused, operation, listSet);
|
||||
dlg_result = true;
|
||||
});
|
||||
|
||||
while (!dlg_result)
|
||||
{
|
||||
thread_ctrl::wait_for(1000);
|
||||
}
|
||||
selected = Emu.GetCallbacks().get_save_dialog()->ShowSaveDataList(save_entries, focused, operation, listSet);
|
||||
|
||||
// UI returns -1 for new save games
|
||||
if (selected == -1)
|
||||
@@ -598,7 +587,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
}
|
||||
//else if (psf.empty())
|
||||
//{
|
||||
// // setParam is specified if something required updating.
|
||||
// // setParam is specified if something required updating.
|
||||
// // Do not exit. Recreate mode will handle the rest
|
||||
// //return CELL_OK;
|
||||
//}
|
||||
@@ -735,11 +724,16 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
fs::file file(dir_path + file_path, fs::read);
|
||||
if (!file)
|
||||
{
|
||||
cellSaveData.error("savedata file not found");
|
||||
cellSaveData.error("Failed to open file %s%s", dir_path, file_path);
|
||||
return CELL_SAVEDATA_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
file.seek(fileSet->fileOffset);
|
||||
fileGet->excSize = static_cast<u32>(file.read(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
std::vector<uchar> buf;
|
||||
buf.resize(std::min<u32>(fileSet->fileSize, fileSet->fileBufSize));
|
||||
buf.resize(file.read(buf.data(), buf.size()));
|
||||
std::memcpy(fileSet->fileBuf.get_ptr(), buf.data(), buf.size());
|
||||
fileGet->excSize = ::size32(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -747,7 +741,9 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
{
|
||||
fs::file file(dir_path + file_path, fs::write + fs::create);
|
||||
file.seek(fileSet->fileOffset);
|
||||
fileGet->excSize = static_cast<u32>(file.write(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
const auto start = static_cast<uchar*>(fileSet->fileBuf.get_ptr());
|
||||
std::vector<uchar> buf(start, start + std::min<u32>(fileSet->fileSize, fileSet->fileBufSize));
|
||||
fileGet->excSize = ::narrow<u32>(file.write(buf.data(), buf.size()));
|
||||
file.trunc(file.pos()); // truncate
|
||||
break;
|
||||
}
|
||||
@@ -763,7 +759,9 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
{
|
||||
fs::file file(dir_path + file_path, fs::write + fs::create);
|
||||
file.seek(fileSet->fileOffset);
|
||||
fileGet->excSize = static_cast<u32>(file.write(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
const auto start = static_cast<uchar*>(fileSet->fileBuf.get_ptr());
|
||||
std::vector<uchar> buf(start, start + std::min<u32>(fileSet->fileSize, fileSet->fileBufSize));
|
||||
fileGet->excSize = ::narrow<u32>(file.write(buf.data(), buf.size()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -889,7 +887,7 @@ s32 cellSaveDataFixedLoad2(ppu_thread& ppu, u32 version, PSetList setList, PSetB
|
||||
return savedata_op(ppu, SAVEDATA_OP_FIXED_LOAD, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, userdata, 0, vm::null);
|
||||
}
|
||||
|
||||
s32 cellSaveDataFixedSave(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed,
|
||||
s32 cellSaveDataFixedSave(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed,
|
||||
PFuncStat funcStat, PFuncFile funcFile, u32 container)
|
||||
{
|
||||
cellSaveData.warning("cellSaveDataFixedSave(version=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcStat=*0x%x, funcFile=*0x%x, container=0x%x)",
|
||||
@@ -1059,7 +1057,7 @@ void cellSaveDataEnableOverlay(s32 enable)
|
||||
}
|
||||
|
||||
|
||||
// Functions (Extensions)
|
||||
// Functions (Extensions)
|
||||
s32 cellSaveDataListDelete(ppu_thread& ppu, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.warning("cellSaveDataListDelete(setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", setList, setBuf, funcList, funcDone, container, userdata);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellSearch.h"
|
||||
@@ -7,13 +8,62 @@
|
||||
|
||||
logs::channel cellSearch("cellSearch");
|
||||
|
||||
s32 cellSearchInitialize(ppu_thread& ppu, CellSearchMode mode, u32 container, vm::ptr<CellSearchSystemCallback> func, vm::ptr<u32> userData)
|
||||
template<>
|
||||
void fmt_class_string<CellSearchError>::format(std::string& out, u64 arg)
|
||||
{
|
||||
cellSearch.warning("cellSearchInitialize()");
|
||||
format_enum(out, arg, [](auto error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
STR_CASE(CELL_SEARCH_CANCELED);
|
||||
STR_CASE(CELL_SEARCH_ERROR_PARAM);
|
||||
STR_CASE(CELL_SEARCH_ERROR_BUSY);
|
||||
STR_CASE(CELL_SEARCH_ERROR_NO_MEMORY);
|
||||
STR_CASE(CELL_SEARCH_ERROR_UNKNOWN_MODE);
|
||||
STR_CASE(CELL_SEARCH_ERROR_ALREADY_INITIALIZED);
|
||||
STR_CASE(CELL_SEARCH_ERROR_NOT_INITIALIZED);
|
||||
STR_CASE(CELL_SEARCH_ERROR_FINALIZING);
|
||||
STR_CASE(CELL_SEARCH_ERROR_NOT_SUPPORTED_SEARCH);
|
||||
STR_CASE(CELL_SEARCH_ERROR_CONTENT_OBSOLETE);
|
||||
STR_CASE(CELL_SEARCH_ERROR_CONTENT_NOT_FOUND);
|
||||
STR_CASE(CELL_SEARCH_ERROR_NOT_LIST);
|
||||
STR_CASE(CELL_SEARCH_ERROR_OUT_OF_RANGE);
|
||||
STR_CASE(CELL_SEARCH_ERROR_INVALID_SEARCHID);
|
||||
STR_CASE(CELL_SEARCH_ERROR_ALREADY_GOT_RESULT);
|
||||
STR_CASE(CELL_SEARCH_ERROR_NOT_SUPPORTED_CONTEXT);
|
||||
STR_CASE(CELL_SEARCH_ERROR_INVALID_CONTENTTYPE);
|
||||
STR_CASE(CELL_SEARCH_ERROR_DRM);
|
||||
STR_CASE(CELL_SEARCH_ERROR_TAG);
|
||||
STR_CASE(CELL_SEARCH_ERROR_GENERIC);
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
struct search_t
|
||||
{
|
||||
vm::ptr<CellSearchSystemCallback> func;
|
||||
vm::ptr<void> userData;
|
||||
};
|
||||
|
||||
struct search_object_t
|
||||
{
|
||||
// TODO: Figured out the correct values to set here
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 64;
|
||||
static const u32 invalid = 0xFFFFFFFF;
|
||||
};
|
||||
|
||||
error_code cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr<CellSearchSystemCallback> func, vm::ptr<void> userData)
|
||||
{
|
||||
cellSearch.warning("cellSearchInitialize(mode=0x%x, container=0x%x, func=*0x%x, userData=*0x%x)", (u32) mode, container, func, userData);
|
||||
|
||||
const auto search = fxm::make_always<search_t>();
|
||||
search->func = func;
|
||||
search->userData = userData;
|
||||
|
||||
// TODO: Store the arguments somewhere so we can use them later.
|
||||
|
||||
//inform callback that search is alive
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
func(ppu, CELL_SEARCH_EVENT_INITIALIZE_RESULT, CELL_OK, vm::null, userData);
|
||||
@@ -23,124 +73,350 @@ s32 cellSearchInitialize(ppu_thread& ppu, CellSearchMode mode, u32 container, vm
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchFinalize()
|
||||
error_code cellSearchFinalize()
|
||||
{
|
||||
cellSearch.warning("cellSearchFinalize()");
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_FINALIZE_RESULT, CELL_OK, vm::null, search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchStartListSearch()
|
||||
error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchStartListSearch(type=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", (u32) type, (u32) sortOrder, outSearchId);
|
||||
|
||||
if (!outSearchId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
*outSearchId = idm::make<search_object_t>();
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
vm::var<CellSearchResultParam> resultParam;
|
||||
resultParam->searchId = *outSearchId;
|
||||
resultParam->resultNum = 0; // TODO
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_LISTSEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchStartContentSearchInList()
|
||||
error_code cellSearchStartContentSearchInList(vm::cptr<CellSearchContentId> listId, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchStartContentSearchInList(listId=*0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", listId, (u32) sortKey, (u32) sortOrder, outSearchId);
|
||||
|
||||
if (!listId || !outSearchId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
*outSearchId = idm::make<search_object_t>();
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
vm::var<CellSearchResultParam> resultParam;
|
||||
resultParam->searchId = *outSearchId;
|
||||
resultParam->resultNum = 0; // TODO
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_CONTENTSEARCH_INLIST_RESULT, CELL_OK, vm::cast(resultParam.addr()), search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchStartContentSearch()
|
||||
error_code cellSearchStartContentSearch(CellSearchContentSearchType type, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchStartContentSearch(type=0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", (u32) type, (u32) sortKey, (u32) sortOrder, outSearchId);
|
||||
|
||||
if (!outSearchId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
*outSearchId = idm::make<search_object_t>();
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
vm::var<CellSearchResultParam> resultParam;
|
||||
resultParam->searchId = *outSearchId;
|
||||
resultParam->resultNum = 0; // TODO
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_CONTENTSEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchStartSceneSearchInVideo()
|
||||
error_code cellSearchStartSceneSearchInVideo(vm::cptr<CellSearchContentId> videoId, CellSearchSceneSearchType searchType, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchStartSceneSearchInVideo(videoId=*0x%x, searchType=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", videoId, (u32) searchType, (u32) sortOrder, outSearchId);
|
||||
|
||||
if (!videoId || !outSearchId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
*outSearchId = idm::make<search_object_t>();
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
vm::var<CellSearchResultParam> resultParam;
|
||||
resultParam->searchId = *outSearchId;
|
||||
resultParam->resultNum = 0; // TODO
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_SCENESEARCH_INVIDEO_RESULT, CELL_OK, vm::cast(resultParam.addr()), search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchStartSceneSearch()
|
||||
error_code cellSearchStartSceneSearch(CellSearchSceneSearchType searchType, vm::cptr<char> gameTitle, vm::cpptr<char> tags, u32 tagNum, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchStartSceneSearch(searchType=0x%x, gameTitle=%s, tags=**0x%x, tagNum=0x%x, sortKey=0x%x, sortOrder=0x%x, outSearchId=*0x%x)", (u32) searchType, gameTitle, tags, tagNum, (u32) sortKey, (u32) sortOrder, outSearchId);
|
||||
|
||||
if (!gameTitle || !outSearchId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
*outSearchId = idm::make<search_object_t>();
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto search = fxm::get_always<search_t>();
|
||||
|
||||
vm::var<CellSearchResultParam> resultParam;
|
||||
resultParam->searchId = *outSearchId;
|
||||
resultParam->resultNum = 0; // TODO
|
||||
|
||||
search->func(ppu, CELL_SEARCH_EVENT_SCENESEARCH_RESULT, CELL_OK, vm::cast(resultParam.addr()), search->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoByOffset()
|
||||
error_code cellSearchGetContentInfoByOffset(CellSearchId searchId, s32 offset, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoByOffset(searchId=0x%x, offset=0x%x, infoBuffer=*0x%x, outContentType=*0x%x, outContentId=*0x%x)", searchId, offset, infoBuffer, outContentType, outContentId);
|
||||
|
||||
if (!outContentType)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoByContentId()
|
||||
error_code cellSearchGetContentInfoByContentId(vm::cptr<CellSearchContentId> contentId, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoByContentId(contentId=*0x%x, infoBuffer=*0x%x, outContentType=*0x%x)", contentId, infoBuffer, outContentType);
|
||||
|
||||
if (!outContentType)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetOffsetByContentId()
|
||||
error_code cellSearchGetOffsetByContentId(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, vm::ptr<s32> outOffset)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetOffsetByContentId(searchId=0x%x, contentId=*0x%x, outOffset=*0x%x)", searchId, contentId, outOffset);
|
||||
|
||||
if (!outOffset)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentIdByOffset()
|
||||
error_code cellSearchGetContentIdByOffset(CellSearchId searchId, s32 offset, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId, vm::ptr<CellSearchTimeInfo> outTimeInfo)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentIdByOffset(searchId=0x%x, offset=0x%x, outContentType=*0x%x, outContentId=*0x%x, outTimeInfo=*0x%x)", searchId, offset, outContentType, outContentId, outTimeInfo);
|
||||
|
||||
if (!outContentType || !outContentId)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoGameComment()
|
||||
error_code cellSearchGetContentInfoGameComment(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> gameComment)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment);
|
||||
|
||||
if (!gameComment)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetMusicSelectionContext()
|
||||
error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, CellSearchRepeatMode repeatMode, CellSearchContextOption option, vm::ptr<CellMusicSelectionContext> outContext)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetMusicSelectionContext(searchId=0x%x, contentId=*0x%x, repeatMode=0x%x, option=0x%x, outContext=*0x%x)", searchId, contentId, (u32) repeatMode, (u32) option, outContext);
|
||||
|
||||
if (!outContext)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetMusicSelectionContextOfSingleTrack()
|
||||
error_code cellSearchGetMusicSelectionContextOfSingleTrack(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellMusicSelectionContext> outContext)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetMusicSelectionContextOfSingleTrack(contentId=*0x%x, outContext=*0x%x)", contentId, outContext);
|
||||
|
||||
if (!contentId || !outContext)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoPath()
|
||||
error_code cellSearchGetContentInfoPath(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPath> infoPath)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoPath(contentId=*0x%x, infoPath=*0x%x)", contentId, infoPath);
|
||||
|
||||
if (!infoPath)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoPathMovieThumb()
|
||||
error_code cellSearchGetContentInfoPathMovieThumb(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPathMovieThumb> infoMt)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt);
|
||||
|
||||
if (!infoMt)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchPrepareFile()
|
||||
error_code cellSearchPrepareFile(vm::cptr<char> path)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchPrepareFile(path=%s)", path);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoDeveloperData()
|
||||
error_code cellSearchGetContentInfoDeveloperData(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> developerData)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoDeveloperData(contentId=*0x%x, developerData=*0x%x)", contentId, developerData);
|
||||
|
||||
if (!contentId || !developerData)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchGetContentInfoSharable()
|
||||
error_code cellSearchGetContentInfoSharable(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchSharableType> sharable)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchGetContentInfoSharable(contentId=*0x%x, sharable=*0x%x)", contentId, sharable);
|
||||
|
||||
if (!contentId || !sharable)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchCancel()
|
||||
error_code cellSearchCancel(CellSearchId searchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.todo("cellSearchCancel(searchId=0x%x)", searchId);
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSearchEnd()
|
||||
error_code cellSearchEnd(CellSearchId searchId)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
cellSearch.warning("cellSearchEnd(searchId=0x%x)", searchId);
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
idm::remove<search_object_t>(searchId);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
// Error Codes
|
||||
enum
|
||||
enum CellSearchError : u32
|
||||
{
|
||||
CELL_SEARCH_CANCELED = 1,
|
||||
CELL_SEARCH_ERROR_PARAM = 0x8002C801,
|
||||
@@ -30,17 +28,20 @@ enum
|
||||
// Constants
|
||||
enum
|
||||
{
|
||||
CELL_SEARCH_CONTENT_ID_SIZE = 16,
|
||||
CELL_SEARCH_TITLE_LEN_MAX = 384,
|
||||
CELL_SEARCH_TAG_NUM_MAX = 6,
|
||||
CELL_SEARCH_TAG_LEN_MAX = 63,
|
||||
CELL_MUSIC_SELECTION_CONTEXT_SIZE = 2048,
|
||||
CELL_SEARCH_PATH_LEN_MAX = 63,
|
||||
CELL_SEARCH_MTOPTION_LEN_MAX = 63,
|
||||
CELL_SEARCH_CONTENT_ID_SIZE = 16,
|
||||
CELL_SEARCH_TITLE_LEN_MAX = 384,
|
||||
CELL_SEARCH_TAG_NUM_MAX = 6,
|
||||
CELL_SEARCH_TAG_LEN_MAX = 63,
|
||||
CELL_MUSIC_SELECTION_CONTEXT_SIZE = 2048,
|
||||
CELL_SEARCH_PATH_LEN_MAX = 63,
|
||||
CELL_SEARCH_MTOPTION_LEN_MAX = 63,
|
||||
CELL_SEARCH_DEVELOPERDATA_LEN_MAX = 64,
|
||||
CELL_SEARCH_GAMECOMMENT_SIZE_MAX = 1024,
|
||||
CELL_SEARCH_CONTENT_BUFFER_SIZE_MAX = 2048,
|
||||
};
|
||||
|
||||
// Sort keys
|
||||
enum : s32
|
||||
enum CellSearchSortKey : s32
|
||||
{
|
||||
CELL_SEARCH_SORTKEY_NONE = 0,
|
||||
CELL_SEARCH_SORTKEY_DEFAULT = 1,
|
||||
@@ -56,15 +57,15 @@ enum : s32
|
||||
};
|
||||
|
||||
// Sort order
|
||||
enum : s32
|
||||
enum CellSearchSortOrder : s32
|
||||
{
|
||||
CELL_SEARCH_SORTORDER_NONE = 0,
|
||||
CELL_SEARCH_SORTORDER_ASCENDING = 1,
|
||||
CELL_SEARCH_SOFTORDER_DESCENDING = 2,
|
||||
CELL_SEARCH_SORTORDER_DESCENDING = 2,
|
||||
};
|
||||
|
||||
// Content types
|
||||
enum : s32
|
||||
enum CellSearchContentType : s32
|
||||
{
|
||||
CELL_SEARCH_CONTENTTYPE_NONE = 0,
|
||||
CELL_SEARCH_CONTENTTYPE_MUSIC = 1,
|
||||
@@ -122,15 +123,22 @@ enum CellSearchSceneType : s32
|
||||
// List types
|
||||
enum CellSearchListType : s32
|
||||
{
|
||||
CELL_SEARCH_LISTTYPE_NONE = 0,
|
||||
CELL_SEARCH_LISTTYPE_MUSIC_ALBUM = 1,
|
||||
CELL_SEARCH_LISTTYPE_MUSIC_GENRE = 2,
|
||||
CELL_SEARCH_LISTTYPE_MUSIC_ARTIST = 3,
|
||||
CELL_SEARCH_LISTTYPE_PHOTO_YEAR = 4,
|
||||
CELL_SEARCH_LISTTYPE_PHOTO_MONTH = 5,
|
||||
CELL_SEARCH_LISTTYPE_PHOTO_ALBUM = 6,
|
||||
CELL_SEARCH_LISTTYPE_PHOTO_PLAYLIST = 7,
|
||||
CELL_SEARCH_LISTTYPE_VIDEO_ALBUM = 8,
|
||||
CELL_SEARCH_LISTTYPE_MUSIC_PLAYLIST = 9,
|
||||
};
|
||||
|
||||
// Content status
|
||||
enum CellSearchContentStatus : s32
|
||||
{
|
||||
CELL_SEARCH_CONTENTSTATUS_NONE,
|
||||
CELL_SEARCH_CONTENTSTATUS_AVAILABLE,
|
||||
CELL_SEARCH_CONTENTSTATUS_NOT_SUPPORTED,
|
||||
CELL_SEARCH_CONTENTSTATUS_BROKEN,
|
||||
@@ -139,7 +147,7 @@ enum CellSearchContentStatus : s32
|
||||
// Search orientation
|
||||
enum CellSearchOrientation : s32
|
||||
{
|
||||
CELL_SEARCH_ORIENTATION_UNKNOWN,
|
||||
CELL_SEARCH_ORIENTATION_UNKNOWN = 0,
|
||||
CELL_SEARCH_ORIENTATION_TOP_LEFT,
|
||||
CELL_SEARCH_ORIENTATION_TOP_RIGHT,
|
||||
CELL_SEARCH_ORIENTATION_BOTTOM_RIGHT,
|
||||
@@ -165,7 +173,60 @@ enum CellSearchEvent : s32
|
||||
CELL_SEARCH_EVENT_SCENESEARCH_RESULT,
|
||||
};
|
||||
|
||||
using CellSearchSystemCallback = void(CellSearchEvent event, s32 result, vm::cptr<u32> param, vm::ptr<u32> userData);
|
||||
enum CellSearchListSearchType : s32
|
||||
{
|
||||
CELL_SEARCH_LISTSEARCHTYPE_NONE = 0,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ALBUM,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_MUSIC_GENRE,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_MUSIC_ARTIST,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_PHOTO_YEAR,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_PHOTO_MONTH,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_PHOTO_ALBUM,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_PHOTO_PLAYLIST,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_VIDEO_ALBUM,
|
||||
CELL_SEARCH_LISTSEARCHTYPE_MUSIC_PLAYLIST,
|
||||
};
|
||||
|
||||
enum CellSearchContentSearchType : s32
|
||||
{
|
||||
CELL_SEARCH_CONTENTSEARCHTYPE_NONE = 0,
|
||||
CELL_SEARCH_CONTENTSEARCHTYPE_MUSIC_ALL,
|
||||
CELL_SEARCH_CONTENTSEARCHTYPE_PHOTO_ALL,
|
||||
CELL_SEARCH_CONTENTSEARCHTYPE_VIDEO_ALL,
|
||||
};
|
||||
|
||||
enum CellSearchSceneSearchType : s32
|
||||
{
|
||||
CELL_SEARCH_SCENESEARCHTYPE_NONE = 0,
|
||||
CELL_SEARCH_SCENESEARCHTYPE_CHAPTER,
|
||||
CELL_SEARCH_SCENESEARCHTYPE_CLIP_HIGHLIGHT,
|
||||
CELL_SEARCH_SCENESEARCHTYPE_CLIP_USER,
|
||||
CELL_SEARCH_SCENESEARCHTYPE_CLIP,
|
||||
CELL_SEARCH_SCENESEARCHTYPE_ALL,
|
||||
};
|
||||
|
||||
enum CellSearchRepeatMode : s32
|
||||
{
|
||||
CELL_SEARCH_REPEATMODE_NONE = 0,
|
||||
CELL_SEARCH_REPEATMODE_REPEAT1,
|
||||
CELL_SEARCH_REPEATMODE_ALL,
|
||||
CELL_SEARCH_REPEATMODE_NOREPEAT1,
|
||||
};
|
||||
|
||||
enum CellSearchContextOption : s32
|
||||
{
|
||||
CELL_SEARCH_CONTEXTOPTION_NONE = 0,
|
||||
CELL_SEARCH_CONTEXTOPTION_SHUFFLE,
|
||||
};
|
||||
|
||||
enum CellSearchSharableType : s32
|
||||
{
|
||||
CELL_SEARCH_SHARABLETYPE_PROHIBITED = 0,
|
||||
CELL_SEARCH_SHARABLETYPE_PERMITTED,
|
||||
};
|
||||
|
||||
using CellSearchId = s32;
|
||||
using CellSearchSystemCallback = void(CellSearchEvent event, s32 result, vm::ps3::cptr<void> param, vm::ps3::ptr<void> userData);
|
||||
|
||||
struct CellSearchContentId
|
||||
{
|
||||
@@ -174,7 +235,7 @@ struct CellSearchContentId
|
||||
|
||||
struct CellSearchResultParam
|
||||
{
|
||||
be_t<s32> searchId;
|
||||
be_t<CellSearchId> searchId;
|
||||
be_t<u32> resultNum;
|
||||
};
|
||||
|
||||
|
||||
@@ -474,6 +474,18 @@ s32 _ZN4cxml8Document5ClearEv()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN4cxml8Document5WriteEPFiPKvjPvES3_()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN4cxml8Document12RegisterFileEPKvjPNS_4FileE()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN4cxml8Document13CreateElementEPKciPNS_7ElementE()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
@@ -546,6 +558,12 @@ s32 _ZN8cxmlutil6GetIntERKN4cxml7ElementEPKcPi()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN8cxmlutil7SetFileERKN4cxml7ElementEPKcRKNS0_4FileE()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN8cxmlutil8GetFloatERKN4cxml7ElementEPKcPf()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
@@ -682,6 +700,8 @@ DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []()
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8DocumentC1Ev);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8DocumentD1Ev);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document5ClearEv);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document5WriteEPFiPKvjPvES3_);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document12RegisterFileEPKvjPNS_4FileE);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document13CreateElementEPKciPNS_7ElementE);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document14SetHeaderMagicEPKc);
|
||||
REG_FUNC(cellSysutil, _ZN4cxml8Document16CreateFromBufferEPKvjb);
|
||||
@@ -696,6 +716,7 @@ DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []()
|
||||
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil6SetIntERKN4cxml7ElementEPKci);
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil6GetIntERKN4cxml7ElementEPKcPi);
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil7SetFileERKN4cxml7ElementEPKcRKNS0_4FileE);
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil8GetFloatERKN4cxml7ElementEPKcPf);
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil9GetStringERKN4cxml7ElementEPKcPS5_Pj);
|
||||
REG_FUNC(cellSysutil, _ZN8cxmlutil9SetStringERKN4cxml7ElementEPKcS5_);
|
||||
|
||||
@@ -40,6 +40,9 @@ error_code cellUserInfoGetStat(u32 id, vm::ptr<CellUserInfoUserStat> stat)
|
||||
id = 1;
|
||||
}
|
||||
|
||||
if (!stat)
|
||||
return CELL_USERINFO_ERROR_PARAM;
|
||||
|
||||
const std::string& path = vfs::get(fmt::format("/dev_hdd0/home/%08d/", id));
|
||||
|
||||
if (!fs::is_dir(path))
|
||||
@@ -104,7 +107,7 @@ error_code cellUserInfoGetList(vm::ptr<u32> listNum, vm::ptr<CellUserInfoUserLis
|
||||
// TODO: Properly set the current user ID here, once implemented
|
||||
*currentUserId = 1;
|
||||
}
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,99 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel cellVideoExport("cellVideoExport");
|
||||
|
||||
s32 cellVideoExportProgress()
|
||||
struct CellVideoExportSetParam
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
vm::bptr<char> title;
|
||||
vm::bptr<char> game_title;
|
||||
vm::bptr<char> game_comment;
|
||||
be_t<s32> editable;
|
||||
vm::bptr<void> reserved2;
|
||||
};
|
||||
|
||||
using CellVideoExportUtilFinishCallback = void(s32 result, vm::ptr<void> userdata);
|
||||
|
||||
error_code cellVideoExportProgress(vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
cellVideoExport.todo("cellVideoExportProgress(funcFinish=*0x%x, userdata=*0x%x)", funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, 0xFFFF, userdata); // 0-0xFFFF where 0xFFFF = 100%
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellVideoExportInitialize2()
|
||||
error_code cellVideoExportInitialize2(u32 version, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellVideoExport.todo("cellVideoExportInitialize2(version=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellVideoExportInitialize()
|
||||
error_code cellVideoExportInitialize(u32 version, u32 container, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellVideoExport.todo("cellVideoExportInitialize(version=0x%x, container=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, container, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellVideoExportFromFileWithCopy()
|
||||
error_code cellVideoExportFromFileWithCopy(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellVideoExportSetParam> param, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellVideoExport.todo("cellVideoExportFromFileWithCopy(srcHddDir=%s, srcHddFile=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", srcHddDir, srcHddFile, param, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellVideoExportFromFile()
|
||||
error_code cellVideoExportFromFile(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellVideoExportSetParam> param, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellVideoExport.todo("cellVideoExportFromFile(srcHddDir=%s, srcHddFile=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", srcHddDir, srcHddFile, param, funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellVideoExportFinalize()
|
||||
error_code cellVideoExportFinalize(vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellVideoExport.todo("cellVideoExportFinalize(funcFinish=*0x%x, userdata=*0x%x)", funcFinish, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
funcFinish(ppu, CELL_OK, userdata);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,24 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellVideoUpload.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
logs::channel cellVideoUpload("cellVideoUpload");
|
||||
|
||||
s32 cellVideoUploadInitialize(vm::cptr<CellVideoUploadParam> pParam, vm::ptr<CellVideoUploadCallback> cb, vm::ptr<void> userdata)
|
||||
error_code cellVideoUploadInitialize(vm::cptr<CellVideoUploadParam> pParam, vm::ptr<CellVideoUploadCallback> cb, vm::ptr<void> userdata)
|
||||
{
|
||||
cellVideoUpload.todo("cellVideoUploadInitialize(pParam=*0x%x, cb=*0x%x, userdata=*0x%x)", pParam, cb, userdata);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
vm::var<char[]> pResultURL(128);
|
||||
|
||||
cb(ppu, CELL_VIDEO_UPLOAD_STATUS_INITIALIZED, CELL_OK, pResultURL, userdata);
|
||||
cb(ppu, CELL_VIDEO_UPLOAD_STATUS_FINALIZED, CELL_OK, pResultURL, userdata);
|
||||
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
struct CellVideoUploadOption
|
||||
{
|
||||
be_t<s32> type;
|
||||
@@ -11,27 +9,27 @@ struct CellVideoUploadOption
|
||||
struct CellVideoUploadParam
|
||||
{
|
||||
be_t<s32> siteID;
|
||||
vm::bcptr<char> pFilePath;
|
||||
vm::ps3::bcptr<char> pFilePath;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
vm::bcptr<char> pClientId;
|
||||
vm::bcptr<char> pDeveloperKey;
|
||||
vm::bcptr<char> pTitle_UTF8;
|
||||
vm::bcptr<char> pDescription_UTF8;
|
||||
vm::bcptr<char> pKeyword_1_UTF8;
|
||||
vm::bcptr<char> pKeyword_2_UTF8;
|
||||
vm::bcptr<char> pKeyword_3_UTF8;
|
||||
vm::ps3::bcptr<char> pClientId;
|
||||
vm::ps3::bcptr<char> pDeveloperKey;
|
||||
vm::ps3::bcptr<char> pTitle_UTF8;
|
||||
vm::ps3::bcptr<char> pDescription_UTF8;
|
||||
vm::ps3::bcptr<char> pKeyword_1_UTF8;
|
||||
vm::ps3::bcptr<char> pKeyword_2_UTF8;
|
||||
vm::ps3::bcptr<char> pKeyword_3_UTF8;
|
||||
u8 isPrivate;
|
||||
u8 rating;
|
||||
} youtube;
|
||||
} u;
|
||||
be_t<s32> numOfOption;
|
||||
vm::bptr<CellVideoUploadOption> pOption;
|
||||
vm::ps3::bptr<CellVideoUploadOption> pOption;
|
||||
};
|
||||
|
||||
typedef void(CellVideoUploadCallback)(s32 status, s32 errorCode, vm::cptr<char> pResultURL, vm::ptr<void> userdata);
|
||||
using CellVideoUploadCallback = void(s32 status, s32 errorCode, vm::ps3::cptr<char> pResultURL, vm::ps3::ptr<void> userdata);
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -59,3 +57,9 @@ enum
|
||||
CELL_VIDEO_UPLOAD_ERROR_FILE_OPEN = 0x8002d023,
|
||||
CELL_VIDEO_UPLOAD_ERROR_INVALID_STATE = 0x8002d024
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_VIDEO_UPLOAD_STATUS_INITIALIZED = 1,
|
||||
CELL_VIDEO_UPLOAD_STATUS_FINALIZED = 2
|
||||
};
|
||||
|
||||
@@ -2,9 +2,16 @@
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellWebBrowser.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
extern logs::channel cellSysutil;
|
||||
|
||||
struct browser_t
|
||||
{
|
||||
vm::ptr<CellWebBrowserSystemCallback> system_cb;
|
||||
vm::ptr<void> userData;
|
||||
};
|
||||
|
||||
s32 cellWebBrowserActivate()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
@@ -15,9 +22,10 @@ s32 cellWebBrowserConfig()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfig2()
|
||||
error_code cellWebBrowserConfig2(vm::cptr<CellWebBrowserConfig2> config, u32 version)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfig2(config=*0x%x, version=%d)", config, version);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigGetHeapSize()
|
||||
@@ -45,9 +53,10 @@ s32 cellWebBrowserConfigSetErrorHook2()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetFullScreen2()
|
||||
error_code cellWebBrowserConfigSetFullScreen2(vm::cptr<CellWebBrowserConfig2> config, u32 full)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetFullScreen2(config=*0x%x, full=%d)", config, full);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetFullVersion2()
|
||||
@@ -60,9 +69,10 @@ s32 cellWebBrowserConfigSetFunction()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetFunction2()
|
||||
error_code cellWebBrowserConfigSetFunction2(vm::ptr<CellWebBrowserConfig2> config, u32 funcset)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetFunction2(config=*0x%x, funcset=0x%x)", config, funcset);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetHeapSize()
|
||||
@@ -70,9 +80,10 @@ s32 cellWebBrowserConfigSetHeapSize()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetHeapSize2()
|
||||
error_code cellWebBrowserConfigSetHeapSize2(vm::ptr<CellWebBrowserConfig2> config, u32 size)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetHeapSize(config=*0x%x, size=0x%x)", config, size);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetMimeSet()
|
||||
@@ -80,9 +91,10 @@ s32 cellWebBrowserConfigSetMimeSet()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetNotifyHook2()
|
||||
error_code cellWebBrowserConfigSetNotifyHook2(vm::cptr<CellWebBrowserConfig2> config, vm::ptr<CellWebBrowserNotify> cb, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetNotifyHook2(config=*0x%x, cb=*0x%x, userdata=*0x%x)", config, cb, userdata);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetRequestHook2()
|
||||
@@ -95,14 +107,16 @@ s32 cellWebBrowserConfigSetStatusHook2()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetTabCount2()
|
||||
error_code cellWebBrowserConfigSetTabCount2(vm::cptr<CellWebBrowserConfig2> config, u32 tab_count)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetTabCount2(config=*0x%x, tab_count=%d)", config, tab_count);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetUnknownMIMETypeHook2()
|
||||
error_code cellWebBrowserConfigSetUnknownMIMETypeHook2(vm::cptr<CellWebBrowserConfig2> config, vm::ptr<CellWebBrowserMIMETypeCallback> cb, vm::ptr<void> userdata)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetUnknownMIMETypeHook2(config=*0x%x, cb=*0x%x, userdata=*0x%x)", config, cb, userdata);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetVersion()
|
||||
@@ -110,9 +124,10 @@ s32 cellWebBrowserConfigSetVersion()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetViewCondition2()
|
||||
error_code cellWebBrowserConfigSetViewCondition2(vm::ptr<CellWebBrowserConfig2> config, u32 cond)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserConfigSetViewCondition2(config=*0x%x, cond=0x%x)", config, cond);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserConfigSetViewRect2()
|
||||
@@ -180,7 +195,7 @@ s32 cellWebBrowserEstimate()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserEstimate2(vm::cptr<CellWebBrowserConfig2> config, vm::ptr<u32> memSize)
|
||||
error_code cellWebBrowserEstimate2(vm::cptr<CellWebBrowserConfig2> config, vm::ptr<u32> memSize)
|
||||
{
|
||||
cellSysutil.warning("cellWebBrowserEstimate2(config=*0x%x, memSize=*0x%x)", config, memSize);
|
||||
|
||||
@@ -190,15 +205,26 @@ s32 cellWebBrowserEstimate2(vm::cptr<CellWebBrowserConfig2> config, vm::ptr<u32>
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserGetUsrdataOnGameExit(vm::ptr<CellWebBrowserUsrdata> ptr)
|
||||
error_code cellWebBrowserGetUsrdataOnGameExit(vm::ptr<CellWebBrowserUsrdata> ptr)
|
||||
{
|
||||
cellSysutil.todo("cellWebBrowserGetUsrdataOnGameExit(ptr=*0x%x", ptr);
|
||||
cellSysutil.todo("cellWebBrowserGetUsrdataOnGameExit(ptr=*0x%x)", ptr);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserInitialize()
|
||||
error_code cellWebBrowserInitialize(vm::ptr<CellWebBrowserSystemCallback> system_cb, u32 container)
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserInitialize(system_cb=*0x%x, container=0x%x)", system_cb, container);
|
||||
|
||||
const auto browser = fxm::make_always<browser_t>();
|
||||
browser->system_cb = system_cb;
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
system_cb(ppu, CELL_SYSUTIL_WEBBROWSER_INITIALIZING_FINISHED, browser->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellWebBrowserNavigate2()
|
||||
@@ -216,9 +242,17 @@ s32 cellWebBrowserSetSystemCallbackUsrdata()
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellWebBrowserShutdown()
|
||||
void cellWebBrowserShutdown()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
cellSysutil.todo("cellWebBrowserShutdown()");
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
const auto browser = fxm::get_always<browser_t>();
|
||||
|
||||
browser->system_cb(ppu, CELL_SYSUTIL_WEBBROWSER_SHUTDOWN_FINISHED, browser->userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
}
|
||||
|
||||
s32 cellWebBrowserUpdatePointerDisplayPos2()
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
|
||||
#include "cellSysutil.h"
|
||||
|
||||
//events
|
||||
enum CellWebBrowserEvent : s32
|
||||
{
|
||||
CELL_SYSUTIL_WEBBROWSER_INITIALIZING_FINISHED = 1,
|
||||
CELL_SYSUTIL_WEBBROWSER_SHUTDOWN_FINISHED = 4,
|
||||
CELL_SYSUTIL_WEBBROWSER_LOADING_FINISHED = 5,
|
||||
CELL_SYSUTIL_WEBBROWSER_UNLOADING_FINISHED = 7,
|
||||
CELL_SYSUTIL_WEBBROWSER_RELEASED = 9,
|
||||
CELL_SYSUTIL_WEBBROWSER_GRABBED = 11,
|
||||
};
|
||||
|
||||
using CellWebBrowserCallback = void(s32 cb_type, vm::ptr<void> client_session, vm::ptr<void> usrdata);
|
||||
using CellWebComponentCallback = void(s32 web_browser_id, s32 cb_type, vm::ptr<void> client_session, vm::ptr<void> usrdata);
|
||||
using CellWebBrowserSystemCallback = void(s32 cb_type, vm::ptr<void> usrdata);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sceNpMatchingInt("sceNpMatchingInt");
|
||||
|
||||
s32 sceNpMatchingGetRoomMemberList()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpMatchingInt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
// Parameter "unknown" added to distinguish this function
|
||||
// from the one in sceNp.cpp which has the same name
|
||||
s32 sceNpMatchingJoinRoomGUI(vm::ptr<void> unknown)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpMatchingInt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpMatchingGetRoomListGUI()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpMatchingInt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpMatchingSendRoomMessage()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpMatchingInt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
DECLARE(ppu_module_manager::sceNpMatchingInt)("sceNpMatchingInt", []()
|
||||
{
|
||||
REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomMemberList);
|
||||
REG_FUNC(sceNpMatchingInt, sceNpMatchingJoinRoomGUI);
|
||||
REG_FUNC(sceNpMatchingInt, sceNpMatchingGetRoomListGUI);
|
||||
REG_FUNC(sceNpMatchingInt, sceNpMatchingSendRoomMessage);
|
||||
});
|
||||
@@ -137,28 +137,32 @@ error_code sceNpSnsFbGetAccessToken(u32 handle, vm::cptr<SceNpSnsFbAccessTokenPa
|
||||
|
||||
s32 sceNpSnsFbStreamPublish()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(sceNpSns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpSnsFbCheckThrottle()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(sceNpSns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpSnsFbCheckConfig()
|
||||
{
|
||||
sceNpSns.todo("sceNpSnsFbCheckConfig()");
|
||||
UNIMPLEMENTED_FUNC(sceNpSns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpSnsFbLoadThrottle()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(sceNpSns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpSnsFbGetLongAccessToken()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
UNIMPLEMENTED_FUNC(sceNpSns);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -196,7 +196,12 @@ error_code sceNpTrophyCreateContext(vm::ptr<u32> context, vm::cptr<SceNpCommunic
|
||||
}
|
||||
|
||||
// open trophy pack file
|
||||
fs::file stream(vfs::get("/app_home/../TROPDIR/" + name + "/TROPHY.TRP"));
|
||||
fs::file stream(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/TROPDIR/" + name + "/TROPHY.TRP"));
|
||||
|
||||
if (!stream && (Emu.GetCat() == "DG" || Emu.GetCat() == "GD"))
|
||||
{
|
||||
stream.open(vfs::get("/dev_bdvd/PS3_GAME/TROPDIR/" + name + "/TROPHY.TRP"));
|
||||
}
|
||||
|
||||
// check if exists and opened
|
||||
if (!stream)
|
||||
@@ -326,7 +331,7 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
|
||||
error_code sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64> reqspace, u64 options)
|
||||
{
|
||||
sceNpTrophy.todo("sceNpTrophyGetRequiredDiskSpace(context=0x%x, handle=0x%x, reqspace=*0x%x, options=0x%llx)", context, handle, reqspace, options);
|
||||
sceNpTrophy.warning("sceNpTrophyGetRequiredDiskSpace(context=0x%x, handle=0x%x, reqspace=*0x%x, options=0x%llx)", context, handle, reqspace, options);
|
||||
|
||||
if (!reqspace)
|
||||
{
|
||||
@@ -347,12 +352,18 @@ error_code sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64>
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE;
|
||||
}
|
||||
|
||||
// TODO: This is not accurate. It's just an approximation of the real value
|
||||
// The real value can be obtained in TRP.cpp:
|
||||
// m_headers.trp_file_size - sizeof(m_headers) - (m_headers.trp_files_count * m_headers.trp_element_size);
|
||||
// TODO: eventually this should be set to 0 when trophys are detected as already installed, setting to 0 now causes some games to not call registerContext, which leads to trophys never getting installed
|
||||
*reqspace = ctxt->trp_stream.size();
|
||||
if (!fs::is_dir("/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name))
|
||||
{
|
||||
TRPLoader trp(ctxt->trp_stream);
|
||||
|
||||
if (trp.LoadHeader())
|
||||
{
|
||||
*reqspace = trp.GetRequiredSpace();
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*reqspace = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -510,7 +521,7 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
|
||||
// Get icon for the notification.
|
||||
std::string trophyIconPath = "/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name + "/TROP" + padding + std::to_string(trophyId) + ".PNG";
|
||||
fs::file trophyIconFile = fs::file(vfs::get(trophyIconPath));
|
||||
u32 iconSize = trophyIconFile.size();
|
||||
size_t iconSize = trophyIconFile.size();
|
||||
std::vector<uchar> trophyIconData;
|
||||
trophyIconFile.read(trophyIconData, iconSize);
|
||||
|
||||
@@ -523,9 +534,8 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
|
||||
sceNpTrophy.error("Failed to get info for trophy dialog. Error code %x", ret);
|
||||
*details = SceNpTrophyDetails();
|
||||
}
|
||||
Emu.CallAfter([det = *details, trophyIconData]() {
|
||||
Emu.GetCallbacks().get_trophy_notification_dialog()->ShowTrophyNotification(det, trophyIconData);
|
||||
});
|
||||
|
||||
Emu.GetCallbacks().get_trophy_notification_dialog()->ShowTrophyNotification(*details, trophyIconData);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
||||
@@ -1436,7 +1436,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
|
||||
|
||||
void ppu_acontext::UNK(ppu_opcode_t op)
|
||||
{
|
||||
//std::fill_n(gpr, 32, spec_gpr{});
|
||||
std::fill_n(gpr, 32, spec_gpr{});
|
||||
LOG_ERROR(PPU, "Unknown/Illegal opcode: 0x%08x at 0x%x" HERE, op.opcode, cia);
|
||||
}
|
||||
|
||||
@@ -2563,7 +2563,7 @@ void ppu_acontext::MULHW(ppu_opcode_t op)
|
||||
|
||||
void ppu_acontext::LDARX(ppu_opcode_t op)
|
||||
{
|
||||
//gpr[op.rd] = {};
|
||||
gpr[op.rd] = {};
|
||||
}
|
||||
|
||||
void ppu_acontext::DCBF(ppu_opcode_t op)
|
||||
@@ -2879,7 +2879,7 @@ void ppu_acontext::LVRX(ppu_opcode_t op)
|
||||
|
||||
void ppu_acontext::LSWI(ppu_opcode_t op)
|
||||
{
|
||||
//std::fill_n(gpr, 32, spec_gpr{});
|
||||
std::fill_n(gpr, 32, spec_gpr{});
|
||||
}
|
||||
|
||||
void ppu_acontext::LFSUX(ppu_opcode_t op)
|
||||
@@ -3106,7 +3106,7 @@ void ppu_acontext::STHU(ppu_opcode_t op)
|
||||
|
||||
void ppu_acontext::LMW(ppu_opcode_t op)
|
||||
{
|
||||
//std::fill_n(gpr, 32, spec_gpr{});
|
||||
std::fill_n(gpr, 32, spec_gpr{});
|
||||
}
|
||||
|
||||
void ppu_acontext::STMW(ppu_opcode_t op)
|
||||
|
||||
@@ -1548,7 +1548,14 @@ void PPUDisAsm::OR(ppu_opcode_t op)
|
||||
{
|
||||
if (op.rs == op.rb)
|
||||
{
|
||||
DisAsm_R2_RC("mr", op.ra, op.rb, op.rc);
|
||||
switch (op.opcode)
|
||||
{
|
||||
case 0x7f9ce378: return Write("db8cyc");
|
||||
case 0x7fbdeb78: return Write("db10cyc");
|
||||
case 0x7fdef378: return Write("db12cyc");
|
||||
case 0x7ffffb78: return Write("db16cyc");
|
||||
default : DisAsm_R2_RC("mr", op.ra, op.rb, op.rc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__SSSE3__)
|
||||
#define _mm_shuffle_epi8
|
||||
#endif
|
||||
|
||||
inline u64 dup32(u32 x) { return x | static_cast<u64>(x) << 32; }
|
||||
|
||||
// Write values to CR field
|
||||
@@ -83,6 +87,20 @@ extern __m128 sse_log2_ps(__m128 A)
|
||||
return _mm_add_ps(_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(x5, x6), x7), x4), _c), _mm_add_ps(_mm_mul_ps(x4, _c), x8));
|
||||
}
|
||||
|
||||
extern __m128i sse_pshufb(__m128i data, __m128i index)
|
||||
{
|
||||
v128 m = v128::fromV(_mm_and_si128(index, _mm_set1_epi8(0xf)));
|
||||
v128 a = v128::fromV(data);
|
||||
v128 r;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
r._u8[i] = a._u8[m._u8[i]];
|
||||
}
|
||||
|
||||
return _mm_and_si128(r.vi, _mm_cmpgt_epi8(index, _mm_set1_epi8(-1)));
|
||||
}
|
||||
|
||||
extern __m128i sse_altivec_vperm(__m128i A, __m128i B, __m128i C)
|
||||
{
|
||||
const auto index = _mm_andnot_si128(C, _mm_set1_epi8(0x1f));
|
||||
@@ -92,26 +110,40 @@ extern __m128i sse_altivec_vperm(__m128i A, __m128i B, __m128i C)
|
||||
return _mm_or_si128(_mm_and_si128(mask, sa), _mm_andnot_si128(mask, sb));
|
||||
}
|
||||
|
||||
extern __m128i sse_altivec_vperm_v0(__m128i A, __m128i B, __m128i C)
|
||||
{
|
||||
__m128i ab[2]{B, A};
|
||||
v128 index = v128::fromV(_mm_andnot_si128(C, _mm_set1_epi8(0x1f)));
|
||||
v128 res;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
res._u8[i] = ((u8*)+ab)[index._u8[i]];
|
||||
}
|
||||
|
||||
return res.vi;
|
||||
}
|
||||
|
||||
extern __m128i sse_altivec_lvsl(u64 addr)
|
||||
{
|
||||
alignas(16) static const u64 lvsl_values[0x10][2] =
|
||||
alignas(16) static const u8 lvsl_values[0x10][0x10] =
|
||||
{
|
||||
{ 0x08090A0B0C0D0E0F, 0x0001020304050607 },
|
||||
{ 0x090A0B0C0D0E0F10, 0x0102030405060708 },
|
||||
{ 0x0A0B0C0D0E0F1011, 0x0203040506070809 },
|
||||
{ 0x0B0C0D0E0F101112, 0x030405060708090A },
|
||||
{ 0x0C0D0E0F10111213, 0x0405060708090A0B },
|
||||
{ 0x0D0E0F1011121314, 0x05060708090A0B0C },
|
||||
{ 0x0E0F101112131415, 0x060708090A0B0C0D },
|
||||
{ 0x0F10111213141516, 0x0708090A0B0C0D0E },
|
||||
{ 0x1011121314151617, 0x08090A0B0C0D0E0F },
|
||||
{ 0x1112131415161718, 0x090A0B0C0D0E0F10 },
|
||||
{ 0x1213141516171819, 0x0A0B0C0D0E0F1011 },
|
||||
{ 0x131415161718191A, 0x0B0C0D0E0F101112 },
|
||||
{ 0x1415161718191A1B, 0x0C0D0E0F10111213 },
|
||||
{ 0x15161718191A1B1C, 0x0D0E0F1011121314 },
|
||||
{ 0x161718191A1B1C1D, 0x0E0F101112131415 },
|
||||
{ 0x1718191A1B1C1D1E, 0x0F10111213141516 },
|
||||
{ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
|
||||
{ 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 },
|
||||
{ 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02 },
|
||||
{ 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03 },
|
||||
{ 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04 },
|
||||
{ 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05 },
|
||||
{ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06 },
|
||||
{ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07 },
|
||||
{ 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08 },
|
||||
{ 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09 },
|
||||
{ 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a },
|
||||
{ 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b },
|
||||
{ 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c },
|
||||
{ 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d },
|
||||
{ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e },
|
||||
{ 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f },
|
||||
};
|
||||
|
||||
return _mm_load_si128((__m128i*)lvsl_values[addr & 0xf]);
|
||||
@@ -119,24 +151,24 @@ extern __m128i sse_altivec_lvsl(u64 addr)
|
||||
|
||||
extern __m128i sse_altivec_lvsr(u64 addr)
|
||||
{
|
||||
alignas(16) static const u64 lvsr_values[0x10][2] =
|
||||
alignas(16) static const u8 lvsr_values[0x10][0x10] =
|
||||
{
|
||||
{ 0x18191A1B1C1D1E1F, 0x1011121314151617 },
|
||||
{ 0x1718191A1B1C1D1E, 0x0F10111213141516 },
|
||||
{ 0x161718191A1B1C1D, 0x0E0F101112131415 },
|
||||
{ 0x15161718191A1B1C, 0x0D0E0F1011121314 },
|
||||
{ 0x1415161718191A1B, 0x0C0D0E0F10111213 },
|
||||
{ 0x131415161718191A, 0x0B0C0D0E0F101112 },
|
||||
{ 0x1213141516171819, 0x0A0B0C0D0E0F1011 },
|
||||
{ 0x1112131415161718, 0x090A0B0C0D0E0F10 },
|
||||
{ 0x1011121314151617, 0x08090A0B0C0D0E0F },
|
||||
{ 0x0F10111213141516, 0x0708090A0B0C0D0E },
|
||||
{ 0x0E0F101112131415, 0x060708090A0B0C0D },
|
||||
{ 0x0D0E0F1011121314, 0x05060708090A0B0C },
|
||||
{ 0x0C0D0E0F10111213, 0x0405060708090A0B },
|
||||
{ 0x0B0C0D0E0F101112, 0x030405060708090A },
|
||||
{ 0x0A0B0C0D0E0F1011, 0x0203040506070809 },
|
||||
{ 0x090A0B0C0D0E0F10, 0x0102030405060708 },
|
||||
{ 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10 },
|
||||
{ 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f },
|
||||
{ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e },
|
||||
{ 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d },
|
||||
{ 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c },
|
||||
{ 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b },
|
||||
{ 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a },
|
||||
{ 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09 },
|
||||
{ 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08 },
|
||||
{ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07 },
|
||||
{ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06 },
|
||||
{ 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05 },
|
||||
{ 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04 },
|
||||
{ 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03 },
|
||||
{ 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02 },
|
||||
{ 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 },
|
||||
};
|
||||
|
||||
return _mm_load_si128((__m128i*)lvsr_values[addr & 0xf]);
|
||||
@@ -202,6 +234,26 @@ extern void sse_cellbe_stvrx(u64 addr, __m128i a)
|
||||
_mm_maskmoveu_si128(_mm_shuffle_epi8(a, lvrx_masks[addr & 0xf]), lvlx_masks[addr & 0xf], (char*)vm::base(addr & ~0xf));
|
||||
}
|
||||
|
||||
extern __m128i sse_cellbe_lvlx_v0(u64 addr)
|
||||
{
|
||||
return sse_pshufb(_mm_load_si128((__m128i*)vm::base(addr & ~0xf)), lvlx_masks[addr & 0xf]);
|
||||
}
|
||||
|
||||
extern void sse_cellbe_stvlx_v0(u64 addr, __m128i a)
|
||||
{
|
||||
_mm_maskmoveu_si128(sse_pshufb(a, lvlx_masks[addr & 0xf]), lvrx_masks[addr & 0xf], (char*)vm::base(addr & ~0xf));
|
||||
}
|
||||
|
||||
extern __m128i sse_cellbe_lvrx_v0(u64 addr)
|
||||
{
|
||||
return sse_pshufb(_mm_load_si128((__m128i*)vm::base(addr & ~0xf)), lvrx_masks[addr & 0xf]);
|
||||
}
|
||||
|
||||
extern void sse_cellbe_stvrx_v0(u64 addr, __m128i a)
|
||||
{
|
||||
_mm_maskmoveu_si128(sse_pshufb(a, lvrx_masks[addr & 0xf]), lvlx_masks[addr & 0xf], (char*)vm::base(addr & ~0xf));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct add_flags_result_t
|
||||
{
|
||||
@@ -928,9 +980,16 @@ bool ppu_interpreter_fast::VMHRADDSHS(ppu_thread& ppu, ppu_opcode_t op)
|
||||
const auto a = ppu.vr[op.va].vi;
|
||||
const auto b = ppu.vr[op.vb].vi;
|
||||
const auto c = ppu.vr[op.vc].vi;
|
||||
const auto m = _mm_mulhrs_epi16(a, b);
|
||||
const auto s = _mm_cmpeq_epi16(m, _mm_set1_epi16(-0x8000)); // detect special case (positive 0x8000)
|
||||
ppu.vr[op.vd].vi = _mm_adds_epi16(_mm_adds_epi16(_mm_xor_si128(m, s), c), _mm_srli_epi16(s, 15));
|
||||
const auto x80 = _mm_set1_epi16(0x80); // 0x80 * 0x80 = 0x4000, add this to the product
|
||||
const auto al = _mm_unpacklo_epi16(a, x80);
|
||||
const auto ah = _mm_unpackhi_epi16(a, x80);
|
||||
const auto bl = _mm_unpacklo_epi16(b, x80);
|
||||
const auto bh = _mm_unpackhi_epi16(b, x80);
|
||||
const auto ml = _mm_srai_epi32(_mm_madd_epi16(al, bl), 15);
|
||||
const auto mh = _mm_srai_epi32(_mm_madd_epi16(ah, bh), 15);
|
||||
const auto cl = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), c), 16);
|
||||
const auto ch = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), c), 16);
|
||||
ppu.vr[op.vd].vi = _mm_packs_epi32(_mm_add_epi32(ml, cl), _mm_add_epi32(mh, ch));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1320,7 +1379,13 @@ bool ppu_interpreter::VOR(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::VPERM(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::VPERM(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
ppu.vr[op.vd].vi = sse_altivec_vperm_v0(ppu.vr[op.va].vi, ppu.vr[op.vb].vi, ppu.vr[op.vc].vi);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::VPERM(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
ppu.vr[op.vd].vi = sse_altivec_vperm(ppu.vr[op.va].vi, ppu.vr[op.vb].vi, ppu.vr[op.vc].vi);
|
||||
return true;
|
||||
@@ -2050,7 +2115,7 @@ bool ppu_interpreter::VSRB(ppu_thread& ppu, ppu_opcode_t op)
|
||||
auto& d = ppu.vr[op.vd];
|
||||
const auto& a = ppu.vr[op.va];
|
||||
const auto& b = ppu.vr[op.vb];
|
||||
|
||||
|
||||
for (uint i = 0; i < 16; i++)
|
||||
{
|
||||
d._u8[i] = a._u8[i] >> (b._u8[i] & 0x7);
|
||||
@@ -2964,7 +3029,7 @@ bool ppu_interpreter::BCCTR(ppu_thread& ppu, ppu_opcode_t op)
|
||||
if (op.lk) ppu.lr = link;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3163,7 +3228,7 @@ bool ppu_interpreter::MFOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
||||
const u32 n = cntlz32(op.crm) & 7;
|
||||
const u32 p = n * 4;
|
||||
const u32 v = ppu.cr[p + 0] << 3 | ppu.cr[p + 1] << 2 | ppu.cr[p + 2] << 1 | ppu.cr[p + 3] << 0;
|
||||
|
||||
|
||||
ppu.gpr[op.rd] = v << (p ^ 0x1c);
|
||||
}
|
||||
else
|
||||
@@ -3874,7 +3939,14 @@ bool ppu_interpreter::DIVW(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::LVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::LVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
ppu.vr[op.vd].vi = sse_cellbe_lvlx_v0(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::LVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
ppu.vr[op.vd].vi = sse_cellbe_lvlx(addr);
|
||||
@@ -3938,7 +4010,14 @@ bool ppu_interpreter::SRD(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::LVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::LVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
ppu.vr[op.vd].vi = sse_cellbe_lvrx_v0(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::LVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
ppu.vr[op.vd].vi = sse_cellbe_lvrx(addr);
|
||||
@@ -4006,7 +4085,14 @@ bool ppu_interpreter::LFDUX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::STVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::STVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
sse_cellbe_stvlx_v0(addr, ppu.vr[op.vs].vi);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::STVLX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
sse_cellbe_stvlx(addr, ppu.vr[op.vs].vi);
|
||||
@@ -4054,7 +4140,14 @@ bool ppu_interpreter::STFSX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::STVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::STVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
sse_cellbe_stvrx_v0(addr, ppu.vr[op.vs].vi);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::STVRX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
|
||||
sse_cellbe_stvrx(addr, ppu.vr[op.vs].vi);
|
||||
@@ -4114,7 +4207,12 @@ bool ppu_interpreter::STFDUX(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::LVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::LVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return LVLX(ppu, op);
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::LVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return LVLX(ppu, op);
|
||||
}
|
||||
@@ -4164,7 +4262,12 @@ bool ppu_interpreter::SRAD(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::LVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::LVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return LVRX(ppu, op);
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::LVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return LVRX(ppu, op);
|
||||
}
|
||||
@@ -4201,7 +4304,12 @@ bool ppu_interpreter::EIEIO(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::STVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::STVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return STVLX(ppu, op);
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::STVLXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return STVLX(ppu, op);
|
||||
}
|
||||
@@ -4220,7 +4328,12 @@ bool ppu_interpreter::EXTSH(ppu_thread& ppu, ppu_opcode_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::STVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter_precise::STVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return STVRX(ppu, op);
|
||||
}
|
||||
|
||||
bool ppu_interpreter_fast::STVRXL(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
return STVRX(ppu, op);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
class ppu_thread;
|
||||
|
||||
using ppu_inter_func_t = bool(*)(ppu_thread& ppu, ppu_opcode_t op);
|
||||
|
||||
struct ppu_interpreter
|
||||
{
|
||||
static bool MFVSCR(ppu_thread&, ppu_opcode_t);
|
||||
@@ -75,7 +77,6 @@ struct ppu_interpreter
|
||||
static bool VNMSUBFP(ppu_thread&, ppu_opcode_t);
|
||||
static bool VNOR(ppu_thread&, ppu_opcode_t);
|
||||
static bool VOR(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPERM(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKPX(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKUHUM(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKUWUM(ppu_thread&, ppu_opcode_t);
|
||||
@@ -247,42 +248,34 @@ struct ppu_interpreter
|
||||
static bool STVXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool DIVD(ppu_thread&, ppu_opcode_t);
|
||||
static bool DIVW(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LDBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LSWX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LWBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LFSX(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRW(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRD(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LSWI(ppu_thread&, ppu_opcode_t);
|
||||
static bool LFSUX(ppu_thread&, ppu_opcode_t);
|
||||
static bool SYNC(ppu_thread&, ppu_opcode_t);
|
||||
static bool LFDX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LFDUX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STDBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STSWX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STWBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STFSX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STFSUX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STSWI(ppu_thread&, ppu_opcode_t);
|
||||
static bool STFDX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STFDUX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool LHBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRAW(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRAD(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool DSS(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRAWI(ppu_thread&, ppu_opcode_t);
|
||||
static bool SRADI(ppu_thread&, ppu_opcode_t);
|
||||
static bool EIEIO(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool STHBRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool EXTSH(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool EXTSB(ppu_thread&, ppu_opcode_t);
|
||||
static bool STFIWX(ppu_thread&, ppu_opcode_t);
|
||||
static bool EXTSW(ppu_thread&, ppu_opcode_t);
|
||||
@@ -362,6 +355,16 @@ struct ppu_interpreter
|
||||
|
||||
struct ppu_interpreter_precise final : ppu_interpreter
|
||||
{
|
||||
static bool VPERM(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRXL(ppu_thread&, ppu_opcode_t);
|
||||
|
||||
static bool VPKSHSS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKSHUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKSWSS(ppu_thread&, ppu_opcode_t);
|
||||
@@ -395,11 +398,21 @@ struct ppu_interpreter_precise final : ppu_interpreter
|
||||
|
||||
struct ppu_interpreter_fast final : ppu_interpreter
|
||||
{
|
||||
static bool VPERM(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool LVRXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVLXL(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRX(ppu_thread&, ppu_opcode_t);
|
||||
static bool STVRXL(ppu_thread&, ppu_opcode_t);
|
||||
|
||||
static bool VPKSHSS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKSHUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKSWSS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKSWUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKUHUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKUHUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VPKUWUS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VADDSBS(ppu_thread&, ppu_opcode_t);
|
||||
static bool VADDSHS(ppu_thread&, ppu_opcode_t);
|
||||
|
||||
@@ -244,6 +244,7 @@ static void ppu_initialize_modules(const std::shared_ptr<ppu_linkage_info>& link
|
||||
&ppu_module_manager::sceNp2,
|
||||
&ppu_module_manager::sceNpClans,
|
||||
&ppu_module_manager::sceNpCommerce2,
|
||||
&ppu_module_manager::sceNpMatchingInt,
|
||||
&ppu_module_manager::sceNpSns,
|
||||
&ppu_module_manager::sceNpTrophy,
|
||||
&ppu_module_manager::sceNpTus,
|
||||
@@ -1345,7 +1346,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!load_libs.empty())
|
||||
{
|
||||
const std::string lle_dir = vfs::get("/dev_flash/sys/external/");
|
||||
@@ -1426,6 +1427,18 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
*args++ = arg_addr;
|
||||
}
|
||||
|
||||
// Fix primary stack size
|
||||
switch (primary_stacksize)
|
||||
{
|
||||
case 0x10: primary_stacksize = 32 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_32K
|
||||
case 0x20: primary_stacksize = 64 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_64K
|
||||
case 0x30: primary_stacksize = 96 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_96K
|
||||
case 0x40: primary_stacksize = 128 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_128K
|
||||
case 0x50: primary_stacksize = 256 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_256K
|
||||
case 0x60: primary_stacksize = 512 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_512K
|
||||
case 0x70: primary_stacksize = 1024 * 1024; break; // SYS_PROCESS_PRIMARY_STACK_SIZE_1M
|
||||
}
|
||||
|
||||
// Initialize main thread
|
||||
auto ppu = idm::make_ptr<ppu_thread>("main_thread", primary_prio, primary_stacksize);
|
||||
|
||||
|
||||
@@ -255,6 +255,7 @@ public:
|
||||
static const ppu_static_module sceNp2;
|
||||
static const ppu_static_module sceNpClans;
|
||||
static const ppu_static_module sceNpCommerce2;
|
||||
static const ppu_static_module sceNpMatchingInt;
|
||||
static const ppu_static_module sceNpSns;
|
||||
static const ppu_static_module sceNpTrophy;
|
||||
static const ppu_static_module sceNpTus;
|
||||
|
||||
@@ -71,7 +71,7 @@ inline u32 ppu_decode(u32 inst)
|
||||
}
|
||||
|
||||
// PPU decoder object. D provides functions. T is function pointer type returned.
|
||||
template<typename D, typename T = decltype(&D::UNK)>
|
||||
template <typename D, typename T = decltype(&D::UNK)>
|
||||
class ppu_decoder
|
||||
{
|
||||
// Fast lookup table
|
||||
@@ -555,6 +555,12 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
ppu_decoder(F&& init) : ppu_decoder()
|
||||
{
|
||||
init(m_table);
|
||||
}
|
||||
|
||||
const std::array<T, 0x20000>& get_table() const
|
||||
{
|
||||
return m_table;
|
||||
|
||||
@@ -56,6 +56,16 @@
|
||||
|
||||
const bool s_use_rtm = utils::has_rtm();
|
||||
|
||||
const bool s_use_ssse3 =
|
||||
#ifdef _MSC_VER
|
||||
utils::has_ssse3();
|
||||
#elif __SSSE3__
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#define _mm_shuffle_epi8
|
||||
#endif
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
@@ -101,12 +111,61 @@ void fmt_class_string<ppu_decoder_type>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
const ppu_decoder<ppu_interpreter_precise> s_ppu_interpreter_precise;
|
||||
const ppu_decoder<ppu_interpreter_fast> s_ppu_interpreter_fast;
|
||||
// Table of identical interpreter functions when precise contains SSE2 version, and fast contains SSSE3 functions
|
||||
const std::pair<ppu_inter_func_t, ppu_inter_func_t> s_ppu_dispatch_table[]
|
||||
{
|
||||
#define FUNC(x) {&ppu_interpreter_precise::x, &ppu_interpreter_fast::x}
|
||||
FUNC(VPERM),
|
||||
FUNC(LVLX),
|
||||
FUNC(LVLXL),
|
||||
FUNC(LVRX),
|
||||
FUNC(LVRXL),
|
||||
FUNC(STVLX),
|
||||
FUNC(STVLXL),
|
||||
FUNC(STVRX),
|
||||
FUNC(STVRXL),
|
||||
#undef FUNC
|
||||
};
|
||||
|
||||
extern const ppu_decoder<ppu_interpreter_precise> g_ppu_interpreter_precise([](auto& table)
|
||||
{
|
||||
if (s_use_ssse3)
|
||||
{
|
||||
for (auto& func : table)
|
||||
{
|
||||
for (const auto& pair : s_ppu_dispatch_table)
|
||||
{
|
||||
if (pair.first == func)
|
||||
{
|
||||
func = pair.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extern const ppu_decoder<ppu_interpreter_fast> g_ppu_interpreter_fast([](auto& table)
|
||||
{
|
||||
if (!s_use_ssse3)
|
||||
{
|
||||
for (auto& func : table)
|
||||
{
|
||||
for (const auto& pair : s_ppu_dispatch_table)
|
||||
{
|
||||
if (pair.second == func)
|
||||
{
|
||||
func = pair.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extern void ppu_initialize();
|
||||
extern void ppu_initialize(const ppu_module& info);
|
||||
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name);
|
||||
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, atomic_t<u32>&);
|
||||
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
||||
|
||||
// Get pointer to executable cache
|
||||
@@ -120,8 +179,8 @@ static u32 ppu_cache(u32 addr)
|
||||
{
|
||||
// Select opcode table
|
||||
const auto& table = *(
|
||||
g_cfg.core.ppu_decoder == ppu_decoder_type::precise ? &s_ppu_interpreter_precise.get_table() :
|
||||
g_cfg.core.ppu_decoder == ppu_decoder_type::fast ? &s_ppu_interpreter_fast.get_table() :
|
||||
g_cfg.core.ppu_decoder == ppu_decoder_type::precise ? &g_ppu_interpreter_precise.get_table() :
|
||||
g_cfg.core.ppu_decoder == ppu_decoder_type::fast ? &g_ppu_interpreter_fast.get_table() :
|
||||
(fmt::throw_exception<std::logic_error>("Invalid PPU decoder"), nullptr));
|
||||
|
||||
return ::narrow<u32>(reinterpret_cast<std::uintptr_t>(table[ppu_decode(vm::read32(addr))]));
|
||||
@@ -154,7 +213,7 @@ static bool ppu_check_toc(ppu_thread& ppu, ppu_opcode_t op)
|
||||
if (ppu.gpr[2] != found->second)
|
||||
{
|
||||
LOG_ERROR(PPU, "Unexpected TOC (0x%x, expected 0x%x)", ppu.gpr[2], found->second);
|
||||
|
||||
|
||||
if (!ppu.state.test_and_set(cpu_flag::dbg_pause) && ppu.check_state())
|
||||
{
|
||||
return false;
|
||||
@@ -207,8 +266,8 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_function_t ptr)
|
||||
{
|
||||
LOG_ERROR(PPU, "ppu_register_function_at(0x%x): empty range", addr);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
|
||||
@@ -275,6 +334,15 @@ extern void ppu_breakpoint(u32 addr)
|
||||
}
|
||||
}
|
||||
|
||||
void ppu_thread::on_spawn()
|
||||
{
|
||||
if (g_cfg.core.thread_scheduler_enabled)
|
||||
{
|
||||
// Bind to primary set
|
||||
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(thread_class::ppu));
|
||||
}
|
||||
}
|
||||
|
||||
void ppu_thread::on_init(const std::shared_ptr<void>& _this)
|
||||
{
|
||||
if (!stack_addr)
|
||||
@@ -401,7 +469,7 @@ std::string ppu_thread::dump() const
|
||||
{
|
||||
ret += '\n';
|
||||
}
|
||||
|
||||
|
||||
ret += "\nRegisters:\n=========\n";
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "GPR[%d] = 0x%llx\n", i, gpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "FPR[%d] = %.6G\n", i, fpr[i]);
|
||||
@@ -455,7 +523,9 @@ void ppu_thread::cpu_task()
|
||||
{
|
||||
case ppu_cmd::opcode:
|
||||
{
|
||||
cmd_pop(), s_ppu_interpreter_fast.decode(arg)(*this, {arg});
|
||||
cmd_pop(), g_cfg.core.ppu_decoder == ppu_decoder_type::precise
|
||||
? g_ppu_interpreter_precise.decode(arg)(*this, {arg})
|
||||
: g_ppu_interpreter_fast.decode(arg)(*this, {arg});
|
||||
break;
|
||||
}
|
||||
case ppu_cmd::set_gpr:
|
||||
@@ -521,7 +591,7 @@ void ppu_thread::exec_task()
|
||||
{
|
||||
reinterpret_cast<ppu_function_t>(static_cast<std::uintptr_t>(ppu_ref(cia)))(*this);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -545,7 +615,7 @@ void ppu_thread::exec_task()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cia % 16)
|
||||
if (cia % 16 || !s_use_ssse3)
|
||||
{
|
||||
// Unaligned
|
||||
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + cia);
|
||||
@@ -616,7 +686,7 @@ ppu_thread::~ppu_thread()
|
||||
ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack)
|
||||
: cpu_thread(idm::last_id())
|
||||
, prio(prio)
|
||||
, stack_size(stack ? ::align(std::min<u32>(stack, 0x100000), 0x1000) : 0x4000)
|
||||
, stack_size(stack >= 0x1000 ? ::align(std::min<u32>(stack, 0x100000), 0x1000) : 0x4000)
|
||||
, stack_addr(0)
|
||||
, start_time(get_system_time())
|
||||
, m_name(name)
|
||||
@@ -808,12 +878,17 @@ extern ppu_function_t ppu_get_syscall(u64 code);
|
||||
extern __m128 sse_exp2_ps(__m128 A);
|
||||
extern __m128 sse_log2_ps(__m128 A);
|
||||
extern __m128i sse_altivec_vperm(__m128i A, __m128i B, __m128i C);
|
||||
extern __m128i sse_altivec_vperm_v0(__m128i A, __m128i B, __m128i C);
|
||||
extern __m128i sse_altivec_lvsl(u64 addr);
|
||||
extern __m128i sse_altivec_lvsr(u64 addr);
|
||||
extern __m128i sse_cellbe_lvlx(u64 addr);
|
||||
extern __m128i sse_cellbe_lvrx(u64 addr);
|
||||
extern void sse_cellbe_stvlx(u64 addr, __m128i a);
|
||||
extern void sse_cellbe_stvrx(u64 addr, __m128i a);
|
||||
extern __m128i sse_cellbe_lvlx_v0(u64 addr);
|
||||
extern __m128i sse_cellbe_lvrx_v0(u64 addr);
|
||||
extern void sse_cellbe_stvlx_v0(u64 addr, __m128i a);
|
||||
extern void sse_cellbe_stvrx_v0(u64 addr, __m128i a);
|
||||
|
||||
[[noreturn]] static void ppu_trap(ppu_thread& ppu, u64 addr)
|
||||
{
|
||||
@@ -889,7 +964,7 @@ extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
|
||||
vm::writer_lock lock(0);
|
||||
|
||||
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(static_cast<u32>(ppu.rdata), reg_value);
|
||||
|
||||
|
||||
if (result)
|
||||
{
|
||||
vm::reservation_update(addr, sizeof(u32));
|
||||
@@ -1024,13 +1099,13 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
{ "__stdcx", (u64)&ppu_stdcx },
|
||||
{ "__vexptefp", (u64)&sse_exp2_ps },
|
||||
{ "__vlogefp", (u64)&sse_log2_ps },
|
||||
{ "__vperm", (u64)&sse_altivec_vperm },
|
||||
{ "__vperm", s_use_ssse3 ? (u64)&sse_altivec_vperm : (u64)&sse_altivec_vperm_v0 },
|
||||
{ "__lvsl", (u64)&sse_altivec_lvsl },
|
||||
{ "__lvsr", (u64)&sse_altivec_lvsr },
|
||||
{ "__lvlx", (u64)&sse_cellbe_lvlx },
|
||||
{ "__lvrx", (u64)&sse_cellbe_lvrx },
|
||||
{ "__stvlx", (u64)&sse_cellbe_stvlx },
|
||||
{ "__stvrx", (u64)&sse_cellbe_stvrx },
|
||||
{ "__lvlx", s_use_ssse3 ? (u64)&sse_cellbe_lvlx : (u64)&sse_cellbe_lvlx_v0 },
|
||||
{ "__lvrx", s_use_ssse3 ? (u64)&sse_cellbe_lvrx : (u64)&sse_cellbe_lvrx_v0 },
|
||||
{ "__stvlx", s_use_ssse3 ? (u64)&sse_cellbe_stvlx : (u64)&sse_cellbe_stvlx_v0 },
|
||||
{ "__stvrx", s_use_ssse3 ? (u64)&sse_cellbe_stvrx : (u64)&sse_cellbe_stvrx_v0 },
|
||||
};
|
||||
|
||||
for (u64 index = 0; index < 1024; index++)
|
||||
@@ -1075,18 +1150,20 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
std::vector<u64*> vars;
|
||||
std::vector<ppu_function_t> funcs;
|
||||
};
|
||||
|
||||
|
||||
// Permanently loaded compiled PPU modules (name -> data)
|
||||
jit_module& jit_mod = fxm::get_always<std::unordered_map<std::string, jit_module>>()->emplace(cache_path + info.name, jit_module{}).first->second;
|
||||
|
||||
// Compiler instance (deferred initialization)
|
||||
std::unique_ptr<jit_compiler> jit;
|
||||
std::shared_ptr<jit_compiler> jit;
|
||||
|
||||
// Compiler mutex
|
||||
semaphore<> jmutex;
|
||||
// Compiler mutex (global)
|
||||
static semaphore<> jmutex;
|
||||
|
||||
// Initialize semaphore with the max number of threads
|
||||
semaphore<INT32_MAX> jcores(std::thread::hardware_concurrency());
|
||||
u32 max_threads = static_cast<u32>(g_cfg.core.llvm_threads);
|
||||
s32 thread_count = max_threads > 0 ? std::min(max_threads, std::thread::hardware_concurrency()) : std::thread::hardware_concurrency();
|
||||
semaphore<INT32_MAX> jcores(thread_count);
|
||||
|
||||
if (!jcores.get())
|
||||
{
|
||||
@@ -1106,10 +1183,17 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
// Difference between function name and current location
|
||||
const u32 reloc = info.name.empty() ? 0 : info.segs.at(0).addr;
|
||||
|
||||
atomic_t<u32> fragment_sync{0};
|
||||
|
||||
u32 fragment_count{0};
|
||||
|
||||
while (jit_mod.vars.empty() && fpos < info.funcs.size())
|
||||
{
|
||||
// Initialize compiler instance
|
||||
if (!jit) jit = std::make_unique<jit_compiler>(s_link_table, g_cfg.core.llvm_cpu);
|
||||
if (!jit)
|
||||
{
|
||||
jit = std::make_shared<jit_compiler>(s_link_table, g_cfg.core.llvm_cpu);
|
||||
}
|
||||
|
||||
// First function in current module part
|
||||
const auto fstart = fpos;
|
||||
@@ -1230,16 +1314,17 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
{
|
||||
semaphore_lock lock(jmutex);
|
||||
jit->add(cache_path + obj_name);
|
||||
|
||||
LOG_SUCCESS(PPU, "LLVM: Loaded module %s", obj_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create worker thread for compilation
|
||||
jthreads.emplace_back([&jit, &jmutex, &jcores, obj_name = obj_name, part = std::move(part), &cache_path]()
|
||||
jthreads.emplace_back([&jit, &jcores, obj_name = obj_name, part = std::move(part), &cache_path, &fragment_sync, findex = ::size32(jthreads)]()
|
||||
{
|
||||
// Set low priority
|
||||
thread_ctrl::set_native_priority(-1);
|
||||
|
||||
|
||||
// Allocate "core"
|
||||
{
|
||||
semaphore_lock jlock(jcores);
|
||||
@@ -1251,7 +1336,7 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
|
||||
// Use another JIT instance
|
||||
jit_compiler jit2({}, g_cfg.core.llvm_cpu);
|
||||
ppu_initialize2(jit2, part, cache_path, obj_name);
|
||||
ppu_initialize2(jit2, part, cache_path, obj_name, findex, fragment_sync);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped() || !fs::is_file(cache_path + obj_name))
|
||||
@@ -1259,12 +1344,15 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
return;
|
||||
}
|
||||
|
||||
// Proceed with original JIT instance
|
||||
// Proceed with original JIT instance
|
||||
semaphore_lock lock(jmutex);
|
||||
jit->add(cache_path + obj_name);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize fragment count sync var
|
||||
fragment_sync.exchange(::size32(jthreads));
|
||||
|
||||
// Join worker threads
|
||||
for (auto& thread : jthreads)
|
||||
{
|
||||
@@ -1278,8 +1366,10 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
|
||||
// Jit can be null if the loop doesn't ever enter.
|
||||
if (jit && jit_mod.vars.empty())
|
||||
{
|
||||
{
|
||||
semaphore_lock lock(jmutex);
|
||||
jit->fin();
|
||||
|
||||
// Get and install function addresses
|
||||
for (const auto& func : info.funcs)
|
||||
{
|
||||
@@ -1346,7 +1436,7 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name)
|
||||
static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, atomic_t<u32>& fragment_sync)
|
||||
{
|
||||
#ifdef LLVM_AVAILABLE
|
||||
using namespace llvm;
|
||||
@@ -1356,7 +1446,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||
|
||||
// Initialize target
|
||||
module->setTargetTriple(Triple::normalize(sys::getProcessTriple()));
|
||||
|
||||
|
||||
// Initialize translator
|
||||
PPUTranslator translator(jit.get_context(), module.get(), module_part);
|
||||
|
||||
@@ -1429,13 +1519,16 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||
|
||||
if (module_part.funcs[fi].size)
|
||||
{
|
||||
// Update dialog
|
||||
Emu.CallAfter([=, max = module_part.funcs.size()]()
|
||||
// Update dialog
|
||||
Emu.CallAfter([=, max = module_part.funcs.size(), &fragment_sync]()
|
||||
{
|
||||
dlg->ProgressBarSetMsg(0, fmt::format("Compiling %u of %u", fi + 1, fmax));
|
||||
|
||||
if (fi * 100 / fmax != (fi + 1) * 100 / fmax)
|
||||
dlg->ProgressBarInc(0, 1);
|
||||
|
||||
if (u32 fragment_count = fragment_sync.load())
|
||||
dlg->SetMsg(fmt::format("Compiling PPU module (%u of %u):\n%s\nPlease wait...", fragment_index + 1, fragment_count, obj_name));
|
||||
});
|
||||
|
||||
// Translate
|
||||
@@ -1448,7 +1541,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||
{
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1461,10 +1554,13 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||
//mpm.run(*module);
|
||||
|
||||
// Update dialog
|
||||
Emu.CallAfter([=]()
|
||||
Emu.CallAfter([=, &fragment_sync]()
|
||||
{
|
||||
dlg->ProgressBarSetMsg(0, "Generating code, this may take a long time...");
|
||||
dlg->ProgressBarInc(0, 100);
|
||||
|
||||
if (u32 fragment_count = fragment_sync.load())
|
||||
dlg->SetMsg(fmt::format("Compiling PPU module (%u of %u):\n%s\nPlease wait...", fragment_index + 1, fragment_count, obj_name));
|
||||
});
|
||||
|
||||
std::string result;
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 2048;
|
||||
|
||||
virtual void on_spawn() override;
|
||||
virtual void on_init(const std::shared_ptr<void>&) override;
|
||||
virtual std::string get_name() const override;
|
||||
virtual std::string dump() const override;
|
||||
|
||||