Compare commits

..

15 Commits

Author SHA1 Message Date
Zangetsu38 a3f28c170c Fix 2017-07-16 18:45:44 +02:00
Jake 7f509298a9 fix video playback 2017-07-16 18:45:44 +02:00
Jake e2f3a1952f Throw on memory loc until i find something that uses 2017-07-16 18:45:44 +02:00
Jake c5828faf0f Move vblank to 'custom' package_id, move fps limit sleep, fix dx12 0 size fb crash 2017-07-16 18:45:44 +02:00
Jake cfb573694c tiles, sync, bufferId, flipReset 2017-07-16 18:45:44 +02:00
Jake 8e7301b446 gcm: Fix bufferId, sysutil: add refreshrate 2017-07-16 18:45:44 +02:00
Jake f2ae336474 add to auto lle 2017-07-16 18:45:44 +02:00
Jake 3e2549e873 fix thread 2017-07-16 18:45:44 +02:00
Jake 3dd03e1066 dma main fix 2017-07-16 18:45:44 +02:00
Jake 637547718f fix labels 2017-07-16 18:45:44 +02:00
Jake ccc09353ea stuff 2017-07-16 18:45:44 +02:00
Jake 9dfd00d5b0 Rebase and cleanup, removed irrelevant code, lv2 lle gcm for now 2017-07-16 18:45:44 +02:00
Zangetsu38 cb0673e58d Update LLVM 5.0 2017-07-16 18:41:45 +02:00
Zion Nimchuk ecf9a037cc Initial LLVM 5 port 2017-07-16 18:40:04 +02:00
Zangetsu38 c97b06ecf0 Update Project to Visual Studio 2017. 2017-07-16 18:40:04 +02:00
161 changed files with 2361 additions and 5440 deletions
-1
View File
@@ -8,7 +8,6 @@
[submodule "llvm"]
path = llvm
url = https://github.com/llvm-mirror/llvm
branch = release_50
[submodule "rsx_program_decompiler"]
path = rsx_program_decompiler
url = https://github.com/RPCS3/rsx_program_decompiler
+25 -24
View File
@@ -29,6 +29,10 @@ matrix:
exclude:
- os: osx
compiler: gcc
include:
- os: linux
compiler: clang
env: WITHOUT_LLVM="yes"
git:
@@ -43,21 +47,19 @@ before_install:
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01';
fi;
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
wget http://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run ;
chmod a+x ./qt-unified-linux-x64-online.run ;
export QT_QPA_PLATFORM=minimal ;
./qt-unified-linux-x64-online.run --script qt-installer-noninteractive.qs --no-force-installations ;
sudo add-apt-repository ppa:beineri/opt-qt59-trusty -y;
sudo apt-get update;
sudo apt-get install qt59base -y --allow-unauthenticated;
fi;
# Add coverall for C++ so coverall.io could be triggered. Even it should be --coverage and gcov.
# Install updated libglew-dev since the version provided by trusty is outdated
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
pip install --user cpp-coveralls requests[security];
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew-dev_1.13.0-2_amd64.deb;
wget http://mirrors.kernel.org/ubuntu/pool/main/g/glew/libglew1.13_1.13.0-2_amd64.deb;
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
sudo dpkg -i libglew1.13_1.13.0-2_amd64.deb libglew-dev_1.13.0-2_amd64.deb libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb;
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.21.0+dfsg1-1~16.04.1_amd64.deb;
wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.21.0+dfsg1-1~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.21.0+dfsg1-1~16.04.1_amd64.deb libvulkan-dev_1.0.21.0+dfsg1-1~16.04.1_amd64.deb;
else
brew update; brew update;
brew install ccache glew llvm40;
@@ -65,31 +67,31 @@ before_install:
before_script:
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal 3rdparty/hidapi Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
- source /opt/qt59/bin/qt59-env.sh
- mkdir build
- cd build
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
- if [ -z "$WITHOUT_LLVM" ]; then
cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
else
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DWITHOUT_LLVM=ON;
fi;
- make -j 3
- # AppImage generation
- if [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
export LD_LIBRARY_PATH=~/Qt/5.9.1/gcc_64/lib;
export LD_LIBRARY_PATH=${PWD}/3rdparty/libpng:/opt/qt59/lib/:$LD_LIBRARY_PATH ;
make DESTDIR=appdir install ; find appdir/ ;
find ../bin ;
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
chmod a+x linuxdeployqt*.AppImage ;
export PATH=~/Qt/5.9.1/gcc_64/bin/:${PATH} ;
./linuxdeployqt*.AppImage --appimage-extract ;
unset QTDIR; unset QT_PLUGIN_PATH ;
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
mkdir ./appdir/usr/plugins/imageformats/ ;
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 ;
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -appimage ;
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq ;
curl ${UPLOAD_URL}${TRAVIS_COMMIT:0:7}-${TRAVIS_BUILD_NUMBER}_linux64 --upload-file ./RPCS3*.AppImage;
zip -r9 rpcs3.zip ./RPCS3*.AppImage;
if [ -z "$WITHOUT_LLVM" ]; then
export LLVM="-LLVM";
fi;
curl ${UPLOAD_URL}${TRAVIS_COMMIT:0:7}-${TRAVIS_BUILD_NUMBER}${LLVM}_linux64 --upload-file rpcs3.zip;
fi;
script:
@@ -122,10 +124,9 @@ addons:
- libstdc++-5-dev
- lib32stdc++6
- zlib1g-dev
# We need to install qt 5.9.1 manually because the version trusty provides is too old.
# We need to install qt 5.8 manually because the version trusty provides is too old.
#- qtbase5-dev
- libudev-dev
- libevdev-dev
coverity_scan:
project:
name: $TRAVIS_REPO_SLUG
+9 -37
View File
@@ -12,7 +12,6 @@
#include "File.h"
#include "Log.h"
#include "mutex.h"
#include "sysinfo.h"
#include "VirtualMemory.h"
#ifdef _MSC_VER
@@ -344,30 +343,22 @@ public:
LOG_SUCCESS(GENERAL, "LLVM: Created module: %s", module->getName().data());
}
static std::unique_ptr<llvm::MemoryBuffer> load(const std::string& path)
std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* module) override
{
if (fs::file cached{path, fs::read})
std::string name = m_path;
name.append(module->getName());
if (fs::file cached{name, fs::read})
{
auto buf = llvm::MemoryBuffer::getNewUninitMemBuffer(cached.size());
cached.read(const_cast<char*>(buf->getBufferStart()), buf->getBufferSize());
return buf;
}
return nullptr;
}
std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* module) override
{
std::string path = m_path;
path.append(module->getName());
if (auto buf = load(path))
{
LOG_SUCCESS(GENERAL, "LLVM: Loaded module: %s", module->getName().data());
return buf;
}
return nullptr;
else
{
return nullptr;
}
}
};
@@ -378,20 +369,6 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
if (m_cpu.empty())
{
m_cpu = llvm::sys::getHostCPUName();
if (m_cpu == "sandybridge" ||
m_cpu == "ivybridge" ||
m_cpu == "haswell" ||
m_cpu == "broadwell" ||
m_cpu == "skylake" ||
m_cpu == "skylake-avx512" ||
m_cpu == "cannonlake")
{
if (!utils::has_avx())
{
m_cpu = "nehalem";
}
}
}
std::string result;
@@ -453,11 +430,6 @@ void jit_compiler::add(std::unique_ptr<llvm::Module> module, const std::string&
}
}
void jit_compiler::add(const std::string& path)
{
m_engine->addObjectFile(std::move(llvm::object::ObjectFile::createObjectFile(*ObjectCache::load(path)).get()));
}
void jit_compiler::fin()
{
m_engine->finalizeObject();
+1 -4
View File
@@ -49,12 +49,9 @@ public:
return m_context;
}
// Add module (path to obj cache dir)
// Add module
void add(std::unique_ptr<llvm::Module> module, const std::string& path);
// Add object (path to obj file)
void add(const std::string& path);
// Finalize
void fin();
+7
View File
@@ -1413,6 +1413,13 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp)
msg += fmt::format("RPCS3 image base: %p.\n", GetModuleHandle(NULL));
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION)
{
msg += "\n"
"Illegal instruction exception occured.\n"
"Note that your CPU must support SSSE3 extension.\n";
}
// TODO: print registers and the callstack
// Report fatal error
+4 -35
View File
@@ -14,13 +14,9 @@ void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
case patch_type::le16: return "le16";
case patch_type::le32: return "le32";
case patch_type::le64: return "le64";
case patch_type::bef32: return "bef32";
case patch_type::bef64: return "bef64";
case patch_type::be16: return "be16";
case patch_type::be32: return "be32";
case patch_type::be64: return "be64";
case patch_type::lef32: return "lef32";
case patch_type::lef64: return "lef64";
}
return unknown;
@@ -43,44 +39,23 @@ void patch_engine::append(const std::string& patch)
u64 type64 = 0;
cfg::try_to_enum_value(&type64, &fmt_class_string<patch_type>::format, patch[0].Scalar());
struct patch info{};
struct patch info;
info.type = static_cast<patch_type>(type64);
info.offset = patch[1].as<u32>();
switch (info.type)
{
case patch_type::bef32:
case patch_type::lef32:
{
info.value_as<f32>() = patch[2].as<f32>();
break;
}
case patch_type::bef64:
case patch_type::lef64:
{
info.value_as<f64>() = patch[2].as<f64>();
break;
}
default:
{
info.value = patch[2].as<u64>();
break;
}
}
info.value = patch[2].as<u64>();
data.emplace_back(info);
}
}
}
}
std::size_t patch_engine::apply(const std::string& name, u8* dst) const
void patch_engine::apply(const std::string& name, u8* dst) const
{
const auto found = m_map.find(name);
if (found == m_map.cend())
{
return 0;
return;
}
// Apply modifications sequentially
@@ -101,13 +76,11 @@ std::size_t patch_engine::apply(const std::string& name, u8* dst) const
break;
}
case patch_type::le32:
case patch_type::lef32:
{
*reinterpret_cast<le_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
break;
}
case patch_type::le64:
case patch_type::lef64:
{
*reinterpret_cast<le_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
break;
@@ -118,19 +91,15 @@ std::size_t patch_engine::apply(const std::string& name, u8* dst) const
break;
}
case patch_type::be32:
case patch_type::bef32:
{
*reinterpret_cast<be_t<u32, 1>*>(ptr) = static_cast<u32>(p.value);
break;
}
case patch_type::be64:
case patch_type::bef64:
{
*reinterpret_cast<be_t<u64, 1>*>(ptr) = static_cast<u64>(p.value);
break;
}
}
}
return found->second.size();
}
+2 -12
View File
@@ -11,13 +11,9 @@ enum class patch_type
le16,
le32,
le64,
lef32,
lef64,
be16,
be32,
be64,
bef32,
bef64,
};
class patch_engine
@@ -27,12 +23,6 @@ class patch_engine
patch_type type;
u32 offset;
u64 value;
template <typename T>
T& value_as()
{
return *reinterpret_cast<T*>(reinterpret_cast<char*>(&value));
}
};
// Database
@@ -42,6 +32,6 @@ public:
// Load from file
void append(const std::string& path);
// Apply patch (returns the number of entries applied)
std::size_t apply(const std::string& name, u8* dst) const;
// Apply patch
void apply(const std::string& name, u8* dst) const;
};
-61
View File
@@ -1,61 +0,0 @@
#include "sysinfo.h"
#include "StrFmt.h"
#ifdef _WIN32
#include "windows.h"
#else
#include <unistd.h>
#endif
std::string utils::get_system_info()
{
std::string result;
std::string brand;
if (get_cpuid(0x80000000, 0)[0] >= 0x80000004)
{
for (u32 i = 0; i < 3; i++)
{
brand.append(reinterpret_cast<const char*>(get_cpuid(0x80000002 + i, 0).data()), 16);
}
}
else
{
brand = "Unknown CPU";
}
brand.erase(0, brand.find_first_not_of(' '));
brand.erase(brand.find_last_not_of(' ') + 1);
while (auto found = brand.find(" ") + 1)
{
brand.erase(brand.begin() + found);
}
#ifdef _WIN32
::SYSTEM_INFO sysInfo;
::GetNativeSystemInfo(&sysInfo);
::MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(memInfo);
::GlobalMemoryStatusEx(&memInfo);
const u32 num_proc = sysInfo.dwNumberOfProcessors;
const u64 mem_total = memInfo.ullTotalPhys;
#else
const u32 num_proc = ::sysconf(_SC_NPROCESSORS_ONLN);
const u64 mem_total = ::sysconf(_SC_PHYS_PAGES) * ::sysconf(_SC_PAGE_SIZE);
#endif
fmt::append(result, "%s | %d Threads | %.2f GiB RAM", brand, num_proc, mem_total / (1024.0f * 1024 * 1024));
if (has_avx())
{
result += " | AVX";
}
if (has_rtm())
{
result += " | TSX";
}
return result;
}
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include "types.h"
#include <string>
namespace utils
{
inline std::array<u32, 4> get_cpuid(u32 func, u32 subfunc)
{
int regs[4];
#ifdef _MSC_VER
__cpuidex(regs, func, subfunc);
#else
__asm__ volatile("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (func), "c" (subfunc));
#endif
return {0u+regs[0], 0u+regs[1], 0u+regs[2], 0u+regs[3]};
}
inline bool has_ssse3()
{
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x200;
}
inline bool has_avx()
{
return get_cpuid(0, 0)[0] >= 0x1 && get_cpuid(1, 0)[2] & 0x10000000;
}
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()
{
while (true)
{
const auto status = _xbegin();
if (status == _XBEGIN_STARTED)
{
return true;
}
if (!(status & _XABORT_RETRY))
{
return false;
}
}
}
std::string get_system_info();
}
+2 -2
View File
@@ -1,4 +1,4 @@
version: '0.0.3-{build}'
version: '0.0.2-{build}'
os: Visual Studio 2017
platform: x64
@@ -32,7 +32,7 @@ install:
artifacts:
- path: bin
name: 'rpcs3-v0.0.3-$(Date)-$(COMMIT_SHA)_win64'
name: 'rpcs3-v0.0.2-$(Date)-$(COMMIT_SHA)_win64'
type: zip
cache:
+1
View File
@@ -0,0 +1 @@
make_fself compiled.elf EBOOT.BIN
+1 -1
Submodule llvm updated: 079c1f30fc...9a59c1b6f3
-60
View File
@@ -1,60 +0,0 @@
// http://stackoverflow.com/a/34032216/78204
function Controller() {
installer.autoRejectMessageBoxes();
installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
})
}
Controller.prototype.WelcomePageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.CredentialsPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.IntroductionPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.TargetDirectoryPageCallback = function()
{
gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.value("HomeDir") + "/Qt");
//gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.value("InstallerDirPath") + "/Qt");
//gui.currentPageWidget().TargetDirectoryLineEdit.setText("/scratch/Qt");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
widget.deselectAll();
widget.selectComponent("qt.591.gcc_64");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function() {
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
gui.clickButton(buttons.NextButton);
}
Controller.prototype.StartMenuDirectoryPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function()
{
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function() {
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
checkBoxForm.launchQtCreatorCheckBox.checked = false;
}
gui.clickButton(buttons.FinishButton);
}
+17 -23
View File
@@ -85,9 +85,10 @@ else()
endif()
if(NOT MSVC)
if($ENV{CI})
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1") # fix for travis gcc OoM crash. Might be fixed with the move to containers.
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
# This hides our LLVM from mesa's LLVM, otherwise we get some unresolvable conflicts.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs,ALL")
if(WIN32)
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
@@ -97,7 +98,7 @@ if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--allow-multiple-definition")
endif()
add_compile_options(-msse -msse2 -mcx16 -mssse3 -mrtm)
add_compile_options(-msse -msse2 -mcx16 -mssse3)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# This fixes 'some' of the st11range issues. See issue #2516
@@ -108,10 +109,9 @@ if(NOT MSVC)
CHECK_C_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
if(HAS_NO_PIE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
endif()
CHECK_C_COMPILER_FLAG("-nopie" HAS_NOPIE)
if(HAS_NOPIE)
if (NOT HAS_NO_PIE)
else()
CHECK_C_COMPILER_FLAG("-nopie" HAS_NO_PIE)
if(HAS_NO_PIE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nopie")
endif()
endif()
@@ -158,17 +158,6 @@ elseif(WIN32)
set(PLATFORM_ARCH "Windows/x86_64")
else()
set(PLATFORM_ARCH "linux/x86_64")
option(USE_LIBEVDEV "libevdev-based joystick support" ON)
endif()
if(USE_LIBEVDEV)
find_package(PkgConfig)
pkg_check_modules(LIBEVDEV libevdev)
if(LIBEVDEV_FOUND)
add_definitions(-DHAVE_LIBEVDEV)
include_directories(SYSTEM ${LIBEVDEV_INCLUDE_DIRS})
list(APPEND ADDITIONAL_LIBS ${LIBEVDEV_LDFLAGS})
endif()
endif()
# Select the version of libpng to use, default is builtin
@@ -225,10 +214,16 @@ if(NOT LLVM_FOUND)
else()
add_definitions(${LLVM_DEFINITIONS})
add_definitions(-DLLVM_AVAILABLE)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
llvm_map_components_to_libnames(LLVM_LIBS mcjit vectorize ipo x86codegen x86disassembler)
#Use static linking for windows binary but always dynamic on *nix
if (WIN32)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
llvm_map_components_to_libnames(LLVM_LIBS mcjit vectorize ipo x86codegen x86disassembler)
else()
llvm_map_components_to_libnames(LLVM_LIBS mcjit vectorize ipo x86codegen x86disassembler mcdisassembler)
endif()
else()
llvm_map_components_to_libnames(LLVM_LIBS mcjit vectorize ipo x86codegen x86disassembler mcdisassembler)
set(LLVM_LIBS LLVM)
endif()
if (NOT MSVC)
@@ -288,7 +283,6 @@ 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")
foreach (TMP_PATH ${RPCS3_SRC})
foreach (EXCLUDE_PATH ${EXCLUDE_FILES})
@@ -300,7 +294,7 @@ foreach (TMP_PATH ${RPCS3_SRC})
endforeach(TMP_PATH)
# Remove the Qt moc files as part of clean, they are compiled when generating automoc
file(GLOB_RECURSE TMP_MOC "${RPCS3_SRC_DIR}/moc_*.cpp" "${RPCS3_SRC_DIR}/rpcs3_automoc.cpp" "${RPCS3_SRC_DIR}/qrc_resources.cpp")
file(GLOB_RECURSE TMP_MOC "${RPCS3_SRC_DIR}/moc_*.cpp" "${RPCS3_SRC_DIR}/rpcs3_automoc.cpp")
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${TMP_MOC}")
if (WIN32)
+4 -22
View File
@@ -1,12 +1,9 @@
#include "stdafx.h"
#include "Utilities/sysinfo.h"
#include "Emu/Memory/vm.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/lv2/sys_sync.h"
#include "MFC.h"
const bool s_use_rtm = utils::has_rtm();
template <>
void fmt_class_string<MFC>::format(std::string& out, u64 arg)
{
@@ -148,25 +145,10 @@ void mfc_thread::cpu_task()
vm::reservation_acquire(cmd.eal, 128);
// Store unconditionally
if (s_use_rtm && utils::transaction_enter())
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
data = to_write;
vm::reservation_update(cmd.eal, 128);
vm::notify(cmd.eal, 128);
_xend();
}
else
{
vm::writer_lock lock(0);
data = to_write;
vm::reservation_update(cmd.eal, 128);
vm::notify(cmd.eal, 128);
}
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)
{
+3 -22
View File
@@ -2,35 +2,16 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
namespace vm { using namespace ps3; }
logs::channel cellCrossController("cellCrossController");
struct CellCrossControllerParam
s32 cellCrossController_37E1F502() // LittleBigPlanet 2 and 3
{
vm::bcptr<char> pPackageFileName;
vm::bcptr<char> pSignatureFileName;
vm::bcptr<char> pIconFileName;
vm::bptr<void> option;
};
struct CellCrossControllerPackageInfo
{
vm::bcptr<char> pTitle;
vm::bcptr<char> pTitleId;
vm::bcptr<char> pAppVer;
};
using CellCrossControllerCallback = void(s32 status, s32 errorCode, vm::ptr<void> option, vm::ptr<void> userdata);
s32 cellCrossControllerInitialize(vm::cptr<CellCrossControllerParam> pParam, vm::cptr<CellCrossControllerPackageInfo> pPkgInfo, vm::ptr<CellCrossControllerCallback> cb, vm::ptr<void> userdata) // LittleBigPlanet 2 and 3
{
cellCrossController.todo("cellCrossControllerInitialize(pParam=*0x%x, pPkgInfo=*0x%x, cb=*0x%x, userdata=*0x%x)", pParam, pPkgInfo, cb, userdata);
cellCrossController.todo("cellCrossController_37E1F502");
return CELL_OK;
}
DECLARE(ppu_module_manager::cellCrossController)("cellCrossController", []()
{
REG_FUNC(cellCrossController, cellCrossControllerInitialize);
REG_FNID(cellCrossController, 0x37E1F502, cellCrossController_37E1F502);
});
+1 -1
View File
@@ -554,7 +554,7 @@ s32 cellFontExtend(u32 a1, u32 a2, u32 a3)
//Something happens
}
//Something happens?
return -1;
return CELL_OK;
}
s32 cellFontRenderCharGlyphImageVertical()
+19 -21
View File
@@ -80,13 +80,14 @@ struct content_permission final
// SFO file
psf::registry sfo;
// Temporary directory path
std::string temp;
// True if temporary directory is created and must be moved or deleted
bool is_temporary = false;
template <typename Dir, typename Sfo>
content_permission(Dir&& dir, Sfo&& sfo)
content_permission(Dir&& dir, Sfo&& sfo, bool is_temp = false)
: dir(std::forward<Dir>(dir))
, sfo(std::forward<Sfo>(sfo))
, is_temporary(is_temp)
{
}
@@ -94,9 +95,9 @@ struct content_permission final
{
try
{
if (!temp.empty())
if (is_temporary)
{
fs::remove_all(temp);
fs::remove_all(vfs::get("/dev_hdd1/game/" + dir));
}
}
catch (...)
@@ -182,14 +183,13 @@ s32 cellHddGameGetSizeKB(vm::ptr<u32> size)
{
cellGame.warning("cellHddGameGetSizeKB(size=*0x%x)", size);
const std::string local_dir = vfs::get("/dev_hdd0/game/" + Emu.GetTitleID());
const std::string& local_dir = vfs::get("/dev_hdd0/game/" + Emu.GetTitleID());
if (!fs::is_dir(local_dir))
{
return CELL_HDDGAME_ERROR_FAILURE;
}
*size = ::narrow<u32>(fs::get_dir_size(local_dir) / 1024);
*size = (u32)(fs::get_dir_size(local_dir)/1024);
return CELL_OK;
}
@@ -209,16 +209,16 @@ s32 cellGameDataGetSizeKB(vm::ptr<u32> size)
{
cellGame.warning("cellGameDataGetSizeKB(size=*0x%x)", size);
const std::string local_dir = vfs::get("/dev_hdd0/game/" + Emu.GetTitleID());
const std::string& local_dir = vfs::get("/dev_hdd0/game/" + Emu.GetTitleID());
if (!fs::is_dir(local_dir))
{
return CELL_GAMEDATA_ERROR_FAILURE;
}
*size = ::narrow<u32>(fs::get_dir_size(local_dir) / 1024);
*size = (u32)(fs::get_dir_size(local_dir)/1024);
return CELL_OK;
}
s32 cellGameDataSetSystemVer()
@@ -383,7 +383,7 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
const std::string dir = prm->dir.empty() ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + prm->dir;
if (!prm->temp.empty())
if (prm->is_temporary)
{
// Make temporary directory persistent
const auto vdir = vfs::get(dir);
@@ -393,7 +393,7 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
fmt::throw_exception("cellGameContentPermit(): epic fail: directory '%s' already exists", dir);
}
if (fs::rename(prm->temp, vdir))
if (fs::rename(vfs::get("/dev_hdd1/game/" + prm->dir), vdir))
{
cellGame.success("cellGameContentPermit(): directory '%s' has been created", dir);
}
@@ -406,7 +406,7 @@ error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPa
psf::save_object(fs::file(vdir + "/PARAM.SFO", fs::rewrite), prm->sfo);
// Disable deletion
prm->temp.clear();
prm->is_temporary = false;
}
strcpy_trunc(*contentInfoPath, dir);
@@ -570,8 +570,8 @@ error_code cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<c
strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo);
strcpy_trunc(*tmp_usrdirPath, tmp_usrdir);
prm->temp = vfs::get(tmp_contentInfo);
cellGame.success("cellGameCreateGameData(): temporary directory '%s' has been created", tmp_contentInfo);
prm->is_temporary = true;
// Initial PARAM.SFO parameters (overwrite)
prm->sfo =
@@ -714,10 +714,9 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
return CELL_OK;
}
error_code cellGameGetSizeKB(vm::ptr<s32> size)
s32 cellGameGetSizeKB(vm::ptr<s32> size)
{
cellGame.warning("cellGameGetSizeKB(size=*0x%x)", size);
const auto prm = fxm::get<content_permission>();
if (!prm)
@@ -725,14 +724,13 @@ error_code cellGameGetSizeKB(vm::ptr<s32> size)
return CELL_GAME_ERROR_FAILURE;
}
const std::string local_dir = !prm->temp.empty() ? prm->temp : vfs::get("/dev_hdd0/game/" + prm->dir);
const std::string& local_dir = prm->is_temporary? vfs::get("/dev_hdd1/game/"s + prm->dir) : vfs::get("/dev_hdd0/game/"s + prm->dir); //should we check the temporary folder?
if (!fs::is_dir(local_dir))
{
return CELL_GAME_ERROR_ACCESS_ERROR;
return CELL_GAME_ERROR_FAILURE;
}
*size = ::narrow<u32>(fs::get_dir_size(local_dir) / 1024);
*size = (u32)(fs::get_dir_size(local_dir)/1024);
return CELL_OK;
}
+8 -14
View File
@@ -5,15 +5,14 @@
logs::channel cellGameExec("cellGameExec");
s32 cellGameSetExitParam(u32 execdata)
s32 cellGameSetExitParam()
{
cellGameExec.todo("cellGameSetExitParam(execdata=0x%x)", execdata);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellGameGetHomeDataExportPath(vm::ptr<char> exportPath)
{
cellGameExec.warning("cellGameGetHomeDataExportPath(exportPath=*0x%x)", exportPath);
cellGameExec.warning("cellGameGetHomeDataExportPath(exportPath=0x%x)", exportPath);
// TODO: PlayStation home is defunct.
@@ -22,17 +21,12 @@ s32 cellGameGetHomeDataExportPath(vm::ptr<char> exportPath)
s32 cellGameGetHomePath()
{
UNIMPLEMENTED_FUNC(cellGameExec);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellGameGetHomeDataImportPath(vm::ptr<char> importPath)
s32 cellGameGetHomeDataImportPath()
{
cellGameExec.warning("cellGameGetHomeDataImportPath(importPath=*0x%x)", importPath);
// TODO: PlayStation home is defunct.
return CELL_GAME_ERROR_NOAPP;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellGameGetHomeLaunchOptionPath(vm::ptr<char> commonPath, vm::ptr<char> personalPath)
@@ -43,9 +37,9 @@ s32 cellGameGetHomeLaunchOptionPath(vm::ptr<char> commonPath, vm::ptr<char> pers
return CELL_GAME_ERROR_NOAPP;
}
s32 cellGameGetBootGameInfo(vm::ptr<u32> type, vm::ptr<char> dirName, vm::ptr<u32> execdata)
s32 cellGameGetBootGameInfo(vm::ptr<u32> type, vm::ptr<char> dirName, vm::ptr<u32> execData)
{
cellGameExec.todo("cellGameGetBootGameInfo(type=*0x%x, dirName=%s, execdata=*0x%x)", type, dirName, execdata);
cellGameExec.todo("cellGameGetBootGameInfo(type=*0x%x, dirName=%s, execData=*0x%x)", type, dirName, execData);
// TODO: Support more boot types
*type = CELL_GAME_GAMETYPE_SYS;
+90 -147
View File
@@ -26,19 +26,16 @@ const u32 tiled_pitches[] = {
0x00010000
};
struct CellGcmSysConfig {
u32 zculls_addr;
vm::ptr<CellGcmDisplayInfo> gcm_buffers{ vm::null };
u32 tiles_addr;
u32 ctxt_addr;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
};
u64 system_mode = 0;
u32 local_size = 0;
u32 local_addr = 0;
u64 system_mode = 0;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
u32 map_offset_addr = 0;
u32 map_offset_pos = 0;
// Auxiliary functions
@@ -85,12 +82,7 @@ void InitOffsetTable()
u32 cellGcmGetLabelAddress(u8 index)
{
cellGcmSys.trace("cellGcmGetLabelAddress(index=%d)", index);
const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.label_addr + 0x10 * index;
return gcm_info.label_addr + 0x10 * index;
}
vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 location)
@@ -102,7 +94,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
return vm::null;
}
return vm::ptr<CellGcmReportData>::make(0x40301400 + index * 0x10);
return vm::ptr<CellGcmReportData>::make(0xC0000000 + index * 0x10);
}
if (location == CELL_GCM_LOCATION_MAIN) {
@@ -125,7 +117,7 @@ u64 cellGcmGetTimeStamp(u32 index)
cellGcmSys.error("cellGcmGetTimeStamp: Wrong local index (%d)", index);
return 0;
}
return vm::read64(0x40301400 + index * 0x10);
return vm::read64(0xC0000000 + index * 0x10);
}
u32 cellGcmGetCurrentField()
@@ -152,7 +144,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
*/
vm::ptr<CellGcmReportData> _cellGcmFunc12()
{
return vm::ptr<CellGcmReportData>::make(0x40301400); // TODO
return vm::ptr<CellGcmReportData>::make(0xC0000000); // TODO
}
u32 cellGcmGetReport(u32 type, u32 index)
@@ -180,7 +172,7 @@ u32 cellGcmGetReportDataAddress(u32 index)
cellGcmSys.error("cellGcmGetReportDataAddress: Wrong local index (%d)", index);
return 0;
}
return 0x40301400 + index * 0x10;
return 0xC0000000 + index * 0x10;
}
u32 cellGcmGetReportDataLocation(u32 index, u32 location)
@@ -200,7 +192,7 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index);
return 0;
}
return vm::read64(0x40301400 + index * 0x10);
return vm::read64(0xC0000000 + index * 0x10);
}
if (location == CELL_GCM_LOCATION_MAIN) {
@@ -222,31 +214,20 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
u32 cellGcmGetControlRegister()
{
cellGcmSys.trace("cellGcmGetControlRegister()");
const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.control_addr;
return gcm_info.control_addr;
}
u32 cellGcmGetDefaultCommandWordSize()
{
cellGcmSys.trace("cellGcmGetDefaultCommandWordSize()");
const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.command_size;
return gcm_info.command_size;
}
u32 cellGcmGetDefaultSegmentWordSize()
{
cellGcmSys.trace("cellGcmGetDefaultSegmentWordSize()");
const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.segment_size;
return gcm_info.segment_size;
}
s32 cellGcmInitDefaultFifoMode(s32 mode)
@@ -299,10 +280,8 @@ s32 cellGcmBindZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
void cellGcmGetConfiguration(vm::ptr<CellGcmConfig> config)
{
cellGcmSys.trace("cellGcmGetConfiguration(config=*0x%x)", config);
const auto m_config = fxm::get<CellGcmSysConfig>();
if (m_config)
*config = m_config->current_config;
*config = current_config;
}
u32 cellGcmGetFlipStatus()
@@ -318,9 +297,9 @@ u32 cellGcmGetTiledPitchSize(u32 size)
{
cellGcmSys.trace("cellGcmGetTiledPitchSize(size=%d)", size);
for (size_t i = 0; i < sizeof(tiled_pitches) / sizeof(tiled_pitches[0]) - 1; i++) {
if (tiled_pitches[i] < size && size <= tiled_pitches[i + 1]) {
return tiled_pitches[i + 1];
for (size_t i=0; i < sizeof(tiled_pitches) / sizeof(tiled_pitches[0]) - 1; i++) {
if (tiled_pitches[i] < size && size <= tiled_pitches[i+1]) {
return tiled_pitches[i+1];
}
}
return 0;
@@ -345,12 +324,8 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
{
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
auto m_config = fxm::make<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
m_config->current_config.ioAddress = 0;
m_config->current_config.localAddress = 0;
current_config.ioAddress = 0;
current_config.localAddress = 0;
local_size = 0;
local_addr = 0;
@@ -381,42 +356,33 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
return CELL_GCM_ERROR_FAILURE;
}
m_config->current_config.ioSize = ioSize;
m_config->current_config.ioAddress = ioAddress;
m_config->current_config.localSize = local_size;
m_config->current_config.localAddress = local_addr;
m_config->current_config.memoryFrequency = 650000000;
m_config->current_config.coreFrequency = 500000000;
map_offset_addr = 0;
map_offset_pos = 0;
current_config.ioSize = ioSize;
current_config.ioAddress = ioAddress;
current_config.localSize = local_size;
current_config.localAddress = local_addr;
current_config.memoryFrequency = 650000000;
current_config.coreFrequency = 500000000;
// Create contexts
u32 addr = vm::falloc(0x40000000, 0x400000);
if (addr == 0 || addr != 0x40000000)
fmt::throw_exception("Failed to alloc 0x40000000.");
g_defaultCommandBufferBegin = ioAddress;
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
m_config->gcm_info.context_addr = 0x40000000;
m_config->gcm_info.control_addr = 0x40100000;
m_config->gcm_info.label_addr = 0x40300000;
gcm_info.context_addr = vm::alloc(0x1000, vm::main);
gcm_info.control_addr = vm::alloc(0x1000, vm::main);
gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ???
m_config->current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning
m_config->current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump
m_config->current_context.current = m_config->current_context.begin;
m_config->current_context.callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(cellGcmCallback));
current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning
current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump
current_context.current = current_context.begin;
current_context.callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(cellGcmCallback));
m_config->ctxt_addr = context.addr();
m_config->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main));
m_config->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main);
m_config->tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main);
vm::_ref<CellGcmContextData>(gcm_info.context_addr) = current_context;
context->set(gcm_info.context_addr);
vm::_ref<CellGcmContextData>(m_config->gcm_info.context_addr) = m_config->current_context;
context->set(m_config->gcm_info.context_addr);
// 0x40 is to offset CellGcmControl from RsxDmaControl
m_config->gcm_info.control_addr += 0x40;
auto& ctrl = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr);
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr);
ctrl.put = 0;
ctrl.get = 0;
ctrl.ref = -1;
@@ -424,10 +390,15 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
const auto render = fxm::get<GSRender>();
render->intr_thread = idm::make_ptr<ppu_thread>("_gcm_intr_thread", 1, 0x4000);
render->intr_thread->run();
render->ctxt_addr = context.addr();
render->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main));
render->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main);
render->tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main);
render->gcm_buffers_count = 0;
render->gcm_current_buffer = 0;
render->main_mem_addr = 0;
render->isHLE = true;
render->label_addr = m_config->gcm_info.label_addr;
render->init(ioAddress, ioSize, m_config->gcm_info.control_addr - 0x40, local_addr);
render->label_addr = gcm_info.label_addr;
render->init(g_defaultCommandBufferBegin, cmdSize, gcm_info.control_addr, local_addr);
return CELL_OK;
}
@@ -460,10 +431,6 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
{
cellGcmSys.trace("cellGcmSetDisplayBuffer(id=0x%x, offset=0x%x, pitch=%d, width=%d, height=%d)", id, offset, width ? pitch / width : pitch, width, height);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (id > 7)
{
cellGcmSys.error("cellGcmSetDisplayBuffer: CELL_GCM_ERROR_FAILURE");
@@ -472,21 +439,16 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
const auto render = fxm::get<GSRender>();
auto buffers = render->display_buffers;
auto buffers = render->gcm_buffers;
buffers[id].offset = offset;
buffers[id].pitch = pitch;
buffers[id].width = width;
buffers[id].height = height;
m_config->gcm_buffers[id].offset = offset;
m_config->gcm_buffers[id].pitch = pitch;
m_config->gcm_buffers[id].width = width;
m_config->gcm_buffers[id].height = height;
if (id + 1 > render->display_buffers_count)
if (id + 1 > render->gcm_buffers_count)
{
render->display_buffers_count = id + 1;
render->gcm_buffers_count = id + 1;
}
return CELL_OK;
@@ -503,7 +465,17 @@ void cellGcmSetFlipMode(u32 mode)
{
cellGcmSys.warning("cellGcmSetFlipMode(mode=%d)", mode);
fxm::get<GSRender>()->requested_vsync.store(mode == CELL_GCM_DISPLAY_VSYNC);
switch (mode)
{
case CELL_GCM_DISPLAY_HSYNC:
case CELL_GCM_DISPLAY_VSYNC:
case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE:
fxm::get<GSRender>()->flip_mode = mode;
break;
default:
break;
}
}
void cellGcmSetFlipStatus()
@@ -516,9 +488,6 @@ void cellGcmSetFlipStatus()
s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
{
cellGcmSys.trace("cellGcmSetPrepareFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (id > 7)
{
@@ -537,9 +506,9 @@ s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32
const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id });
if (ctxt.addr() == m_config->gcm_info.context_addr)
if (ctxt.addr() == gcm_info.context_addr)
{
vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).put += cmd_size;
vm::_ref<CellGcmControl>(gcm_info.control_addr).put += cmd_size;
}
return id;
@@ -566,12 +535,15 @@ void cellGcmSetSecondVFrequency(u32 freq)
switch (freq)
{
case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ:
render->frequency_mode = freq;
render->fps_limit = 59.94;
break;
case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT:
render->frequency_mode = freq;
cellGcmSys.todo("Unimplemented display frequency: Scanout");
break;
case CELL_GCM_DISPLAY_FREQUENCY_DISABLE:
render->frequency_mode = freq;
cellGcmSys.todo("Unimplemented display frequency: Disabled");
break;
default:
@@ -585,10 +557,6 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
cellGcmSys.warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{
cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_VALUE");
@@ -623,7 +591,7 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
tile.base = base;
tile.bank = bank;
vm::_ptr<CellGcmTileInfo>(m_config->tiles_addr)[index] = tile.pack();
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack();
return CELL_OK;
}
@@ -656,7 +624,7 @@ void cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
s32 cellGcmSetWaitFlipUnsafe()
{
cellGcmSys.todo("cellGcmSetWaitFlipUnsafe()");
return CELL_OK;
}
@@ -665,10 +633,6 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
cellGcmSys.todo("cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return;
if (index >= rsx::limits::zculls_count)
{
cellGcmSys.error("cellGcmSetZcull: CELL_GCM_ERROR_INVALID_VALUE");
@@ -679,7 +643,7 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
auto& zcull = render->zculls[index];
zcull.offset = offset;
zcull.width = width;
zcull.width = width;
zcull.height = height;
zcull.cullStart = cullStart;
zcull.zFormat = zFormat;
@@ -690,7 +654,7 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
zcull.sRef = sRef;
zcull.sMask = sMask;
vm::_ptr<CellGcmZcullInfo>(m_config->zculls_addr)[index] = zcull.pack();
vm::_ptr<CellGcmZcullInfo>(render->zculls_addr)[index] = zcull.pack();
}
s32 cellGcmUnbindTile(u8 index)
@@ -726,35 +690,26 @@ s32 cellGcmUnbindZcull(u8 index)
u32 cellGcmGetTileInfo()
{
cellGcmSys.warning("cellGcmGetTileInfo()");
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->tiles_addr;
return fxm::get<GSRender>()->tiles_addr;
}
u32 cellGcmGetZcullInfo()
{
cellGcmSys.warning("cellGcmGetZcullInfo()");
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->zculls_addr;
return fxm::get<GSRender>()->zculls_addr;
}
u32 cellGcmGetDisplayInfo()
{
cellGcmSys.warning("cellGcmGetDisplayInfo()");
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_buffers.addr();
return fxm::get<GSRender>()->gcm_buffers.addr();
}
s32 cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id)
{
cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id);
if ((*id = fxm::get<GSRender>()->current_display_buffer) > UINT8_MAX)
if ((*id = fxm::get<GSRender>()->gcm_current_buffer) > UINT8_MAX)
{
fmt::throw_exception("Unexpected" HERE);
}
@@ -921,7 +876,7 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
u32 realAddr;
if (!RSXIOMem.getRealAddr(ioOffset, realAddr))
if (!RSXIOMem.getRealAddr(ioOffset, realAddr))
return CELL_GCM_ERROR_FAILURE;
*address = realAddr;
@@ -943,6 +898,7 @@ s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
{
offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i;
offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i;
render->strict_ordering[(io >> 20) + i] = is_strict;
}
}
else
@@ -992,7 +948,6 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{
cellGcmSys.warning("cellGcmMapMainMemory(ea=0x%x, size=0x%x, offset=*0x%x)", ea, size, offset);
if (size == 0) return CELL_OK;
if ((ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
u32 io = RSXIOMem.Map(ea, size);
@@ -1007,6 +962,7 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{
offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i);
offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i);
render->strict_ordering[(io >> 20) + i] = false;
}
*offset = io;
@@ -1157,27 +1113,23 @@ s32 cellGcmSetCursorImageOffset(u32 offset)
void cellGcmSetDefaultCommandBuffer()
{
cellGcmSys.warning("cellGcmSetDefaultCommandBuffer()");
auto m_config = fxm::get<CellGcmSysConfig>();
if (m_config)
vm::write32(m_config->ctxt_addr, m_config->gcm_info.context_addr);
vm::write32(fxm::get<GSRender>()->ctxt_addr, gcm_info.context_addr);
}
s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segmentSize)
{
cellGcmSys.warning("cellGcmSetDefaultCommandBufferAndSegmentWordSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
const auto& put = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).put;
const auto& get = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).get;
const auto& put = vm::_ref<CellGcmControl>(gcm_info.control_addr).put;
const auto& get = vm::_ref<CellGcmControl>(gcm_info.control_addr).get;
if (put != 0x1000 || get != 0x1000 || bufferSize < segmentSize * 2)
{
return CELL_GCM_ERROR_FAILURE;
}
m_config->gcm_info.command_size = bufferSize;
m_config->gcm_info.segment_size = segmentSize;
gcm_info.command_size = bufferSize;
gcm_info.segment_size = segmentSize;
return CELL_OK;
}
@@ -1196,11 +1148,9 @@ s32 _cellGcmSetFlipCommand(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32
s32 _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
{
cellGcmSys.trace("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
s32 res = cellGcmSetPrepareFlip(ppu, ctx, id);
vm::write32(m_config->gcm_info.label_addr + 0x10 * label_index, label_value);
vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value);
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
}
@@ -1209,10 +1159,6 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
cellGcmSys.warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
// Copied form cellGcmSetTileInfo
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{
@@ -1248,7 +1194,7 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
tile.base = base;
tile.bank = bank;
vm::_ptr<CellGcmTileInfo>(m_config->tiles_addr)[index] = tile.pack();
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack();
return CELL_OK;
}
@@ -1340,11 +1286,8 @@ static bool isInCommandBufferExcept(u32 getPos, u32 bufferBegin, u32 bufferEnd)
s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 count)
{
cellGcmSys.trace("cellGcmCallback(context=*0x%x, count=0x%x)", context, count);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
auto& ctrl = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr);
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr);
// Flush command buffer (ie allow RSX to read up to context->current)
ctrl.put.exchange(getOffsetFromAddress(context->current.addr()));
@@ -1485,4 +1428,4 @@ DECLARE(ppu_module_manager::cellGcmSys)("cellGcmSys", []()
// Special
REG_FUNC(cellGcmSys, cellGcmCallback).flags = MFF_HIDDEN;
});
});
-7
View File
@@ -141,12 +141,6 @@ s32 cellOskDialogExtRegisterKeyboardEventHookCallback(u16 hookEventMode, vm::ptr
return CELL_OK;
}
s32 cellOskDialogExtRegisterKeyboardEventHookCallbackEx(u16 hookEventMode, vm::ptr<cellOskDialogHardwareKeyboardEventHookCallback> pCallback)
{
cellOskDialog.todo("cellOskDialogExtRegisterKeyboardEventHookCallbackEx(hookEventMode=%u, pCallback=*0x%x)", hookEventMode, pCallback);
return CELL_OK;
}
s32 cellOskDialogExtAddJapaneseOptionDictionary(vm::cpptr<char> filePath)
{
cellOskDialog.todo("cellOskDialogExtAddJapaneseOptionDictionary(filePath=**0x%0x)", filePath);
@@ -253,7 +247,6 @@ DECLARE(ppu_module_manager::cellOskDialog)("cellOskExtUtility", []()
{
REG_FUNC(cellOskExtUtility, cellOskDialogExtInputDeviceUnlock);
REG_FUNC(cellOskExtUtility, cellOskDialogExtRegisterKeyboardEventHookCallback);
REG_FUNC(cellOskExtUtility, cellOskDialogExtRegisterKeyboardEventHookCallbackEx);
REG_FUNC(cellOskExtUtility, cellOskDialogExtAddJapaneseOptionDictionary);
REG_FUNC(cellOskExtUtility, cellOskDialogExtEnableClipboard);
REG_FUNC(cellOskExtUtility, cellOskDialogExtSendFinishMessage);
+12 -61
View File
@@ -1,90 +1,41 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
namespace vm { using namespace ps3; }
logs::channel cellRec("cellRec");
struct CellRecSpursParam
s32 cellRecOpen()
{
vm::bptr<struct CellSpurs> pSpurs;
be_t<s32> spu_usage_rate;
u8 priority[8];
};
struct CellRecOption
{
be_t<s32> option;
union
{
be_t<s32> ppu_thread_priority;
be_t<s32> spu_thread_priority;
be_t<s32> capture_priority;
be_t<s32> use_system_spu;
be_t<s32> fit_to_youtube;
be_t<s32> xmb_bgm;
be_t<s32> mpeg4_fast_encode;
be_t<u32> ring_sec;
be_t<s32> video_input;
be_t<s32> audio_input;
be_t<s32> audio_input_mix_vol;
be_t<s32> reduce_memsize;
be_t<s32> show_xmb;
vm::bptr<char> metadata_filename;
vm::bptr<CellRecSpursParam> pSpursParam;
be_t<u64> dummy;
} value;
};
struct CellRecParam
{
be_t<s32> videoFmt;
be_t<s32> audioFmt;
be_t<s32> numOfOpt;
vm::bptr<CellRecOption> pOpt;
};
using CellRecCallback = void(s32 recStatus, s32 recError, vm::ptr<void> userdata);
s32 cellRecOpen(vm::cptr<char> pDirName, vm::cptr<char> pFileName, vm::cptr<CellRecParam> pParam, u32 container, vm::ptr<CellRecCallback> cb, vm::ptr<void> cbUserData)
{
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);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellRecClose(s32 isDiscard)
s32 cellRecClose()
{
cellRec.todo("cellRecClose(isDiscard=0x%x)", isDiscard);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
void cellRecGetInfo(s32 info, vm::ptr<u64> pValue)
s32 cellRecGetInfo()
{
cellRec.todo("cellRecGetInfo(info=0x%x, pValue=*0x%x)", info, pValue);
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellRecStop()
{
cellRec.todo("cellRecStop()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellRecStart()
{
cellRec.todo("cellRecStart()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
u32 cellRecQueryMemSize(vm::cptr<CellRecParam> pParam)
s32 cellRecQueryMemSize()
{
cellRec.todo("cellRecQueryMemSize(pParam=*0x%x)", pParam);
return 1 * 1024 * 1024; // dummy memory size
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellRecSetInfo(s32 setInfo, u64 value)
s32 cellRecSetInfo()
{
cellRec.todo("cellRecSetInfo(setInfo=0x%x, value=0x%x)", setInfo, value);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
+5 -4
View File
@@ -123,8 +123,8 @@ s32 cellRescGetFlipStatus()
s32 cellRescGetRegisterCount()
{
cellResc.todo("cellRescGetRegisterCount()");
return 0;
UNIMPLEMENTED_FUNC(cellResc);
return CELL_OK;
}
u64 cellRescGetLastFlipTime()
@@ -134,9 +134,10 @@ u64 cellRescGetLastFlipTime()
return 0;
}
void cellRescSetRegisterCount(s32 regCount)
s32 cellRescSetRegisterCount()
{
cellResc.todo("cellRescSetRegisterCount(regCount=0x%x)", regCount);
UNIMPLEMENTED_FUNC(cellResc);
return CELL_OK;
}
void cellRescSetVBlankHandler(vm::ptr<void(u32)> handler)
-134
View File
@@ -248,126 +248,12 @@ s32 cellSailRecorderCancel()
return CELL_OK;
}
s32 cellSailRecorderRegisterComposer()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailRecorderUnregisterComposer()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailRecorderDumpImage()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerInitialize()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerFinalize()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetStreamParameter()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsAudioParameter()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsUserParameter()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsVideoParameter()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsAudioAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsUserAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerGetEsVideoAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerTryGetEsAudioAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerTryGetEsUserAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerTryGetEsVideoAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerReleaseEsAudioAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerReleaseEsUserAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerReleaseEsVideoAu()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerNotifyCallCompleted()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
s32 cellSailComposerNotifySessionError()
{
UNIMPLEMENTED_FUNC(cellSailRec);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellSailRec)("cellSailRec", []()
{
static ppu_static_module cellMp4("cellMp4");
@@ -415,26 +301,6 @@ DECLARE(ppu_module_manager::cellSailRec)("cellSailRec", []()
REG_FUNC(cellSailRec, cellSailRecorderStart);
REG_FUNC(cellSailRec, cellSailRecorderStop);
REG_FUNC(cellSailRec, cellSailRecorderCancel);
REG_FUNC(cellSailRec, cellSailRecorderRegisterComposer);
REG_FUNC(cellSailRec, cellSailRecorderUnregisterComposer);
REG_FUNC(cellSailRec, cellSailRecorderDumpImage);
REG_FUNC(cellSailRec, cellSailComposerInitialize);
REG_FUNC(cellSailRec, cellSailComposerFinalize);
REG_FUNC(cellSailRec, cellSailComposerGetStreamParameter);
REG_FUNC(cellSailRec, cellSailComposerGetEsAudioParameter);
REG_FUNC(cellSailRec, cellSailComposerGetEsUserParameter);
REG_FUNC(cellSailRec, cellSailComposerGetEsVideoParameter);
REG_FUNC(cellSailRec, cellSailComposerGetEsAudioAu);
REG_FUNC(cellSailRec, cellSailComposerGetEsUserAu);
REG_FUNC(cellSailRec, cellSailComposerGetEsVideoAu);
REG_FUNC(cellSailRec, cellSailComposerTryGetEsAudioAu);
REG_FUNC(cellSailRec, cellSailComposerTryGetEsUserAu);
REG_FUNC(cellSailRec, cellSailComposerTryGetEsVideoAu);
REG_FUNC(cellSailRec, cellSailComposerReleaseEsAudioAu);
REG_FUNC(cellSailRec, cellSailComposerReleaseEsUserAu);
REG_FUNC(cellSailRec, cellSailComposerReleaseEsVideoAu);
REG_FUNC(cellSailRec, cellSailComposerNotifyCallCompleted);
REG_FUNC(cellSailRec, cellSailComposerNotifySessionError);
});
+13 -19
View File
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/Modules/cellSysutil.h"
@@ -725,7 +725,7 @@ s32 static NEVER_INLINE save_op_get_list_item(vm::cptr<char> dirName, vm::ptr<Ce
userId = 1u;
}
std::string save_path = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/%s/", userId, dirName.get_ptr()));
std::string sfo = save_path + "PARAM.SFO";
std::string sfo = save_path + "param.sfo";
if (!fs::is_dir(save_path) && !fs::is_file(sfo))
{
@@ -743,26 +743,20 @@ s32 static NEVER_INLINE save_op_get_list_item(vm::cptr<char> dirName, vm::ptr<Ce
strcpy_trunc(sysFileParam->detail, psf.at("DETAIL").as_string());
}
if (dir)
fs::stat_t dir_info{};
if (!fs::stat(save_path, dir_info))
{
fs::stat_t dir_info{};
if (!fs::stat(save_path, dir_info))
{
return CELL_SAVEDATA_ERROR_INTERNAL;
}
// get file stats, namely directory
strcpy_trunc(dir->dirName, dirName.get_ptr());
dir->atime = dir_info.atime;
dir->ctime = dir_info.ctime;
dir->mtime = dir_info.mtime;
return CELL_SAVEDATA_ERROR_INTERNAL;
}
if (bind)
{
//TODO: Set bind in accordance to any problems
*bind = 0;
}
// get file stats, namely directory
strcpy_trunc(dir->dirName, dirName.get_ptr());
dir->atime = dir_info.atime;
dir->ctime = dir_info.ctime;
dir->mtime = dir_info.mtime;
//TODO: Set bind in accordance to any problems
*bind = 0;
return CELL_OK;
}
@@ -1,9 +1,9 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "cellSubDisplay.h"
#include "cellSubdisplay.h"
logs::channel cellSubDisplay("cellSubDisplay");
logs::channel cellSubdisplay("cellSubdisplay");
template<>
void fmt_class_string<CellSubDisplayError>::format(std::string& out, u64 arg)
@@ -28,51 +28,51 @@ void fmt_class_string<CellSubDisplayError>::format(std::string& out, u64 arg)
error_code cellSubDisplayInit(vm::ptr<CellSubDisplayParam> pParam, vm::ptr<CellSubDisplayHandler> func, vm::ptr<void> userdata, u32 container)
{
cellSubDisplay.todo("cellSubDisplayInit(pParam=*0x%x, func=*0x%x, userdata=*0x%x, container=0x%x)", pParam, func, userdata, container);
cellSubdisplay.todo("cellSubDisplayInit(pParam=*0x%x, func=*0x%x, userdata=*0x%x, container=0x%x)", pParam, func, userdata, container);
return CELL_OK;
}
error_code cellSubDisplayEnd()
{
cellSubDisplay.todo("cellSubDisplayEnd()");
cellSubdisplay.todo("cellSubDisplayEnd()");
return CELL_OK;
}
error_code cellSubDisplayGetRequiredMemory(vm::ptr<CellSubDisplayParam> pParam)
{
cellSubDisplay.warning("cellSubDisplayGetRequiredMemory(pParam=*0x%x)", pParam);
cellSubdisplay.warning("cellSubDisplayGetRequiredMemory(pParam=*0x%x)", pParam);
switch (pParam->version)
if (pParam->version == CELL_SUBDISPLAY_VERSION_0002)
{
case CELL_SUBDISPLAY_VERSION_0001: return not_an_error(CELL_SUBDISPLAY_0001_MEMORY_CONTAINER_SIZE);
case CELL_SUBDISPLAY_VERSION_0002: return not_an_error(CELL_SUBDISPLAY_0002_MEMORY_CONTAINER_SIZE);
case CELL_SUBDISPLAY_VERSION_0003: return not_an_error(CELL_SUBDISPLAY_0003_MEMORY_CONTAINER_SIZE);
return not_an_error(CELL_SUBDISPLAY_0002_MEMORY_CONTAINER_SIZE);
}
else
{
return not_an_error(CELL_SUBDISPLAY_0001_MEMORY_CONTAINER_SIZE);
}
return CELL_SUBDISPLAY_ERROR_INVALID_VALUE;
}
error_code cellSubDisplayStart()
{
cellSubDisplay.todo("cellSubDisplayStart()");
cellSubdisplay.todo("cellSubDisplayStart()");
return CELL_OK;
}
error_code cellSubDisplayStop()
{
cellSubDisplay.todo("cellSubDisplayStop()");
cellSubdisplay.todo("cellSubDisplayStop()");
return CELL_OK;
}
error_code cellSubDisplayGetVideoBuffer(s32 groupId, vm::pptr<void> ppVideoBuf, vm::ptr<u32> pSize)
{
cellSubDisplay.todo("cellSubDisplayGetVideoBuffer(groupId=%d, ppVideoBuf=**0x%x, pSize=*0x%x)", groupId, ppVideoBuf, pSize);
cellSubdisplay.todo("cellSubDisplayGetVideoBuffer(groupId=%d, ppVideoBuf=**0x%x, pSize=*0x%x)", groupId, ppVideoBuf, pSize);
return CELL_OK;
}
error_code cellSubDisplayAudioOutBlocking(s32 groupId, vm::ptr<void> pvData, s32 samples)
{
cellSubDisplay.todo("cellSubDisplayAudioOutBlocking(groupId=%d, pvData=*0x%x, samples=%d)", groupId, pvData, samples);
cellSubdisplay.todo("cellSubDisplayAudioOutBlocking(groupId=%d, pvData=*0x%x, samples=%d)", groupId, pvData, samples);
if (samples % 1024)
{
@@ -84,7 +84,7 @@ error_code cellSubDisplayAudioOutBlocking(s32 groupId, vm::ptr<void> pvData, s32
error_code cellSubDisplayAudioOutNonBlocking(s32 groupId, vm::ptr<void> pvData, s32 samples)
{
cellSubDisplay.todo("cellSubDisplayAudioOutNonBlocking(groupId=%d, pvData=*0x%x, samples=%d)", groupId, pvData, samples);
cellSubdisplay.todo("cellSubDisplayAudioOutNonBlocking(groupId=%d, pvData=*0x%x, samples=%d)", groupId, pvData, samples);
if (samples % 1024)
{
@@ -96,43 +96,34 @@ error_code cellSubDisplayAudioOutNonBlocking(s32 groupId, vm::ptr<void> pvData,
error_code cellSubDisplayGetPeerNum(s32 groupId)
{
cellSubDisplay.todo("cellSubDisplayGetPeerNum(groupId=%d)", groupId);
cellSubdisplay.todo("cellSubDisplayGetPeerNum(groupId=%d)", groupId);
return CELL_OK;
}
error_code cellSubDisplayGetPeerList(s32 groupId, vm::ptr<CellSubDisplayPeerInfo> pInfo, vm::ptr<s32> pNum)
{
cellSubDisplay.todo("cellSubDisplayGetPeerList(groupId=%d, pInfo=*0x%x, pNum=*0x%x)", groupId, pInfo, pNum);
cellSubdisplay.todo("cellSubDisplayGetPeerList(groupId=%d, pInfo=*0x%x, pNum=*0x%x)", groupId, pInfo, pNum);
*pNum = 0;
return CELL_OK;
}
error_code cellSubDisplayGetTouchInfo(s32 groupId, vm::ptr<CellSubDisplayTouchInfo> pTouchInfo, vm::ptr<s32> pNumTouchInfo)
{
cellSubDisplay.todo("cellSubDisplayGetTouchInfo(groupId=%d, pTouchInfo=*0x%x, pNumTouchInfo=*0x%x)", groupId, pTouchInfo, pNumTouchInfo);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellSubDisplay)("cellSubDisplay", []()
DECLARE(ppu_module_manager::cellSubdisplay)("cellSubdisplay", []()
{
// Initialization / Termination Functions
REG_FUNC(cellSubDisplay, cellSubDisplayInit);
REG_FUNC(cellSubDisplay, cellSubDisplayEnd);
REG_FUNC(cellSubDisplay, cellSubDisplayGetRequiredMemory);
REG_FUNC(cellSubDisplay, cellSubDisplayStart);
REG_FUNC(cellSubDisplay, cellSubDisplayStop);
REG_FUNC(cellSubdisplay, cellSubDisplayInit);
REG_FUNC(cellSubdisplay, cellSubDisplayEnd);
REG_FUNC(cellSubdisplay, cellSubDisplayGetRequiredMemory);
REG_FUNC(cellSubdisplay, cellSubDisplayStart);
REG_FUNC(cellSubdisplay, cellSubDisplayStop);
// Data Setting Functions
REG_FUNC(cellSubDisplay, cellSubDisplayGetVideoBuffer);
REG_FUNC(cellSubDisplay, cellSubDisplayAudioOutBlocking);
REG_FUNC(cellSubDisplay, cellSubDisplayAudioOutNonBlocking);
REG_FUNC(cellSubdisplay, cellSubDisplayGetVideoBuffer);
REG_FUNC(cellSubdisplay, cellSubDisplayAudioOutBlocking);
REG_FUNC(cellSubdisplay, cellSubDisplayAudioOutNonBlocking);
// Peer Status Acquisition Functions
REG_FUNC(cellSubDisplay, cellSubDisplayGetPeerNum);
REG_FUNC(cellSubDisplay, cellSubDisplayGetPeerList);
//
REG_FUNC(cellSubDisplay, cellSubDisplayGetTouchInfo);
REG_FUNC(cellSubdisplay, cellSubDisplayGetPeerNum);
REG_FUNC(cellSubdisplay, cellSubDisplayGetPeerList);
});
@@ -23,11 +23,9 @@ enum
CELL_SUBDISPLAY_STATUS_FATALERROR = 3,
CELL_SUBDISPLAY_VERSION_0001 = 1,
CELL_SUBDISPLAY_VERSION_0002 = 2,
CELL_SUBDISPLAY_VERSION_0003 = 3,
CELL_SUBDISPLAY_MODE_REMOTEPLAY = 1,
CELL_SUBDISPLAY_VIDEO_FORMAT_A8R8G8B8 = 1,
CELL_SUBDISPLAY_VIDEO_FORMAT_R8G8B8A8 = 2,
CELL_SUBDISPLAY_VIDEO_FORMAT_YUV420 = 3,
CELL_SUBDISPLAY_VIDEO_ASPECT_RATIO_16_9 = 0,
CELL_SUBDISPLAY_VIDEO_ASPECT_RATIO_4_3 = 1,
CELL_SUBDISPLAY_VIDEO_MODE_SETDATA = 0,
@@ -36,7 +34,6 @@ enum
CELL_SUBDISPLAY_AUDIO_MODE_CAPTURE = 1,
CELL_SUBDISPLAY_0001_MEMORY_CONTAINER_SIZE = 8 * 1024 * 1024,
CELL_SUBDISPLAY_0002_MEMORY_CONTAINER_SIZE = 10 * 1024 * 1024,
CELL_SUBDISPLAY_0003_MEMORY_CONTAINER_SIZE = 10 * 1024 * 1024,
CELL_SUBDISPLAY_NICKNAME_LEN = 256,
CELL_SUBDISPLAY_PSPID_LEN = 16,
};
@@ -85,12 +82,4 @@ struct CellSubDisplayPeerInfo
CellSubDisplayNickname pspNickname;
};
struct CellSubDisplayTouchInfo
{
u8 status;
u8 force;
be_t<u16> x;
be_t<u16> y;
};
using CellSubDisplayHandler = void(s32 cbMsg, u64 cbParam, vm::ptr<void> userdata);
-1
View File
@@ -251,7 +251,6 @@ static const char* get_module_id(u16 id)
case 0xf034: return "CELL_SYSMODULE_SAIL_REC";
case 0xf035: return "CELL_SYSMODULE_SYSUTIL_NP_TROPHY";
case 0xf044: return "CELL_SYSMODULE_SYSUTIL_NP_EULA";
case 0xf053: return "CELL_SYSMODULE_ADEC_AT3MULTI";
case 0xf054: return "CELL_SYSMODULE_LIBATRAC3MULTI";
case 0xffff: return "CELL_SYSMODULE_INVALID";
}
-21
View File
@@ -471,12 +471,6 @@ s32 _ZN4cxml8DocumentD1Ev()
return CELL_OK;
}
s32 _ZN4cxml8Document5ClearEv()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN4cxml8Document13CreateElementEPKciPNS_7ElementE()
{
UNIMPLEMENTED_FUNC(cellSysutil);
@@ -513,12 +507,6 @@ s32 _ZNK4cxml7Element12GetAttributeEPKcPNS_9AttributeE()
return CELL_OK;
}
s32 _ZNK4cxml7Element13GetFirstChildEv()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZNK4cxml7Element14GetNextSiblingEv()
{
UNIMPLEMENTED_FUNC(cellSysutil);
@@ -549,12 +537,6 @@ s32 _ZN8cxmlutil6GetIntERKN4cxml7ElementEPKcPi()
return CELL_OK;
}
s32 _ZN8cxmlutil8GetFloatERKN4cxml7ElementEPKcPf()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN8cxmlutil9GetStringERKN4cxml7ElementEPKcPS5_Pj()
{
UNIMPLEMENTED_FUNC(cellSysutil);
@@ -654,7 +636,6 @@ DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []()
REG_FUNC(cellSysutil, _ZN4cxml8DocumentC1Ev);
REG_FUNC(cellSysutil, _ZN4cxml8DocumentD1Ev);
REG_FUNC(cellSysutil, _ZN4cxml8Document5ClearEv);
REG_FUNC(cellSysutil, _ZN4cxml8Document13CreateElementEPKciPNS_7ElementE);
REG_FUNC(cellSysutil, _ZN4cxml8Document14SetHeaderMagicEPKc);
REG_FUNC(cellSysutil, _ZN4cxml8Document16CreateFromBufferEPKvjb);
@@ -662,14 +643,12 @@ DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []()
REG_FUNC(cellSysutil, _ZNK4cxml4File7GetAddrEv);
REG_FUNC(cellSysutil, _ZNK4cxml7Element12GetAttributeEPKcPNS_9AttributeE);
REG_FUNC(cellSysutil, _ZNK4cxml7Element13GetFirstChildEv);
REG_FUNC(cellSysutil, _ZNK4cxml7Element14GetNextSiblingEv);
REG_FUNC(cellSysutil, _ZNK4cxml9Attribute6GetIntEPi);
REG_FUNC(cellSysutil, _ZNK4cxml9Attribute7GetFileEPNS_4FileE);
REG_FUNC(cellSysutil, _ZN8cxmlutil6SetIntERKN4cxml7ElementEPKci);
REG_FUNC(cellSysutil, _ZN8cxmlutil6GetIntERKN4cxml7ElementEPKcPi);
REG_FUNC(cellSysutil, _ZN8cxmlutil8GetFloatERKN4cxml7ElementEPKcPf);
REG_FUNC(cellSysutil, _ZN8cxmlutil9GetStringERKN4cxml7ElementEPKcPS5_Pj);
REG_FUNC(cellSysutil, _ZN8cxmlutil9SetStringERKN4cxml7ElementEPKcS5_);
REG_FUNC(cellSysutil, _ZN8cxmlutil16CheckElementNameERKN4cxml7ElementEPKc);
+12 -19
View File
@@ -54,8 +54,7 @@ s32 cellSysutilAvc2SetVoiceMuting()
s32 cellSysutilAvc2StartVoiceDetection()
{
cellSysutilAvc2.todo("cellSysutilAvc2StartVoiceDetection()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2UnloadAsync()
@@ -88,10 +87,10 @@ s32 cellSysutilAvc2SetWindowString()
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2EstimateMemoryContainerSize(vm::cptr<CellSysutilAvc2InitParam> initparam, vm::ptr<u32> size)
s32 cellSysutilAvc2EstimateMemoryContainerSize()
{
cellSysutilAvc2.todo("cellSysutilAvc2EstimateMemoryContainerSize(initparam=*0x%x, size=*0x%x)", initparam, size);
return CELL_OK;
UNIMPLEMENTED_FUNC(cellSysutilAvc2);
return CELL_OK;
}
s32 cellSysutilAvc2SetVideoMuting()
@@ -131,10 +130,9 @@ s32 cellSysutilAvc2GetSpeakerVolumeLevel()
s32 cellSysutilAvc2IsCameraAttached(vm::ptr<u8> status)
{
cellSysutilAvc2.todo("cellSysutilAvc2IsCameraAttached(status=*0x%x)", status);
cellSysutilAvc2.todo("cellSysutilAvc2IsCameraAttached()");
*status = CELL_AVC2_CAMERA_STATUS_DETACHED;
return CELL_OK;
}
@@ -275,16 +273,14 @@ s32 cellSysutilAvc2SetSpeakerMuting()
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2Load(SceNpMatching2ContextId ctx_id, u32 container, vm::ptr<CellSysutilAvc2Callback> callback_func, vm::ptr<void> user_data, vm::cptr<CellSysutilAvc2InitParam> init_param)
s32 cellSysutilAvc2Load()
{
cellSysutilAvc2.todo("cellSysutilAvc2Load(ctx_id=0x%x, container=0x%x, callback_func=*0x%x, user_data=*0x%x, init_param=*0x%x)", ctx_id, container, callback_func, user_data, init_param);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2SetAttribute(vm::cptr<CellSysutilAvc2Attribute> attr)
s32 cellSysutilAvc2SetAttribute()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetAttribute(attr=*0x%x)", attr);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2UnloadAsync2()
@@ -307,13 +303,10 @@ s32 cellSysutilAvc2HideWindow()
fmt::throw_exception("Unimplemented" HERE);
}
s32 cellSysutilAvc2GetVoiceMuting(vm::ptr<u8> muting)
s32 cellSysutilAvc2GetVoiceMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetVoiceMuting(muting=*0x%x)", muting);
*muting = 1;
return CELL_OK;
UNIMPLEMENTED_FUNC(cellSysutilAvc2);
return CELL_OK;
}
s32 cellSysutilAvc2GetScreenShowStatus()
+2 -16
View File
@@ -511,9 +511,9 @@ s32 sceNpBasicGetEvent(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, vm::ptr<
sceNp.warning("sceNpBasicGetEvent(event=*0x%x, from=*0x%x, data=*0x%x, size=*0x%x)", event, from, data, size);
// TODO: Check for other error and pass other events
//*event = SCE_NP_BASIC_EVENT_OFFLINE; // This event only indicates a contact is offline, not the current status of the connection
*event = SCE_NP_BASIC_EVENT_OFFLINE;
return SCE_NP_BASIC_ERROR_NO_EVENT;
return CELL_OK;
}
s32 sceNpCommerceCreateCtx()
@@ -1511,18 +1511,6 @@ s32 sceNpScoreGetRankingByRangeAsync()
return CELL_OK;
}
s32 sceNpScoreGetFriendsRanking()
{
UNIMPLEMENTED_FUNC(sceNp);
return CELL_OK;
}
s32 sceNpScoreGetFriendsRankingAsync()
{
UNIMPLEMENTED_FUNC(sceNp);
return CELL_OK;
}
s32 sceNpScoreCensorComment()
{
UNIMPLEMENTED_FUNC(sceNp);
@@ -2025,8 +2013,6 @@ DECLARE(ppu_module_manager::sceNp)("sceNp", []()
REG_FUNC(sceNp, sceNpScoreGetRankingByNpIdAsync);
REG_FUNC(sceNp, sceNpScoreGetRankingByRange);
REG_FUNC(sceNp, sceNpScoreGetRankingByRangeAsync);
REG_FUNC(sceNp, sceNpScoreGetFriendsRanking);
REG_FUNC(sceNp, sceNpScoreGetFriendsRankingAsync);
REG_FUNC(sceNp, sceNpScoreCensorComment);
REG_FUNC(sceNp, sceNpScoreCensorCommentAsync);
REG_FUNC(sceNp, sceNpScoreSanitizeComment);
+1 -1
View File
@@ -678,7 +678,7 @@ union SceNpSignalingConnectionInfo
SceNpId npId;
struct address {
be_t<u32> addr; // in_addr
be_t<u16> port; // in_port_t
//in_port_t port; // TODO: Implement this?
};
be_t<u32> packet_loss;
};
-43
View File
@@ -469,42 +469,6 @@ s32 sceNpMatching2SignalingGetPeerNetInfoResult()
return CELL_OK;
}
s32 sceNpAuthOAuthInit()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
s32 sceNpAuthOAuthTerm()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
s32 sceNpAuthCreateOAuthRequest()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
s32 sceNpAuthDeleteOAuthRequest()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
s32 sceNpAuthAbortOAuthRequest()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
s32 sceNpAuthGetAuthorizationCode()
{
UNIMPLEMENTED_FUNC(sceNp2);
return CELL_OK;
}
DECLARE(ppu_module_manager::sceNp2)("sceNp2", []()
{
REG_FUNC(sceNp2, sceNpMatching2DestroyContext);
@@ -580,11 +544,4 @@ DECLARE(ppu_module_manager::sceNp2)("sceNp2", []()
REG_FUNC(sceNp2, sceNpMatching2SignalingGetLocalNetInfo);
REG_FUNC(sceNp2, sceNpMatching2SignalingGetPeerNetInfo);
REG_FUNC(sceNp2, sceNpMatching2SignalingGetPeerNetInfoResult);
REG_FUNC(sceNp2, sceNpAuthOAuthInit);
REG_FUNC(sceNp2, sceNpAuthOAuthTerm);
REG_FUNC(sceNp2, sceNpAuthCreateOAuthRequest);
REG_FUNC(sceNp2, sceNpAuthDeleteOAuthRequest);
REG_FUNC(sceNp2, sceNpAuthAbortOAuthRequest);
REG_FUNC(sceNp2, sceNpAuthGetAuthorizationCode);
});
+1 -6
View File
@@ -155,11 +155,6 @@ s32 sceNpSnsFbLoadThrottle()
fmt::throw_exception("Unimplemented" HERE);
}
s32 sceNpSnsFbGetLongAccessToken()
{
fmt::throw_exception("Unimplemented" HERE);
}
DECLARE(ppu_module_manager::sceNpSns)("sceNpSns", []()
{
@@ -169,7 +164,7 @@ DECLARE(ppu_module_manager::sceNpSns)("sceNpSns", []()
REG_FUNC(sceNpSns, sceNpSnsFbDestroyHandle);
REG_FUNC(sceNpSns, sceNpSnsFbAbortHandle);
REG_FUNC(sceNpSns, sceNpSnsFbGetAccessToken);
REG_FUNC(sceNpSns, sceNpSnsFbGetLongAccessToken);
REG_FUNC(sceNpSns, sceNpSnsFbStreamPublish);
REG_FUNC(sceNpSns, sceNpSnsFbCheckThrottle);
REG_FUNC(sceNpSns, sceNpSnsFbCheckConfig);
-42
View File
@@ -140,18 +140,6 @@ s32 sceNpTusGetMultiUserVariableVUserAsync()
return CELL_OK;
}
s32 sceNpTusGetFriendsVariable()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTusGetFriendsVariableAsync()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTusAddAndGetVariable()
{
UNIMPLEMENTED_FUNC(sceNpTus);
@@ -320,18 +308,6 @@ s32 sceNpTusGetMultiUserDataStatusVUserAsync()
return CELL_OK;
}
s32 sceNpTusGetFriendsDataStatus()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTusGetFriendsDataStatusAsync()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTusDeleteMultiSlotData()
{
UNIMPLEMENTED_FUNC(sceNpTus);
@@ -356,18 +332,6 @@ s32 sceNpTusDeleteMultiSlotDataVUserAsync()
return CELL_OK;
}
s32 sceNpTssGetData()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTssGetDataAsync()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
DECLARE(ppu_module_manager::sceNpTus)("sceNpTus", []()
{
REG_FUNC(sceNpTus, sceNpTusInit);
@@ -392,8 +356,6 @@ DECLARE(ppu_module_manager::sceNpTus)("sceNpTus", []()
REG_FUNC(sceNpTus, sceNpTusGetMultiUserVariableVUser);
REG_FUNC(sceNpTus, sceNpTusGetMultiUserVariableAsync);
REG_FUNC(sceNpTus, sceNpTusGetMultiUserVariableVUserAsync);
REG_FUNC(sceNpTus, sceNpTusGetFriendsVariable);
REG_FUNC(sceNpTus, sceNpTusGetFriendsVariableAsync);
REG_FUNC(sceNpTus, sceNpTusAddAndGetVariable);
REG_FUNC(sceNpTus, sceNpTusAddAndGetVariableVUser);
REG_FUNC(sceNpTus, sceNpTusAddAndGetVariableAsync);
@@ -422,12 +384,8 @@ DECLARE(ppu_module_manager::sceNpTus)("sceNpTus", []()
REG_FUNC(sceNpTus, sceNpTusGetMultiUserDataStatusVUser);
REG_FUNC(sceNpTus, sceNpTusGetMultiUserDataStatusAsync);
REG_FUNC(sceNpTus, sceNpTusGetMultiUserDataStatusVUserAsync);
REG_FUNC(sceNpTus, sceNpTusGetFriendsDataStatus);
REG_FUNC(sceNpTus, sceNpTusGetFriendsDataStatusAsync);
REG_FUNC(sceNpTus, sceNpTusDeleteMultiSlotData);
REG_FUNC(sceNpTus, sceNpTusDeleteMultiSlotDataVUser);
REG_FUNC(sceNpTus, sceNpTusDeleteMultiSlotDataAsync);
REG_FUNC(sceNpTus, sceNpTusDeleteMultiSlotDataVUserAsync);
REG_FUNC(sceNpTus, sceNpTssGetData);
REG_FUNC(sceNpTus, sceNpTssGetDataAsync);
});
+11 -11
View File
@@ -18,11 +18,11 @@ vm::ptr<void> _sys_memset(vm::ptr<void> dst, s32 value, u32 size);
struct sys_lwmutex_t;
struct sys_lwmutex_attribute_t;
error_code sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr);
error_code sys_lwmutex_lock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout);
error_code sys_lwmutex_trylock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
error_code sys_lwmutex_unlock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
error_code sys_lwmutex_destroy(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr);
s32 sys_lwmutex_lock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout);
s32 sys_lwmutex_trylock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
s32 sys_lwmutex_unlock(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
s32 sys_lwmutex_destroy(ppu_thread& CPU, vm::ptr<sys_lwmutex_t> lwmutex);
struct sys_lwmutex_locker
{
@@ -45,11 +45,11 @@ struct sys_lwmutex_locker
struct sys_lwcond_t;
struct sys_lwcond_attribute_t;
error_code sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr);
error_code sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond);
error_code sys_lwcond_signal(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond);
error_code sys_lwcond_signal_all(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond);
error_code sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id);
error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr);
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond);
s32 sys_lwcond_signal(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond);
s32 sys_lwcond_signal_all(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond);
s32 sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id);
s32 sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
void sys_ppu_thread_exit(ppu_thread& CPU, u64 val);
+1 -1
View File
@@ -16,5 +16,5 @@ void sys_libc_memcpy(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
DECLARE(ppu_module_manager::sys_libc)("sys_libc", []()
{
REG_FNID(sys_libc, "memcpy", sys_libc_memcpy).flags = MFF_FORCED_HLE;
REG_FNID(sys_libc, "memcpy", sys_libc_memcpy);
});
+38 -76
View File
@@ -5,24 +5,17 @@
#include "Emu/Cell/lv2/sys_lwmutex.h"
#include "Emu/Cell/lv2/sys_lwcond.h"
#include "Emu/Cell/lv2/sys_mutex.h"
#include "Emu/Cell/lv2/sys_cond.h"
#include "sysPrxForUser.h"
extern logs::channel sysPrxForUser;
extern bool g_avoid_lwm = false;
error_code sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr)
s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwcond_attribute_t> attr)
{
sysPrxForUser.trace("sys_lwcond_create(lwcond=*0x%x, lwmutex=*0x%x, attr=*0x%x)", lwcond, lwmutex, attr);
vm::var<u32> out_id;
vm::var<sys_cond_attribute_t> attrs;
attrs->pshared = SYS_SYNC_NOT_PROCESS_SHARED;
attrs->name_u64 = attr->name_u64;
if (auto res = g_avoid_lwm ? sys_cond_create(out_id, lwmutex->sleep_queue, attrs) : _sys_lwcond_create(out_id, lwmutex->sleep_queue, lwcond, attr->name_u64, 0))
if (s32 res = _sys_lwcond_create(out_id, lwmutex->sleep_queue, lwcond, attr->name_u64, 0))
{
return res;
}
@@ -32,16 +25,11 @@ error_code sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t
return CELL_OK;
}
error_code sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
s32 sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
{
sysPrxForUser.trace("sys_lwcond_destroy(lwcond=*0x%x)", lwcond);
if (g_avoid_lwm)
{
return sys_cond_destroy(lwcond->lwcond_queue);
}
if (error_code res = _sys_lwcond_destroy(lwcond->lwcond_queue))
if (s32 res = _sys_lwcond_destroy(lwcond->lwcond_queue))
{
return res;
}
@@ -50,20 +38,16 @@ error_code sys_lwcond_destroy(vm::ptr<sys_lwcond_t> lwcond)
return CELL_OK;
}
error_code sys_lwcond_signal(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
s32 sys_lwcond_signal(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
{
sysPrxForUser.trace("sys_lwcond_signal(lwcond=*0x%x)", lwcond);
if (g_avoid_lwm)
{
return sys_cond_signal(ppu, lwcond->lwcond_queue);
}
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
if ((lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_RETRY)
{
return _sys_lwcond_signal(ppu, lwcond->lwcond_queue, 0, -1, 2);
// TODO (protocol ignored)
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, -1, 2);
}
if (lwmutex->vars.owner.load() == ppu.id)
@@ -72,21 +56,18 @@ error_code sys_lwcond_signal(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
lwmutex->all_info++;
// call the syscall
if (error_code res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 1))
if (s32 res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 1))
{
ppu.test_state();
lwmutex->all_info--;
if (res != CELL_EPERM)
{
return res;
}
return res == CELL_EPERM ? CELL_OK : res;
}
return CELL_OK;
}
if (error_code res = sys_lwmutex_trylock(ppu, lwmutex))
if (s32 res = sys_lwmutex_trylock(ppu, lwmutex))
{
// if locking failed
@@ -103,7 +84,7 @@ error_code sys_lwcond_signal(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
lwmutex->all_info++;
// call the syscall
if (error_code res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 3))
if (s32 res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, -1, 3))
{
ppu.test_state();
lwmutex->all_info--;
@@ -111,35 +92,28 @@ error_code sys_lwcond_signal(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
// unlock the lightweight mutex
sys_lwmutex_unlock(ppu, lwmutex);
if (res != CELL_ENOENT)
{
return res;
}
return res == CELL_ENOENT ? CELL_OK : res;
}
return CELL_OK;
}
error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
s32 sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
{
sysPrxForUser.trace("sys_lwcond_signal_all(lwcond=*0x%x)", lwcond);
if (g_avoid_lwm)
{
return sys_cond_signal_all(ppu, lwcond->lwcond_queue);
}
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
if ((lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_RETRY)
{
return _sys_lwcond_signal_all(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, 2);
// TODO (protocol ignored)
//return _sys_lwcond_signal_all(lwcond->lwcond_queue, lwmutex->sleep_queue, 2);
}
if (lwmutex->vars.owner.load() == ppu.id)
{
// if owns the mutex, call the syscall
const error_code res = _sys_lwcond_signal_all(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, 1);
const s32 res = _sys_lwcond_signal_all(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, 1);
if (res <= 0)
{
@@ -153,7 +127,7 @@ error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
return CELL_OK;
}
if (error_code res = sys_lwmutex_trylock(ppu, lwmutex))
if (s32 res = sys_lwmutex_trylock(ppu, lwmutex))
{
// if locking failed
@@ -167,7 +141,7 @@ error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
}
// if locking succeeded, call the syscall
error_code res = _sys_lwcond_signal_all(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, 1);
s32 res = _sys_lwcond_signal_all(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, 1);
ppu.test_state();
@@ -184,20 +158,16 @@ error_code sys_lwcond_signal_all(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond)
return res;
}
error_code sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
s32 sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
{
sysPrxForUser.trace("sys_lwcond_signal_to(lwcond=*0x%x, ppu_thread_id=0x%x)", lwcond, ppu_thread_id);
if (g_avoid_lwm)
{
return sys_cond_signal_to(ppu, lwcond->lwcond_queue, ppu_thread_id);
}
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
if ((lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_RETRY)
{
return _sys_lwcond_signal(ppu, lwcond->lwcond_queue, 0, ppu_thread_id, 2);
// TODO (protocol ignored)
//return _sys_lwcond_signal(lwcond->lwcond_queue, 0, ppu_thread_id, 2);
}
if (lwmutex->vars.owner.load() == ppu.id)
@@ -206,7 +176,7 @@ error_code sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u
lwmutex->all_info++;
// call the syscall
if (error_code res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 1))
if (s32 res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 1))
{
ppu.test_state();
lwmutex->all_info--;
@@ -217,7 +187,7 @@ error_code sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u
return CELL_OK;
}
if (error_code res = sys_lwmutex_trylock(ppu, lwmutex))
if (s32 res = sys_lwmutex_trylock(ppu, lwmutex))
{
// if locking failed
@@ -234,7 +204,7 @@ error_code sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u
lwmutex->all_info++;
// call the syscall
if (error_code res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 3))
if (s32 res = _sys_lwcond_signal(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, ppu_thread_id, 3))
{
ppu.test_state();
lwmutex->all_info--;
@@ -248,15 +218,10 @@ error_code sys_lwcond_signal_to(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u
return CELL_OK;
}
error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
s32 sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
{
sysPrxForUser.trace("sys_lwcond_wait(lwcond=*0x%x, timeout=0x%llx)", lwcond, timeout);
if (g_avoid_lwm)
{
return sys_cond_wait(ppu, lwcond->lwcond_queue, timeout);
}
const be_t<u32> tid(ppu.id);
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
@@ -275,7 +240,7 @@ error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 ti
lwmutex->recursive_count = 0;
// call the syscall
const error_code res = _sys_lwcond_queue_wait(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, timeout);
s32 res = _sys_lwcond_queue_wait(ppu, lwcond->lwcond_queue, lwmutex->sleep_queue, timeout);
if (res == CELL_OK || res == CELL_ESRCH)
{
@@ -288,7 +253,7 @@ error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 ti
const auto old = lwmutex->vars.owner.exchange(tid);
lwmutex->recursive_count = recursive_value;
if (old == lwmutex_free || old == lwmutex_dead)
if (old != lwmutex_reserved)
{
fmt::throw_exception("Locking failed (lwmutex=*0x%x, owner=0x%x)" HERE, lwmutex, old);
}
@@ -298,20 +263,17 @@ error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 ti
if (res == CELL_EBUSY || res == CELL_ETIMEDOUT)
{
if (error_code res2 = sys_lwmutex_lock(ppu, lwmutex, 0))
const s32 res2 = sys_lwmutex_lock(ppu, lwmutex, 0);
if (res2 == CELL_OK)
{
return res2;
// if successfully locked, restore recursive value
lwmutex->recursive_count = recursive_value;
return res == CELL_EBUSY ? CELL_OK : res;
}
// if successfully locked, restore recursive value
lwmutex->recursive_count = recursive_value;
if (res == CELL_EBUSY)
{
return CELL_OK;
}
return res;
return res2;
}
if (res == CELL_EDEADLK)
@@ -320,15 +282,15 @@ error_code sys_lwcond_wait(ppu_thread& ppu, vm::ptr<sys_lwcond_t> lwcond, u64 ti
const auto old = lwmutex->vars.owner.exchange(tid);
lwmutex->recursive_count = recursive_value;
if (old == lwmutex_free || old == lwmutex_dead)
if (old != lwmutex_reserved)
{
fmt::throw_exception("Locking failed (lwmutex=*0x%x, owner=0x%x)" HERE, lwmutex, old);
}
return not_an_error(CELL_ETIMEDOUT);
return CELL_ETIMEDOUT;
}
fmt::throw_exception("Unexpected syscall result (lwcond=*0x%x, result=0x%x)" HERE, lwcond, +res);
fmt::throw_exception("Unexpected syscall result (lwcond=*0x%x, result=0x%x)" HERE, lwcond, res);
}
void sysPrxForUser_sys_lwcond_init()
+11 -42
View File
@@ -5,14 +5,11 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_lwmutex.h"
#include "Emu/Cell/lv2/sys_mutex.h"
#include "sysPrxForUser.h"
extern logs::channel sysPrxForUser;
extern bool g_avoid_lwm;
error_code sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
{
sysPrxForUser.trace("sys_lwmutex_create(lwmutex=*0x%x, attr=*0x%x)", lwmutex, attr);
@@ -35,16 +32,8 @@ error_code sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmute
}
vm::var<u32> out_id;
vm::var<sys_mutex_attribute_t> attrs;
attrs->protocol = attr->protocol;
attrs->recursive = attr->recursive;
attrs->pshared = SYS_SYNC_NOT_PROCESS_SHARED;
attrs->adaptive = SYS_SYNC_NOT_ADAPTIVE;
attrs->ipc_key = 0;
attrs->flags = 0;
attrs->name_u64 = attr->name_u64;
if (error_code res = g_avoid_lwm ? sys_mutex_create(out_id, attrs) : _sys_lwmutex_create(out_id, protocol, lwmutex, 0x80000001, attr->name_u64, 0))
if (s32 res = _sys_lwmutex_create(out_id, protocol, lwmutex, 0x80000001, attr->name_u64, 0))
{
return res;
}
@@ -56,15 +45,10 @@ error_code sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmute
return CELL_OK;
}
error_code sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
s32 sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
{
sysPrxForUser.trace("sys_lwmutex_destroy(lwmutex=*0x%x)", lwmutex);
if (g_avoid_lwm)
{
return sys_mutex_destroy(lwmutex->sleep_queue);
}
// check to prevent recursive locking in the next call
if (lwmutex->vars.owner.load() == ppu.id)
{
@@ -72,13 +56,13 @@ error_code sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
}
// attempt to lock the mutex
if (error_code res = sys_lwmutex_trylock(ppu, lwmutex))
if (s32 res = sys_lwmutex_trylock(ppu, lwmutex))
{
return res;
}
// call the syscall
if (error_code res = _sys_lwmutex_destroy(lwmutex->sleep_queue))
if (s32 res = _sys_lwmutex_destroy(lwmutex->sleep_queue))
{
// unlock the mutex if failed
sys_lwmutex_unlock(ppu, lwmutex);
@@ -92,15 +76,10 @@ error_code sys_lwmutex_destroy(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
return CELL_OK;
}
error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
s32 sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
{
sysPrxForUser.trace("sys_lwmutex_lock(lwmutex=*0x%x, timeout=0x%llx)", lwmutex, timeout);
if (g_avoid_lwm)
{
return sys_mutex_lock(ppu, lwmutex->sleep_queue, timeout);
}
const be_t<u32> tid(ppu.id);
// try to lock lightweight mutex
@@ -167,7 +146,7 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64
}
// lock using the syscall
const error_code res = _sys_lwmutex_lock(ppu, lwmutex->sleep_queue, timeout);
const s32 res = _sys_lwmutex_lock(ppu, lwmutex->sleep_queue, timeout);
lwmutex->all_info--;
@@ -193,15 +172,10 @@ error_code sys_lwmutex_lock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex, u64
return res;
}
error_code sys_lwmutex_trylock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
s32 sys_lwmutex_trylock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
{
sysPrxForUser.trace("sys_lwmutex_trylock(lwmutex=*0x%x)", lwmutex);
if (g_avoid_lwm)
{
return sys_mutex_trylock(ppu, lwmutex->sleep_queue);
}
const be_t<u32> tid(ppu.id);
// try to lock lightweight mutex
@@ -245,7 +219,7 @@ error_code sys_lwmutex_trylock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
if (old_owner == lwmutex_reserved)
{
// should be locked by the syscall
const error_code res = _sys_lwmutex_trylock(lwmutex->sleep_queue);
const s32 res = _sys_lwmutex_trylock(lwmutex->sleep_queue);
if (res == CELL_OK)
{
@@ -262,18 +236,13 @@ error_code sys_lwmutex_trylock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
}
// locked by another thread
return not_an_error(CELL_EBUSY);
return CELL_EBUSY;
}
error_code sys_lwmutex_unlock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
s32 sys_lwmutex_unlock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex)
{
sysPrxForUser.trace("sys_lwmutex_unlock(lwmutex=*0x%x)", lwmutex);
if (g_avoid_lwm)
{
return sys_mutex_unlock(ppu, lwmutex->sleep_queue);
}
const be_t<u32> tid(ppu.id);
// check owner
+16 -103
View File
@@ -1,17 +1,10 @@
#include "stdafx.h"
#include "Utilities/StrUtil.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_mutex.h"
#include "Emu/Cell/lv2/sys_cond.h"
#include "sysPrxForUser.h"
extern logs::channel sysPrxForUser;
using sys_mempool_t = u32;
@@ -22,9 +15,6 @@ struct memory_pool_t
static const u32 id_step = 1;
static const u32 id_count = 1023;
u32 mutexid;
u32 condid;
vm::ptr<void> chunk;
u64 chunk_size;
u64 block_size;
@@ -32,7 +22,13 @@ struct memory_pool_t
std::vector<vm::ptr<void>> free_blocks;
};
s32 sys_mempool_create(ppu_thread& ppu, vm::ptr<sys_mempool_t> mempool, vm::ptr<void> chunk, const u64 chunk_size, const u64 block_size, const u64 ralignment)
vm::ptr<void> sys_mempool_allocate_block(sys_mempool_t mempool)
{
sysPrxForUser.todo("sys_mempool_allocate_block(mempool=%d)", mempool);
return vm::null;
}
s32 sys_mempool_create(vm::ptr<sys_mempool_t> mempool, vm::ptr<void> chunk, const u64 chunk_size, const u64 block_size, const u64 ralignment)
{
sysPrxForUser.warning("sys_mempool_create(mempool=*0x%x, chunk=*0x%x, chunk_size=%d, block_size=%d, ralignment=%d)", mempool, chunk, chunk_size, block_size, ralignment);
@@ -76,65 +72,18 @@ s32 sys_mempool_create(ppu_thread& ppu, vm::ptr<sys_mempool_t> mempool, vm::ptr<
{
memory_pool->free_blocks[i] = vm::ptr<void>::make(chunk.addr() + i * block_size);
}
// Create synchronization variables
vm::var<u32> mutexid;
vm::var<sys_mutex_attribute_t> attr;
attr->protocol = SYS_SYNC_PRIORITY;
attr->recursive = SYS_SYNC_NOT_RECURSIVE;
attr->pshared = SYS_SYNC_NOT_PROCESS_SHARED;
attr->adaptive = SYS_SYNC_NOT_ADAPTIVE;
attr->ipc_key = 0; // No idea what this is
attr->flags = 0; // Also no idea what this is.
strcpy_trunc(attr->name, "mp_m" + std::to_string(*mempool));
error_code ret = sys_mutex_create(mutexid, attr);
if (ret != 0)
{ // TODO: Better exception handling.
fmt::throw_exception("mempool %x failed to create mutex", mempool);
}
memory_pool->mutexid = *mutexid;
vm::var<u32> condid;
vm::var<sys_cond_attribute_t> condAttr;
condAttr->pshared = SYS_SYNC_NOT_PROCESS_SHARED;
condAttr->flags = 0; // No idea what this is
condAttr->ipc_key = 0; // Also no idea what this is
strcpy_trunc(condAttr->name, "mp_c" + std::to_string(*mempool));
ret = sys_cond_create(condid, *mutexid, condAttr);
if (ret != CELL_OK)
{ // TODO: Better exception handling.
fmt::throw_exception("mempool %x failed to create condition variable", mempool);
}
memory_pool->condid = *condid;
return CELL_OK;
}
void sys_mempool_destroy(ppu_thread& ppu, sys_mempool_t mempool)
void sys_mempool_destroy(sys_mempool_t mempool)
{
sysPrxForUser.warning("sys_mempool_destroy(mempool=%d)", mempool);
auto memory_pool = idm::get<memory_pool_t>(mempool);
if (memory_pool)
{
u32 condid = memory_pool->condid;
u32 mutexid = memory_pool->mutexid;
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
idm::remove<memory_pool_t>(mempool);
sys_mutex_unlock(ppu, mutexid);
sys_mutex_destroy(mutexid);
sys_cond_destroy(condid);
}
else
{
sysPrxForUser.error("Trying to destroy an already destroyed mempool=%d", mempool);
}
idm::remove<memory_pool_t>(mempool);
}
s32 sys_mempool_free_block(ppu_thread& ppu, sys_mempool_t mempool, vm::ptr<void> block)
s32 sys_mempool_free_block(sys_mempool_t mempool, vm::ptr<void> block)
{
sysPrxForUser.warning("sys_mempool_free_block(mempool=%d, block=*0x%x)", mempool, block);
@@ -144,21 +93,16 @@ s32 sys_mempool_free_block(ppu_thread& ppu, sys_mempool_t mempool, vm::ptr<void>
return CELL_EINVAL;
}
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
// Cannot free a block not belonging to this memory pool
if (block.addr() > memory_pool->chunk.addr() + memory_pool->chunk_size)
{
sys_mutex_unlock(ppu, memory_pool->mutexid);
return CELL_EINVAL;
}
memory_pool->free_blocks.push_back(block);
sys_cond_signal(ppu, memory_pool->condid);
sys_mutex_unlock(ppu, memory_pool->mutexid);
return CELL_OK;
}
u64 sys_mempool_get_count(ppu_thread& ppu, sys_mempool_t mempool)
u64 sys_mempool_get_count(sys_mempool_t mempool)
{
sysPrxForUser.warning("sys_mempool_get_count(mempool=%d)", mempool);
@@ -167,40 +111,11 @@ u64 sys_mempool_get_count(ppu_thread& ppu, sys_mempool_t mempool)
{
return CELL_EINVAL;
}
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
u64 ret = memory_pool->free_blocks.size();
sys_mutex_unlock(ppu, memory_pool->mutexid);
return ret;
return memory_pool->free_blocks.size();
}
vm::ptr<void> sys_mempool_allocate_block(ppu_thread& ppu, sys_mempool_t mempool)
{
sysPrxForUser.warning("sys_mempool_allocate_block(mempool=%d)", mempool);
auto memory_pool = idm::get<memory_pool_t>(mempool);
if (!memory_pool)
{ // if the memory pool gets deleted-- is null, clearly it's impossible to allocate memory.
return vm::null;
}
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
while (memory_pool->free_blocks.size() == 0) // while is to guard against spurious wakeups
{
sys_cond_wait(ppu, memory_pool->condid, 0);
memory_pool = idm::get<memory_pool_t>(mempool);
if (!memory_pool) // in case spurious wake up was from delete, don't die by accessing a freed pool.
{ // No need to unlock as if the pool is freed, the lock was freed as well.
return vm::null;
}
}
auto block_ptr = memory_pool->free_blocks.back();
memory_pool->free_blocks.pop_back();
sys_mutex_unlock(ppu, memory_pool->mutexid);
return block_ptr;
}
vm::ptr<void> sys_mempool_try_allocate_block(ppu_thread& ppu, sys_mempool_t mempool)
vm::ptr<void> sys_mempool_try_allocate_block(sys_mempool_t mempool)
{
sysPrxForUser.warning("sys_mempool_try_allocate_block(mempool=%d)", mempool);
@@ -211,14 +126,12 @@ vm::ptr<void> sys_mempool_try_allocate_block(ppu_thread& ppu, sys_mempool_t memp
return vm::null;
}
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
auto block_ptr = memory_pool->free_blocks.back();
memory_pool->free_blocks.pop_back();
sys_mutex_unlock(ppu, memory_pool->mutexid);
return block_ptr;
}
void sysPrxForUser_sys_mempool_init()
{
REG_FUNC(sysPrxForUser, sys_mempool_allocate_block);
+61 -46
View File
@@ -567,43 +567,24 @@ namespace sys_net
return -1;
}
if (level != PS3_SOL_SOCKET && level != IPPROTO_TCP)
if (level != SOL_SOCKET && level != IPPROTO_TCP)
{
fmt::throw_exception("Invalid socket option level!" HERE);
}
s32 ret;
if (level == PS3_SOL_SOCKET)
#ifdef _WIN32
if (level == SOL_SOCKET)
{
switch (optname)
{
#ifdef _WIN32
case OP_SO_NBIO:
{
unsigned long mode = *(unsigned long*)optval.get_ptr();
ret = ioctlsocket(sock->s, FIONBIO, &mode);
break;
}
#else
case OP_SO_NBIO:
{
// Obtain the flags
s32 flags = fcntl(s, F_GETFL, 0);
if (flags < 0)
{
fmt::throw_exception("Failed to obtain socket flags." HERE);
}
u32 mode = *(u32*)optval.get_ptr();
flags = mode ? (flags &~O_NONBLOCK) : (flags | O_NONBLOCK);
// Re-set the flags
ret = fcntl(sock->s, F_SETFL, flags);
break;
}
#endif
case OP_SO_SNDBUF:
{
u32 sendbuff = *(u32*)optval.get_ptr();
@@ -642,14 +623,12 @@ namespace sys_net
}
case OP_SO_USECRYPTO:
{
libnet.todo("Socket option OP_SO_USECRYPTO is unimplemented");
ret = CELL_OK;
libnet.warning("Socket option OP_SO_USECRYPTO is unimplemented");
break;
}
case OP_SO_USESIGNATURE:
{
libnet.todo("Socket option OP_SO_USESIGNATURE is unimplemented");
ret = CELL_OK;
libnet.warning("Socket option OP_SO_USESIGNATURE is unimplemented");
break;
}
case OP_SO_BROADCAST:
@@ -665,7 +644,7 @@ namespace sys_net
break;
}
default:
libnet.error("Unknown socket option: 0x%x", optname);
libnet.error("Unknown socket option for Win32: 0x%x", optname);
}
}
else if (level == PROTO_IPPROTO_TCP)
@@ -674,31 +653,71 @@ namespace sys_net
{
case OP_TCP_NODELAY:
{
#ifdef _WIN32
const char delay = *(char*)optval.get_ptr();
ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_NODELAY, &delay, sizeof(delay));
#else
u32 delay = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_NODELAY, &delay, optlen);
#endif
break;
}
case OP_TCP_MAXSEG:
{
#ifdef _WIN32
libnet.warning("TCP_MAXSEG can't be set on Windows.");
#else
u32 maxseg = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_MAXSEG, &maxseg, optlen);
#endif
break;
}
default:
libnet.error("Unknown TCP option: 0x%x", optname);
libnet.error("Unknown TCP option for Win32: 0x%x", optname);
}
}
#else
if (level == SOL_SOCKET)
{
switch (optname)
{
case OP_SO_NBIO:
{
// Obtain the flags
s32 flags = fcntl(s, F_GETFL, 0);
if (flags < 0)
{
fmt::throw_exception("Failed to obtain socket flags." HERE);
}
u32 mode = *(u32*)optval.get_ptr();
flags = mode ? (flags &~O_NONBLOCK) : (flags | O_NONBLOCK);
// Re-set the flags
ret = fcntl(sock->s, F_SETFL, flags);
break;
}
default:
libnet.error("Unknown socket option for Unix: 0x%x", optname);
}
}
else if (level == PROTO_IPPROTO_TCP)
{
switch (optname)
{
case OP_TCP_NODELAY:
{
u32 delay = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_NODELAY, &delay, optlen);
break;
}
case OP_TCP_MAXSEG:
{
u32 maxseg = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, IPPROTO_TCP, TCP_MAXSEG, &maxseg, optlen);
break;
}
default:
libnet.error("Unknown TCP option for Unix: 0x%x", optname);
}
}
#endif
if (ret != 0)
{
@@ -802,8 +821,8 @@ namespace sys_net
s32 socketselect(s32 nfds, vm::ptr<fd_set> readfds, vm::ptr<fd_set> writefds, vm::ptr<fd_set> exceptfds, vm::ptr<timeval> timeout)
{
libnet.warning("socketselect(nfds=%d, readfds=*0x%x, writefds=*0x%x, exceptfds=*0x%x, timeout.tv_sec=%d, timeout.tv_usec=%d)",
nfds, readfds, writefds, exceptfds, timeout->tv_sec, timeout->tv_usec);
libnet.warning("socketselect(nfds=%d, readfds=*0x%x, writefds=*0x%x, exceptfds=*0x%x, timeout=*0x%x)", nfds, readfds, writefds, exceptfds, timeout);
::timeval _timeout;
if (timeout)
@@ -811,12 +830,8 @@ namespace sys_net
_timeout.tv_sec = timeout->tv_sec;
_timeout.tv_usec = timeout->tv_usec;
}
if (_timeout.tv_usec >= 1000000)
{
_timeout.tv_sec = _timeout.tv_sec ? _timeout.tv_sec - 1 : _timeout.tv_sec + 1;
_timeout.tv_usec = 0;
}
//libnet.error("timeval: %d . %d", _timeout.tv_sec, _timeout.tv_usec);
::fd_set _readfds;
::fd_set _writefds;
-3
View File
@@ -9,9 +9,6 @@ namespace vm { using namespace ps3; }
namespace sys_net
{
// It turns out SOL_SOCKET is equal to 1 on Linux, but 0xffff on Windows, and it appears the PS3 uses 0xffff, like Windows
#define PS3_SOL_SOCKET 0xffff
// Error codes
enum
{
+1 -1
View File
@@ -229,7 +229,7 @@ error_code sys_prx_get_module_info(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<s
return _sys_prx_get_module_info(id, 0, opt);
}
error_code sys_prx_get_module_id_by_name(vm::cptr<char> name, u64 flags, vm::ptr<sys_prx_get_module_id_by_name_option_t> pOpt)
error_code sys_prx_get_module_id_by_name(vm::cptr<char> name, u64 flags, vm::ps3::ptr<sys_prx_get_module_id_by_name_option_t> pOpt)
{
sysPrxForUser.trace("sys_prx_get_module_id_by_name(name=%s, flags=0x%x, pOpt=*0x%x)", name, flags, pOpt);
+4 -4
View File
@@ -129,11 +129,11 @@ extern std::string ppu_get_syscall_name(u64 code)
case 152: return "sys_raw_spu_get_int_mask";
case 153: return "sys_raw_spu_set_int_stat";
case 154: return "sys_raw_spu_get_int_stat";
case 155: return "_sys_spu_image_get_information";
case 155: return "sys_spu_image_get_information?";
case 156: return "sys_spu_image_open";
case 157: return "_sys_spu_image_import";
case 158: return "_sys_spu_image_close";
case 159: return "_sys_raw_spu_image_load";
case 157: return "sys_spu_image_import";
case 158: return "sys_spu_image_close";
case 159: return "sys_raw_spu_load";
case 160: return "sys_raw_spu_create";
case 161: return "sys_raw_spu_destroy";
case 163: return "sys_raw_spu_read_puint_mb";
+11 -41
View File
@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "Utilities/VirtualMemory.h"
#include "Utilities/bin_patch.h"
#include "Crypto/sha1.h"
#include "Crypto/unself.h"
#include "Loader/ELF.h"
@@ -202,7 +201,7 @@ static void ppu_initialize_modules(const std::shared_ptr<ppu_linkage_info>& link
&ppu_module_manager::cellSpurs,
&ppu_module_manager::cellSpursJq,
&ppu_module_manager::cellSsl,
&ppu_module_manager::cellSubDisplay,
&ppu_module_manager::cellSubdisplay,
&ppu_module_manager::cellSync,
&ppu_module_manager::cellSync2,
&ppu_module_manager::cellSysconf,
@@ -505,7 +504,7 @@ static auto ppu_load_exports(const std::shared_ptr<ppu_linkage_info>& link, u32
// Static function
const auto _sf = _sm && _sm->functions.count(fnid) ? &_sm->functions.at(fnid) : nullptr;
if (_sf && (_sf->flags & MFF_FORCED_HLE) && g_cfg.core.hook_functions)
if (_sf && (_sf->flags & MFF_FORCED_HLE))
{
// Inject a branch to the HLE implementation
const u32 _entry = vm::read32(faddr);
@@ -933,6 +932,11 @@ void ppu_unload_prx(const lv2_prx& prx)
void ppu_load_exec(const ppu_exec_object& elf)
{
if (g_cfg.core.hook_functions)
{
LOG_TODO(LOADER, "'Hook static functions' option deactivated");
}
// Set for delayed initialization in ppu_initialize()
const auto _main = fxm::make<ppu_module>();
@@ -950,11 +954,6 @@ void ppu_load_exec(const ppu_exec_object& elf)
u32 primary_stacksize = 0x100000;
u32 malloc_pagesize = 0x100000;
// Executable hash
sha1_context sha;
sha1_starts(&sha);
u8 sha1_hash[20];
// Allocate memory at fixed positions
for (const auto& prog : elf.progs)
{
@@ -965,11 +964,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE);
const u32 type = _seg.type = prog.p_type;
const u32 flag = _seg.flags = prog.p_flags;
// Hash big-endian values
sha1_update(&sha, (uchar*)&prog.p_type, sizeof(prog.p_type));
sha1_update(&sha, (uchar*)&prog.p_flags, sizeof(prog.p_flags));
if (type == 0x1 /* LOAD */ && prog.p_memsz)
{
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
@@ -978,11 +973,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
if (!vm::falloc(addr, size, vm::main))
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
// Copy segment data, hash it
// Copy segment data
std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size());
sha1_update(&sha, (uchar*)&prog.p_vaddr, sizeof(prog.p_vaddr));
sha1_update(&sha, (uchar*)&prog.p_memsz, sizeof(prog.p_memsz));
sha1_update(&sha, prog.bin.data(), prog.bin.size());
// Initialize executable code if necessary
if (prog.p_flags & 0x1)
@@ -1012,28 +1004,6 @@ void ppu_load_exec(const ppu_exec_object& elf)
}
}
sha1_finish(&sha, sha1_hash);
// Format patch name
std::string hash("PPU-0000000000000000000000000000000000000000");
for (u32 i = 0; i < sizeof(sha1_hash); i++)
{
constexpr auto pal = "0123456789abcdef";
hash[4 + i * 2] = pal[sha1_hash[i] >> 4];
hash[5 + i * 2] = pal[sha1_hash[i] & 15];
}
// Apply the patch
auto applied = fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr);
if (!Emu.GetTitleID().empty())
{
// Alternative patch
applied += fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr);
}
LOG_NOTICE(LOADER, "PPU executable hash: %s (<- %u)", hash, applied);
// Initialize HLE modules
ppu_initialize_modules(link);
@@ -1198,7 +1168,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
{ "cellFont", "libfont.sprx" },
{ "cellFontFT", "libfontFT.sprx" },
{ "cellFontFT", "libfreetype.sprx" },
{ "cellGcmSys", "libgcm_sys.sprx" },
{ "cellGcmSys", "libgcm_sys.sprx"},
{ "cellGifDec", "libgifdec.sprx" },
{ "cellGifDec", "libsre.sprx" },
{ "cellJpgDec", "libjpgdec.sprx" },
@@ -1294,7 +1264,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
if (!fs::is_dir(lle_dir))
{
LOG_ERROR(GENERAL, "/dev_flash/sys/external/ directory does not exist!"
"\nYou should install the PS3 Firmware (Menu: File -> Install Firmware)."
"\nYou should install the PS3 Firmware (Menu: Tools -> Install Firmware)."
"\nVisit https://rpcs3.net/ for Quickstart Guide and more information.");
}
+1 -1
View File
@@ -189,7 +189,7 @@ public:
static const ppu_static_module cellSpurs;
static const ppu_static_module cellSpursJq;
static const ppu_static_module cellSsl;
static const ppu_static_module cellSubDisplay;
static const ppu_static_module cellSubdisplay;
static const ppu_static_module cellSync;
static const ppu_static_module cellSync2;
static const ppu_static_module cellSysconf;
+4 -54
View File
@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "Utilities/VirtualMemory.h"
#include "Utilities/sysinfo.h"
#include "Crypto/sha1.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
@@ -54,8 +53,6 @@
#include <cfenv>
#include "Utilities/GSL.h"
const bool s_use_rtm = utils::has_rtm();
extern u64 get_system_time();
namespace vm { using namespace ps3; }
@@ -828,26 +825,6 @@ extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
return false;
}
if (s_use_rtm && utils::transaction_enter())
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(static_cast<u32>(ppu.rdata), reg_value);
if (result)
{
vm::reservation_update(addr, sizeof(u32));
vm::notify(addr, sizeof(u32));
}
_xend();
ppu.raddr = 0;
return result;
}
vm::writer_lock lock(0);
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(static_cast<u32>(ppu.rdata), reg_value);
@@ -872,26 +849,6 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
return false;
}
if (s_use_rtm && utils::transaction_enter())
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u64)) && data.compare_and_swap_test(ppu.rdata, reg_value);
if (result)
{
vm::reservation_update(addr, sizeof(u64));
vm::notify(addr, sizeof(u64));
}
_xend();
ppu.raddr = 0;
return result;
}
vm::writer_lock lock(0);
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u64)) && data.compare_and_swap_test(ppu.rdata, reg_value);
@@ -1163,12 +1120,6 @@ extern void ppu_initialize(const ppu_module& info)
sha1_update(&ctx, vm::ps3::_ptr<const u8>(func.addr), func.size);
}
if (info.name == "liblv2.sprx")
{
const be_t<u64> forced_upd = 1;
sha1_update(&ctx, reinterpret_cast<const u8*>(&forced_upd), sizeof(forced_upd));
}
sha1_finish(&ctx, output);
fmt::append(obj_name, "-%016X-%s.obj", reinterpret_cast<be_t<u64>&>(output), jit->cpu());
}
@@ -1191,8 +1142,7 @@ extern void ppu_initialize(const ppu_module& info)
if (fs::is_file(cache_path + obj_name))
{
semaphore_lock lock(jmutex);
jit->add(cache_path + obj_name);
LOG_SUCCESS(PPU, "LLVM: Loaded module %s", obj_name);
ppu_initialize2(*jit, part, cache_path, obj_name);
continue;
}
@@ -1223,7 +1173,7 @@ extern void ppu_initialize(const ppu_module& info)
// Proceed with original JIT instance
semaphore_lock lock(jmutex);
jit->add(cache_path + obj_name);
ppu_initialize2(*jit, part, cache_path, obj_name);
});
}
@@ -1303,8 +1253,6 @@ extern void ppu_initialize(const ppu_module& info)
}
}
}
#else
fmt::throw_exception("LLVM is not available in this build.");
#endif
}
@@ -1338,6 +1286,8 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
std::shared_ptr<MsgDialogBase> dlg;
// Check cached file
if (!fs::is_file(cache_path + obj_name))
{
legacy::FunctionPassManager pm(module.get());
+5 -3
View File
@@ -295,6 +295,7 @@ Value* PPUTranslator::RegLoad(Value*& local)
if (local)
{
// Simple load
assert(!m_globals[index] || m_globals[index]->getType() == local->getType()->getPointerTo());
return local;
}
@@ -306,6 +307,7 @@ Value* PPUTranslator::RegLoad(Value*& local)
void PPUTranslator::RegStore(llvm::Value* value, llvm::Value*& local)
{
const auto glb = RegInit(local);
assert(glb->getType() == value->getType()->getPointerTo());
local = value;
}
@@ -329,7 +331,7 @@ void PPUTranslator::FlushRegisters()
m_ir->SetInsertPoint(block);
}
m_ir->CreateStore(local, m_ir->CreateBitCast(m_globals[index], local->getType()->getPointerTo()));
m_ir->CreateStore(local, m_globals[index]);
m_globals[index] = nullptr;
}
}
@@ -4267,7 +4269,7 @@ Value* PPUTranslator::GetVr(u32 vr, VrType type)
switch (type)
{
case VrType::vi32: return m_ir->CreateBitCast(value, GetType<u32[4]>());
case VrType::vi32: return value;
case VrType::vi8: return m_ir->CreateBitCast(value, GetType<u8[16]>());
case VrType::vi16: return m_ir->CreateBitCast(value, GetType<u16[8]>());
case VrType::vf: return m_ir->CreateBitCast(value, GetType<f32[4]>());
@@ -4296,7 +4298,7 @@ void PPUTranslator::SetVr(u32 vr, Value* value)
}
}
RegStore(value, m_vr[vr]);
RegStore(m_ir->CreateBitCast(value, GetType<u32[4]>()), m_vr[vr]);
}
Value* PPUTranslator::GetCrb(u32 crb)
+17 -31
View File
@@ -5,7 +5,7 @@
const spu_decoder<spu_itype> s_spu_itype;
spu_function_t* SPUDatabase::find(const be_t<u32>* data, u64 key, u32 max_size)
std::shared_ptr<spu_function_t> SPUDatabase::find(const be_t<u32>* data, u64 key, u32 max_size)
{
for (auto found = m_db.equal_range(key); found.first != found.second; found.first++)
{
@@ -14,7 +14,7 @@ spu_function_t* SPUDatabase::find(const be_t<u32>* data, u64 key, u32 max_size)
// Compare binary data explicitly (TODO: optimize)
if (LIKELY(func->size <= max_size) && std::memcmp(func->data.data(), data, func->size) == 0)
{
return func.get();
return func;
}
}
@@ -33,7 +33,7 @@ SPUDatabase::~SPUDatabase()
// TODO: serialize database
}
spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_limit)
std::shared_ptr<spu_function_t> SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_limit)
{
// Check arguments (bounds and alignment)
if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4)
@@ -43,27 +43,23 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
// Key for multimap
const u64 key = entry | u64{ ls[entry / 4] } << 32;
const be_t<u32>* base = ls + entry / 4;
const u32 block_sz = max_limit - entry;
{
reader_lock lock(m_mutex);
// Try to find existing function in the database
if (auto func = find(base, key, block_sz))
if (auto func = find(ls + entry / 4, key, max_limit - entry))
{
return func;
}
}
{
writer_lock lock(m_mutex);
writer_lock lock(m_mutex);
// Double-check
if (auto func = find(base, key, block_sz))
{
return func;
}
// Double-check
if (auto func = find(ls + entry / 4, key, max_limit - entry))
{
return func;
}
// Initialize block entries with the function entry point
@@ -85,15 +81,11 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
const auto type = s_spu_itype.decode(op.opcode);
// Find existing function
if (pos != entry && find(ls + pos / 4, pos | u64{ op.opcode } << 32, limit - pos))
{
reader_lock lock(m_mutex);
// Find existing function
if (pos != entry && find(ls + pos / 4, pos | u64{ op.opcode } << 32, limit - pos))
{
limit = pos;
break;
}
limit = pos;
break;
}
// Additional analysis at the beginning of the block
@@ -319,16 +311,10 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
// Set whether the function can reset stack
func->does_reset_stack = ila_sp_pos < limit;
// Lock here just before we write to the db
// Its is unlikely that the second check will pass anyway so we delay this step since compiling functions is very fast
{
writer_lock lock(m_mutex);
// Add function to the database
m_db.emplace(key, func);
// Add function to the database
m_db.emplace(key, func);
}
LOG_SUCCESS(SPU, "Function detected [0x%05x-0x%05x] (size=0x%x)", func->addr, func->addr + func->size, func->size);
LOG_NOTICE(SPU, "Function detected [0x%05x-0x%05x] (size=0x%x)", func->addr, func->addr + func->size, func->size);
return func.get();
return func;
}
+2 -2
View File
@@ -289,12 +289,12 @@ class SPUDatabase final : spu_itype
std::unordered_multimap<u64, std::shared_ptr<spu_function_t>> m_db;
// For internal use
spu_function_t* find(const be_t<u32>* data, u64 key, u32 max_size);
std::shared_ptr<spu_function_t> find(const be_t<u32>* data, u64 key, u32 max_size);
public:
SPUDatabase();
~SPUDatabase();
// Try to retrieve SPU function information
spu_function_t* analyse(const be_t<u32>* ls, u32 entry, u32 limit = 0x40000);
std::shared_ptr<spu_function_t> analyse(const be_t<u32>* ls, u32 entry, u32 limit = 0x40000);
};
+2 -11
View File
@@ -5,7 +5,6 @@
#include "SPUThread.h"
#include "SPURecompiler.h"
#include "SPUASMJITRecompiler.h"
#include <algorithm>
extern u64 get_system_time();
@@ -23,15 +22,8 @@ void spu_recompiler_base::enter(SPUThread& spu)
// Get SPU LS pointer
const auto _ls = vm::ps3::_ptr<u32>(spu.offset);
// Search if cached data matches
auto func = spu.compiled_cache[spu.pc / 4];
// Check shared db if we dont have a match
if (!func || !std::equal(func->data.begin(), func->data.end(), _ls + spu.pc / 4, [](const be_t<u32>& l, const be_t<u32>& r) { return *(u32*)(u8*)&l == *(u32*)(u8*)&r; }))
{
func = spu.spu_db->analyse(_ls, spu.pc);
spu.compiled_cache[spu.pc / 4] = func;
}
// Always validate (TODO)
const auto func = spu.spu_db->analyse(_ls, spu.pc);
// Reset callstack if necessary
if ((func->does_reset_stack && spu.recursion_level) || spu.recursion_level >= 128)
@@ -40,7 +32,6 @@ void spu_recompiler_base::enter(SPUThread& spu)
return;
}
// Compile if needed
if (!func->compiled)
{
if (!spu.spu_rec)
+10 -146
View File
@@ -1,6 +1,5 @@
#include "stdafx.h"
#include "Utilities/lockless.h"
#include "Utilities/sysinfo.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
@@ -23,8 +22,6 @@
#include <atomic>
#include <thread>
const bool s_use_rtm = utils::has_rtm();
#ifdef _MSC_VER
bool operator ==(const u128& lhs, const u128& rhs)
{
@@ -33,7 +30,6 @@ bool operator ==(const u128& lhs, const u128& rhs)
#endif
extern u64 get_timebased_time();
extern u64 get_system_time();
extern thread_local u64 g_tls_fault_spu;
@@ -59,81 +55,6 @@ void fmt_class_string<spu_decoder_type>::format(std::string& out, u64 arg)
});
}
namespace spu
{
namespace scheduler
{
std::array<std::atomic<u8>, 65536> atomic_instruction_table = {};
constexpr u32 native_jiffy_duration_us = 1500; //About 1ms resolution with a half offset
void acquire_pc_address(u32 pc, u32 timeout_ms = 3)
{
const u8 max_concurrent_instructions = (u8)g_cfg.core.preferred_spu_threads;
const u32 pc_offset = pc >> 2;
if (atomic_instruction_table[pc_offset].load(std::memory_order_consume) >= max_concurrent_instructions)
{
if (timeout_ms > 0)
{
const auto timeout = timeout_ms * 1000u; //convert to microseconds
const auto start = get_system_time();
auto remaining = timeout;
while (atomic_instruction_table[pc_offset].load(std::memory_order_consume) >= max_concurrent_instructions)
{
if (remaining >= native_jiffy_duration_us)
std::this_thread::sleep_for(1ms);
else
std::this_thread::yield();
const auto now = get_system_time();
const auto elapsed = now - start;
if (elapsed > timeout) break;
remaining = timeout - elapsed;
}
}
else
{
//Slight pause if function is overburdened
thread_ctrl::wait_for(100);
}
}
atomic_instruction_table[pc_offset]++;
}
void release_pc_address(u32 pc)
{
const u32 pc_offset = pc >> 2;
atomic_instruction_table[pc_offset]--;
}
struct concurrent_execution_watchdog
{
u32 pc = 0;
bool active = false;
concurrent_execution_watchdog(SPUThread& spu)
:pc(spu.pc)
{
if (g_cfg.core.preferred_spu_threads > 0)
{
acquire_pc_address(pc, (u32)g_cfg.core.spu_delay_penalty);
active = true;
}
}
~concurrent_execution_watchdog()
{
if (active)
release_pc_address(pc);
}
};
}
}
void spu_int_ctrl_t::set(u64 ints)
{
// leave only enabled interrupts
@@ -562,7 +483,6 @@ void SPUThread::do_dma_transfer(const spu_mfc_cmd& args, bool from_mfc)
void SPUThread::process_mfc_cmd()
{
spu::scheduler::concurrent_execution_watchdog watchdog(*this);
LOG_TRACE(SPU, "DMAC: cmd=%s, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", ch_mfc_cmd.cmd, ch_mfc_cmd.lsa, ch_mfc_cmd.eal, ch_mfc_cmd.tag, ch_mfc_cmd.size);
const auto mfc = fxm::check_unlocked<mfc_thread>();
@@ -579,7 +499,7 @@ void SPUThread::process_mfc_cmd()
}
// TODO: investigate lost notifications
std::this_thread::yield();
std::this_thread::sleep_for(0us);
_mm_lfence();
}
};
@@ -624,22 +544,9 @@ void SPUThread::process_mfc_cmd()
thread_ctrl::wait_for(100);
}
}
else if (s_use_rtm && utils::transaction_enter())
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
rtime = vm::reservation_acquire(raddr, 128);
rdata = data;
_xend();
_ref<decltype(rdata)>(ch_mfc_cmd.lsa & 0x3ffff) = rdata;
return ch_atomic_stat.set_value(MFC_GETLLAR_SUCCESS);
}
else
{
// Fast path
rdata = data;
_mm_lfence();
}
@@ -670,36 +577,15 @@ void SPUThread::process_mfc_cmd()
if (raddr == ch_mfc_cmd.eal && rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
{
// TODO: vm::check_addr
if (s_use_rtm && utils::transaction_enter())
vm::writer_lock lock;
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
data = to_write;
result = true;
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
{
data = to_write;
result = true;
vm::reservation_update(raddr, 128);
vm::notify(raddr, 128);
}
_xend();
}
else
{
vm::writer_lock lock;
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
{
data = to_write;
result = true;
vm::reservation_update(raddr, 128);
vm::notify(raddr, 128);
}
vm::reservation_update(raddr, 128);
vm::notify(raddr, 128);
}
}
@@ -735,23 +621,6 @@ void SPUThread::process_mfc_cmd()
// Store unconditionally
// TODO: vm::check_addr
if (s_use_rtm && utils::transaction_enter())
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
data = to_write;
vm::reservation_update(ch_mfc_cmd.eal, 128);
vm::notify(ch_mfc_cmd.eal, 128);
_xend();
ch_atomic_stat.set_value(MFC_PUTLLUC_SUCCESS);
return;
}
vm::writer_lock lock(0);
data = to_write;
vm::reservation_update(ch_mfc_cmd.eal, 128);
@@ -1028,7 +897,7 @@ bool SPUThread::get_ch_value(u32 ch, u32& out)
if (ctr > 10000)
{
ctr = 0;
std::this_thread::yield();
std::this_thread::sleep_for(0us);
}
else
{
@@ -1109,11 +978,6 @@ bool SPUThread::get_ch_value(u32 ch, u32& out)
case SPU_RdDec:
{
out = ch_dec_value - (u32)(get_timebased_time() - ch_dec_start_timestamp);
//Polling: We might as well hint to the scheduler to slot in another thread since this one is counting down
if (g_cfg.core.spu_loop_detection && out > spu::scheduler::native_jiffy_duration_us)
std::this_thread::yield();
return true;
}
-1
View File
@@ -582,7 +582,6 @@ public:
std::exception_ptr pending_exception;
std::array<struct spu_function_t*, 65536> compiled_cache{};
std::shared_ptr<class SPUDatabase> spu_db;
std::shared_ptr<class spu_recompiler_base> spu_rec;
u32 recursion_level = 0;
+5 -5
View File
@@ -195,18 +195,18 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
BIND_FUNC(sys_time_get_current_time), //145 (0x091)
null_func,//BIND_FUNC(sys_time_get_system_time), //146 (0x092) ROOT
BIND_FUNC(sys_time_get_timebase_frequency), //147 (0x093)
BIND_FUNC(_sys_rwlock_trywlock), //148 (0x094)
null_func,//BIND_FUNC(_sys_rwlock_trywlock) //148 (0x094)
null_func, //149 (0x095) UNS
BIND_FUNC(sys_raw_spu_create_interrupt_tag), //150 (0x096)
BIND_FUNC(sys_raw_spu_set_int_mask), //151 (0x097)
BIND_FUNC(sys_raw_spu_get_int_mask), //152 (0x098)
BIND_FUNC(sys_raw_spu_set_int_stat), //153 (0x099)
BIND_FUNC(sys_raw_spu_get_int_stat), //154 (0x09A)
BIND_FUNC(_sys_spu_image_get_information), //155 (0x09B)
null_func,//BIND_FUNC(sys_spu_image_get_information?) //155 (0x09B)
BIND_FUNC(sys_spu_image_open), //156 (0x09C)
BIND_FUNC(_sys_spu_image_import), //157 (0x09D)
BIND_FUNC(_sys_spu_image_close), //158 (0x09E)
BIND_FUNC(_sys_raw_spu_image_load), //159 (0x09F)
null_func,//BIND_FUNC(sys_spu_image_import) //157 (0x09D)
null_func,//BIND_FUNC(sys_spu_image_close) //158 (0x09E)
null_func,//BIND_FUNC(sys_raw_spu_load) //159 (0x09F)
BIND_FUNC(sys_raw_spu_create), //160 (0x0A0)
BIND_FUNC(sys_raw_spu_destroy), //161 (0x0A1)
null_func, //162 (0x0A2) UNS
+11 -15
View File
@@ -2,7 +2,6 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
@@ -13,14 +12,18 @@ namespace vm { using namespace ps3; }
logs::channel sys_cond("sys_cond");
template<> DECLARE(ipc_manager<lv2_cond, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr)
{
sys_cond.warning("sys_cond_create(cond_id=*0x%x, mutex_id=0x%x, attr=*0x%x)", cond_id, mutex_id, attr);
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
{
sys_cond.error("sys_cond_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex)
@@ -28,21 +31,13 @@ error_code sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_
return CELL_ESRCH;
}
if (auto error = lv2_obj::create<lv2_cond>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (const u32 id = idm::make<lv2_obj, lv2_cond>(attr->name_u64, std::move(mutex)))
{
return std::make_shared<lv2_cond>(
attr->pshared,
attr->flags,
attr->ipc_key,
attr->name_u64,
std::move(mutex));
}))
{
return error;
*cond_id = id;
return CELL_OK;
}
*cond_id = idm::last_id();
return CELL_OK;
return CELL_EAGAIN;
}
error_code sys_cond_destroy(u32 cond_id)
@@ -56,6 +51,7 @@ error_code sys_cond_destroy(u32 cond_id)
return CELL_EBUSY;
}
cond.mutex->cond_count--;
return {};
});
+4 -9
View File
@@ -30,20 +30,15 @@ struct lv2_cond final : lv2_obj
atomic_t<u32> waiters{0};
std::deque<cpu_thread*> sq;
lv2_cond(u32 shared, s32 flags, u64 key, u64 name, std::shared_ptr<lv2_mutex> mutex)
: shared(shared)
, key(key)
, flags(flags)
lv2_cond(u64 name, std::shared_ptr<lv2_mutex> mutex)
: shared(0)
, key(0)
, flags(0)
, name(name)
, mutex(std::move(mutex))
{
this->mutex->cond_count++;
}
~lv2_cond()
{
this->mutex->cond_count--;
}
};
class ppu_thread;
+13 -17
View File
@@ -99,12 +99,10 @@ error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queu
return CELL_EINVAL;
}
auto queue = std::make_shared<lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size);
if (event_queue_key == SYS_EVENT_QUEUE_LOCAL)
{
// Not an IPC queue
if (const u32 _id = idm::import_existing<lv2_obj, lv2_event_queue>(std::move(queue)))
if (const u32 _id = idm::make<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size))
{
*equeue_id = _id;
return CELL_OK;
@@ -113,27 +111,25 @@ error_code sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queu
return CELL_EAGAIN;
}
// Create IPC queue
if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> std::shared_ptr<lv2_event_queue>
{
if (const u32 _id = idm::import_existing<lv2_obj, lv2_event_queue>(queue))
{
*equeue_id = _id;
return std::move(queue);
}
std::shared_ptr<lv2_event_queue> result;
return nullptr;
// Create IPC queue
if (!ipc_manager<lv2_event_queue, u64>::add(event_queue_key, [&]() -> const std::shared_ptr<lv2_event_queue>&
{
result = idm::make_ptr<lv2_obj, lv2_event_queue>(protocol, type, attr->name_u64, event_queue_key, size);
return result;
}))
{
return CELL_EEXIST;
}
if (queue)
if (result)
{
return CELL_EAGAIN;
*equeue_id = idm::last_id();
return CELL_OK;
}
return CELL_OK;
return CELL_EAGAIN;
}
error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
@@ -228,8 +224,6 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
{
sys_event.trace("sys_event_queue_receive(equeue_id=0x%x, *0x%x, timeout=0x%llx)", equeue_id, dummy_event, timeout);
ppu.gpr[3] = CELL_OK;
const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError
{
if (queue.type != SYS_PPU_QUEUE)
@@ -269,6 +263,8 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
}
// If cancelled, gpr[3] will be non-zero. Other registers must contain event data.
ppu.gpr[3] = 0;
while (!ppu.state.test_and_reset(cpu_flag::signal))
{
if (timeout)
+10 -17
View File
@@ -2,7 +2,6 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
@@ -14,8 +13,6 @@ namespace vm { using namespace ps3; }
logs::channel sys_event_flag("sys_event_flag");
template<> DECLARE(ipc_manager<lv2_event_flag, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init)
@@ -40,6 +37,12 @@ error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribu
return CELL_EINVAL;
}
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
{
sys_event_flag.error("sys_event_flag_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
const u32 type = attr->type;
if (type != SYS_SYNC_WAITER_SINGLE && type != SYS_SYNC_WAITER_MULTIPLE)
@@ -48,23 +51,13 @@ error_code sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribu
return CELL_EINVAL;
}
if (auto error = lv2_obj::create<lv2_event_flag>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (const u32 _id = idm::make<lv2_obj, lv2_event_flag>(protocol, type, attr->name_u64, init))
{
return std::make_shared<lv2_event_flag>(
attr->protocol,
attr->pshared,
attr->ipc_key,
attr->flags,
attr->type,
attr->name_u64,
init);
}))
{
return error;
*id = _id;
return CELL_OK;
}
*id = idm::last_id();
return CELL_OK;
return CELL_EAGAIN;
}
error_code sys_event_flag_destroy(u32 id)
+4 -4
View File
@@ -45,11 +45,11 @@ struct lv2_event_flag final : lv2_obj
atomic_t<u64> pattern;
std::deque<cpu_thread*> sq;
lv2_event_flag(u32 protocol, u32 shared, u64 key, s32 flags, s32 type, u64 name, u64 pattern)
lv2_event_flag(u32 protocol, s32 type, u64 name, u64 pattern)
: protocol(protocol)
, shared(shared)
, key(key)
, flags(flags)
, shared(0)
, key(0)
, flags(0)
, type(type)
, name(name)
, pattern(pattern)
+11 -17
View File
@@ -24,7 +24,7 @@ error_code _sys_lwcond_create(vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sy
return CELL_ESRCH;
}
if (const u32 id = idm::make<lv2_obj, lv2_lwcond>(name, lwmutex_id, control))
if (const u32 id = idm::make<lv2_obj, lv2_lwcond>(name, lwmutex_id))
{
*lwcond_id = id;
return CELL_OK;
@@ -79,9 +79,9 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3
{
mutex = idm::check_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (cond.waiters)
if (mutex && cond.waiters)
{
semaphore_lock lock(cond.mutex);
semaphore_lock lock(mutex->mutex);
cpu_thread* result = nullptr;
@@ -99,7 +99,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3
}
else
{
result = cond.schedule<ppu_thread>(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK);
result = cond.schedule<ppu_thread>(cond.sq, mutex->protocol);
}
if (result)
@@ -111,10 +111,8 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u3
static_cast<ppu_thread*>(result)->gpr[3] = CELL_EBUSY;
}
if (mode == 1)
if (mode != 2 && !mutex->signaled.fetch_op([](u32& v) { if (v) v--; }))
{
verify(HERE), !mutex->signaled;
semaphore_lock lock(mutex->mutex);
mutex->sq.emplace_back(result);
result = nullptr;
mode = 2; // Enforce CELL_OK
@@ -172,13 +170,13 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
{
mutex = idm::check_unlocked<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (cond.waiters)
if (mutex && cond.waiters)
{
semaphore_lock lock(cond.mutex);
semaphore_lock lock(mutex->mutex);
u32 result = 0;
while (const auto cpu = cond.schedule<ppu_thread>(cond.sq, cond.control->lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK))
while (const auto cpu = cond.schedule<ppu_thread>(cond.sq, mutex->protocol))
{
cond.waiters--;
@@ -187,10 +185,8 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
static_cast<ppu_thread*>(cpu)->gpr[3] = CELL_EBUSY;
}
if (mode == 1)
if (mode != 2 && !mutex->signaled.fetch_op([](u32& v) { if (v) v--; }))
{
verify(HERE), !mutex->signaled;
semaphore_lock lock(mutex->mutex);
mutex->sq.emplace_back(cpu);
}
else
@@ -241,15 +237,13 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
return nullptr;
}
semaphore_lock lock(cond.mutex);
semaphore_lock lock(mutex->mutex);
// Add a waiter
cond.waiters++;
cond.sq.emplace_back(&ppu);
cond.sleep(ppu, timeout);
semaphore_lock lock2(mutex->mutex);
// Process lwmutex sleep queue
if (const auto cpu = mutex->schedule<ppu_thread>(mutex->sq, mutex->protocol))
{
@@ -280,7 +274,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
if (passed >= timeout)
{
semaphore_lock lock(cond->mutex);
semaphore_lock lock(mutex->mutex);
if (!cond->unqueue(cond->sq, &ppu))
{
+1 -4
View File
@@ -25,16 +25,13 @@ struct lv2_lwcond final : lv2_obj
const u64 name;
const u32 lwid;
vm::ps3::ptr<sys_lwcond_t> control;
semaphore<> mutex;
atomic_t<u32> waiters{0};
std::deque<cpu_thread*> sq;
lv2_lwcond(u64 name, u32 lwid, vm::ps3::ptr<sys_lwcond_t> control)
lv2_lwcond(u64 name, u32 lwid)
: name(name)
, lwid(lwid)
, control(control)
{
}
};
+16 -24
View File
@@ -2,7 +2,6 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
@@ -12,8 +11,6 @@ namespace vm { using namespace ps3; }
logs::channel sys_mutex("sys_mutex");
template<> DECLARE(ipc_manager<lv2_mutex, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
@@ -25,53 +22,48 @@ error_code sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t
return CELL_EFAULT;
}
switch (attr->protocol)
const u32 protocol = attr->protocol;
switch (protocol)
{
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT:
sys_mutex.fatal("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT");
sys_mutex.todo("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT");
break;
default:
{
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", attr->protocol);
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", protocol);
return CELL_EINVAL;
}
}
switch (attr->recursive)
const u32 recursive = attr->recursive;
switch (recursive)
{
case SYS_SYNC_RECURSIVE: break;
case SYS_SYNC_NOT_RECURSIVE: break;
default:
{
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", attr->recursive);
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", recursive);
return CELL_EINVAL;
}
}
if (attr->adaptive != SYS_SYNC_NOT_ADAPTIVE)
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->adaptive != SYS_SYNC_NOT_ADAPTIVE || attr->ipc_key || attr->flags)
{
sys_mutex.todo("sys_mutex_create(): unexpected adaptive (0x%x)", attr->adaptive);
sys_mutex.error("sys_mutex_create(): unknown attributes (pshared=0x%x, adaptive=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->adaptive, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
if (auto error = lv2_obj::create<lv2_mutex>(attr->pshared, attr->ipc_key, attr->flags, [&]()
if (const u32 id = idm::make<lv2_obj, lv2_mutex>(protocol, recursive, attr->name_u64))
{
return std::make_shared<lv2_mutex>(
attr->protocol,
attr->recursive,
attr->pshared,
attr->adaptive,
attr->ipc_key,
attr->flags,
attr->name_u64);
}))
{
return error;
*mutex_id = id;
return CELL_OK;
}
*mutex_id = idm::last_id();
return CELL_OK;
return CELL_EAGAIN;
}
error_code sys_mutex_destroy(u32 mutex_id)
+5 -5
View File
@@ -37,13 +37,13 @@ struct lv2_mutex final : lv2_obj
atomic_t<u32> cond_count{0}; // Condition Variables
std::deque<cpu_thread*> sq;
lv2_mutex(u32 protocol, u32 recursive, u32 shared, u32 adaptive, u64 key, s32 flags, u64 name)
lv2_mutex(u32 protocol, u32 recursive, u64 name)
: protocol(protocol)
, recursive(recursive)
, shared(shared)
, adaptive(adaptive)
, key(key)
, flags(flags)
, shared(0)
, adaptive(0)
, key(0)
, flags(0)
, name(name)
{
}
+1 -1
View File
@@ -306,7 +306,7 @@ error_code _sys_prx_get_module_list(u64 flags, vm::ptr<sys_prx_get_module_list_o
error_code _sys_prx_get_module_info(u32 id, u64 flags, vm::ptr<sys_prx_module_info_option_t> pOpt)
{
sys_prx.todo("_sys_prx_get_module_info(id=0x%x, flags=%d, pOpt=*0x%x)", id, flags, pOpt);
sys_prx.todo("_sys_prx_get_module_info(id=%d, flags=%d, pOpt=*0x%x)", id, flags, pOpt);
return CELL_OK;
}
+1 -8
View File
@@ -43,14 +43,7 @@ struct sys_prx_load_module_option_t
vm::ps3::bptr<void> base_addr;
};
struct sys_prx_segment_info_t
{
be_t<u64> base;
be_t<u64> filesz;
be_t<u64> memsz;
be_t<u64> index;
be_t<u64> type;
};
struct sys_prx_segment_info_t;// TODO
struct sys_prx_module_info_t
{
+269 -196
View File
@@ -14,13 +14,94 @@ logs::channel sys_rsx("sys_rsx");
extern u64 get_timebased_time();
struct SysRsxConfig {
be_t<u32> rsx_event_port{ 0 };
u32 driverInfo{ 0 };
struct RsxDriverInfo {
be_t<u32> version_driver; // 0x0
be_t<u32> version_gpu; // 0x4
be_t<u32> memory_size; // 0x8
be_t<u32> hardware_channel; // 0xC
be_t<u32> nvcore_frequency; // 0x10
be_t<u32> memory_frequency; // 0x14
be_t<u32> unk1[4]; // 0x18 - 0x24
be_t<u32> unk2; // 0x28 -- pgraph stuff
be_t<u32> reportsNotifyOffset;// 0x2C offset to notify memory
be_t<u32> reportsOffset; // 0x30 offset to reports memory
be_t<u32> reportsReportOffset;// 0x34 offset to reports in reports memory
be_t<u32> unk3[6]; // 0x38-0x54
be_t<u32> systemModeFlags; // 0x54
u8 unk4[0x1064]; // 0x10B8
struct Head {
be_t<u64> lastFlipTime; // 0x0 last flip time
be_t<u32> flipFlags; // 0x8 flags to handle flip/queue
be_t<u32> unk1; // 0xC
be_t<u32> flipBufferId; // 0x10
be_t<u32> queuedBufferId; // 0x14 todo: this is definately not this variable but its 'unused' so im using it for queueId to pass to flip handler
be_t<u32> unk3; // 0x18
be_t<u32> unk6; // 0x18 possible low bits of time stamp? used in getlastVBlankTime
be_t<u64> lastSecondVTime; // 0x20 last time for second vhandler freq
be_t<u64> unk4; // 0x28
be_t<u64> vBlankCount; // 0x30
be_t<u32> unk; // 0x38 possible u32, 'flip field', top/bottom for interlaced
be_t<u32> unk5; // 0x3C possible high bits of time stamp? used in getlastVBlankTime
} head[8]; // size = 0x40, 0x200
be_t<u32> unk7; // 0x12B8
be_t<u32> unk8; // 0x12BC
be_t<u32> handlers; // 0x12C0 -- flags showing which handlers are set
be_t<u32> unk9; // 0x12C4
be_t<u32> unk10; // 0x12C8
be_t<u32> userCmdParam; // 0x12CC
be_t<u32> handler_queue; // 0x12D0
be_t<u32> unk11; // 0x12D4
be_t<u32> unk12; // 0x12D8
be_t<u32> unk13; // 0x12DC
be_t<u32> unk14; // 0x12E0
be_t<u32> unk15; // 0x12E4
be_t<u32> unk16; // 0x12E8
be_t<u32> unk17; // 0x12F0
be_t<u32> lastError; // 0x12F4 error param for cellGcmSetGraphicsHandler
// todo: theres more to this
};
template <size_t S> class Sizer { };
Sizer<sizeof(RsxDriverInfo)> foo;
static_assert(sizeof(RsxDriverInfo) == 0x12F8, "rsxSizeTest");
static_assert(sizeof(RsxDriverInfo::Head) == 0x40, "rsxHeadSizeTest");
struct RsxDmaControl {
u8 resv[0x40];
be_t<u32> put;
be_t<u32> get;
be_t<u32> ref;
be_t<u32> unk[2];
be_t<u32> unk1;
};
struct RsxSemaphore {
be_t<u32> val;
be_t<u32> pad;
be_t<u64> timestamp;
};
struct RsxNotify {
be_t<u64> timestamp;
be_t<u64> zero;
};
struct RsxReport {
be_t<u64> timestamp;
be_t<u32> val;
be_t<u32> pad;
};
struct RsxReports {
RsxSemaphore semaphore[0x100];
RsxNotify notify[64];
RsxReport report[2048];
};
be_t<u32> g_rsx_event_port{ 0 };
u32 g_driverInfo{ 0 };
u64 rsxTimeStamp() {
return get_timebased_time();
return get_timebased_time();
}
s32 sys_rsx_device_open()
@@ -49,10 +130,10 @@ s32 sys_rsx_device_close()
*/
s32 sys_rsx_memory_allocate(vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7)
{
sys_rsx.warning("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7);
sys_rsx.todo("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7);
*mem_handle = 1;
*mem_addr = vm::falloc(0xC0000000, size, vm::video);
*mem_handle = 1;
*mem_addr = vm::falloc(0xC0000000, size, vm::video);
return CELL_OK;
}
@@ -79,83 +160,87 @@ s32 sys_rsx_memory_free(u32 mem_handle)
*/
s32 sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_dma_control, vm::ptr<u64> lpar_driver_info, vm::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode)
{
sys_rsx.warning("sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx)",
context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, system_mode);
sys_rsx.todo("sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx)",
context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, system_mode);
auto m_sysrsx = fxm::make<SysRsxConfig>();
if (!m_sysrsx)
fmt::throw_exception("sys_rsx_context_allocate called twice.");
vm::falloc(0x40000000, 0x10000000, vm::rsx_context);
u32 addr = vm::falloc(0x40000000, 0x400000);
if (addr == 0 || addr != 0x40000000)
fmt::throw_exception("Failed to alloc 0x40000000.");
*context_id = 0x55555555;
*context_id = 0x55555555;
*lpar_dma_control = 0x40100000;
*lpar_driver_info = 0x40200000;
*lpar_reports = 0x40300000;
*lpar_dma_control = 0x40100000;
*lpar_driver_info = 0x40200000;
*lpar_reports = 0x40300000;
auto &reports = vm::_ref<RsxReports>(*lpar_reports);
std::memset(&reports, 0, sizeof(RsxReports));
auto &reports = vm::_ref<RsxReports>(*lpar_reports);
std::memset(&reports, 0, sizeof(RsxReports));
for (int i = 0; i < 64; ++i)
reports.notify[i].timestamp = (u64)-1;
for (int i = 0; i < 64; ++i)
reports.notify[i].timestamp = (u64)-1;
for (int i = 0; i < 256; ++i) {
reports.semaphore[i].val = 0x1337C0D3;
reports.semaphore[i].pad = 0x1337BABE;
reports.semaphore[i].timestamp = (u64)-1; // technically different but should be fine
}
for (int i = 0; i < 256; ++i) {
reports.semaphore[i].val = 0x1337C0D3;
reports.semaphore[i].pad = 0x1337BABE;
reports.semaphore[i].timestamp = (u64)-1; // technically different but should be fine
}
for (int i = 0; i < 2048; ++i)
reports.report[i].timestamp = (u64)-1;
for (int i = 0; i < 2048; ++i)
reports.report[i].timestamp = (u64)-1;
auto &sysReports = vm::_ref<RsxSemaphore>(0x40000030);
// slight hack for testing....
sysReports.val = 1;
auto &driverInfo = vm::_ref<RsxDriverInfo>(*lpar_driver_info);
auto &driverInfo = vm::_ref<RsxDriverInfo>(*lpar_driver_info);
std::memset(&driverInfo, 0, sizeof(RsxDriverInfo));
std::memset(&driverInfo, 0, sizeof(RsxDriverInfo));
driverInfo.version_driver = 0x211;
driverInfo.version_gpu = 0x5c;
driverInfo.memory_size = 0xFE00000;
driverInfo.nvcore_frequency = 500000000; // 0x1DCD6500
driverInfo.memory_frequency = 650000000; // 0x26BE3680
driverInfo.reportsNotifyOffset = 0x1000;
driverInfo.reportsOffset = 0;
driverInfo.reportsReportOffset = 0x1400;
driverInfo.systemModeFlags = system_mode;
driverInfo.hardware_channel = 1; // * i think* this 1 for games, 0 for vsh
driverInfo.version_driver = 0x211;
driverInfo.version_gpu = 0x5c;
driverInfo.memory_size = 0xFE00000;
driverInfo.nvcore_frequency = 500000000; // 0x1DCD6500
driverInfo.memory_frequency = 650000000; // 0x26BE3680
driverInfo.reportsNotifyOffset = 0x1000;
driverInfo.reportsOffset = 0;
driverInfo.reportsReportOffset = 0x1400;
driverInfo.systemModeFlags = system_mode;
driverInfo.hardware_channel = 1; // * i think* this 1 for games, 0 for vsh
m_sysrsx->driverInfo = *lpar_driver_info;
g_driverInfo = *lpar_driver_info;
auto &dmaControl = vm::_ref<RsxDmaControl>(*lpar_dma_control);
dmaControl.get = 0;
dmaControl.put = 0;
dmaControl.ref = 0xFFFFFFFF;
auto &dmaControl = vm::_ref<RsxDmaControl>(*lpar_dma_control);
dmaControl.get = 0;
dmaControl.put = 0;
dmaControl.ref = 0xFFFFFFFF;
if (false/*system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB*/)
RSXIOMem.SetRange(0, 0x20000000 /*512MB*/);
else
RSXIOMem.SetRange(0, 0x10000000 /*256MB*/);
if (false/*system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB*/)
RSXIOMem.SetRange(0, 0x20000000 /*512MB*/);
else
RSXIOMem.SetRange(0, 0x10000000 /*256MB*/);
sys_event_queue_attribute_t attr;
attr.protocol = SYS_SYNC_PRIORITY;
attr.type = SYS_PPU_QUEUE;
auto queueId = vm::make_var<u32>(0);
sys_event_queue_create(queueId, vm::make_var(attr), 0, 0x20);
driverInfo.handler_queue = queueId->value();
sys_event_queue_attribute_t attr;
attr.protocol = SYS_SYNC_PRIORITY;
attr.type = SYS_PPU_QUEUE;
auto queueId = vm::make_var<u32>(0);
sys_event_queue_create(queueId, vm::make_var(attr), 0, 0x20);
driverInfo.handler_queue = queueId->value();
sys_event_port_create(queueId, SYS_EVENT_PORT_LOCAL, 0);
sys_event_port_connect_local(queueId->value(), driverInfo.handler_queue);
sys_event_port_create(queueId, SYS_EVENT_PORT_LOCAL, 0);
sys_event_port_connect_local(queueId->value(), driverInfo.handler_queue);
m_sysrsx->rsx_event_port = queueId->value();
g_rsx_event_port = queueId->value();
const auto render = fxm::get<GSRender>();
render->display_buffers_count = 0;
render->current_display_buffer = 0;
render->main_mem_addr = 0;
render->label_addr = *lpar_reports;
render->init(0, 0, *lpar_dma_control, 0xC0000000);
const auto render = fxm::get<GSRender>();
render->ctrl = vm::_ptr<CellGcmControl>(*lpar_dma_control);
//render->intr_thread = idm::make_ptr<ppu_thread>("_gcm_intr_thread", 1, 0x4000);
//render->intr_thread->run();
//render->ctxt_addr = 0;
render->gcm_buffers.set((vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main)));
render->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main);
render->gcm_buffers_count = 0;
render->gcm_current_buffer = 0;
render->main_mem_addr = 0;
render->label_addr = *lpar_reports;
render->init(0x30100000, 0x200000, *lpar_dma_control, 0xC0000000);
return CELL_OK;
}
@@ -181,11 +266,11 @@ s32 sys_rsx_context_free(u32 context_id)
*/
s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
{
sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
if (size == 0) return CELL_OK;
if (RSXIOMem.Map(ea, size, io))
return CELL_OK;
return CELL_EINVAL;
sys_rsx.todo("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
if (RSXIOMem.Map(ea, size, io))
return CELL_OK;
LOG_ERROR(RSX, "rsx_iomap failed");
return CELL_EINVAL;
}
/*
@@ -197,140 +282,128 @@ s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
*/
s32 sys_rsx_context_iounmap(u32 context_id, u32 io_addr, u32 a3, u32 size)
{
sys_rsx.warning("sys_rsx_context_iounmap(context_id=0x%x, io_addr=0x%x, a3=0x%x, size=0x%x)", context_id, io_addr, a3, size);
if (RSXIOMem.UnmapAddress(io_addr, size))
return CELL_OK;
return CELL_EINVAL;
sys_rsx.todo("sys_rsx_context_iounmap(context_id=0x%x, io_addr=0x%x, a3=0x%x, size=0x%x)", context_id, io_addr, a3, size);
if (RSXIOMem.UnmapAddress(io_addr, size))
return CELL_OK;
LOG_ERROR(RSX, "rsx_iounmap failed");
return CELL_EINVAL;
}
/*
* lv2 SysCall 674 (0x2A2): sys_rsx_context_attribute
* @param context_id (IN): RSX context, e.g. 0x55555555
* @param package_id (IN):
* @param a3 (IN):
* @param a4 (IN):
* @param a5 (IN):
* @param a6 (IN):
* @param package_id (IN):
* @param a3 (IN):
* @param a4 (IN):
* @param a5 (IN):
* @param a6 (IN):
*/
s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6)
{
// Flip/queue/user command/vblank as trace to help with log spam
if (package_id == 0x102 || package_id == 0x103 || package_id == 0xFED || package_id == 0xFEF)
sys_rsx.trace("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
else
sys_rsx.warning("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
if (package_id != 0xFED)
sys_rsx.todo("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
// todo: these event ports probly 'shouldnt' be here as i think its supposed to be interrupts that are sent from rsx somewhere in lv1
// hle/lle protection
if (g_driverInfo == 0)
return CELL_OK;
// todo: these event ports probly 'shouldnt' be here as i think its supposed to be interrupts that are sent from rsx somewhere in lv1
const auto render = fxm::get<GSRender>();
//hle protection
if (render->isHLE)
return 0;
auto m_sysrsx = fxm::get<SysRsxConfig>();
auto &driverInfo = vm::_ref<RsxDriverInfo>(m_sysrsx->driverInfo);
switch (package_id)
const auto render = fxm::get<GSRender>();
auto &driverInfo = vm::_ref<RsxDriverInfo>(g_driverInfo);
switch(package_id)
{
case 0x001: // FIFO
render->ctrl->get = a3;
render->ctrl->put = a4;
render->ctrl->get = a3;
render->ctrl->put = a4;
break;
case 0x100: // Display mode set
break;
case 0x101: // Display sync set, cellGcmSetFlipMode
// a4 == 2 is vsync, a4 == 1 is hsync
render->requested_vsync.store(a4 == 2);
break;
break;
case 0x101: // Display sync set, cellGcmSetFlipMode
break;
case 0x102: // Display flip
driverInfo.head[a3].flipFlags |= 0x80000000;
driverInfo.head[a3].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
// lets give this a shot for giving bufferid back to gcm
driverInfo.head[a3].flipBufferId = driverInfo.head[a3].queuedBufferId;
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
vm::_ref<u32>(0x40300010) = 0;
if (a3 == 0)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0);
if (a3 == 1)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 4), 0);
driverInfo.head[a3].flipFlags |= 0x80000000;
driverInfo.head[a3].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
// lets give this a shot for giving bufferid back to gcm
driverInfo.head[a3].flipBufferId = driverInfo.head[a3].queuedBufferId;
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
vm::_ref<u32>(0x40300010) = 0;
if (a3 == 0)
sys_event_port_send(g_rsx_event_port, 0, (1 << 3), 0);
if (a3 == 1)
sys_event_port_send(g_rsx_event_port, 0, (1 << 4), 0);
break;
case 0x103: // Display Queue
driverInfo.head[a3].queuedBufferId = a4;
driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4);
if (a3 == 0)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 5), 0);
if (a3 == 1)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 6), 0);
driverInfo.head[a3].queuedBufferId = a4;
driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4);
if (a3 == 0)
sys_event_port_send(g_rsx_event_port, 0, (1 << 5), 0);
if (a3 == 1)
sys_event_port_send(g_rsx_event_port, 0, (1 << 6), 0);
break;
case 0x104: // Display buffer
{
u8 id = a3 & 0xFF;
u32 width = (a4 >> 32) & 0xFFFFFFFF;
u32 height = a4 & 0xFFFFFFFF;
u32 pitch = (a5 >> 32) & 0xFFFFFFFF;
u32 offset = a5 & 0xFFFFFFFF;
if (id > 7)
return -17;
render->display_buffers[id].width = width;
render->display_buffers[id].height = height;
render->display_buffers[id].pitch = pitch;
render->display_buffers[id].offset = offset;
{
u8 id = a3 & 0xFF;
u32 width = (a4 >> 32) & 0xFFFFFFFF;
u32 height = a4 & 0xFFFFFFFF;
u32 pitch = (a5 >> 32) & 0xFFFFFFFF;
u32 offset = a5 & 0xFFFFFFFF;
if (id > 7)
return -17;
render->gcm_buffers[id].width = width;
render->gcm_buffers[id].height = height;
render->gcm_buffers[id].pitch = pitch;
render->gcm_buffers[id].offset = offset;
render->display_buffers_count = std::max((u32)id + 1, render->display_buffers_count);
}
if (id + 1 > render->gcm_buffers_count)
render->gcm_buffers_count = id + 1;
}
break;
case 0x105: // destroy buffer?
break;
case 0x105: // destroy buffer?
break;
case 0x106: // ? (Used by cellGcmInitPerfMon)
break;
case 0x108: // cellGcmSetSecondVFrequency
// a4 == 3, CELL_GCM_DISPLAY_FREQUENCY_59_94HZ
// a4 == 2, CELL_GCM_DISPLAY_FREQUENCY_SCANOUT
// a4 == 4, CELL_GCM_DISPLAY_FREQUENCY_DISABLE
// Note: Scanout/59_94 is ignored currently as we report refresh rate of 59_94hz as it is, so the difference doesnt matter
render->enable_second_vhandler.store(a4 != 4);
break;
case 0x108: // ? set interrupt freq?
break;
case 0x10a: // ? Involved in managing flip status through cellGcmResetFlipStatus
{
if (a3 > 7)
return -17;
u32 flipStatus = driverInfo.head[a3].flipFlags;
flipStatus = (flipStatus & a4) | a5;
driverInfo.head[a3].flipFlags = flipStatus;
}
{
if (a3 > 7)
return -17;
u32 flipStatus = driverInfo.head[a3].flipFlags;
flipStatus = (flipStatus & a4) | a5;
driverInfo.head[a3].flipFlags = flipStatus;
}
break;
case 0x10D: // Called by cellGcmInitCursor
break;
case 0x10D: // Called by cellGcmInitCursor
break;
case 0x300: // Tiles
{
//a4 high bits = ret.tile = (location + 1) | (bank << 4) | ((offset / 0x10000) << 16) | (location << 31);
//a4 low bits = ret.limit = ((offset + size - 1) / 0x10000) << 16 | (location << 31);
//a5 high bits = ret.pitch = (pitch / 0x100) << 8;
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
{
//a4 high bits = ret.tile = (location + 1) | (bank << 4) | ((offset / 0x10000) << 16) | (location << 31);
//a4 low bits = ret.limit = ((offset + size - 1) / 0x10000) << 16 | (location << 31);
//a5 high bits = ret.pitch = (pitch / 0x100) << 8;
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
auto& tile = render->tiles[a3];
tile.location = ((a4 >> 32) & 0xF) - 1;
tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000);
tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset;
tile.pitch = (((a5 >> 32) & 0xFFFFFFFF) >> 8) * 0x100;
tile.comp = ((a5 & 0xFFFFFFFF) >> 26) & 0xF;
tile.base = (a5 & 0xFFFFFFFF) & 0x7FF;
tile.bank = (((a4 >> 32) & 0xFFFFFFFF) >> 4) & 0xF;
tile.binded = a5 != 0;
}
auto& tile = render->tiles[a3];
tile.location = ((a4 >> 32) & 0xF) - 1;
tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000);
tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset;
tile.pitch = (((a5 >> 32) & 0xFFFFFFFF) >> 8) * 0x100;
tile.comp = ((a5 & 0xFFFFFFFF) >> 26) & 0xF;
tile.base = (a5 & 0xFFFFFFFF) & 0x7FF;
tile.bank = (((a4 >> 32) & 0xFFFFFFFF) >> 4) & 0xF;
tile.binded = a5 != 0;
}
break;
case 0x301: // Depth-buffer (Z-cull)
break;
case 0x302: // something with zcull
break;
case 0x302: // something with zcull
break;
case 0x600: // Framebuffer setup
break;
@@ -340,24 +413,24 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
case 0x602: // Framebuffer blit sync
break;
case 0x603: // Framebuffer close
break;
case 0x603: // Framebuffer close
break;
case 0xFED: // hack: vblank command
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
driverInfo.head[a3].vBlankCount++;
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 1), 0);
if (render->enable_second_vhandler)
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 11), 0); // second vhandler
break;
case 0xFEF: // hack: user command
// 'custom' invalid package id for now
// as i think we need custom lv1 interrupts to handle this accurately
// this also should probly be set by rsxthread
driverInfo.userCmdParam = a4;
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 7), 0);
break;
case 0xFED: // hack: vblank command
// todo: this is wrong and should be 'second' vblank handler and freq
// although gcmSys seems just hardcoded at 1, so w/e
driverInfo.head[a3].vBlankCount++;
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
sys_event_port_send(g_rsx_event_port, 0, (1 << 1), 0);
sys_event_port_send(g_rsx_event_port, 0, (1 << 11), 0); // second vhandler
break;
case 0xFEF: // hack: user command
// 'custom' invalid package id for now
// as i think we need custom lv1 interrupts to handle this accurately
// this also should probly be set by rsxthread
driverInfo.userCmdParam = a4;
sys_event_port_send(g_rsx_event_port, 0, (1 << 7), 0);
break;
default:
return CELL_EINVAL;
}
@@ -373,17 +446,17 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
*/
s32 sys_rsx_device_map(vm::ptr<u64> addr, vm::ptr<u64> a2, u32 dev_id)
{
sys_rsx.warning("sys_rsx_device_map(addr=*0x%x, a2=*0x%x, dev_id=0x%x)", addr, a2, dev_id);
sys_rsx.todo("sys_rsx_device_map(addr=*0x%x, a2=*0x%x, dev_id=0x%x)", addr, a2, dev_id);
if (dev_id != 8) {
if (dev_id != 8) {
// TODO: lv1 related
fmt::throw_exception("sys_rsx_device_map: Invalid dev_id %d", dev_id);
fmt::throw_exception("sys_rsx_device_map: Invalid dev_id %d", dev_id);
}
// a2 seems to not be referenced in cellGcmSys
*a2 = 0;
// a2 seems to not be referenced in cellGcmSys
*a2 = 0;
*addr = 0x40000000;
*addr = 0x40000000;
return CELL_OK;
}
@@ -400,11 +473,11 @@ s32 sys_rsx_device_unmap(u32 dev_id)
}
/*
* lv2 SysCall 677 (0x2A5): sys_rsx_attribute
*/
* lv2 SysCall 677 (0x2A5): sys_rsx_attribute
*/
s32 sys_rsx_attribute(u32 packageId, u32 a2, u32 a3, u32 a4, u32 a5)
{
sys_rsx.warning("sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", packageId, a2, a3, a4, a5);
sys_rsx.todo("sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", packageId, a2, a3, a4, a5);
return CELL_OK;
}
}
+1 -89
View File
@@ -1,93 +1,5 @@
#pragma once
struct RsxDriverInfo {
be_t<u32> version_driver; // 0x0
be_t<u32> version_gpu; // 0x4
be_t<u32> memory_size; // 0x8
be_t<u32> hardware_channel; // 0xC
be_t<u32> nvcore_frequency; // 0x10
be_t<u32> memory_frequency; // 0x14
be_t<u32> unk1[4]; // 0x18 - 0x24
be_t<u32> unk2; // 0x28 -- pgraph stuff
be_t<u32> reportsNotifyOffset;// 0x2C offset to notify memory
be_t<u32> reportsOffset; // 0x30 offset to reports memory
be_t<u32> reportsReportOffset;// 0x34 offset to reports in reports memory
be_t<u32> unk3[6]; // 0x38-0x54
be_t<u32> systemModeFlags; // 0x54
u8 unk4[0x1064]; // 0x10B8
struct Head {
be_t<u64> lastFlipTime; // 0x0 last flip time
be_t<u32> flipFlags; // 0x8 flags to handle flip/queue
be_t<u32> unk1; // 0xC
be_t<u32> flipBufferId; // 0x10
be_t<u32> queuedBufferId; // 0x14 todo: this is definately not this variable but its 'unused' so im using it for queueId to pass to flip handler
be_t<u32> unk3; // 0x18
be_t<u32> unk6; // 0x18 possible low bits of time stamp? used in getlastVBlankTime
be_t<u64> lastSecondVTime; // 0x20 last time for second vhandler freq
be_t<u64> unk4; // 0x28
be_t<u64> vBlankCount; // 0x30
be_t<u32> unk; // 0x38 possible u32, 'flip field', top/bottom for interlaced
be_t<u32> unk5; // 0x3C possible high bits of time stamp? used in getlastVBlankTime
} head[8]; // size = 0x40, 0x200
be_t<u32> unk7; // 0x12B8
be_t<u32> unk8; // 0x12BC
be_t<u32> handlers; // 0x12C0 -- flags showing which handlers are set
be_t<u32> unk9; // 0x12C4
be_t<u32> unk10; // 0x12C8
be_t<u32> userCmdParam; // 0x12CC
be_t<u32> handler_queue; // 0x12D0
be_t<u32> unk11; // 0x12D4
be_t<u32> unk12; // 0x12D8
be_t<u32> unk13; // 0x12DC
be_t<u32> unk14; // 0x12E0
be_t<u32> unk15; // 0x12E4
be_t<u32> unk16; // 0x12E8
be_t<u32> unk17; // 0x12F0
be_t<u32> lastError; // 0x12F4 error param for cellGcmSetGraphicsHandler
// todo: theres more to this
};
static_assert(sizeof(RsxDriverInfo) == 0x12F8, "rsxSizeTest");
static_assert(sizeof(RsxDriverInfo::Head) == 0x40, "rsxHeadSizeTest");
struct RsxDmaControl {
u8 resv[0x40];
atomic_be_t<u32> put;
atomic_be_t<u32> get;
atomic_be_t<u32> ref;
be_t<u32> unk[2];
be_t<u32> unk1;
};
struct RsxSemaphore {
be_t<u32> val;
be_t<u32> pad;
be_t<u64> timestamp;
};
struct RsxNotify {
be_t<u64> timestamp;
be_t<u64> zero;
};
struct RsxReport {
be_t<u64> timestamp;
be_t<u32> val;
be_t<u32> pad;
};
struct RsxReports {
RsxSemaphore semaphore[0x100];
RsxNotify notify[64];
RsxReport report[2048];
};
struct RsxDisplayInfo {
be_t<u32> offset;
be_t<u32> pitch;
be_t<u32> width;
be_t<u32> height;
};
// SysCalls
s32 sys_rsx_device_open();
s32 sys_rsx_device_close();
@@ -100,4 +12,4 @@ s32 sys_rsx_context_iounmap(u32 context_id, u32 a2, u32 io_addr, u32 size);
s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
s32 sys_rsx_device_map(vm::ps3::ptr<u64> addr, vm::ps3::ptr<u64> a2, u32 dev_id);
s32 sys_rsx_device_unmap(u32 dev_id);
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
+20 -19
View File
@@ -2,7 +2,6 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
@@ -12,8 +11,6 @@ namespace vm { using namespace ps3; }
logs::channel sys_rwlock("sys_rwlock");
template<> DECLARE(ipc_manager<lv2_rwlock, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr)
@@ -36,16 +33,19 @@ error_code sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribu
return CELL_EINVAL;
}
if (auto error = lv2_obj::create<lv2_rwlock>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
{
return std::make_shared<lv2_rwlock>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64);
}))
{
return error;
sys_rwlock.error("sys_rwlock_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
*rw_lock_id = idm::last_id();
return CELL_OK;
if (const u32 id = idm::make<lv2_obj, lv2_rwlock>(protocol, attr->name_u64))
{
*rw_lock_id = id;
return CELL_OK;
}
return CELL_EAGAIN;
}
error_code sys_rwlock_destroy(u32 rw_lock_id)
@@ -225,9 +225,9 @@ error_code sys_rwlock_runlock(ppu_thread& ppu, u32 rw_lock_id)
// Remove one reader
const s64 _old = rwlock->owner.fetch_op([](s64& val)
{
if (val < -1)
if (val < 0)
{
val += 2;
val++;
}
});
@@ -260,7 +260,7 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
{
sys_rwlock.trace("sys_rwlock_wlock(rw_lock_id=0x%x, timeout=0x%llx)", rw_lock_id, timeout);
const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id, [&](lv2_rwlock& rwlock) -> s64
const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id, [&](lv2_rwlock& rwlock)
{
const s64 val = rwlock.owner;
@@ -268,12 +268,12 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
{
if (rwlock.owner.compare_and_swap_test(0, ppu.id << 1))
{
return 0;
return true;
}
}
else if (val >> 1 == ppu.id)
{
return val;
return false;
}
semaphore_lock lock(rwlock.mutex);
@@ -294,9 +294,10 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
{
rwlock.wq.emplace_back(&ppu);
rwlock.sleep(ppu, timeout);
return false;
}
return _old;
return true;
});
if (!rwlock)
@@ -304,12 +305,12 @@ error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
return CELL_ESRCH;
}
if (rwlock.ret == 0)
if (rwlock.ret)
{
return CELL_OK;
}
if (rwlock.ret >> 1 == ppu.id)
if (rwlock->owner >> 1 == ppu.id)
{
return CELL_EDEADLK;
}
@@ -418,7 +419,7 @@ error_code sys_rwlock_wunlock(ppu_thread& ppu, u32 rw_lock_id)
if (auto cpu = rwlock->schedule<ppu_thread>(rwlock->wq, rwlock->protocol))
{
rwlock->owner = cpu->id << 1 | !rwlock->wq.empty() | !rwlock->rq.empty();
rwlock->owner = cpu->id << 1 | !rwlock->wq.empty();
rwlock->awake(*cpu);
}
+4 -6
View File
@@ -32,11 +32,11 @@ struct lv2_rwlock final : lv2_obj
std::deque<cpu_thread*> rq;
std::deque<cpu_thread*> wq;
lv2_rwlock(u32 protocol, u32 shared, u64 key, s32 flags, u64 name)
lv2_rwlock(u32 protocol, u64 name)
: protocol(protocol)
, shared(shared)
, key(key)
, flags(flags)
, shared(0)
, key(0)
, flags(0)
, name(name)
{
}
@@ -55,5 +55,3 @@ error_code sys_rwlock_runlock(ppu_thread& ppu, u32 rw_lock_id);
error_code sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout);
error_code sys_rwlock_trywlock(ppu_thread& ppu, u32 rw_lock_id);
error_code sys_rwlock_wunlock(ppu_thread& ppu, u32 rw_lock_id);
constexpr auto _sys_rwlock_trywlock = sys_rwlock_trywlock;
+18 -17
View File
@@ -2,7 +2,6 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
@@ -12,8 +11,6 @@ namespace vm { using namespace ps3; }
logs::channel sys_semaphore("sys_semaphore");
template<> DECLARE(ipc_manager<lv2_sema, u64>::g_ipc) {};
extern u64 get_system_time();
error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
@@ -42,16 +39,19 @@ error_code sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attri
return CELL_EINVAL;
}
if (auto error = lv2_obj::create<lv2_sema>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (attr->pshared != SYS_SYNC_NOT_PROCESS_SHARED || attr->ipc_key || attr->flags)
{
return std::make_shared<lv2_sema>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64, max_val, initial_val);
}))
{
return error;
sys_semaphore.error("sys_semaphore_create(): unknown attributes (pshared=0x%x, ipc_key=0x%x, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
*sem_id = idm::last_id();
return CELL_OK;
if (const u32 id = idm::make<lv2_obj, lv2_sema>(protocol, attr->name_u64, max_val, initial_val))
{
*sem_id = id;
return CELL_OK;
}
return CELL_EAGAIN;
}
error_code sys_semaphore_destroy(u32 sem_id)
@@ -131,13 +131,7 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
{
semaphore_lock lock(sem->mutex);
if (!sem->unqueue(sem->sq, &ppu))
{
timeout = 0;
continue;
}
verify(HERE), 0 > sem->val.fetch_op([](s32& val)
const s32 val = sem->val.fetch_op([](s32& val)
{
if (val < 0)
{
@@ -145,6 +139,13 @@ error_code sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
}
});
if (val >= 0)
{
timeout = 0;
continue;
}
verify(HERE), sem->unqueue(sem->sq, &ppu);
ppu.gpr[3] = CELL_ETIMEDOUT;
break;
}
+4 -4
View File
@@ -32,11 +32,11 @@ struct lv2_sema final : lv2_obj
atomic_t<s32> val;
std::deque<cpu_thread*> sq;
lv2_sema(u32 protocol, u32 shared, u64 key, s32 flags, u64 name, s32 max, s32 value)
lv2_sema(u32 protocol, u64 name, s32 max, s32 value)
: protocol(protocol)
, shared(shared)
, key(key)
, flags(flags)
, shared(0)
, key(0)
, flags(0)
, name(name)
, max(max)
, val(value)
+28 -67
View File
@@ -34,13 +34,24 @@ void sys_spu_image::load(const fs::file& stream)
const u32 addr = this->segs.addr() + 4096;
sha1_context ctx;
u8 output[20];
sha1_starts(&ctx);
sha1_update(&ctx, reinterpret_cast<const u8*>(&obj.header), sizeof(obj.header));
for (const auto& shdr : obj.shdrs)
{
sha1_update(&ctx, reinterpret_cast<const u8*>(&shdr), sizeof(spu_exec_object::shdr_t));
LOG_NOTICE(SPU, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", shdr.sh_type, shdr.sh_addr, shdr.sh_size, shdr.sh_flags);
}
for (const auto& prog : obj.progs)
{
sha1_update(&ctx, reinterpret_cast<const u8*>(&prog), sizeof(spu_exec_object::phdr_t));
sha1_update(&ctx, reinterpret_cast<const u8*>(prog.bin.data()), prog.bin.size());
LOG_NOTICE(SPU, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY)
@@ -74,6 +85,22 @@ void sys_spu_image::load(const fs::file& stream)
LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type);
}
}
sha1_finish(&ctx, output);
// Format patch name
std::string hash("spu-");
for (u8 x : output) fmt::append(hash, "%02x", x);
LOG_NOTICE(LOADER, "Loaded SPU image: %s", hash);
// Apply the patch
fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr + addr);
if (!Emu.GetTitleID().empty())
{
// Alternative patch
fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + addr);
}
}
void sys_spu_image::free()
@@ -86,29 +113,15 @@ void sys_spu_image::free()
void sys_spu_image::deploy(u32 loc)
{
// Segment info dump
std::string dump;
// Executable hash
sha1_context sha;
sha1_starts(&sha);
u8 sha1_hash[20];
for (int i = 0; i < nsegs; i++)
{
auto& seg = segs[i];
fmt::append(dump, "\n\t[%d] t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", i, seg.type, seg.ls, seg.size, seg.addr);
// Hash big-endian values
sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type));
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
LOG_NOTICE(SPU, "*** Deploy: t=0x%x, ls=0x%x, size=0x%x, addr=0x%x", seg.type, seg.ls, seg.size, seg.addr);
if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY)
{
std::memcpy(vm::base(loc + seg.ls), vm::base(seg.addr), seg.size);
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
sha1_update(&sha, vm::g_base_addr + seg.addr, seg.size);
}
else if (seg.type == SYS_SPU_SEGMENT_TYPE_FILL)
{
@@ -118,32 +131,8 @@ void sys_spu_image::deploy(u32 loc)
}
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr);
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
sha1_update(&sha, (uchar*)&seg.addr, sizeof(seg.addr));
}
}
sha1_finish(&sha, sha1_hash);
// Format patch name
std::string hash("SPU-0000000000000000000000000000000000000000");
for (u32 i = 0; i < sizeof(sha1_hash); i++)
{
constexpr auto pal = "0123456789abcdef";
hash[4 + i * 2] = pal[sha1_hash[i] >> 4];
hash[5 + i * 2] = pal[sha1_hash[i] & 15];
}
// Apply the patch
auto applied = fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr + loc);
if (!Emu.GetTitleID().empty())
{
// Alternative patch
applied += fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr + loc);
}
LOG_NOTICE(LOADER, "Loaded SPU image: %s (<- %u)%s", hash, applied, dump);
}
error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
@@ -158,13 +147,6 @@ error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu)
return CELL_OK;
}
error_code _sys_spu_image_get_information(vm::ptr<sys_spu_image> img, u32 ptr1, u32 ptr2)
{
sys_spu.todo("_sys_spu_image_get_information(img=*0x%x, 1=*0x%x, 2=*0x%x)", img, ptr1, ptr2);
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_get_information");
}
error_code sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::cptr<char> path)
{
sys_spu.warning("sys_spu_image_open(img=*0x%x, path=%s)", img, path);
@@ -182,27 +164,6 @@ error_code sys_spu_image_open(vm::ptr<sys_spu_image> img, vm::cptr<char> path)
return CELL_OK;
}
error_code _sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 arg3, u32 arg4)
{
sys_spu.todo("_sys_spu_image_import(img=*0x%x, src=*0x%x, arg3=0x%x, arg4=0x%x)", img, src, arg3, arg4);
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_import");
}
error_code _sys_spu_image_close(vm::ptr<sys_spu_image> img)
{
sys_spu.todo("_sys_spu_image_close(img=*0x%x)", img);
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_close");
}
error_code _sys_raw_spu_image_load(vm::ptr<sys_spu_image> img, u32 ptr, u32 arg3)
{
sys_spu.todo("_sys_raw_spu_image_load(img=*0x%x, ptr=*0x%x, arg3=0x%x)", img, ptr, arg3);
fmt::throw_exception("Unimlemented syscall: _sys_raw_spu_image_load");
}
error_code sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group_id, u32 spu_num, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_thread_attribute> attr, vm::ptr<sys_spu_thread_argument> arg)
{
sys_spu.warning("sys_spu_thread_initialize(thread=*0x%x, group=0x%x, spu_num=%d, img=*0x%x, attr=*0x%x, arg=*0x%x)", thread, group_id, spu_num, img, attr, arg);
-4
View File
@@ -203,11 +203,7 @@ class ppu_thread;
// Syscalls
error_code sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
error_code _sys_spu_image_get_information(vm::ps3::ptr<sys_spu_image> img, u32 ptr1, u32 ptr2);
error_code sys_spu_image_open(vm::ps3::ptr<sys_spu_image> img, vm::ps3::cptr<char> path);
error_code _sys_spu_image_import(vm::ps3::ptr<sys_spu_image> img, u32 src, u32 arg3, u32 arg4);
error_code _sys_spu_image_close(vm::ps3::ptr<sys_spu_image> img);
error_code _sys_raw_spu_image_load(vm::ps3::ptr<sys_spu_image> img, u32 ptr, u32 arg3);
error_code sys_spu_thread_initialize(vm::ps3::ptr<u32> thread, u32 group, u32 spu_num, vm::ps3::ptr<sys_spu_image>, vm::ps3::ptr<sys_spu_thread_attribute>, vm::ps3::ptr<sys_spu_thread_argument>);
error_code sys_spu_thread_set_argument(u32 id, vm::ps3::ptr<sys_spu_thread_argument> arg);
error_code sys_spu_thread_group_create(vm::ps3::ptr<u32> id, u32 num, s32 prio, vm::ps3::ptr<sys_spu_thread_group_attribute> attr);
+20 -101
View File
@@ -7,52 +7,46 @@
#include "Emu/Memory/vm.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/IdManager.h"
#include "Emu/IPC.h"
#include <deque>
// attr_protocol (waiting scheduling policy)
enum
{
SYS_SYNC_FIFO = 0x1, // First In, First Out Order
SYS_SYNC_PRIORITY = 0x2, // Priority Order
SYS_SYNC_PRIORITY_INHERIT = 0x3, // Basic Priority Inheritance Protocol
SYS_SYNC_RETRY = 0x4, // Not selected while unlocking
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xf,
// First In, First Out
SYS_SYNC_FIFO = 1,
// Priority Order
SYS_SYNC_PRIORITY = 2,
// Basic Priority Inheritance Protocol (probably not implemented)
SYS_SYNC_PRIORITY_INHERIT = 3,
// Not selected while unlocking
SYS_SYNC_RETRY = 4,
//
SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF,
};
// attr_recursive (recursive locks policy)
enum
{
SYS_SYNC_RECURSIVE = 0x10,
SYS_SYNC_NOT_RECURSIVE = 0x20,
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xf0,
// Recursive locks are allowed
SYS_SYNC_RECURSIVE = 0x10,
// Recursive locks are NOT allowed
SYS_SYNC_NOT_RECURSIVE = 0x20,
//
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
};
// attr_pshared (sharing among processes policy)
// attr_pshared
enum
{
SYS_SYNC_PROCESS_SHARED = 0x100,
SYS_SYNC_NOT_PROCESS_SHARED = 0x200,
SYS_SYNC_ATTR_PSHARED_MASK = 0xf00,
};
// attr_flags (creation policy)
enum
{
SYS_SYNC_NEWLY_CREATED = 0x1, // Create new object, fails if specified IPC key exists
SYS_SYNC_NOT_CREATE = 0x2, // Reference existing object, fails if IPC key not found
SYS_SYNC_NOT_CARE = 0x3, // Reference existing object, create new one if IPC key not found
SYS_SYNC_ATTR_FLAGS_MASK = 0xf,
SYS_SYNC_NOT_PROCESS_SHARED = 0x200,
};
// attr_adaptive
enum
{
SYS_SYNC_ADAPTIVE = 0x1000,
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
SYS_SYNC_ATTR_ADAPTIVE_MASK = 0xf000,
SYS_SYNC_ADAPTIVE = 0x1000,
SYS_SYNC_NOT_ADAPTIVE = 0x2000,
};
// Base class for some kernel objects (shared set of 8192 objects).
@@ -132,81 +126,6 @@ struct lv2_obj
static void cleanup();
template <typename T, typename F>
static error_code create(u32 pshared, u64 ipc_key, s32 flags, F&& make)
{
switch (pshared)
{
case SYS_SYNC_PROCESS_SHARED:
{
switch (flags)
{
case SYS_SYNC_NEWLY_CREATED:
case SYS_SYNC_NOT_CARE:
{
std::shared_ptr<T> result = make();
if (!ipc_manager<T, u64>::add(ipc_key, [&] { if (!idm::import_existing<lv2_obj, T>(result)) result.reset(); return result; }, &result))
{
if (flags == SYS_SYNC_NEWLY_CREATED)
{
return CELL_EEXIST;
}
if (!idm::import_existing<lv2_obj, T>(result))
{
return CELL_EAGAIN;
}
return CELL_OK;
}
else if (!result)
{
return CELL_EAGAIN;
}
else
{
return CELL_OK;
}
}
case SYS_SYNC_NOT_CREATE:
{
auto result = ipc_manager<T, u64>::get(ipc_key);
if (!result)
{
return CELL_ESRCH;
}
if (!idm::import_existing<lv2_obj, T>(result))
{
return CELL_EAGAIN;
}
return CELL_OK;
}
default:
{
return CELL_EINVAL;
}
}
}
case SYS_SYNC_NOT_PROCESS_SHARED:
{
if (!idm::import<lv2_obj, T>(std::forward<F>(make)))
{
return CELL_EAGAIN;
}
return CELL_OK;
}
default:
{
return CELL_EINVAL;
}
}
}
private:
// Scheduler mutex
static semaphore<> g_mutex;
+1 -1
View File
@@ -25,7 +25,7 @@ struct lv2_timer final : public lv2_obj, public named_thread
void on_stop() override;
semaphore<> mutex;
atomic_t<u32> state{SYS_TIMER_STATE_STOP};
atomic_t<u32> state{SYS_TIMER_STATE_RUN};
std::weak_ptr<lv2_event_queue> port;
u64 source;
+5 -14
View File
@@ -7,7 +7,7 @@
// IPC manager for objects of type T and IPC keys of type K.
// External declaration of g_ipc is required.
template <typename T, typename K>
template<typename T, typename K>
class ipc_manager final
{
std::unordered_map<K, std::weak_ptr<T>> m_map;
@@ -18,27 +18,18 @@ class ipc_manager final
public:
// Add new object if specified ipc_key is not used
template <typename F>
static bool add(const K& ipc_key, F&& provider, std::shared_ptr<T>* out = nullptr)
template<typename F>
static bool add(const K& ipc_key, F&& provider)
{
writer_lock lock(g_ipc.m_mutex);
// Get object location
std::weak_ptr<T>& wptr = g_ipc.m_map[ipc_key];
if ((out && !(*out = wptr.lock())) || wptr.expired())
if (wptr.expired())
{
// Call a function which must return the object
if (out)
{
*out = provider();
wptr = *out;
}
else
{
wptr = provider();
}
wptr = provider();
return true;
}
-1
View File
@@ -189,7 +189,6 @@ enum CellKbMappingType
CELL_KB_MAPPING_BELGIAN_BELGIUM,
CELL_KB_MAPPING_POLISH_POLAND,
CELL_KB_MAPPING_PORTUGUESE_BRAZIL,
CELL_KB_MAPPING_TURKISH_TURKEY
};
static const u32 KB_MAX_KEYBOARDS = 127;
+3 -6
View File
@@ -55,16 +55,13 @@ bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr)
return false;
}
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
/*for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if (addr >= m_mapped_memory[i].addr && addr + size - 1 <= m_mapped_memory[i].addr + m_mapped_memory[i].size - 1)
{
// it seems mapping another range inside a previous one is legit on ps3
// as long as it's coherent aliasing : offset from EA must match IO offset
// example game using this pattern : BCES01584 - the last of us
return (addr - m_mapped_memory[i].addr) == (realaddr - m_mapped_memory[i].realAddress);
return false;
}
}
}*/
m_mapped_memory.emplace_back(addr, realaddr, size);
return true;
+3 -3
View File
@@ -27,9 +27,9 @@
namespace vm
{
static u8* memory_reserve_4GiB(std::uintptr_t _addr = 0)
static u8* memory_reserve_4GiB(std::uintptr_t addr = 0)
{
for (u64 addr = _addr + 0x100000000;; addr += 0x100000000)
for (u64 addr = 0x100000000;; addr += 0x100000000)
{
if (auto ptr = utils::memory_reserve(0x100000000, (void*)addr))
{
@@ -783,10 +783,10 @@ namespace vm
{
std::make_shared<block_t>(0x00010000, 0x1FFF0000), // main
std::make_shared<block_t>(0x20000000, 0x10000000), // user
std::make_shared<block_t>(0x40000000, 0x30000000), // rsx contexts
std::make_shared<block_t>(0xC0000000, 0x10000000), // video
std::make_shared<block_t>(0xD0000000, 0x10000000), // stack
std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved
std::make_shared<block_t>(0x40000000, 0x10000000), // rsx contexts
};
}
}
+1
View File
@@ -16,6 +16,7 @@ namespace vm
{
main,
user_space,
rsx_context,
video,
stack,
+5 -29
View File
@@ -1,13 +1,10 @@
#include "stdafx.h"
#include "Utilities/sysinfo.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "ARMv7Thread.h"
#include "ARMv7Interpreter.h"
const bool s_use_rtm = utils::has_rtm();
using namespace arm_code::arm_encoding_alias;
#define ARG(arg, ...) const u32 arg = args::arg::extract(__VA_ARGS__);
@@ -2094,34 +2091,13 @@ void arm_interpreter::STREX(ARMv7Thread& cpu, const u32 op, const u32 cond)
return;
}
bool result;
vm::writer_lock lock(0);
if (s_use_rtm && utils::transaction_enter())
const bool result = cpu.rtime == vm::reservation_acquire(addr, cpu.rtime) && data.compare_and_swap_test(cpu.rdata, value);
if (result)
{
if (!vm::reader_lock{vm::try_to_lock})
{
_xabort(0);
}
result = cpu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(cpu.rdata, value);
if (result)
{
vm::reservation_update(addr, sizeof(u32));
}
_xend();
}
else
{
vm::writer_lock lock(0);
result = cpu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(cpu.rdata, value);
if (result)
{
vm::reservation_update(addr, sizeof(u32));
}
vm::reservation_update(addr, sizeof(u32));
}
cpu.raddr = 0;
-3
View File
@@ -63,9 +63,6 @@ std::string CgBinaryDisasm::GetDSTDisasm(bool isSca)
LOG_ERROR(RSX, "dst index out of range: %u", d3.dst);
ret += fmt::format("o[%d]", d3.dst) + GetVecMaskDisasm();
// Vertex Program supports double destinations, notably in MOV
if (d0.dst_tmp != 0x3f)
ret += fmt::format(" R%d", d0.dst_tmp) + GetVecMaskDisasm();
break;
}
+4 -14
View File
@@ -125,13 +125,8 @@ namespace
u32 min_block_size = std::min(src_stride, dst_stride);
if (min_block_size == 0) min_block_size = dst_stride;
u32 iterations = 0;
u32 remainder = is_128_aligned ? 0 : 1 + ((16 - min_block_size) / min_block_size);
if (vertex_count > remainder)
iterations = vertex_count - remainder;
else
remainder = vertex_count;
const u32 remainder = is_128_aligned? 0: (16 - min_block_size) / min_block_size;
const u32 iterations = is_128_aligned? vertex_count: vertex_count - remainder;
for (u32 i = 0; i < iterations; ++i)
{
@@ -173,13 +168,8 @@ namespace
u32 min_block_size = std::min(src_stride, dst_stride);
if (min_block_size == 0) min_block_size = dst_stride;
u32 iterations = 0;
u32 remainder = is_128_aligned ? 0 : 1 + ((16 - min_block_size) / min_block_size);
if (vertex_count > remainder)
iterations = vertex_count - remainder;
else
remainder = vertex_count;
const u32 remainder = is_128_aligned ? 0 : (16 - min_block_size) / min_block_size;
const u32 iterations = is_128_aligned ? vertex_count : vertex_count - remainder;
for (u32 i = 0; i < iterations; ++i)
{
@@ -41,21 +41,16 @@ std::string VertexProgramDecompiler::GetDST(bool isSca)
{
std::string ret;
std::string mask = GetMask(isSca);
switch (isSca ? 0x1f : d3.dst)
{
case 0x1f:
ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp)) + mask;
ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("tmp") + std::to_string(isSca ? d3.sca_dst_tmp : d0.dst_tmp));
break;
default:
if (d3.dst > 15)
LOG_ERROR(RSX, "dst index out of range: %u", d3.dst);
ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? getFloatTypeName(4) + "(0.0f, 0.0f, 0.0f, 1.0f)" : getFloatTypeName(4) + "(0.0, 0.0, 0.0, 0.0)") + mask;
// Handle double destination register as 'dst_reg = tmp'
if (d0.dst_tmp != 0x3f)
ret += " = " + m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("tmp") + std::to_string(d0.dst_tmp)) + mask;
ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? getFloatTypeName(4) + "(0.0f, 0.0f, 0.0f, 1.0f)" : getFloatTypeName(4) + "(0.0, 0.0, 0.0, 0.0)");
break;
}
@@ -162,7 +157,7 @@ void VertexProgramDecompiler::SetDST(bool is_sca, std::string value)
}
else if (d3.dst != 0x1f || (is_sca ? d3.sca_dst_tmp != 0x3f : d0.dst_tmp != 0x3f))
{
dest = GetDST(is_sca);
dest = GetDST(is_sca) + mask;
}
//std::string code;
@@ -314,7 +309,7 @@ void VertexProgramDecompiler::AddCodeCond(const std::string& dst, const std::str
swizzle = swizzle == "xyzw" ? "" : "." + swizzle;
std::string cond = compareFunction(cond_string_table[d0.cond], "cc" + std::to_string(d0.cond_reg_sel_1) + swizzle, getFloatTypeName(4) + "(0., 0., 0., 0.)");
std::string cond = compareFunction(cond_string_table[d0.cond], "cc" + std::to_string(d0.cond_reg_sel_1) + swizzle.c_str(), getFloatTypeName(4) + "(0., 0., 0., 0.)");
ShaderVariable dst_var(dst);
dst_var.symplify();
+5 -79
View File
@@ -93,12 +93,7 @@ namespace rsx
auto It = m_render_targets_storage.find(address);
// TODO: Fix corner cases
// This doesn't take overlapping surface(s) into account.
surface_storage_type old_surface_storage;
surface_storage_type new_surface_storage;
surface_type old_surface = nullptr;
surface_type new_surface = nullptr;
if (It != m_render_targets_storage.end())
{
surface_storage_type &rtt = It->second;
@@ -109,43 +104,10 @@ namespace rsx
}
old_surface = Traits::get(rtt);
old_surface_storage = std::move(rtt);
invalidated_resources.push_back(std::move(rtt));
m_render_targets_storage.erase(address);
}
//Search invalidated resources for a suitable surface
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
{
auto &rtt = *It;
if (Traits::rtt_has_format_width_height(rtt, color_format, width, height, true))
{
new_surface_storage = std::move(rtt);
if (old_surface)
//Exchange this surface with the invalidated one
rtt = std::move(old_surface_storage);
else
//rtt is now empty - erase it
invalidated_resources.erase(It);
new_surface = Traits::get(new_surface_storage);
Traits::invalidate_rtt_surface_contents(command_list, new_surface, old_surface, true);
Traits::prepare_rtt_for_drawing(command_list, new_surface);
break;
}
}
if (old_surface != nullptr && new_surface == nullptr)
//This was already determined to be invalid and is excluded from testing above
invalidated_resources.push_back(std::move(old_surface_storage));
if (new_surface != nullptr)
{
//New surface was found among existing surfaces
m_render_targets_storage[address] = std::move(new_surface_storage);
return new_surface;
}
m_render_targets_storage[address] = Traits::create_new_surface(address, color_format, width, height, old_surface, std::forward<Args>(extra_params)...);
return Traits::get(m_render_targets_storage[address]);
}
@@ -157,11 +119,7 @@ namespace rsx
surface_depth_format depth_format, size_t width, size_t height,
Args&&... extra_params)
{
surface_storage_type old_surface_storage;
surface_storage_type new_surface_storage;
surface_type old_surface = nullptr;
surface_type new_surface = nullptr;
auto It = m_depth_stencil_storage.find(address);
if (It != m_depth_stencil_storage.end())
{
@@ -173,42 +131,10 @@ namespace rsx
}
old_surface = Traits::get(ds);
old_surface_storage = std::move(ds);
invalidated_resources.push_back(std::move(ds));
m_depth_stencil_storage.erase(address);
}
//Search invalidated resources for a suitable surface
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
{
auto &ds = *It;
if (Traits::ds_has_format_width_height(ds, depth_format, width, height, true))
{
new_surface_storage = std::move(ds);
if (old_surface)
//Exchange this surface with the invalidated one
ds = std::move(old_surface_storage);
else
invalidated_resources.erase(It);
new_surface = Traits::get(new_surface_storage);
Traits::prepare_ds_for_drawing(command_list, new_surface);
Traits::invalidate_depth_surface_contents(command_list, new_surface, old_surface, true);
break;
}
}
if (old_surface != nullptr && new_surface == nullptr)
//This was already determined to be invalid and is excluded from testing above
invalidated_resources.push_back(std::move(old_surface_storage));
if (new_surface != nullptr)
{
//New surface was found among existing surfaces
m_depth_stencil_storage[address] = std::move(new_surface_storage);
return new_surface;
}
m_depth_stencil_storage[address] = Traits::create_new_surface(address, depth_format, width, height, old_surface, std::forward<Args>(extra_params)...);
return Traits::get(m_depth_stencil_storage[address]);
}
@@ -432,10 +358,10 @@ namespace rsx
void invalidate_surface_cache_data(command_list_type command_list)
{
for (auto &rtt : m_render_targets_storage)
Traits::invalidate_rtt_surface_contents(command_list, Traits::get(std::get<1>(rtt)), nullptr, false);
Traits::invalidate_rtt_surface_contents(command_list, Traits::get(std::get<1>(rtt)));
for (auto &ds : m_depth_stencil_storage)
Traits::invalidate_depth_surface_contents(command_list, Traits::get(std::get<1>(ds)), nullptr, true);
Traits::invalidate_depth_surface_contents(command_list, Traits::get(std::get<1>(ds)));
}
};
}
}
+5 -4
View File
@@ -223,8 +223,9 @@ namespace
const std::vector<std::pair<u32, u32>>& vertex_ranges, d3d12_data_heap& m_buffer_data)
{
size_t index_count = std::accumulate(
vertex_ranges.begin(), vertex_ranges.end(), 0ll, [](size_t acc, const auto& pair) {
return acc + get_index_count(rsx::method_registers.current_draw_clause.primitive, pair.second);
vertex_ranges.begin(), vertex_ranges.end(), 0, [](size_t acc, const auto& pair) {
return acc + get_index_count(
rsx::method_registers.current_draw_clause.primitive, pair.second);
});
// Alloc
@@ -235,7 +236,7 @@ namespace
void* mapped_buffer =
m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
u32 vertex_count = 0;
size_t vertex_count = 0;
for (const auto& pair : vertex_ranges)
vertex_count += pair.second;
@@ -468,7 +469,7 @@ D3D12GSRender::upload_and_set_vertex_index_data(ID3D12GraphicsCommandList* comma
return std::apply_visitor(
draw_command_visitor(command_list, m_buffer_data, m_vertex_buffer_data.Get(),
[this](
const auto& state, const auto& list) { return get_vertex_buffers(state, list, 0); }),
const auto& state, const auto& list) { return get_vertex_buffers(state, list); }),
get_draw_command(rsx::method_registers));
}
+9 -14
View File
@@ -324,17 +324,6 @@ void D3D12GSRender::end()
{
std::chrono::time_point<steady_clock> start_duration = steady_clock::now();
std::chrono::time_point<steady_clock> program_load_start = steady_clock::now();
load_program();
std::chrono::time_point<steady_clock> program_load_end = steady_clock::now();
m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();
if (!m_fragment_program.valid)
{
rsx::thread::end();
return;
}
std::chrono::time_point<steady_clock> rtt_duration_start = steady_clock::now();
prepare_render_targets(get_current_resource_storage().command_list.Get());
@@ -355,6 +344,11 @@ void D3D12GSRender::end()
std::chrono::time_point<steady_clock> vertex_index_duration_end = steady_clock::now();
m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count();
std::chrono::time_point<steady_clock> program_load_start = steady_clock::now();
load_program();
std::chrono::time_point<steady_clock> program_load_end = steady_clock::now();
m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_shared_root_signature.Get());
get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers.stencil_func_ref());
@@ -523,9 +517,10 @@ void D3D12GSRender::flip(int buffer)
size_t offset = 0;
if (false)
{
u32 addr = rsx::get_address(display_buffers[current_display_buffer].offset, CELL_GCM_LOCATION_LOCAL);
w = display_buffers[current_display_buffer].width;
h = display_buffers[current_display_buffer].height;
CellGcmDisplayInfo* buffers = nullptr;// = vm::ps3::_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
u32 addr = rsx::get_address(gcm_buffers[gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
w = gcm_buffers[gcm_current_buffer].width;
h = gcm_buffers[gcm_current_buffer].height;
u8 *src_buffer = vm::ps3::_ptr<u8>(addr);
row_pitch = align(w * 4, 256);
@@ -56,9 +56,6 @@ void D3D12GSRender::load_program()
m_vertex_program = get_current_vertex_program();
m_fragment_program = get_current_fragment_program(rtt_lookup_func);
if (!m_fragment_program.valid)
return;
D3D12PipelineProperties prop = {};
prop.Topology = get_primitive_topology_type(rsx::method_registers.current_draw_clause.primitive);
@@ -176,15 +176,15 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
rsx::method_registers.clear_color_a() / 255.f,
};
u32 clip_width = rsx::method_registers.surface_clip_width();
u32 clip_height = rsx::method_registers.surface_clip_height();
u32 clip_width = rsx::method_registers.surface_clip_width();
u32 clip_height = rsx::method_registers.surface_clip_height();
if (clip_height == 0 || clip_width == 0)
return;
if (clip_height == 0 || clip_width == 0)
return;
m_rtts.prepare_render_target(copycmdlist,
rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(),
clip_width, clip_height,
clip_width, clip_height,
rsx::method_registers.surface_color_target(),
get_color_surface_addresses(), get_zeta_surface_address(),
m_device.Get(), clear_color, 1.f, 0);
@@ -329,7 +329,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
{
for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
{
if (!address_color[i] || std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
if (!address_color[i])
continue;
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), rsx::method_registers.surface_color());
invalidate_address(address_color[i]);
@@ -381,7 +381,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
{
if (!address_color[i] || std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
if (!address_color[i])
continue;
copy_readback_buffer_to_dest(dest_buffer[i], m_readback_resources, color_buffer_offset_in_heap[i], srcPitch, dstPitch, clip_h);
}
+4 -6
View File
@@ -116,30 +116,28 @@ struct render_target_traits
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
}
static
void invalidate_rtt_surface_contents(
gsl::not_null<ID3D12GraphicsCommandList*>,
ID3D12Resource*, ID3D12Resource*, bool)
ID3D12Resource*)
{}
static
void invalidate_depth_surface_contents(
gsl::not_null<ID3D12GraphicsCommandList*>,
ID3D12Resource*, ID3D12Resource*, bool)
ID3D12Resource*)
{
//TODO
}
static
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false)
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height)
{
DXGI_FORMAT dxgi_format = get_color_surface_format(surface_color_format);
return rtt->GetDesc().Format == dxgi_format && rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
}
static
bool ds_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_depth_format, size_t width, size_t height, bool=false)
bool ds_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_depth_format, size_t width, size_t height)
{
//TODO: Check format
return rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
+13 -3
View File
@@ -7,11 +7,21 @@
struct CellGcmControl
{
atomic_be_t<u32> put;
atomic_be_t<u32> get;
atomic_be_t<u32> ref;
u8 resv[0x40];
atomic_be_t<u32> put;
atomic_be_t<u32> get;
atomic_be_t<u32> ref;
be_t<u32> unk[2];
be_t<u32> unk1;
};
/*struct CellGcmControl
{
atomic_be_t<u32> put;
atomic_be_t<u32> get;
atomic_be_t<u32> ref;
};*/
struct CellGcmConfig
{
be_t<u32> localAddress;
+66 -115
View File
@@ -26,11 +26,6 @@ GLGSRender::GLGSRender() : GSRender()
{
//TODO
//shaders_cache.load(rsx::old_shaders_cache::shader_language::glsl);
if (g_cfg.video.disable_vertex_cache)
m_vertex_cache.reset(new gl::null_vertex_cache());
else
m_vertex_cache.reset(new gl::weak_vertex_cache());
}
u32 GLGSRender::enable(u32 condition, u32 cap)
@@ -327,15 +322,17 @@ namespace
void GLGSRender::end()
{
std::chrono::time_point<steady_clock> program_start = steady_clock::now();
//Load program here since it is dependent on vertex state
if (skip_frame || !framebuffer_status_valid || !load_program())
if (skip_frame || !framebuffer_status_valid)
{
rsx::thread::end();
return;
}
std::chrono::time_point<steady_clock> program_start = steady_clock::now();
//Load program here since it is dependent on vertex state
load_program();
std::chrono::time_point<steady_clock> program_stop = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count();
@@ -367,80 +364,44 @@ void GLGSRender::end()
surface->old_contents = nullptr;
};
//Check if we have any 'recycled' surfaces in memory and if so, clear them
std::vector<int> buffers_to_clear;
bool clear_all_color = true;
bool clear_depth = false;
for (int index = 0; index < 4; index++)
{
if (std::get<0>(m_rtts.m_bound_render_targets[index]) != 0)
{
if (std::get<1>(m_rtts.m_bound_render_targets[index])->cleared())
clear_all_color = false;
else
buffers_to_clear.push_back(index);
}
}
gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil);
if (ds && !ds->cleared())
{
clear_depth = true;
}
//Temporarily disable pixel tests
glDisable(GL_SCISSOR_TEST);
glDepthMask(GL_TRUE);
glClearDepth(1.0);
glClearStencil(255);
//Temporarily disable pixel tests
glDisable(GL_SCISSOR_TEST);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (clear_depth || buffers_to_clear.size() > 0)
{
GLenum mask = 0;
if (clear_depth)
if (g_cfg.video.strict_rendering_mode)
{
glDepthMask(GL_TRUE);
glClearDepth(1.0);
glClearStencil(255);
mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
//Copy previous data if any
if (ds->old_contents != nullptr)
copy_rtt_contents(ds);
}
if (clear_all_color)
mask |= GL_COLOR_BUFFER_BIT;
glClear(mask);
if (buffers_to_clear.size() > 0 && !clear_all_color)
{
GLfloat colors[] = { 0.f, 0.f, 0.f, 0.f };
//It is impossible for the render target to be typa A or B here (clear all would have been flagged)
for (auto &i: buffers_to_clear)
glClearBufferfv(draw_fbo.id(), i, colors);
}
if (clear_depth)
glDepthMask(rsx::method_registers.depth_write_enabled());
glDepthMask(rsx::method_registers.depth_write_enabled());
glEnable(GL_SCISSOR_TEST);
ds->set_cleared();
}
if (g_cfg.video.strict_rendering_mode)
{
if (ds->old_contents != nullptr)
copy_rtt_contents(ds);
for (auto &rtt : m_rtts.m_bound_render_targets)
{
if (std::get<0>(rtt) != 0)
{
auto surface = std::get<1>(rtt);
if (surface->old_contents != nullptr)
if (!surface->cleared() && surface->old_contents != nullptr)
copy_rtt_contents(surface);
}
}
}
glEnable(GL_SCISSOR_TEST);
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
//Setup textures
@@ -502,6 +463,7 @@ void GLGSRender::end()
}
else
{
//LOG_ERROR(RSX, "No work is needed for this draw call! Muhahahahahahaha");
skip_upload = true;
}
@@ -843,14 +805,9 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
{
case NV4097_CLEAR_SURFACE:
{
if (arg & 0xF3)
{
//Only do all this if we have actual work to do
init_buffers(true);
synchronize_buffers();
clear_surface(arg);
}
init_buffers(true);
synchronize_buffers();
clear_surface(arg);
return true;
}
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
@@ -884,10 +841,8 @@ bool GLGSRender::load_program()
return std::make_tuple(true, surface->get_native_pitch());
};
RSXFragmentProgram fragment_program = get_current_fragment_program(rtt_lookup_func);
if (!fragment_program.valid) return false;
RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program = get_current_fragment_program(rtt_lookup_func);
u32 unnormalized_rtts = 0;
@@ -985,52 +940,29 @@ void GLGSRender::flip(int buffer)
return;
}
u32 buffer_width = display_buffers[buffer].width;
u32 buffer_height = display_buffers[buffer].height;
u32 buffer_pitch = display_buffers[buffer].pitch;
u32 buffer_width = gcm_buffers[buffer].width;
u32 buffer_height = gcm_buffers[buffer].height;
u32 buffer_pitch = gcm_buffers[buffer].pitch;
// Calculate blit coordinates
coordi aspect_ratio;
areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });
sizei csize(m_frame->client_width(), m_frame->client_height());
sizei new_size = csize;
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
if (!g_cfg.video.stretch_to_display_area)
{
const double aq = (double)buffer_width / buffer_height;
const double rq = (double)new_size.width / new_size.height;
const double q = aq / rq;
if (q > 1.0)
{
new_size.height = int(new_size.height / q);
aspect_ratio.y = (csize.height - new_size.height) / 2;
}
else if (q < 1.0)
{
new_size.width = int(new_size.width * q);
aspect_ratio.x = (csize.width - new_size.width) / 2;
}
}
aspect_ratio.size = new_size;
// Find the source image
rsx::tiled_region buffer_region = get_tiled_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
u32 absolute_address = buffer_region.address + buffer_region.base;
gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address);
m_flip_fbo.recreate();
__glcheck m_flip_fbo.recreate();
m_flip_fbo.bind();
auto *flip_fbo = &m_flip_fbo;
if (render_target_texture)
{
buffer_width = render_target_texture->width();
buffer_height = render_target_texture->height();
__glcheck m_flip_fbo.color = *render_target_texture;
__glcheck m_flip_fbo.read_buffer(m_flip_fbo.color);
}
else
{
@@ -1063,14 +995,36 @@ void GLGSRender::flip(int buffer)
__glcheck m_flip_fbo.read_buffer(m_flip_fbo.color);
}
// Blit source image to the screen
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });
coordi aspect_ratio;
sizei csize(m_frame->client_width(), m_frame->client_height());
sizei new_size = csize;
if (!g_cfg.video.stretch_to_display_area)
{
const double aq = (double)buffer_width / buffer_height;
const double rq = (double)new_size.width / new_size.height;
const double q = aq / rq;
if (q > 1.0)
{
new_size.height = int(new_size.height / q);
aspect_ratio.y = (csize.height - new_size.height) / 2;
}
else if (q < 1.0)
{
new_size.width = int(new_size.width * q);
aspect_ratio.x = (csize.width - new_size.width) / 2;
}
}
aspect_ratio.size = new_size;
gl::screen.clear(gl::buffers::color_depth_stencil);
__glcheck m_flip_fbo.blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical(), gl::buffers::color, gl::filter::linear);
__glcheck flip_fbo->blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical(), gl::buffers::color, gl::filter::linear);
if (g_cfg.video.overlay)
{
@@ -1087,7 +1041,6 @@ void GLGSRender::flip(int buffer)
m_frame->flip(m_context);
rsx::thread::flip(buffer);
// Cleanup
m_gl_texture_cache.clear_temporary_surfaces();
for (auto &tex : m_rtts.invalidated_resources)
@@ -1098,9 +1051,7 @@ void GLGSRender::flip(int buffer)
if (g_cfg.video.invalidate_surface_cache_every_frame)
m_rtts.invalidate_surface_cache_data(nullptr);
m_vertex_cache->purge();
//If we are skipping the next frame, do not reset perf counters
//If we are skipping the next frame, fo not reset perf counters
if (skip_frame) return;
m_draw_calls = 0;
+2 -8
View File
@@ -14,13 +14,6 @@
#pragma comment(lib, "opengl32.lib")
namespace gl
{
using vertex_cache = rsx::vertex_cache::default_vertex_cache<rsx::vertex_cache::uploaded_range<GLenum>, GLenum>;
using weak_vertex_cache = rsx::vertex_cache::weak_vertex_cache<GLenum>;
using null_vertex_cache = vertex_cache;
}
struct work_item
{
std::condition_variable cv;
@@ -64,7 +57,8 @@ private:
s64 m_vertex_upload_time = 0;
s64 m_textures_upload_time = 0;
std::unique_ptr<gl::vertex_cache> m_vertex_cache;
//Compare to see if transform matrix have changed
size_t m_transform_buffer_hash = 0;
GLint m_min_texbuffer_alignment = 256;
GLint m_uniform_buffer_offset_align = 256;
-2
View File
@@ -173,8 +173,6 @@ OPENGL_PROC(PFNGLMULTIDRAWARRAYSPROC, MultiDrawArrays);
OPENGL_PROC(PFNGLGETTEXTUREIMAGEEXTPROC, GetTextureImageEXT);
OPENGL_PROC(PFNGLGETTEXTUREIMAGEPROC, GetTextureImage);
OPENGL_PROC(PFNGLCLEARBUFFERFVPROC, ClearBufferfv);
//Sampler Objects
OPENGL_PROC(PFNGLGENSAMPLERSPROC, GenSamplers);
OPENGL_PROC(PFNGLDELETESAMPLERSPROC, DeleteSamplers);
-1
View File
@@ -169,7 +169,6 @@ void GLGSRender::init_buffers(bool skip_reading)
{
LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical);
framebuffer_status_valid = false;
return;
}
const auto pitchs = get_pitchs();
+4 -11
View File
@@ -192,7 +192,6 @@ struct gl_render_target_traits
if (old_surface != nullptr && old_surface->get_compatible_internal_format() == internal_fmt)
result->old_contents = old_surface;
result->set_cleared();
return result;
}
@@ -241,25 +240,19 @@ struct gl_render_target_traits
static void prepare_ds_for_drawing(void *, gl::render_target*) {}
static void prepare_ds_for_sampling(void *, gl::render_target*) {}
static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); }
static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); }
static void invalidate_rtt_surface_contents(void *, gl::render_target*) {}
static void invalidate_depth_surface_contents(void *, gl::render_target *ds) { ds->set_cleared(false); }
static
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false)
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height)
{
if (check_refs) //TODO
return false;
auto internal_fmt = rsx::internals::sized_internal_format(format);
return rtt->get_compatible_internal_format() == internal_fmt && rtt->width() == width && rtt->height() == height;
}
static
bool ds_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_depth_format, size_t width, size_t height, bool check_refs=false)
bool ds_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_depth_format, size_t width, size_t height)
{
if (check_refs) //TODO
return false;
// TODO: check format
return rtt->width() == width && rtt->height() == height;
}
+19 -33
View File
@@ -198,13 +198,12 @@ namespace
struct vertex_buffer_visitor
{
vertex_buffer_visitor(u32 vtx_cnt, gl::ring_buffer& heap, gl::glsl::program* prog, gl::texture* attrib_buffer, u32 min_texbuffer_offset, gl::vertex_cache* vertex_cache)
vertex_buffer_visitor(u32 vtx_cnt, gl::ring_buffer& heap, gl::glsl::program* prog, gl::texture* attrib_buffer, u32 min_texbuffer_offset)
: vertex_count(vtx_cnt)
, m_attrib_ring_info(heap)
, m_program(prog)
, m_gl_attrib_buffers(attrib_buffer)
, m_min_texbuffer_alignment(min_texbuffer_offset)
, m_vertex_cache(vertex_cache)
{
}
@@ -214,30 +213,21 @@ namespace
if (!m_program->uniforms.has_location(s_reg_table[vertex_array.index], &location))
return;
GLenum gl_type = to_gl_internal_type(vertex_array.type, vertex_array.attribute_size);
// Fill vertex_array
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_array.type, vertex_array.attribute_size);
u32 data_size = vertex_count * element_size;
u32 gl_type = to_gl_internal_type(vertex_array.type, vertex_array.attribute_size);
auto& texture = m_gl_attrib_buffers[vertex_array.index];
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_array.type, vertex_array.attribute_size);
const u32 data_size = vertex_count * element_size;
const uintptr_t local_addr = (uintptr_t)vertex_array.data.data();
u32 buffer_offset = 0;
auto mapping = m_attrib_ring_info.alloc_from_heap(data_size, m_min_texbuffer_alignment);
gsl::byte* dst = static_cast<gsl::byte*>(mapping.first);
buffer_offset = mapping.second;
gsl::span<gsl::byte> dest_span(dst, data_size);
if (auto uploaded = m_vertex_cache->find_vertex_range(local_addr, gl_type, data_size))
{
buffer_offset = uploaded->offset_in_heap;
}
else
{
// Fill vertex_array
auto mapping = m_attrib_ring_info.alloc_from_heap(data_size, m_min_texbuffer_alignment);
gsl::byte* dst = static_cast<gsl::byte*>(mapping.first);
buffer_offset = mapping.second;
gsl::span<gsl::byte> dest_span(dst, data_size);
m_vertex_cache->store_range(local_addr, gl_type, data_size, buffer_offset);
write_vertex_array_data_to_buffer(dest_span, vertex_array.data, vertex_count, vertex_array.type, vertex_array.attribute_size, vertex_array.stride, rsx::get_vertex_type_size_on_host(vertex_array.type, vertex_array.attribute_size));
prepare_buffer_for_writing(dst, vertex_array.type, vertex_array.attribute_size, vertex_count);
}
write_vertex_array_data_to_buffer(dest_span, vertex_array.data, vertex_count, vertex_array.type, vertex_array.attribute_size, vertex_array.stride, rsx::get_vertex_type_size_on_host(vertex_array.type, vertex_array.attribute_size));
prepare_buffer_for_writing(dst, vertex_array.type, vertex_array.attribute_size, vertex_count);
texture.copy_from(m_attrib_ring_info, gl_type, buffer_offset, data_size);
}
@@ -273,7 +263,6 @@ namespace
gl::glsl::program* m_program;
gl::texture* m_gl_attrib_buffers;
GLint m_min_texbuffer_alignment;
gl::vertex_cache* m_vertex_cache;
};
struct draw_command_visitor
@@ -283,7 +272,6 @@ namespace
draw_command_visitor(gl::ring_buffer& index_ring_buffer, gl::ring_buffer& attrib_ring_buffer,
gl::texture* gl_attrib_buffers, gl::glsl::program* program, GLint min_texbuffer_alignment,
gl::vertex_cache* vertex_cache,
std::function<attribute_storage(rsx::rsx_state, std::vector<std::pair<u32, u32>>)> gvb)
: m_index_ring_buffer(index_ring_buffer)
, m_attrib_ring_buffer(attrib_ring_buffer)
@@ -291,7 +279,6 @@ namespace
, m_program(program)
, m_min_texbuffer_alignment(min_texbuffer_alignment)
, get_vertex_buffers(gvb)
, m_vertex_cache(vertex_cache)
{
for (u8 index = 0; index < rsx::limits::vertex_count; ++index) {
if (rsx::method_registers.vertex_arrays_info[index].size() ||
@@ -381,7 +368,7 @@ namespace
gl::ring_buffer& m_index_ring_buffer;
gl::ring_buffer& m_attrib_ring_buffer;
gl::texture* m_gl_attrib_buffers;
gl::vertex_cache* m_vertex_cache;
gl::glsl::program* m_program;
GLint m_min_texbuffer_alignment;
std::function<attribute_storage(rsx::rsx_state, std::vector<std::pair<u32, u32>>)>
@@ -392,7 +379,7 @@ namespace
u32 verts_allocated = max_index - min_index + 1;
vertex_buffer_visitor visitor(verts_allocated, m_attrib_ring_buffer,
m_program, m_gl_attrib_buffers, m_min_texbuffer_alignment, m_vertex_cache);
m_program, m_gl_attrib_buffers, m_min_texbuffer_alignment);
const auto& vertex_buffers =
get_vertex_buffers(rsx::method_registers, {{min_index, verts_allocated}});
for (const auto& vbo : vertex_buffers) std::apply_visitor(visitor, vbo);
@@ -465,12 +452,11 @@ std::tuple<u32, std::optional<std::tuple<GLenum, u32>>> GLGSRender::set_vertex_b
{
std::chrono::time_point<steady_clock> then = steady_clock::now();
auto result = std::apply_visitor(draw_command_visitor(*m_index_ring_buffer, *m_attrib_ring_buffer,
m_gl_attrib_buffers, m_program, m_min_texbuffer_alignment,
m_vertex_cache.get(),
[this](const auto& state, const auto& list) {
return this->get_vertex_buffers(state, list, 0);
}),
get_draw_command(rsx::method_registers));
m_gl_attrib_buffers, m_program, m_min_texbuffer_alignment,
[this](const auto& state, const auto& list) {
return this->get_vertex_buffers(state, list);
}),
get_draw_command(rsx::method_registers));
std::chrono::time_point<steady_clock> now = steady_clock::now();
m_vertex_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
-3
View File
@@ -239,8 +239,6 @@ struct RSXFragmentProgram
u8 textures_alpha_kill[16];
u32 textures_zfunc[16];
bool valid;
rsx::texture_dimension_extended get_texture_dimension(u8 id) const
{
return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);
@@ -265,7 +263,6 @@ struct RSXFragmentProgram
, ctrl(0)
, unnormalized_coords(0)
, texture_dimensions(0)
, valid(false)
{
}
};
+126 -134
View File
@@ -5,6 +5,7 @@
#include "RSXThread.h"
#include "Emu/Cell/PPUCallback.h"
#include "Emu/Cell/lv2/sys_rsx.h"
#include "Common/BufferUtils.h"
#include "rsx_methods.h"
@@ -34,55 +35,69 @@ namespace rsx
switch (location)
{
case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER:
case CELL_GCM_LOCATION_LOCAL:
{
// TODO: Don't use unnamed constants like 0xC0000000
return 0xC0000000 + offset;
}
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
case CELL_GCM_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(offset))
case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER:
case CELL_GCM_LOCATION_LOCAL:
{
return result;
// TODO: Don't use unnamed constants like 0xC0000000
return 0xC0000000 + offset;
}
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
}
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL:
return 0x40301400 + offset;
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(0x0e000000 + offset))
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
case CELL_GCM_LOCATION_MAIN:
{
return result;
if (u32 result = RSXIOMem.RealAddr(offset))
{
return result;
}
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
//if (fxm::get<GSRender>()->strict_ordering[offset >> 20])
//{
// _mm_mfence(); // probably doesn't have any effect on current implementation
//}
}
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
}
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL:
return 0x40301400 + offset; // not sure if this should be 0x40300000 or offset to the actual reports, lets try reports for now
//return 0x100000 + offset; // TODO: Properly implement
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0:
fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 (offset=0x%x, location=0x%x)" HERE, offset, location);
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(0x0e000000 + offset))
{
return result;
}
case CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0:
fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 (offset=0x%x, location=0x%x)" HERE, offset, location);
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW:
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R:
return 0x40300000 + offset;
//if (fxm::get<GSRender>()->strict_ordering[offset >> 20])
//{
// _mm_mfence(); // probably doesn't have any effect on current implementation
//}
}
case CELL_GCM_CONTEXT_DMA_DEVICE_RW:
return 0x40000000 + offset;
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0:
fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 (offset=0x%x, location=0x%x)" HERE, offset, location);
case CELL_GCM_CONTEXT_DMA_DEVICE_R:
return 0x40000000 + offset;
case CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0:
fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 (offset=0x%x, location=0x%x)" HERE, offset, location);
default:
fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location);
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW:
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R:
return 0x40300000 + offset; // this offset also doesnt seem like its right, but it works for now so w/e
//return 0x100 + offset; // TODO: Properly implement
case CELL_GCM_CONTEXT_DMA_DEVICE_RW:
return 0x40000000 + offset;
//fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_RW (offset=0x%x, location=0x%x)" HERE, offset, location);
case CELL_GCM_CONTEXT_DMA_DEVICE_R:
return 0x40000000 + offset;
//fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_R (offset=0x%x, location=0x%x)" HERE, offset, location);
default:
fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location);
}
}
@@ -388,7 +403,7 @@ namespace rsx
if (get_system_time() - start_time > vblank_count * 1000000 / 60)
{
vblank_count++;
sys_rsx_context_attribute(0x55555555, 0xFED, 1, 0, 0, 0);
sys_rsx_context_attribute(0x55555555, 0xFED, 1, 0, 0, 0);
if (vblank_handler)
{
intr_thread->cmd_list
@@ -403,16 +418,13 @@ namespace rsx
continue;
}
while (Emu.IsPaused())
std::this_thread::sleep_for(10ms);
while (Emu.IsPaused())
std::this_thread::sleep_for(10ms);
std::this_thread::sleep_for(1ms); // hack
}
});
// Raise priority above other threads
thread_ctrl::set_native_priority(1);
// TODO: exit condition
while (!Emu.IsStopped())
{
@@ -507,7 +519,7 @@ namespace rsx
u32 reg = ((cmd & RSX_METHOD_NON_INCREMENT_CMD_MASK) == RSX_METHOD_NON_INCREMENT_CMD) ? first_cmd : first_cmd + i;
u32 value = args[i];
//LOG_NOTICE(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value);
//LOG_WARNING(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value);
method_registers.decode(reg, value);
@@ -544,18 +556,15 @@ namespace rsx
m_vblank_thread.reset();
}
if (m_vertex_streaming_task.available_threads > 0)
if (m_vertex_streaming_task.processing_threads.size() > 0)
{
for (auto &task : m_vertex_streaming_task.worker_threads)
for (auto &thr : m_vertex_streaming_task.processing_threads)
{
if (!task.worker_thread)
break;
task.worker_thread->join();
task.worker_thread.reset();
thr->join();
thr.reset();
}
m_vertex_streaming_task.available_threads = 0;
m_vertex_streaming_task.processing_threads.resize(0);
}
}
@@ -758,7 +767,7 @@ namespace rsx
}
std::vector<std::variant<vertex_array_buffer, vertex_array_register, empty_vertex_array>>
thread::get_vertex_buffers(const rsx::rsx_state& state, const std::vector<std::pair<u32, u32>>& vertex_ranges, const u64 consumed_attrib_mask) const
thread::get_vertex_buffers(const rsx::rsx_state& state, const std::vector<std::pair<u32, u32>>& vertex_ranges) const
{
std::vector<std::variant<vertex_array_buffer, vertex_array_register, empty_vertex_array>> result;
result.reserve(rsx::limits::vertex_count);
@@ -766,10 +775,8 @@ namespace rsx
u32 input_mask = state.vertex_attrib_input_mask();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
const bool enabled = !!(input_mask & (1 << index));
const bool consumed = !!(consumed_attrib_mask & (1ull << index));
if (!enabled && !consumed)
bool enabled = !!(input_mask & (1 << index));
if (!enabled)
continue;
if (state.vertex_arrays_info[index].size() > 0)
@@ -986,17 +993,9 @@ namespace rsx
RSXFragmentProgram thread::get_current_fragment_program(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info) const
{
RSXFragmentProgram result = {};
const u32 shader_program = rsx::method_registers.shader_program_address();
if (shader_program == 0)
return result;
const u32 program_location = (shader_program & 0x3) - 1;
const u32 program_offset = (shader_program & ~0x3);
result.offset = program_offset;
result.addr = vm::base(rsx::get_address(program_offset, program_location));
result.valid = true;
u32 shader_program = rsx::method_registers.shader_program_address();
result.offset = shader_program & ~0x3;
result.addr = vm::base(rsx::get_address(result.offset, (shader_program & 0x3) - 1));
result.ctrl = rsx::method_registers.shader_control();
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
@@ -1073,9 +1072,9 @@ namespace rsx
rsx::method_registers.reset();
}
void thread::init(u32 ioAddress, u32 ioSize, u32 ctrlAddress, u32 localAddress)
void thread::init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
{
ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
ctrl = vm::_ptr<CellGcmControl>(ctrlAddress);
this->ioAddress = ioAddress;
this->ioSize = ioSize;
local_mem_addr = localAddress;
@@ -1141,8 +1140,7 @@ namespace rsx
}
}
void thread::post_vertex_stream_to_upload(gsl::span<const gsl::byte> src, gsl::span<gsl::byte> dst, rsx::vertex_base_type type, u32 vector_element_count,
u32 attribute_src_stride, u8 dst_stride, u32 vertex_count, std::function<void(void *, rsx::vertex_base_type, u8, u32)> callback)
void thread::post_vertex_stream_to_upload(gsl::span<const gsl::byte> src, gsl::span<gsl::byte> dst, rsx::vertex_base_type type, u32 vector_element_count, u32 attribute_src_stride, u8 dst_stride, std::function<void(void *, rsx::vertex_base_type, u8, u32)> callback)
{
upload_stream_packet packet;
packet.dst_span = dst;
@@ -1152,95 +1150,94 @@ namespace rsx
packet.dst_stride = dst_stride;
packet.vector_width = vector_element_count;
packet.post_upload_func = callback;
packet.vertex_count = vertex_count;
if (m_vertex_streaming_task.available_threads == 0)
m_vertex_streaming_task.packets.push_back(packet);
}
void thread::start_vertex_upload_task(u32 vertex_count)
{
if (m_vertex_streaming_task.processing_threads.size() == 0)
{
const u32 streaming_thread_count = (u32)g_cfg.video.vertex_upload_threads;
m_vertex_streaming_task.available_threads = streaming_thread_count;
m_vertex_streaming_task.processing_threads.resize(streaming_thread_count);
for (u32 n = 0; n < streaming_thread_count; ++n)
{
thread_ctrl::spawn(m_vertex_streaming_task.worker_threads[n].worker_thread, "Vertex Stream " + std::to_string(n), [this, n]()
thread_ctrl::spawn(m_vertex_streaming_task.processing_threads[n], "Vertex Stream " + std::to_string(n), [this, n]()
{
auto &owner = m_vertex_streaming_task;
auto &task = m_vertex_streaming_task.worker_threads[n];
auto &task = m_vertex_streaming_task;
const u32 index = n;
while (!Emu.IsStopped())
{
if (task.thread_status.load(std::memory_order_consume) != 0)
if (task.remaining_packets != 0)
{
for (auto &packet: task.packets)
//Wait for me!
task.ready_threads--;
const size_t step = task.processing_threads.size();
const size_t job_count = task.packets.size();
//Process every nth packet
size_t current_job = index;
while (true)
{
write_vertex_array_data_to_buffer(packet.dst_span, packet.src_span, packet.vertex_count, packet.type, packet.vector_width, packet.src_stride, packet.dst_stride);
if (current_job >= job_count)
break;
auto &packet = task.packets[current_job];
write_vertex_array_data_to_buffer(packet.dst_span, packet.src_span, task.vertex_count, packet.type, packet.vector_width, packet.src_stride, packet.dst_stride);
if (packet.post_upload_func)
packet.post_upload_func(packet.dst_span.data(), packet.type, (u8)packet.vector_width, packet.vertex_count);
packet.post_upload_func(packet.dst_span.data(), packet.type, (u8)packet.vector_width, task.vertex_count);
owner.remaining_tasks--;
_mm_sfence();
task.remaining_packets--;
current_job += step;
}
task.packets.resize(0);
task.thread_status.store(0);
_mm_sfence();
}
_mm_mfence();
std::this_thread::yield();
while (task.remaining_packets > 0 && !Emu.IsStopped())
{
_mm_lfence();
std::this_thread::sleep_for(0us);
}
_mm_sfence();
task.ready_threads++;
}
else
std::this_thread::sleep_for(0us);
//thread_ctrl::wait();
//busy_wait();
}
});
}
}
//Increment job counter..
m_vertex_streaming_task.remaining_tasks++;
//Assign this packet to a thread
//Simple round robin based on first available thread
upload_stream_worker *best_fit = nullptr;
for (auto &worker : m_vertex_streaming_task.worker_threads)
while (m_vertex_streaming_task.ready_threads != 0 && !Emu.IsStopped())
{
if (!worker.worker_thread)
break;
if (worker.thread_status.load(std::memory_order_consume) == 0)
{
if (worker.packets.size() == 0)
{
worker.packets.push_back(packet);
return;
}
if (best_fit == nullptr)
best_fit = &worker;
else if (best_fit->packets.size() > worker.packets.size())
best_fit = &worker;
}
_mm_lfence();
busy_wait();
}
best_fit->packets.push_back(packet);
}
void thread::start_vertex_upload_task()
{
for (auto &worker : m_vertex_streaming_task.worker_threads)
{
if (!worker.worker_thread)
break;
if (worker.thread_status.load(std::memory_order_consume) == 0 && worker.packets.size() > 0)
{
worker.thread_status.store(1);
}
}
m_vertex_streaming_task.vertex_count = vertex_count;
m_vertex_streaming_task.ready_threads = 0;
m_vertex_streaming_task.remaining_packets = (int)m_vertex_streaming_task.packets.size();
}
void thread::wait_for_vertex_upload_task()
{
while (m_vertex_streaming_task.remaining_tasks.load(std::memory_order_consume) != 0 && !Emu.IsStopped())
while (m_vertex_streaming_task.remaining_packets > 0 && !Emu.IsStopped())
{
_mm_pause();
_mm_lfence();
busy_wait();
}
m_vertex_streaming_task.packets.resize(0);
}
bool thread::vertex_upload_task_ready()
@@ -1248,12 +1245,7 @@ namespace rsx
if (g_cfg.video.vertex_upload_threads < 2)
return false;
//Not initialized
if (m_vertex_streaming_task.available_threads == 0)
return true;
//At least two threads are available
return (m_vertex_streaming_task.remaining_tasks < (m_vertex_streaming_task.available_threads - 1));
return (m_vertex_streaming_task.remaining_packets == 0 && m_vertex_streaming_task.ready_threads == 0);
}
void thread::flip(int buffer)
+21 -27
View File
@@ -22,8 +22,6 @@
#include "Utilities/variant.hpp"
#include "define_new_memleakdetect.h"
#include "Emu/Cell/lv2/sys_rsx.h"
extern u64 get_system_time();
extern bool user_asked_for_frame_capture;
@@ -115,7 +113,7 @@ namespace rsx
std::vector<u32> element_push_buffer;
public:
RsxDmaControl* ctrl = nullptr;
CellGcmControl* ctrl = nullptr;
Timer timer_sync;
@@ -131,23 +129,24 @@ namespace rsx
public:
std::shared_ptr<class ppu_thread> intr_thread;
// I hate this flag, but until hle is closer to lle, its needed
bool isHLE{ false };
u32 ioAddress, ioSize;
u32 flip_status;
int flip_mode;
int debug_level;
int frequency_mode;
atomic_t<bool> requested_vsync{false};
atomic_t<bool> enable_second_vhandler{false};
RsxDisplayInfo display_buffers[8];
u32 display_buffers_count{0};
u32 current_display_buffer{0};
u32 tiles_addr;
u32 zculls_addr;
vm::ps3::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
u32 gcm_buffers_count;
u32 gcm_current_buffer;
u32 ctxt_addr;
u32 label_addr;
u32 nv406e_semaphore_addr;
u32 nv4097_semaphore_index;
u32 local_mem_addr, main_mem_addr;
bool strict_ordering[0x1000];
bool m_rtts_dirty;
bool m_transform_constants_dirty;
@@ -216,7 +215,7 @@ namespace rsx
gsl::span<const gsl::byte> get_raw_vertex_buffer(const rsx::data_array_format_info&, u32 base_offset, const std::vector<std::pair<u32, u32>>& vertex_ranges) const;
std::vector<std::variant<vertex_array_buffer, vertex_array_register, empty_vertex_array>>
get_vertex_buffers(const rsx::rsx_state& state, const std::vector<std::pair<u32, u32>>& vertex_ranges, const u64 consumed_attrib_mask) const;
get_vertex_buffers(const rsx::rsx_state& state, const std::vector<std::pair<u32, u32>>& vertex_ranges) const;
std::variant<draw_array_command, draw_indexed_array_command, draw_inlined_array>
get_draw_command(const rsx::rsx_state& state) const;
@@ -247,30 +246,25 @@ namespace rsx
gsl::span<gsl::byte> dst_span;
rsx::vertex_base_type type;
u32 vector_width;
u32 vertex_count;
u32 src_stride;
u8 dst_stride;
};
struct upload_stream_worker
{
std::shared_ptr<thread_ctrl> worker_thread;
std::vector<upload_stream_packet> packets;
std::atomic<int> thread_status = { 0 };
};
struct upload_stream_task
{
std::array<upload_stream_worker, 16> worker_threads;
int available_threads = 0;
std::atomic<int> remaining_tasks = {0};
std::vector<upload_stream_packet> packets;
std::atomic<int> remaining_packets = { 0 };
std::atomic<int> ready_threads = { 0 };
std::atomic<u32> vertex_count;
std::vector<std::shared_ptr<thread_ctrl>> processing_threads;
};
upload_stream_task m_vertex_streaming_task;
void post_vertex_stream_to_upload(gsl::span<const gsl::byte> src, gsl::span<gsl::byte> dst, rsx::vertex_base_type type,
u32 vector_element_count, u32 attribute_src_stride, u8 dst_stride, u32 vertex_count,
u32 vector_element_count, u32 attribute_src_stride, u8 dst_stride,
std::function<void(void *, rsx::vertex_base_type, u8, u32)> callback);
void start_vertex_upload_task();
void start_vertex_upload_task(u32 vertex_count);
void wait_for_vertex_upload_task();
bool vertex_upload_task_ready();
@@ -348,7 +342,7 @@ namespace rsx
public:
void reset();
void init(u32 ioAddress, u32 ioSize, u32 ctrlAddress, u32 localAddress);
void init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
tiled_region get_tiled_address(u32 offset, u32 location);
GcmTileInfo *find_tile(u32 offset, u32 location);

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