Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f3d08a9d4 | |||
| f614151133 | |||
| 7e7d3e658e | |||
| 7b81d19103 | |||
| 9425e22ad0 | |||
| c8b39fe7dd |
@@ -59,6 +59,7 @@ 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/RPCS3/llvm
|
||||
branch = release_60
|
||||
url = https://github.com/llvm-mirror/llvm
|
||||
branch = release_50
|
||||
[submodule "GSL"]
|
||||
path = 3rdparty/GSL
|
||||
url = https://github.com/Microsoft/GSL.git
|
||||
[submodule "libpng"]
|
||||
path = 3rdparty/libpng
|
||||
url = https://github.com/RPCS3/libpng
|
||||
url = https://github.com/Zangetsu38/libpng
|
||||
ignore = dirty
|
||||
[submodule "Vulkan/glslang"]
|
||||
path = Vulkan/glslang
|
||||
@@ -25,6 +25,9 @@
|
||||
[submodule "Utilities/yaml-cpp"]
|
||||
path = Utilities/yaml-cpp
|
||||
url = https://github.com/RPCS3/yaml-cpp
|
||||
[submodule "3rdparty/pugixml"]
|
||||
path = 3rdparty/pugixml
|
||||
url = https://github.com/RPCS3/pugixml
|
||||
[submodule "3rdparty/cereal"]
|
||||
path = 3rdparty/cereal
|
||||
url = https://github.com/USCiLab/cereal.git
|
||||
@@ -33,12 +36,8 @@
|
||||
url = https://github.com/madler/zlib
|
||||
[submodule "3rdparty/hidapi"]
|
||||
path = 3rdparty/hidapi
|
||||
url = https://github.com/RPCS3/hidapi
|
||||
url = https://github.com/Zangetsu38/hidapi
|
||||
branch = master
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/Optional"]
|
||||
path = 3rdparty/Optional
|
||||
url = https://github.com/akrzemi1/Optional.git
|
||||
[submodule "3rdparty/pugixml"]
|
||||
path = 3rdparty/pugixml
|
||||
url = https://github.com/zeux/pugixml
|
||||
|
||||
@@ -22,10 +22,12 @@ 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;
|
||||
@@ -33,16 +35,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 ;
|
||||
travis_wait 60 ./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations --verbose ;
|
||||
./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations ;
|
||||
fi;
|
||||
|
||||
# Install updated libglew-dev since the version provided by trusty is outdated
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
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;
|
||||
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;
|
||||
else
|
||||
brew update;
|
||||
brew install ccache glew llvm40;
|
||||
@@ -52,32 +54,30 @@ 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.10.0/gcc_64/lib/cmake
|
||||
- export CXXFLAGS="$CXXFLAGS -DTRAVIS=true";
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
|
||||
- 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 -G Ninja;
|
||||
- ninja
|
||||
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
|
||||
- make -j 3
|
||||
- # AppImage generation
|
||||
- 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/ ;
|
||||
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.9.1/gcc_64/lib;
|
||||
make DESTDIR=appdir 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.10.0/gcc_64/bin/:${PATH} ;
|
||||
export PATH=~/Qt/5.9.1/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.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 ;
|
||||
cp ~/Qt/5.9.1/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
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,7 +99,6 @@ addons:
|
||||
packages:
|
||||
- binutils
|
||||
- cmake
|
||||
- ninja-build
|
||||
- libasound2-dev
|
||||
- libopenal-dev
|
||||
- freeglut3-dev
|
||||
@@ -109,15 +108,14 @@ addons:
|
||||
- libc6-dev
|
||||
- llvm-4.0
|
||||
- llvm-4.0-dev
|
||||
# Clang 5.0 is now bundled in travis, so we no longer need the ppa version.
|
||||
#- clang-4.0
|
||||
- clang-4.0
|
||||
- libedit-dev
|
||||
- g++-5
|
||||
- gcc-5
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
# We need to install qt 5.10.0 manually because the version trusty provides is too old.
|
||||
# We need to install qt 5.9.1 manually because the version trusty provides is too old.
|
||||
#- qtbase5-dev
|
||||
- libudev-dev
|
||||
- libevdev-dev
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
option(WITH_GDB "WITH_GDB" OFF)
|
||||
option(WITHOUT_LLVM "WITHOUT_LLVM" OFF)
|
||||
|
||||
@@ -20,20 +20,19 @@ If you want to contribute please take a look at the [Coding Style](https://githu
|
||||
## Dependencies
|
||||
|
||||
### Windows
|
||||
* [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)
|
||||
* [Visual Studio 2017](https://www.visualstudio.com/en/downloads/)
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2017](https://go.microsoft.com/fwlink/?LinkId=746572)
|
||||
* [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.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)
|
||||
* [Qt 5.9+](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)
|
||||
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
|
||||
|
||||
### Linux
|
||||
* [Qt 5.7+](https://www.qt.io/download-open-source/)
|
||||
* [Qt 5.9+](https://www.qt.io/download-open-source/)
|
||||
* GCC 5.1+ or Clang 3.5.0+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691))
|
||||
* 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`
|
||||
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-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`
|
||||
* Fedora: `sudo dnf install cmake qt5-devel vulkan-devel glew glew-devel`
|
||||
**If you have a NVIDIA GPU, you may need to install the libglvnd package.**
|
||||
|
||||
### MacOS
|
||||
@@ -48,23 +47,15 @@ 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.8\msvc2015_64\` </br>
|
||||
|
||||
|
||||
Open `rpcs3.sln`
|
||||
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.9.1\msvc2017_64\` </br>
|
||||
|
||||
*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.8\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.9.1\msvc2015_64`. </br>
|
||||
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
### Building the projects
|
||||
You may want to download precompiled [LLVM lib](https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8) and extract to root rpcs3 folder (which contains `rpcs3.sln`), as well as download and extract [additional libs](https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U) to `lib\%CONFIGURATION%-x64\` to speed up compilation time (unoptimised/debug libs are currently not available precompiled).
|
||||
|
||||
If you're not using precompiled libs, build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*. </br></br>
|
||||
|
||||
`Build > Build Solution`</br>
|
||||
|
||||
1) Build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*. </br>
|
||||
2) Press *BUILD* > *Build Solution* or *Rebuild Solution*. </br>
|
||||
|
||||
|
||||
## Building on Linux & Mac OS:
|
||||
|
||||
@@ -470,7 +470,7 @@ struct se_storage<T, 16, 16>
|
||||
|
||||
static inline v128 swap(const v128& src)
|
||||
{
|
||||
return v128::from64(se_storage<u64>::swap(src._u64[1]), se_storage<u64>::swap(src._u64[0]));
|
||||
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)));
|
||||
}
|
||||
|
||||
static inline v128 to(const T& src)
|
||||
|
||||
@@ -202,12 +202,9 @@ 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)
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace cfg
|
||||
bool m_value;
|
||||
|
||||
public:
|
||||
bool def;
|
||||
const bool def;
|
||||
|
||||
_bool(node* owner, const std::string& name, bool def = false)
|
||||
: _base(type::_bool, owner, name)
|
||||
@@ -150,11 +150,6 @@ namespace cfg
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(const bool& value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
};
|
||||
|
||||
// Value node with fixed set of possible values, each maps to an enum value of type T.
|
||||
@@ -222,7 +217,7 @@ namespace cfg
|
||||
int_type m_value;
|
||||
|
||||
public:
|
||||
int_type def;
|
||||
const int_type def;
|
||||
|
||||
_int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)))
|
||||
: _base(type::_int, owner, name)
|
||||
@@ -258,11 +253,6 @@ namespace cfg
|
||||
return false;
|
||||
}
|
||||
|
||||
void set(const s64& value)
|
||||
{
|
||||
m_value = static_cast<int_type>(value);
|
||||
}
|
||||
|
||||
std::vector<std::string> to_list() const override
|
||||
{
|
||||
return make_int_range(Min, Max);
|
||||
@@ -281,7 +271,7 @@ namespace cfg
|
||||
std::string m_value;
|
||||
|
||||
public:
|
||||
std::string def;
|
||||
const std::string def;
|
||||
|
||||
string(node* owner, const std::string& name, const std::string& def = {})
|
||||
: _base(type::string, owner, name)
|
||||
|
||||
@@ -75,25 +75,10 @@ static time_t to_time(const FILETIME& ft)
|
||||
|
||||
static FILETIME from_time(s64 _time)
|
||||
{
|
||||
const ullong wtime = (_time + 11644473600ULL) * 10000000ULL;
|
||||
FILETIME result;
|
||||
|
||||
if (_time <= -11644473600ll)
|
||||
{
|
||||
result.dwLowDateTime = 0;
|
||||
result.dwHighDateTime = 0;
|
||||
}
|
||||
else if (_time > INT64_MAX / 10000000ll - 11644473600ll)
|
||||
{
|
||||
result.dwLowDateTime = 0xffffffff;
|
||||
result.dwHighDateTime = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ullong wtime = (_time + 11644473600ull) * 10000000ull;
|
||||
result.dwLowDateTime = static_cast<DWORD>(wtime);
|
||||
result.dwHighDateTime = static_cast<DWORD>(wtime >> 32);
|
||||
}
|
||||
|
||||
result.dwLowDateTime = static_cast<DWORD>(wtime);
|
||||
result.dwHighDateTime = static_cast<DWORD>(wtime >> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -111,8 +96,6 @@ static fs::error to_error(DWORD e)
|
||||
case ERROR_INVALID_NAME: return fs::error::inval;
|
||||
case ERROR_SHARING_VIOLATION: return fs::error::acces;
|
||||
case ERROR_DIR_NOT_EMPTY: return fs::error::notempty;
|
||||
case ERROR_NOT_READY: return fs::error::noent;
|
||||
//case ERROR_INVALID_PARAMETER: return fs::error::inval;
|
||||
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
@@ -123,7 +106,6 @@ static fs::error to_error(DWORD e)
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/file.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
@@ -955,13 +937,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
return;
|
||||
}
|
||||
|
||||
if (test(mode & fs::unshare) && ::flock(fd, LOCK_EX | LOCK_NB) != 0)
|
||||
{
|
||||
g_tls_error = errno == EWOULDBLOCK ? fs::error::acces : to_error(errno);
|
||||
::close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
class unix_file final : public file_base, public get_native_handle
|
||||
{
|
||||
const int m_fd;
|
||||
@@ -1034,7 +1009,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,12 +1233,7 @@ bool fs::dir::open(const std::string& path)
|
||||
}
|
||||
|
||||
struct ::stat file_info;
|
||||
|
||||
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);
|
||||
}
|
||||
verify("dir::read" HERE), ::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) == 0;
|
||||
|
||||
info.name = found->d_name;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -1363,7 +1333,7 @@ std::string fs::get_data_dir(const std::string& prefix, const std::string& locat
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
buf.push_back(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -422,7 +422,7 @@ namespace fs
|
||||
|
||||
class iterator
|
||||
{
|
||||
const dir* m_parent;
|
||||
dir* m_parent;
|
||||
dir_entry m_entry;
|
||||
|
||||
public:
|
||||
@@ -432,7 +432,7 @@ namespace fs
|
||||
from_current
|
||||
};
|
||||
|
||||
iterator(const dir* parent, mode mode_ = mode::from_first)
|
||||
iterator(dir* parent, mode mode_ = mode::from_first)
|
||||
: m_parent(parent)
|
||||
{
|
||||
if (!m_parent)
|
||||
@@ -458,7 +458,7 @@ namespace fs
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
*this = {m_parent, mode::from_current};
|
||||
*this = { m_parent, mode::from_current };
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -468,14 +468,14 @@ namespace fs
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin() const
|
||||
iterator begin()
|
||||
{
|
||||
return {m_dir ? this : nullptr};
|
||||
return{ m_dir ? this : nullptr };
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
iterator end()
|
||||
{
|
||||
return {nullptr};
|
||||
return{ nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "JIT.h"
|
||||
@@ -49,11 +47,6 @@ static void* const s_memory = []() -> void*
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
LLVMLinkInMCJIT();
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
auto ptr = ::mmap(nullptr, s_memory_size, PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1, 0);
|
||||
if (ptr != MAP_FAILED)
|
||||
return ptr;
|
||||
#else
|
||||
for (u64 addr = 0x10000000; addr <= 0x80000000 - s_memory_size; addr += 0x1000000)
|
||||
{
|
||||
if (auto ptr = utils::memory_reserve(s_memory_size, (void*)addr))
|
||||
@@ -61,7 +54,6 @@ static void* const s_memory = []() -> void*
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return utils::memory_reserve(s_memory_size);
|
||||
}();
|
||||
@@ -71,8 +63,6 @@ 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
|
||||
@@ -89,30 +79,7 @@ extern void jit_finalize()
|
||||
|
||||
s_unwind.clear();
|
||||
#else
|
||||
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();
|
||||
// TODO: unregister EH frames if necessary
|
||||
#endif
|
||||
|
||||
utils::memory_decommit(s_memory, s_memory_size);
|
||||
@@ -196,7 +163,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return {addr, llvm::JITSymbolFlags::Exported};
|
||||
}
|
||||
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
virtual u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
@@ -217,7 +184,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
virtual 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);
|
||||
@@ -242,7 +209,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return (u8*)std::exchange(s_next, (void*)next);
|
||||
}
|
||||
|
||||
bool finalizeMemory(std::string* = nullptr) override
|
||||
virtual bool finalizeMemory(std::string* = nullptr) override
|
||||
{
|
||||
// Lock memory manager
|
||||
writer_lock lock(s_mutex);
|
||||
@@ -259,7 +226,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
|
||||
return false;
|
||||
}
|
||||
|
||||
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
virtual void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Lock memory manager
|
||||
@@ -286,15 +253,16 @@ 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);
|
||||
}
|
||||
|
||||
void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
virtual void deregisterEHFrames() override
|
||||
{
|
||||
LOG_ERROR(GENERAL, "deregisterEHFrames() called"); // Not expected
|
||||
|
||||
return RTDyldMemoryManager::deregisterEHFrames();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -308,7 +276,7 @@ struct EventListener : llvm::JITEventListener
|
||||
{
|
||||
}
|
||||
|
||||
void NotifyObjectEmitted(const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& inf) override
|
||||
virtual 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)
|
||||
@@ -404,7 +372,7 @@ public:
|
||||
};
|
||||
|
||||
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, std::string _cpu)
|
||||
: m_link(_link)
|
||||
: m_link(std::move(_link))
|
||||
, m_cpu(std::move(_cpu))
|
||||
{
|
||||
if (m_cpu.empty())
|
||||
|
||||
@@ -4,19 +4,15 @@
|
||||
#include "sema.h"
|
||||
|
||||
#include "Utilities/sysinfo.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "rpcs3_version.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <chrono>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
@@ -45,7 +41,6 @@ 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;
|
||||
@@ -54,32 +49,23 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
|
||||
namespace logs
|
||||
{
|
||||
// Memory-mapped buffer size
|
||||
constexpr u64 s_log_size = 32 * 1024 * 1024;
|
||||
constexpr std::size_t s_log_size = 128 * 1024 * 1024;
|
||||
constexpr std::size_t s_log_size_s = s_log_size / 2;
|
||||
constexpr std::size_t s_log_size_t = s_log_size / 4 + s_log_size_s;
|
||||
constexpr std::size_t s_log_size_e = s_log_size / 8 + s_log_size_t;
|
||||
constexpr std::size_t s_log_size_f = s_log_size / 16 + s_log_size_e;
|
||||
|
||||
class file_writer
|
||||
{
|
||||
fs::file m_file;
|
||||
std::string m_name;
|
||||
std::thread m_writer;
|
||||
fs::file m_fout;
|
||||
fs::file m_fout2;
|
||||
u64 m_max_size;
|
||||
|
||||
#ifdef _WIN32
|
||||
::HANDLE m_fmap;
|
||||
#endif
|
||||
atomic_t<std::size_t> m_pos{0};
|
||||
std::size_t m_size{0};
|
||||
uchar* m_fptr{};
|
||||
z_stream m_zs{};
|
||||
semaphore<> m_m;
|
||||
|
||||
alignas(128) atomic_t<u64> m_buf{0}; // MSB (40 bit): push begin, LSB (24 bis): push size
|
||||
alignas(128) atomic_t<u64> m_out{0}; // Amount of bytes written to file
|
||||
|
||||
uchar m_zout[65536];
|
||||
|
||||
// Write buffered logs immediately
|
||||
bool flush(u64 bufv);
|
||||
|
||||
public:
|
||||
file_writer(const std::string& name);
|
||||
@@ -133,7 +119,7 @@ namespace logs
|
||||
static file_listener* get_logger()
|
||||
{
|
||||
// Use magic static
|
||||
static file_listener logger("RPCS3");
|
||||
static file_listener logger("RPCS3.log");
|
||||
return &logger;
|
||||
}
|
||||
|
||||
@@ -305,45 +291,13 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u
|
||||
logs::file_writer::file_writer(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
const std::string log_name = fs::get_config_dir() + name + ".log";
|
||||
const std::string buf_name = fs::get_config_dir() + name + ".buf";
|
||||
|
||||
try
|
||||
{
|
||||
if (!m_file.open(buf_name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
|
||||
if (!m_file.open(fs::get_config_dir() + name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
|
||||
{
|
||||
if (fs::g_tls_error == fs::error::acces)
|
||||
{
|
||||
if (fs::exists(buf_name))
|
||||
{
|
||||
fmt::throw_exception("Another instance of %s is running. Close it or kill its process, if necessary.", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Cannot create %s.log (access denied)."
|
||||
#ifdef _WIN32
|
||||
"\nNote that %s cannot be installed in Program Files or similar directory with limited permissions."
|
||||
#else
|
||||
"\nPlease, check %s permissions in '~/.config/'."
|
||||
#endif
|
||||
, name, name);
|
||||
}
|
||||
}
|
||||
|
||||
fmt::throw_exception("Cannot create %s.log (error %s)", name, fs::g_tls_error);
|
||||
fmt::throw_exception("Can't create file %s (error %s)", name, fs::g_tls_error);
|
||||
}
|
||||
|
||||
// Check free space
|
||||
fs::device_stat stats{};
|
||||
if (!fs::statfs(fs::get_config_dir(), stats) || stats.avail_free < s_log_size * 8)
|
||||
{
|
||||
fmt::throw_exception("Not enough free space (%f KB)", stats.avail_free / 1000000.);
|
||||
}
|
||||
|
||||
// Limit log size to ~25% of free space
|
||||
m_max_size = stats.avail_free / 4;
|
||||
|
||||
// Initialize memory mapped file
|
||||
#ifdef _WIN32
|
||||
m_fmap = CreateFileMappingW(m_file.get_handle(), 0, PAGE_READWRITE, s_log_size >> 32, s_log_size & 0xffffffff, 0);
|
||||
m_fptr = m_fmap ? (uchar*)MapViewOfFile(m_fmap, FILE_MAP_WRITE, 0, 0, 0) : nullptr;
|
||||
@@ -353,94 +307,44 @@ logs::file_writer::file_writer(const std::string& name)
|
||||
#endif
|
||||
|
||||
verify(name.c_str()), m_fptr;
|
||||
std::memset(m_fptr, '\n', s_log_size);
|
||||
|
||||
// Rotate backups (TODO)
|
||||
fs::remove_file(fs::get_config_dir() + name + "1.log.gz");
|
||||
fs::remove_file(fs::get_config_dir() + name + "1.gz");
|
||||
fs::create_dir(fs::get_config_dir() + "old_logs");
|
||||
fs::rename(fs::get_config_dir() + m_name + ".log.gz", fs::get_config_dir() + "old_logs/" + m_name + ".log.gz", true);
|
||||
|
||||
// Actual log file (allowed to fail)
|
||||
m_fout.open(log_name, fs::rewrite);
|
||||
|
||||
// Compressed log
|
||||
if (!m_fout2.open(log_name + ".gz", fs::rewrite) || deflateInit2(&m_zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
{
|
||||
m_fout2.close();
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::thread([text = std::string{e.what()}]{ report_fatal_error(text); }).detach();
|
||||
return;
|
||||
fs::rename(fs::get_config_dir() + m_name + ".gz", fs::get_config_dir() + "old_logs/" + m_name + ".gz", true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::thread([]{ report_fatal_error("Unknown error" HERE); }).detach();
|
||||
return;
|
||||
catch_all_exceptions();
|
||||
}
|
||||
|
||||
m_writer = std::thread([this]()
|
||||
{
|
||||
thread_ctrl::set_native_priority(-1);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const u64 bufv = m_buf;
|
||||
|
||||
if (bufv & 0xffffff)
|
||||
{
|
||||
// Wait if threads are writing logs
|
||||
std::this_thread::yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flush(bufv))
|
||||
{
|
||||
if (m_out == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logs::file_writer::~file_writer()
|
||||
{
|
||||
if (!m_fptr)
|
||||
if (m_size == 0)
|
||||
{
|
||||
return;
|
||||
m_size = std::min<std::size_t>(+m_pos, s_log_size);
|
||||
}
|
||||
|
||||
// Stop writer thread
|
||||
while (m_out << 24 < m_buf)
|
||||
// Compress
|
||||
z_stream zs{};
|
||||
if (deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY) == Z_OK)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
auto buf = std::make_unique<uchar[]>(s_log_size);
|
||||
zs.avail_in = ::narrow<u32>(m_size);
|
||||
zs.avail_out = s_log_size;
|
||||
zs.next_in = m_fptr;
|
||||
zs.next_out = buf.get();
|
||||
|
||||
m_out = -1;
|
||||
m_writer.join();
|
||||
|
||||
if (m_fout2)
|
||||
{
|
||||
m_zs.avail_in = 0;
|
||||
m_zs.next_in = nullptr;
|
||||
|
||||
do
|
||||
if (deflate(&zs, Z_FINISH) != Z_STREAM_ERROR)
|
||||
{
|
||||
m_zs.avail_out = sizeof(m_zout);
|
||||
m_zs.next_out = m_zout;
|
||||
|
||||
if (deflate(&m_zs, Z_FINISH) == Z_STREAM_ERROR || m_fout2.write(m_zout, sizeof(m_zout) - m_zs.avail_out) != sizeof(m_zout) - m_zs.avail_out)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fs::file(fs::get_config_dir() + m_name + ".gz", fs::rewrite).write(buf.get(), zs.total_out);
|
||||
}
|
||||
while (m_zs.avail_out == 0);
|
||||
|
||||
deflateEnd(&m_zs);
|
||||
if (deflateEnd(&zs) != Z_OK)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -449,109 +353,33 @@ logs::file_writer::~file_writer()
|
||||
#else
|
||||
::munmap(m_fptr, s_log_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool logs::file_writer::flush(u64 bufv)
|
||||
{
|
||||
semaphore_lock lock(m_m);
|
||||
|
||||
const u64 st = +m_out;
|
||||
const u64 end = std::min<u64>((st + s_log_size) & ~(s_log_size - 1), bufv >> 24);
|
||||
|
||||
if (end > st)
|
||||
{
|
||||
// Avoid writing too big fragments
|
||||
const u64 size = std::min<u64>(end - st, sizeof(m_zout) / 2);
|
||||
|
||||
// Write uncompressed
|
||||
if (m_fout && st < m_max_size && m_fout.write(m_fptr + st % s_log_size, size) != size)
|
||||
{
|
||||
m_fout.close();
|
||||
}
|
||||
|
||||
// Write compressed
|
||||
if (m_fout2 && st < m_max_size)
|
||||
{
|
||||
m_zs.avail_in = size;
|
||||
m_zs.next_in = m_fptr + st % s_log_size;
|
||||
|
||||
do
|
||||
{
|
||||
m_zs.avail_out = sizeof(m_zout);
|
||||
m_zs.next_out = m_zout;
|
||||
|
||||
if (deflate(&m_zs, Z_NO_FLUSH) == Z_STREAM_ERROR || m_fout2.write(m_zout, sizeof(m_zout) - m_zs.avail_out) != sizeof(m_zout) - m_zs.avail_out)
|
||||
{
|
||||
deflateEnd(&m_zs);
|
||||
m_fout2.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (m_zs.avail_out == 0);
|
||||
}
|
||||
|
||||
m_out += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
m_file.trunc(m_size);
|
||||
}
|
||||
|
||||
void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
|
||||
{
|
||||
if (!m_fptr)
|
||||
// Adaptive log limit
|
||||
const auto lim =
|
||||
sev >= logs::level::success ? s_log_size_s :
|
||||
sev == logs::level::todo ? s_log_size_t :
|
||||
sev == logs::level::error ? s_log_size_e : s_log_size_f;
|
||||
|
||||
if (m_pos >= lim)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: write bigger fragment directly in blocking manner
|
||||
while (size && size <= 0xffffff)
|
||||
// Acquire memory
|
||||
const auto pos = m_pos.fetch_add(size);
|
||||
|
||||
// Write if possible
|
||||
if (pos + size <= s_log_size)
|
||||
{
|
||||
u64 bufv;
|
||||
|
||||
const auto pos = m_buf.atomic_op([&](u64& v) -> uchar*
|
||||
{
|
||||
const u64 v1 = v >> 24;
|
||||
const u64 v2 = v & 0xffffff;
|
||||
|
||||
if (UNLIKELY(v2 + size > 0xffffff || v1 + v2 + size >= m_out + s_log_size))
|
||||
{
|
||||
bufv = v;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v += size;
|
||||
return m_fptr + (v1 + v2) % s_log_size;
|
||||
});
|
||||
|
||||
if (UNLIKELY(!pos))
|
||||
{
|
||||
if ((bufv & 0xffffff) + size > 0xffffff || bufv & 0xffffff)
|
||||
{
|
||||
// Concurrency limit reached
|
||||
std::this_thread::yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Queue is full, need to write out
|
||||
flush(bufv);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pos + size > m_fptr + s_log_size)
|
||||
{
|
||||
const auto frag = m_fptr + s_log_size - pos;
|
||||
std::memcpy(pos, text, frag);
|
||||
std::memcpy(m_fptr, text + frag, size - frag);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(pos, text, size);
|
||||
}
|
||||
|
||||
m_buf += (u64{size} << 24) - size;
|
||||
break;
|
||||
std::memcpy(m_fptr + pos, text, size);
|
||||
}
|
||||
else if (pos <= s_log_size)
|
||||
{
|
||||
m_size = pos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,7 +417,6 @@ 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,12 +24,6 @@ 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,9 +6,7 @@
|
||||
#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>
|
||||
@@ -18,12 +16,6 @@
|
||||
#ifdef __APPLE__
|
||||
#define _XOPEN_SOURCE
|
||||
#define __USE_GNU
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/thread_policy.h>
|
||||
#endif
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
#include <pthread_np.h>
|
||||
#define cpu_set_t cpuset_t
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
@@ -39,6 +31,32 @@ thread_local u64 g_tls_fault_all = 0;
|
||||
thread_local u64 g_tls_fault_rsx = 0;
|
||||
thread_local u64 g_tls_fault_spu = 0;
|
||||
|
||||
static void report_fatal_error(const std::string& msg)
|
||||
{
|
||||
static semaphore<> g_report_only_once;
|
||||
|
||||
g_report_only_once.wait();
|
||||
|
||||
std::string _msg = msg + "\n"
|
||||
"HOW TO REPORT ERRORS: https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support\n"
|
||||
"Please, don't send incorrect reports. Thanks for understanding.\n";
|
||||
|
||||
#ifdef _WIN32
|
||||
_msg += "\nPress Yes or Enter to visit the URL above immediately.";
|
||||
const std::size_t buf_size = _msg.size() + 1;
|
||||
const int size = static_cast<int>(buf_size);
|
||||
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]);
|
||||
MultiByteToWideChar(CP_UTF8, 0, _msg.c_str(), size, buffer.get(), size);
|
||||
|
||||
if (MessageBoxW(0, buffer.get(), L"Fatal error", MB_ICONERROR | MB_YESNO) == IDYES)
|
||||
{
|
||||
ShellExecuteW(0, L"open", L"https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support", 0, 0, SW_SHOWNORMAL);
|
||||
}
|
||||
#else
|
||||
std::printf("Fatal error: \n%s", _msg.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
[[noreturn]] void catch_all_exceptions()
|
||||
{
|
||||
try
|
||||
@@ -53,6 +71,8 @@ thread_local u64 g_tls_fault_spu = 0;
|
||||
{
|
||||
report_fatal_error("Unhandled exception (unknown)");
|
||||
}
|
||||
|
||||
std::abort();
|
||||
}
|
||||
|
||||
enum x64_reg_t : u32
|
||||
@@ -965,8 +985,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;
|
||||
}
|
||||
@@ -1471,11 +1491,13 @@ const bool s_exception_handler_set = []() -> bool
|
||||
if (!AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)exception_handler))
|
||||
{
|
||||
report_fatal_error("AddVectoredExceptionHandler() failed.");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (!SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exception_filter))
|
||||
{
|
||||
report_fatal_error("SetUnhandledExceptionFilter() failed.");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1522,6 +1544,7 @@ static void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
|
||||
// TODO (debugger interaction)
|
||||
report_fatal_error(fmt::format("Segfault %s location %p at %p.", cause, info->si_addr, RIP(context)));
|
||||
std::abort();
|
||||
}
|
||||
|
||||
const bool s_exception_handler_set = []() -> bool
|
||||
@@ -1549,8 +1572,6 @@ 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
|
||||
@@ -1747,7 +1768,7 @@ bool thread_ctrl::_wait_for(u64 usec)
|
||||
}
|
||||
}
|
||||
}
|
||||
while (_this->m_cond.wait(_lock, std::exchange(usec, usec > cond_variable::max_timeout ? -1 : 0)));
|
||||
while (_this->m_cond.wait(_lock, std::exchange(usec, usec == -1 ? -1 : 0)));
|
||||
|
||||
// Timeout
|
||||
return false;
|
||||
@@ -1857,156 +1878,38 @@ 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
|
||||
HANDLE _this_thread = GetCurrentThread();
|
||||
INT native_priority = THREAD_PRIORITY_NORMAL;
|
||||
|
||||
if (priority > 0)
|
||||
switch (priority)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
native_priority = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||
if (priority < 0)
|
||||
break;
|
||||
case -1:
|
||||
native_priority = THREAD_PRIORITY_BELOW_NORMAL;
|
||||
|
||||
if (!SetThreadPriority(_this_thread, native_priority))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "SetThreadPriority() failed: 0x%x", GetLastError());
|
||||
break;
|
||||
}
|
||||
#else
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
|
||||
pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
|
||||
if (priority > 0)
|
||||
param.sched_priority = sched_get_priority_max(policy);
|
||||
if (priority < 0)
|
||||
param.sched_priority = sched_get_priority_min(policy);
|
||||
|
||||
if (int err = pthread_setschedparam(pthread_self(), policy, ¶m))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "pthraed_setschedparam() failed: %d", err);
|
||||
}
|
||||
SetThreadPriority(_this_thread, native_priority);
|
||||
#endif
|
||||
}
|
||||
|
||||
void thread_ctrl::set_thread_affinity_mask(u16 mask)
|
||||
void thread_ctrl::set_ideal_processor_core(int core)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE _this_thread = GetCurrentThread();
|
||||
SetThreadAffinityMask(_this_thread, (DWORD_PTR)mask);
|
||||
#elif __APPLE__
|
||||
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);
|
||||
|
||||
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);
|
||||
SetThreadIdealProcessor(_this_thread, core);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
named_thread::named_thread()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -10,29 +10,9 @@
|
||||
#include "sema.h"
|
||||
#include "cond.h"
|
||||
|
||||
// Report error and call std::abort(), defined in main.cpp
|
||||
[[noreturn]] void report_fatal_error(const std::string&);
|
||||
|
||||
// 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
|
||||
{
|
||||
@@ -108,9 +88,6 @@ 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;
|
||||
|
||||
@@ -254,17 +231,8 @@ 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);
|
||||
|
||||
// Sets the preferred affinity mask for this thread
|
||||
static void set_thread_affinity_mask(u16 mask);
|
||||
static void set_ideal_processor_core(int core);
|
||||
};
|
||||
|
||||
class named_thread
|
||||
|
||||
@@ -32,23 +32,13 @@ void patch_engine::append(const std::string& patch)
|
||||
{
|
||||
if (fs::file f{patch})
|
||||
{
|
||||
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;
|
||||
}
|
||||
auto root = YAML::Load(f.to_string());
|
||||
|
||||
for (auto pair : root)
|
||||
{
|
||||
auto& name = pair.first.Scalar();
|
||||
auto& data = m_map[name];
|
||||
|
||||
|
||||
for (auto patch : pair.second)
|
||||
{
|
||||
u64 type64 = 0;
|
||||
@@ -101,7 +91,7 @@ void patch_engine::append(const std::string& patch)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data.emplace_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
bool cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
|
||||
{
|
||||
verify(HERE), _old != -1; // Very unlikely: it requires 2^32 distinct threads to wait simultaneously
|
||||
const bool is_inf = _timeout > max_timeout;
|
||||
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = _timeout * -10;
|
||||
|
||||
if (HRESULT rc = NtWaitForKeyedEvent(nullptr, &m_value, false, is_inf ? nullptr : &timeout))
|
||||
if (HRESULT rc = NtWaitForKeyedEvent(nullptr, &m_value, false, _timeout == -1 ? nullptr : &timeout))
|
||||
{
|
||||
verify(HERE), rc == WAIT_TIMEOUT;
|
||||
|
||||
@@ -38,12 +37,12 @@ bool cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
|
||||
|
||||
for (u32 value = _old + 1;; value = m_value)
|
||||
{
|
||||
const int err = futex((int*)&m_value.raw(), FUTEX_WAIT_PRIVATE, value, is_inf ? nullptr : &timeout, nullptr, 0) == 0
|
||||
const int err = futex((int*)&m_value.raw(), FUTEX_WAIT_PRIVATE, value, _timeout == -1 ? nullptr : &timeout, nullptr, 0) == 0
|
||||
? 0
|
||||
: errno;
|
||||
|
||||
// Normal or timeout wakeup
|
||||
if (!err || (!is_inf && err == ETIMEDOUT))
|
||||
if (!err || (_timeout != -1 && err == ETIMEDOUT))
|
||||
{
|
||||
// Cleanup (remove waiter)
|
||||
verify(HERE), m_value--;
|
||||
|
||||
@@ -47,6 +47,4 @@ public:
|
||||
imp_wake(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr u64 max_timeout = u64{UINT32_MAX} / 1000 * 1000000;
|
||||
};
|
||||
|
||||
@@ -13,10 +13,9 @@ 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 https://rpcs3.net/.
|
||||
rem // https://github.com/RPCS3/rpcs3 and http://rpcs3.net/.
|
||||
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
setlocal ENABLEEXTENSIONS
|
||||
|
||||
set GIT_VERSION_FILE=%~p0..\rpcs3\git-version.h
|
||||
if not defined GIT (
|
||||
@@ -55,33 +54,9 @@ if errorlevel 1 (
|
||||
goto done
|
||||
)
|
||||
|
||||
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 // Echo obtained GIT_VERSION for debug purposes if needed
|
||||
echo %GIT_VERSION%
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set GIT_VERSION=%%I
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%GIT_VERSION%-%%I
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
|
||||
rem // Don't modify the file if it already has the current version.
|
||||
if exist "%GIT_VERSION_FILE%" (
|
||||
@@ -94,7 +69,7 @@ if exist "%GIT_VERSION_FILE%" (
|
||||
echo // This is a generated file. > "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION "%GIT_VERSION%" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH ^"%GIT_BRANCH%^" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH "%GIT_BRANCH%" >> "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo // If you don't want this file to update/recompile, change to 1. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION_NO_UPDATE 0 >> "%GIT_VERSION_FILE%"
|
||||
|
||||
@@ -7,44 +7,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
bool utils::has_ssse3()
|
||||
{
|
||||
static const bool g_value = get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x200;
|
||||
return g_value;
|
||||
}
|
||||
|
||||
bool utils::has_avx()
|
||||
{
|
||||
static const bool g_value = get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x10000000;
|
||||
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
|
||||
static const bool g_value = get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0x4800) == 0x4800;
|
||||
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;
|
||||
@@ -88,21 +50,6 @@ std::string utils::get_system_info()
|
||||
if (has_avx())
|
||||
{
|
||||
result += " | AVX";
|
||||
|
||||
if (has_avx2())
|
||||
{
|
||||
result += '+';
|
||||
}
|
||||
|
||||
if (has_512())
|
||||
{
|
||||
result += '+';
|
||||
}
|
||||
|
||||
if (has_xop())
|
||||
{
|
||||
result += 'x';
|
||||
}
|
||||
}
|
||||
|
||||
if (has_rtm())
|
||||
|
||||
@@ -8,25 +8,29 @@ 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]};
|
||||
}
|
||||
|
||||
bool has_ssse3();
|
||||
inline bool has_ssse3()
|
||||
{
|
||||
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x200;
|
||||
}
|
||||
|
||||
bool has_avx();
|
||||
inline bool has_avx()
|
||||
{
|
||||
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x10000000;
|
||||
}
|
||||
|
||||
bool has_avx2();
|
||||
|
||||
bool has_rtm();
|
||||
|
||||
bool has_512();
|
||||
|
||||
bool has_xop();
|
||||
inline bool has_rtm()
|
||||
{
|
||||
// Check RTM and MPX extensions in order to filter out TSX on Haswell CPUs
|
||||
return get_cpuid(0, 0)[0] >= 0x7 && (get_cpuid(7, 0)[1] & 0x4800) == 0x4800;
|
||||
}
|
||||
|
||||
inline bool transaction_enter()
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define CONCATENATE_DETAIL(x, y) x ## y
|
||||
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
|
||||
|
||||
#define STRINGIZE_DETAIL(x) #x ""
|
||||
#define STRINGIZE_DETAIL(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
|
||||
|
||||
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
|
||||
@@ -534,26 +534,6 @@ inline u64 cntlz64(u64 arg, bool nonzero = false)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u32 cnttz32(u32 arg, bool nonzero = false)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
ulong res;
|
||||
return _BitScanForward(&res, arg) || nonzero ? res : 32;
|
||||
#else
|
||||
return arg || nonzero ? __builtin_ctzll(arg) : 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u64 cnttz64(u64 arg, bool nonzero = false)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
ulong res;
|
||||
return _BitScanForward64(&res, arg) || nonzero ? res : 64;
|
||||
#else
|
||||
return arg || nonzero ? __builtin_ctzll(arg) : 64;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper function, used by ""_u16, ""_u32, ""_u64
|
||||
constexpr u8 to_u8(char c)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#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
|
||||
@@ -850,22 +849,6 @@ 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);
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -39,24 +39,20 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine>
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
|
||||
</NMakeReBuildCommandLine>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m</NMakeBuildCommandLine>
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m</NMakeReBuildCommandLine>
|
||||
<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
|
||||
<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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
@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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</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 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 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 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,100 +1,44 @@
|
||||
version: '0.0.3-{build}'
|
||||
|
||||
version: '{build}'
|
||||
|
||||
image: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
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
|
||||
|
||||
cache:
|
||||
- llvmlibs.7z -> appveyor.yml
|
||||
- vulkan.7z -> appveyor.yml
|
||||
- compat_database.dat
|
||||
|
||||
install:
|
||||
- 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
|
||||
|
||||
- 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
|
||||
|
||||
os: Visual Studio 2017
|
||||
platform: x64
|
||||
|
||||
configuration: Release - LLVM
|
||||
|
||||
build:
|
||||
parallel: true
|
||||
project: rpcs3.sln
|
||||
verbosity: normal
|
||||
|
||||
before_build:
|
||||
- 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
|
||||
|
||||
after_build:
|
||||
- ps: | # remove unnecessary files
|
||||
rm .\bin\rpcs3.exp, .\bin\rpcs3.lib, .\bin\rpcs3.pdb
|
||||
|
||||
- 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"
|
||||
|
||||
clone_folder: C:\rpcs3
|
||||
clone_depth: 3
|
||||
test: off
|
||||
|
||||
artifacts:
|
||||
- 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
|
||||
configuration:
|
||||
# Release
|
||||
- ReleaseLLVM
|
||||
|
||||
on_finish:
|
||||
- ps: | # update appveyor build version, done last to prevent webhook breakage
|
||||
update-appveyorbuild -version $env:AVVER
|
||||
before_build:
|
||||
- ps: $env:Date="$(git show -s --date=short --format='%ad')"
|
||||
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp 3rdparty/cereal 3rdparty/zlib 3rdparty/hidapi 3rdparty/Optional
|
||||
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
|
||||
- 7z x vulkan.7z -aos -oC:\rpcs3\Vulkan > null
|
||||
- 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 CXXFLAGS=-DBRANCH=%BRANCH%
|
||||
- if %configuration%==Release (cmake -G "Visual Studio 15 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
|
||||
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 15 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/lib/cmake/llvm -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
|
||||
|
||||
build_script:
|
||||
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
install:
|
||||
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-BE73aaGDNxdG1PM1JPb0hNeHM" -FileName llvmlibs.7z
|
||||
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
|
||||
- if not exist zlib.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-HVE3xvheVFX05lRFdnZlh5aUU" -FileName zlib.7z
|
||||
- set QTDIR=C:\Qt\5.9.1\msvc2017_64
|
||||
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
|
||||
- set PATH=C:\Program Files (x86)\MSBuild\15.0\Bin;%QTDIR%;%PATH%
|
||||
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
|
||||
|
||||
artifacts:
|
||||
- path: bin
|
||||
name: 'rpcs3-v0.0.3-$(Date)-$(COMMIT_SHA)_win64'
|
||||
type: zip
|
||||
|
||||
cache:
|
||||
- llvmlibs.7z -> appveyor.yml
|
||||
- vulkan.7z -> appveyor.yml
|
||||
- zlib.7z -> appveyor.yml
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
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 */
|
||||
}
|
||||
@@ -40,7 +40,7 @@ QWidget {
|
||||
|
||||
/* Mouse tooltips */
|
||||
QToolTip {
|
||||
border: 0.05em solid #323232;
|
||||
border: 1px solid #323232;
|
||||
background-color: #323232;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
@@ -49,29 +49,29 @@ QToolTip {
|
||||
QHeaderView::section {
|
||||
background-color: #323232;
|
||||
color: #ecf0f1;
|
||||
padding-left: 0.2em;
|
||||
border: 0.05em solid #323232;
|
||||
padding-left: 4px;
|
||||
border: 1px solid #323232;
|
||||
}
|
||||
|
||||
/* Settings Dialog: Tabs */
|
||||
QTabBar::tab {
|
||||
color: #ecf0f1;
|
||||
border: 0.05em solid #444;
|
||||
border: 1px solid #444;
|
||||
border-bottom-style: none;
|
||||
background-color: #333333;
|
||||
padding-left: 0.9em;
|
||||
padding-right: 0.9em;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
margin-right: -0.2em;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
margin-right: -2px;
|
||||
}
|
||||
QTabBar::tab:last {
|
||||
margin-right: 0em;
|
||||
margin-right: 0px;
|
||||
}
|
||||
QTabBar::tab:!selected {
|
||||
color: #b1b1b1;
|
||||
border-bottom-style: solid;
|
||||
margin-top: 0.15em;
|
||||
margin-top: 3px;
|
||||
background-color: #292929;
|
||||
}
|
||||
QTabBar::tab:hover {
|
||||
@@ -81,11 +81,11 @@ QTabBar::tab:hover {
|
||||
|
||||
/* Checkboxes */
|
||||
QCheckBox::indicator {
|
||||
border-radius: 0.1em;
|
||||
border: 0.05em solid #ecf0f1;
|
||||
margin-top: 0.05em;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #ecf0f1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
background-color: #2ecc71; /* Green */
|
||||
@@ -99,11 +99,11 @@ QCheckBox::indicator::disabled {
|
||||
|
||||
/* Radio Buttons */
|
||||
QRadioButton::indicator {
|
||||
border-radius: 0.4em;
|
||||
border: 0.05em solid;
|
||||
border-color: white;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ecf0f1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
QRadioButton::indicator:checked {
|
||||
background-color: #2ecc71; /* Green */
|
||||
@@ -119,10 +119,10 @@ QRadioButton::indicator::disabled {
|
||||
QComboBox {
|
||||
background-color: #404040;
|
||||
color: #fff;
|
||||
border: 0.05em solid #1e1e1e;
|
||||
border-radius: 0.15em;
|
||||
padding-bottom: 0.2em;
|
||||
padding-left: 0.4em;
|
||||
border: 1px solid #1e1e1e;
|
||||
border-radius: 3px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
QComboBox::disabled {
|
||||
background-color: #828790;
|
||||
@@ -131,15 +131,15 @@ QComboBox::disabled {
|
||||
|
||||
/* Group Boxes (Settings Dialog) */
|
||||
QGroupBox {
|
||||
margin-top: 1em;
|
||||
font-size: 8pt;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.3em;
|
||||
margin-top: 17px;
|
||||
font-size: 13px;
|
||||
border: 1px solid #bdc3c7;
|
||||
border-radius: 4px;
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top;
|
||||
padding: 0.3em 0.5em 0.3em 0.5em;
|
||||
subcontrol-position: top center;
|
||||
padding: 5px 10px 5px 10px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -154,19 +154,19 @@ QPushButton::disabled {
|
||||
|
||||
/* Log and Debugger borders */
|
||||
QTextEdit {
|
||||
border: 0.05em solid #828790;
|
||||
border: 1px solid #828790;
|
||||
}
|
||||
|
||||
/* For dock buttons to be visible */
|
||||
QDockWidget::close-button, QDockWidget::float-button {
|
||||
background-color: #bdc3c7;
|
||||
border: 0.05em solid #000;
|
||||
border-radius: 0.3em;
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Disable ugly borders */
|
||||
QTabWidget::pane {
|
||||
border: 0em solid #828790;
|
||||
border: 0px solid #828790;
|
||||
}
|
||||
|
||||
/* Top menu bar */
|
||||
@@ -174,14 +174,14 @@ QMenuBar::item:selected {
|
||||
background: #444444;
|
||||
}
|
||||
QMenu::item {
|
||||
padding-left: 1.5em;
|
||||
padding-right: 0.75em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
padding-left: 20px;
|
||||
padding-right: 15px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background: #444444;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border: 1px solid #bdc3c7;
|
||||
}
|
||||
QMenu::item:disabled {
|
||||
background-color: #444444;
|
||||
@@ -223,7 +223,7 @@ QLabel#color_button {
|
||||
|
||||
/* Seachbar on main toolbar */
|
||||
QLineEdit#mw_searchbar {
|
||||
margin-left: 0.7em;
|
||||
margin-left:14px;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
@@ -241,10 +241,10 @@ QToolButton::hover {
|
||||
|
||||
/* Set Theme UI colors */
|
||||
QLabel#gamelist_icon_background_color {
|
||||
color: transparent;
|
||||
background-color: #323232;
|
||||
}
|
||||
QLabel#gamelist_toolbar_icon_color {
|
||||
color: #828790;
|
||||
background-color: #e3e3e3;
|
||||
}
|
||||
|
||||
/* Set Windows Taskbar Thumbnail colors */
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
/*
|
||||
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 */
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before 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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@@ -39,30 +39,30 @@
|
||||
<NMakePreprocessorDefinitions>
|
||||
</NMakePreprocessorDefinitions>
|
||||
<NMakeBuildCommandLine>
|
||||
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
|
||||
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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
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
|
||||
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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
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
|
||||
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
|
||||
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 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
|
||||
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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>
|
||||
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
|
||||
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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>
|
||||
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
|
||||
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
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -9,8 +9,7 @@ function Controller() {
|
||||
}
|
||||
|
||||
Controller.prototype.WelcomePageCallback = function() {
|
||||
// Wait 10 seconds to load licenses and such.
|
||||
gui.clickButton(buttons.NextButton, 10000);
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
Controller.prototype.CredentialsPageCallback = function() {
|
||||
@@ -33,7 +32,7 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
widget.deselectAll();
|
||||
widget.selectComponent("qt.qt5.5100.gcc_64");
|
||||
widget.selectComponent("qt.591.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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</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 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.13
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjitsrc\asmjit.vcxproj", "{AC40FF01-426E-4838-A317-66354CEFAE88}"
|
||||
EndProject
|
||||
|
||||
@@ -1,48 +1,50 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules")
|
||||
set(RES_FILES "")
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
# Qt section
|
||||
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)
|
||||
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})
|
||||
else()
|
||||
find_package(Qt5 5.7 COMPONENTS DBus Gui)
|
||||
if(Qt5DBus_FOUND)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus Qt5::Network)
|
||||
find_package(Qt5DBus)
|
||||
if (Qt5DBus_FOUND)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus)
|
||||
add_definitions(-DHAVE_QTDBUS)
|
||||
else()
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::Network)
|
||||
set(RPCS3_QT_LIBS Qt5::Widgets)
|
||||
endif()
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
include_directories(${Qt5Widgets_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Let's make sure we have Qt before we continue
|
||||
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")
|
||||
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")
|
||||
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-qt593-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt593-trusty
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-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.8\\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.9\\msvc2017_64\\)")
|
||||
elseif("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
|
||||
else()
|
||||
@@ -55,16 +57,14 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
# To make UI files on cmake 3.7 or less work
|
||||
if(CMAKE_VERION VERSION_LESS 3.8)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
endif()
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
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,18 +101,14 @@ 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 -mrtm)
|
||||
|
||||
if(NOT DEFINED ENV{TRAVIS})
|
||||
add_compile_options(-march=native)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
|
||||
add_compile_options(-msse -msse2 -mcx16 -mssse3 -mrtm)
|
||||
|
||||
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")
|
||||
@@ -120,13 +116,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_CXX_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
|
||||
CHECK_CXX_COMPILER_FLAG("-nopie" HAS_NOPIE)
|
||||
CHECK_C_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
|
||||
CHECK_C_COMPILER_FLAG("-nopie" HAS_NOPIE)
|
||||
|
||||
if(HAS_NO_PIE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
|
||||
@@ -134,11 +130,12 @@ 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()
|
||||
@@ -154,49 +151,44 @@ 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)
|
||||
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 WITHOUT_LLVM)
|
||||
find_package(LLVM 5.0 CONFIG)
|
||||
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 5.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()
|
||||
|
||||
|
||||
@@ -207,17 +199,18 @@ 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(ALSA)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(ALSA alsa)
|
||||
if(ALSA_FOUND)
|
||||
add_definitions(-DHAVE_ALSA)
|
||||
include_directories(SYSTEM ${ALSA_INCLUDE_DIRS})
|
||||
list(APPEND ADDITIONAL_LIBS ${ALSA_LIBRARIES})
|
||||
list(APPEND ADDITIONAL_LIBS ${ALSA_LDFLAGS})
|
||||
endif()
|
||||
endif()
|
||||
if(USE_PULSE)
|
||||
@@ -243,9 +236,6 @@ 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()
|
||||
@@ -272,6 +262,8 @@ else()
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${GLEW_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
"${RPCS3_SRC_DIR}/../3rdparty/pugixml/src"
|
||||
@@ -300,17 +292,17 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(NOT LLVM_FOUND)
|
||||
message("LLVM 4.0 not found. RPCS3 will be compiled without LLVM support.")
|
||||
Message("LLVM 5.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()
|
||||
@@ -329,7 +321,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()
|
||||
|
||||
@@ -341,7 +333,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
|
||||
@@ -352,26 +344,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)
|
||||
@@ -380,29 +372,24 @@ 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} opengl32.lib glu32.lib libpthread)
|
||||
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} 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 swscale.lib png16_static ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
|
||||
target_link_libraries(rpcs3 avformat.lib avcodec.lib avutil.lib swresample.lib swscale.lib png16_static ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
|
||||
else()
|
||||
target_link_libraries(rpcs3 ${OPENAL_LIBRARY} ${OPENGL_LIBRARIES})
|
||||
target_link_libraries(rpcs3 ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
|
||||
if(APPLE)
|
||||
target_link_libraries(rpcs3 hidapi-mac "-framework CoreFoundation" "-framework IOKit")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
@@ -413,57 +400,50 @@ else()
|
||||
if(VULKAN_FOUND)
|
||||
target_link_libraries(rpcs3 ${VULKAN_LIBRARIES})
|
||||
endif()
|
||||
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS} -lpthread ZLIB::ZLIB ${ADDITIONAL_LIBS})
|
||||
if(USE_SYSTEM_FFMPEG)
|
||||
target_link_libraries(rpcs3 ${CMAKE_DL_LIBS} -lpthread ${ZLIB_LIBRARIES} ${ADDITIONAL_LIBS})
|
||||
if (USE_SYSTEM_FFMPEG)
|
||||
link_libraries(${FFMPEG_LIBRARY_DIR})
|
||||
target_link_libraries(rpcs3 libavformat.so libavcodec.so libavutil.so libswscale.so)
|
||||
target_link_libraries(rpcs3 libavformat.so libavcodec.so libavutil.so libswresample.so libswscale.so)
|
||||
else()
|
||||
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswscale.a)
|
||||
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.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_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7))
|
||||
if (CMAKE_COMPILER_IS_GNUCC 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
|
||||
@@ -475,9 +455,4 @@ 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()
|
||||
|
||||
@@ -4,19 +4,27 @@
|
||||
#include "sha1.h"
|
||||
#include "key_vault.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "unpkg.h"
|
||||
|
||||
bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync, const std::string& pkg_filepath)
|
||||
{
|
||||
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
|
||||
|
||||
std::vector<fs::file> filelist;
|
||||
filelist.emplace_back(fs::file{path});
|
||||
u32 cur_file = 0;
|
||||
u64 cur_offset = 0;
|
||||
u64 cur_file_offset = 0;
|
||||
u32 cur_file=0;
|
||||
|
||||
fs::file original_file(pkg_filepath);
|
||||
original_file.seek(pkg_f.pos());
|
||||
|
||||
filelist.push_back(std::move(original_file));
|
||||
|
||||
// Save current file offset (probably zero)
|
||||
const u64 start_offset = pkg_f.pos();
|
||||
u64 cur_offset = start_offset;
|
||||
u64 cur_file_offset = start_offset;
|
||||
|
||||
// Get basic PKG information
|
||||
PKGHeader header;
|
||||
|
||||
auto archive_seek = [&](const s64 new_offset, const fs::seek_mode damode = fs::seek_set)
|
||||
{
|
||||
@@ -65,8 +73,6 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
return num_read;
|
||||
};
|
||||
|
||||
// Get basic PKG information
|
||||
PKGHeader header;
|
||||
|
||||
if (archive_read(&header, sizeof(header)) != sizeof(header))
|
||||
{
|
||||
@@ -102,18 +108,18 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
}
|
||||
}
|
||||
|
||||
if (header.pkg_size > filelist[0].size())
|
||||
if (header.pkg_size > pkg_f.size())
|
||||
{
|
||||
// Check if multi-files pkg
|
||||
if (path.size() < 7 || path.compare(path.size() - 7, 7, "_00.pkg", 7) != 0)
|
||||
//Check if multi-files pkg
|
||||
if (pkg_filepath.length() < 7 || pkg_filepath.substr(pkg_filepath.length() - 7).compare("_00.pkg") != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name_wo_number = path.substr(0, path.size() - 7);
|
||||
u64 cursize = filelist[0].size();
|
||||
while (cursize < header.pkg_size)
|
||||
std::string name_wo_number = pkg_filepath.substr(0, pkg_filepath.length() - 7);
|
||||
u64 cursize = pkg_f.size();
|
||||
while (cursize != header.pkg_size)
|
||||
{
|
||||
std::string archive_filename = fmt::format("%s_%02d.pkg", name_wo_number, filelist.size());
|
||||
|
||||
@@ -125,7 +131,7 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
}
|
||||
|
||||
cursize += archive_file.size();
|
||||
filelist.emplace_back(std::move(archive_file));
|
||||
filelist.push_back(std::move(archive_file));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,12 +143,6 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
|
||||
be_t<u32> drm_type{0};
|
||||
be_t<u32> content_type{0};
|
||||
std::string install_id;
|
||||
|
||||
// Read title ID and use it as an installation directory
|
||||
install_id.resize(9);
|
||||
archive_seek(55);
|
||||
archive_read(&install_id.front(), install_id.size());
|
||||
|
||||
archive_seek(header.pkg_info_off);
|
||||
|
||||
@@ -179,50 +179,18 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA:
|
||||
{
|
||||
if (packet.size > 8)
|
||||
{
|
||||
// Read an actual installation directory (DLC)
|
||||
install_id.resize(packet.size);
|
||||
archive_read(&install_id.front(), packet.size);
|
||||
install_id = install_id.c_str() + 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
archive_seek(packet.size, fs::seek_cur);
|
||||
}
|
||||
|
||||
// If false, an existing directory is being overwritten: cannot cancel the operation
|
||||
bool was_null = true;
|
||||
|
||||
// Get full path and create the directory
|
||||
const std::string dir = Emu.GetHddDir() + "game/" + install_id + '/';
|
||||
|
||||
if (!fs::create_dir(dir))
|
||||
{
|
||||
if (fs::g_tls_error == fs::error::exist)
|
||||
{
|
||||
was_null = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Could not create the installation directory %s", dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate buffer with BUF_SIZE size or more if required
|
||||
const std::unique_ptr<u128[]> buf(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count) / sizeof(u128)]);
|
||||
|
||||
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
||||
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
|
||||
{
|
||||
archive_seek(header.data_offset + offset);
|
||||
archive_seek(start_offset + header.data_offset + offset);
|
||||
|
||||
// Read the data and set available size
|
||||
const u64 read = archive_read(buf.get(), size);
|
||||
@@ -366,16 +334,8 @@ bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
|
||||
if (sync.fetch_add((block_size + 0.0) / header.data_size) < 0.)
|
||||
{
|
||||
if (was_null)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Package installation cancelled: %s", dir);
|
||||
out.close();
|
||||
fs::remove_all(dir, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot cancel the installation
|
||||
sync += 1.;
|
||||
LOG_ERROR(LOADER, "Package installation cancelled: %s", dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,4 +57,4 @@ struct PKGEntry
|
||||
be_t<u32> pad; // Padding (zeros)
|
||||
};
|
||||
|
||||
bool pkg_install(const std::string& path, atomic_t<double>&);
|
||||
bool pkg_install(const class fs::file& pkg_f, const std::string& dir, atomic_t<double>&, const std::string& pkg_filepath);
|
||||
|
||||
@@ -148,40 +148,20 @@ 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);
|
||||
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);
|
||||
}
|
||||
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)
|
||||
@@ -210,32 +190,6 @@ 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)
|
||||
{
|
||||
@@ -246,15 +200,6 @@ 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);
|
||||
@@ -273,16 +218,6 @@ 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);
|
||||
@@ -301,14 +236,6 @@ 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);
|
||||
@@ -363,65 +290,6 @@ 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);
|
||||
@@ -766,19 +634,6 @@ 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);
|
||||
@@ -793,11 +648,6 @@ 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)
|
||||
@@ -1035,22 +885,11 @@ 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.LoadLE(self_f);
|
||||
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
self_f.seek(0);
|
||||
sce_hdr.Load(self_f);
|
||||
}
|
||||
sce_hdr.Load(self_f);
|
||||
|
||||
// Check SCE magic.
|
||||
if (!sce_hdr.CheckMagic())
|
||||
@@ -1060,26 +899,11 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
}
|
||||
|
||||
// Read SELF header.
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
self_hdr.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
self_hdr.LoadLE(self_f);
|
||||
}
|
||||
self_hdr.Load(self_f);
|
||||
|
||||
// Read the APP INFO.
|
||||
self_f.seek(self_hdr.se_appinfooff);
|
||||
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
app_info.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
app_info.LoadLE(self_f);
|
||||
}
|
||||
app_info.Load(self_f);
|
||||
|
||||
// Read ELF header.
|
||||
self_f.seek(self_hdr.se_elfoff);
|
||||
@@ -1102,14 +926,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
{
|
||||
phdr32_arr.emplace_back();
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
phdr32_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
phdr32_arr.back().LoadLE(self_f);
|
||||
}
|
||||
phdr32_arr.back().Load(self_f);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1139,26 +956,12 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < ((isElf32) ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
|
||||
{
|
||||
secinfo_arr.emplace_back();
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
secinfo_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
secinfo_arr.back().LoadLE(self_f);
|
||||
}
|
||||
secinfo_arr.back().Load(self_f);
|
||||
}
|
||||
|
||||
// Read SCE version info.
|
||||
self_f.seek(self_hdr.se_sceveroff);
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
scev_info.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
scev_info.LoadLE(self_f);
|
||||
}
|
||||
scev_info.Load(self_f);
|
||||
|
||||
// Read control info.
|
||||
ctrlinfo_arr.clear();
|
||||
@@ -1169,14 +972,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
{
|
||||
ctrlinfo_arr.emplace_back();
|
||||
ControlInfo &cinfo = ctrlinfo_arr.back();
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
cinfo.Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.LoadLE(self_f);
|
||||
}
|
||||
cinfo.Load(self_f);
|
||||
i += cinfo.size;
|
||||
}
|
||||
|
||||
@@ -1196,14 +992,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
|
||||
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
{
|
||||
shdr32_arr.emplace_back();
|
||||
if (!isVita(sce_hdr))
|
||||
{
|
||||
shdr32_arr.back().Load(self_f);
|
||||
}
|
||||
else
|
||||
{
|
||||
shdr32_arr.back().LoadLE(self_f);
|
||||
}
|
||||
shdr32_arr.back().Load(self_f);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1368,8 +1157,6 @@ 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.
|
||||
@@ -1432,14 +1219,6 @@ 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);
|
||||
|
||||
@@ -1487,16 +1266,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1516,75 +1285,20 @@ fs::file SELFDecrypter::MakeElf(bool isElf32)
|
||||
// Write program headers.
|
||||
for (u32 i = 0; i < elf32_hdr.e_phnum; ++i)
|
||||
{
|
||||
if (elf32_hdr.e_data == 1)
|
||||
{
|
||||
WritePhdrLE(e, phdr32_arr[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePhdr(e, phdr32_arr[i]);
|
||||
}
|
||||
WritePhdr(e, phdr32_arr[i]);
|
||||
}
|
||||
|
||||
if (meta_hdr.section_count != 0)
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
// PHDR type.
|
||||
if (meta_shdr[i].type == 2)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
// 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 += secinfo_arr[i].size;
|
||||
data_buf_offset += meta_shdr[i].data_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1595,14 +1309,7 @@ fs::file SELFDecrypter::MakeElf(bool isElf32)
|
||||
|
||||
for (u32 i = 0; i < elf32_hdr.e_shnum; ++i)
|
||||
{
|
||||
if (elf32_hdr.e_data == 1)
|
||||
{
|
||||
WriteShdrLE(e, shdr32_arr[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteShdr(e, shdr32_arr[i]);
|
||||
}
|
||||
WriteShdr(e, shdr32_arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1717,20 +1424,8 @@ static bool IsSelfElf32(const fs::file& f)
|
||||
|
||||
SceHeader hdr;
|
||||
SelfHeader sh;
|
||||
|
||||
hdr.LoadLE(f);
|
||||
|
||||
if (!isVita(hdr))
|
||||
{
|
||||
f.seek(0);
|
||||
hdr.Load(f);
|
||||
sh.Load(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
sh.LoadLE(f);
|
||||
}
|
||||
|
||||
hdr.Load(f);
|
||||
sh.Load(f);
|
||||
|
||||
// Locate the class byte and check it.
|
||||
u8 elf_class[0x8];
|
||||
@@ -1756,23 +1451,13 @@ static bool CheckDebugSelf(fs::file& s)
|
||||
// Check for DEBUG version.
|
||||
if (key_version == 0x80 || key_version == 0xc0)
|
||||
{
|
||||
|
||||
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(realoffset);
|
||||
s.seek(key_version == 0x80 ? +s.read<be_t<u64>>() : +s.read<le_t<u64>>());
|
||||
|
||||
// Write the real ELF file back.
|
||||
fs::file e = fs::make_stream<std::vector<u8>>();
|
||||
@@ -1875,4 +1560,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,7 +11,6 @@ struct AppInfo
|
||||
u64 padding;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -25,7 +24,6 @@ struct SectionInfo
|
||||
u32 encrypted;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -37,7 +35,6 @@ struct SCEVersionInfo
|
||||
u32 unknown;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
void Show();
|
||||
};
|
||||
|
||||
@@ -95,33 +92,9 @@ 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();
|
||||
};
|
||||
|
||||
@@ -344,7 +317,6 @@ 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; }
|
||||
};
|
||||
@@ -363,7 +335,6 @@ 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>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
||||
@@ -50,8 +50,6 @@ OpenALThread::OpenALThread()
|
||||
{
|
||||
m_format = g_cfg.audio.convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
|
||||
}
|
||||
|
||||
m_buffers = std::make_unique<ALuint[]>(g_cfg.audio.frames);
|
||||
}
|
||||
|
||||
OpenALThread::~OpenALThread()
|
||||
@@ -85,7 +83,7 @@ void OpenALThread::Close()
|
||||
if (alIsSource(m_source))
|
||||
alDeleteSources(1, &m_source);
|
||||
|
||||
alDeleteBuffers(g_cfg.audio.frames, m_buffers.get());
|
||||
alDeleteBuffers(g_al_buffers_count, m_buffers);
|
||||
checkForAlError("alDeleteBuffers");
|
||||
}
|
||||
|
||||
@@ -100,7 +98,7 @@ void OpenALThread::Open(const void* src, int size)
|
||||
alGenSources(1, &m_source);
|
||||
checkForAlError("alGenSources");
|
||||
|
||||
alGenBuffers(g_cfg.audio.frames, m_buffers.get());
|
||||
alGenBuffers(g_al_buffers_count, m_buffers);
|
||||
checkForAlError("alGenBuffers");
|
||||
|
||||
alSourcei(m_source, AL_LOOPING, AL_FALSE);
|
||||
@@ -108,13 +106,13 @@ void OpenALThread::Open(const void* src, int size)
|
||||
|
||||
m_buffer_size = size;
|
||||
|
||||
for (int i = 0; i < g_cfg.audio.frames; ++i)
|
||||
for (uint i = 0; i<g_al_buffers_count; ++i)
|
||||
{
|
||||
alBufferData(m_buffers[i], m_format, src, m_buffer_size, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(m_source, g_cfg.audio.frames, m_buffers.get());
|
||||
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
|
||||
checkForAlError("alSourceQueueBuffers");
|
||||
Play();
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
#include "Emu/Audio/AudioThread.h"
|
||||
#include "3rdparty/OpenAL/include/alext.h"
|
||||
#include <memory>
|
||||
|
||||
class OpenALThread : public AudioThread
|
||||
{
|
||||
private:
|
||||
static const uint g_al_buffers_count = 24;
|
||||
|
||||
ALint m_format;
|
||||
ALuint m_source;
|
||||
std::unique_ptr<ALuint[]> m_buffers;
|
||||
ALuint m_buffers[g_al_buffers_count];
|
||||
ALsizei m_buffer_size;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/GSL.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "ALSAThread.h"
|
||||
@@ -8,12 +9,10 @@
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
static thread_local snd_pcm_t* s_tls_handle{nullptr};
|
||||
static thread_local snd_pcm_hw_params_t* s_tls_hw_params{nullptr};
|
||||
static thread_local snd_pcm_sw_params_t* s_tls_sw_params{nullptr};
|
||||
|
||||
static void error(int err, const char* reason)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "ALSA: %s failed: %s\n", reason, snd_strerror(err));
|
||||
fprintf(stderr, "ALSA: %s failed: %s\n", reason, snd_strerror(err));
|
||||
}
|
||||
|
||||
static bool check(int err, const char* reason)
|
||||
@@ -29,88 +28,55 @@ static bool check(int err, const char* reason)
|
||||
|
||||
ALSAThread::ALSAThread()
|
||||
{
|
||||
snd_pcm_hw_params_t* hw_params{nullptr};
|
||||
|
||||
auto at_ret = gsl::finally([&]()
|
||||
{
|
||||
if (hw_params)
|
||||
{
|
||||
snd_pcm_hw_params_free(hw_params);
|
||||
}
|
||||
});
|
||||
|
||||
if (!check(snd_pcm_open(&s_tls_handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK), "snd_pcm_open"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_malloc(&s_tls_hw_params), "snd_pcm_hw_params_malloc"))
|
||||
if (!check(snd_pcm_hw_params_malloc(&hw_params), "snd_pcm_hw_params_malloc"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_any(s_tls_handle, s_tls_hw_params), "snd_pcm_hw_params_any"))
|
||||
if (!check(snd_pcm_hw_params_any(s_tls_handle, hw_params), "snd_pcm_hw_params_any"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_access(s_tls_handle, s_tls_hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "snd_pcm_hw_params_set_access"))
|
||||
if (!check(snd_pcm_hw_params_set_access(s_tls_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED), "snd_pcm_hw_params_set_access"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_format(s_tls_handle, s_tls_hw_params, g_cfg.audio.convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
|
||||
if (!check(snd_pcm_hw_params_set_format(s_tls_handle, hw_params, g_cfg.audio.convert_to_u16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_FLOAT_LE), "snd_pcm_hw_params_set_format"))
|
||||
return;
|
||||
|
||||
uint rate = 48000;
|
||||
if (!check(snd_pcm_hw_params_set_rate_near(s_tls_handle, s_tls_hw_params, &rate, nullptr), "snd_pcm_hw_params_set_rate_near"))
|
||||
if (!check(snd_pcm_hw_params_set_rate(s_tls_handle, hw_params, 48000, 0), "snd_pcm_hw_params_set_rate_near"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, s_tls_hw_params, g_cfg.audio.downmix_to_2ch ? 2 : 8), "snd_pcm_hw_params_set_channels"))
|
||||
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, hw_params, g_cfg.audio.downmix_to_2ch ? 2 : 8), "snd_pcm_hw_params_set_channels"))
|
||||
return;
|
||||
|
||||
//uint period = 5333;
|
||||
//if (!check(snd_pcm_hw_params_set_period_time_near(s_tls_handle, s_tls_hw_params, &period, nullptr), "snd_pcm_hw_params_set_period_time_near"))
|
||||
// return;
|
||||
|
||||
//if (!check(snd_pcm_hw_params_set_periods(s_tls_handle, s_tls_hw_params, 4, 0), "snd_pcm_hw_params_set_periods"))
|
||||
// return;
|
||||
|
||||
snd_pcm_uframes_t bufsize_frames = g_cfg.audio.frames * 256;
|
||||
snd_pcm_uframes_t period_frames = 256;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_buffer_size_near(s_tls_handle, s_tls_hw_params, &bufsize_frames), "snd_pcm_hw_params_set_buffer_size_near"))
|
||||
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, 8 * 256), "snd_pcm_hw_params_set_buffer_size"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_period_size_near(s_tls_handle, s_tls_hw_params, &period_frames, 0), "snd_pcm_hw_params_set_period_size"))
|
||||
if (!check(snd_pcm_hw_params_set_period_size(s_tls_handle, hw_params, 256, 0), "snd_pcm_hw_params_set_period_size"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params(s_tls_handle, s_tls_hw_params), "snd_pcm_hw_params"))
|
||||
return;
|
||||
//if (!check(snd_pcm_hw_params_set_periods(s_tls_handle, hw_params, 2, 0), "snd_pcm_hw_params_set_periods"))
|
||||
// return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_get_buffer_size(s_tls_hw_params, &bufsize_frames), "snd_pcm_hw_params_get_buffer_size"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_get_period_size(s_tls_hw_params, &period_frames, nullptr), "snd_pcm_hw_params_get_period_size"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_sw_params_malloc(&s_tls_sw_params), "snd_pcm_sw_params_malloc"))
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
if (!check(snd_pcm_sw_params_set_stop_threshold(s_tls_handle, s_tls_sw_params, bufsize_frames), "snd_pcm_sw_params_set_stop_threshold"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_sw_params(s_tls_handle, s_tls_sw_params), "snd_pcm_sw_params"))
|
||||
if (!check(snd_pcm_hw_params(s_tls_handle, hw_params), "snd_pcm_hw_params"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_prepare(s_tls_handle), "snd_pcm_prepare"))
|
||||
return;
|
||||
|
||||
LOG_NOTICE(GENERAL, "ALSA: bufsize_frames=%u, period_frames=%u", bufsize_frames, period_frames);
|
||||
}
|
||||
|
||||
ALSAThread::~ALSAThread()
|
||||
{
|
||||
if (s_tls_sw_params)
|
||||
{
|
||||
snd_pcm_sw_params_free(s_tls_sw_params);
|
||||
}
|
||||
|
||||
if (s_tls_hw_params)
|
||||
{
|
||||
snd_pcm_hw_params_free(s_tls_hw_params);
|
||||
}
|
||||
|
||||
if (s_tls_handle)
|
||||
{
|
||||
snd_pcm_close(s_tls_handle);
|
||||
@@ -139,30 +105,29 @@ void ALSAThread::AddData(const void* src, int size)
|
||||
size /= g_cfg.audio.convert_to_u16 ? 2 : 4;
|
||||
size /= g_cfg.audio.downmix_to_2ch ? 2 : 8;
|
||||
|
||||
int res = snd_pcm_writei(s_tls_handle, src, size);
|
||||
int res;
|
||||
|
||||
if (res == -EAGAIN)
|
||||
while (true)
|
||||
{
|
||||
LOG_WARNING(GENERAL, "ALSA: EAGAIN");
|
||||
return;
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
res = snd_pcm_recover(s_tls_handle, res, 0);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
LOG_WARNING(GENERAL, "ALSA: failed to recover (%d)", res);
|
||||
return;
|
||||
}
|
||||
|
||||
res = snd_pcm_writei(s_tls_handle, src, size);
|
||||
|
||||
if (res == -EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (res == -EPIPE)
|
||||
{
|
||||
snd_pcm_prepare(s_tls_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != size)
|
||||
{
|
||||
LOG_WARNING(GENERAL, "ALSA: error (%d)", res);
|
||||
error(res, "snd_pcm_writei");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void XAudio2Thread::xa27_open()
|
||||
return;
|
||||
}
|
||||
|
||||
s_tls_source_voice->SetVolume(g_cfg.audio.downmix_to_2ch ? 1.0f : 4.0f);
|
||||
s_tls_source_voice->SetVolume(g_cfg.audio.downmix_to_2ch ? 1.0 : 4.0);
|
||||
}
|
||||
|
||||
void XAudio2Thread::xa27_add(const void* src, int size)
|
||||
|
||||
@@ -1,13 +1 @@
|
||||
#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,750 +1 @@
|
||||
#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,7 +3,6 @@
|
||||
#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();
|
||||
@@ -51,13 +50,6 @@ 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;
|
||||
@@ -143,142 +135,107 @@ void mfc_thread::cpu_task()
|
||||
|
||||
if (queue_size)
|
||||
{
|
||||
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& cmd = spu.mfc_queue[0];
|
||||
|
||||
if ((cmd.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) == MFC_PUTQLLUC_CMD)
|
||||
{
|
||||
auto& cmd = spu.mfc_queue[i];
|
||||
auto& data = vm::ps3::_ref<decltype(spu.rdata)>(cmd.eal);
|
||||
const auto to_write = spu._ref<decltype(spu.rdata)>(cmd.lsa & 0x3ffff);
|
||||
|
||||
// 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;
|
||||
cmd.size = 0;
|
||||
no_updates = 0;
|
||||
|
||||
if ((cmd.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) == MFC_PUTQLLUC_CMD)
|
||||
vm::reservation_acquire(cmd.eal, 128);
|
||||
|
||||
// Store unconditionally
|
||||
if (s_use_rtm && utils::transaction_enter())
|
||||
{
|
||||
auto& data = vm::ps3::_ref<decltype(spu.rdata)>(cmd.eal);
|
||||
const auto to_write = spu._ref<decltype(spu.rdata)>(cmd.lsa & 0x3ffff);
|
||||
if (!vm::reader_lock{vm::try_to_lock})
|
||||
{
|
||||
_xabort(0);
|
||||
}
|
||||
|
||||
cmd.size = 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 (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;
|
||||
no_updates = 0;
|
||||
|
||||
vm::reservation_acquire(cmd.eal, 128);
|
||||
|
||||
// Store unconditionally
|
||||
if (s_use_rtm && utils::transaction_enter())
|
||||
if (item.sb & 0x8000)
|
||||
{
|
||||
if (!vm::reader_lock{ vm::try_to_lock })
|
||||
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)
|
||||
{
|
||||
_xabort(0);
|
||||
spu.notify();
|
||||
}
|
||||
|
||||
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 && 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.ch_stall_mask & (1u << cmd.tag)) == 0)
|
||||
{
|
||||
cmd.lsa &= 0x3fff0;
|
||||
|
||||
// try to get the whole list done in one go
|
||||
while (cmd.size != 0)
|
||||
else if (evt & SPU_EVENT_INTR_ENABLED)
|
||||
{
|
||||
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;
|
||||
}
|
||||
spu.state += cpu_flag::suspend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (!cmd.size)
|
||||
{
|
||||
spu.mfc_queue.end_pop();
|
||||
no_updates = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,21 +245,26 @@ void mfc_thread::cpu_task()
|
||||
{
|
||||
// Mask incomplete transfers
|
||||
u32 completed = spu.ch_tag_mask;
|
||||
|
||||
for (u32 i = 0; i < spu.mfc_queue.size(); i++)
|
||||
{
|
||||
for (u32 i = 0; i < spu.mfc_queue.size(); i++)
|
||||
const auto& _cmd = spu.mfc_queue[i];
|
||||
|
||||
if (_cmd.size)
|
||||
{
|
||||
const auto& _cmd = spu.mfc_queue[i];
|
||||
if (_cmd.size)
|
||||
if (spu.ch_tag_upd == 1)
|
||||
{
|
||||
completed &= ~(1u << _cmd.tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
if (completed && spu.ch_tag_upd.exchange(0))
|
||||
{
|
||||
spu.ch_tag_stat.push(spu, completed);
|
||||
no_updates = 0;
|
||||
@@ -311,6 +273,7 @@ void mfc_thread::cpu_task()
|
||||
|
||||
test_state();
|
||||
}
|
||||
|
||||
if (no_updates++)
|
||||
{
|
||||
if (no_updates >= 3)
|
||||
@@ -376,12 +339,3 @@ 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,6 +113,4 @@ public:
|
||||
virtual void cpu_task() override;
|
||||
|
||||
virtual void add_spu(spu_ptr _spu);
|
||||
|
||||
virtual void on_spawn() override;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ extern "C"
|
||||
{
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libswresample/swresample.h"
|
||||
}
|
||||
|
||||
#include "cellPamf.h"
|
||||
|
||||
@@ -57,8 +57,6 @@ void audio_config::on_init(const std::shared_ptr<void>& _this)
|
||||
|
||||
void audio_config::on_task()
|
||||
{
|
||||
thread_ctrl::set_native_priority(1);
|
||||
|
||||
AudioDumper m_dump(g_cfg.audio.dump_to_file ? 2 : 0); // Init AudioDumper for 2 channels if enabled
|
||||
|
||||
float buf2ch[2 * BUFFER_SIZE]{}; // intermediate buffer for 2 channels
|
||||
@@ -339,8 +337,8 @@ void audio_config::on_task()
|
||||
case 8: m_dump.WriteData(&buf8ch, sizeof(buf8ch)); break; // write file data (8 ch)
|
||||
}
|
||||
|
||||
cellAudio.trace("Audio perf: (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
cellAudio.trace("Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -164,8 +164,6 @@ 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 CELL_OK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 cellFontRenderCharGlyphImageVertical()
|
||||
|
||||
@@ -94,7 +94,7 @@ struct content_permission final
|
||||
{
|
||||
try
|
||||
{
|
||||
if (temp.size() > 1)
|
||||
if (!temp.empty())
|
||||
{
|
||||
fs::remove_all(temp);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ s32 cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName, u32 e
|
||||
|
||||
if (dir.size() != 9)
|
||||
{
|
||||
return (s32)CELL_HDDGAME_ERROR_PARAM;
|
||||
return 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 (s32)CELL_HDDGAME_ERROR_CBRESULT;
|
||||
return CELL_HDDGAME_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
// TODO ?
|
||||
@@ -186,7 +186,7 @@ s32 cellHddGameGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
if (!fs::is_dir(local_dir))
|
||||
{
|
||||
return (s32)CELL_HDDGAME_ERROR_FAILURE;
|
||||
return CELL_HDDGAME_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*size = ::narrow<u32>(fs::get_dir_size(local_dir) / 1024);
|
||||
@@ -196,8 +196,7 @@ s32 cellHddGameGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
s32 cellHddGameSetSystemVer()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGame);
|
||||
return CELL_OK;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellHddGameExitBroken()
|
||||
@@ -224,8 +223,7 @@ s32 cellGameDataGetSizeKB(vm::ptr<u32> size)
|
||||
|
||||
s32 cellGameDataSetSystemVer()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGame);
|
||||
return CELL_OK;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
s32 cellGameDataExitBroken()
|
||||
@@ -248,43 +246,51 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
if (!type)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
// 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 (Emu.GetCat() == "DG")
|
||||
const std::string& category = psf::get_string(sfo, "CATEGORY");
|
||||
|
||||
if (category == "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 (dirName) strcpy_trunc(*dirName, ""); // ???
|
||||
|
||||
if (!fxm::make<content_permission>("", psf::load_object(fs::file(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")))))
|
||||
if (!fxm::make<content_permission>("", std::move(sfo)))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else if (Emu.GetCat() == "GD")
|
||||
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")
|
||||
{
|
||||
*type = CELL_GAME_GAMETYPE_DISC;
|
||||
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
||||
if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); // ???
|
||||
|
||||
if (!fxm::make<content_permission>("", psf::load_object(fs::file(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")))))
|
||||
if (!fxm::make<content_permission>("", std::move(sfo)))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*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;
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@@ -304,16 +310,18 @@ error_code cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> r
|
||||
size->sysSizeKB = 0;
|
||||
}
|
||||
|
||||
if (Emu.GetCat() != "GD")
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO")));
|
||||
|
||||
if (psf::get_string(sfo, "CATEGORY") != "GD")
|
||||
{
|
||||
return CELL_GAME_ERROR_NOTPATCH;
|
||||
}
|
||||
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), psf::load_object(fs::file(vfs::get("/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")))))
|
||||
if (!fxm::make<content_permission>(Emu.GetTitleID(), std::move(sfo)))
|
||||
{
|
||||
return CELL_GAME_ERROR_BUSY;
|
||||
}
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -321,9 +329,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 || (type != CELL_GAME_GAMETYPE_DISC && !dirName))
|
||||
if ((type - 1) >= 3)
|
||||
{
|
||||
return {CELL_GAME_ERROR_PARAM, type};
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
if (size)
|
||||
@@ -367,7 +375,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;
|
||||
@@ -404,7 +412,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;
|
||||
}
|
||||
|
||||
@@ -412,7 +420,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)
|
||||
{
|
||||
@@ -421,7 +429,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;
|
||||
@@ -431,7 +439,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");
|
||||
|
||||
@@ -444,7 +452,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(Emu.GetCat() == "DG" ? "/dev_bdvd/PS3_GAME/PARAM.SFO"s : "/dev_hdd0/game/" + Emu.GetTitleID() + "/PARAM.SFO")));
|
||||
psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO")));
|
||||
|
||||
cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL;
|
||||
cbGet->getParam.parentalLevel = psf::get_integer(sfo, "PARENTAL_LEVEL", 0);
|
||||
@@ -456,58 +464,52 @@ 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)
|
||||
{
|
||||
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());
|
||||
|
||||
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; 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);
|
||||
|
||||
//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 (!fs::is_dir(vdir))
|
||||
{
|
||||
return {CELL_GAME_ERROR_INTERNAL, dir};
|
||||
cellGame.fatal("directory where param.sfo is to be created does not exist");
|
||||
return CELL_GAME_ERROR_INTERNAL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -657,11 +659,6 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
|
||||
{
|
||||
cellGame.warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
|
||||
|
||||
if (!buf || bufsize == 0)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto prm = fxm::get<content_permission>();
|
||||
|
||||
if (!prm)
|
||||
@@ -688,11 +685,6 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
|
||||
{
|
||||
cellGame.warning("cellGameSetParamString(id=%d, buf=*0x%x)", id, buf);
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto prm = fxm::get<content_permission>();
|
||||
|
||||
if (!prm)
|
||||
@@ -717,7 +709,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;
|
||||
}
|
||||
|
||||
psf::assign(prm->sfo, key, psf::string(max_size, buf.get_ptr()));
|
||||
prm->sfo.emplace(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;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ s32 cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->vendor_id[i] = current_info.vendor_id[i];
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->product_id[i] = current_info.product_id[i];
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->status[i] = current_info.status[i];
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr<CellMouseInfoTablet> info)
|
||||
|
||||
info->is_supported = 0; // Unimplemented: (0=Tablet mode is not supported)
|
||||
info->mode = 1; // Unimplemented: (1=Mouse mode)
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
|
||||
MouseData& current_data = handler->GetData(port_no);
|
||||
data->update = current_data.update;
|
||||
data->buttons = current_data.buttons;
|
||||
@@ -134,27 +134,22 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
|
||||
|
||||
s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
|
||||
{
|
||||
sys_io.todo("cellMouseGetDataList(port_no=%d, data=0x%x", port_no, data);
|
||||
if (g_cfg.io.mouse == mouse_handler::null)
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
else
|
||||
{
|
||||
data->list_num = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellMouseSetTabletMode(u32 port_no, u32 mode)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellMouseGetTabletDataList(u32 port_no, u32 data_addr)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
#include "cellMsgDialog.h"
|
||||
@@ -24,7 +23,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const MsgDialogType _type = {type ^ CELL_MSGDIALOG_TYPE_BG_INVISIBLE};
|
||||
const MsgDialogType _type = { type };
|
||||
|
||||
switch (_type.button_type.unshifted())
|
||||
{
|
||||
@@ -61,6 +60,13 @@ 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
|
||||
@@ -75,33 +81,6 @@ 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)
|
||||
@@ -234,33 +213,6 @@ 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)
|
||||
@@ -268,6 +220,10 @@ 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)
|
||||
@@ -287,14 +243,6 @@ 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)
|
||||
@@ -315,20 +263,6 @@ 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)
|
||||
@@ -336,7 +270,7 @@ s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::cptr<char> msgStrin
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
if (progressBarIndex >= dlg->type.progress_bar_count)
|
||||
if (progressBarIndex >= dlg->type.progress_bar_count || !msgString)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_PARAM;
|
||||
}
|
||||
@@ -353,15 +287,6 @@ 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)
|
||||
@@ -386,15 +311,6 @@ 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,7 +84,6 @@ 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,37 +266,21 @@ error_code cellGameUpdateTerm()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartAsync(ppu_thread& ppu, vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartAsync(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(ppu_thread& ppu, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckFinishAsync(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(ppu_thread& ppu, vm::ptr<CellGameUpdateCallback> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsync(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;
|
||||
}
|
||||
|
||||
@@ -306,37 +290,21 @@ error_code cellGameUpdateCheckAbort()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellGameUpdateCheckStartAsyncEx(ppu_thread& ppu, vm::cptr<CellGameUpdateParam> param, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartAsyncEx(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(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckFinishAsyncEx(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(ppu_thread& ppu, vm::ptr<CellGameUpdateCallbackEx> cb_func, vm::ptr<void> userdata)
|
||||
error_code cellGameUpdateCheckStartWithoutDialogAsyncEx(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,15 +45,14 @@ 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
|
||||
|
||||
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;
|
||||
auto& pads = handler->GetPads();
|
||||
auto pad = pads[port_no];
|
||||
|
||||
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;
|
||||
@@ -66,7 +65,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;
|
||||
}
|
||||
|
||||
@@ -79,18 +78,19 @@ 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;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const 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))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
auto pad = pads[port_no];
|
||||
|
||||
u16 d1Initial, d2Initial;
|
||||
d1Initial = pad->m_digital_1;
|
||||
d2Initial = pad->m_digital_2;
|
||||
@@ -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,6 +235,7 @@ 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)
|
||||
{
|
||||
@@ -265,7 +266,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)
|
||||
{
|
||||
@@ -327,7 +328,7 @@ s32 cellPadPeriphGetInfo(vm::ptr<CellPadPeriphInfo> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
// TODO: Support other types of controllers
|
||||
for (u32 i = 0; i < CELL_PAD_MAX_PORT_NUM; ++i)
|
||||
@@ -336,7 +337,6 @@ 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,11 +359,7 @@ s32 cellPadPeriphGetData(u32 port_no, vm::ptr<CellPadPeriphData> data)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
// todo: support for 'unique' controllers, which goes in offsets 24+ in padData
|
||||
@@ -390,11 +386,7 @@ 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;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
// TODO: This is used just to get data from a BD/CEC remote,
|
||||
@@ -422,11 +414,7 @@ s32 cellPadSetActDirect(u32 port_no, vm::ptr<CellPadActParam> param)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
handler->SetRumble(port_no, param->motor[1], param->motor[0] > 0);
|
||||
@@ -450,7 +438,7 @@ s32 cellPadGetInfo(vm::ptr<CellPadInfo> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
for (u32 i=0; i<CELL_MAX_PADS; ++i)
|
||||
{
|
||||
@@ -482,7 +470,7 @@ s32 cellPadGetInfo2(vm::ptr<CellPadInfo2> info)
|
||||
info->now_connect = rinfo.now_connect;
|
||||
info->system_info = rinfo.system_info;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
for (u32 i=0; i<CELL_PAD_MAX_PORT_NUM; ++i)
|
||||
{
|
||||
@@ -512,15 +500,13 @@ s32 cellPadGetCapabilityInfo(u32 port_no, vm::ptr<CellCapabilityInfo> info)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
//Should return the same as device capability mask, psl1ght has it backwards in pad->h
|
||||
info->info[0] = pad->m_device_capability;
|
||||
info->info[0] = pads[port_no]->m_device_capability;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -538,15 +524,12 @@ s32 cellPadSetPortSetting(u32 port_no, u32 port_setting)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
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))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
pads[port_no]->m_port_setting = port_setting;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -563,14 +546,12 @@ s32 cellPadInfoPressMode(u32 port_no)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return (pad->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) > 0;
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
return (pads[port_no]->m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE) > 0;
|
||||
}
|
||||
|
||||
s32 cellPadInfoSensorMode(u32 port_no)
|
||||
@@ -586,14 +567,12 @@ s32 cellPadInfoSensorMode(u32 port_no)
|
||||
|
||||
if (port_no >= rinfo.max_connect)
|
||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
if (port_no >= rinfo.now_connect)
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
|
||||
return (pad->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) > 0;
|
||||
const auto& pads = handler->GetPads();
|
||||
|
||||
return (pads[port_no]->m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE) > 0;
|
||||
}
|
||||
|
||||
s32 cellPadSetPressMode(u32 port_no, u32 mode)
|
||||
@@ -612,17 +591,15 @@ 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;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
if (mode)
|
||||
pad->m_port_setting |= CELL_PAD_SETTING_PRESS_ON;
|
||||
pads[port_no]->m_port_setting |= CELL_PAD_SETTING_PRESS_ON;
|
||||
else
|
||||
pad->m_port_setting &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
pads[port_no]->m_port_setting &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -643,17 +620,15 @@ 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;
|
||||
|
||||
const auto& pads = handler->GetPads();
|
||||
const auto pad = pads[port_no];
|
||||
auto& pads = handler->GetPads();
|
||||
|
||||
if (mode)
|
||||
pad->m_port_setting |= CELL_PAD_SETTING_SENSOR_ON;
|
||||
pads[port_no]->m_port_setting |= CELL_PAD_SETTING_SENSOR_ON;
|
||||
else
|
||||
pad->m_port_setting &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return CELL_PAD_ERROR_NO_DEVICE;
|
||||
pads[port_no]->m_port_setting &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -686,16 +661,12 @@ 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;
|
||||
|
||||
// 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;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellPadLddUnregisterController(s32 handle)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
@@ -21,16 +20,6 @@ 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);
|
||||
@@ -49,81 +38,39 @@ s32 cellPhotoRegistFromFile()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportInitialize(u32 version, u32 container, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportInitialize()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportInitialize2(u32 version, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportInitialize2()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportFinalize(vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportFinalize()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportFromFile(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellPhotoExportSetParam> param, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportFromFile()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportFromFileWithCopy(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellPhotoExportSetParam> param, vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportFromFileWithCopy()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellPhotoExportProgress(vm::ptr<CellPhotoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellPhotoExportProgress()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellPhotoExport);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
#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;
|
||||
@@ -58,40 +46,15 @@ struct CellRecParam
|
||||
|
||||
using CellRecCallback = void(s32 recStatus, s32 recError, vm::ptr<void> userdata);
|
||||
|
||||
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)
|
||||
s32 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;
|
||||
}
|
||||
|
||||
error_code cellRecClose(s32 isDiscard)
|
||||
s32 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;
|
||||
}
|
||||
|
||||
@@ -100,31 +63,15 @@ void cellRecGetInfo(s32 info, vm::ptr<u64> pValue)
|
||||
cellRec.todo("cellRecGetInfo(info=0x%x, pValue=*0x%x)", info, pValue);
|
||||
}
|
||||
|
||||
error_code cellRecStop()
|
||||
s32 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;
|
||||
}
|
||||
|
||||
error_code cellRecStart()
|
||||
s32 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;
|
||||
}
|
||||
|
||||
@@ -134,7 +81,7 @@ u32 cellRecQueryMemSize(vm::cptr<CellRecParam> pParam)
|
||||
return 1 * 1024 * 1024; // dummy memory size
|
||||
}
|
||||
|
||||
error_code cellRecSetInfo(s32 setInfo, u64 value)
|
||||
s32 cellRecSetInfo(s32 setInfo, u64 value)
|
||||
{
|
||||
cellRec.todo("cellRecSetInfo(setInfo=0x%x, value=0x%x)", setInfo, value);
|
||||
return CELL_OK;
|
||||
|
||||
@@ -37,8 +37,7 @@ enum : u32
|
||||
SAVEDATA_OP_FIXED_SAVE = 6,
|
||||
SAVEDATA_OP_FIXED_LOAD = 7,
|
||||
|
||||
SAVEDATA_OP_LIST_DELETE = 13,
|
||||
SAVEDATA_OP_FIXED_DELETE = 14,
|
||||
SAVEDATA_OP_FIXED_DELETE = 14,
|
||||
};
|
||||
|
||||
namespace
|
||||
@@ -53,7 +52,6 @@ namespace
|
||||
CellSaveDataStatSet statSet;
|
||||
CellSaveDataFileGet fileGet;
|
||||
CellSaveDataFileSet fileSet;
|
||||
CellSaveDataDoneGet doneGet;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,12 +81,11 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
vm::ptr<CellSaveDataStatSet> statSet = g_savedata_context.ptr(&savedata_context::statSet);
|
||||
vm::ptr<CellSaveDataFileGet> fileGet = g_savedata_context.ptr(&savedata_context::fileGet);
|
||||
vm::ptr<CellSaveDataFileSet> fileSet = g_savedata_context.ptr(&savedata_context::fileSet);
|
||||
vm::ptr<CellSaveDataDoneGet> doneGet = g_savedata_context.ptr(&savedata_context::doneGet);
|
||||
|
||||
//TODO: get current user ID
|
||||
// userId(0) = CELL_SYSUTIL_USERID_CURRENT
|
||||
// path of the specified user (00000001 by default)
|
||||
const std::string base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u));
|
||||
const std::string& base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u));
|
||||
|
||||
result->userdata = userdata; // probably should be assigned only once (allows the callback to change it)
|
||||
|
||||
@@ -101,9 +98,9 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
listGet->dirNum = 0;
|
||||
listGet->dirListNum = 0;
|
||||
listGet->dirList.set(setBuf->buf.addr());
|
||||
std::memset(listGet->reserved, 0, sizeof(listGet->reserved));
|
||||
memset(listGet->reserved, 0, sizeof(listGet->reserved));
|
||||
|
||||
const auto prefix_list = fmt::split(setList->dirNamePrefix.get_ptr(), {"|"});
|
||||
const auto prefix_list = fmt::split(setList->dirNamePrefix.get_ptr(), { "|" });
|
||||
|
||||
// get the saves matching the supplied prefix
|
||||
for (auto&& entry : fs::dir(base_dir))
|
||||
@@ -152,7 +149,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");
|
||||
u64 iconSize = icon.size();
|
||||
u32 iconSize = icon.size();
|
||||
std::vector<uchar> iconData;
|
||||
icon.read(iconData, iconSize);
|
||||
save_entry2.iconBuf = iconData;
|
||||
@@ -207,11 +204,10 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
auto& dir = *dir_list++;
|
||||
strcpy_trunc(dir.dirName, entry.dirName);
|
||||
strcpy_trunc(dir.listParam, entry.listParam);
|
||||
std::memset(dir.reserved, 0, sizeof(dir.reserved));
|
||||
memset(dir.reserved, 0, sizeof(dir.reserved));
|
||||
}
|
||||
|
||||
s32 selected = -1;
|
||||
s32 focused = -1;
|
||||
|
||||
if (funcList)
|
||||
{
|
||||
@@ -221,14 +217,14 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
if (result->result < 0)
|
||||
{
|
||||
//TODO: display dialog
|
||||
cellSaveData.warning("savedata_op(): funcList returned result=%d.", result->result);
|
||||
cellSaveData.warning("savedata_op(): funcList returned < 0.");
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
// if the callback has returned ok, lets return OK.
|
||||
// typically used at game launch when no list is actually required.
|
||||
// CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM is only valid for funcFile and funcDone
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -247,6 +243,19 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
return true;
|
||||
}), save_entries.end());
|
||||
|
||||
// Add any new data (not currently supported by the UI)
|
||||
//if (listSet->newData)
|
||||
//{
|
||||
// SaveDataEntry *_saveDataEntry = new SaveDataEntry();
|
||||
// _saveDataEntry->dirName = listSet->newData->dirName.get_ptr();
|
||||
|
||||
// save_entry.dirName = listSet->newData->dirName.get_ptr();
|
||||
// save_entries.emplace_back(*_saveDataEntry);
|
||||
//}
|
||||
|
||||
// Focus save data
|
||||
s32 focused = -1;
|
||||
|
||||
switch (const u32 pos_type = listSet->focusPosition)
|
||||
{
|
||||
case CELL_SAVEDATA_FOCUSPOS_DIRNAME:
|
||||
@@ -314,49 +323,22 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
return CELL_SAVEDATA_ERROR_PARAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto delete_save = [&](const std::string& del_path)
|
||||
{
|
||||
strcpy_trunc(doneGet->dirName, save_entries[selected].dirName);
|
||||
doneGet->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB
|
||||
doneGet->sizeKB = 0;
|
||||
doneGet->excResult = CELL_OK;
|
||||
std::memset(doneGet->reserved, 0, sizeof(doneGet->reserved));
|
||||
// Display Save Data List but do so asynchronously in the GUI thread.
|
||||
bool hasNewData = (bool)listSet->newData; // newData
|
||||
atomic_t<bool> dlg_result(false);
|
||||
|
||||
const fs::dir _dir{del_path};
|
||||
|
||||
for (auto&& file : _dir)
|
||||
Emu.CallAfter([&]()
|
||||
{
|
||||
if (!file.is_directory)
|
||||
{
|
||||
doneGet->sizeKB += ::align(file.size, 4096);
|
||||
selected = Emu.GetCallbacks().get_save_dialog()->ShowSaveDataList(save_entries, focused, hasNewData, listSet);
|
||||
dlg_result = true;
|
||||
});
|
||||
|
||||
if (!fs::remove_file(del_path + file.name))
|
||||
{
|
||||
doneGet->excResult = CELL_SAVEDATA_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_dir)
|
||||
while (!dlg_result)
|
||||
{
|
||||
doneGet->excResult = CELL_SAVEDATA_ERROR_NODATA;
|
||||
thread_ctrl::wait_for(1000);
|
||||
}
|
||||
|
||||
if (!doneGet->excResult && !fs::remove_dir(del_path))
|
||||
{
|
||||
doneGet->excResult = CELL_SAVEDATA_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
funcDone(ppu, result, doneGet);
|
||||
};
|
||||
|
||||
while (funcList)
|
||||
{
|
||||
// Display Save Data List asynchronously in the GUI thread.
|
||||
selected = Emu.GetCallbacks().get_save_dialog()->ShowSaveDataList(save_entries, focused, operation, listSet);
|
||||
|
||||
// UI returns -1 for new save games
|
||||
if (selected == -1)
|
||||
{
|
||||
@@ -369,29 +351,6 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
return CELL_CANCEL;
|
||||
}
|
||||
|
||||
if (operation == SAVEDATA_OP_LIST_DELETE)
|
||||
{
|
||||
delete_save(base_dir + save_entries[selected].dirName + '/');
|
||||
|
||||
if (result->result < 0)
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): funcDone returned result=%d.", result->result);
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
// CELL_SAVEDATA_CBRESULT_OK_NEXT expected
|
||||
save_entries.erase(save_entries.cbegin() + selected);
|
||||
focused = save_entries.empty() ? -1 : selected;
|
||||
selected = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (funcFixed)
|
||||
@@ -400,7 +359,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
funcFixed(ppu, result, listGet, fixedSet);
|
||||
|
||||
// skip all following steps if OK_LAST
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
@@ -411,8 +370,8 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
// depends on fixedSet->option
|
||||
// 0 = none
|
||||
// 1 = skip confirmation dialog
|
||||
|
||||
cellSaveData.warning("savedata_op(): funcFixed returned result=%d.", result->result);
|
||||
|
||||
cellSaveData.warning("savedata_op(): funcFixed returned < 0.");
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
@@ -435,18 +394,6 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
save_entry.dirName = fixedSet->dirName.get_ptr();
|
||||
}
|
||||
|
||||
if (operation == SAVEDATA_OP_FIXED_DELETE)
|
||||
{
|
||||
delete_save(base_dir + save_entries[selected].dirName + '/');
|
||||
|
||||
if (result->result < 0)
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): funcDone_ returned result=%d.", result->result);
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected >= 0)
|
||||
@@ -557,15 +504,15 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
|
||||
if (result->result < 0)
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): funcStat returned result=%d.", result->result);
|
||||
cellSaveData.warning("savedata_op(): funcStat returned 0x%x", result->result);
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST || result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM)
|
||||
if (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
if (statSet->setParam)
|
||||
{
|
||||
// Update PARAM.SFO
|
||||
@@ -587,7 +534,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;
|
||||
//}
|
||||
@@ -597,7 +544,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
case CELL_SAVEDATA_RECREATE_NO:
|
||||
{
|
||||
//CELL_SAVEDATA_RECREATE_NO = overwrite and let the user know, not data is corrupt.
|
||||
//cellSaveData.error("Savedata %s considered broken", save_entry.dirName);
|
||||
//cellSaveData.error("Savedata %s considered broken", save_entry.dirName);
|
||||
//TODO: if this is a save, and it's not auto, then show a dialog
|
||||
// fallthrough
|
||||
}
|
||||
@@ -644,7 +591,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
|
||||
// Create save directory if necessary
|
||||
if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path))
|
||||
{
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): failed to create %s", dir_path);
|
||||
return CELL_SAVEDATA_ERROR_ACCESS_ERROR;
|
||||
}
|
||||
@@ -660,7 +607,7 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
|
||||
if (result->result < 0)
|
||||
{
|
||||
cellSaveData.warning("savedata_op(): funcFile returned result=%d.", result->result);
|
||||
cellSaveData.warning("savedata_op(): funcFile returned < 0.");
|
||||
return CELL_SAVEDATA_ERROR_CBRESULT;
|
||||
}
|
||||
|
||||
@@ -724,16 +671,11 @@ 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("Failed to open file %s%s", dir_path, file_path);
|
||||
cellSaveData.error("savedata file not found");
|
||||
return CELL_SAVEDATA_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
file.seek(fileSet->fileOffset);
|
||||
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);
|
||||
fileGet->excSize = static_cast<u32>(file.read(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -741,9 +683,7 @@ 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);
|
||||
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()));
|
||||
fileGet->excSize = static_cast<u32>(file.write(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
file.trunc(file.pos()); // truncate
|
||||
break;
|
||||
}
|
||||
@@ -759,9 +699,7 @@ 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);
|
||||
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()));
|
||||
fileGet->excSize = static_cast<u32>(file.write(fileSet->fileBuf.get_ptr(), std::min<u32>(fileSet->fileSize, fileSet->fileBufSize)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -782,8 +720,9 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
static NEVER_INLINE s32 savedata_get_list_item(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB, u32 userId)
|
||||
s32 static NEVER_INLINE save_op_get_list_item(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB, u32 userId)
|
||||
{
|
||||
|
||||
//TODO: accurately get the current user
|
||||
if (userId == 0)
|
||||
{
|
||||
@@ -867,6 +806,7 @@ s32 cellSaveDataListLoad(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf
|
||||
version, setList, setBuf, funcList, funcStat, funcFile, container);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_LIST_LOAD, version, vm::null, 1, setList, setBuf, funcList, vm::null, funcStat, funcFile, container, 2, vm::null, 0, vm::null);
|
||||
|
||||
}
|
||||
|
||||
s32 cellSaveDataFixedSave2(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed,
|
||||
@@ -887,13 +827,14 @@ 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)",
|
||||
version, setList, setBuf, funcFixed, funcStat, funcFile, container);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_FIXED_SAVE, version, vm::null, 1, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, vm::null, 0, vm::null);
|
||||
|
||||
}
|
||||
|
||||
s32 cellSaveDataFixedLoad(ppu_thread& ppu, u32 version, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed,
|
||||
@@ -973,10 +914,10 @@ s32 cellSaveDataDelete(u32 container)
|
||||
|
||||
s32 cellSaveDataFixedDelete(ppu_thread& ppu, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.warning("cellSaveDataFixedDelete(setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)",
|
||||
cellSaveData.todo("cellSaveDataFixedDelete(setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)",
|
||||
setList, setBuf, funcFixed, funcDone, container, userdata);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_FIXED_DELETE, 0, vm::null, 1, setList, setBuf, vm::null, funcFixed, vm::null, vm::null, container, 2, userdata, 0, funcDone);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSaveDataUserListSave(ppu_thread& ppu, u32 version, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncStat funcStat, PFuncFile funcFile, u32 container, vm::ptr<void> userdata)
|
||||
@@ -1045,24 +986,26 @@ s32 cellSaveDataUserListAutoLoad(ppu_thread& ppu, u32 version, u32 userId, u32 e
|
||||
|
||||
s32 cellSaveDataUserFixedDelete(ppu_thread& ppu, u32 userId, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.error("cellSaveDataUserFixedDelete(userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)",
|
||||
cellSaveData.todo("cellSaveDataUserFixedDelete(userId=%d, setList=*0x%x, setBuf=*0x%x, funcFixed=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)",
|
||||
userId, setList, setBuf, funcFixed, funcDone, container, userdata);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_FIXED_DELETE, 0, vm::null, 1, setList, setBuf, vm::null, funcFixed, vm::null, vm::null, container, 6, userdata, userId, funcDone);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellSaveDataEnableOverlay(s32 enable)
|
||||
{
|
||||
cellSaveData.error("cellSaveDataEnableOverlay(enable=%d)", enable);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
UNIMPLEMENTED_FUNC(cellSaveData);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_LIST_DELETE, 0, vm::null, 0, setList, setBuf, funcList, vm::null, vm::null, vm::null, container, 0x40, userdata, 0, funcDone);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSaveDataListImport(ppu_thread& ppu, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
@@ -1096,15 +1039,15 @@ s32 cellSaveDataFixedExport(ppu_thread& ppu, vm::cptr<char> dirName, u32 maxSize
|
||||
s32 cellSaveDataGetListItem(vm::cptr<char> dirName, vm::ptr<CellSaveDataDirStat> dir, vm::ptr<CellSaveDataSystemFileParam> sysFileParam, vm::ptr<u32> bind, vm::ptr<u32> sizeKB)
|
||||
{
|
||||
cellSaveData.warning("cellSavaDataGetListItem(dirName=%s, dir=*0x%x, sysFileParam=*0x%x, bind=*0x%x, sizeKB=*0x%x)", dirName, dir, sysFileParam, bind, sizeKB);
|
||||
|
||||
return savedata_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, 0);
|
||||
|
||||
return save_op_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, 0);
|
||||
}
|
||||
|
||||
s32 cellSaveDataUserListDelete(ppu_thread& ppu, u32 userId, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
{
|
||||
cellSaveData.error("cellSaveDataUserListDelete(userId=%d, setList=*0x%x, setBuf=*0x%x, funcList=*0x%x, funcDone=*0x%x, container=0x%x, userdata=*0x%x)", userId, setList, setBuf, funcList, funcDone, container, userdata);
|
||||
UNIMPLEMENTED_FUNC(cellSaveData);
|
||||
|
||||
return savedata_op(ppu, SAVEDATA_OP_LIST_DELETE, 0, vm::null, 0, setList, setBuf, funcList, vm::null, vm::null, vm::null, container, 0x40, userdata, userId, funcDone);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellSaveDataUserListImport(ppu_thread& ppu, u32 userId, PSetList setList, u32 maxSizeKB, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||
@@ -1139,7 +1082,7 @@ s32 cellSaveDataUserGetListItem(u32 userId, vm::cptr<char> dirName, vm::ptr<Cell
|
||||
{
|
||||
cellSaveData.warning("cellSavaDataGetListItem(dirName=%s, dir=*0x%x, sysFileParam=*0x%x, bind=*0x%x, sizeKB=*0x%x, userID=*0x%x)", dirName, dir, sysFileParam, bind, sizeKB, userId);
|
||||
|
||||
return savedata_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, userId);
|
||||
return save_op_get_list_item(dirName, dir, sysFileParam, bind, sizeKB, userId);
|
||||
}
|
||||
|
||||
void cellSysutil_SaveData_init()
|
||||
|
||||
@@ -291,5 +291,5 @@ class SaveDialogBase
|
||||
public:
|
||||
virtual ~SaveDialogBase();
|
||||
|
||||
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet) = 0;
|
||||
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, bool isSaving, vm::ptr<CellSaveDataListSet> listSet) = 0;
|
||||
};
|
||||
|
||||
@@ -1,422 +1,138 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellSearch.h"
|
||||
#include "cellSysutil.h"
|
||||
|
||||
logs::channel cellSearch("cellSearch");
|
||||
|
||||
template<>
|
||||
void fmt_class_string<CellSearchError>::format(std::string& out, u64 arg)
|
||||
s32 cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr<CellSearchSystemCallback> func, vm::ptr<u32> userData)
|
||||
{
|
||||
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);
|
||||
}
|
||||
cellSearch.warning("cellSearchInitialize()");
|
||||
|
||||
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;
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
||||
{
|
||||
func(ppu, CELL_SEARCH_EVENT_INITIALIZE_RESULT, CELL_OK, vm::null, userData);
|
||||
return CELL_OK;
|
||||
});
|
||||
// TODO: Store the arguments somewhere so we can use them later.
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchFinalize()
|
||||
s32 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;
|
||||
}
|
||||
|
||||
error_code cellSearchStartListSearch(CellSearchListSearchType type, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
s32 cellSearchStartListSearch()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchStartContentSearchInList(vm::cptr<CellSearchContentId> listId, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
s32 cellSearchStartContentSearchInList()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchStartContentSearch(CellSearchContentSearchType type, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
s32 cellSearchStartContentSearch()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchStartSceneSearchInVideo(vm::cptr<CellSearchContentId> videoId, CellSearchSceneSearchType searchType, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
s32 cellSearchStartSceneSearchInVideo()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchStartSceneSearch(CellSearchSceneSearchType searchType, vm::cptr<char> gameTitle, vm::cpptr<char> tags, u32 tagNum, CellSearchSortKey sortKey, CellSearchSortOrder sortOrder, vm::ptr<CellSearchId> outSearchId)
|
||||
s32 cellSearchStartSceneSearch()
|
||||
{
|
||||
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;
|
||||
});
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoByOffset(CellSearchId searchId, s32 offset, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId)
|
||||
s32 cellSearchGetContentInfoByOffset()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoByContentId(vm::cptr<CellSearchContentId> contentId, vm::ptr<void> infoBuffer, vm::ptr<CellSearchContentType> outContentType)
|
||||
s32 cellSearchGetContentInfoByContentId()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoByContentId(contentId=*0x%x, infoBuffer=*0x%x, outContentType=*0x%x)", contentId, infoBuffer, outContentType);
|
||||
|
||||
if (!outContentType)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetOffsetByContentId(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, vm::ptr<s32> outOffset)
|
||||
s32 cellSearchGetOffsetByContentId()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentIdByOffset(CellSearchId searchId, s32 offset, vm::ptr<CellSearchContentType> outContentType, vm::ptr<CellSearchContentId> outContentId, vm::ptr<CellSearchTimeInfo> outTimeInfo)
|
||||
s32 cellSearchGetContentIdByOffset()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoGameComment(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> gameComment)
|
||||
s32 cellSearchGetContentInfoGameComment()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoGameComment(contentId=*0x%x, gameComment=*0x%x)", contentId, gameComment);
|
||||
|
||||
if (!gameComment)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetMusicSelectionContext(CellSearchId searchId, vm::cptr<CellSearchContentId> contentId, CellSearchRepeatMode repeatMode, CellSearchContextOption option, vm::ptr<CellMusicSelectionContext> outContext)
|
||||
s32 cellSearchGetMusicSelectionContext()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetMusicSelectionContextOfSingleTrack(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellMusicSelectionContext> outContext)
|
||||
s32 cellSearchGetMusicSelectionContextOfSingleTrack()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetMusicSelectionContextOfSingleTrack(contentId=*0x%x, outContext=*0x%x)", contentId, outContext);
|
||||
|
||||
if (!contentId || !outContext)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoPath(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPath> infoPath)
|
||||
s32 cellSearchGetContentInfoPath()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoPath(contentId=*0x%x, infoPath=*0x%x)", contentId, infoPath);
|
||||
|
||||
if (!infoPath)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoPathMovieThumb(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchContentInfoPathMovieThumb> infoMt)
|
||||
s32 cellSearchGetContentInfoPathMovieThumb()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoPathMovieThumb(contentId=*0x%x, infoMt=*0x%x)", contentId, infoMt);
|
||||
|
||||
if (!infoMt)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchPrepareFile(vm::cptr<char> path)
|
||||
s32 cellSearchPrepareFile()
|
||||
{
|
||||
cellSearch.todo("cellSearchPrepareFile(path=%s)", path);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoDeveloperData(vm::cptr<CellSearchContentId> contentId, vm::ptr<char> developerData)
|
||||
s32 cellSearchGetContentInfoDeveloperData()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoDeveloperData(contentId=*0x%x, developerData=*0x%x)", contentId, developerData);
|
||||
|
||||
if (!contentId || !developerData)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchGetContentInfoSharable(vm::cptr<CellSearchContentId> contentId, vm::ptr<CellSearchSharableType> sharable)
|
||||
s32 cellSearchGetContentInfoSharable()
|
||||
{
|
||||
cellSearch.todo("cellSearchGetContentInfoSharable(contentId=*0x%x, sharable=*0x%x)", contentId, sharable);
|
||||
|
||||
if (!contentId || !sharable)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_PARAM;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchCancel(CellSearchId searchId)
|
||||
s32 cellSearchCancel()
|
||||
{
|
||||
cellSearch.todo("cellSearchCancel(searchId=0x%x)", searchId);
|
||||
|
||||
const auto searchObject = idm::get<search_object_t>(searchId);
|
||||
|
||||
if (!searchObject)
|
||||
{
|
||||
return CELL_SEARCH_ERROR_INVALID_SEARCHID;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellSearchEnd(CellSearchId searchId)
|
||||
s32 cellSearchEnd()
|
||||
{
|
||||
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);
|
||||
|
||||
UNIMPLEMENTED_FUNC(cellSearch);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
// Error Codes
|
||||
enum CellSearchError : u32
|
||||
enum
|
||||
{
|
||||
CELL_SEARCH_CANCELED = 1,
|
||||
CELL_SEARCH_ERROR_PARAM = 0x8002C801,
|
||||
@@ -28,20 +30,17 @@ enum CellSearchError : u32
|
||||
// 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_DEVELOPERDATA_LEN_MAX = 64,
|
||||
CELL_SEARCH_GAMECOMMENT_SIZE_MAX = 1024,
|
||||
CELL_SEARCH_CONTENT_BUFFER_SIZE_MAX = 2048,
|
||||
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,
|
||||
};
|
||||
|
||||
// Sort keys
|
||||
enum CellSearchSortKey : s32
|
||||
enum : s32
|
||||
{
|
||||
CELL_SEARCH_SORTKEY_NONE = 0,
|
||||
CELL_SEARCH_SORTKEY_DEFAULT = 1,
|
||||
@@ -57,15 +56,15 @@ enum CellSearchSortKey : s32
|
||||
};
|
||||
|
||||
// Sort order
|
||||
enum CellSearchSortOrder : s32
|
||||
enum : s32
|
||||
{
|
||||
CELL_SEARCH_SORTORDER_NONE = 0,
|
||||
CELL_SEARCH_SORTORDER_ASCENDING = 1,
|
||||
CELL_SEARCH_SORTORDER_DESCENDING = 2,
|
||||
CELL_SEARCH_SOFTORDER_DESCENDING = 2,
|
||||
};
|
||||
|
||||
// Content types
|
||||
enum CellSearchContentType : s32
|
||||
enum : s32
|
||||
{
|
||||
CELL_SEARCH_CONTENTTYPE_NONE = 0,
|
||||
CELL_SEARCH_CONTENTTYPE_MUSIC = 1,
|
||||
@@ -123,22 +122,15 @@ 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,
|
||||
@@ -147,7 +139,7 @@ enum CellSearchContentStatus : s32
|
||||
// Search orientation
|
||||
enum CellSearchOrientation : s32
|
||||
{
|
||||
CELL_SEARCH_ORIENTATION_UNKNOWN = 0,
|
||||
CELL_SEARCH_ORIENTATION_UNKNOWN,
|
||||
CELL_SEARCH_ORIENTATION_TOP_LEFT,
|
||||
CELL_SEARCH_ORIENTATION_TOP_RIGHT,
|
||||
CELL_SEARCH_ORIENTATION_BOTTOM_RIGHT,
|
||||
@@ -173,60 +165,7 @@ enum CellSearchEvent : s32
|
||||
CELL_SEARCH_EVENT_SCENESEARCH_RESULT,
|
||||
};
|
||||
|
||||
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);
|
||||
using CellSearchSystemCallback = void(CellSearchEvent event, s32 result, vm::cptr<u32> param, vm::ptr<u32> userData);
|
||||
|
||||
struct CellSearchContentId
|
||||
{
|
||||
@@ -235,7 +174,7 @@ struct CellSearchContentId
|
||||
|
||||
struct CellSearchResultParam
|
||||
{
|
||||
be_t<CellSearchId> searchId;
|
||||
be_t<s32> searchId;
|
||||
be_t<u32> resultNum;
|
||||
};
|
||||
|
||||
|
||||
@@ -474,18 +474,6 @@ 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);
|
||||
@@ -558,12 +546,6 @@ s32 _ZN8cxmlutil6GetIntERKN4cxml7ElementEPKcPi()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN8cxmlutil7SetFileERKN4cxml7ElementEPKcRKNS0_4FileE()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 _ZN8cxmlutil8GetFloatERKN4cxml7ElementEPKcPf()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellSysutil);
|
||||
@@ -700,8 +682,6 @@ 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);
|
||||
@@ -716,7 +696,6 @@ 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,9 +40,6 @@ 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))
|
||||
@@ -107,7 +104,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ struct vdec_thread : ppu_thread
|
||||
{
|
||||
AVCodec* codec{};
|
||||
AVCodecContext* ctx{};
|
||||
SwsContext* sws{};
|
||||
|
||||
const s32 type;
|
||||
const u32 profile;
|
||||
@@ -148,7 +147,6 @@ struct vdec_thread : ppu_thread
|
||||
{
|
||||
avcodec_close(ctx);
|
||||
avcodec_free_context(&ctx);
|
||||
sws_freeContext(sws);
|
||||
}
|
||||
|
||||
virtual std::string dump() const override
|
||||
@@ -363,7 +361,7 @@ struct vdec_thread : ppu_thread
|
||||
{
|
||||
au_count--;
|
||||
}
|
||||
|
||||
|
||||
while (std::lock_guard<std::mutex>{mutex}, max_frames && out.size() > max_frames)
|
||||
{
|
||||
thread_ctrl::wait();
|
||||
@@ -485,7 +483,7 @@ s32 cellVdecClose(ppu_thread& ppu, u32 handle)
|
||||
vdec->cmd_push({vdec_cmd::close, 0});
|
||||
vdec->max_frames = 0;
|
||||
}
|
||||
|
||||
|
||||
vdec->notify();
|
||||
vdec->join();
|
||||
idm::remove<ppu_thread>(handle);
|
||||
@@ -588,7 +586,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
|
||||
}
|
||||
|
||||
vdec->notify();
|
||||
|
||||
|
||||
if (outBuff)
|
||||
{
|
||||
const int w = frame->width;
|
||||
@@ -634,7 +632,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
|
||||
}
|
||||
}
|
||||
|
||||
vdec->sws = sws_getCachedContext(vdec->sws, w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL);
|
||||
std::unique_ptr<SwsContext, void(*)(SwsContext*)> sws(sws_getContext(w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL), sws_freeContext);
|
||||
|
||||
u8* in_data[4] = { frame->data[0], frame->data[1], frame->data[2], alpha_plane.get() };
|
||||
int in_line[4] = { frame->linesize[0], frame->linesize[1], frame->linesize[2], w * 1 };
|
||||
@@ -650,7 +648,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
|
||||
out_line[2] = w / 2;
|
||||
}
|
||||
|
||||
sws_scale(vdec->sws, in_data, in_line, 0, h, out_data, out_line);
|
||||
sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line);
|
||||
|
||||
//const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128);
|
||||
|
||||
@@ -773,7 +771,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
|
||||
avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5;
|
||||
avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important
|
||||
avc->timing_info_present_flag = true;
|
||||
|
||||
|
||||
switch (frc)
|
||||
{
|
||||
case CELL_VDEC_FRC_24000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001; break;
|
||||
@@ -840,7 +838,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
|
||||
mp2->horizontal_size = frame->width;
|
||||
mp2->vertical_size = frame->height;
|
||||
mp2->aspect_ratio_information = CELL_VDEC_MPEG2_ARI_SAR_1_1; // ???
|
||||
|
||||
|
||||
switch (frc)
|
||||
{
|
||||
case CELL_VDEC_FRC_24000DIV1001: mp2->frame_rate_code = CELL_VDEC_MPEG2_FRC_24000DIV1001; break;
|
||||
|
||||
@@ -1,99 +1,36 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
|
||||
#include "cellSysutil.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel cellVideoExport("cellVideoExport");
|
||||
|
||||
struct CellVideoExportSetParam
|
||||
s32 cellVideoExportProgress()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
error_code cellVideoExportInitialize2(u32 version, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellVideoExportInitialize2()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
error_code cellVideoExportInitialize(u32 version, u32 container, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellVideoExportInitialize()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
error_code cellVideoExportFromFileWithCopy(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellVideoExportSetParam> param, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellVideoExportFromFileWithCopy()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
error_code cellVideoExportFromFile(vm::cptr<char> srcHddDir, vm::cptr<char> srcHddFile, vm::ptr<CellVideoExportSetParam> param, vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellVideoExportFromFile()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
error_code cellVideoExportFinalize(vm::ptr<CellVideoExportUtilFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||
s32 cellVideoExportFinalize()
|
||||
{
|
||||
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;
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
}
|
||||
|
||||
|
||||
|
||||