Compare commits

..

8 Commits

Author SHA1 Message Date
Zangetsu38 668005c856 Fix 2017-07-31 09:16:37 +02:00
Jake 7efa53b218 Add gcm to auto lle / liblv2 2017-07-31 09:16:37 +02:00
Jake ad3fc60631 d3d12: Fix 0 sized framebuffer crashes 2017-07-31 09:16:37 +02:00
Jake c09cbeac15 sys_rsx: implement support for lle-gcm 2017-07-31 09:16:37 +02:00
Jake e854eb6ecd rsx/gcm: Implement rsx dma. Refactor gcm/rsx to not be as codependent 2017-07-31 09:16:37 +02:00
Zangetsu38 e7841b5d9e Update LLVM 5.0 2017-07-31 09:15:24 +02:00
Zangetsu38 76a49518e0 Update Project to Visual Studio 2017. 2017-07-31 09:07:17 +02:00
Zion Nimchuk 4a197e16a6 Initial LLVM 5 port 2017-07-31 09:07:15 +02:00
197 changed files with 3756 additions and 8036 deletions
-5
View File
@@ -41,10 +41,6 @@
/Vulkan/Vulkan-build
/Vulkan/glslang-build
# Themes
!/bin/GuiConfigs/
/bin/GuiConfigs/*.ini
/bin/rpcs3.ini
/bin/rpcs3.ipdb
/bin/rpcs3.iobj
@@ -75,7 +71,6 @@ rpcs3/git-version.h
!/bin/dev_hdd0/game/
/bin/dev_hdd0/game/*
!/bin/dev_hdd0/game/TEST12345/
/bin/dev_hdd0/disc/*
# Ignore other system generated files
bin/dev_hdd0/*.txt
-13
View File
@@ -62,24 +62,12 @@ before_install:
brew update; brew update;
brew install ccache glew llvm40;
fi;
# We need to update binutils to a newer version to link against the ffmpeg libs on.
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
sudo add-apt-repository ppa:jonathonf/binutils -y ;
sudo apt-get update ;
sudo apt-get install binutils -y;
ld --version ;
fi;
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
- mkdir build
- cd build
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
else
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/#$TRAVIS_PULL_REQUEST";
fi;
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr;
- make -j 3
- # AppImage generation
@@ -138,7 +126,6 @@ addons:
#- qtbase5-dev
- libudev-dev
- libevdev-dev
- libpulse-dev
coverity_scan:
project:
name: $TRAVIS_REPO_SLUG
+2 -2
View File
@@ -1,6 +1,6 @@
# Getting Started
Before getting started using the emulator, read the [Quickstart Guide](https://rpcs3.net/quickstart) and the [FAQ](https://rpcs3.net/faq). After reading those, if you need support, visit our [Forums](https://forums.rpcs3.net).
Before getting started using the emulator, read the [Quickstart Guide](https://rpcs3.net/quickstart) and the [FAQ](https://rpcs3.net/faq). After reading those, if you need support, visit our [Forums](http://www.emunewz.net/forum/forumdisplay.php?fid=172).
# Issue Reporting
@@ -13,7 +13,7 @@ Before getting started using the emulator, read the [Quickstart Guide](https://r
- Use understandable English. It doesn't need to be perfect, but clear enough to understand your message.
- While reporting issues, don't forget to include details about your system (OS, CPU, GPU, etc.), as well as the RPCS3.log file.
Submitting your test results for Commercial Games must be done on our forums. Please read the [Game Compatibility](https://github.com/RPCS3/rpcs3/wiki/Game-Compatibility) wiki page before doing so.
Submitting your test results for Commercial Games must be done on our forums' [Commercial Games](http://www.emunewz.net/forum/forumdisplay.php?fid=193) section. If there's already a thread for the game you want to report post in it, otherwise please make a new thread following the [Guidelines for submitting new games](http://www.emunewz.net/forum/showthread.php?tid=174376).
# Contributing
+5 -8
View File
@@ -8,9 +8,9 @@ RPCS3
The world's first open-source PlayStation 3 emulator/debugger written in C++ for Windows and Linux.
You can find some basic information in our [**website**](https://rpcs3.net/).
For discussion about this emulator and PS3 emulation please visit our [**forums**](https://forums.rpcs3.net) and our [**Discord server**](https://discord.me/RPCS3).
For discussion about this emulator and PS3 emulation please visit our [**forums**](http://www.emunewz.net/forum/forumdisplay.php?fid=172) and our [**Discord server**](https://discord.me/RPCS3).
[**Support Lead Developers Nekotekina and kd-11 on Patreon**](https://www.patreon.com/Nekotekina)
[**Support Lead Developer Nekotekina on Patreon**](https://www.patreon.com/Nekotekina)
## Development
@@ -33,12 +33,12 @@ If you want to contribute please take a look at the [Coding Style](https://githu
* GCC 5.1+ or Clang 3.5.0+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691))
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git qt5-default`
* Arch: `sudo pacman -S glew openal cmake llvm qt5-base`
* Fedora: `sudo dnf install cmake qt5-devel vulkan-devel glew glew-devel`
* Fedora: `sudo dnf install cmake qt5-devel vulkan-devel libGLEW`
### Mac OSX
Mac OSX is not supported at this moment because it doesn't meet system requirements (OpenGL 4.3)
* Xcode 6+ (tested with Xcode 6.4)
* Install with Homebrew: `brew install glew llvm qt cmake`
* Install with Homebrew: `brew install glew`
## Building on Windows:
@@ -66,10 +66,7 @@ To initialize the repository don't forget to execute `git submodule update --ini
4) `cmake CMakeLists.txt && make GitVersion && make` </br>
5) Run RPCS3 with `./bin/rpcs3` </br>
If you are on OSX and want to build with brew llvm and qt don't forget to add the following environment variables
* `LLVM_DIR=/usr/local/opt/llvm/` (or wherever llvm was installed).
* `Qt5_DIR=/usr/local/opt/qt/lib/cmake/Qt5` (or wherever qt was installed).
If you are on OSX and want to build with llvm don't forget to add `-DLLVM_DIR=...` (or wherever llvm brew was installed) to cmake invocation.
When using GDB, configure it to ignore SIGSEGV signal (`handle SIGSEGV nostop noprint`).
+3 -25
View File
@@ -48,11 +48,6 @@ namespace cfg
static void decode(const YAML::Node& data, class _base& rhs);
}
std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
{
return {std::to_string(min), std::to_string(max)};
}
bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
{
// TODO: this could be rewritten without exceptions (but it should be as safe as possible and provide logs)
@@ -87,8 +82,6 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string& value)
{
u64 max = -1;
for (u64 i = 0;; i++)
{
std::string var;
@@ -106,8 +99,6 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
{
break;
}
max = i;
}
try
@@ -117,22 +108,14 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
if (pos != value.size())
{
if (out) cfg.error("cfg::try_to_enum_value('%s'): unexpected characters (pos=%zu)", value, pos);
return false;
}
if (val > max)
{
if (out) cfg.error("cfg::try_to_enum_value('%s'): out of bounds(0..%u)", value, max);
return false;
}
if (out) *out = val;
return true;
}
catch (const std::exception& e)
catch (...)
{
if (out) cfg.error("cfg::try_to_enum_value('%s'): invalid enum value: %s", value, e.what());
return false;
}
}
@@ -285,19 +268,14 @@ std::string cfg::node::to_string() const
YAML::Emitter out;
cfg::encode(out, *this);
return {out.c_str(), out.size()};
return{ out.c_str(), out.size() };
}
bool cfg::node::from_string(const std::string& value) try
bool cfg::node::from_string(const std::string& value)
{
cfg::decode(YAML::Load(value), *this);
return true;
}
catch (const std::exception& e)
{
cfg.fatal("%s thrown: %s", typeid(e).name(), e.what());
return false;
}
void cfg::node::from_default()
{
-8
View File
@@ -12,9 +12,6 @@
namespace cfg
{
// Format min and max values
std::vector<std::string> make_int_range(s64 min, s64 max);
// Convert string to signed integer
bool try_to_int64(s64* out, const std::string& value, s64 min, s64 max);
@@ -252,11 +249,6 @@ namespace cfg
return false;
}
std::vector<std::string> to_list() const override
{
return make_int_range(Min, Max);
}
};
// Alias for 32 bit int
+6 -66
View File
@@ -93,7 +93,6 @@ static fs::error to_error(DWORD e)
case ERROR_NEGATIVE_SEEK: return fs::error::inval;
case ERROR_DIRECTORY: return fs::error::inval;
case ERROR_INVALID_NAME: return fs::error::inval;
case ERROR_SHARING_VIOLATION: return fs::error::acces;
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
}
}
@@ -510,7 +509,7 @@ bool fs::remove_dir(const std::string& path)
#endif
}
bool fs::rename(const std::string& from, const std::string& to, bool overwrite)
bool fs::rename(const std::string& from, const std::string& to)
{
const auto device = get_virtual_device(from);
@@ -525,43 +524,14 @@ bool fs::rename(const std::string& from, const std::string& to, bool overwrite)
}
#ifdef _WIN32
const auto ws1 = to_wchar(from);
const auto ws2 = to_wchar(to);
if (!MoveFileExW(ws1.get(), ws2.get(), overwrite ? MOVEFILE_REPLACE_EXISTING : 0))
if (!MoveFileW(to_wchar(from).get(), to_wchar(to).get()))
{
DWORD error1 = GetLastError();
if (overwrite && error1 == ERROR_ACCESS_DENIED && is_dir(from) && is_dir(to))
{
if (RemoveDirectoryW(ws2.get()))
{
if (MoveFileW(ws1.get(), ws2.get()))
{
return true;
}
error1 = GetLastError();
CreateDirectoryW(ws2.get(), NULL); // TODO
}
else
{
error1 = GetLastError();
}
}
g_tls_error = to_error(error1);
g_tls_error = to_error(GetLastError());
return false;
}
return true;
#else
if (!overwrite && exists(to))
{
g_tls_error = fs::error::exist;
return false;
}
if (::rename(from.c_str(), to.c_str()) != 0)
{
g_tls_error = to_error(errno);
@@ -794,13 +764,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
disp = test(mode & fs::trunc) ? TRUNCATE_EXISTING : OPEN_EXISTING;
}
DWORD share = FILE_SHARE_READ;
if (!test(mode & fs::unshare))
{
share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
}
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
@@ -808,7 +772,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return;
}
class windows_file final : public file_base, public get_native_handle
class windows_file final : public file_base
{
const HANDLE m_handle;
@@ -915,11 +879,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return size.QuadPart;
}
native_handle get() override
{
return m_handle;
}
};
m_file = std::make_unique<windows_file>(handle);
@@ -943,7 +902,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return;
}
class unix_file final : public file_base, public get_native_handle
class unix_file final : public file_base
{
const int m_fd;
@@ -1032,11 +991,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return file_info.st_size;
}
native_handle get() override
{
return m_fd;
}
};
m_file = std::make_unique<unix_file>(fd);
@@ -1112,20 +1066,6 @@ fs::file::file(const void* ptr, std::size_t size)
m_file = std::make_unique<memory_stream>(ptr, size);
}
fs::native_handle fs::file::get_handle() const
{
if (auto getter = dynamic_cast<get_native_handle*>(m_file.get()))
{
return getter->get();
}
#ifdef _WIN32
return INVALID_HANDLE_VALUE;
#else
return -1;
#endif
}
void fs::dir::xnull() const
{
fmt::throw_exception<std::logic_error>("fs::dir is null");
+1 -18
View File
@@ -10,12 +10,6 @@
namespace fs
{
#ifdef _WIN32
using native_handle = void*;
#else
using native_handle = int;
#endif
// File open mode flags
enum class open_mode : u32
{
@@ -25,7 +19,6 @@ namespace fs
create,
trunc,
excl,
unshare,
__bitset_enum_max
};
@@ -36,7 +29,6 @@ namespace fs
constexpr auto create = +open_mode::create; // Create file if it doesn't exist
constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty
constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr auto unshare = +open_mode::unshare; // Prevent opening the file twice
constexpr auto rewrite = open_mode::write + open_mode::create + open_mode::trunc;
@@ -63,12 +55,6 @@ namespace fs
s64 ctime;
};
// Native handle getter
struct get_native_handle
{
virtual native_handle get() = 0;
};
// File handle base
struct file_base
{
@@ -159,7 +145,7 @@ namespace fs
bool create_path(const std::string& path);
// Rename (move) file or directory
bool rename(const std::string& from, const std::string& to, bool overwrite);
bool rename(const std::string& from, const std::string& to);
// Copy file contents
bool copy_file(const std::string& from, const std::string& to, bool overwrite);
@@ -361,9 +347,6 @@ namespace fs
if (seek(0), !read(result)) xfail();
return result;
}
// Get native handle if available
native_handle get_handle() const;
};
class dir final
+3 -3
View File
@@ -90,13 +90,13 @@ extern void jit_finalize()
// Helper class
struct MemoryManager : llvm::RTDyldMemoryManager
{
std::unordered_map<std::string, u64>& m_link;
std::unordered_map<std::string, std::uintptr_t>& m_link;
std::array<u8, 16>* m_tramps{};
u8* m_code_addr{}; // TODO
MemoryManager(std::unordered_map<std::string, u64>& table)
MemoryManager(std::unordered_map<std::string, std::uintptr_t>& table)
: m_link(table)
{
}
@@ -371,7 +371,7 @@ public:
}
};
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, std::string _cpu)
jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>& _link, std::string _cpu)
: m_link(std::move(_link))
, m_cpu(std::move(_cpu))
{
+18 -175
View File
@@ -3,21 +3,16 @@
#include "StrFmt.h"
#include "sema.h"
#include "Utilities/sysinfo.h"
#include "rpcs3_version.h"
#include <string>
#include <unordered_map>
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#else
#include <chrono>
#include <sys/mman.h>
#endif
#include <zlib.h>
static std::string empty_string()
{
return {};
@@ -49,38 +44,29 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
namespace logs
{
constexpr std::size_t s_log_size = 128 * 1024 * 1024;
constexpr std::size_t s_log_size_s = s_log_size / 2;
constexpr std::size_t s_log_size_t = s_log_size / 4 + s_log_size_s;
constexpr std::size_t s_log_size_e = s_log_size / 8 + s_log_size_t;
constexpr std::size_t s_log_size_f = s_log_size / 16 + s_log_size_e;
class file_writer
{
// Could be memory-mapped file
fs::file m_file;
std::string m_name;
#ifdef _WIN32
::HANDLE m_fmap;
#endif
atomic_t<std::size_t> m_pos{0};
std::size_t m_size{0};
uchar* m_fptr{};
public:
file_writer(const std::string& name);
virtual ~file_writer();
virtual ~file_writer() = default;
// Append raw data
void log(logs::level sev, const char* text, std::size_t size);
void log(const char* text, std::size_t size);
};
struct file_listener : public file_writer, public listener
{
file_listener(const std::string& name);
virtual ~file_listener() = default;
file_listener(const std::string& name)
: file_writer(name)
, listener()
{
const std::string& start = fmt::format("\xEF\xBB\xBF" "RPCS3 v%s\n", rpcs3::version.to_string());
file_writer::log(start.data(), start.size());
}
// Encode level, current thread name, channel name and write log message
virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) override;
@@ -151,26 +137,12 @@ namespace logs
}
};
struct stored_message
{
message m;
u64 stamp;
std::string prefix;
std::string text;
};
// Channel registry mutex
semaphore<> g_mutex;
// Channel registry
std::unordered_map<std::string, channel_info> g_channels;
// Messages for delayed listener initialization
std::vector<stored_message> g_messages;
// Must be set to true in main()
atomic_t<bool> g_init{false};
void reset()
{
semaphore_lock lock(g_mutex);
@@ -187,17 +159,6 @@ namespace logs
g_channels[ch_name].set_level(value);
}
// Must be called in main() to stop accumulating messages in g_messages
void set_init()
{
if (!g_init)
{
semaphore_lock lock(g_mutex);
g_messages.clear();
g_init = true;
}
}
}
logs::listener::~listener()
@@ -209,19 +170,11 @@ void logs::listener::add(logs::listener* _new)
// Get first (main) listener
listener* lis = get_logger();
semaphore_lock lock(g_mutex);
// Install new listener at the end of linked list
while (lis->m_next || !lis->m_next.compare_and_swap_test(nullptr, _new))
{
lis = lis->m_next;
}
// Send initial messages
for (const auto& msg : g_messages)
{
_new->log(msg.stamp, msg.m, msg.prefix, msg.text);
}
}
void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u64* args)
@@ -254,29 +207,12 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u
}
// Get text
thread_local std::string text; text.clear();
std::string text;
fmt::raw_append(text, fmt, sup, args);
std::string prefix = g_tls_log_prefix();
// Get first (main) listener
listener* lis = get_logger();
if (!g_init)
{
semaphore_lock lock(g_mutex);
if (!g_init)
{
while (lis)
{
lis->log(stamp, *this, prefix, text);
lis = lis->m_next;
}
// Store message additionally
g_messages.emplace_back(stored_message{*this, stamp, std::move(prefix), text});
}
}
// Send message to all listeners
while (lis)
@@ -289,28 +225,13 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u
[[noreturn]] extern void catch_all_exceptions();
logs::file_writer::file_writer(const std::string& name)
: m_name(fs::get_config_dir() + name)
{
try
{
if (!m_file.open(m_name, fs::read + fs::write + fs::create + fs::trunc + fs::unshare))
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
{
fmt::throw_exception("Can't create file %s (error %s)", name, fs::g_tls_error);
fmt::throw_exception("Can't create log file %s (error %s)", name, fs::g_tls_error);
}
#ifdef _WIN32
m_fmap = CreateFileMappingW(m_file.get_handle(), 0, PAGE_READWRITE, s_log_size >> 32, s_log_size & 0xffffffff, 0);
m_fptr = m_fmap ? (uchar*)MapViewOfFile(m_fmap, FILE_MAP_WRITE, 0, 0, 0) : nullptr;
#else
m_file.trunc(s_log_size);
m_fptr = (uchar*)::mmap(0, s_log_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_file.get_handle(), 0);
#endif
verify(m_name.c_str()), m_fptr;
std::memset(m_fptr, '\n', s_log_size);
// Rotate backups (TODO)
fs::rename(m_name + ".gz", m_name + "1.gz", true);
}
catch (...)
{
@@ -318,92 +239,14 @@ logs::file_writer::file_writer(const std::string& name)
}
}
logs::file_writer::~file_writer()
void logs::file_writer::log(const char* text, std::size_t size)
{
if (m_size == 0)
{
m_size = std::min<std::size_t>(+m_pos, s_log_size);
}
// Compress
z_stream zs{};
if (deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY) == Z_OK)
{
auto buf = std::make_unique<uchar[]>(s_log_size);
zs.avail_in = ::narrow<u32>(m_size);
zs.avail_out = s_log_size;
zs.next_in = m_fptr;
zs.next_out = buf.get();
if (deflate(&zs, Z_FINISH) != Z_STREAM_ERROR)
{
fs::file(m_name + ".gz", fs::rewrite).write(buf.get(), zs.total_out);
}
if (deflateEnd(&zs) != Z_OK)
{
}
}
#ifdef _WIN32
UnmapViewOfFile(m_fptr);
CloseHandle(m_fmap);
m_file.seek(m_size);
SetEndOfFile(m_file.get_handle());
#else
::munmap(m_fptr, s_log_size);
m_file.trunc(m_size);
#endif
}
void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
{
// Adaptive log limit
const auto lim =
sev >= logs::level::success ? s_log_size_s :
sev == logs::level::todo ? s_log_size_t :
sev == logs::level::error ? s_log_size_e : s_log_size_f;
if (m_pos >= lim)
{
return;
}
// Acquire memory
const auto pos = m_pos.fetch_add(size);
// Write if possible
if (pos + size <= s_log_size)
{
std::memcpy(m_fptr + pos, text, size);
}
else if (pos <= s_log_size)
{
m_size = pos;
}
}
logs::file_listener::file_listener(const std::string& name)
: file_writer(name)
, listener()
{
// Write UTF-8 BOM
file_writer::log(logs::level::always, "\xEF\xBB\xBF", 3);
// Write initial message
stored_message ver;
ver.m.ch = nullptr;
ver.m.sev = level::always;
ver.stamp = 0;
ver.text = fmt::format("RPCS3 v%s\n%s", rpcs3::version.to_string(), utils::get_system_info());
file_writer::log(logs::level::always, ver.text.data(), ver.text.size());
file_writer::log(logs::level::always, "\n", 1);
g_messages.emplace_back(std::move(ver));
m_file.write(text, size);
}
void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::string& prefix, const std::string& _text)
{
thread_local std::string text;
std::string text; text.reserve(prefix.size() + _text.size() + 200);
// Used character: U+00B7 (Middle Dot)
switch (msg.sev)
@@ -432,7 +275,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
text += "} ";
}
if (msg.ch && '\0' != *msg.ch->name)
if ('\0' != *msg.ch->name)
{
text += msg.ch->name;
text += msg.sev == level::todo ? " TODO: " : ": ";
@@ -445,5 +288,5 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
text += _text;
text += '\n';
file_writer::log(msg.sev, text.data(), text.size());
file_writer::log(text.data(), text.size());
}
+2 -2
View File
@@ -257,8 +257,8 @@ struct fmt::cfmt_src
void skip(std::size_t extra)
{
sup += extra + 1;
args += extra + 1;
++sup += extra;
++args += extra;
}
std::size_t fmt_string(std::string& out, std::size_t extra) const
+4 -16
View File
@@ -30,25 +30,13 @@ thread_local u64 g_tls_fault_spu = 0;
static void report_fatal_error(const std::string& msg)
{
static semaphore<> g_report_only_once;
g_report_only_once.wait();
std::string _msg = msg + "\n"
"HOW TO REPORT ERRORS: https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support\n"
"HOW TO REPORT ERRORS: Check the FAQ, README, other sources.\n"
"Please, don't send incorrect reports. Thanks for understanding.\n";
#ifdef _WIN32
_msg += "\nPress Yes or Enter to visit the URL above immediately.";
const std::size_t buf_size = _msg.size() + 1;
const int size = static_cast<int>(buf_size);
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]);
MultiByteToWideChar(CP_UTF8, 0, _msg.c_str(), size, buffer.get(), size);
if (MessageBoxW(0, buffer.get(), L"Fatal error", MB_ICONERROR | MB_YESNO) == IDYES)
{
ShellExecuteW(0, L"open", L"https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support", 0, 0, SW_SHOWNORMAL);
}
_msg += "Press (Ctrl+C) to copy this message.";
MessageBoxA(0, _msg.c_str(), "Fatal error", MB_ICONERROR); // TODO: unicode message
#else
std::printf("Fatal error: \n%s", _msg.c_str());
#endif
@@ -1248,7 +1236,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
return true;
}
if (vm::check_addr(addr, std::max<std::size_t>(1, d_size), vm::page_allocated | (is_writing ? vm::page_writable : vm::page_readable)))
if (vm::check_addr(addr, std::max<std::size_t>(1, d_size)))
{
if (cpu)
{
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#include <stdint.h>
namespace rpcs3
{
template<typename T>
static size_t hash_base(T value)
{
return static_cast<size_t>(value);
}
template<typename T>
static size_t hash_struct(const T& value)
{
// FNV 64-bit
size_t result = 14695981039346656037ull;
const unsigned char *bytes = reinterpret_cast<const unsigned char*>(&value);
for (size_t n = 0; n < sizeof(T); ++n)
{
result ^= bytes[n];
result *= 1099511628211ull;
}
return result;
}
}
+4 -10
View File
@@ -32,6 +32,7 @@
#define SAFE_BUFFERS
#define NEVER_INLINE __attribute__((noinline))
#define FORCE_INLINE __attribute__((always_inline)) inline
#define thread_local __thread
#endif
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size")
@@ -918,7 +919,7 @@ struct error_code
error_code() = default;
// Implementation must be provided specially
static s32 error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2);
static s32 error_report(const fmt_type_info* sup, u64 arg);
// Helper type
enum class not_an_error : s32
@@ -939,7 +940,7 @@ struct error_code
// Not an error constructor
template<typename ET, typename = decltype(ET::__not_an_error)>
error_code(const ET& value, std::nullptr_t = nullptr)
error_code(const ET& value, int = 0)
: value(static_cast<s32>(value))
{
}
@@ -947,14 +948,7 @@ struct error_code
// Error constructor
template<typename ET, typename = std::enable_if_t<is_error<ET>::value>>
error_code(const ET& value)
: value(error_report(fmt::get_type_info<fmt_unveil_t<ET>>(), fmt_unveil<ET>::get(value), nullptr, 0))
{
}
// Error constructor (2 args)
template<typename ET, typename T2, typename = std::enable_if_t<is_error<ET>::value>>
error_code(const ET& value, const T2& value2)
: value(error_report(fmt::get_type_info<fmt_unveil_t<ET>>(), fmt_unveil<ET>::get(value), fmt::get_type_info<fmt_unveil_t<T2>>(), fmt_unveil<T2>::get(value2)))
: value(error_report(fmt::get_type_info<fmt_unveil_t<ET>>(), fmt_unveil<ET>::get(value)))
{
}
+1 -4
View File
@@ -15,9 +15,6 @@ before_build:
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp 3rdparty/cereal 3rdparty/zlib 3rdparty/hidapi
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
- 7z x vulkan.7z -aos -oC:\rpcs3\Vulkan > null
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
- set CXXFLAGS=-DBRANCH=%BRANCH%
- if %configuration%==Release (cmake -G "Visual Studio 15 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 15 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/lib/cmake/llvm -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
@@ -28,7 +25,7 @@ install:
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
- if not exist zlib.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-HVE3xvheVFX05lRFdnZlh5aUU" -FileName zlib.7z
- set QTDIR=C:\Qt\5.9.1\msvc2017_64
- set QTDIR=C:\Qt\5.9\msvc2017_64
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
- set PATH=C:\Program Files (x86)\MSBuild\15.0\Bin;%QTDIR%;%PATH%
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
-248
View File
@@ -1,248 +0,0 @@
/*
Kuroi (Dark) Theme for RPCS3
by Ani @ https://github.com/AniLeo
r1 (2017.08.15)
*/
/*
Color Scheme
(Darker to Lighter)
Black
> 292929
> 323232
> 333333
> 3d3d3d
> 404040
> 444444
Light Grey
> 828790
> bdc3c7
> ecf0f1
> b1b1b1
> 7f8c8d
Green
> 2ecc71
Red
> e74c3c
*/
/* Every widget */
QWidget {
background-color: #323232;
color: #bdc3c7;
alternate-background-color: #3d3d3d;
}
/* Mouse tooltips */
QToolTip {
border: 1px solid #323232;
background-color: #323232;
color: #ecf0f1;
}
/* Table headers */
QHeaderView::section {
background-color: #323232;
color: #ecf0f1;
padding-left: 4px;
border: 1px solid #323232;
}
/* Settings Dialog: Tabs */
QTabBar::tab {
color: #ecf0f1;
border: 1px solid #444;
border-bottom-style: none;
background-color: #333333;
padding-left: 16px;
padding-right: 16px;
padding-top: 4px;
padding-bottom: 4px;
margin-right: -2px;
}
QTabBar::tab:last {
margin-right: 0px;
}
QTabBar::tab:!selected {
color: #b1b1b1;
border-bottom-style: solid;
margin-top: 3px;
background-color: #292929;
}
QTabBar::tab:hover {
background-color: #333333;
color: #ecf0f1;
}
/* Checkboxes */
QCheckBox::indicator {
border-radius: 2px;
border: 1px solid #ecf0f1;
width: 10px;
height: 10px;
margin-top: 1px;
}
QCheckBox::indicator:checked {
background-color: #2ecc71; /* Green */
}
QCheckBox::indicator:unchecked {
background-color: #e74c3c; /* Red */
}
QCheckBox::indicator::disabled {
background-color: #7f8c8d; /* Gray */
}
/* Radio Buttons */
QRadioButton::indicator {
border-radius: 6px;
border: 1px solid #ecf0f1;
width: 10px;
height: 10px;
margin-top: 1px;
}
QRadioButton::indicator:checked {
background-color: #2ecc71; /* Green */
}
QRadioButton::indicator:unchecked {
background-color: #e74c3c; /* Red */
}
QRadioButton::indicator::disabled {
background-color: #7f8c8d; /* Gray */
}
/* Combo Boxes */
QComboBox {
background-color: #404040;
color: #fff;
border: 1px solid #1e1e1e;
border-radius: 3px;
padding-bottom: 2px;
padding-left: 4px;
}
QComboBox::disabled {
background-color: #828790;
color: #fff;
}
/* Group Boxes (Settings Dialog) */
QGroupBox {
margin-top: 17px;
font-size: 13px;
border: 1px solid #bdc3c7;
border-radius: 4px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center;
padding: 5px 10px 5px 10px;
color: #fff;
}
/* Buttons */
QPushButton {
background-color: #404040;
}
QPushButton::disabled {
background-color: #444444;
color: #828790;
}
/* Log and Debugger borders */
QTextEdit {
border: 1px solid #828790;
}
/* For dock buttons to be visible */
QDockWidget::close-button, QDockWidget::float-button {
background-color: #bdc3c7;
border: 1px solid #000;
border-radius: 4px;
}
/* Disable ugly borders */
QTabWidget::pane {
border: 0px solid #828790;
}
/* Top menu bar */
QMenuBar::item:selected {
background: #444444;
}
QMenu::item {
padding-left: 20px;
padding-right: 15px;
padding-top: 4px;
padding-bottom: 4px;
}
QMenu::item:selected {
background: #444444;
border: 1px solid #bdc3c7;
}
QMenu::item:disabled {
background-color: #444444;
color: #828790;
}
/* Libraries list */
QListWidget::item:selected {
background-color: #3d3d3d;
color: #ecf0f1;
}
QListWidget::item:hover {
background-color: #4c4b4b;
color: #ecf0f1;
}
/* Pad Settings: Controller Image */
QLabel#l_controller {
color: #bdc3c7;
}
/* Game Grid Font */
QLabel#gamegrid_font {
font-weight: 600;
font-size: 8pt;
font-family: Lucida Grande;
color: #ecf0f1;
}
/* Slider on toolbar */
QWidget#sizeSliderContainer {
background: transparent;
}
/* Debug UI Settings buttons */
QLabel#color_button {
background: transparent;
}
/* Seachbar on main toolbar */
QLineEdit#mw_searchbar {
margin-left:14px;
color: #ecf0f1;
}
/* Uniform colors in Toolbar */
QToolButton {
background: transparent;
color: transparent;
}
QToolButton::disabled {
background-color: #828790;
}
QToolButton::hover {
background-color: #444444;
}
/* Set Theme UI colors */
QLabel#gamelist_icon_background_color {
background-color: #323232;
}
QLabel#gamelist_toolbar_icon_color {
background-color: #e3e3e3;
}
+1 -1
Submodule llvm updated: a3b2103ffc...079c1f30fc
+11 -42
View File
@@ -87,10 +87,7 @@ endif()
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
# This hides our LLVM from mesa's LLVM, otherwise we get some unresolvable conflicts.
if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs,ALL")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs,ALL")
if(WIN32)
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
@@ -104,23 +101,17 @@ if(NOT MSVC)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# This fixes 'some' of the st11range issues. See issue #2516
if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-image_base,0x10000 -Wl,-pagezero_size,0x10000")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -image-base=0x10000")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -image-base=0x10000")
endif()
# Some distros have the compilers set to use PIE by default, but RPCS3 doesn't work with PIE, so we need to disable it.
if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie")
else()
CHECK_C_COMPILER_FLAG("-no-pie" HAS_NO_PIE)
CHECK_C_COMPILER_FLAG("-nopie" HAS_NOPIE)
if(HAS_NO_PIE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
elseif(HAS_NOPIE)
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)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nopie")
endif()
endif()
@@ -136,7 +127,7 @@ endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
#on some Linux distros shm_unlink and similar functions are in librt only
set(ADDITIONAL_LIBS "rt" "X11")
set(ADDITIONAL_LIBS "rt" "X11" "asound")
elseif(NOT MSVC AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
#it seems like glibc includes the iconv functions we use but other libc
#implementations like the one on OSX don't seem implement them
@@ -167,29 +158,9 @@ elseif(WIN32)
set(PLATFORM_ARCH "Windows/x86_64")
else()
set(PLATFORM_ARCH "linux/x86_64")
option(USE_ALSA "ALSA audio backend" ON)
option(USE_PULSE "PulseAudio audio backend" ON)
option(USE_LIBEVDEV "libevdev-based joystick support" ON)
endif()
if(USE_ALSA)
find_package(PkgConfig)
pkg_check_modules(ALSA alsa)
if(ALSA_FOUND)
add_definitions(-DHAVE_ALSA)
include_directories(SYSTEM ${ALSA_INCLUDE_DIRS})
list(APPEND ADDITIONAL_LIBS ${ALSA_LDFLAGS})
endif()
endif()
if(USE_PULSE)
find_package(PkgConfig)
pkg_check_modules(PULSE libpulse-simple)
if(PULSE_FOUND)
add_definitions(-DHAVE_PULSE)
include_directories(SYSTEM ${PULSE_INCLUDE_DIRS})
list(APPEND ADDITIONAL_LIBS ${PULSE_LDFLAGS})
endif()
endif()
if(USE_LIBEVDEV)
find_package(PkgConfig)
pkg_check_modules(LIBEVDEV libevdev)
@@ -350,9 +321,7 @@ if(WIN32)
target_link_libraries(rpcs3 avformat.lib avcodec.lib avutil.lib swresample.lib swscale.lib png16_static ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
else()
target_link_libraries(rpcs3 ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
if(APPLE)
target_link_libraries(rpcs3 hidapi-mac "-framework CoreFoundation" "-framework IOKit")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(rpcs3 hidapi-hidraw udev vulkan)
else()
target_link_libraries(rpcs3 hidapi-libusb usb)
+8 -8
View File
@@ -150,8 +150,8 @@ s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER *edat, NPD_HEADER *np
const int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
const int metadata_offset = 0x100;
std::unique_ptr<u8[]> enc_data;
std::unique_ptr<u8[]> dec_data;
std::unique_ptr<u8> enc_data;
std::unique_ptr<u8> dec_data;
u8 hash[0x10] = { 0 };
u8 key_result[0x10] = { 0 };
u8 hash_result[0x14] = { 0 };
@@ -315,7 +315,7 @@ int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD
{
const int total_blocks = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
u64 size_left = (int)edat->file_size;
std::unique_ptr<u8[]> data(new u8[edat->block_size]);
std::unique_ptr<u8> data(new u8[edat->block_size]);
for (int i = 0; i < total_blocks; i++)
{
@@ -427,8 +427,8 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
long bytes_read = 0;
long bytes_to_read = metadata_size;
std::unique_ptr<u8[]> metadata(new u8[metadata_size]);
std::unique_ptr<u8[]> empty_metadata(new u8[metadata_size]);
std::unique_ptr<u8> metadata(new u8[metadata_size]);
std::unique_ptr<u8> empty_metadata(new u8[metadata_size]);
while (bytes_to_read > 0)
{
@@ -487,7 +487,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
if ((edat->flags & EDAT_FLAG_0x20) != 0) //Sony failed again, they used buffer from 0x100 with half size of real metadata.
{
int metadata_buf_size = block_num * 0x10;
std::unique_ptr<u8[]> metadata_buf(new u8[metadata_buf_size]);
std::unique_ptr<u8> metadata_buf(new u8[metadata_buf_size]);
f->seek(file_offset + metadata_offset);
f->read(metadata_buf.get(), metadata_buf_size);
sha1(metadata_buf.get(), metadata_buf_size, signature_hash);
@@ -516,7 +516,7 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs:
{
// Setup header signature hash.
memset(signature_hash, 0, 20);
std::unique_ptr<u8[]> header_buf(new u8[0xD8]);
std::unique_ptr<u8> header_buf(new u8[0xD8]);
f->seek(file_offset);
f->read(header_buf.get(), 0xD8);
sha1(header_buf.get(), 0xD8, signature_hash );
@@ -577,7 +577,7 @@ int validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *
int dev_hash_result = 0;
const int file_name_length = (int) strlen(file_name);
std::unique_ptr<u8[]> buf(new u8[0x30 + file_name_length]);
std::unique_ptr<u8> buf(new u8[0x30 + file_name_length]);
// Build the title buffer (content_id + file_name).
memcpy(buf.get(), npd->content_id, 0x30);
+11 -90
View File
@@ -3,77 +3,19 @@
#include "aes.h"
#include "sha1.h"
#include "key_vault.h"
#include "Utilities/StrFmt.h"
#include "unpkg.h"
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync, const std::string& pkg_filepath)
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync)
{
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
std::vector<fs::file> filelist;
u32 cur_file=0;
fs::file original_file(pkg_filepath);
original_file.seek(pkg_f.pos());
filelist.push_back(std::move(original_file));
// Save current file offset (probably zero)
const u64 start_offset = pkg_f.pos();
u64 cur_offset = start_offset;
u64 cur_file_offset = start_offset;
// Get basic PKG information
PKGHeader header;
auto archive_seek = [&](const s64 new_offset, const fs::seek_mode damode = fs::seek_set)
{
if(damode == fs::seek_set) cur_offset = new_offset;
else if (damode == fs::seek_cur) cur_offset += new_offset;
u64 _offset = 0;
for (u32 i = 0; i < filelist.size(); i++)
{
if (cur_offset < (_offset + filelist[i].size()))
{
cur_file = i;
cur_file_offset = cur_offset - _offset;
filelist[i].seek(cur_file_offset);
break;
}
_offset += filelist[i].size();
}
};
auto archive_read = [&](const void *data_ptr, const u64 num_bytes)
{
u64 num_bytes_left = filelist[cur_file].size() - cur_file_offset;
//check if it continues in another file
if (num_bytes > num_bytes_left)
{
filelist[cur_file].read((u8 *)data_ptr, num_bytes_left);
if ((cur_file + 1) < filelist.size()) cur_file++;
else
{
cur_offset += num_bytes_left;
cur_file_offset = filelist[cur_file].size();
return num_bytes_left;
}
u64 num_read = filelist[cur_file].read((u8 *)data_ptr + num_bytes_left, num_bytes - num_bytes_left);
cur_offset += (num_read + num_bytes_left);
cur_file_offset = num_read;
return (num_read+num_bytes_left);
}
u64 num_read = filelist[cur_file].read((u8 *)data_ptr, num_bytes);
cur_offset += num_read;
cur_file_offset += num_read;
return num_read;
};
if (archive_read(&header, sizeof(header)) != sizeof(header))
if (!pkg_f.read(header))
{
LOG_ERROR(LOADER, "PKG file is too short!");
return false;
@@ -109,29 +51,8 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
if (header.pkg_size > pkg_f.size())
{
//Check if multi-files pkg
if (pkg_filepath.length() < 7 || pkg_filepath.substr(pkg_filepath.length() - 7).compare("_00.pkg") != 0)
{
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
return false;
}
std::string name_wo_number = pkg_filepath.substr(0, pkg_filepath.length() - 7);
u64 cursize = pkg_f.size();
while (cursize != header.pkg_size)
{
std::string archive_filename = fmt::format("%s_%2d.pkg", name_wo_number, filelist.size());
fs::file archive_file(archive_filename);
if (!archive_file)
{
LOG_ERROR(LOADER, "Missing part of the multi-files pkg: %s", archive_filename);
return false;
}
cursize += archive_file.size();
filelist.push_back(std::move(archive_file));
}
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
return false;
}
if (header.data_size + header.data_offset > header.pkg_size)
@@ -143,7 +64,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
be_t<u32> drm_type{0};
be_t<u32> content_type{0};
archive_seek(header.pkg_info_off);
pkg_f.seek(header.pkg_info_off);
for (u32 i = 0; i < header.pkg_info_num; i++)
{
@@ -153,7 +74,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
be_t<u32> size;
} packet;
archive_read(&packet, sizeof(packet));
pkg_f.read(packet);
// TODO
switch (+packet.id)
@@ -162,7 +83,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
{
if (packet.size == sizeof(drm_type))
{
archive_read(&drm_type, sizeof(drm_type));
pkg_f.read(drm_type);
continue;
}
@@ -172,7 +93,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
{
if (packet.size == sizeof(content_type))
{
archive_read(&content_type, sizeof(content_type));
pkg_f.read(content_type);
continue;
}
@@ -180,7 +101,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
}
}
archive_seek(packet.size, fs::seek_cur);
pkg_f.seek(packet.size, fs::seek_cur);
}
// Allocate buffer with BUF_SIZE size or more if required
@@ -189,10 +110,10 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
// Define decryption subfunction (`psp` arg selects the key for specific block)
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
{
archive_seek(start_offset + header.data_offset + offset);
pkg_f.seek(start_offset + header.data_offset + offset);
// Read the data and set available size
const u64 read = archive_read(buf.get(), size);
const u64 read = pkg_f.read(buf.get(), size);
// Get block count
const u64 blocks = (read + 15) / 16;
+1 -1
View File
@@ -57,4 +57,4 @@ struct PKGEntry
be_t<u32> pad; // Padding (zeros)
};
bool pkg_install(const class fs::file& pkg_f, const std::string& dir, atomic_t<double>&, const std::string& pkg_filepath);
bool pkg_install(const class fs::file& pkg_f, const std::string& dir, atomic_t<double>&);
+2 -2
View File
@@ -118,7 +118,7 @@ void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
{
std::unique_ptr<u8[]> out(new u8[key_len]);
std::unique_ptr<u8> out(new u8[key_len]);
sha1_hmac(key, key_len, in, in_len, out.get());
@@ -132,7 +132,7 @@ void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
{
std::unique_ptr<u8[]> out(new u8[key_len]);
std::unique_ptr<u8> out(new u8[key_len]);
aes_context ctx;
aes_setkey_enc(&ctx, key, 128);
+1 -1
View File
@@ -4,7 +4,7 @@
#include "ALSAThread.h"
#ifdef HAVE_ALSA
#ifdef __linux__
#include <alsa/asoundlib.h>
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#ifdef HAVE_ALSA
#ifdef __linux__
#include "Emu/Audio/AudioThread.h"
-60
View File
@@ -1,60 +0,0 @@
#include "Emu/System.h"
#include "PulseThread.h"
#ifdef HAVE_PULSE
#include <pulse/simple.h>
#include <pulse/error.h>
PulseThread::PulseThread()
{
}
PulseThread::~PulseThread()
{
this->Close();
}
void PulseThread::Play()
{
}
void PulseThread::Close()
{
if(this->connection) {
pa_simple_free(this->connection);
this->connection = nullptr;
}
}
void PulseThread::Stop()
{
}
void PulseThread::Open(const void* src, int size)
{
pa_sample_spec ss;
ss.format = g_cfg.audio.convert_to_u16 ? PA_SAMPLE_S16LE : PA_SAMPLE_FLOAT32LE;
ss.channels = g_cfg.audio.downmix_to_2ch ? 2 : 8;
ss.rate = 48000;
int err;
this->connection = pa_simple_new(NULL, "RPCS3", PA_STREAM_PLAYBACK, NULL, "Game", &ss, NULL, NULL, &err);
if(!this->connection) {
fprintf(stderr, "PulseAudio: Failed to initialize audio: %s\n", pa_strerror(err));
}
this->AddData(src, size);
}
void PulseThread::AddData(const void* src, int size)
{
if(this->connection) {
int err;
if(pa_simple_write(this->connection, src, size, &err) < 0) {
fprintf(stderr, "PulseAudio: Failed to write audio stream: %s\n", pa_strerror(err));
}
}
}
#endif
-23
View File
@@ -1,23 +0,0 @@
#pragma once
#ifdef HAVE_PULSE
#include <pulse/simple.h>
#include "Emu/Audio/AudioThread.h"
class PulseThread : public AudioThread
{
public:
PulseThread();
virtual ~PulseThread() override;
virtual void Play() override;
virtual void Open(const void* src, int size) override;
virtual void Close() override;
virtual void Stop() override;
virtual void AddData(const void* src, int size) override;
private:
pa_simple *connection = nullptr;
};
#endif
-8
View File
@@ -195,12 +195,6 @@ s32 cellAtracGetInternalErrorInfo(vm::ptr<CellAtracHandle> pHandle, vm::ptr<s32>
return CELL_OK;
}
s32 cellAtracGetSamplingRate()
{
UNIMPLEMENTED_FUNC(cellAtrac);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellAtrac)("cellAtrac", []()
{
REG_FUNC(cellAtrac, cellAtracSetDataAndGetMemSize);
@@ -233,6 +227,4 @@ DECLARE(ppu_module_manager::cellAtrac)("cellAtrac", []()
REG_FUNC(cellAtrac, cellAtracResetPlayPosition);
REG_FUNC(cellAtrac, cellAtracGetInternalErrorInfo);
REG_FUNC(cellAtrac, cellAtracGetSamplingRate);
});
@@ -203,12 +203,6 @@ s32 cellAtracMultiGetInternalErrorInfo(vm::ptr<CellAtracMultiHandle> pHandle, vm
return CELL_OK;
}
s32 cellAtracMultiGetSamplingRate()
{
UNIMPLEMENTED_FUNC(cellAtracMulti);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellAtracMulti)("cellAtracMulti", []()
{
REG_FUNC(cellAtracMulti, cellAtracMultiSetDataAndGetMemSize);
@@ -242,6 +236,4 @@ DECLARE(ppu_module_manager::cellAtracMulti)("cellAtracMulti", []()
REG_FUNC(cellAtracMulti, cellAtracMultiResetPlayPosition);
REG_FUNC(cellAtracMulti, cellAtracMultiGetInternalErrorInfo);
REG_FUNC(cellAtracMulti, cellAtracMultiGetSamplingRate);
});
+35 -42
View File
@@ -11,39 +11,39 @@ logs::channel cellAvconfExt("cellAvconfExt");
vm::gvar<f32> g_gamma; // TODO
s32 cellAudioOutUnregisterDevice(u32 deviceNumber)
s32 cellAudioOutUnregisterDevice()
{
cellAvconfExt.todo("cellAudioOutUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioOutGetDeviceInfo2(u32 deviceNumber, u32 deviceIndex, vm::ptr<CellAudioOutDeviceInfo2> info)
s32 cellAudioOutGetDeviceInfo2()
{
cellAvconfExt.todo("cellAudioOutGetDeviceInfo2(deviceNumber=0x%x, deviceIndex=0x%x, info=*0x%x)", deviceNumber, deviceIndex, info);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutSetXVColor()
{
UNIMPLEMENTED_FUNC(cellAvconfExt);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutSetupDisplay()
{
UNIMPLEMENTED_FUNC(cellAvconfExt);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioInGetDeviceInfo(u32 deviceNumber, u32 deviceIndex, vm::ptr<CellAudioInDeviceInfo> info)
s32 cellAudioInGetDeviceInfo()
{
cellAvconfExt.todo("cellAudioInGetDeviceInfo(deviceNumber=0x%x, deviceIndex=0x%x, info=*0x%x)", deviceNumber, deviceIndex, info);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutConvertCursorColor(u32 videoOut, s32 displaybuffer_format, f32 gamma, s32 source_buffer_format, vm::ptr<void> src_addr, vm::ptr<u32> dest_addr, s32 num)
s32 cellVideoOutConvertCursorColor()
{
cellAvconfExt.todo("cellVideoOutConvertCursorColor(videoOut=%d, displaybuffer_format=0x%x, gamma=0x%x, source_buffer_format=0x%x, src_addr=*0x%x, dest_addr=*0x%x, num=0x%x)", videoOut, displaybuffer_format, gamma, source_buffer_format, src_addr, dest_addr, num);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
@@ -61,16 +61,16 @@ s32 cellVideoOutGetGamma(u32 videoOut, vm::ptr<f32> gamma)
return CELL_OK;
}
s32 cellAudioInGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioInDeviceInfo> info)
s32 cellAudioInGetAvailableDeviceInfo()
{
cellAvconfExt.todo("cellAudioInGetAvailableDeviceInfo(count=0x%x, info=*0x%x)", count, info);
return 0; // number of available devices
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioOutGetAvailableDeviceInfo(u32 count, vm::ptr<CellAudioOutDeviceInfo2> info)
s32 cellAudioOutGetAvailableDeviceInfo()
{
cellAvconfExt.todo("cellAudioOutGetAvailableDeviceInfo(count=0x%x, info=*0x%x)", count, info);
return 0; // number of available devices
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutSetGamma(u32 videoOut, f32 gamma)
@@ -92,37 +92,37 @@ s32 cellVideoOutSetGamma(u32 videoOut, f32 gamma)
return CELL_OK;
}
s32 cellAudioOutRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::ptr<CellAudioOutRegistrationOption> option, vm::ptr<CellAudioOutDeviceConfiguration> config)
s32 cellAudioOutRegisterDevice()
{
cellAvconfExt.todo("cellAudioOutRegisterDevice(deviceType=0x%llx, name=%s, option=*0x%x, config=*0x%x)", deviceType, name, option, config);
return 0; // device number
}
s32 cellAudioOutSetDeviceMode(u32 deviceMode)
{
cellAvconfExt.todo("cellAudioOutSetDeviceMode(deviceMode=0x%x)", deviceMode);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioInSetDeviceMode(u32 deviceMode)
s32 cellAudioOutSetDeviceMode()
{
cellAvconfExt.todo("cellAudioInSetDeviceMode(deviceMode=0x%x)", deviceMode);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioInRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::ptr<CellAudioInRegistrationOption> option, vm::ptr<CellAudioInDeviceConfiguration> config)
s32 cellAudioInSetDeviceMode()
{
cellAvconfExt.todo("cellAudioInRegisterDevice(deviceType=0x%llx, name=%s, option=*0x%x, config=*0x%x)", deviceType, name, option, config);
return 0; // device number
}
s32 cellAudioInUnregisterDevice(u32 deviceNumber)
{
cellAvconfExt.todo("cellAudioInUnregisterDevice(deviceNumber=0x%x)", deviceNumber);
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
s32 cellAudioInRegisterDevice()
{
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellAudioInUnregisterDevice()
{
UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK;
}
s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
{
cellAvconfExt.warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize=*0x%x)", videoOut, screenSize);
@@ -143,12 +143,6 @@ s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<f32> screenSize)
return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET;
}
s32 cellVideoOutSetCopyControl(u32 videoOut, u32 control)
{
cellAvconfExt.todo("cellVideoOutSetCopyControl(videoOut=%d, control=0x%x)", videoOut, control);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
{
@@ -174,5 +168,4 @@ DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
REG_FUNC(cellSysutilAvconfExt, cellAudioInRegisterDevice);
REG_FUNC(cellSysutilAvconfExt, cellAudioInUnregisterDevice);
REG_FUNC(cellSysutilAvconfExt, cellVideoOutGetScreenSize);
REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetCopyControl);
});
+2 -2
View File
@@ -262,7 +262,7 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
return CELL_GAME_ERROR_BUSY;
}
}
else if (category == "AP" || category == "AV" || category == "HG" || category == "AT" || category == "AM" || category == "SF")
else if (category == "AP" || category == "AV" || category == "HG")
{
*type = CELL_GAME_GAMETYPE_HDD;
*attributes = 0; // TODO
@@ -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, false))
if (fs::rename(prm->temp, vdir))
{
cellGame.success("cellGameContentPermit(): directory '%s' has been created", dir);
}
+1 -1
View File
@@ -484,7 +484,7 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
m_config->gcm_buffers[id].width = width;
m_config->gcm_buffers[id].height = height;
if (id + 1u > render->display_buffers_count)
if (id + 1 > render->display_buffers_count)
{
render->display_buffers_count = id + 1;
}
-7
View File
@@ -65,12 +65,6 @@ s32 cellHttpSetProxy()
return CELL_OK;
}
s32 cellHttpGetCookie()
{
UNIMPLEMENTED_FUNC(cellHttp);
return CELL_OK;
}
s32 cellHttpGetProxy()
{
UNIMPLEMENTED_FUNC(cellHttp);
@@ -707,7 +701,6 @@ DECLARE(ppu_module_manager::cellHttp)("cellHttp", []()
REG_FUNC(cellHttp, cellHttpsInit);
REG_FUNC(cellHttp, cellHttpsEnd);
REG_FUNC(cellHttp, cellHttpSetProxy);
REG_FUNC(cellHttp, cellHttpGetCookie);
REG_FUNC(cellHttp, cellHttpGetProxy);
REG_FUNC(cellHttp, cellHttpInitCookie);
+3 -3
View File
@@ -161,7 +161,7 @@ bool _L10nCodeParse(s32 code, HostCode& retCode)
#ifdef _MSC_VER
// Use code page to transform std::string to std::wstring.
s32 _OEM2Wide(HostCode oem_code, const std::string& src, std::wstring& dst)
s32 _OEM2Wide(HostCode oem_code, const std::string src, std::wstring& dst)
{
//Such length returned should include the '\0' character.
s32 length = MultiByteToWideChar(oem_code, 0, src.c_str(), -1, NULL, 0);
@@ -178,7 +178,7 @@ s32 _OEM2Wide(HostCode oem_code, const std::string& src, std::wstring& dst)
}
// Use Code page to transform std::wstring to std::string.
s32 _Wide2OEM(HostCode oem_code, const std::wstring& src, std::string& dst)
s32 _Wide2OEM(HostCode oem_code, const std::wstring src, std::string& dst)
{
//Such length returned should include the '\0' character.
s32 length = WideCharToMultiByte(oem_code, 0, src.c_str(), -1, NULL, 0, NULL, NULL);
@@ -195,7 +195,7 @@ s32 _Wide2OEM(HostCode oem_code, const std::wstring& src, std::string& dst)
}
// Convert Codepage to Codepage (all char*)
std::string _OemToOem(HostCode src_code, HostCode dst_code, const std::string& str)
std::string _OemToOem(HostCode src_code, HostCode dst_code, const std::string str)
{
std::wstring wide; std::string result;
_OEM2Wide(src_code, str, wide);
+1 -1
View File
@@ -83,7 +83,7 @@ public:
virtual ~MsgDialogBase();
virtual void Create(const std::string& msg) = 0;
virtual void CreateOsk(const std::string& msg, char16_t* osk_text, u32 charlimit) = 0;
virtual void CreateOsk(const std::string& msg, char16_t* osk_text) = 0;
virtual void ProgressBarSetMsg(u32 progressBarIndex, const std::string& msg) = 0;
virtual void ProgressBarReset(u32 progressBarIndex) = 0;
virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0;
-57
View File
@@ -202,54 +202,6 @@ error_code cellNetCtlGetNatInfo(vm::ptr<CellNetCtlNatInfo> natInfo)
return CELL_OK;
}
error_code cellNetCtlAddHandlerGameInt()
{
cellNetCtl.todo("cellNetCtlAddHandlerGameInt()");
return CELL_OK;
}
error_code cellNetCtlConnectGameInt()
{
cellNetCtl.todo("cellNetCtlConnectGameInt()");
return CELL_OK;
}
error_code cellNetCtlDelHandlerGameInt()
{
cellNetCtl.todo("cellNetCtlDelHandlerGameInt()");
return CELL_OK;
}
error_code cellNetCtlDisconnectGameInt()
{
cellNetCtl.todo("cellNetCtlDisconnectGameInt()");
return CELL_OK;
}
error_code cellNetCtlGetInfoGameInt()
{
cellNetCtl.todo("cellNetCtlGetInfoGameInt()");
return CELL_OK;
}
error_code cellNetCtlGetScanInfoGameInt()
{
cellNetCtl.todo("cellNetCtlGetScanInfoGameInt()");
return CELL_OK;
}
error_code cellNetCtlGetStateGameInt()
{
cellNetCtl.todo("cellNetCtlGetStateGameInt()");
return CELL_OK;
}
error_code cellNetCtlScanGameInt()
{
cellNetCtl.todo("cellNetCtlScanGameInt()");
return CELL_OK;
}
error_code cellGameUpdateInit()
{
cellNetCtl.todo("cellGameUpdateInit()");
@@ -322,15 +274,6 @@ DECLARE(ppu_module_manager::cellNetCtl)("cellNetCtl", []()
REG_FUNC(cellNetCtl, cellNetCtlGetNatInfo);
REG_FUNC(cellNetCtl, cellNetCtlAddHandlerGameInt);
REG_FUNC(cellNetCtl, cellNetCtlConnectGameInt);
REG_FUNC(cellNetCtl, cellNetCtlDelHandlerGameInt);
REG_FUNC(cellNetCtl, cellNetCtlDisconnectGameInt);
REG_FUNC(cellNetCtl, cellNetCtlGetInfoGameInt);
REG_FUNC(cellNetCtl, cellNetCtlGetScanInfoGameInt);
REG_FUNC(cellNetCtl, cellNetCtlGetStateGameInt);
REG_FUNC(cellNetCtl, cellNetCtlScanGameInt);
REG_FUNC(cellNetCtl, cellGameUpdateInit);
REG_FUNC(cellNetCtl, cellGameUpdateTerm);
+2 -9
View File
@@ -14,21 +14,14 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
{
cellOskDialog.warning("cellOskDialogLoadAsync(container=0x%x, dialogParam=*0x%x, inputFieldInfo=*0x%x)", container, dialogParam, inputFieldInfo);
u32 maxLength = (inputFieldInfo->limit_length >= 512) ? 511 : (u32)inputFieldInfo->limit_length;
std::memset(s_osk_text, 0, sizeof(s_osk_text));
if (inputFieldInfo->init_text.addr() != 0)
for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++)
s_osk_text[i] = inputFieldInfo->init_text[i];
const auto osk = Emu.GetCallbacks().get_msg_dialog();
bool result = false;
osk->on_close = [&](s32 status)
{
if (status != CELL_MSGDIALOG_BUTTON_OK) sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
sysutil_send_system_cmd(status == CELL_MSGDIALOG_BUTTON_OK ? CELL_SYSUTIL_OSKDIALOG_FINISHED : CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
result = true;
};
@@ -39,7 +32,7 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
Emu.CallAfter([&]()
{
osk->CreateOsk("On Screen Keyboard", s_osk_text, maxLength);
osk->CreateOsk("On Screen Keyboard", s_osk_text);
});
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0);
+1 -1
View File
@@ -248,7 +248,7 @@ s32 cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
}
data->button[0] = 0x0; // always 0
// bits 15-8 reserved, 7-4 = 0x7, 3-0: data->len/2;
data->button[1] = (0x7 << 4) | std::min(data->len / 2, 15);
data->button[1] = (0x7 << 4) | std::min(data->len / 2, 15) & 0xF;
//lets still send new data anyway, not sure whats expected still
data->button[CELL_PAD_BTN_OFFSET_DIGITAL1] = pad.m_digital_1;
data->button[CELL_PAD_BTN_OFFSET_DIGITAL2] = pad.m_digital_2;
-7
View File
@@ -118,12 +118,6 @@ s32 cellSearchGetContentInfoDeveloperData()
return CELL_OK;
}
s32 cellSearchGetContentInfoSharable()
{
UNIMPLEMENTED_FUNC(cellSearch);
return CELL_OK;
}
s32 cellSearchCancel()
{
UNIMPLEMENTED_FUNC(cellSearch);
@@ -156,7 +150,6 @@ DECLARE(ppu_module_manager::cellSearch)("cellSearchUtility", []()
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoPathMovieThumb);
REG_FUNC(cellSearchUtility, cellSearchPrepareFile);
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoDeveloperData);
REG_FUNC(cellSearchUtility, cellSearchGetContentInfoSharable);
REG_FUNC(cellSearchUtility, cellSearchCancel);
REG_FUNC(cellSearchUtility, cellSearchEnd);
});
+1 -1
View File
@@ -17,7 +17,7 @@
logs::channel cellSpurs("cellSpurs");
error_code sys_spu_image_close(vm::ptr<sys_spu_image> img);
s32 sys_spu_image_close(vm::ptr<sys_spu_image> img);
// TODO
struct cell_error_t
+1 -37
View File
@@ -585,36 +585,6 @@ s32 _ZN8cxmlutil7GetFileERKN4cxml7ElementEPKcPNS0_4FileE()
return CELL_OK;
}
s32 _ZN16sysutil_cxmlutil11FixedMemory3EndEi()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN16sysutil_cxmlutil11FixedMemory5BeginEi()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN16sysutil_cxmlutil11FixedMemory8AllocateEN4cxml14AllocationTypeEPvS3_jPS3_Pj()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN16sysutil_cxmlutil12PacketWriter5WriteEPKvjPv()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 _ZN16sysutil_cxmlutil12PacketWriterC1EiiRN4cxml8DocumentE()
{
UNIMPLEMENTED_FUNC(cellSysutil);
return CELL_OK;
}
s32 cellSysutil_E1EC7B6A(vm::ptr<u32> unk)
{
cellSysutil.todo("cellSysutil_E1EC7B6A(unk=*0x%x)", unk);
@@ -705,12 +675,6 @@ DECLARE(ppu_module_manager::cellSysutil)("cellSysutil", []()
REG_FUNC(cellSysutil, _ZN8cxmlutil16CheckElementNameERKN4cxml7ElementEPKc);
REG_FUNC(cellSysutil, _ZN8cxmlutil16FindChildElementERKN4cxml7ElementEPKcS5_S5_);
REG_FUNC(cellSysutil, _ZN8cxmlutil7GetFileERKN4cxml7ElementEPKcPNS0_4FileE);
REG_FUNC(cellSysutil, _ZN16sysutil_cxmlutil11FixedMemory3EndEi);
REG_FUNC(cellSysutil, _ZN16sysutil_cxmlutil11FixedMemory5BeginEi);
REG_FUNC(cellSysutil, _ZN16sysutil_cxmlutil11FixedMemory8AllocateEN4cxml14AllocationTypeEPvS3_jPS3_Pj);
REG_FUNC(cellSysutil, _ZN16sysutil_cxmlutil12PacketWriter5WriteEPKvjPv);
REG_FUNC(cellSysutil, _ZN16sysutil_cxmlutil12PacketWriterC1EiiRN4cxml8DocumentE);
REG_FNID(cellSysutil, 0xE1EC7B6A, cellSysutil_E1EC7B6A);
});
+101 -181
View File
@@ -7,181 +7,129 @@
logs::channel cellSysutilAvc2("cellSysutilAvc2");
template<>
void fmt_class_string<CellSysutilAvc2Error>::format(std::string& out, u64 arg)
s32 cellSysutilAvc2GetPlayerInfo()
{
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(CELL_AVC2_ERROR_UNKNOWN);
STR_CASE(CELL_AVC2_ERROR_NOT_SUPPORTED);
STR_CASE(CELL_AVC2_ERROR_NOT_INITIALIZED);
STR_CASE(CELL_AVC2_ERROR_ALREADY_INITIALIZED);
STR_CASE(CELL_AVC2_ERROR_INVALID_ARGUMENT);
STR_CASE(CELL_AVC2_ERROR_OUT_OF_MEMORY);
STR_CASE(CELL_AVC2_ERROR_ERROR_BAD_ID);
STR_CASE(CELL_AVC2_ERROR_INVALID_STATUS);
STR_CASE(CELL_AVC2_ERROR_TIMEOUT);
STR_CASE(CELL_AVC2_ERROR_NO_SESSION);
STR_CASE(CELL_AVC2_ERROR_WINDOW_ALREADY_EXISTS);
STR_CASE(CELL_AVC2_ERROR_TOO_MANY_WINDOWS);
STR_CASE(CELL_AVC2_ERROR_TOO_MANY_PEER_WINDOWS);
STR_CASE(CELL_AVC2_ERROR_WINDOW_NOT_FOUND);
}
return unknown;
});
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetPlayerInfo(vm::cptr<SceNpMatching2RoomMemberId> player_id, vm::ptr<CellSysutilAvc2PlayerInfo> player_info)
s32 cellSysutilAvc2JoinChat()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetPlayerInfo(player_id=*0x%x, player_info=*0x%x)", player_id, player_info);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2JoinChat(vm::cptr<SceNpMatching2RoomId> room_id)
s32 cellSysutilAvc2StopStreaming()
{
cellSysutilAvc2.todo("cellSysutilAvc2JoinChat(room_id=*0x%x)", room_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2StopStreaming()
s32 cellSysutilAvc2ChangeVideoResolution()
{
cellSysutilAvc2.todo("cellSysutilAvc2StopStreaming()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2ChangeVideoResolution(CellSysutilAvc2VideoResolution resolution)
s32 cellSysutilAvc2ShowScreen()
{
cellSysutilAvc2.todo("cellSysutilAvc2ChangeVideoResolution(resolution=0x%x)", resolution);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2ShowScreen()
s32 cellSysutilAvc2GetVideoMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2ShowScreen()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetVideoMuting(vm::ptr<u8> muting)
s32 cellSysutilAvc2GetWindowAttribute()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetVideoMuting(muting=*0x%x)", muting);
*muting = 1;
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetWindowAttribute(SceNpMatching2RoomMemberId member_id, vm::ptr<CellSysutilAvc2WindowAttribute> attr)
s32 cellSysutilAvc2StopStreaming2()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetWindowAttribute(member_id=0x%x, attr=*0x%x)", member_id, attr);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2StopStreaming2(CellSysutilAvc2MediaType mediaType)
s32 cellSysutilAvc2SetVoiceMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2StopStreaming2(mediaType=0x%x)", mediaType);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetVoiceMuting(u8 muting)
{
cellSysutilAvc2.todo("cellSysutilAvc2SetVoiceMuting(muting=0x%x)", muting);
return CELL_OK;
}
error_code cellSysutilAvc2StartVoiceDetection()
s32 cellSysutilAvc2StartVoiceDetection()
{
cellSysutilAvc2.todo("cellSysutilAvc2StartVoiceDetection()");
return CELL_OK;
}
error_code cellSysutilAvc2UnloadAsync()
s32 cellSysutilAvc2UnloadAsync()
{
cellSysutilAvc2.todo("cellSysutilAvc2UnloadAsync()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2StopVoiceDetection()
s32 cellSysutilAvc2StopVoiceDetection()
{
cellSysutilAvc2.todo("cellSysutilAvc2StopVoiceDetection()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetAttribute(vm::ptr<CellSysutilAvc2Attribute> attr)
s32 cellSysutilAvc2GetAttribute()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetAttribute(attr=*0x%x)", attr);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2LoadAsync(SceNpMatching2ContextId ctx_id, u32 container, vm::ptr<CellSysutilAvc2Callback> callback_func, vm::ptr<void> user_data, vm::cptr<CellSysutilAvc2InitParam> init_param)
s32 cellSysutilAvc2LoadAsync()
{
cellSysutilAvc2.todo("cellSysutilAvc2LoadAsync(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);
}
error_code cellSysutilAvc2SetSpeakerVolumeLevel(f32 level)
s32 cellSysutilAvc2SetSpeakerVolumeLevel()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetSpeakerVolumeLevel(level=0x%x)", level);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetWindowString(SceNpMatching2RoomMemberId member_id, vm::cptr<char> string)
s32 cellSysutilAvc2SetWindowString()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetWindowString(member_id=0x%x, string=%s)", member_id, string);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2EstimateMemoryContainerSize(vm::cptr<CellSysutilAvc2InitParam> initparam, vm::ptr<u32> size)
s32 cellSysutilAvc2EstimateMemoryContainerSize(vm::cptr<CellSysutilAvc2InitParam> initparam, vm::ptr<u32> size)
{
cellSysutilAvc2.todo("cellSysutilAvc2EstimateMemoryContainerSize(initparam=*0x%x, size=*0x%x)", initparam, size);
return CELL_OK;
}
error_code cellSysutilAvc2SetVideoMuting(u8 muting)
s32 cellSysutilAvc2SetVideoMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetVideoMuting(muting=0x%x)", muting);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetPlayerVoiceMuting(SceNpMatching2RoomMemberId member_id, u8 muting)
s32 cellSysutilAvc2SetPlayerVoiceMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetPlayerVoiceMuting(member_id=0x%x, muting=0x%x)", member_id, muting);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetStreamingTarget()
s32 cellSysutilAvc2SetStreamingTarget()
{
UNIMPLEMENTED_FUNC(cellSysutilAvc2);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2Unload()
s32 cellSysutilAvc2Unload()
{
cellSysutilAvc2.todo("cellSysutilAvc2Unload()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2DestroyWindow(SceNpMatching2RoomMemberId member_id)
s32 cellSysutilAvc2DestroyWindow()
{
cellSysutilAvc2.todo("cellSysutilAvc2DestroyWindow(member_id=0x%x)", member_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetWindowPosition(SceNpMatching2RoomMemberId member_id, f32 x, f32 y, f32 z)
s32 cellSysutilAvc2SetWindowPosition()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetWindowPosition(member_id=0x%x, x=0x%x, y=0x%x, z=0x%x)", member_id, x, y, z);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetSpeakerVolumeLevel(vm::ptr<f32> level)
s32 cellSysutilAvc2GetSpeakerVolumeLevel()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetSpeakerVolumeLevel(level=*0x%x)", level);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2IsCameraAttached(vm::ptr<u8> status)
s32 cellSysutilAvc2IsCameraAttached(vm::ptr<u8> status)
{
cellSysutilAvc2.todo("cellSysutilAvc2IsCameraAttached(status=*0x%x)", status);
@@ -190,43 +138,37 @@ error_code cellSysutilAvc2IsCameraAttached(vm::ptr<u8> status)
return CELL_OK;
}
error_code cellSysutilAvc2MicRead(vm::ptr<void> ptr, vm::ptr<u32> pSize)
s32 cellSysutilAvc2MicRead()
{
cellSysutilAvc2.todo("cellSysutilAvc2MicRead(ptr=*0x%x, pSize=*0x%x)", ptr, pSize);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetPlayerVoiceMuting(SceNpMatching2RoomMemberId member_id, vm::ptr<u8> muting)
s32 cellSysutilAvc2GetPlayerVoiceMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetPlayerVoiceMuting(member_id=0x%x, muting=*0x%x)", member_id, muting);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2JoinChatRequest(vm::cptr<SceNpMatching2RoomId> room_id)
s32 cellSysutilAvc2JoinChatRequest()
{
cellSysutilAvc2.todo("cellSysutilAvc2JoinChatRequest(room_id=*0x%x)", room_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2StartStreaming()
s32 cellSysutilAvc2StartStreaming()
{
cellSysutilAvc2.todo("cellSysutilAvc2StartStreaming()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetWindowAttribute(SceNpMatching2RoomMemberId member_id, vm::cptr<CellSysutilAvc2WindowAttribute> attr)
s32 cellSysutilAvc2SetWindowAttribute()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetWindowAttribute(member_id=0x%x, attr=*0x%x)", member_id, attr);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetWindowShowStatus(SceNpMatching2RoomMemberId member_id, vm::ptr<u8> visible)
s32 cellSysutilAvc2GetWindowShowStatus()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetWindowShowStatus(member_id=0x%x, visible=*0x%x)", member_id, visible);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2InitParam(u16 version, vm::ptr<CellSysutilAvc2InitParam> option)
s32 cellSysutilAvc2InitParam(u16 version, vm::ptr<CellSysutilAvc2InitParam> option)
{
cellSysutilAvc2.warning("cellSysutilAvc2InitParam(version=%d, option=*0x%x)", version, option);
@@ -273,118 +215,99 @@ error_code cellSysutilAvc2InitParam(u16 version, vm::ptr<CellSysutilAvc2InitPara
return CELL_OK;
}
error_code cellSysutilAvc2GetWindowSize(SceNpMatching2RoomMemberId member_id, vm::ptr<f32> width, vm::ptr<f32> height)
s32 cellSysutilAvc2GetWindowSize()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetWindowSize(member_id=0x%x, width=*0x%x, height=*0x%x)", member_id, width, height);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetStreamPriority(u8 priority)
s32 cellSysutilAvc2SetStreamPriority()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetStreamPriority(priority=0x%x)", priority);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2LeaveChatRequest()
s32 cellSysutilAvc2LeaveChatRequest()
{
cellSysutilAvc2.todo("cellSysutilAvc2LeaveChatRequest()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2IsMicAttached(vm::ptr<u8> status)
s32 cellSysutilAvc2IsMicAttached()
{
cellSysutilAvc2.todo("cellSysutilAvc2IsMicAttached(status=*0x%x)", status);
*status = CELL_AVC2_MIC_STATUS_DETACHED;
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2CreateWindow(SceNpMatching2RoomMemberId member_id)
s32 cellSysutilAvc2CreateWindow()
{
cellSysutilAvc2.todo("cellSysutilAvc2CreateWindow(member_id=0x%x)", member_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetSpeakerMuting(vm::ptr<u8> muting)
s32 cellSysutilAvc2GetSpeakerMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetSpeakerMuting(muting=*0x%x)", muting);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2ShowWindow(SceNpMatching2RoomMemberId member_id)
s32 cellSysutilAvc2ShowWindow()
{
cellSysutilAvc2.todo("cellSysutilAvc2ShowWindow(member_id=0x%x)", member_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetWindowSize(SceNpMatching2RoomMemberId member_id, f32 width, f32 height)
s32 cellSysutilAvc2SetWindowSize()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetWindowSize(member_id=0x%x, width=0x%x, height=0x%x)", member_id, width, height);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2EnumPlayers(vm::ptr<s32> players_num, vm::ptr<SceNpMatching2RoomMemberId> players_id)
s32 cellSysutilAvc2EnumPlayers()
{
cellSysutilAvc2.todo("cellSysutilAvc2EnumPlayers(players_num=*0x%x, players_id=*0x%x)", players_num, players_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetWindowString(SceNpMatching2RoomMemberId member_id, vm::ptr<char> string, vm::ptr<u8> len)
s32 cellSysutilAvc2GetWindowString()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetWindowString(member_id=0x%x, string=*0x%x, len=*0x%x)", member_id, string, len);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2LeaveChat()
s32 cellSysutilAvc2LeaveChat()
{
cellSysutilAvc2.todo("cellSysutilAvc2LeaveChat()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2SetSpeakerMuting(u8 muting)
s32 cellSysutilAvc2SetSpeakerMuting()
{
cellSysutilAvc2.todo("cellSysutilAvc2SetSpeakerMuting(muting=0x%x)", muting);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2Load(SceNpMatching2ContextId ctx_id, u32 container, vm::ptr<CellSysutilAvc2Callback> callback_func, vm::ptr<void> user_data, vm::cptr<CellSysutilAvc2InitParam> init_param)
s32 cellSysutilAvc2Load(SceNpMatching2ContextId ctx_id, u32 container, vm::ptr<CellSysutilAvc2Callback> callback_func, vm::ptr<void> user_data, vm::cptr<CellSysutilAvc2InitParam> init_param)
{
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;
}
error_code cellSysutilAvc2SetAttribute(vm::cptr<CellSysutilAvc2Attribute> attr)
s32 cellSysutilAvc2SetAttribute(vm::cptr<CellSysutilAvc2Attribute> attr)
{
cellSysutilAvc2.todo("cellSysutilAvc2SetAttribute(attr=*0x%x)", attr);
return CELL_OK;
}
error_code cellSysutilAvc2UnloadAsync2(CellSysutilAvc2MediaType mediaType)
s32 cellSysutilAvc2UnloadAsync2()
{
cellSysutilAvc2.todo("cellSysutilAvc2UnloadAsync2(mediaType=0x%x)", mediaType);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2StartStreaming2(CellSysutilAvc2MediaType mediaType)
s32 cellSysutilAvc2StartStreaming2()
{
cellSysutilAvc2.todo("cellSysutilAvc2StartStreaming2(mediaType=0x%x)", mediaType);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2HideScreen()
s32 cellSysutilAvc2HideScreen()
{
cellSysutilAvc2.todo("cellSysutilAvc2HideScreen()");
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2HideWindow(SceNpMatching2RoomMemberId member_id)
s32 cellSysutilAvc2HideWindow()
{
cellSysutilAvc2.todo("cellSysutilAvc2HideWindow(member_id=0x%x)", member_id);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetVoiceMuting(vm::ptr<u8> muting)
s32 cellSysutilAvc2GetVoiceMuting(vm::ptr<u8> muting)
{
cellSysutilAvc2.todo("cellSysutilAvc2GetVoiceMuting(muting=*0x%x)", muting);
@@ -393,22 +316,19 @@ error_code cellSysutilAvc2GetVoiceMuting(vm::ptr<u8> muting)
return CELL_OK;
}
error_code cellSysutilAvc2GetScreenShowStatus(vm::ptr<u8> visible)
s32 cellSysutilAvc2GetScreenShowStatus()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetScreenShowStatus(visible=*0x%x)", visible);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2Unload2(CellSysutilAvc2MediaType mediaType)
s32 cellSysutilAvc2Unload2()
{
cellSysutilAvc2.todo("cellSysutilAvc2Unload2(mediaType=0x%x)", mediaType);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
error_code cellSysutilAvc2GetWindowPosition(SceNpMatching2RoomMemberId member_id, vm::ptr<f32> x, vm::ptr<f32> y, vm::ptr<f32> z)
s32 cellSysutilAvc2GetWindowPosition()
{
cellSysutilAvc2.todo("cellSysutilAvc2GetWindowPosition(member_id=0x%x, x=*0x%x, y=*0x%x, z=*0x%x)", member_id, x, y, z);
return CELL_OK;
fmt::throw_exception("Unimplemented" HERE);
}
+8 -25
View File
@@ -3,7 +3,7 @@
namespace vm { using namespace ps3; }
// Error codes
enum CellSysutilAvc2Error : u32
enum
{
CELL_AVC2_ERROR_UNKNOWN = 0x8002b701,
CELL_AVC2_ERROR_NOT_SUPPORTED = 0x8002b702,
@@ -113,14 +113,6 @@ enum
CELL_AVC2_CAMERA_STATUS_UNKNOWN = 3,
};
enum
{
CELL_AVC2_MIC_STATUS_DETACHED = 0,
CELL_AVC2_MIC_STATUS_ATTACHED_OFF = 1,
CELL_AVC2_MIC_STATUS_ATTACHED_ON = 2,
CELL_AVC2_MIC_STATUS_UNKNOWN = 3,
};
typedef u32 CellSysutilAvc2AttributeId;
typedef u32 CellSysutilAvc2WindowAttributeId;
@@ -151,7 +143,7 @@ struct CellSysutilAvc2VideoInitParam
be_t<u16> max_video_windows;
be_t<u16> max_video_framerate;
be_t<u32> max_video_bitrate;
be_t<CellSysutilAvc2CoordinatesForm> coordinates_form;
CellSysutilAvc2CoordinatesForm coordinates_form;
u8 video_stream_sharing;
};
@@ -174,15 +166,15 @@ struct CellSysutilAvc2InitParam
struct CellSysutilAvc2RoomMemberList
{
vm::bptr<SceNpMatching2RoomMemberId> member_id;
vm::ptr<SceNpMatching2RoomMemberId> member_id;
u8 member_num;
};
struct CellSysutilAvc2MemberIpAndPortList
{
vm::bptr<SceNpMatching2RoomMemberId> member_id;
vm::bptr<u32> dst_addr; // in_addr
vm::bptr<u16> dst_port; // in_port_t
vm::ptr<SceNpMatching2RoomMemberId> member_id;
vm::ptr<u32> dst_addr; // in_addr
vm::ptr<u16> dst_port;
be_t<SceNpMatching2RoomMemberId> my_member_id;
u8 member_num;
};
@@ -191,7 +183,7 @@ union CellSysutilAvc2AttributeParam
{
be_t<u64> int_param;
be_t<f32> float_param;
vm::bptr<void> ptr_param;
vm::ptr<void> ptr_param;
};
struct CellSysutilAvc2Attribute
@@ -204,7 +196,7 @@ union CellSysutilAvc2WindowAttributeParam
{
be_t<s32> int_vector[4];
be_t<f32> float_vector[4];
vm::bptr<void> ptr_vector[4];
vm::ptr<void> ptr_vector[4];
};
struct CellSysutilAvc2WindowAttribute
@@ -212,12 +204,3 @@ struct CellSysutilAvc2WindowAttribute
be_t<CellSysutilAvc2WindowAttributeId> attr_id;
CellSysutilAvc2WindowAttributeParam attr_param;
};
struct CellSysutilAvc2PlayerInfo
{
be_t<SceNpMatching2RoomMemberId> member_id;
u8 joined;
u8 connected;
u8 mic_attached;
u8 reserved[11];
};
-23
View File
@@ -43,12 +43,6 @@ s32 cellUsbdRegisterLdd()
return CELL_OK;
}
s32 cellUsbdRegisterCompositeLdd()
{
UNIMPLEMENTED_FUNC(cellUsbd);
return CELL_OK;
}
s32 cellUsbdRegisterExtraLdd()
{
UNIMPLEMENTED_FUNC(cellUsbd);
@@ -67,12 +61,6 @@ s32 cellUsbdUnregisterLdd()
return CELL_OK;
}
s32 cellUsbdUnregisterCompositeLdd()
{
UNIMPLEMENTED_FUNC(cellUsbd);
return CELL_OK;
}
s32 cellUsbdUnregisterExtraLdd()
{
UNIMPLEMENTED_FUNC(cellUsbd);
@@ -163,13 +151,6 @@ s32 cellUsbdFreeMemory()
return CELL_OK;
}
s32 cellUsbdResetDevice()
{
UNIMPLEMENTED_FUNC(cellUsbd);
return CELL_OK;
}
DECLARE(ppu_module_manager::cellUsbd)("cellUsbd", []()
{
REG_FUNC(cellUsbd, cellUsbdInit);
@@ -180,11 +161,9 @@ DECLARE(ppu_module_manager::cellUsbd)("cellUsbd", []()
REG_FUNC(cellUsbd, cellUsbdGetThreadPriority);
REG_FUNC(cellUsbd, cellUsbdRegisterLdd);
REG_FUNC(cellUsbd, cellUsbdRegisterCompositeLdd);
REG_FUNC(cellUsbd, cellUsbdRegisterExtraLdd);
REG_FUNC(cellUsbd, cellUsbdRegisterExtraLdd2);
REG_FUNC(cellUsbd, cellUsbdUnregisterLdd);
REG_FUNC(cellUsbd, cellUsbdUnregisterCompositeLdd);
REG_FUNC(cellUsbd, cellUsbdUnregisterExtraLdd);
REG_FUNC(cellUsbd, cellUsbdOpenPipe);
@@ -205,6 +184,4 @@ DECLARE(ppu_module_manager::cellUsbd)("cellUsbd", []()
REG_FUNC(cellUsbd, cellUsbdAllocateMemory);
REG_FUNC(cellUsbd, cellUsbdFreeMemory);
REG_FUNC(cellUsbd, cellUsbdResetDevice);
});
+16 -14
View File
@@ -128,24 +128,26 @@ error_code cellVideoOutGetResolution(u32 resolutionId, vm::ptr<CellVideoOutResol
error_code cellVideoOutConfigure(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option, u32 waitForEvent)
{
cellSysutil.todo("cellVideoOutConfigure(videoOut=%d, config=*0x%x, option=*0x%x, waitForEvent=%d)", videoOut, config, option, waitForEvent);
cellSysutil.warning("cellVideoOutConfigure(videoOut=%d, config=*0x%x, option=*0x%x, waitForEvent=%d)", videoOut, config, option, waitForEvent);
if (!config)
switch (videoOut)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_PARAMETER;
case CELL_VIDEO_OUT_PRIMARY:
if (config->resolutionId != g_video_out_resolution_id.at(g_cfg.video.resolution)
|| (config->format != CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8 &&
config->format != CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8B8G8R8 &&
config->format != CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT)
|| (config->aspect != CELL_VIDEO_OUT_ASPECT_AUTO && config->aspect != g_video_out_aspect_id.at(g_cfg.video.aspect_ratio)))
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
return CELL_OK;
case CELL_VIDEO_OUT_SECONDARY:
return CELL_OK;
}
if (!config->pitch)
{
return CELL_VIDEO_OUT_ERROR_PARAMETER_OUT_OF_RANGE;
}
if (config->resolutionId == 0x92 || config->resolutionId == 0xa1)
{
return CELL_VIDEO_OUT_ERROR_ILLEGAL_CONFIGURATION;
}
return CELL_OK;
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
}
error_code cellVideoOutGetConfiguration(u32 videoOut, vm::ptr<CellVideoOutConfiguration> config, vm::ptr<CellVideoOutOption> option)
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -976,7 +976,7 @@ s32 sceNpManagerGetOnlineId(vm::ptr<SceNpOnlineId> onlineId)
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
@@ -998,7 +998,7 @@ s32 sceNpManagerGetNpId(ppu_thread& ppu, vm::ptr<SceNpId> npId)
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
@@ -1086,7 +1086,7 @@ s32 sceNpManagerGetAccountRegion(vm::ptr<SceNpCountryCode> countryCode, vm::ptr<
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
@@ -1108,7 +1108,7 @@ s32 sceNpManagerGetAccountAge(vm::ptr<s32> age)
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
@@ -1130,7 +1130,7 @@ s32 sceNpManagerGetContentRatingFlag(vm::ptr<s32> isRestricted, vm::ptr<s32> age
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
@@ -1156,7 +1156,7 @@ s32 sceNpManagerGetChatRestrictionFlag(vm::ptr<s32> isRestricted)
return SCE_NP_ERROR_OFFLINE;
}
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN && g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
if (g_psn_connection_status != SCE_NP_MANAGER_STATUS_LOGGING_IN || g_psn_connection_status != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_ERROR_INVALID_STATE;
}
-15
View File
@@ -368,19 +368,6 @@ s32 sceNpTssGetDataAsync()
return CELL_OK;
}
s32 sceNpTssGetDataNoLimit()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
s32 sceNpTssGetDataNoLimitAsync()
{
UNIMPLEMENTED_FUNC(sceNpTus);
return CELL_OK;
}
DECLARE(ppu_module_manager::sceNpTus)("sceNpTus", []()
{
REG_FUNC(sceNpTus, sceNpTusInit);
@@ -443,6 +430,4 @@ DECLARE(ppu_module_manager::sceNpTus)("sceNpTus", []()
REG_FUNC(sceNpTus, sceNpTusDeleteMultiSlotDataVUserAsync);
REG_FUNC(sceNpTus, sceNpTssGetData);
REG_FUNC(sceNpTus, sceNpTssGetDataAsync);
REG_FUNC(sceNpTus, sceNpTssGetDataNoLimit);
REG_FUNC(sceNpTus, sceNpTssGetDataNoLimitAsync);
});
+1 -1
View File
@@ -31,7 +31,7 @@ struct ps3_fmt_src
void skip(std::size_t extra)
{
g_count += (u32)extra + 1;
++g_count += (u32)extra;
}
std::size_t fmt_string(std::string& out, std::size_t extra) const
-7
View File
@@ -1211,12 +1211,6 @@ namespace sys_net
return CELL_OK;
}
s32 _sce_net_add_name_server()
{
UNIMPLEMENTED_FUNC(libnet);
return CELL_OK;
}
s32 _sce_net_add_name_server_with_char()
{
UNIMPLEMENTED_FUNC(libnet);
@@ -1348,7 +1342,6 @@ DECLARE(ppu_module_manager::libnet)("sys_net", []()
REG_FUNC_(sys_netset_if_up);
REG_FUNC_(sys_netset_open);
REG_FUNC_(_sce_net_add_name_server);
REG_FUNC_(_sce_net_add_name_server_with_char);
REG_FUNC_(_sce_net_flush_route);
+22 -342
View File
@@ -5,7 +5,6 @@
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/Cell/lv2/sys_spu.h"
#include "Crypto/unself.h"
#include "Loader/ELF.h"
#include "sysPrxForUser.h"
extern logs::channel sysPrxForUser;
@@ -17,365 +16,46 @@ spu_printf_cb_t g_spu_printf_dgcb;
spu_printf_cb_t g_spu_printf_atcb;
spu_printf_cb_t g_spu_printf_dtcb;
struct spu_elf_ldr
s32 sys_spu_elf_get_information(u32 elf_img, vm::ptr<u32> entry, vm::ptr<s32> nseg)
{
be_t<u32> _vtable;
vm::bptr<void> src;
be_t<u32> x8;
be_t<u64> ehdr_off;
be_t<u64> phdr_off;
s32 get_ehdr(vm::ptr<elf_ehdr<elf_be, u64>> out)
{
if (!src)
{
return -1;
}
if (_vtable == vm::cast(u32{1}))
{
vm::ptr<elf_ehdr<elf_be, u32>> ehdr = vm::cast(src.addr() + ehdr_off);
std::memcpy(out.get_ptr(), ehdr.get_ptr(), 0x10); // Not needed?
out->e_type = ehdr->e_type;
out->e_machine = ehdr->e_machine;
out->e_version = ehdr->e_version;
out->e_entry = ehdr->e_entry;
out->e_phoff = ehdr->e_phoff;
out->e_shoff = ehdr->e_shoff;
out->e_flags = ehdr->e_flags;
out->e_ehsize = ehdr->e_ehsize;
out->e_phentsize = ehdr->e_phentsize;
out->e_phnum = ehdr->e_phnum;
out->e_shentsize = ehdr->e_shentsize;
out->e_shnum = ehdr->e_shnum;
out->e_shstrndx = ehdr->e_shstrndx;
}
else
{
vm::ptr<elf_ehdr<elf_be, u64>> ehdr = vm::cast(src.addr() + ehdr_off);
*out = *ehdr;
}
return 0;
}
s32 get_phdr(vm::ptr<elf_phdr<elf_be, u64>> out, u32 count)
{
if (!src)
{
return -1;
}
if (_vtable == vm::cast(u32{1}))
{
vm::ptr<elf_ehdr<elf_be, u32>> ehdr = vm::cast(src.addr() + ehdr_off);
vm::ptr<elf_phdr<elf_be, u32>> phdr = vm::cast(src.addr() + (phdr_off ? +phdr_off : +ehdr->e_phoff));
for (; count; count--, phdr++, out++)
{
out->p_type = phdr->p_type;
out->p_flags = phdr->p_flags;
out->p_offset = phdr->p_offset;
out->p_vaddr = phdr->p_vaddr;
out->p_paddr = phdr->p_paddr;
out->p_filesz = phdr->p_filesz;
out->p_memsz = phdr->p_memsz;
out->p_align = phdr->p_align;
}
}
else
{
vm::ptr<elf_ehdr<elf_be, u64>> ehdr = vm::cast(src.addr() + ehdr_off);
vm::ptr<elf_phdr<elf_be, u64>> phdr = vm::cast(src.addr() + (phdr_off ? +phdr_off : +ehdr->e_phoff));
std::memcpy(out.get_ptr(), phdr.get_ptr(), sizeof(*out) * count);
}
return 0;
}
};
struct spu_elf_info
{
u8 e_class;
vm::bptr<spu_elf_ldr> ldr;
struct sce_hdr
{
be_t<u32> se_magic;
be_t<u32> se_hver;
be_t<u16> se_flags;
be_t<u16> se_type;
be_t<u32> se_meta;
be_t<u64> se_hsize;
be_t<u64> se_esize;
} sce0;
struct self_hdr
{
be_t<u64> se_htype;
be_t<u64> se_appinfooff;
be_t<u64> se_elfoff;
be_t<u64> se_phdroff;
be_t<u64> se_shdroff;
be_t<u64> se_secinfoff;
be_t<u64> se_sceveroff;
be_t<u64> se_controloff;
be_t<u64> se_controlsize;
be_t<u64> pad;
} self;
// Doesn't exist there
spu_elf_ldr _overlay;
error_code init(vm::ptr<void> src, s32 arg2 = 0)
{
if (!src)
{
return CELL_EINVAL;
}
u32 ehdr_off = 0;
u32 phdr_off = 0;
// Check SCE header if found
std::memcpy(&sce0, src.get_ptr(), sizeof(sce0));
if (sce0.se_magic == 0x53434500 /* SCE\0 */)
{
if (sce0.se_hver != 2 || sce0.se_type != 1 || sce0.se_meta == 0)
{
return CELL_ENOEXEC;
}
std::memcpy(&self, src.get_ptr(), sizeof(self));
ehdr_off = static_cast<u32>(+self.se_elfoff);
phdr_off = static_cast<u32>(+self.se_phdroff);
if (self.se_htype != 3 || !ehdr_off || !phdr_off)
{
return CELL_ENOEXEC;
}
}
// Check ELF header
vm::ptr<elf_ehdr<elf_be, u32>> ehdr = vm::cast(src.addr() + ehdr_off);
if (ehdr->e_magic != "\177ELF"_u32 || ehdr->e_data != 2 /* BE */)
{
return CELL_ENOEXEC;
}
if (ehdr->e_class != 1 && ehdr->e_class != 2)
{
return CELL_ENOEXEC;
}
e_class = ehdr->e_class;
ldr = vm::get_addr(&_overlay);
ldr->_vtable = vm::cast(u32{e_class}); // TODO
ldr->src = vm::static_ptr_cast<u8>(src);
ldr->x8 = arg2;
ldr->ehdr_off = ehdr_off;
ldr->phdr_off = phdr_off;
return CELL_OK;
}
};
error_code sys_spu_elf_get_information(u32 elf_img, vm::ptr<u32> entry, vm::ptr<s32> nseg)
{
sysPrxForUser.warning("sys_spu_elf_get_information(elf_img=0x%x, entry=*0x%x, nseg=*0x%x)", elf_img, entry, nseg);
// Initialize ELF loader
vm::var<spu_elf_info> info(spu_elf_info{});
if (auto res = info->init(vm::cast(elf_img)))
{
return res;
}
// Reject SCE header
if (info->sce0.se_magic == 0x53434500)
{
return CELL_ENOEXEC;
}
// Load ELF header
vm::var<elf_ehdr<elf_be, u64>> ehdr(elf_ehdr<elf_be, u64>{});
if (info->ldr->get_ehdr(ehdr) || ehdr->e_machine != elf_machine::spu || !ehdr->e_phnum)
{
return CELL_ENOEXEC;
}
// Load program headers
vm::var<elf_phdr<elf_be, u64>[]> phdr(ehdr->e_phnum);
if (info->ldr->get_phdr(phdr, ehdr->e_phnum))
{
return CELL_ENOEXEC;
}
const s32 num_segs = sys_spu_image::get_nsegs<false>(phdr);
if (num_segs < 0)
{
return CELL_ENOEXEC;
}
*entry = static_cast<u32>(ehdr->e_entry);
*nseg = num_segs;
sysPrxForUser.todo("sys_spu_elf_get_information(elf_img=0x%x, entry=*0x%x, nseg=*0x%x)", elf_img, entry, nseg);
return CELL_OK;
}
error_code sys_spu_elf_get_segments(u32 elf_img, vm::ptr<sys_spu_segment> segments, s32 nseg)
s32 sys_spu_elf_get_segments(u32 elf_img, vm::ptr<sys_spu_segment> segments, s32 nseg)
{
sysPrxForUser.warning("sys_spu_elf_get_segments(elf_img=0x%x, segments=*0x%x, nseg=0x%x)", elf_img, segments, nseg);
// Initialize ELF loader
vm::var<spu_elf_info> info(spu_elf_info{});
if (auto res = info->init(vm::cast(elf_img)))
{
return res;
}
// Load ELF header
vm::var<elf_ehdr<elf_be, u64>> ehdr(elf_ehdr<elf_be, u64>{});
if (info->ldr->get_ehdr(ehdr) || ehdr->e_machine != elf_machine::spu || !ehdr->e_phnum)
{
return CELL_ENOEXEC;
}
// Load program headers
vm::var<elf_phdr<elf_be, u64>[]> phdr(ehdr->e_phnum);
if (info->ldr->get_phdr(phdr, ehdr->e_phnum))
{
return CELL_ENOEXEC;
}
const s32 num_segs = sys_spu_image::fill<false>(segments, nseg, phdr, elf_img);
if (num_segs == -2)
{
return CELL_ENOMEM;
}
else if (num_segs < 0)
{
return CELL_ENOEXEC;
}
sysPrxForUser.todo("sys_spu_elf_get_segments(elf_img=0x%x, segments=*0x%x, nseg=0x%x)", elf_img, segments, nseg);
return CELL_OK;
}
error_code sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 type)
s32 sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 type)
{
sysPrxForUser.warning("sys_spu_image_import(img=*0x%x, src=0x%x, type=%d)", img, src, type);
if (type != SYS_SPU_IMAGE_PROTECT && type != SYS_SPU_IMAGE_DIRECT)
{
return CELL_EINVAL;
}
// Load from memory (TODO)
img->load(fs::file{vm::base(src), 0 - src});
// Initialize ELF loader
vm::var<spu_elf_info> info(spu_elf_info{});
if (auto res = info->init(vm::cast(src)))
{
return res;
}
// Reject SCE header
if (info->sce0.se_magic == 0x53434500)
{
return CELL_ENOEXEC;
}
// Load ELF header
vm::var<elf_ehdr<elf_be, u64>> ehdr(elf_ehdr<elf_be, u64>{});
if (info->ldr->get_ehdr(ehdr) || ehdr->e_machine != elf_machine::spu || !ehdr->e_phnum)
{
return CELL_ENOEXEC;
}
// Load program headers
vm::var<elf_phdr<elf_be, u64>[]> phdr(ehdr->e_phnum);
if (info->ldr->get_phdr(phdr, ehdr->e_phnum))
{
return CELL_ENOEXEC;
}
if (type == SYS_SPU_IMAGE_PROTECT)
{
u32 img_size = 0;
for (const auto& p : phdr)
{
if (p.p_type != 1 && p.p_type != 4)
{
return CELL_ENOEXEC;
}
img_size = std::max<u32>(img_size, static_cast<u32>(p.p_offset + p.p_filesz));
}
return _sys_spu_image_import(img, src, img_size, 0);
}
else
{
s32 num_segs = sys_spu_image::get_nsegs(phdr);
if (num_segs < 0)
{
return CELL_ENOEXEC;
}
img->nsegs = num_segs;
img->entry_point = static_cast<u32>(ehdr->e_entry);
vm::ptr<sys_spu_segment> segs = vm::cast(vm::alloc(num_segs * sizeof(sys_spu_segment), vm::main));
if (!segs)
{
return CELL_ENOMEM;
}
if (sys_spu_image::fill(segs, num_segs, phdr, src) != num_segs)
{
vm::dealloc(segs.addr());
return CELL_ENOEXEC;
}
img->type = SYS_SPU_IMAGE_TYPE_USER;
img->segs = segs;
return CELL_OK;
}
return CELL_OK;
}
error_code sys_spu_image_close(vm::ptr<sys_spu_image> img)
s32 sys_spu_image_close(vm::ptr<sys_spu_image> img)
{
sysPrxForUser.warning("sys_spu_image_close(img=*0x%x)", img);
if (img->type == SYS_SPU_IMAGE_TYPE_USER)
{
//_sys_free(img->segs.addr());
vm::dealloc_verbose_nothrow(img->segs.addr(), vm::main);
}
else if (img->type == SYS_SPU_IMAGE_TYPE_KERNEL)
{
// Call the syscall
return _sys_spu_image_close(img);
//return syscall_158(img);
}
else
{
return CELL_EINVAL;
}
img->free();
return CELL_OK;
}
@@ -383,7 +63,7 @@ s32 sys_raw_spu_load(s32 id, vm::cptr<char> path, vm::ptr<u32> entry)
{
sysPrxForUser.warning("sys_raw_spu_load(id=%d, path=%s, entry=*0x%x)", id, path, entry);
const fs::file elf_file = fs::file(vfs::get(path.get_ptr()));
const fs::file elf_file = decrypt_self(fs::file(vfs::get(path.get_ptr())));
if (!elf_file)
{
@@ -393,10 +73,10 @@ s32 sys_raw_spu_load(s32 id, vm::cptr<char> path, vm::ptr<u32> entry)
sys_spu_image img;
img.load(elf_file);
img.deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, img.segs.get_ptr(), img.nsegs);
img.deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id);
img.free();
*entry = img.entry_point;
*entry = img.entry_point | 1;
return CELL_OK;
}
@@ -406,15 +86,15 @@ s32 sys_raw_spu_image_load(ppu_thread& ppu, s32 id, vm::ptr<sys_spu_image> img)
sysPrxForUser.warning("sys_raw_spu_image_load(id=%d, img=*0x%x)", id, img);
// Load SPU segments
img->deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, img->segs.get_ptr(), img->nsegs);
img->deploy(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id);
// Use MMIO
vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, img->entry_point);
vm::write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, img->entry_point | 1);
return CELL_OK;
}
error_code _sys_spu_printf_initialize(spu_printf_cb_t agcb, spu_printf_cb_t dgcb, spu_printf_cb_t atcb, spu_printf_cb_t dtcb)
s32 _sys_spu_printf_initialize(spu_printf_cb_t agcb, spu_printf_cb_t dgcb, spu_printf_cb_t atcb, spu_printf_cb_t dtcb)
{
sysPrxForUser.warning("_sys_spu_printf_initialize(agcb=*0x%x, dgcb=*0x%x, atcb=*0x%x, dtcb=*0x%x)", agcb, dgcb, atcb, dtcb);
@@ -427,7 +107,7 @@ error_code _sys_spu_printf_initialize(spu_printf_cb_t agcb, spu_printf_cb_t dgcb
return CELL_OK;
}
error_code _sys_spu_printf_finalize()
s32 _sys_spu_printf_finalize()
{
sysPrxForUser.warning("_sys_spu_printf_finalize()");
@@ -439,7 +119,7 @@ error_code _sys_spu_printf_finalize()
return CELL_OK;
}
error_code _sys_spu_printf_attach_group(ppu_thread& ppu, u32 group)
s32 _sys_spu_printf_attach_group(ppu_thread& ppu, u32 group)
{
sysPrxForUser.warning("_sys_spu_printf_attach_group(group=0x%x)", group);
@@ -451,7 +131,7 @@ error_code _sys_spu_printf_attach_group(ppu_thread& ppu, u32 group)
return g_spu_printf_agcb(ppu, group);
}
error_code _sys_spu_printf_detach_group(ppu_thread& ppu, u32 group)
s32 _sys_spu_printf_detach_group(ppu_thread& ppu, u32 group)
{
sysPrxForUser.warning("_sys_spu_printf_detach_group(group=0x%x)", group);
@@ -463,7 +143,7 @@ error_code _sys_spu_printf_detach_group(ppu_thread& ppu, u32 group)
return g_spu_printf_dgcb(ppu, group);
}
error_code _sys_spu_printf_attach_thread(ppu_thread& ppu, u32 thread)
s32 _sys_spu_printf_attach_thread(ppu_thread& ppu, u32 thread)
{
sysPrxForUser.warning("_sys_spu_printf_attach_thread(thread=0x%x)", thread);
@@ -475,7 +155,7 @@ error_code _sys_spu_printf_attach_thread(ppu_thread& ppu, u32 thread)
return g_spu_printf_atcb(ppu, thread);
}
error_code _sys_spu_printf_detach_thread(ppu_thread& ppu, u32 thread)
s32 _sys_spu_printf_detach_thread(ppu_thread& ppu, u32 thread)
{
sysPrxForUser.warning("_sys_spu_printf_detach_thread(thread=0x%x)", thread);
+1 -1
View File
@@ -11,7 +11,7 @@ public:
}
private:
u32 DisAsmBranchTarget(const s32 imm) override
u32 DisAsmBranchTarget(const s32 imm)
{
return dump_pc + (imm & ~3);
}
+1 -1
View File
@@ -133,7 +133,7 @@ extern std::string ppu_get_syscall_name(u64 code)
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_spu_image_get_segments";
case 159: return "_sys_raw_spu_image_load";
case 160: return "sys_raw_spu_create";
case 161: return "sys_raw_spu_destroy";
case 163: return "sys_raw_spu_read_puint_mb";
+5 -19
View File
@@ -88,26 +88,12 @@ void ppu_module_manager::register_module(ppu_static_module* module)
ppu_static_function& ppu_module_manager::access_static_function(const char* module, u32 fnid)
{
auto& res = access().at(module)->functions[fnid];
if (res.name)
{
fmt::throw_exception("PPU FNID duplication in module %s (%s, 0x%x)", module, res.name, fnid);
}
return res;
return access().at(module)->functions[fnid];
}
ppu_static_variable& ppu_module_manager::access_static_variable(const char* module, u32 vnid)
{
auto& res = access().at(module)->variables[vnid];
if (res.name)
{
fmt::throw_exception("PPU VNID duplication in module %s (%s, 0x%x)", module, res.name, vnid);
}
return res;
return access().at(module)->variables[vnid];
}
const ppu_static_module* ppu_module_manager::get_module(const std::string& name)
@@ -989,7 +975,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
fmt::throw_exception("Invalid binary size (0x%llx, memsz=0x%x)", prog.bin.size(), size);
if (!vm::falloc(addr, size))
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
@@ -1305,9 +1291,9 @@ void ppu_load_exec(const ppu_exec_object& elf)
{
const std::string lle_dir = vfs::get("/dev_flash/sys/external/");
if (!fs::is_dir(lle_dir) || !fs::is_file(lle_dir + "libsysmodule.sprx"))
if (!fs::is_dir(lle_dir))
{
LOG_ERROR(GENERAL, "PS3 firmware is not installed or the installed firmware is invalid."
LOG_ERROR(GENERAL, "/dev_flash/sys/external/ directory does not exist!"
"\nYou should install the PS3 Firmware (Menu: File -> Install Firmware)."
"\nVisit https://rpcs3.net/ for Quickstart Guide and more information.");
}
+1 -1
View File
@@ -578,7 +578,7 @@ ppu_thread::~ppu_thread()
ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack)
: cpu_thread(idm::last_id())
, prio(prio)
, stack_size(stack ? ::align(std::min<u32>(stack, 0x100000), 0x1000) : 0x4000)
, stack_size(std::max<u32>(stack, 0x4000))
, stack_addr(0)
, start_time(get_system_time())
, m_name(name)
+1 -1
View File
@@ -41,7 +41,7 @@ struct TypeGen<T, std::enable_if_t<std::is_void<T>::value>>
};
template<typename T>
struct TypeGen<T, std::enable_if_t<std::is_same<T, s64>::value || std::is_same<T, u64>::value || std::is_same<T, uptr>::value>>
struct TypeGen<T, std::enable_if_t<std::is_same<T, s64>::value || std::is_same<T, u64>::value>>
{
static llvm::Type* get(llvm::LLVMContext& context) { return llvm::Type::getInt64Ty(context); }
};
+15 -27
View File
@@ -77,25 +77,6 @@ bool RawSPUThread::read_reg(const u32 addr, u32& value)
value = status;
return true;
}
case Prxy_TagStatus_offs:
{
value = mfc_proxy.size() ? 0 : +mfc_prxy_mask;
return true;
}
case SPU_NPC_offs:
{
//npc = pc | ((ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0);
value = npc;
return true;
}
case SPU_RunCntl_offs:
{
value = run_ctrl;
return true;
}
}
LOG_ERROR(SPU, "RawSPUThread[%d]: Read32(0x%x): unknown/illegal offset (0x%x)", index, addr, offset);
@@ -149,15 +130,23 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
case MFC_Class_CMD_offs:
{
g_tls_mfc[index].cmd = MFC(value & 0xff);
do_dma_transfer(g_tls_mfc[index]);
g_tls_mfc[index] = {};
g_tls_mfc[index].cmd = MFC(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL);
if (value & MFC_START_MASK)
if (mfc_proxy.try_push(g_tls_mfc[index]))
{
try_start();
}
auto mfc = fxm::check_unlocked<mfc_thread>();
if (test(mfc->state, cpu_flag::stop) && mfc->state.test_and_reset(cpu_flag::stop))
{
mfc->notify();
}
g_tls_mfc[index] = {};
g_tls_mfc[index].cmd = MFC(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL);
}
else
{
g_tls_mfc[index] = {};
g_tls_mfc[index].cmd = MFC(MFC_PPU_DMA_QUEUE_FULL);
}
return true;
}
@@ -183,7 +172,6 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
case Prxy_QueryMask_offs:
{
mfc_prxy_mask = value;
return true;
}
+1 -1
View File
@@ -166,7 +166,7 @@ void spu_recompiler::compile(spu_function_t& f)
dis_asm.dump_pc = m_pos;
dis_asm.disasm(m_pos);
compiler.comment(dis_asm.last_opcode.c_str());
log += dis_asm.last_opcode;
log += dis_asm.last_opcode.c_str();
log += '\n';
}
-1
View File
@@ -274,7 +274,6 @@ void SPUThread::cpu_init()
srr0 = 0;
ch_tag_upd = 0;
ch_tag_mask = 0;
mfc_prxy_mask = 0;
ch_tag_stat.data.store({});
ch_stall_mask = 0;
ch_stall_stat.data.store({});
-2
View File
@@ -550,8 +550,6 @@ public:
spu_channel_4_t ch_in_mbox;
atomic_t<u32> mfc_prxy_mask;
spu_channel_t ch_out_mbox;
spu_channel_t ch_out_intr_mbox;
+2 -2
View File
@@ -187,7 +187,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
BIND_FUNC(sys_event_port_disconnect), //137 (0x089)
BIND_FUNC(sys_event_port_send), //138 (0x08A)
BIND_FUNC(sys_event_flag_get), //139 (0x08B)
BIND_FUNC(sys_event_port_connect_ipc), //140 (0x08C)
null_func,//BIND_FUNC(sys_event_port_connect_ipc) //140 (0x08C)
BIND_FUNC(sys_timer_usleep), //141 (0x08D)
BIND_FUNC(sys_timer_sleep), //142 (0x08E)
null_func,//BIND_FUNC(sys_time_set_timezone) //143 (0x08F) ROOT
@@ -206,7 +206,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
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_spu_image_get_segments), //159 (0x09F)
BIND_FUNC(_sys_raw_spu_image_load), //159 (0x09F)
BIND_FUNC(sys_raw_spu_create), //160 (0x0A0)
BIND_FUNC(sys_raw_spu_destroy), //161 (0x0A1)
null_func, //162 (0x0A2) UNS
+1 -31
View File
@@ -323,7 +323,7 @@ error_code sys_event_port_create(vm::ptr<u32> eport_id, s32 port_type, u64 name)
{
sys_event.warning("sys_event_port_create(eport_id=*0x%x, port_type=%d, name=0x%llx)", eport_id, port_type, name);
if (port_type != SYS_EVENT_PORT_LOCAL && port_type != 3)
if (port_type != SYS_EVENT_PORT_LOCAL)
{
sys_event.error("sys_event_port_create(): unknown port type (%d)", port_type);
return CELL_EINVAL;
@@ -393,36 +393,6 @@ error_code sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
return CELL_OK;
}
error_code sys_event_port_connect_ipc(u32 eport_id, u64 ipc_key)
{
sys_event.warning("sys_event_port_connect_ipc(eport_id=0x%x, ipc_key=0x%x)", eport_id, ipc_key);
auto queue = lv2_event_queue::find(ipc_key);
writer_lock lock(id_manager::g_mutex);
const auto port = idm::check_unlocked<lv2_obj, lv2_event_port>(eport_id);
if (!port || !queue)
{
return CELL_ESRCH;
}
if (port->type != 3)
{
return CELL_EINVAL;
}
if (!port->queue.expired())
{
return CELL_EISCONN;
}
port->queue = std::move(queue);
return CELL_ESRCH;
}
error_code sys_event_port_disconnect(u32 eport_id)
{
sys_event.warning("sys_event_port_disconnect(eport_id=0x%x)", eport_id);
-1
View File
@@ -136,6 +136,5 @@ error_code sys_event_queue_drain(u32 event_queue_id);
error_code sys_event_port_create(vm::ps3::ptr<u32> eport_id, s32 port_type, u64 name);
error_code sys_event_port_destroy(u32 eport_id);
error_code sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
error_code sys_event_port_connect_ipc(u32 eport_id, u64 ipc_key);
error_code sys_event_port_disconnect(u32 eport_id);
error_code sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3);
+42 -40
View File
@@ -192,6 +192,7 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
if (!path[0])
{
sys_fs.error("sys_fs_open(%s) failed: path is invalid", path);
return CELL_EINVAL;
}
@@ -199,14 +200,16 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
if (local_path.empty())
{
return {CELL_ENOTMOUNTED, path};
sys_fs.error("sys_fs_open(%s) failed: device not mounted", path);
return CELL_ENOTMOUNTED;
}
// TODO: other checks for path
if (fs::is_dir(local_path))
{
return {CELL_EISDIR, path};
sys_fs.error("sys_fs_open(%s) failed: path is a directory", path);
return CELL_EISDIR;
}
bs_t<fs::open_mode> open_mode{};
@@ -274,21 +277,20 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
if (!file)
{
sys_fs.error("sys_fs_open(%s): failed to open file (flags=%#o, mode=%#o)", path, flags, mode);
if (test(open_mode & fs::excl))
{
return not_an_error(CELL_EEXIST); // approximation
return CELL_EEXIST; // approximation
}
return {CELL_ENOENT, path};
return CELL_ENOENT;
}
if ((flags & CELL_FS_O_MSELF) && (!verify_mself(*fd, file)))
{
return {CELL_ENOTMSELF, path};
}
const auto casted_arg = vm::static_ptr_cast<const u64>(arg);
return CELL_ENOTMSELF;
const auto casted_arg = vm::static_ptr_cast<const u64>(arg);//static_cast<const be_t<u32> *>(arg.get_ptr());
if (size == 8)
{
// check for sdata
@@ -303,7 +305,8 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
auto sdata_file = std::make_unique<EDATADecrypter>(std::move(file));
if (!sdata_file->ReadHeader())
{
return {CELL_EFSSPECIFIC, path};
sys_fs.error("sys_fs_open(%s): Error reading sdata header!", path);
return CELL_EFSSPECIFIC;
}
file.reset(std::move(sdata_file));
@@ -322,14 +325,14 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
auto sdata_file = std::make_unique<EDATADecrypter>(std::move(file), edatkeys->devKlic, edatkeys->rifKey);
if (!sdata_file->ReadHeader())
{
return {CELL_EFSSPECIFIC, path};
sys_fs.error("sys_fs_open(%s): Error reading edata header!", path);
return CELL_EFSSPECIFIC;
}
file.reset(std::move(sdata_file));
}
}
}
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(path.get_ptr(), std::move(file), mode, flags))
{
*fd = id;
@@ -337,7 +340,7 @@ error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode
}
// Out of file descriptors
return {CELL_EMFILE, path};
return CELL_EMFILE;
}
error_code sys_fs_read(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread)
@@ -421,21 +424,24 @@ error_code sys_fs_opendir(vm::cptr<char> path, vm::ptr<u32> fd)
if (local_path.empty())
{
return {CELL_ENOTMOUNTED, path};
sys_fs.error("sys_fs_opendir(%s) failed: device not mounted", path);
return CELL_ENOTMOUNTED;
}
// TODO: other checks for path
if (fs::is_file(local_path))
{
return {CELL_ENOTDIR, path};
sys_fs.error("sys_fs_opendir(%s) failed: path is a file", path);
return CELL_ENOTDIR;
}
fs::dir dir(local_path);
if (!dir)
{
return {CELL_ENOENT, path};
sys_fs.error("sys_fs_opendir(%s): failed to open directory", path);
return CELL_ENOENT;
}
if (const u32 id = idm::make<lv2_fs_object, lv2_dir>(path.get_ptr(), std::move(dir)))
@@ -500,14 +506,16 @@ error_code sys_fs_stat(vm::cptr<char> path, vm::ptr<CellFsStat> sb)
if (local_path.empty())
{
return {CELL_ENOTMOUNTED, path};
sys_fs.warning("sys_fs_stat(%s) failed: not mounted", path);
return CELL_ENOTMOUNTED;
}
fs::stat_t info;
if (!fs::stat(local_path, info))
{
return {CELL_ENOENT, path};
sys_fs.error("sys_fs_stat(%s) failed: not found", path);
return CELL_ENOENT;
}
sb->mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666;
@@ -564,12 +572,12 @@ error_code sys_fs_mkdir(vm::cptr<char> path, s32 mode)
if (fs::is_dir(local_path))
{
return {CELL_EEXIST, path};
return CELL_EEXIST;
}
if (!fs::create_path(local_path))
{
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
sys_fs.notice("sys_fs_mkdir(): directory %s created", path);
@@ -580,16 +588,9 @@ error_code sys_fs_rename(vm::cptr<char> from, vm::cptr<char> to)
{
sys_fs.warning("sys_fs_rename(from=%s, to=%s)", from, to);
if (!fs::rename(vfs::get(from.get_ptr()), vfs::get(to.get_ptr()), false))
if (!fs::rename(vfs::get(from.get_ptr()), vfs::get(to.get_ptr())))
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, from};
case fs::error::exist: return {CELL_EEXIST, to};
default: sys_fs.error("sys_fs_rename(): unknown error %s", error);
}
return {CELL_EIO, from}; // ???
return CELL_ENOENT; // ???
}
sys_fs.notice("sys_fs_rename(): %s renamed to %s", from, to);
@@ -604,11 +605,11 @@ error_code sys_fs_rmdir(vm::cptr<char> path)
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return CELL_ENOENT;
default: sys_fs.error("sys_fs_rmdir(): unknown error %s", error);
}
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
sys_fs.notice("sys_fs_rmdir(): directory %s removed", path);
@@ -623,11 +624,11 @@ error_code sys_fs_unlink(vm::cptr<char> path)
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return CELL_ENOENT;
default: sys_fs.error("sys_fs_unlink(): unknown error %s", error);
}
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
sys_fs.notice("sys_fs_unlink(): file %s deleted", path);
@@ -1005,7 +1006,8 @@ error_code sys_fs_lseek(u32 fd, s64 offset, s32 whence, vm::ptr<u64> pos)
if (whence >= 3)
{
return {CELL_EINVAL, whence};
sys_fs.error("sys_fs_lseek(): invalid seek whence (%d)", whence);
return CELL_EINVAL;
}
const auto file = idm::get<lv2_fs_object, lv2_file>(fd);
@@ -1106,11 +1108,11 @@ error_code sys_fs_truncate(vm::cptr<char> path, u64 size)
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return CELL_ENOENT;
default: sys_fs.error("sys_fs_truncate(): unknown error %s", error);
}
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
return CELL_OK;
@@ -1173,11 +1175,11 @@ error_code sys_fs_disk_free(vm::ps3::cptr<char> path, vm::ptr<u64> total_free, v
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return CELL_ENOENT;
default: sys_fs.error("sys_fs_disk_free(): unknown error %s", error);
}
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
*total_free = info.total_free;
@@ -1194,11 +1196,11 @@ error_code sys_fs_utime(vm::ps3::cptr<char> path, vm::ps3::cptr<CellFsUtimbuf> t
{
switch (auto error = fs::g_tls_error)
{
case fs::error::noent: return {CELL_ENOENT, path};
case fs::error::noent: return CELL_ENOENT;
default: sys_fs.error("sys_fs_utime(): unknown error %s", error);
}
return {CELL_EIO, path}; // ???
return CELL_EIO; // ???
}
return CELL_OK;
+3 -1
View File
@@ -116,7 +116,9 @@ error_code prx_load_module(std::string path, u64 flags, vm::ptr<sys_prx_load_mod
return not_an_error(idm::last_id());
}
const ppu_prx_object obj = decrypt_self(fs::file(vfs::get(path)), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
const auto loadedkeys = fxm::get_always<LoadedNpdrmKeys_t>();
const ppu_prx_object obj = decrypt_self(fs::file(vfs::get(path)), loadedkeys->devKlic.data());
if (obj != elf_error::ok)
{
+1 -24
View File
@@ -328,30 +328,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
break;
case 0x301: // Depth-buffer (Z-cull)
{
//a4 high = region = (1 << 0) | (zFormat << 4) | (aaFormat << 8);
//a4 low = size = ((width >> 6) << 22) | ((height >> 6) << 6);
//a5 high = start = cullStart&(~0xFFF);
//a5 low = offset = offset;
//a6 high = status0 = (zcullDir << 1) | (zcullFormat << 2) | ((sFunc & 0xF) << 12) | (sRef << 16) | (sMask << 24);
//a6 low = status1 = (0x2000 << 0) | (0x20 << 16);
auto &zcull = render->zculls[a3];
zcull.zFormat = ((a4 >> 32) >> 4) & 0xF;
zcull.aaFormat = ((a4 >> 32) >> 8) & 0xF;
zcull.width = ((a4 & 0xFFFFFFFF) >> 22) << 6;
zcull.height = (((a4 & 0xFFFFFFFF) >> 6) & 0xFF) << 6;
zcull.cullStart = (a5 >> 32);
zcull.offset = (a5 & 0xFFFFFFFF);
zcull.zcullDir = ((a6 >> 32) >> 1) & 0x1;
zcull.zcullFormat = ((a6 >> 32) >> 2) & 0x3FF;
zcull.sFunc = ((a6 >> 32) >> 12) & 0xF;
zcull.sRef = ((a6 >> 32) >> 16) & 0xFF;
zcull.sMask = ((a6 >> 32) >> 24) & 0xFF;
zcull.binded = (a6 & 0xFFFFFFFF) != 0;
}
break;
break;
case 0x302: // something with zcull
break;
case 0x600: // Framebuffer setup
+56 -56
View File
@@ -3,7 +3,6 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Crypto/unself.h"
#include "Crypto/unedat.h"
#include "Crypto/sha1.h"
#include "Loader/ELF.h"
#include "Utilities/bin_patch.h"
@@ -21,13 +20,20 @@ logs::channel sys_spu("sys_spu");
void sys_spu_image::load(const fs::file& stream)
{
const spu_exec_object obj{stream, 0, elf_opt::no_sections + elf_opt::no_data};
const spu_exec_object obj{stream};
if (obj != elf_error::ok)
{
fmt::throw_exception("Failed to load SPU image: %s" HERE, obj.get_error());
}
this->type = SYS_SPU_IMAGE_TYPE_KERNEL;
this->entry_point = obj.header.e_entry;
this->segs.set(vm::alloc(65 * 4096, vm::main));
this->nsegs = 0;
const u32 addr = this->segs.addr() + 4096;
for (const auto& shdr : obj.shdrs)
{
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);
@@ -37,30 +43,37 @@ void sys_spu_image::load(const fs::file& stream)
{
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 && prog.p_type != SYS_SPU_SEGMENT_TYPE_INFO)
if (prog.p_type == SYS_SPU_SEGMENT_TYPE_COPY)
{
auto& seg = segs[nsegs++];
seg.type = prog.p_type;
seg.ls = prog.p_vaddr;
seg.addr = addr + prog.p_vaddr;
seg.size = std::min(prog.p_filesz, prog.p_memsz);
std::memcpy(vm::base(seg.addr), prog.bin.data(), seg.size);
if (prog.p_memsz > prog.p_filesz)
{
auto& zero = segs[nsegs++];
zero.type = SYS_SPU_SEGMENT_TYPE_FILL;
zero.ls = prog.p_vaddr + prog.p_filesz;
zero.addr = 0;
zero.size = prog.p_memsz - seg.size;
}
}
else if (prog.p_type == SYS_SPU_SEGMENT_TYPE_INFO)
{
auto& seg = segs[nsegs++];
seg.type = SYS_SPU_SEGMENT_TYPE_INFO;
seg.ls = prog.p_vaddr;
seg.addr = 0;
seg.size = prog.p_filesz;
}
else
{
LOG_ERROR(SPU, "Unknown program type (0x%x)", prog.p_type);
}
}
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
type = SYS_SPU_IMAGE_TYPE_KERNEL;
entry_point = obj.header.e_entry;
nsegs = sys_spu_image::get_nsegs(obj.progs);
segs = vm::cast(vm::alloc(mem_size, vm::main));
const u32 src = segs.addr() + nsegs * sizeof(sys_spu_segment);
stream.seek(0);
stream.read(vm::base(src), stream.size());
if (nsegs < 0 || sys_spu_image::fill(segs, nsegs, obj.progs, src) != nsegs)
{
fmt::throw_exception("Failed to load SPU segments (%d)" HERE, nsegs);
}
vm::page_protect(segs.addr(), ::align(mem_size, 4096), 0, 0, vm::page_writable);
}
void sys_spu_image::free()
@@ -71,7 +84,7 @@ void sys_spu_image::free()
}
}
void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
void sys_spu_image::deploy(u32 loc)
{
// Segment info dump
std::string dump;
@@ -81,19 +94,19 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
sha1_starts(&sha);
u8 sha1_hash[20];
for (u32 i = 0; i < nsegs; i++)
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);
sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type));
// Hash big-endian values
sha1_update(&sha, (uchar*)&seg.type, sizeof(seg.type));
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
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.size, sizeof(seg.size));
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
sha1_update(&sha, vm::g_base_addr + seg.addr, seg.size);
}
@@ -105,15 +118,9 @@ void sys_spu_image::deploy(u32 loc, sys_spu_segment* segs, u32 nsegs)
}
std::fill_n(vm::_ptr<u32>(loc + seg.ls), seg.size / 4, seg.addr);
sha1_update(&sha, (uchar*)&seg.size, sizeof(seg.size));
sha1_update(&sha, (uchar*)&seg.ls, sizeof(seg.ls));
sha1_update(&sha, (uchar*)&seg.addr, sizeof(seg.addr));
}
else if (seg.type == SYS_SPU_SEGMENT_TYPE_INFO)
{
const be_t<u32> size = seg.size + 0x14; // Workaround
sha1_update(&sha, (uchar*)&size, sizeof(size));
}
}
sha1_finish(&sha, sha1_hash);
@@ -151,24 +158,22 @@ 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, vm::ptr<u32> entry_point, vm::ptr<s32> nsegs)
error_code _sys_spu_image_get_information(vm::ptr<sys_spu_image> img, u32 ptr1, u32 ptr2)
{
sys_spu.warning("_sys_spu_image_get_information(img=*0x%x, entry_point=*0x%x, nsegs=*0x%x)", img, entry_point, nsegs);
sys_spu.todo("_sys_spu_image_get_information(img=*0x%x, 1=*0x%x, 2=*0x%x)", img, ptr1, ptr2);
*entry_point = img->entry_point;
*nsegs = img->nsegs;
return CELL_OK;
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);
const fs::file elf_file = decrypt_self(fs::file(vfs::get(path.get_ptr())), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
const fs::file elf_file = decrypt_self(fs::file(vfs::get(path.get_ptr())));
if (!elf_file)
{
sys_spu.error("sys_spu_image_open() error: failed to open %s!", path);
sys_spu.error("sys_spu_image_open() error: %s not found!", path);
return CELL_ENOENT;
}
@@ -177,29 +182,25 @@ 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 size, u32 arg4)
error_code _sys_spu_image_import(vm::ptr<sys_spu_image> img, u32 src, u32 arg3, u32 arg4)
{
sys_spu.warning("_sys_spu_image_import(img=*0x%x, src=*0x%x, size=0x%x, arg4=0x%x)", img, src, size, arg4);
sys_spu.todo("_sys_spu_image_import(img=*0x%x, src=*0x%x, arg3=0x%x, arg4=0x%x)", img, src, arg3, arg4);
img->load(fs::file{vm::base(src), size});
return CELL_OK;
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_import");
}
error_code _sys_spu_image_close(vm::ptr<sys_spu_image> img)
{
sys_spu.warning("_sys_spu_image_close(img=*0x%x)", img);
sys_spu.todo("_sys_spu_image_close(img=*0x%x)", img);
vm::dealloc(img->segs.addr(), vm::main);
return CELL_OK;
fmt::throw_exception("Unimplemented syscall: _sys_spu_image_close");
}
error_code _sys_spu_image_get_segments(vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_segment> segments, s32 nseg)
error_code _sys_raw_spu_image_load(vm::ptr<sys_spu_image> img, u32 ptr, u32 arg3)
{
sys_spu.error("_sys_spu_image_get_segments(img=*0x%x, segments=*0x%x, nseg=%d)", img, segments, nseg);
sys_spu.todo("_sys_raw_spu_image_load(img=*0x%x, ptr=*0x%x, arg3=0x%x)", img, ptr, arg3);
// TODO: apply SPU patches
std::memcpy(segments.get_ptr(), img->segs.get_ptr(), sizeof(sys_spu_segment) * nseg);
return CELL_OK;
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)
@@ -241,8 +242,7 @@ error_code sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group_id, u32 spu_
group->threads[spu_num] = std::move(spu);
group->args[spu_num] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
group->imgs[spu_num] = std::make_pair(*img, std::vector<sys_spu_segment>());
group->imgs[spu_num].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs);
group->imgs[spu_num] = *img;
if (++group->init == group->num)
{
@@ -384,9 +384,9 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
auto& args = group->args[thread->index];
auto& img = group->imgs[thread->index];
sys_spu_image::deploy(thread->offset, img.second.data(), img.first.nsegs);
img.deploy(thread->offset);
thread->pc = img.first.entry_point;
thread->pc = img.entry_point;
thread->cpu_init();
thread->gpr[3] = v128::from64(0, args[0]);
thread->gpr[4] = v128::from64(0, args[1]);
+6 -89
View File
@@ -112,92 +112,9 @@ struct sys_spu_image
vm::ps3::bptr<sys_spu_segment> segs;
be_t<s32> nsegs;
template <bool CountInfo = true, typename Phdrs>
static s32 get_nsegs(const Phdrs& phdrs)
{
s32 num_segs = 0;
for (const auto& phdr : phdrs)
{
if (phdr.p_type != 1 && phdr.p_type != 4)
{
return -1;
}
if (phdr.p_type == 1 && phdr.p_filesz != phdr.p_memsz && phdr.p_filesz)
{
num_segs += 2;
}
else if (phdr.p_type == 1 || CountInfo)
{
num_segs += 1;
}
}
return num_segs;
}
template <bool WriteInfo = true, typename Phdrs>
static s32 fill(vm::ps3::ptr<sys_spu_segment> segs, s32 nsegs, const Phdrs& phdrs, u32 src)
{
s32 num_segs = 0;
for (const auto& phdr : phdrs)
{
if (phdr.p_type == 1)
{
if (phdr.p_filesz)
{
if (num_segs >= nsegs)
{
return -2;
}
auto* seg = &segs[num_segs++];
seg->type = SYS_SPU_SEGMENT_TYPE_COPY;
seg->ls = static_cast<u32>(phdr.p_vaddr);
seg->size = static_cast<u32>(phdr.p_filesz);
seg->addr = static_cast<u32>(phdr.p_offset + src);
}
if (phdr.p_memsz > phdr.p_filesz)
{
if (num_segs >= nsegs)
{
return -2;
}
auto* seg = &segs[num_segs++];
seg->type = SYS_SPU_SEGMENT_TYPE_FILL;
seg->ls = static_cast<u32>(phdr.p_vaddr + phdr.p_filesz);
seg->size = static_cast<u32>(phdr.p_memsz - phdr.p_filesz);
seg->addr = 0;
}
}
else if (WriteInfo && phdr.p_type == 4)
{
if (num_segs >= nsegs)
{
return -2;
}
auto* seg = &segs[num_segs++];
seg->type = SYS_SPU_SEGMENT_TYPE_INFO;
seg->size = 0x20;
seg->addr = static_cast<u32>(phdr.p_offset + 0x14 + src);
}
else if (phdr.p_type != 4)
{
return -1;
}
}
return num_segs;
}
void load(const fs::file& stream);
void free();
static void deploy(u32 loc, sys_spu_segment* segs, u32 nsegs);
void deploy(u32 loc);
};
enum : u32
@@ -236,7 +153,7 @@ struct lv2_spu_group
cond_variable cv; // used to signal waiting PPU thread
std::array<std::shared_ptr<SPUThread>, 256> threads; // SPU Threads
std::array<std::pair<sys_spu_image, std::vector<sys_spu_segment>>, 256> imgs; // SPU Images
std::array<sys_spu_image, 256> imgs; // SPU Images
std::array<std::array<u64, 4>, 256> args; // SPU Thread Arguments
std::weak_ptr<lv2_event_queue> ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events
@@ -286,11 +203,11 @@ 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, vm::ps3::ptr<u32> entry_point, vm::ps3::ptr<s32> nsegs);
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 size, u32 arg4);
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_spu_image_get_segments(vm::ps3::ptr<sys_spu_image> img, vm::ps3::ptr<sys_spu_segment> segments, s32 nseg);
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);
@@ -298,7 +215,7 @@ error_code sys_spu_thread_group_destroy(u32 id);
error_code sys_spu_thread_group_start(ppu_thread&, u32 id);
error_code sys_spu_thread_group_suspend(u32 id);
error_code sys_spu_thread_group_resume(u32 id);
error_code sys_spu_thread_group_yield(u32 id);
error_code sys_spu_thread_group_yield(u32 id);
error_code sys_spu_thread_group_terminate(u32 id, s32 value);
error_code sys_spu_thread_group_join(ppu_thread&, u32 id, vm::ps3::ptr<u32> cause, vm::ps3::ptr<u32> status);
error_code sys_spu_thread_group_set_priority(u32 id, s32 priority);
+1 -8
View File
@@ -26,9 +26,7 @@ public:
// Get object location
std::weak_ptr<T>& wptr = g_ipc.m_map[ipc_key];
std::shared_ptr<T> old;
if ((out && !(old = wptr.lock())) || wptr.expired())
if ((out && !(*out = wptr.lock())) || wptr.expired())
{
// Call a function which must return the object
if (out)
@@ -44,11 +42,6 @@ public:
return true;
}
if (out)
{
*out = std::move(old);
}
return false;
}
-2
View File
@@ -50,7 +50,6 @@ void idm::init()
{
// Allocate
g_map.resize(id_manager::typeinfo::get_count());
idm::clear();
}
void idm::clear()
@@ -76,7 +75,6 @@ void fxm::init()
{
// Allocate
g_vec.resize(id_manager::typeinfo::get_count());
fxm::clear();
}
void fxm::clear()
+4 -15
View File
@@ -6,7 +6,6 @@
#include "Utilities/VirtualMemory.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/RSX/GSRender.h"
#ifdef _WIN32
#include <Windows.h>
@@ -657,7 +656,6 @@ namespace vm
if (found != m_map.end())
{
const u32 size = found->second;
const auto rsxthr = fxm::get<GSRender>();
// Remove entry
m_map.erase(found);
@@ -665,9 +663,6 @@ namespace vm
// Unmap "real" memory pages
_page_unmap(addr, size);
// Notify rsx to invalidate range
if (rsxthr != nullptr) rsxthr->on_notify_memory_unmapped(addr, size);
// Write supplementary info if necessary
if (sup_out) *sup_out = m_sup[addr];
@@ -680,8 +675,10 @@ namespace vm
return 0;
}
u32 block_t::imp_used(const vm::writer_lock&)
u32 block_t::used()
{
reader_lock lock;
u32 result = 0;
for (auto& entry : m_map)
@@ -692,13 +689,6 @@ namespace vm
return result;
}
u32 block_t::used()
{
writer_lock lock(0);
return imp_used(lock);
}
std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags)
{
writer_lock lock(0);
@@ -744,7 +734,7 @@ namespace vm
{
if (*it && (*it)->addr == addr)
{
if (must_be_empty && (!it->unique() || (*it)->imp_used(lock)))
if (must_be_empty && (!it->unique() || (*it)->used()))
{
return *it;
}
@@ -797,7 +787,6 @@ namespace vm
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
std::make_shared<block_t>(0x30000000, 0x10000000), // main extend
};
}
}
-3
View File
@@ -156,9 +156,6 @@ namespace vm
// Unmap memory at specified location previously returned by alloc(), return size
u32 dealloc(u32 addr, u32* sup_out = nullptr);
// Internal
u32 imp_used(const vm::writer_lock&);
// Get allocated memory count
u32 used();
};
-10
View File
@@ -96,16 +96,6 @@ namespace vm
{
return m_size / SIZE_32(T);
}
auto begin() const
{
return *this + 0;
}
auto end() const
{
return *this + get_count();
}
};
// LE variable
+4 -5
View File
@@ -51,22 +51,21 @@ std::string CgBinaryDisasm::GetScaMaskDisasm()
std::string CgBinaryDisasm::GetDSTDisasm(bool isSca)
{
std::string ret;
std::string mask = GetMaskDisasm(isSca);
switch ((isSca && d3.sca_dst_tmp != 0x3f) ? 0x1f : d3.dst)
switch (isSca ? 0x1f : d3.dst)
{
case 0x1f:
ret += (isSca ? fmt::format("R%d", d3.sca_dst_tmp) : fmt::format("R%d", d0.dst_tmp)) + mask;
ret += isSca ? fmt::format("R%d", d3.sca_dst_tmp) + GetScaMaskDisasm() : fmt::format("R%d", d0.dst_tmp) + GetVecMaskDisasm();
break;
default:
if (d3.dst > 15)
LOG_ERROR(RSX, "dst index out of range: %u", d3.dst);
ret += fmt::format("o[%d]", d3.dst) + mask;
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) + mask;
ret += fmt::format(" R%d", d0.dst_tmp) + GetVecMaskDisasm();
break;
}
+15 -1
View File
@@ -610,12 +610,12 @@ bool is_primitive_native(rsx::primitive_type draw_mode)
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::quad_strip:
return true;
case rsx::primitive_type::line_loop:
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::quads:
case rsx::primitive_type::quad_strip:
return false;
}
fmt::throw_exception("Wrong primitive type" HERE);
@@ -641,6 +641,8 @@ u32 get_index_count(rsx::primitive_type draw_mode, u32 initial_index_count)
return (initial_index_count - 2) * 3;
case rsx::primitive_type::quads:
return (6 * initial_index_count) / 4;
case rsx::primitive_type::quad_strip:
return (6 * (initial_index_count - 2)) / 2;
default:
return 0;
}
@@ -689,6 +691,18 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
}
return;
case rsx::primitive_type::quad_strip:
for (unsigned i = 0; i < (count - 2) / 2; i++)
{
// First triangle
typedDst[6 * i] = 2 * i;
typedDst[6 * i + 1] = 2 * i + 1;
typedDst[6 * i + 2] = 2 * i + 2;
// Second triangle
typedDst[6 * i + 3] = 2 * i + 2;
typedDst[6 * i + 4] = 2 * i + 1;
typedDst[6 * i + 5] = 2 * i + 3;
}
return;
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_strip:
-347
View File
@@ -1,347 +0,0 @@
#pragma once
#include <sstream>
#include "ShaderParam.h"
namespace program_common
{
static void insert_compare_op(std::ostream& OS)
{
OS << "bool comparison_passes(float a, float b, uint func)\n";
OS << "{\n";
OS << " switch (func)\n";
OS << " {\n";
OS << " default:\n";
OS << " case 0: return false; //never\n";
OS << " case 1: return (a < b); //less\n";
OS << " case 2: return (a == b); //equal\n";
OS << " case 3: return (a <= b); //lequal\n";
OS << " case 4: return (a > b); //greater\n";
OS << " case 5: return (a != b); //nequal\n";
OS << " case 6: return (a >= b); //gequal\n";
OS << " case 7: return true; //always\n";
OS << " }\n";
OS << "}\n\n";
}
static void insert_fog_declaration(std::ostream& OS, const std::string wide_vector_type, const std::string input_coord, bool declare = false)
{
std::string template_body;
if (!declare)
template_body += "$T fetch_fog_value(uint mode)\n";
else
template_body += "$T fetch_fog_value(uint mode, $T $I)\n";
template_body += "{\n";
template_body += " $T result = $T(0., 0., 0., 0.);\n";
template_body += " switch(mode)\n";
template_body += " {\n";
template_body += " default:\n";
template_body += " return result;\n";
template_body += " case 0:\n";
template_body += " //linear\n";
template_body += " result = $T(fog_param1 * $I.x + (fog_param0 - 1.), fog_param1 * $I.x + (fog_param0 - 1.), 0., 0.);\n";
template_body += " break;\n";
template_body += " case 1:\n";
template_body += " //exponential\n";
template_body += " result = $T(11.084 * (fog_param1 * $I.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * $I.x + fog_param0 - 1.5)), 0., 0.);\n";
template_body += " break;\n";
template_body += " case 2:\n";
template_body += " //exponential2\n";
template_body += " result = $T(4.709 * (fog_param1 * $I.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * $I.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
template_body += " break;\n";
template_body += " case 3:\n";
template_body += " //exponential_abs\n";
template_body += " result = $T(11.084 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs($I.x) + fog_param0 - 1.5)), 0., 0.);\n";
template_body += " break;\n";
template_body += " case 4:\n";
template_body += " //exponential2_abs\n";
template_body += " result = $T(4.709 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs($I.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
template_body += " break;\n";
template_body += " case 5:\n";
template_body += " //linear_abs\n";
template_body += " result = $T(fog_param1 * abs($I.x) + (fog_param0 - 1.), fog_param1 * abs($I.x) + (fog_param0 - 1.), 0., 0.);\n";
template_body += " break;\n";
template_body += " }\n";
template_body += "\n";
template_body += " result.y = clamp(result.y, 0., 1.);\n";
template_body += " return result;\n";
template_body += "}\n\n";
std::pair<std::string, std::string> replacements[] =
{std::make_pair("$T", wide_vector_type),
std::make_pair("$I", input_coord)};
OS << fmt::replace_all(template_body, replacements);
}
}
namespace glsl
{
enum program_domain
{
glsl_vertex_program = 0,
glsl_fragment_program = 1
};
enum glsl_rules
{
glsl_rules_opengl4,
glsl_rules_rpirv
};
static std::string getFloatTypeNameImpl(size_t elementCount)
{
switch (elementCount)
{
default:
abort();
case 1:
return "float";
case 2:
return "vec2";
case 3:
return "vec3";
case 4:
return "vec4";
}
}
static std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::string &Op1)
{
switch (f)
{
case COMPARE::FUNCTION_SEQ:
return "equal(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SGE:
return "greaterThanEqual(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SGT:
return "greaterThan(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SLE:
return "lessThanEqual(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SLT:
return "lessThan(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SNE:
return "notEqual(" + Op0 + ", " + Op1 + ")";
}
fmt::throw_exception("Unknown compare function" HERE);
}
static void insert_vertex_input_fetch(std::stringstream& OS, glsl_rules rules, bool glsl4_compliant=true)
{
std::string vertex_id_name = (rules == glsl_rules_opengl4) ? "gl_VertexID" : "gl_VertexIndex";
//Actually decode a vertex attribute from a raw byte stream
OS << "struct attribute_desc\n";
OS << "{\n";
OS << " int type;\n";
OS << " int attribute_size;\n";
OS << " int starting_offset;\n";
OS << " int stride;\n";
OS << " int swap_bytes;\n";
OS << " int is_volatile;\n";
OS << " int frequency;\n";
OS << " int divisor;\n";
OS << " int modulo;\n";
OS << "};\n\n";
OS << "uint get_bits(uvec4 v, int swap)\n";
OS << "{\n";
OS << " if (swap != 0) return (v.w | v.z << 8 | v.y << 16 | v.x << 24);\n";
OS << " return (v.x | v.y << 8 | v.z << 16 | v.w << 24);\n";
OS << "}\n\n";
OS << "uint get_bits(uvec2 v, int swap)\n";
OS << "{\n";
OS << " if (swap != 0) return (v.y | v.x << 8);\n";
OS << " return (v.x | v.y << 8);\n";
OS << "}\n\n";
OS << "int preserve_sign_s16(uint bits)\n";
OS << "{\n";
OS << " //convert raw 16 bit value into signed 32-bit integer counterpart\n";
OS << " uint sign = bits & 0x8000;\n";
OS << " if (sign != 0) return int(bits | 0xFFFF0000);\n";
OS << " return int(bits);\n";
OS << "}\n\n";
//For intel GPUs which cannot access vectors in indexed mode (driver bug? or glsl version too low?)
if (!glsl4_compliant)
{
OS << "void mov(inout vec4 vector, in int index, in float scalar)\n";
OS << "{\n";
OS << " switch(index)\n";
OS << " {\n";
OS << " case 0: vector.x = scalar; return;\n";
OS << " case 1: vector.y = scalar; return;\n";
OS << " case 2: vector.z = scalar; return;\n";
OS << " case 3: vector.w = scalar; return;\n";
OS << " }\n";
OS << "}\n";
}
else
{
OS << "#define mov(v, i, s) v[i] = s\n";
}
OS << "#define get_s16(v, s) preserve_sign_s16(get_bits(v, s))\n\n";
OS << "vec4 fetch_attribute(attribute_desc desc, int vertex_id, usamplerBuffer input_stream)\n";
OS << "{\n";
OS << " vec4 result = vec4(0., 0., 0., 1.);\n";
OS << " vec4 scale = vec4(1.);\n";
OS << " uvec4 tmp;\n";
OS << " uint bits;\n";
OS << " bool reverse_order = false;\n";
OS << "\n";
OS << " int first_byte = (vertex_id * desc.stride) + desc.starting_offset;\n";
OS << " for (int n = 0; n < 4; n++)\n";
OS << " {\n";
OS << " if (n == desc.attribute_size) break;\n";
OS << "\n";
OS << " switch (desc.type)\n";
OS << " {\n";
OS << " case 0:\n";
OS << " //signed normalized 16-bit\n";
OS << " tmp.x = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.y = texelFetch(input_stream, first_byte++).x;\n";
OS << " mov(result, n, get_s16(tmp.xy, desc.swap_bytes));\n";
OS << " mov(scale, n, 32767.);\n";
OS << " break;\n";
OS << " case 1:\n";
OS << " //float\n";
OS << " tmp.x = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.y = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.z = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.w = texelFetch(input_stream, first_byte++).x;\n";
OS << " mov(result, n, uintBitsToFloat(get_bits(tmp, desc.swap_bytes)));\n";
OS << " break;\n";
OS << " case 2:\n";
OS << " //half\n";
OS << " tmp.x = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.y = texelFetch(input_stream, first_byte++).x;\n";
OS << " mov(result, n, unpackHalf2x16(uint(get_bits(tmp.xy, desc.swap_bytes))).x);\n";
OS << " break;\n";
OS << " case 3:\n";
OS << " //unsigned byte\n";
OS << " mov(result, n, texelFetch(input_stream, first_byte++).x);\n";
OS << " mov(scale, n, 255.);\n";
OS << " reverse_order = (desc.swap_bytes != 0);\n";
OS << " break;\n";
OS << " case 4:\n";
OS << " //signed word\n";
OS << " tmp.x = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.y = texelFetch(input_stream, first_byte++).x;\n";
OS << " mov(result, n, get_s16(tmp.xy, desc.swap_bytes));\n";
OS << " break;\n";
OS << " case 5:\n";
OS << " //cmp\n";
OS << " tmp.x = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.y = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.z = texelFetch(input_stream, first_byte++).x;\n";
OS << " tmp.w = texelFetch(input_stream, first_byte++).x;\n";
OS << " bits = get_bits(tmp, desc.swap_bytes);\n";
OS << " result.x = preserve_sign_s16((bits & 0x7FF) << 5);\n";
OS << " result.y = preserve_sign_s16(((bits >> 11) & 0x7FF) << 5);\n";
OS << " result.z = preserve_sign_s16(((bits >> 22) & 0x3FF) << 6);\n";
OS << " result.w = 1.;\n";
OS << " scale = vec4(32767., 32767., 32767., 1.);\n";
OS << " break;\n";
OS << " case 6:\n";
OS << " //ub256\n";
OS << " mov(result, n, float(texelFetch(input_stream, first_byte++).x));\n";
OS << " reverse_order = (desc.swap_bytes != 0);\n";
OS << " break;\n";
OS << " }\n";
OS << " }\n\n";
OS << " result /= scale;\n";
OS << " return (reverse_order)? result.wzyx: result;\n";
OS << "}\n\n";
OS << "attribute_desc fetch_desc(int location)\n";
OS << "{\n";
OS << " attribute_desc result;\n";
OS << " int attribute_flags = input_attributes[location].w;\n";
OS << " result.type = input_attributes[location].x;\n";
OS << " result.attribute_size = input_attributes[location].y;\n";
OS << " result.starting_offset = input_attributes[location].z;\n";
OS << " result.stride = attribute_flags & 0xFF;\n";
OS << " result.swap_bytes = (attribute_flags >> 8) & 0x1;\n";
OS << " result.is_volatile = (attribute_flags >> 9) & 0x1;\n";
OS << " result.frequency = (attribute_flags >> 10) & 0x3;\n";
OS << " result.modulo = (attribute_flags >> 12) & 0x1;\n";
OS << " result.divisor = (attribute_flags >> 13) & 0xFFFF;\n";
OS << " return result;\n";
OS << "}\n\n";
OS << "vec4 read_location(int location)\n";
OS << "{\n";
OS << " attribute_desc desc = fetch_desc(location);\n";
OS << "\n";
OS << " int vertex_id = " << vertex_id_name << " - int(vertex_base_index);\n";
OS << " if (desc.frequency == 0)\n";
OS << " vertex_id = 0;\n";
OS << " else if (desc.frequency > 1)\n";
OS << " {\n";
OS << " //if a vertex modifier is active; vertex_base must be 0 and is ignored\n";
OS << " if (desc.modulo != 0)\n";
OS << " vertex_id = " << vertex_id_name << " % desc.divisor;\n";
OS << " else\n";
OS << " vertex_id = " << vertex_id_name << " / desc.divisor;\n";
OS << " }\n";
OS << "\n";
OS << " if (desc.is_volatile != 0)\n";
OS << " return fetch_attribute(desc, vertex_id, volatile_input_stream);\n";
OS << " else\n";
OS << " return fetch_attribute(desc, vertex_id, persistent_input_stream);\n";
OS << "}\n\n";
}
static void insert_glsl_legacy_function(std::ostream& OS, glsl::program_domain domain)
{
OS << "vec4 lit_legacy(vec4 val)";
OS << "{\n";
OS << " vec4 clamped_val = val;\n";
OS << " clamped_val.x = max(val.x, 0.);\n";
OS << " clamped_val.y = max(val.y, 0.);\n";
OS << " vec4 result;\n";
OS << " result.x = 1.;\n";
OS << " result.w = 1.;\n";
OS << " result.y = clamped_val.x;\n";
OS << " result.z = clamped_val.x > 0. ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.;\n";
OS << " return result;\n";
OS << "}\n\n";
if (domain == glsl::program_domain::glsl_vertex_program)
return;
program_common::insert_compare_op(OS);
//NOTE: After testing with GOW, the w component is either the original depth or wraps around to the x component
//Since component.r == depth_value with some precision loss, just use the precise depth value for now (further testing needed)
OS << "vec4 decodeLinearDepth(float depth_value)\n";
OS << "{\n";
OS << " uint value = uint(depth_value * 16777215);\n";
OS << " uint b = (value & 0xff);\n";
OS << " uint g = (value >> 8) & 0xff;\n";
OS << " uint r = (value >> 16) & 0xff;\n";
OS << " return vec4(float(r)/255., float(g)/255., float(b)/255., depth_value);\n";
OS << "}\n\n";
OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n";
OS << "{\n";
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
OS << "}\n\n";
OS << "vec4 texture2DReconstruct(sampler2DRect tex, vec2 coord)\n";
OS << "{\n";
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
OS << "}\n\n";
}
static void insert_fog_declaration(std::ostream& OS)
{
program_common::insert_fog_declaration(OS, "vec4", "fog_c");
}
}
+3 -11
View File
@@ -28,7 +28,7 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
return false;
if (binary1.data.size() != binary2.data.size())
return false;
if (!binary1.skip_vertex_input_check && !binary2.skip_vertex_input_check && binary1.rsx_vertex_inputs != binary2.rsx_vertex_inputs)
if (binary1.rsx_vertex_inputs != binary2.rsx_vertex_inputs)
return false;
const qword *instBuffer1 = (const qword*)binary1.data.data();
@@ -107,20 +107,12 @@ size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) cons
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
{
if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode ||
binary1.back_color_diffuse_output != binary2.back_color_diffuse_output || binary1.back_color_specular_output != binary2.back_color_specular_output ||
binary1.front_back_color_enabled != binary2.front_back_color_enabled ||
binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func ||
binary1.shadow_textures != binary2.shadow_textures || binary1.redirected_textures != binary2.redirected_textures)
return false;
for (u8 index = 0; index < 16; ++index)
{
if (binary1.textures_alpha_kill[index] != binary2.textures_alpha_kill[index])
return false;
if (binary1.textures_zfunc[index] != binary2.textures_zfunc[index])
return false;
}
const qword *instBuffer1 = (const qword*)binary1.addr;
const qword *instBuffer2 = (const qword*)binary2.addr;
size_t instIndex = 0;
+3 -11
View File
@@ -5,7 +5,6 @@
#include "Emu/Memory/vm.h"
#include "Utilities/GSL.h"
#include "Utilities/hash.h"
enum class SHADER_TYPE
{
@@ -94,9 +93,9 @@ class program_state_cache
size_t operator()(const pipeline_key &key) const
{
size_t hashValue = 0;
hashValue ^= rpcs3::hash_base<unsigned>(key.vertex_program_id);
hashValue ^= rpcs3::hash_base<unsigned>(key.fragment_program_id);
hashValue ^= rpcs3::hash_struct<pipeline_properties>(key.properties);
hashValue ^= std::hash<unsigned>()(key.vertex_program_id);
hashValue ^= std::hash<unsigned>()(key.fragment_program_id);
hashValue ^= std::hash<pipeline_properties>()(key.properties);
return hashValue;
}
};
@@ -111,7 +110,6 @@ class program_state_cache
protected:
size_t m_next_id = 0;
bool m_cache_miss_flag;
binary_to_vertex_program m_vertex_shader_cache;
binary_to_fragment_program m_fragment_shader_cache;
std::unordered_map <pipeline_key, pipeline_storage_type, pipeline_key_hash, pipeline_key_compare> m_storage;
@@ -199,10 +197,7 @@ public:
{
const auto I = m_storage.find(key);
if (I != m_storage.end())
{
m_cache_miss_flag = false;
return I->second;
}
}
LOG_NOTICE(RSX, "Add program :");
@@ -210,9 +205,6 @@ public:
LOG_NOTICE(RSX, "*** fp id = %d", fragment_program.id);
m_storage[key] = backend_traits::build_pipeline(vertex_program, fragment_program, pipelineProperties, std::forward<Args>(args)...);
m_cache_miss_flag = true;
LOG_SUCCESS(RSX, "New program compiled successfully");
return m_storage[key];
}
@@ -43,7 +43,7 @@ std::string VertexProgramDecompiler::GetDST(bool isSca)
std::string mask = GetMask(isSca);
switch ((isSca && d3.sca_dst_tmp != 0x3f) ? 0x1f : d3.dst)
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;
@@ -209,7 +209,6 @@ std::string VertexProgramDecompiler::Format(const std::string& code)
{ "$awm", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrRegWithoutMask), this) },
{ "$am", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrMask), this) },
{ "$a", std::bind(std::mem_fn(&VertexProgramDecompiler::AddAddrReg), this) },
{ "$vm", std::bind(std::mem_fn(&VertexProgramDecompiler::GetVecMask), this) },
{ "$t", std::bind(std::mem_fn(&VertexProgramDecompiler::GetTex), this) },
@@ -374,7 +373,7 @@ void VertexProgramDecompiler::SetDSTSca(const std::string& code)
SetDST(true, code);
}
std::string VertexProgramDecompiler::NotZeroPositive(const std::string& code)
std::string VertexProgramDecompiler::NotZeroPositive(const std::string code)
{
return "max(" + code + ", 1.E-10)";
}
@@ -607,9 +606,8 @@ std::string VertexProgramDecompiler::Decompile()
case RSX_VEC_OPCODE_MAX: SetDSTVec("max($0, $1)"); break;
case RSX_VEC_OPCODE_SLT: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SLT, "$0", "$1") + ")"); break;
case RSX_VEC_OPCODE_SGE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SGE, "$0", "$1") + ")"); break;
// Note: ARL uses the vec mask to determine channels and ignores the src input mask
// Tested with SH3, BLES00574 (G-Force) and NPUB90415 (Dead Space 2 Demo)
case RSX_VEC_OPCODE_ARL: AddCode("$ifcond $awm$vm = " + getIntTypeName(4) + "($0)$vm;"); break;
// Note: It looks like ARL opcode ignore input/output swizzle mask (SH3)
case RSX_VEC_OPCODE_ARL: AddCode("$ifcond $awm = " + getIntTypeName(4) + "($0);"); break;
case RSX_VEC_OPCODE_FRC: SetDSTVec(getFunction(FUNCTION::FUNCTION_FRACT)); break;
case RSX_VEC_OPCODE_FLR: SetDSTVec("floor($0)"); break;
case RSX_VEC_OPCODE_SEQ: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SEQ, "$0", "$1") + ")"); break;
@@ -61,7 +61,7 @@ struct VertexProgramDecompiler
const std::vector<u32>& m_data;
ParamArray m_parr;
std::string NotZeroPositive(const std::string& code);
std::string NotZeroPositive(const std::string code);
std::string GetMask(bool is_sca);
std::string GetVecMask();
std::string GetScaMask();
+4 -4
View File
@@ -42,7 +42,7 @@ namespace
fmt::throw_exception("Wrong vector size %d" HERE, size);
}
u32 get_vertex_count(const std::vector<std::pair<u32, u32> >& first_count_commands)
u32 get_vertex_count(const std::vector<std::pair<u32, u32> > first_count_commands)
{
u32 vertex_count = 0;
for (const auto &pair : first_count_commands)
@@ -89,7 +89,7 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 512));
fill_scale_offset_data(mapped_buffer, true);
fill_user_clip_data((char*)mapped_buffer + 64);
fill_fragment_state_buffer((char *)mapped_buffer + 128, current_fragment_program);
fill_fragment_state_buffer((char *)mapped_buffer + 128, m_fragment_program);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 512));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
@@ -124,7 +124,7 @@ void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_in
D3D12_CONSTANT_BUFFER_VIEW_DESC D3D12GSRender::upload_fragment_shader_constants()
{
// Get constant from fragment program
size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(current_fragment_program);
size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(m_fragment_program);
// Multiple of 256 never 0
buffer_size = (buffer_size + 255) & ~255;
@@ -132,7 +132,7 @@ D3D12_CONSTANT_BUFFER_VIEW_DESC D3D12GSRender::upload_fragment_shader_constants(
size_t offset = 0;
float *mapped_buffer = m_buffer_data.map<float>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
m_pso_cache.fill_fragment_constants_buffer({ mapped_buffer, ::narrow<int>(buffer_size) }, current_fragment_program);
m_pso_cache.fill_fragment_constants_buffer({ mapped_buffer, ::narrow<int>(buffer_size) }, m_fragment_program);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
return {
@@ -124,8 +124,6 @@ void insert_d3d12_legacy_function(std::ostream& OS, bool is_fragment_program)
if (!is_fragment_program)
return;
program_common::insert_compare_op(OS);
OS << "uint packSnorm2x16(float2 val)";
OS << "{\n";
OS << " uint high_bits = round(clamp(val.x, -1., 1.) * 32767.);\n";
@@ -1,7 +1,6 @@
#pragma once
#include "../Common/ShaderParam.h"
#include "../Common/GLSLCommon.h"
std::string getFloatTypeNameImp(size_t elementCount);
std::string getFunctionImp(FUNCTION f);
+1 -1
View File
@@ -304,7 +304,7 @@ D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(rsx::primitive_type draw_mode)
case rsx::primitive_type::triangle_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case rsx::primitive_type::triangle_fan: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::quads: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::quad_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case rsx::primitive_type::quad_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::polygon: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
fmt::throw_exception("Invalid draw mode (0x%x)" HERE, (u32)draw_mode);
@@ -42,12 +42,8 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
OS << " float4 userClipFactor[2];\n";
OS << " float fog_param0;\n";
OS << " float fog_param1;\n";
OS << " uint alpha_test;\n";
OS << " float alpha_ref;\n";
OS << " uint alpha_func;\n";
OS << " uint fog_mode;\n";
OS << " uint window_origin;\n";
OS << " uint window_height;\n";
OS << " int isAlphaTested;\n";
OS << " float alphaRef;\n";
OS << " float4 texture_parameters[16];\n";
OS << "};\n";
}
@@ -155,6 +151,38 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
namespace
{
// Note: It's not clear whether fog is computed per pixel or per vertex.
// But it makes more sense to compute exp of interpoled value than to interpolate exp values.
void insert_fog_declaration(std::stringstream & OS, rsx::fog_mode mode)
{
switch (mode)
{
case rsx::fog_mode::linear:
OS << " float4 fogc = float4(fog_param1 * In.fogc.x + (fog_param0 - 1.), fog_param1 * In.fogc.x + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential:
OS << " float4 fogc = float4(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * In.fogc.x + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2:
OS << " float4 fogc = float4(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * In.fogc.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
break;
case rsx::fog_mode::linear_abs:
OS << " float4 fogc = float4(fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), fog_param1 * abs(In.fogc.x) + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential_abs:
OS << " float4 fogc = float4(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2_abs:
OS << " float4 fogc = float4(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(In.fogc.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
break;
default:
OS << " float4 fogc = float4(0., 0., 0., 0.);\n";
return;
}
OS << " fogc.y = saturate(fogc.y);\n";
}
std::string insert_texture_fetch(const RSXFragmentProgram& prog, int index)
{
std::string tex_name = "tex" + std::to_string(index) + ".Sample";
@@ -177,18 +205,6 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
{
insert_d3d12_legacy_function(OS, true);
for (const ParamType &PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem &PI : PT.items)
{
if (PI.name == "fogc")
{
program_common::insert_fog_declaration(OS, "float4", "fogc", true);
break;
}
}
}
const std::set<std::string> output_value =
{
"r0", "r1", "r2", "r3", "r4",
@@ -215,7 +231,7 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
}
if (PI.name == "fogc")
{
OS << " float4 fogc = fetch_fog_value(fog_mode, In.fogc);\n";
insert_fog_declaration(OS, m_prog.fog_equation);
continue;
}
if (PI.name == "ssa")
@@ -223,9 +239,10 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";\n";
}
}
OS << " float4 wpos = In.Position;\n";
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
// A bit unclean, but works.
OS << " " << "float4 wpos = In.Position;\n";
if (m_prog.origin_mode == rsx::window_origin::bottom)
OS << " wpos.y = (" << std::to_string(m_prog.height) << " - wpos.y);\n";
OS << " float4 ssa = is_front_face ? float4(1., 1., 1., 1.) : float4(-1., -1., -1., -1.);\n";
// Declare output
@@ -346,7 +363,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
}
}
OS << " if (alpha_test != 0 && !comparison_passes(Out." << first_output_name << ".a, alpha_ref, alpha_func)) discard;\n";
OS << make_comparison_test(m_prog.alpha_func, "isAlphaTested && ", "Out." + first_output_name + ".a", "alphaRef");
}
OS << " return Out;\n";
+1 -1
View File
@@ -329,7 +329,7 @@ void D3D12GSRender::end()
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 (!current_fragment_program.valid)
if (!m_fragment_program.valid)
{
rsx::thread::end();
return;
+2
View File
@@ -61,6 +61,8 @@ private:
data_cache m_texture_cache;
bool invalidate_address(u32 addr);
RSXVertexProgram m_vertex_program;
RSXFragmentProgram m_fragment_program;
PipelineStateObjectCache m_pso_cache;
std::tuple<ComPtr<ID3D12PipelineState>, size_t, size_t> m_current_pso;
+5 -5
View File
@@ -53,10 +53,10 @@ void D3D12GSRender::load_program()
return std::make_tuple(true, native_pitch);
};
get_current_vertex_program();
get_current_fragment_program(rtt_lookup_func);
m_vertex_program = get_current_vertex_program();
m_fragment_program = get_current_fragment_program(rtt_lookup_func);
if (!current_fragment_program.valid)
if (!m_fragment_program.valid)
return;
D3D12PipelineProperties prop = {};
@@ -308,12 +308,12 @@ void D3D12GSRender::load_program()
}
}
m_current_pso = m_pso_cache.getGraphicPipelineState(current_vertex_program, current_fragment_program, prop, m_device.Get(), m_shared_root_signature.Get());
m_current_pso = m_pso_cache.getGraphicPipelineState(m_vertex_program, m_fragment_program, prop, m_device.Get(), m_shared_root_signature.Get());
return;
}
std::pair<std::string, std::string> D3D12GSRender::get_programs() const
{
return std::make_pair(m_pso_cache.get_transform_program(current_vertex_program).content, m_pso_cache.get_shader_program(current_fragment_program).content);
return std::make_pair(m_pso_cache.get_transform_program(m_vertex_program).content, m_pso_cache.get_shader_program(m_fragment_program).content);
}
#endif
@@ -298,9 +298,6 @@ void D3D12GSRender::copy_render_target_to_dma_location()
int clip_w = rsx::method_registers.surface_clip_width();
int clip_h = rsx::method_registers.surface_clip_height();
if (clip_w == 0 || clip_h == 0)
return;
size_t depth_row_pitch = align(clip_w * 4, 256);
size_t depth_buffer_offset_in_heap = 0;
+68
View File
@@ -1,6 +1,22 @@
#include "stdafx.h"
#include "GLCommonDecompiler.h"
std::string getFloatTypeNameImpl(size_t elementCount)
{
switch (elementCount)
{
default:
abort();
case 1:
return "float";
case 2:
return "vec2";
case 3:
return "vec3";
case 4:
return "vec4";
}
}
std::string getFunctionImpl(FUNCTION f)
{
@@ -68,3 +84,55 @@ std::string getFunctionImpl(FUNCTION f)
return "texture2DReconstruct($t, $0.xy * $t_coord_scale)";
}
}
std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::string &Op1)
{
switch (f)
{
case COMPARE::FUNCTION_SEQ:
return "equal(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SGE:
return "greaterThanEqual(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SGT:
return "greaterThan(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SLE:
return "lessThanEqual(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SLT:
return "lessThan(" + Op0 + ", " + Op1 + ")";
case COMPARE::FUNCTION_SNE:
return "notEqual(" + Op0 + ", " + Op1 + ")";
}
fmt::throw_exception("Unknown compare function" HERE);
}
void insert_glsl_legacy_function(std::ostream& OS, gl::glsl::program_domain domain)
{
OS << "vec4 lit_legacy(vec4 val)";
OS << "{\n";
OS << " vec4 clamped_val = val;\n";
OS << " clamped_val.x = max(val.x, 0);\n";
OS << " clamped_val.y = max(val.y, 0);\n";
OS << " vec4 result;\n";
OS << " result.x = 1.0;\n";
OS << " result.w = 1.;\n";
OS << " result.y = clamped_val.x;\n";
OS << " result.z = clamped_val.x > 0.0 ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.0;\n";
OS << " return result;\n";
OS << "}\n\n";
if (domain != gl::glsl::program_domain::glsl_fragment_program)
return;
//NOTE: We lose precision if we just store depth value into 8-bit textures i.e (depth, 0, 0)
//NOTE2: After testing with GOW, the w component is either the original depth or wraps around to the x component
//Since component.r == depth_value with some precision loss, just use the precise depth value for now (further testing needed)
OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n";
OS << "{\n";
OS << " float depth_value = texture(tex, coord.xy).r;\n";
OS << " uint value = uint(depth_value * 16777215);\n";
OS << " uint b = (value & 0xff);\n";
OS << " uint g = (value >> 8) & 0xff;\n";
OS << " uint r = (value >> 16) & 0xff;\n";
OS << " return vec4(float(r)/255., float(g)/255., float(b)/255., depth_value);\n";
OS << "}\n\n";
}
+4 -1
View File
@@ -1,7 +1,10 @@
#pragma once
#include "../Common/ShaderParam.h"
#include "../Common/GLSLCommon.h"
#include "GLHelpers.h"
#include <ostream>
std::string getFloatTypeNameImpl(size_t elementCount);
std::string getFunctionImpl(FUNCTION f);
std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::string &Op1);
void insert_glsl_legacy_function(std::ostream& OS, gl::glsl::program_domain domain);
+44 -25
View File
@@ -3,13 +3,13 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "GLFragmentProgram.h"
#include "../Common/ProgramStateCache.h"
#include "GLCommonDecompiler.h"
#include "../GCM.h"
std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
{
return glsl::getFloatTypeNameImpl(elementCount);
return getFloatTypeNameImpl(elementCount);
}
std::string GLFragmentDecompilerThread::getFunction(FUNCTION f)
@@ -24,7 +24,7 @@ std::string GLFragmentDecompilerThread::saturate(const std::string & code)
std::string GLFragmentDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1)
{
return glsl::compareFunctionImpl(f, Op0, Op1);
return compareFunctionImpl(f, Op0, Op1);
}
void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS)
@@ -145,16 +145,45 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
OS << " float fog_param1;\n";
OS << " uint alpha_test;\n";
OS << " float alpha_ref;\n";
OS << " uint alpha_func;\n";
OS << " uint fog_mode;\n";
OS << " uint window_origin;\n";
OS << " uint window_height;\n";
OS << " vec4 texture_parameters[16];\n"; //sampling: x,y scaling and (unused) offsets data
OS << "};\n";
}
namespace
{
// Note: It's not clear whether fog is computed per pixel or per vertex.
// But it makes more sense to compute exp of interpoled value than to interpolate exp values.
void insert_fog_declaration(std::stringstream & OS, rsx::fog_mode mode)
{
switch (mode)
{
case rsx::fog_mode::linear:
OS << " vec4 fogc = vec4(fog_param1 * fog_c.x + (fog_param0 - 1.), fog_param1 * fog_c.x + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential:
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog_c.x + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2:
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog_c.x + fog_param0 - 1.5), 2.)), 0., 0.);\n";
break;
case rsx::fog_mode::linear_abs:
OS << " vec4 fogc = vec4(fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), fog_param1 * abs(fog_c.x) + (fog_param0 - 1.), 0., 0.);\n";
break;
case rsx::fog_mode::exponential_abs:
OS << " vec4 fogc = vec4(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5)), 0., 0.);\n";
break;
case rsx::fog_mode::exponential2_abs:
OS << " vec4 fogc = vec4(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog_c.x) + fog_param0 - 1.5), 2.)), 0., 0.);\n";
break;
default:
OS << " vec4 fogc = vec4(0.);\n";
return;
}
OS << " fogc.y = clamp(fogc.y, 0., 1.);\n";
}
void insert_texture_scale(std::stringstream & OS, const RSXFragmentProgram& prog, int index)
{
std::string vec_type = "vec2";
@@ -192,20 +221,7 @@ namespace
void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
glsl::insert_glsl_legacy_function(OS, glsl::glsl_fragment_program);
//TODO: Generate input mask during parse stage to avoid this
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
{
if (PI.name == "fogc")
{
glsl::insert_fog_declaration(OS);
break;
}
}
}
insert_glsl_legacy_function(OS, gl::glsl::glsl_fragment_program);
const std::set<std::string> output_values =
{
@@ -225,7 +241,6 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
}
}
OS << "//FP_HASH=" << fmt::format("%llX", program_hash_util::fragment_program_hash()(m_prog)) << "\n";
OS << "void fs_main(" << parameters << ")\n";
OS << "{\n";
@@ -246,7 +261,11 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
OS << " vec4 wpos = gl_FragCoord;\n";
OS << " if (window_origin != 0) wpos.y = window_height - wpos.y;\n";
//Flip wpos in Y
//We could optionally export wpos from the VS, but this is so much easier
if (m_prog.origin_mode == rsx::window_origin::bottom)
OS << " wpos.y = " << std::to_string(m_prog.height) << " - wpos.y;\n";
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
{
@@ -307,7 +326,7 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
if (PI.name == "fogc")
{
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
insert_fog_declaration(OS, m_prog.fog_equation);
continue;
}
}
@@ -375,7 +394,7 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
}
}
OS << " if (alpha_test != 0 && !comparison_passes(" << first_output_name << ".a, alpha_ref, alpha_func)) discard;\n";
OS << make_comparison_test(m_prog.alpha_func, "alpha_test != 0 && ", first_output_name + ".a", "alpha_ref");
}
OS << "}\n\n";
+160 -378
View File
@@ -24,7 +24,8 @@ namespace
GLGSRender::GLGSRender() : GSRender()
{
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1"));
//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());
@@ -32,6 +33,34 @@ GLGSRender::GLGSRender() : GSRender()
m_vertex_cache.reset(new gl::weak_vertex_cache());
}
u32 GLGSRender::enable(u32 condition, u32 cap)
{
if (condition)
{
glEnable(cap);
}
else
{
glDisable(cap);
}
return condition;
}
u32 GLGSRender::enable(u32 condition, u32 cap, u32 index)
{
if (condition)
{
glEnablei(cap, index);
}
else
{
glDisablei(cap, index);
}
return condition;
}
extern CellGcmContextData current_context;
namespace
@@ -165,9 +194,6 @@ void GLGSRender::begin()
if (skip_frame)
return;
if (conditional_render_enabled && conditional_render_test_failed)
return;
init_buffers();
if (!framebuffer_status_valid)
@@ -180,105 +206,87 @@ void GLGSRender::begin()
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
__glcheck glColorMask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
__glcheck glDepthMask(rsx::method_registers.depth_write_enabled());
__glcheck glStencilMask(rsx::method_registers.stencil_mask());
if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
if (__glcheck enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
{
gl_state.depth_func(comparison_op(rsx::method_registers.depth_func()));
float range_near = rsx::method_registers.clip_min();
float range_far = rsx::method_registers.clip_max();
if (g_cfg.video.strict_rendering_mode)
gl_state.depth_range(range_near, range_far);
else
{
//Workaround to preserve depth precision but respect z direction
//Ni no Kuni sets a very restricted z range (0.9x - 1.) and depth reads / tests are broken
if (range_near <= range_far)
gl_state.depth_range(0.f, 1.f);
else
gl_state.depth_range(1.f, 0.f);
}
__glcheck glDepthFunc(comparison_op(rsx::method_registers.depth_func()));
}
if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
if (glDepthBoundsEXT && (__glcheck enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
{
gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
__glcheck glDepthBoundsEXT(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
}
gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER);
//__glcheck glDepthRange(rsx::method_registers.clip_min(), rsx::method_registers.clip_max());
__glcheck enable(rsx::method_registers.dither_enabled(), GL_DITHER);
if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND))
if (__glcheck enable(rsx::method_registers.blend_enabled(), GL_BLEND))
{
glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
__glcheck glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
auto blend_colors = rsx::get_constant_blend_colors();
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
__glcheck glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
__glcheck glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
blend_equation(rsx::method_registers.blend_equation_a()));
}
if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
if (__glcheck enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
{
glStencilFunc(comparison_op(rsx::method_registers.stencil_func()),
rsx::method_registers.stencil_func_ref(),
__glcheck glStencilFunc(comparison_op(rsx::method_registers.stencil_func()), rsx::method_registers.stencil_func_ref(),
rsx::method_registers.stencil_func_mask());
glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
__glcheck glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
stencil_op(rsx::method_registers.stencil_op_zpass()));
if (rsx::method_registers.two_sided_stencil_test_enabled())
{
glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
__glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
__glcheck glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
__glcheck glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
}
}
gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
__glcheck enable(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
__glcheck enable(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
__glcheck enable(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
if (__glcheck enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
{
gl_state.logic_op(logic_op(rsx::method_registers.logic_operation()));
__glcheck glLogicOp(logic_op(rsx::method_registers.logic_operation()));
}
gl_state.line_width(rsx::method_registers.line_width());
gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias());
if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
{
gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode()));
}
gl_state.front_face(front_face(rsx::method_registers.front_face_mode()));
__glcheck glLineWidth(rsx::method_registers.line_width());
__glcheck enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
//TODO
//NV4097_SET_ANISO_SPREAD
__glcheck enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
__glcheck enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
__glcheck enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
__glcheck glPolygonOffset(rsx::method_registers.poly_offset_scale(),
rsx::method_registers.poly_offset_bias());
//NV4097_SET_SPECULAR_ENABLE
//NV4097_SET_TWO_SIDE_LIGHT_EN
//NV4097_SET_FLAT_SHADE_OP
//NV4097_SET_EDGE_FLAG
if (__glcheck enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
{
__glcheck glCullFace(cull_face(rsx::method_registers.cull_face_mode()));
}
__glcheck glFrontFace(front_face(rsx::method_registers.front_face_mode()));
//NV4097_SET_COLOR_KEY_COLOR
//NV4097_SET_SHADER_CONTROL
@@ -319,12 +327,18 @@ namespace
void GLGSRender::end()
{
if (skip_frame || !framebuffer_status_valid || (conditional_render_enabled && conditional_render_test_failed) || !check_program_state())
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())
{
rsx::thread::end();
return;
}
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();
if (manually_flush_ring_buffers)
{
//Use approximations to reseve space. This path is mostly for debug purposes anyway
@@ -336,32 +350,6 @@ void GLGSRender::end()
m_index_ring_buffer->reserve_storage_on_heap(16 * 1024);
}
//Do vertex upload before RTT prep / texture lookups to give the driver time to push data
u32 vertex_draw_count;
u32 actual_vertex_count;
u32 vertex_base;
std::optional<std::tuple<GLenum, u32> > indexed_draw_info;
std::tie(vertex_draw_count, actual_vertex_count, vertex_base, indexed_draw_info) = set_vertex_buffer();
std::chrono::time_point<steady_clock> program_start = steady_clock::now();
//Load program here since it is dependent on vertex state
load_program(vertex_base, actual_vertex_count);
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();
if (manually_flush_ring_buffers)
{
m_attrib_ring_buffer->unmap();
m_index_ring_buffer->unmap();
}
else
{
//DMA push; not needed with MAP_COHERENT
//glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
}
//Check if depth buffer is bound and valid
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
auto copy_rtt_contents = [](gl::render_target *surface)
@@ -410,9 +398,9 @@ void GLGSRender::end()
if (clear_depth)
{
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(1.0);
gl_state.clear_stencil(255);
glDepthMask(GL_TRUE);
glClearDepth(1.0);
glClearStencil(255);
mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
}
@@ -430,7 +418,7 @@ void GLGSRender::end()
}
if (clear_depth)
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
glDepthMask(rsx::method_registers.depth_write_enabled());
ds->set_cleared();
}
@@ -486,12 +474,12 @@ void GLGSRender::end()
int texture_index = i + rsx::limits::fragment_textures_count;
int location;
if (!rsx::method_registers.vertex_textures[i].enabled())
/* if (!rsx::method_registers.vertex_textures[i].enabled())
{
//glActiveTexture(GL_TEXTURE0 + texture_index);
//glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0 + texture_index);
glBindTexture(GL_TEXTURE_2D, 0);
continue;
}
} */
if (m_program->uniforms.has_location("vtex" + std::to_string(i), &location))
{
@@ -503,6 +491,20 @@ void GLGSRender::end()
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
u32 vertex_draw_count = m_last_vertex_count;
std::optional<std::tuple<GLenum, u32> > indexed_draw_info;
bool skip_upload = false;
if (!is_probable_instanced_draw())
{
std::tie(vertex_draw_count, indexed_draw_info) = set_vertex_buffer();
m_last_vertex_count = vertex_draw_count;
}
else
{
skip_upload = true;
}
std::chrono::time_point<steady_clock> draw_start = steady_clock::now();
if (g_cfg.video.debug_output)
@@ -510,38 +512,49 @@ void GLGSRender::end()
m_program->validate();
}
if (indexed_draw_info)
if (manually_flush_ring_buffers)
{
const GLenum index_type = std::get<0>(indexed_draw_info.value());
const u32 index_offset = std::get<1>(indexed_draw_info.value());
m_attrib_ring_buffer->unmap();
m_index_ring_buffer->unmap();
}
if (__glcheck gl_state.enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
if (indexed_draw_info || (skip_upload && m_last_draw_indexed == true))
{
if (__glcheck enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
{
GLenum index_type = (skip_upload)? m_last_ib_type: std::get<0>(indexed_draw_info.value());
__glcheck glPrimitiveRestartIndex((index_type == GL_UNSIGNED_SHORT)? 0xffff: 0xffffffff);
}
__glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, index_type, (GLvoid *)(uintptr_t)index_offset);
m_last_draw_indexed = true;
if (!skip_upload)
{
m_last_ib_type = std::get<0>(indexed_draw_info.value());
m_last_index_offset = std::get<1>(indexed_draw_info.value());
}
__glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, m_last_ib_type, (GLvoid *)(std::ptrdiff_t)m_last_index_offset);
}
else
{
glDrawArrays(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), 0, vertex_draw_count);
draw_fbo.draw_arrays(rsx::method_registers.current_draw_clause.primitive, vertex_draw_count);
m_last_draw_indexed = false;
}
m_attrib_ring_buffer->notify();
m_index_ring_buffer->notify();
m_vertex_state_buffer->notify();
m_scale_offset_buffer->notify();
m_fragment_constants_buffer->notify();
m_transform_constants_buffer->notify();
std::chrono::time_point<steady_clock> draw_end = steady_clock::now();
m_draw_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(draw_end - draw_start).count();
m_draw_calls++;
if (zcull_task_queue.active_query &&
zcull_task_queue.active_query->active)
zcull_task_queue.active_query->num_draws++;
synchronize_buffers();
rsx::thread::end();
}
@@ -580,9 +593,6 @@ void GLGSRender::on_init_thread()
gl::init();
//Enable adaptive vsync if vsync is requested
gl::set_swapinterval(g_cfg.video.vsync ? -1 : 0);
if (g_cfg.video.debug_output)
gl::enable_debugging();
@@ -627,21 +637,13 @@ void GLGSRender::on_init_thread()
const u32 texture_index_offset = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count;
//Array stream buffer
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
auto &tex = m_gl_persistent_stream_buffer;
auto &tex = m_gl_attrib_buffers[index];
tex.create();
tex.set_target(gl::texture::target::textureBuffer);
glActiveTexture(GL_TEXTURE0 + texture_index_offset);
tex.bind();
}
//Register stream buffer
{
auto &tex = m_gl_volatile_stream_buffer;
tex.create();
tex.set_target(gl::texture::target::textureBuffer);
glActiveTexture(GL_TEXTURE0 + texture_index_offset + 1);
glActiveTexture(GL_TEXTURE0 + texture_index_offset + index);
tex.bind();
}
@@ -660,7 +662,7 @@ void GLGSRender::on_init_thread()
m_attrib_ring_buffer.reset(new gl::legacy_ring_buffer());
m_transform_constants_buffer.reset(new gl::legacy_ring_buffer());
m_fragment_constants_buffer.reset(new gl::legacy_ring_buffer());
m_vertex_state_buffer.reset(new gl::legacy_ring_buffer());
m_scale_offset_buffer.reset(new gl::legacy_ring_buffer());
m_index_ring_buffer.reset(new gl::legacy_ring_buffer());
}
else
@@ -668,7 +670,7 @@ void GLGSRender::on_init_thread()
m_attrib_ring_buffer.reset(new gl::ring_buffer());
m_transform_constants_buffer.reset(new gl::ring_buffer());
m_fragment_constants_buffer.reset(new gl::ring_buffer());
m_vertex_state_buffer.reset(new gl::ring_buffer());
m_scale_offset_buffer.reset(new gl::ring_buffer());
m_index_ring_buffer.reset(new gl::ring_buffer());
}
@@ -676,7 +678,7 @@ void GLGSRender::on_init_thread()
m_index_ring_buffer->create(gl::buffer::target::element_array, 64 * 0x100000);
m_transform_constants_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_fragment_constants_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_vertex_state_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_scale_offset_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_vao.element_array_buffer = *m_index_ring_buffer;
@@ -695,17 +697,6 @@ void GLGSRender::on_init_thread()
m_gl_sampler_states[i].bind(i);
}
//Occlusion query
for (u32 i = 0; i < occlusion_query_count; ++i)
{
auto &query = occlusion_query_data[i];
glGenQueries(1, &query.handle);
query.pending = false;
query.active = false;
query.result = 0;
}
//Clip planes are shader controlled; enable all planes driver-side
glEnable(GL_CLIP_DISTANCE0 + 0);
glEnable(GL_CLIP_DISTANCE0 + 1);
@@ -715,13 +706,11 @@ void GLGSRender::on_init_thread()
glEnable(GL_CLIP_DISTANCE0 + 5);
m_gl_texture_cache.initialize(this);
m_shaders_cache->load();
}
void GLGSRender::on_exit()
{
glFinish();
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
m_prog_buffer.clear();
@@ -745,8 +734,10 @@ void GLGSRender::on_exit()
m_vao.remove();
}
m_gl_persistent_stream_buffer.remove();
m_gl_volatile_stream_buffer.remove();
for (gl::texture &tex : m_gl_attrib_buffers)
{
tex.remove();
}
for (auto &sampler : m_gl_sampler_states)
{
@@ -768,9 +759,9 @@ void GLGSRender::on_exit()
m_fragment_constants_buffer->remove();
}
if (m_vertex_state_buffer)
if (m_scale_offset_buffer)
{
m_vertex_state_buffer->remove();
m_scale_offset_buffer->remove();
}
if (m_index_ring_buffer)
@@ -781,15 +772,6 @@ void GLGSRender::on_exit()
m_text_printer.close();
m_gl_texture_cache.close();
for (u32 i = 0; i < occlusion_query_count; ++i)
{
auto &query = occlusion_query_data[i];
query.active = false;
query.pending = false;
glDeleteQueries(1, &query.handle);
}
return GSRender::on_exit();
}
@@ -808,8 +790,8 @@ void GLGSRender::clear_surface(u32 arg)
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers.z_clear_value(surface_depth_format == rsx::surface_depth_format::z24s8);
gl_state.depth_mask(GL_TRUE);
gl_state.clear_depth(f32(clear_depth) / max_depth_value);
glDepthMask(GL_TRUE);
glClearDepth(double(clear_depth) / max_depth_value);
mask |= GLenum(gl::buffers::depth);
gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil);
@@ -824,8 +806,8 @@ void GLGSRender::clear_surface(u32 arg)
{
u8 clear_stencil = rsx::method_registers.stencil_clear_value();
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
gl_state.clear_stencil(clear_stencil);
__glcheck glStencilMask(rsx::method_registers.stencil_mask());
glClearStencil(clear_stencil);
mask |= GLenum(gl::buffers::stencil);
}
@@ -837,8 +819,8 @@ void GLGSRender::clear_surface(u32 arg)
u8 clear_g = rsx::method_registers.clear_color_g();
u8 clear_b = rsx::method_registers.clear_color_b();
gl_state.color_mask(arg & 0xf0);
gl_state.clear_color(clear_r, clear_g, clear_b, clear_a);
glColorMask(((arg & 0x20) ? 1 : 0), ((arg & 0x40) ? 1 : 0), ((arg & 0x80) ? 1 : 0), ((arg & 0x10) ? 1 : 0));
glClearColor(clear_r / 255.f, clear_g / 255.f, clear_b / 255.f, clear_a / 255.f);
mask |= GLenum(gl::buffers::color);
@@ -871,12 +853,6 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
return true;
}
case NV4097_CLEAR_ZCULL_SURFACE:
{
// NOP
// Clearing zcull memory does not modify depth/stencil buffers 'bound' to the zcull region
return true;
}
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
flush_draw_buffers = true;
@@ -886,7 +862,7 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
return false;
}
bool GLGSRender::check_program_state()
bool GLGSRender::load_program()
{
auto rtt_lookup_func = [this](u32 texaddr, rsx::fragment_texture &tex, bool is_depth) -> std::tuple<bool, u16>
{
@@ -908,19 +884,12 @@ bool GLGSRender::check_program_state()
return std::make_tuple(true, surface->get_native_pitch());
};
get_current_fragment_program(rtt_lookup_func);
RSXFragmentProgram fragment_program = get_current_fragment_program(rtt_lookup_func);
if (!fragment_program.valid) return false;
if (current_fragment_program.valid == false)
return false;
RSXVertexProgram vertex_program = get_current_vertex_program();
get_current_vertex_program();
return true;
}
void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
{
auto &fragment_program = current_fragment_program;
auto &vertex_program = current_vertex_program;
u32 unnormalized_rtts = 0;
for (auto &vtx : vertex_program.rsx_vertex_inputs)
{
@@ -934,39 +903,31 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
}
}
vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side
void* pipeline_properties = nullptr;
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, pipeline_properties);
auto old_program = m_program;
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
m_program->use();
if (m_prog_buffer.check_cache_missed())
m_shaders_cache->store(pipeline_properties, vertex_program, fragment_program);
u8 *buf;
u32 vertex_state_offset;
u32 scale_offset_offset;
u32 vertex_constants_offset;
u32 fragment_constants_offset;
const u32 fragment_constants_size = (const u32)m_prog_buffer.get_fragment_constants_buffer_size(fragment_program);
const u32 fragment_buffer_size = fragment_constants_size + (18 * 4 * sizeof(float));
const u32 fragment_buffer_size = fragment_constants_size + (17 * 4 * sizeof(float));
if (manually_flush_ring_buffers)
{
m_vertex_state_buffer->reserve_storage_on_heap(512);
m_scale_offset_buffer->reserve_storage_on_heap(512);
m_fragment_constants_buffer->reserve_storage_on_heap(align(fragment_buffer_size, 256));
if (m_transform_constants_dirty) m_transform_constants_buffer->reserve_storage_on_heap(8192);
}
// Vertex state
auto mapping = m_vertex_state_buffer->alloc_from_heap(512, m_uniform_buffer_offset_align);
// Scale offset
auto mapping = m_scale_offset_buffer->alloc_from_heap(512, m_uniform_buffer_offset_align);
buf = static_cast<u8*>(mapping.first);
vertex_state_offset = mapping.second;
scale_offset_offset = mapping.second;
fill_scale_offset_data(buf, false);
fill_user_clip_data(buf + 64);
*(reinterpret_cast<u32*>(buf + 128)) = rsx::method_registers.transform_branch_bits();
*(reinterpret_cast<u32*>(buf + 132)) = vertex_base;
fill_vertex_layout_state(m_vertex_layout, vertex_count, reinterpret_cast<s32*>(buf + 144));
fill_user_clip_data((char *)buf + 64);
if (m_transform_constants_dirty)
{
@@ -975,6 +936,7 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
buf = static_cast<u8*>(mapping.first);
vertex_constants_offset = mapping.second;
fill_vertex_program_constants_data(buf);
*(reinterpret_cast<u32*>(buf + (468 * 4 * sizeof(float)))) = rsx::method_registers.transform_branch_bits();
}
// Fragment constants
@@ -987,20 +949,21 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
// Fragment state
fill_fragment_state_buffer(buf+fragment_constants_size, fragment_program);
m_vertex_state_buffer->bind_range(0, vertex_state_offset, 512);
m_scale_offset_buffer->bind_range(0, scale_offset_offset, 512);
m_fragment_constants_buffer->bind_range(2, fragment_constants_offset, fragment_buffer_size);
if (m_transform_constants_dirty) m_transform_constants_buffer->bind_range(1, vertex_constants_offset, 8192);
if (manually_flush_ring_buffers)
{
m_vertex_state_buffer->unmap();
m_scale_offset_buffer->unmap();
m_fragment_constants_buffer->unmap();
if (m_transform_constants_dirty) m_transform_constants_buffer->unmap();
}
m_transform_constants_dirty = false;
return true;
}
void GLGSRender::flip(int buffer)
@@ -1101,8 +1064,10 @@ void GLGSRender::flip(int buffer)
}
// Blit source image to the screen
// Disable scissor test (affects blit)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
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);
@@ -1161,12 +1126,6 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing)
return m_gl_texture_cache.flush_section(address);
}
void GLGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
{
if (m_gl_texture_cache.invalidate_range(address_base, size, false))
m_gl_texture_cache.purge_dirty();
}
void GLGSRender::do_local_task()
{
std::lock_guard<std::mutex> lock(queue_guard);
@@ -1224,180 +1183,3 @@ bool GLGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
{
return m_gl_texture_cache.upload_scaled_image(src, dst, interpolate, m_rtts);
}
void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read)
{
if (g_cfg.video.disable_zcull_queries)
return;
bool testing_enabled = zcull_pixel_cnt_enabled || zcull_stats_enabled;
if (framebuffer_swap)
{
zcull_surface_active = false;
const u32 zeta_address = depth_surface_info.address;
if (zeta_address)
{
//Find zeta address in bound zculls
for (int i = 0; i < rsx::limits::zculls_count; i++)
{
if (zculls[i].binded)
{
const u32 rsx_address = rsx::get_address(zculls[i].offset, CELL_GCM_LOCATION_LOCAL);
if (rsx_address == zeta_address)
{
zcull_surface_active = true;
break;
}
}
}
}
}
occlusion_query_info* query = nullptr;
if (zcull_task_queue.task_stack.size() > 0)
query = zcull_task_queue.active_query;
if (query && query->active)
{
if (force_read || (!zcull_rendering_enabled || !testing_enabled || !zcull_surface_active))
{
glEndQuery(GL_ANY_SAMPLES_PASSED);
query->active = false;
query->pending = true;
}
}
else
{
if (zcull_rendering_enabled && testing_enabled && zcull_surface_active)
{
//Find query
u32 free_index = synchronize_zcull_stats();
query = &occlusion_query_data[free_index];
zcull_task_queue.add(query);
glBeginQuery(GL_ANY_SAMPLES_PASSED, query->handle);
query->active = true;
query->result = 0;
query->num_draws = 0;
}
}
}
void GLGSRender::clear_zcull_stats(u32 type)
{
if (g_cfg.video.disable_zcull_queries)
return;
if (type == CELL_GCM_ZPASS_PIXEL_CNT)
{
if (zcull_task_queue.active_query &&
zcull_task_queue.active_query->active &&
zcull_task_queue.active_query->num_draws > 0)
{
//discard active query results
check_zcull_status(false, true);
zcull_task_queue.active_query->pending = false;
//re-enable cull stats if stats are enabled
check_zcull_status(false, false);
zcull_task_queue.active_query->num_draws = 0;
}
current_zcull_stats.clear();
}
}
u32 GLGSRender::get_zcull_stats(u32 type)
{
if (g_cfg.video.disable_zcull_queries)
return 0u;
if (zcull_task_queue.active_query &&
zcull_task_queue.active_query->active &&
current_zcull_stats.zpass_pixel_cnt == 0 &&
type == CELL_GCM_ZPASS_PIXEL_CNT)
{
//The zcull unit is still bound as the read is happening and there are no results ready
check_zcull_status(false, true); //close current query
check_zcull_status(false, false); //start new query since stat counting is still active
}
switch (type)
{
case CELL_GCM_ZPASS_PIXEL_CNT:
{
if (current_zcull_stats.zpass_pixel_cnt > 0)
return UINT16_MAX;
synchronize_zcull_stats(true);
return (current_zcull_stats.zpass_pixel_cnt > 0)? UINT16_MAX : 0;
}
case CELL_GCM_ZCULL_STATS:
case CELL_GCM_ZCULL_STATS1:
case CELL_GCM_ZCULL_STATS2:
//TODO
return UINT16_MAX;
case CELL_GCM_ZCULL_STATS3:
{
//Some kind of inverse value
if (current_zcull_stats.zpass_pixel_cnt > 0)
return 0;
synchronize_zcull_stats(true);
return (current_zcull_stats.zpass_pixel_cnt > 0) ? 0 : UINT16_MAX;
}
default:
LOG_ERROR(RSX, "Unknown zcull stat type %d", type);
return 0;
}
}
u32 GLGSRender::synchronize_zcull_stats(bool hard_sync)
{
if (!zcull_rendering_enabled || zcull_task_queue.pending == 0)
return 0;
u32 result = UINT16_MAX;
GLint count, status;
for (auto &query : zcull_task_queue.task_stack)
{
if (query == nullptr || query->active)
continue;
glGetQueryObjectiv(query->handle, GL_QUERY_RESULT_AVAILABLE, &status);
if (status == GL_FALSE && !hard_sync)
continue;
glGetQueryObjectiv(query->handle, GL_QUERY_RESULT, &count);
query->pending = false;
query = nullptr;
current_zcull_stats.zpass_pixel_cnt += count;
zcull_task_queue.pending--;
}
for (u32 i = 0; i < occlusion_query_count; ++i)
{
auto &query = occlusion_query_data[i];
if (!query.pending && !query.active)
{
result = i;
break;
}
}
if (result == UINT16_MAX && !hard_sync)
return synchronize_zcull_stats(true);
return result;
}
void GLGSRender::notify_zcull_info_changed()
{
check_zcull_status(false, false);
}
+12 -304
View File
@@ -19,8 +19,6 @@ 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;
using shader_cache = rsx::shaders_cache<void*, GLProgramBuffer>;
}
struct work_item
@@ -52,13 +50,12 @@ private:
gl::texture_cache m_gl_texture_cache;
gl::texture m_gl_persistent_stream_buffer;
gl::texture m_gl_volatile_stream_buffer;
gl::texture m_gl_attrib_buffers[rsx::limits::vertex_count];
std::unique_ptr<gl::ring_buffer> m_attrib_ring_buffer;
std::unique_ptr<gl::ring_buffer> m_fragment_constants_buffer;
std::unique_ptr<gl::ring_buffer> m_transform_constants_buffer;
std::unique_ptr<gl::ring_buffer> m_vertex_state_buffer;
std::unique_ptr<gl::ring_buffer> m_scale_offset_buffer;
std::unique_ptr<gl::ring_buffer> m_index_ring_buffer;
u32 m_draw_calls = 0;
@@ -68,7 +65,6 @@ private:
s64 m_textures_upload_time = 0;
std::unique_ptr<gl::vertex_cache> m_vertex_cache;
std::unique_ptr<gl::shader_cache> m_shaders_cache;
GLint m_min_texbuffer_alignment = 256;
GLint m_uniform_buffer_offset_align = 256;
@@ -87,6 +83,11 @@ private:
bool flush_draw_buffers = false;
bool m_last_draw_indexed;
GLenum m_last_ib_type;
size_t m_last_index_offset;
u32 m_last_vertex_count;
public:
gl::fbo draw_fbo;
@@ -100,306 +101,21 @@ private:
//vaos are mandatory for core profile
gl::vao m_vao;
//occlusion query
bool zcull_surface_active = false;
struct occlusion_query_info
{
GLuint handle;
GLint result;
GLint num_draws;
bool pending;
bool active;
};
struct
{
u32 zpass_pixel_cnt;
u32 zcull_stats;
u32 zcull_stats1;
u32 zcull_stats2;
u32 zcull_stats3;
void clear()
{
zpass_pixel_cnt = zcull_stats = zcull_stats1 = zcull_stats2 = zcull_stats3 = 0;
}
}
current_zcull_stats;
struct occlusion_task
{
std::vector<occlusion_query_info*> task_stack;
occlusion_query_info* active_query = nullptr;
u32 pending = 0;
//Add one query to the task
void add(occlusion_query_info* query)
{
active_query = query;
if (task_stack.size() > 0 && pending == 0)
task_stack.resize(0);
const auto empty_slots = task_stack.size() - pending;
if (empty_slots >= 4)
{
for (auto &_query : task_stack)
{
if (_query == nullptr)
{
_query = query;
pending++;
return;
}
}
}
task_stack.push_back(query);
pending++;
}
}
zcull_task_queue = {};
const u32 occlusion_query_count = 128;
std::array<occlusion_query_info, 128> occlusion_query_data = {};
public:
GLGSRender();
private:
struct
{
const u32 DEPTH_BOUNDS_MIN = 0xFFFF0001;
const u32 DEPTH_BOUNDS_MAX = 0xFFFF0002;
const u32 DEPTH_RANGE_MIN = 0xFFFF0003;
const u32 DEPTH_RANGE_MAX = 0xFFFF0004;
std::unordered_map<GLenum, u32> properties = {};
std::unordered_map<GLenum, std::array<u32, 4>> indexed_properties = {};
bool enable(u32 test, GLenum cap)
{
auto found = properties.find(cap);
if (found != properties.end() && found->second == test)
return !!test;
properties[cap] = test;
if (test)
glEnable(cap);
else
glDisable(cap);
return !!test;
}
bool enablei(u32 test, GLenum cap, u32 index)
{
auto found = indexed_properties.find(cap);
const bool exists = found != indexed_properties.end();
if (!exists)
{
indexed_properties[cap] = {};
indexed_properties[cap][index] = test;
}
else
{
if (found->second[index] == test)
return !!test;
found->second[index] = test;
}
if (test)
glEnablei(cap, index);
else
glDisablei(cap, index);
return !!test;
}
const bool test_property(GLenum property, u32 test) const
{
auto found = properties.find(property);
if (found == properties.end())
return false;
return (found->second == test);
}
void depth_func(GLenum func)
{
if (!test_property(GL_DEPTH_FUNC, func))
{
glDepthFunc(func);
properties[GL_DEPTH_FUNC] = func;
}
}
void depth_mask(GLboolean mask)
{
if (!test_property(GL_DEPTH_WRITEMASK, mask))
{
glDepthMask(mask);
properties[GL_DEPTH_WRITEMASK] = mask;
}
}
void clear_depth(GLfloat depth)
{
u32 value = (u32&)depth;
if (!test_property(GL_DEPTH_CLEAR_VALUE, value))
{
glClearDepth(depth);
properties[GL_DEPTH_CLEAR_VALUE] = value;
}
}
void stencil_mask(GLuint mask)
{
if (!test_property(GL_STENCIL_WRITEMASK, mask))
{
glStencilMask(mask);
properties[GL_STENCIL_WRITEMASK] = mask;
}
}
void clear_stencil(GLint stencil)
{
u32 value = (u32&)stencil;
if (!test_property(GL_STENCIL_CLEAR_VALUE, value))
{
glClearStencil(stencil);
properties[GL_STENCIL_CLEAR_VALUE] = value;
}
}
void color_mask(u32 mask)
{
if (!test_property(GL_COLOR_WRITEMASK, mask))
{
glColorMask(((mask & 0x20) ? 1 : 0), ((mask & 0x40) ? 1 : 0), ((mask & 0x80) ? 1 : 0), ((mask & 0x10) ? 1 : 0));
properties[GL_COLOR_WRITEMASK] = mask;
}
}
void color_mask(bool r, bool g, bool b, bool a)
{
u32 mask = 0;
if (r) mask |= 0x20;
if (g) mask |= 0x40;
if (b) mask |= 0x80;
if (a) mask |= 0x10;
color_mask(mask);
}
void clear_color(u8 r, u8 g, u8 b, u8 a)
{
u32 value = (u32)r | (u32)g << 8 | (u32)b << 16 | (u32)a << 24;
if (!test_property(GL_COLOR_CLEAR_VALUE, value))
{
glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
properties[GL_COLOR_CLEAR_VALUE] = value;
}
}
void depth_bounds(float min, float max)
{
u32 depth_min = (u32&)min;
u32 depth_max = (u32&)max;
if (!test_property(DEPTH_BOUNDS_MIN, depth_min) || !test_property(DEPTH_BOUNDS_MAX, depth_max))
{
glDepthBoundsEXT(min, max);
properties[DEPTH_BOUNDS_MIN] = depth_min;
properties[DEPTH_BOUNDS_MAX] = depth_max;
}
}
void depth_range(float min, float max)
{
u32 depth_min = (u32&)min;
u32 depth_max = (u32&)max;
if (!test_property(DEPTH_RANGE_MIN, depth_min) || !test_property(DEPTH_RANGE_MAX, depth_max))
{
glDepthRange(min, max);
properties[DEPTH_RANGE_MIN] = depth_min;
properties[DEPTH_RANGE_MAX] = depth_max;
}
}
void logic_op(GLenum op)
{
if (!test_property(GL_COLOR_LOGIC_OP, op))
{
glLogicOp(op);
properties[GL_COLOR_LOGIC_OP] = op;
}
}
void line_width(GLfloat width)
{
u32 value = (u32&)width;
if (!test_property(GL_LINE_WIDTH, value))
{
glLineWidth(width);
properties[GL_LINE_WIDTH] = value;
}
}
void front_face(GLenum face)
{
if (!test_property(GL_FRONT_FACE, face))
{
glFrontFace(face);
properties[GL_FRONT_FACE] = face;
}
}
void cull_face(GLenum mode)
{
if (!test_property(GL_CULL_FACE_MODE, mode))
{
glCullFace(mode);
properties[GL_CULL_FACE_MODE] = mode;
}
}
void polygon_offset(float factor, float units)
{
u32 _units = (u32&)units;
u32 _factor = (u32&)factor;
if (!test_property(GL_POLYGON_OFFSET_UNITS, _units) || !test_property(GL_POLYGON_OFFSET_FACTOR, _factor))
{
glPolygonOffset(factor, units);
properties[GL_POLYGON_OFFSET_UNITS] = _units;
properties[GL_POLYGON_OFFSET_FACTOR] = _factor;
}
}
}
gl_state;
static u32 enable(u32 enable, u32 cap);
static u32 enable(u32 enable, u32 cap, u32 index);
// Return element to draw and in case of indexed draw index type and offset in index buffer
std::tuple<u32, u32, u32, std::optional<std::tuple<GLenum, u32> > > set_vertex_buffer();
rsx::vertex_input_layout m_vertex_layout = {};
std::tuple<u32, std::optional<std::tuple<GLenum, u32> > > set_vertex_buffer();
void clear_surface(u32 arg);
void init_buffers(bool skip_reading = false);
bool check_program_state();
void load_program(u32 vertex_base, u32 vertex_count);
public:
bool load_program();
void init_buffers(bool skip_reading = false);
void read_buffers();
void write_buffers();
void set_viewport();
@@ -408,9 +124,6 @@ public:
work_item& post_flush_request(u32 address, gl::texture_cache::cached_texture_section *section);
bool scaled_image_from_memory(rsx::blit_src_info& src_info, rsx::blit_dst_info& dst_info, bool interpolate) override;
void check_zcull_status(bool framebuffer_swap, bool force_read);
u32 synchronize_zcull_stats(bool hard_sync = false);
protected:
void begin() override;
@@ -424,12 +137,7 @@ protected:
void do_local_task() override;
void notify_zcull_info_changed() override;
void clear_zcull_stats(u32 type) override;
u32 get_zcull_stats(u32 type) override;
bool on_access_violation(u32 address, bool is_writing) override;
void on_notify_memory_unmapped(u32 address_base, u32 size) override;
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() override;
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() override;
+2 -2
View File
@@ -19,7 +19,7 @@ namespace gl
case rsx::primitive_type::triangle_strip: return GL_TRIANGLE_STRIP;
case rsx::primitive_type::triangle_fan: return GL_TRIANGLE_FAN;
case rsx::primitive_type::quads: return GL_TRIANGLES;
case rsx::primitive_type::quad_strip: return GL_TRIANGLE_STRIP;
case rsx::primitive_type::quad_strip: return GL_TRIANGLES;
case rsx::primitive_type::polygon: return GL_TRIANGLES;
}
fmt::throw_exception("unknow primitive type" HERE);
@@ -543,9 +543,9 @@ namespace gl
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::quad_strip:
return true;
case rsx::primitive_type::quads:
case rsx::primitive_type::quad_strip:
case rsx::primitive_type::polygon:
return false;
}
+10 -16
View File
@@ -82,7 +82,6 @@ namespace gl
bool ARB_texture_barrier_supported = false;
bool NV_texture_barrier_supported = false;
bool initialized = false;
bool vendor_INTEL = false;
void initialize()
{
@@ -155,17 +154,8 @@ namespace gl
}
//Workaround for intel drivers which have terrible capability reporting
std::string vendor_string;
if (const char* raw_string = (const char*)glGetString(GL_VENDOR))
{
vendor_string = raw_string;
std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), ::tolower);
}
else
{
LOG_ERROR(RSX, "Failed to get vendor string from driver. Are we missing a context?");
vendor_string = "intel"; //lowest acceptable value
}
std::string vendor_string = (const char*)glGetString(GL_VENDOR);
std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), ::tolower);
if (vendor_string.find("intel") != std::string::npos)
{
@@ -175,8 +165,6 @@ namespace gl
glGetIntegerv(GL_MAJOR_VERSION, &version_major);
glGetIntegerv(GL_MINOR_VERSION, &version_minor);
vendor_INTEL = true;
//Texture buffers moved into core at GL 3.3
if (version_major > 3 || (version_major == 3 && version_minor >= 3))
ARB_texture_buffer_supported = true;
@@ -838,7 +826,7 @@ namespace gl
buffer::create();
glBindBuffer((GLenum)m_target, m_id);
glBufferStorage((GLenum)m_target, size, data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT);
glBufferStorage((GLenum)m_target, size, data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
m_memory_mapping = glMapBufferRange((GLenum)m_target, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
verify(HERE), m_memory_mapping != nullptr;
@@ -2046,6 +2034,12 @@ namespace gl
namespace glsl
{
enum program_domain
{
glsl_vertex_program = 0,
glsl_fragment_program = 1
};
class compilation_exception : public exception
{
public:
@@ -2544,7 +2538,7 @@ namespace gl
error_msg = buf.get();
}
LOG_ERROR(RSX, "Validation failed: %s", error_msg.c_str());
throw validation_exception(error_msg);
}
}
-9
View File
@@ -183,13 +183,6 @@ OPENGL_PROC(PFNGLSAMPLERPARAMETERIPROC, SamplerParameteri);
OPENGL_PROC(PFNGLSAMPLERPARAMETERFPROC, SamplerParameterf);
OPENGL_PROC(PFNGLSAMPLERPARAMETERFVPROC, SamplerParameterfv);
//Occlusion Query
OPENGL_PROC(PFNGLGENQUERIESPROC, GenQueries);
OPENGL_PROC(PFNGLDELETEQUERIESPROC, DeleteQueries);
OPENGL_PROC(PFNGLGETQUERYOBJECTIVPROC, GetQueryObjectiv);
OPENGL_PROC(PFNGLBEGINQUERYPROC, BeginQuery);
OPENGL_PROC(PFNGLENDQUERYPROC, EndQuery);
//Texture Buffers
OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT);
OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEPROC, TextureBufferRange);
@@ -219,8 +212,6 @@ OPENGL_PROC(PFNGLTEXTUREBARRIERPROC, TextureBarrier);
OPENGL_PROC(PFNGLTEXTUREBARRIERNVPROC, TextureBarrierNV);
//...
WGL_PROC(PFNWGLSWAPINTERVALEXTPROC, SwapIntervalEXT);
#if !defined(__GNUG__) || defined(__MINGW32__)
OPENGL_PROC(PFNGLBLENDCOLORPROC, BlendColor);
OPENGL_PROC(PFNGLBLENDEQUATIONPROC, BlendEquation);
+17 -32
View File
@@ -54,11 +54,24 @@ struct GLTraits
result.uniforms[location] = (i + rsx::limits::fragment_textures_count);
}
const int stream_buffer_start = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count;
//We use texture buffers for vertex attributes. Bind these here as well
//as they are guaranteed to be fixed (1 to 1 mapping)
std::array<const char*, 16> s_reg_table =
{
"in_pos_buffer", "in_weight_buffer", "in_normal_buffer",
"in_diff_color_buffer", "in_spec_color_buffer",
"in_fog_buffer",
"in_point_size_buffer", "in_7_buffer",
"in_tc0_buffer", "in_tc1_buffer", "in_tc2_buffer", "in_tc3_buffer",
"in_tc4_buffer", "in_tc5_buffer", "in_tc6_buffer", "in_tc7_buffer"
};
//Bind locations 0 and 1 to the stream buffers
result.uniforms[0] = stream_buffer_start;
result.uniforms[1] = stream_buffer_start + 1;
for (int i = 0; i < rsx::limits::vertex_count; ++i)
{
int location;
if (result.uniforms.has_location(s_reg_table[i], &location))
result.uniforms[location] = (i + rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count);
}
LOG_NOTICE(RSX, "*** prog id = %d", result.id());
LOG_NOTICE(RSX, "*** vp id = %d", vertexProgramData.id);
@@ -73,32 +86,4 @@ struct GLTraits
class GLProgramBuffer : public program_state_cache<GLTraits>
{
public:
u64 get_hash(void*&)
{
return 0;
}
u64 get_hash(RSXVertexProgram &prog)
{
return program_hash_util::vertex_program_hash()(prog);
}
u64 get_hash(RSXFragmentProgram &prog)
{
return program_hash_util::fragment_program_hash()(prog);
}
template <typename... Args>
void add_pipeline_entry(RSXVertexProgram &vp, RSXFragmentProgram &fp, void* &props, Args&& ...args)
{
vp.skip_vertex_input_check = true;
getGraphicPipelineState(vp, fp, props, std::forward<Args>(args)...);
}
bool check_cache_missed() const
{
return m_cache_miss_flag;
}
};
-3
View File
@@ -161,7 +161,6 @@ void GLGSRender::init_buffers(bool skip_reading)
synchronize_buffers();
m_rtts_dirty = false;
zcull_surface_active = false;
const u16 clip_horizontal = rsx::method_registers.surface_clip_width();
const u16 clip_vertical = rsx::method_registers.surface_clip_height();
@@ -246,8 +245,6 @@ void GLGSRender::init_buffers(bool skip_reading)
framebuffer_status_valid = draw_fbo.check();
if (!framebuffer_status_valid) return;
check_zcull_status(true, false);
draw_fbo.bind();
set_viewport();

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