Merge pull request #1062 from Nekotekina/master

SPURecompiler improved
This commit is contained in:
Hykem 2015-04-25 19:32:47 +01:00
commit d18d19870f
159 changed files with 5702 additions and 5951 deletions

View file

@ -2,7 +2,7 @@
#include "rpcs3/Ini.h" #include "rpcs3/Ini.h"
#include "AutoPause.h" #include "AutoPause.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "Emu/System.h" #include "Emu/System.h"
using namespace Debug; using namespace Debug;
@ -44,23 +44,22 @@ AutoPause::~AutoPause(void)
//This would be able to create in a GUI window. //This would be able to create in a GUI window.
void AutoPause::Reload(void) void AutoPause::Reload(void)
{ {
if (rExists("pause.bin")) if (fs::is_file("pause.bin"))
{ {
m_pause_function.clear(); m_pause_function.clear();
m_pause_function.reserve(16); m_pause_function.reserve(16);
m_pause_syscall.clear(); m_pause_syscall.clear();
m_pause_syscall.reserve(16); m_pause_syscall.reserve(16);
rFile list; fs::file list("pause.bin");
list.Open("pause.bin", rFile::read);
//System calls ID and Function calls ID are all u32 iirc. //System calls ID and Function calls ID are all u32 iirc.
u32 num; u32 num;
size_t fmax = list.Length(); size_t fmax = list.size();
size_t fcur = 0; size_t fcur = 0;
list.Seek(0); list.seek(0);
while (fcur <= fmax - sizeof(u32)) while (fcur <= fmax - sizeof(u32))
{ {
list.Read(&num, sizeof(u32)); list.read(&num, sizeof(u32));
fcur += sizeof(u32); fcur += sizeof(u32);
if (num == 0xFFFFFFFF) break; if (num == 0xFFFFFFFF) break;
@ -77,12 +76,8 @@ void AutoPause::Reload(void)
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num); LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num);
} }
} }
list.Close();
}
else
{
LOG_WARNING(HLE, "No pause.bin found, Auto Pause will not work.");
} }
m_pause_syscall_enable = Ini.DBGAutoPauseSystemCall.GetValue(); m_pause_syscall_enable = Ini.DBGAutoPauseSystemCall.GetValue();
m_pause_function_enable = Ini.DBGAutoPauseFunctionCall.GetValue(); m_pause_function_enable = Ini.DBGAutoPauseFunctionCall.GetValue();
initialized = true; initialized = true;

View file

@ -879,90 +879,6 @@ template<typename T, typename T1, T1 value> struct _se<be_t<T>, T1, value> : pub
#define se32(x) _se<u32, decltype(x), x>::value #define se32(x) _se<u32, decltype(x), x>::value
#define se64(x) _se<u64, decltype(x), x>::value #define se64(x) _se<u64, decltype(x), x>::value
template<typename T> __forceinline u8 Read8(T& f)
{
u8 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u16 Read16(T& f)
{
be_t<u16> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u32 Read32(T& f)
{
be_t<u32> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u64 Read64(T& f)
{
be_t<u64> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u16 Read16LE(T& f)
{
u16 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u32 Read32LE(T& f)
{
u32 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline u64 Read64LE(T& f)
{
u64 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline void Write8(T& f, const u8 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline void Write16LE(T& f, const u16 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline void Write32LE(T& f, const u32 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline void Write64LE(T& f, const u64 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline void Write16(T& f, const u16 data)
{
Write16LE(f, re16(data));
}
template<typename T> __forceinline void Write32(T& f, const u32 data)
{
Write32LE(f, re32(data));
}
template<typename T> __forceinline void Write64(T& f, const u64 data)
{
Write64LE(f, re64(data));
}
template<typename Tto, typename Tfrom> template<typename Tto, typename Tfrom>
struct convert_le_be_t struct convert_le_be_t
{ {

672
Utilities/File.cpp Normal file
View file

@ -0,0 +1,672 @@
#include "stdafx.h"
#include "Log.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/dir.h>")
#pragma warning(disable : 4996)
#include <wx/dir.h>
#pragma warning(pop)
#include "File.h"
#ifdef _WIN32
#include <Windows.h>
#define GET_API_ERROR static_cast<u64>(GetLastError())
std::unique_ptr<wchar_t[]> ConvertUTF8ToWChar(const std::string& source)
{
const size_t length = source.size() + 1; // size + null terminator
const int size = source.size() < INT_MAX ? static_cast<int>(length) : throw std::length_error(__FUNCTION__);
std::unique_ptr<wchar_t[]> buffer(new wchar_t[length]); // allocate buffer assuming that length is the max possible size
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
{
LOG_ERROR(GENERAL, "ConvertUTF8ToWChar(source='%s') failed: 0x%llx", source, GET_API_ERROR);
}
return buffer;
}
time_t to_time_t(const ULARGE_INTEGER& ft)
{
return ft.QuadPart / 10000000ULL - 11644473600ULL;
}
time_t to_time_t(const LARGE_INTEGER& ft)
{
ULARGE_INTEGER v;
v.LowPart = ft.LowPart;
v.HighPart = ft.HighPart;
return to_time_t(v);
}
time_t to_time_t(const FILETIME& ft)
{
ULARGE_INTEGER v;
v.LowPart = ft.dwLowDateTime;
v.HighPart = ft.dwHighDateTime;
return to_time_t(v);
}
bool truncate_file(const std::string& file, uint64_t length)
{
// open the file
const auto handle = CreateFileW(ConvertUTF8ToWChar(file).get(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
return false;
}
LARGE_INTEGER distance;
distance.QuadPart = length;
// seek and truncate
if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN) || !SetEndOfFile(handle))
{
const auto error = GetLastError();
CloseHandle(handle);
SetLastError(error);
return false;
}
return CloseHandle(handle);
}
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <copyfile.h>
#else
#include <sys/sendfile.h>
#endif
#include "errno.h"
#define GET_API_ERROR static_cast<u64>(errno)
#endif
bool fs::stat(const std::string& path, stat_t& info)
{
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(ConvertUTF8ToWChar(path).get(), GetFileExInfoStandard, &attrs))
{
info = {};
return false;
}
info.exists = true;
info.is_directory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
info.is_writable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
info.atime = to_time_t(attrs.ftLastAccessTime);
info.mtime = to_time_t(attrs.ftLastWriteTime);
info.ctime = to_time_t(attrs.ftCreationTime);
#else
struct stat64 file_info;
if (stat64(path.c_str(), &file_info) < 0)
{
info = {};
return false;
}
info.exists = true;
info.is_directory = S_ISDIR(file_info.st_mode);
info.is_writable = file_info.st_mode & 0200; // HACK: approximation
info.size = file_info.st_size;
info.atime = file_info.st_atime;
info.mtime = file_info.st_mtime;
info.ctime = file_info.st_ctime;
#endif
return true;
}
bool fs::exists(const std::string& path)
{
#ifdef _WIN32
return GetFileAttributesW(ConvertUTF8ToWChar(path).get()) != 0xFFFFFFFF;
#else
struct stat buffer;
return stat(path.c_str(), &buffer) == 0;
#endif
}
bool fs::is_file(const std::string& file)
{
#ifdef _WIN32
DWORD attrs;
if ((attrs = GetFileAttributesW(ConvertUTF8ToWChar(file).get())) == INVALID_FILE_ATTRIBUTES)
{
return false;
}
return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0;
#else
struct stat64 file_info;
if (stat64(file.c_str(), &file_info) < 0)
{
return false;
}
return !S_ISDIR(file_info.st_mode);
#endif
}
bool fs::is_dir(const std::string& dir)
{
#ifdef _WIN32
DWORD attrs;
if ((attrs = GetFileAttributesW(ConvertUTF8ToWChar(dir).get())) == INVALID_FILE_ATTRIBUTES)
{
return false;
}
return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
#else
struct stat64 file_info;
if (stat64(dir.c_str(), &file_info) < 0)
{
return false;
}
return S_ISDIR(file_info.st_mode);
#endif
}
bool fs::create_dir(const std::string& dir)
{
#ifdef _WIN32
if (!CreateDirectoryW(ConvertUTF8ToWChar(dir).get(), NULL))
#else
if (mkdir(dir.c_str(), 0777))
#endif
{
LOG_WARNING(GENERAL, "Error creating directory '%s': 0x%llx", dir, GET_API_ERROR);
return false;
}
return true;
}
bool fs::create_path(const std::string& path)
{
size_t start = 0;
while (true)
{
// maybe it could be more optimal if goes from the end recursively
size_t pos = path.find_first_of("/\\", start);
if (pos == std::string::npos)
{
pos = path.length();
}
std::string dir = path.substr(0, pos);
start = ++pos;
if (dir.size() == 0)
{
continue;
}
if (!is_dir(dir))
{
// if doesn't exist or not a dir
if (!create_dir(dir))
{
// if creating failed
return false;
}
}
if (pos >= path.length())
{
break;
}
}
return true;
}
bool fs::remove_dir(const std::string& dir)
{
#ifdef _WIN32
if (!RemoveDirectoryW(ConvertUTF8ToWChar(dir).get()))
#else
if (rmdir(dir.c_str()))
#endif
{
LOG_WARNING(GENERAL, "Error deleting directory '%s': 0x%llx", dir, GET_API_ERROR);
return false;
}
return true;
}
bool fs::rename(const std::string& from, const std::string& to)
{
// TODO: Deal with case-sensitivity
#ifdef _WIN32
if (!MoveFileW(ConvertUTF8ToWChar(from).get(), ConvertUTF8ToWChar(to).get()))
#else
if (rename(from.c_str(), to.c_str()))
#endif
{
LOG_WARNING(GENERAL, "Error renaming '%s' to '%s': 0x%llx", from, to, GET_API_ERROR);
return false;
}
return true;
}
#ifndef _WIN32
int OSCopyFile(const char* source, const char* destination, bool overwrite)
{
/* This function was taken from http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c */
int input, output;
if ((input = open(source, O_RDONLY)) == -1)
{
return -1;
}
if ((output = open(destination, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0666)) == -1)
{
close(input);
return -1;
}
//Here we use kernel-space copying for performance reasons
#if defined(__APPLE__) || defined(__FreeBSD__)
//fcopyfile works on FreeBSD and OS X 10.5+
int result = fcopyfile(input, output, 0, COPYFILE_ALL);
#else
//sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytesCopied = 0;
struct stat fileinfo = { 0 };
fstat(input, &fileinfo);
int result = sendfile(output, input, &bytesCopied, fileinfo.st_size) == -1 ? -1 : 0;
#endif
close(input);
close(output);
return result;
}
#endif
bool fs::copy_file(const std::string& from, const std::string& to, bool overwrite)
{
#ifdef _WIN32
if (!CopyFileW(ConvertUTF8ToWChar(from).get(), ConvertUTF8ToWChar(to).get(), !overwrite))
#else
if (OSCopyFile(from.c_str(), to.c_str(), overwrite))
#endif
{
LOG_WARNING(GENERAL, "Error copying '%s' to '%s': 0x%llx", from, to, GET_API_ERROR);
return false;
}
return true;
}
bool fs::remove_file(const std::string& file)
{
#ifdef _WIN32
if (!DeleteFileW(ConvertUTF8ToWChar(file).get()))
#else
if (unlink(file.c_str()))
#endif
{
LOG_WARNING(GENERAL, "Error deleting file '%s': 0x%llx", file, GET_API_ERROR);
return false;
}
return true;
}
bool fs::truncate_file(const std::string& file, uint64_t length)
{
#ifdef _WIN32
if (!::truncate_file(file, length))
#else
if (truncate64(file.c_str(), length))
#endif
{
LOG_WARNING(GENERAL, "Error resizing file '%s' to 0x%llx: 0x%llx", file, length, GET_API_ERROR);
return false;
}
return true;
}
fs::file::file()
#ifdef _WIN32
: fd(INVALID_HANDLE_VALUE)
#else
: fd(-1)
#endif
{
}
fs::file::~file()
{
#ifdef _WIN32
if (fd != INVALID_HANDLE_VALUE)
{
CloseHandle(fd);
}
#else
if (fd != -1)
{
::close(fd);
}
#endif
}
fs::file::file(const std::string& filename, u32 mode)
#ifdef _WIN32
: fd(INVALID_HANDLE_VALUE)
#else
: fd(-1)
#endif
{
open(filename, mode);
}
fs::file::operator bool() const
{
#ifdef _WIN32
return fd != INVALID_HANDLE_VALUE;
#else
return fd != -1;
#endif
}
void fs::file::import(handle_type handle)
{
this->~file();
fd = handle;
}
bool fs::file::open(const std::string& filename, u32 mode)
{
this->~file();
#ifdef _WIN32
DWORD access = 0;
switch (mode & (o_read | o_write | o_append))
{
case o_read: access |= GENERIC_READ; break;
case o_read | o_append: access |= GENERIC_READ; break;
case o_write: access |= GENERIC_WRITE; break;
case o_write | o_append: access |= FILE_APPEND_DATA; break;
case o_read | o_write: access |= GENERIC_READ | GENERIC_WRITE; break;
case o_read | o_write | o_append: access |= GENERIC_READ | FILE_APPEND_DATA; break;
default:
{
LOG_ERROR(GENERAL, "fs::file::open('%s') failed: neither o_read nor o_write specified (0x%x)", filename, mode);
return false;
}
}
DWORD disp = 0;
switch (mode & (o_create | o_trunc | o_excl))
{
case 0: disp = OPEN_EXISTING; break;
case o_create: disp = OPEN_ALWAYS; break;
case o_trunc: disp = TRUNCATE_EXISTING; break;
case o_create | o_trunc: disp = CREATE_ALWAYS; break;
case o_create | o_excl: disp = CREATE_NEW; break;
case o_create | o_excl | o_trunc: disp = CREATE_NEW; break;
}
if (!disp || (mode & ~(o_read | o_write | o_append | o_create | o_trunc | o_excl)))
{
LOG_ERROR(GENERAL, "fs::file::open('%s') failed: unknown mode specified (0x%x)", filename, mode);
return false;
}
if ((fd = CreateFileW(ConvertUTF8ToWChar(filename).get(), access, FILE_SHARE_READ, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
#else
int flags = 0;
switch (mode & (o_read | o_write))
{
case o_read: flags |= O_RDONLY; break;
case o_write: flags |= O_WRONLY; break;
case o_read | o_write: flags |= O_RDWR; break;
default:
{
LOG_ERROR(GENERAL, "fs::file::open('%s') failed: neither o_read nor o_write specified (0x%x)", filename, mode);
return false;
}
}
if (mode & o_append) flags |= O_APPEND;
if (mode & o_create) flags |= O_CREAT;
if (mode & o_trunc) flags |= O_TRUNC;
if (mode & o_excl) flags |= O_EXCL;
if (((mode & o_excl) && !(mode & o_create)) || (mode & ~(o_read | o_write | o_append | o_create | o_trunc | o_excl)))
{
LOG_ERROR(GENERAL, "fs::file::open('%s') failed: unknown mode specified (0x%x)", filename, mode);
return false;
}
if ((fd = ::open(filename.c_str(), flags, 0666)) == -1)
#endif
{
LOG_WARNING(GENERAL, "fs::file::open('%s', 0x%x) failed: error 0x%llx", filename, mode, GET_API_ERROR);
return false;
}
return true;
}
bool fs::file::is_opened() const
{
return *this;
}
bool fs::file::trunc(u64 size) const
{
#ifdef _WIN32
LARGE_INTEGER old, pos;
pos.QuadPart = 0;
SetFilePointerEx(fd, pos, &old, FILE_CURRENT); // get old position
pos.QuadPart = size;
SetFilePointerEx(fd, pos, NULL, FILE_BEGIN); // set new position
SetEndOfFile(fd); // change file size
SetFilePointerEx(fd, old, NULL, FILE_BEGIN); // restore position
return true; // TODO
#else
return !ftruncate64(fd, size);
#endif
}
bool fs::file::stat(stat_t& info) const
{
#ifdef _WIN32
FILE_BASIC_INFO basic_info;
//FILE_NAME_INFO name_info;
if (!GetFileInformationByHandleEx(fd, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
{
info = {};
return false;
}
info.exists = true;
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
info.is_writable = (basic_info.FileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
info.size = this->size();
info.atime = to_time_t(basic_info.LastAccessTime);
info.mtime = to_time_t(basic_info.ChangeTime);
info.ctime = to_time_t(basic_info.CreationTime);
#else
struct stat64 file_info;
if (fstat64(fd, &file_info) < 0)
{
info = {};
return false;
}
info.exists = true;
info.is_directory = S_ISDIR(file_info.st_mode);
info.is_writable = file_info.st_mode & 0200; // HACK: approximation
info.size = file_info.st_size;
info.atime = file_info.st_atime;
info.mtime = file_info.st_mtime;
info.ctime = file_info.st_ctime;
#endif
return true;
}
bool fs::file::close()
{
#ifdef _WIN32
if (CloseHandle(fd))
{
return true;
}
fd = INVALID_HANDLE_VALUE;
#else
if (!::close(fd))
{
return true;
}
fd = -1;
#endif
return false;
}
u64 fs::file::read(void* buffer, u64 count) const
{
#ifdef _WIN32
DWORD nread;
if (!ReadFile(fd, buffer, count, &nread, NULL))
{
return -1;
}
return nread;
#else
return ::read(fd, buffer, count);
#endif
}
u64 fs::file::write(const void* buffer, u64 count) const
{
#ifdef _WIN32
DWORD nwritten;
if (!WriteFile(fd, buffer, count, &nwritten, NULL))
{
return -1;
}
return nwritten;
#else
return ::write(fd, buffer, count);
#endif
}
u64 fs::file::seek(u64 offset, u32 mode) const
{
assert(mode < 3);
#ifdef _WIN32
LARGE_INTEGER pos;
pos.QuadPart = offset;
if (!SetFilePointerEx(fd, pos, &pos, mode))
{
return -1;
}
return pos.QuadPart;
#else
return lseek64(fd, offset, mode);
#endif
}
u64 fs::file::size() const
{
#ifdef _WIN32
LARGE_INTEGER size;
if (!GetFileSizeEx(fd, &size))
{
return -1;
}
return size.QuadPart;
#else
struct stat64 file_info;
if (fstat64(fd, &file_info) < 0)
{
return -1;
}
return file_info.st_size;
#endif
}
rDir::rDir()
{
handle = reinterpret_cast<void*>(new wxDir());
}
rDir::~rDir()
{
delete reinterpret_cast<wxDir*>(handle);
}
rDir::rDir(const std::string &path)
{
handle = reinterpret_cast<void*>(new wxDir(fmt::FromUTF8(path)));
}
bool rDir::Open(const std::string& path)
{
return reinterpret_cast<wxDir*>(handle)->Open(fmt::FromUTF8(path));
}
bool rDir::IsOpened() const
{
return reinterpret_cast<wxDir*>(handle)->IsOpened();
}
bool rDir::GetFirst(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetFirst(&str);
*filename = str.ToStdString();
return res;
}
bool rDir::GetNext(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetNext(&str);
*filename = str.ToStdString();
return res;
}

97
Utilities/File.h Normal file
View file

@ -0,0 +1,97 @@
#pragma once
enum file_seek_mode : u32
{
from_begin,
from_cur,
from_end,
};
enum file_open_mode : u32
{
o_read = 1 << 0,
o_write = 1 << 1,
o_append = 1 << 2,
o_create = 1 << 3,
o_trunc = 1 << 4,
o_excl = 1 << 5,
};
namespace fs
{
struct stat_t
{
bool exists;
bool is_directory;
bool is_writable;
uint64_t size;
time_t atime;
time_t mtime;
time_t ctime;
};
bool stat(const std::string& path, stat_t& info);
bool exists(const std::string& path);
bool is_file(const std::string& file);
bool is_dir(const std::string& dir);
bool remove_dir(const std::string& dir);
bool create_dir(const std::string& dir);
bool create_path(const std::string& path);
bool rename(const std::string& from, const std::string& to);
bool copy_file(const std::string& from, const std::string& to, bool overwrite);
bool remove_file(const std::string& file);
bool truncate_file(const std::string& file, uint64_t length);
struct file final
{
#ifdef _WIN32
using handle_type = void*;
#else
using handle_type = intptr_t;
#endif
private:
handle_type fd;
public:
file();
~file();
explicit file(const std::string& filename, u32 mode = o_read);
file(const file&) = delete;
file(file&&) = delete; // possibly TODO
file& operator =(const file&) = delete;
file& operator =(file&&) = delete; // possibly TODO
operator bool() const; // check is_opened()
void import(handle_type fd); // replace file handle
bool open(const std::string& filename, u32 mode = o_read);
bool is_opened() const; // check whether the file is opened
bool trunc(u64 size) const; // change file size (possibly appending zero bytes)
bool stat(stat_t& info) const; // get file info
bool close();
u64 read(void* buffer, u64 count) const;
u64 write(const void* buffer, u64 count) const;
u64 seek(u64 offset, u32 mode = from_begin) const;
u64 size() const;
};
}
struct rDir
{
rDir();
~rDir();
rDir(const rDir& other) = delete;
rDir(const std::string &path);
bool Open(const std::string& path);
bool IsOpened() const;
static bool Exists(const std::string &path);
bool GetFirst(std::string *filename) const;
bool GetNext(std::string *filename) const;
void *handle;
};

View file

@ -5,11 +5,11 @@
#include <iostream> #include <iostream>
#include <cinttypes> #include <cinttypes>
#include "Thread.h" #include "Thread.h"
#include "rFile.h" #include "File.h"
using namespace Log; using namespace Log;
LogManager *gLogManager = nullptr; std::unique_ptr<LogManager> g_log_manager;
u32 LogMessage::size() const u32 LogMessage::size() const
{ {
@ -90,14 +90,14 @@ struct CoutListener : LogListener
struct FileListener : LogListener struct FileListener : LogListener
{ {
rFile mFile; fs::file mFile;
bool mPrependChannelName; bool mPrependChannelName;
FileListener(const std::string& name = _PRGNAME_, bool prependChannel = true) FileListener(const std::string& name = _PRGNAME_, bool prependChannel = true)
: mFile(std::string(rPlatform::getConfigDir() + name + ".log").c_str(), rFile::write), : mFile(rPlatform::getConfigDir() + name + ".log", o_write | o_create | o_trunc)
mPrependChannelName(prependChannel) , mPrependChannelName(prependChannel)
{ {
if (!mFile.IsOpened()) if (!mFile)
{ {
rMessageBox("Can't create log file! (" + name + ".log)", "Error", rICON_ERROR); rMessageBox("Can't create log file! (" + name + ".log)", "Error", rICON_ERROR);
} }
@ -119,7 +119,8 @@ struct FileListener : LogListener
} }
} }
} }
mFile.Write(text);
mFile.write(text.c_str(), text.size());
} }
}; };
@ -223,6 +224,7 @@ void LogManager::addListener(std::shared_ptr<LogListener> listener)
channel.addListener(listener); channel.addListener(listener);
} }
} }
void LogManager::removeListener(std::shared_ptr<LogListener> listener) void LogManager::removeListener(std::shared_ptr<LogListener> listener)
{ {
for (auto& channel : mChannels) for (auto& channel : mChannels)
@ -233,12 +235,14 @@ void LogManager::removeListener(std::shared_ptr<LogListener> listener)
LogManager& LogManager::getInstance() LogManager& LogManager::getInstance()
{ {
if (!gLogManager) if (!g_log_manager)
{ {
gLogManager = new LogManager(); g_log_manager.reset(new LogManager());
} }
return *gLogManager;
return *g_log_manager;
} }
LogChannel &LogManager::getChannel(LogType type) LogChannel &LogManager::getChannel(LogType type)
{ {
return mChannels[static_cast<u32>(type)]; return mChannels[static_cast<u32>(type)];
@ -251,9 +255,22 @@ void log_message(Log::LogType type, Log::LogSeverity sev, const char* text)
void log_message(Log::LogType type, Log::LogSeverity sev, std::string text) void log_message(Log::LogType type, Log::LogSeverity sev, std::string text)
{ {
//another msvc bug makes this not work, uncomment this and delete everything else in this function when it's fixed if (g_log_manager)
//Log::LogManager::getInstance().log({logType, severity, text}) {
// another msvc bug makes this not work, uncomment this when it's fixed
Log::LogMessage msg{ type, sev, std::move(text) }; //g_log_manager->log({logType, severity, text});
Log::LogManager::getInstance().log(msg); Log::LogMessage msg{ type, sev, std::move(text) };
g_log_manager->log(msg);
}
else
{
rMessageBox(text,
sev == Notice ? "Notice" :
sev == Warning ? "Warning" :
sev == Success ? "Success" :
sev == Error ? "Error" : "Unknown",
sev == Notice ? rICON_INFORMATION :
sev == Warning ? rICON_EXCLAMATION :
sev == Error ? rICON_ERROR : rICON_INFORMATION);
}
} }

View file

@ -1,5 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/string.h>")
#pragma warning(disable : 4996)
#include <wx/string.h> #include <wx/string.h>
#pragma warning(pop)
std::string u128::to_hex() const std::string u128::to_hex() const
{ {
@ -218,7 +222,7 @@ std::string fmt::merge(std::vector<std::string> source, const std::string& separ
result += source[i] + separator; result += source[i] + separator;
} }
return result + source[source.size() - 1]; return result + source.back();
} }
std::string fmt::merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator) std::string fmt::merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator)

View file

@ -48,47 +48,47 @@ namespace fmt
// the stream `os`. Then write `arg` to to the stream. If there's no // the stream `os`. Then write `arg` to to the stream. If there's no
// `fmt::placeholder` after `pos` everything in `fmt` after pos is written // `fmt::placeholder` after `pos` everything in `fmt` after pos is written
// to `os`. Then `arg` is written to `os` after appending a space character // to `os`. Then `arg` is written to `os` after appending a space character
template<typename T> //template<typename T>
empty_t write(const std::string &fmt, std::ostream &os, std::string::size_type &pos, T &&arg) //empty_t write(const std::string &fmt, std::ostream &os, std::string::size_type &pos, T &&arg)
{ //{
std::string::size_type ins = fmt.find(placeholder, pos); // std::string::size_type ins = fmt.find(placeholder, pos);
if (ins == std::string::npos) // if (ins == std::string::npos)
{ // {
os.write(fmt.data() + pos, fmt.size() - pos); // os.write(fmt.data() + pos, fmt.size() - pos);
os << ' ' << arg; // os << ' ' << arg;
pos = fmt.size(); // pos = fmt.size();
} // }
else // else
{ // {
os.write(fmt.data() + pos, ins - pos); // os.write(fmt.data() + pos, ins - pos);
os << arg; // os << arg;
pos = ins + placeholder.size(); // pos = ins + placeholder.size();
} // }
return{}; // return{};
} //}
// typesafe version of a sprintf-like function. Returns the printed to // typesafe version of a sprintf-like function. Returns the printed to
// string. To mark positions where the arguments are supposed to be // string. To mark positions where the arguments are supposed to be
// inserted use `fmt::placeholder`. If there's not enough placeholders // inserted use `fmt::placeholder`. If there's not enough placeholders
// the rest of the arguments are appended at the end, seperated by spaces // the rest of the arguments are appended at the end, seperated by spaces
template<typename ... Args> //template<typename ... Args>
std::string SFormat(const std::string &fmt, Args&& ... parameters) //std::string SFormat(const std::string &fmt, Args&& ... parameters)
{ //{
std::ostringstream os; // std::ostringstream os;
std::string::size_type pos = 0; // std::string::size_type pos = 0;
std::initializer_list<empty_t> { write(fmt, os, pos, parameters)... }; // std::initializer_list<empty_t> { write(fmt, os, pos, parameters)... };
if (!fmt.empty()) // if (!fmt.empty())
{ // {
os.write(fmt.data() + pos, fmt.size() - pos); // os.write(fmt.data() + pos, fmt.size() - pos);
} // }
std::string result = os.str(); // std::string result = os.str();
return result; // return result;
} //}
//small wrapper used to deal with bitfields //small wrapper used to deal with bitfields
template<typename T> template<typename T>

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
static std::thread::id main_thread;
class NamedThreadBase class NamedThreadBase
{ {
std::string m_name; std::string m_name;

View file

@ -1,414 +0,0 @@
#include "stdafx.h"
#include "Log.h"
#pragma warning(disable : 4996)
#include <wx/dir.h>
#include <wx/file.h>
#include <wx/filename.h>
#include "rFile.h"
#include "errno.h"
#ifdef _WIN32
#include <Windows.h>
// Maybe in StrFmt?
std::wstring ConvertUTF8ToWString(const std::string &source) {
int len = (int)source.size();
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
std::wstring str;
str.resize(size);
if (size > 0) {
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
}
return str;
}
#endif
#ifdef _WIN32
#define GET_API_ERROR GetLastError()
#else
#define GET_API_ERROR errno
#endif
bool getFileInfo(const char *path, FileInfo *fileInfo) {
// TODO: Expand relative paths?
fileInfo->fullName = path;
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) {
fileInfo->size = 0;
fileInfo->isDirectory = false;
fileInfo->exists = false;
return false;
}
fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
fileInfo->exists = true;
#else
struct stat64 file_info;
int result = stat64(path, &file_info);
if (result < 0) {
LOG_NOTICE(GENERAL, "IsDirectory: stat failed on %s", path);
fileInfo->exists = false;
return false;
}
fileInfo->isDirectory = S_ISDIR(file_info.st_mode);
fileInfo->isWritable = false;
fileInfo->size = file_info.st_size;
fileInfo->exists = true;
// HACK: approximation
if (file_info.st_mode & 0200)
fileInfo->isWritable = true;
#endif
return true;
}
bool rIsDir(const std::string &filename) {
FileInfo info;
getFileInfo(filename.c_str(), &info);
return info.isDirectory;
}
bool rMkdir(const std::string &dir)
{
#ifdef _WIN32
return !_mkdir(dir.c_str());
#else
return !mkdir(dir.c_str(), 0777);
#endif
}
bool rMkpath(const std::string &path)
{
size_t start=0, pos;
std::string dir;
bool ret;
while (true) {
if ((pos = path.find_first_of("/\\", start)) == std::string::npos)
pos = path.length();
dir = path.substr(0,pos++);
start = pos;
if(dir.size() == 0)
continue;
#ifdef _WIN32
if((ret = _mkdir(dir.c_str()) != 0) && errno != EEXIST){
#else
if((ret = mkdir(dir.c_str(), 0777) != 0) && errno != EEXIST){
#endif
return !ret;
}
if (pos >= path.length())
return true;
}
return true;
}
bool rRmdir(const std::string &dir)
{
#ifdef _WIN32
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str()))
#else
if (rmdir(dir.c_str()))
#endif
{
LOG_ERROR(GENERAL, "Error deleting directory %s: 0x%llx", dir.c_str(), (u64)GET_API_ERROR);
return false;
}
return true;
}
bool rRename(const std::string &from, const std::string &to)
{
// TODO: Deal with case-sensitivity
#ifdef _WIN32
if (!MoveFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str()))
#else
if (int err = rename(from.c_str(), to.c_str()))
#endif
{
LOG_ERROR(GENERAL, "Error renaming '%s' to '%s': 0x%llx", from.c_str(), to.c_str(), (u64)GET_API_ERROR);
return false;
}
return true;
}
bool rExists(const std::string &file)
{
#ifdef _WIN32
std::wstring wstr = ConvertUTF8ToWString(file);
return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF;
#else
struct stat buffer;
return (stat (file.c_str(), &buffer) == 0);
#endif
}
bool rRemoveFile(const std::string &file)
{
#ifdef _WIN32
if (!DeleteFile(ConvertUTF8ToWString(file).c_str()))
#else
if (unlink(file.c_str()))
#endif
{
LOG_ERROR(GENERAL, "Error deleting file %s: 0x%llx", file.c_str(), (u64)GET_API_ERROR);
return false;
}
return true;
}
wxFile::OpenMode convertOpenMode(rFile::OpenMode open)
{
wxFile::OpenMode mode;
switch (open)
{
case rFile::read:
mode = wxFile::read;
break;
case rFile::write:
mode = wxFile::write;
break;
case rFile::read_write:
mode = wxFile::read_write;
break;
case rFile::write_append:
mode = wxFile::write_append;
break;
case rFile::write_excl:
mode = wxFile::write_excl;
break;
}
return mode;
}
rFile::OpenMode rConvertOpenMode(wxFile::OpenMode open)
{
rFile::OpenMode mode;
switch (open)
{
case wxFile::read:
mode = rFile::read;
break;
case wxFile::write:
mode = rFile::write;
break;
case wxFile::read_write:
mode = rFile::read_write;
break;
case wxFile::write_append:
mode = rFile::write_append;
break;
case wxFile::write_excl:
mode = rFile::write_excl;
break;
}
return mode;
}
wxSeekMode convertSeekMode(rSeekMode mode)
{
wxSeekMode ret;
switch (mode)
{
case rFromStart:
ret = wxFromStart;
break;
case rFromCurrent:
ret = wxFromCurrent;
break;
case rFromEnd:
ret = wxFromEnd;
break;
}
return ret;
}
rSeekMode rConvertSeekMode(wxSeekMode mode)
{
rSeekMode ret;
switch (mode)
{
case wxFromStart:
ret = rFromStart;
break;
case wxFromCurrent:
ret = rFromCurrent;
break;
case wxFromEnd:
ret = rFromEnd;
break;
}
return ret;
}
rFile::rFile()
{
handle = reinterpret_cast<void*>(new wxFile());
}
rFile::rFile(const std::string& filename, rFile::OpenMode open)
{
handle = reinterpret_cast<void*>(new wxFile(fmt::FromUTF8(filename), convertOpenMode(open)));
}
rFile::rFile(int fd)
{
handle = reinterpret_cast<void*>(new wxFile(fd));
}
rFile::~rFile()
{
delete reinterpret_cast<wxFile*>(handle);
}
bool rFile::Access(const std::string &filename, rFile::OpenMode mode)
{
return wxFile::Access(fmt::FromUTF8(filename), convertOpenMode(mode));
}
size_t rFile::Write(const void *buffer, size_t count)
{
return reinterpret_cast<wxFile*>(handle)->Write(buffer,count);
}
bool rFile::Write(const std::string &text)
{
return reinterpret_cast<wxFile*>(handle)->Write(reinterpret_cast<const void*>(text.c_str()),text.size()) != 0;
}
bool rFile::Close()
{
return reinterpret_cast<wxFile*>(handle)->Close();
}
bool rFile::Create(const std::string &filename, bool overwrite, int access)
{
return reinterpret_cast<wxFile*>(handle)->Create(fmt::FromUTF8(filename), overwrite, access);
}
bool rFile::Open(const std::string &filename, rFile::OpenMode mode, int access)
{
return reinterpret_cast<wxFile*>(handle)->Open(fmt::FromUTF8(filename), convertOpenMode(mode), access);
}
bool rFile::IsOpened() const
{
return reinterpret_cast<wxFile*>(handle)->IsOpened();
}
size_t rFile::Length() const
{
return reinterpret_cast<wxFile*>(handle)->Length();
}
size_t rFile::Read(void *buffer, size_t count)
{
return reinterpret_cast<wxFile*>(handle)->Read(buffer,count);
}
size_t rFile::Seek(size_t ofs, rSeekMode mode)
{
return reinterpret_cast<wxFile*>(handle)->Seek(ofs, convertSeekMode(mode));
}
size_t rFile::Tell() const
{
return reinterpret_cast<wxFile*>(handle)->Tell();
}
rDir::rDir()
{
handle = reinterpret_cast<void*>(new wxDir());
}
rDir::~rDir()
{
delete reinterpret_cast<wxDir*>(handle);
}
rDir::rDir(const std::string &path)
{
handle = reinterpret_cast<void*>(new wxDir(fmt::FromUTF8(path)));
}
bool rDir::Open(const std::string& path)
{
return reinterpret_cast<wxDir*>(handle)->Open(fmt::FromUTF8(path));
}
bool rDir::IsOpened() const
{
return reinterpret_cast<wxDir*>(handle)->IsOpened();
}
bool rDir::GetFirst(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetFirst(&str);
*filename = str.ToStdString();
return res;
}
bool rDir::GetNext(std::string *filename) const
{
wxString str;
bool res;
res = reinterpret_cast<wxDir*>(handle)->GetNext(&str);
*filename = str.ToStdString();
return res;
}
rFileName::rFileName()
{
handle = reinterpret_cast<void*>(new wxFileName());
}
rFileName::~rFileName()
{
delete reinterpret_cast<wxFileName*>(handle);
}
rFileName::rFileName(const rFileName& filename)
{
handle = reinterpret_cast<void*>(new wxFileName(*reinterpret_cast<wxFileName*>(filename.handle)));
}
rFileName::rFileName(const std::string& name)
{
handle = reinterpret_cast<void*>(new wxFileName(fmt::FromUTF8(name)));
}
std::string rFileName::GetFullPath()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetFullPath());
}
std::string rFileName::GetPath()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetPath());
}
std::string rFileName::GetName()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetName());
}
std::string rFileName::GetFullName()
{
return fmt::ToUTF8(reinterpret_cast<wxFileName*>(handle)->GetFullName());
}
bool rFileName::Normalize()
{
return reinterpret_cast<wxFileName*>(handle)->Normalize();
}

View file

@ -1,87 +0,0 @@
#pragma once
struct FileInfo {
std::string name;
std::string fullName;
bool exists;
bool isDirectory;
bool isWritable;
uint64_t size;
};
bool getFileInfo(const char *path, FileInfo *fileInfo);
bool rIsDir(const std::string& filename);
bool rRmdir(const std::string& dir);
bool rMkdir(const std::string& dir);
bool rMkpath(const std::string& path);
bool rRename(const std::string &from, const std::string &to);
bool rExists(const std::string &path);
bool rRemoveFile(const std::string &path);
enum rSeekMode
{
rFromStart,
rFromCurrent,
rFromEnd
};
class rFile
{
public:
enum OpenMode
{
read,
write,
read_write,
write_append,
write_excl
};
rFile();
rFile(const rFile& other) = delete;
~rFile();
rFile(const std::string& filename, rFile::OpenMode open = rFile::read);
rFile(int fd);
static bool Access(const std::string &filename, rFile::OpenMode mode);
size_t Write(const void *buffer, size_t count);
bool Write(const std::string &text);
bool Close();
bool Create(const std::string &filename, bool overwrite = false, int access = 0666);
bool Open(const std::string &filename, rFile::OpenMode mode = rFile::read, int access = 0666);
static bool Exists(const std::string&);
bool IsOpened() const;
size_t Length() const;
size_t Read(void *buffer, size_t count);
size_t Seek(size_t ofs, rSeekMode mode = rFromStart);
size_t Tell() const;
void *handle;
};
struct rDir
{
rDir();
~rDir();
rDir(const rDir& other) = delete;
rDir(const std::string &path);
bool Open(const std::string& path);
bool IsOpened() const;
static bool Exists(const std::string &path);
bool GetFirst(std::string *filename) const;
bool GetNext(std::string *filename) const;
void *handle;
};
struct rFileName
{
rFileName();
rFileName(const rFileName& other);
~rFileName();
rFileName(const std::string& name);
std::string GetFullPath();
std::string GetPath();
std::string GetName();
std::string GetFullName();
bool Normalize();
void *handle;
};

View file

@ -1,7 +1,10 @@
#include "stdafx.h" #include "stdafx.h"
#include "restore_new.h" #include "restore_new.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/msgdlg.h>")
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#pragma warning(pop)
#include "define_new_memleakdetect.h" #include "define_new_memleakdetect.h"
#include "rMsgBox.h" #include "rMsgBox.h"

View file

@ -1,7 +1,10 @@
#include "stdafx.h" #include "stdafx.h"
#include "restore_new.h" #include "restore_new.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/image.h>")
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#include <wx/image.h> #include <wx/image.h>
#pragma warning(pop)
#include "define_new_memleakdetect.h" #include "define_new_memleakdetect.h"
#ifndef _WIN32 #ifndef _WIN32

View file

@ -1,7 +1,10 @@
#include "stdafx.h" #include "stdafx.h"
#include "rTime.h" #include "rTime.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/datetime.h>")
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#include <wx/datetime.h> #include <wx/datetime.h>
#pragma warning(pop)
std::string rDefaultDateTimeFormat = "%c"; std::string rDefaultDateTimeFormat = "%c";

View file

@ -1,6 +1,10 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/rXml.h" #include "Utilities/rXml.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/xml/xml.h>")
#pragma warning(disable : 4996)
#include <wx/xml/xml.h> #include <wx/xml/xml.h>
#pragma warning(pop)
rXmlNode::rXmlNode() rXmlNode::rXmlNode()
{ {

View file

@ -2,7 +2,7 @@
#include "key_vault.h" #include "key_vault.h"
#include "unedat.h" #include "unedat.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv) void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
{ {
@ -136,7 +136,7 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
} }
// EDAT/SDAT decryption. // EDAT/SDAT decryption.
int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose) int decrypt_data(const fs::file* in, const fs::file* out, EDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
{ {
// Get metadata info and setup buffers. // Get metadata info and setup buffers.
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size); int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
@ -170,11 +170,11 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0) if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
{ {
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size; metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
in->Seek(metadata_sec_offset); in->seek(metadata_sec_offset);
unsigned char metadata[0x20]; unsigned char metadata[0x20];
memset(metadata, 0, 0x20); memset(metadata, 0, 0x20);
in->Read(metadata, 0x20); in->read(metadata, 0x20);
// If the data is compressed, decrypt the metadata. // If the data is compressed, decrypt the metadata.
// NOTE: For NPD version 1 the metadata is not encrypted. // NOTE: For NPD version 1 the metadata is not encrypted.
@ -199,11 +199,11 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
{ {
// If FLAG 0x20, the metadata precedes each data block. // If FLAG 0x20, the metadata precedes each data block.
metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length); metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length);
in->Seek(metadata_sec_offset); in->seek(metadata_sec_offset);
unsigned char metadata[0x20]; unsigned char metadata[0x20];
memset(metadata, 0, 0x20); memset(metadata, 0, 0x20);
in->Read(metadata, 0x20); in->read(metadata, 0x20);
memcpy(hash_result, metadata, 0x14); memcpy(hash_result, metadata, 0x14);
// If FLAG 0x20 is set, apply custom xor. // If FLAG 0x20 is set, apply custom xor.
@ -220,9 +220,9 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
else else
{ {
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size; metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
in->Seek(metadata_sec_offset); in->seek(metadata_sec_offset);
in->Read(hash_result, 0x10); in->read(hash_result, 0x10);
offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size; offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size;
length = edat->block_size; length = edat->block_size;
@ -242,8 +242,8 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
memset(hash, 0, 0x10); memset(hash, 0, 0x10);
memset(key_result, 0, 0x10); memset(key_result, 0, 0x10);
in->Seek(offset); in->seek(offset);
in->Read(enc_data, length); in->read(enc_data, length);
// Generate a key for the current block. // Generate a key for the current block.
b_key = get_block_key(i, npd); b_key = get_block_key(i, npd);
@ -305,7 +305,7 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
LOG_NOTICE(LOADER, "EDAT: Decompressing data..."); LOG_NOTICE(LOADER, "EDAT: Decompressing data...");
int res = decompress(decomp_data, dec_data, decomp_size); int res = decompress(decomp_data, dec_data, decomp_size);
out->Write(decomp_data, res); out->write(decomp_data, res);
if (verbose) if (verbose)
{ {
@ -330,7 +330,7 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
} }
else else
{ {
out->Write(dec_data, pad_length); out->write(dec_data, pad_length);
} }
delete[] enc_data; delete[] enc_data;
@ -340,9 +340,9 @@ int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsi
return 0; return 0;
} }
int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose) int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, const fs::file* f, bool verbose)
{ {
f->Seek(0); f->seek(0);
unsigned char header[0xA0]; unsigned char header[0xA0];
unsigned char empty_header[0xA0]; unsigned char empty_header[0xA0];
unsigned char header_hash[0x10]; unsigned char header_hash[0x10];
@ -384,12 +384,12 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f,
} }
// Read in the file header. // Read in the file header.
f->Read(header, 0xA0); f->read(header, 0xA0);
// Read in the header and metadata section hashes. // Read in the header and metadata section hashes.
f->Seek(0x90); f->seek(0x90);
f->Read(metadata_hash, 0x10); f->read(metadata_hash, 0x10);
f->Read(header_hash, 0x10); f->read(header_hash, 0x10);
// Setup the hashing mode and the crypto mode used in the file. // Setup the hashing mode and the crypto mode used in the file.
int crypto_mode = 0x1; int crypto_mode = 0x1;
@ -443,10 +443,10 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f,
while (bytes_to_read > 0) while (bytes_to_read > 0)
{ {
// Locate the metadata blocks. // Locate the metadata blocks.
f->Seek(metadata_section_offset); f->seek(metadata_section_offset);
// Read in the metadata. // Read in the metadata.
f->Read(metadata + bytes_read, metadata_section_size); f->read(metadata + bytes_read, metadata_section_size);
// Adjust sizes. // Adjust sizes.
bytes_read += metadata_section_size; bytes_read += metadata_section_size;
@ -490,10 +490,10 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f,
// Read in the metadata and header signatures. // Read in the metadata and header signatures.
f->Seek(0xB0); f->seek(0xB0);
f->Read(metadata_signature, 0x28); f->read(metadata_signature, 0x28);
f->Seek(0xD8); f->seek(0xD8);
f->Read(header_signature, 0x28); f->read(header_signature, 0x28);
// Checking metadata signature. // Checking metadata signature.
// Setup signature r and s. // Setup signature r and s.
@ -508,8 +508,8 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f,
{ {
int metadata_buf_size = block_num * 0x10; int metadata_buf_size = block_num * 0x10;
unsigned char *metadata_buf = new unsigned char[metadata_buf_size]; unsigned char *metadata_buf = new unsigned char[metadata_buf_size];
f->Seek(metadata_offset); f->seek(metadata_offset);
f->Read(metadata_buf, metadata_buf_size); f->read(metadata_buf, metadata_buf_size);
sha1(metadata_buf, metadata_buf_size, signature_hash); sha1(metadata_buf, metadata_buf_size, signature_hash);
delete[] metadata_buf; delete[] metadata_buf;
} }
@ -541,8 +541,8 @@ int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f,
// Setup header signature hash. // Setup header signature hash.
memset(signature_hash, 0, 20); memset(signature_hash, 0, 20);
unsigned char *header_buf = new unsigned char[0xD8]; unsigned char *header_buf = new unsigned char[0xD8];
f->Seek(0x00); f->seek(0x00);
f->Read(header_buf, 0xD8); f->read(header_buf, 0xD8);
sha1(header_buf, 0xD8, signature_hash ); sha1(header_buf, 0xD8, signature_hash );
delete[] header_buf; delete[] header_buf;
@ -639,7 +639,7 @@ int validate_npd_hashes(const char* file_name, unsigned char *klicensee, NPD_HEA
return (title_hash_result && dev_hash_result); return (title_hash_result && dev_hash_result);
} }
bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose) bool extract_data(const fs::file* input, const fs::file* output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
{ {
// Setup NPD and EDAT/SDAT structs. // Setup NPD and EDAT/SDAT structs.
NPD_HEADER *NPD = new NPD_HEADER(); NPD_HEADER *NPD = new NPD_HEADER();
@ -648,8 +648,8 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
// Read in the NPD and EDAT/SDAT headers. // Read in the NPD and EDAT/SDAT headers.
char npd_header[0x80]; char npd_header[0x80];
char edat_header[0x10]; char edat_header[0x10];
input->Read(npd_header, sizeof(npd_header)); input->read(npd_header, sizeof(npd_header));
input->Read(edat_header, sizeof(edat_header)); input->read(edat_header, sizeof(edat_header));
memcpy(NPD->magic, npd_header, 4); memcpy(NPD->magic, npd_header, 4);
NPD->version = swap32(*(int*)&npd_header[4]); NPD->version = swap32(*(int*)&npd_header[4]);
@ -812,9 +812,9 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose) int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose)
{ {
// Prepare the files. // Prepare the files.
rFile input(input_file_name.c_str()); fs::file input(input_file_name);
rFile output(output_file_name.c_str(), rFile::write); fs::file output(output_file_name, o_write | o_create | o_trunc);
rFile rap(rap_file_name.c_str()); fs::file rap(rap_file_name);
// Set keys (RIF and DEVKLIC). // Set keys (RIF and DEVKLIC).
unsigned char rifkey[0x10]; unsigned char rifkey[0x10];
@ -866,36 +866,30 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
} }
// Check the input/output files. // Check the input/output files.
if (!input.IsOpened() || !output.IsOpened()) if (!input || !output)
{ {
LOG_ERROR(LOADER, "EDAT: Failed to open files!"); LOG_ERROR(LOADER, "EDAT: Failed to open files!");
return -1; return -1;
} }
// Read the RAP file, if provided. // Read the RAP file, if provided.
if (rap.IsOpened()) if (rap)
{ {
unsigned char rapkey[0x10]; unsigned char rapkey[0x10];
memset(rapkey, 0, 0x10); memset(rapkey, 0, 0x10);
rap.Read(rapkey, 0x10); rap.read(rapkey, 0x10);
rap_to_rif(rapkey, rifkey); rap_to_rif(rapkey, rifkey);
rap.Close();
} }
// Delete the bad output file if any errors arise. // Delete the bad output file if any errors arise.
if (extract_data(&input, &output, input_file_name.c_str(), devklic, rifkey, verbose)) if (extract_data(&input, &output, input_file_name.c_str(), devklic, rifkey, verbose))
{ {
input.Close(); output.close();
output.Close(); fs::remove_file(output_file_name);
rRemoveFile(output_file_name);
return -1; return -1;
} }
// Cleanup.
input.Close();
output.Close();
return 0; return 0;
} }

View file

@ -1,66 +1,77 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/Log.h"
#include "Utilities/File.h"
#include "utils.h" #include "utils.h"
#include "aes.h" #include "aes.h"
#include "sha1.h" #include "sha1.h"
#include "key_vault.h" #include "key_vault.h"
#include "unpkg.h" #include "unpkg.h"
#include "restore_new.h" #include "restore_new.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependency: <wx/progdlg.h>")
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#include <wx/progdlg.h> #include <wx/progdlg.h>
#pragma warning(pop)
#include "define_new_memleakdetect.h" #include "define_new_memleakdetect.h"
#include "Utilities/Log.h"
#include "Utilities/rFile.h"
// Decryption. // Decryption.
bool CheckHeader(rFile& pkg_f, PKGHeader* m_header) bool CheckHeader(const fs::file& pkg_f, PKGHeader* m_header)
{ {
if (m_header->pkg_magic != 0x7F504B47) { if (m_header->pkg_magic != 0x7F504B47)
{
LOG_ERROR(LOADER, "PKG: Not a package file!"); LOG_ERROR(LOADER, "PKG: Not a package file!");
return false; return false;
} }
switch ((u32)m_header->pkg_type) switch (const u16 type = m_header->pkg_type)
{ {
case PKG_RELEASE_TYPE_DEBUG: break; case PKG_RELEASE_TYPE_DEBUG: break;
case PKG_RELEASE_TYPE_RELEASE: break; case PKG_RELEASE_TYPE_RELEASE: break;
default: default:
LOG_ERROR(LOADER, "PKG: Unknown PKG type!"); {
LOG_ERROR(LOADER, "PKG: Unknown PKG type (0x%x)", type);
return false; return false;
} }
}
switch ((u32)m_header->pkg_platform) switch (const u16 platform = m_header->pkg_platform)
{ {
case PKG_PLATFORM_TYPE_PS3: break; case PKG_PLATFORM_TYPE_PS3: break;
case PKG_PLATFORM_TYPE_PSP: break; case PKG_PLATFORM_TYPE_PSP: break;
default: default:
LOG_ERROR(LOADER, "PKG: Unknown PKG type!"); {
LOG_ERROR(LOADER, "PKG: Unknown PKG platform (0x%x)", platform);
return false;
}
}
if (m_header->header_size != PKG_HEADER_SIZE)
{
LOG_ERROR(LOADER, "PKG: Wrong header size (0x%x)", m_header->header_size);
return false; return false;
} }
if (m_header->header_size != PKG_HEADER_SIZE) { if (m_header->pkg_size != pkg_f.size())
LOG_ERROR(LOADER, "PKG: Wrong header size!"); {
return false; LOG_ERROR(LOADER, "PKG: File size mismatch (pkg_size=0x%x)", m_header->pkg_size);
}
if (m_header->pkg_size != pkg_f.Length()) {
LOG_WARNING(LOADER, "PKG: File size mismatch.");
//return false; //return false;
} }
if (m_header->data_size + m_header->data_offset + 0x60 != pkg_f.Length()) { if (m_header->data_size + m_header->data_offset + 0x60 != pkg_f.size())
LOG_WARNING(LOADER, "PKG: Data size mismatch."); {
LOG_ERROR(LOADER, "PKG: Data size mismatch (data_size=0x%x, offset=0x%x)", m_header->data_size, m_header->data_offset);
//return false; //return false;
} }
return true; return true;
} }
bool LoadHeader(rFile& pkg_f, PKGHeader* m_header) bool LoadHeader(const fs::file& pkg_f, PKGHeader* m_header)
{ {
pkg_f.Seek(0); pkg_f.seek(0);
if (pkg_f.Read(m_header, sizeof(PKGHeader)) != sizeof(PKGHeader)) { if (pkg_f.read(m_header, sizeof(PKGHeader)) != sizeof(PKGHeader))
{
LOG_ERROR(LOADER, "PKG: Package file is too short!"); LOG_ERROR(LOADER, "PKG: Package file is too short!");
return false; return false;
} }
@ -71,10 +82,12 @@ bool LoadHeader(rFile& pkg_f, PKGHeader* m_header)
return true; return true;
} }
int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header) int Decrypt(const fs::file& pkg_f, const fs::file& dec_pkg_f, PKGHeader* m_header)
{ {
if (!LoadHeader(pkg_f, m_header)) if (!LoadHeader(pkg_f, m_header))
{
return -1; return -1;
}
aes_context c; aes_context c;
u8 iv[HASH_LEN]; u8 iv[HASH_LEN];
@ -89,7 +102,7 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
memcpy(key+0x10, &m_header->qa_digest[8], 8); // &data[0x68] memcpy(key+0x10, &m_header->qa_digest[8], 8); // &data[0x68]
memcpy(key+0x18, &m_header->qa_digest[8], 8); // &data[0x68] memcpy(key+0x18, &m_header->qa_digest[8], 8); // &data[0x68]
pkg_f.Seek(m_header->data_offset); pkg_f.seek(m_header->data_offset);
u32 parts = (m_header->data_size + BUF_SIZE - 1) / BUF_SIZE; u32 parts = (m_header->data_size + BUF_SIZE - 1) / BUF_SIZE;
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", parts, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL); wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", parts, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
@ -100,7 +113,7 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
for (u32 i=0; i<parts; i++) for (u32 i=0; i<parts; i++)
{ {
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
u32 length = pkg_f.Read(buf, BUF_SIZE); u32 length = pkg_f.read(buf, BUF_SIZE);
u32 bits = (length + HASH_LEN - 1) / HASH_LEN; u32 bits = (length + HASH_LEN - 1) / HASH_LEN;
if (m_header->pkg_type == PKG_RELEASE_TYPE_DEBUG) if (m_header->pkg_type == PKG_RELEASE_TYPE_DEBUG)
@ -136,7 +149,7 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
buf[j] ^= ctr[j]; buf[j] ^= ctr[j];
} }
} }
dec_pkg_f.Write(buf, length); dec_pkg_f.write(buf, length);
pdlg.Update(i); pdlg.Update(i);
} }
pdlg.Update(parts); pdlg.Update(parts);
@ -144,12 +157,13 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
} }
// Unpacking. // Unpacking.
bool LoadEntries(rFile& dec_pkg_f, PKGHeader* m_header, PKGEntry *m_entries) bool LoadEntries(const fs::file& dec_pkg_f, PKGHeader* m_header, PKGEntry* m_entries)
{ {
dec_pkg_f.Seek(0); dec_pkg_f.seek(0);
dec_pkg_f.Read(m_entries, sizeof(PKGEntry) * m_header->file_count); dec_pkg_f.read(m_entries, sizeof(PKGEntry) * m_header->file_count);
if (m_entries->name_offset / sizeof(PKGEntry) != m_header->file_count) { if (m_entries->name_offset / sizeof(PKGEntry) != m_header->file_count)
{
LOG_ERROR(LOADER, "PKG: Entries are damaged!"); LOG_ERROR(LOADER, "PKG: Entries are damaged!");
return false; return false;
} }
@ -157,12 +171,12 @@ bool LoadEntries(rFile& dec_pkg_f, PKGHeader* m_header, PKGEntry *m_entries)
return true; return true;
} }
bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir) bool UnpackEntry(const fs::file& dec_pkg_f, const PKGEntry& entry, std::string dir)
{ {
char buf[BUF_SIZE]; char buf[BUF_SIZE];
dec_pkg_f.Seek(entry.name_offset); dec_pkg_f.seek(entry.name_offset);
dec_pkg_f.Read(buf, entry.name_size); dec_pkg_f.read(buf, entry.name_size);
buf[entry.name_size] = 0; buf[entry.name_size] = 0;
switch (entry.type.data() >> 24) switch (entry.type.data() >> 24)
@ -172,40 +186,49 @@ bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
case PKG_FILE_ENTRY_SDAT: case PKG_FILE_ENTRY_SDAT:
case PKG_FILE_ENTRY_REGULAR: case PKG_FILE_ENTRY_REGULAR:
{ {
rFile out; const std::string path = dir + std::string(buf, entry.name_size);
auto path = dir + std::string(buf, entry.name_size);
if (rExists(path)) if (fs::is_file(path))
{ {
LOG_WARNING(LOADER, "PKG Loader: File is overwritten: %s", path.c_str()); LOG_WARNING(LOADER, "PKG Loader: '%s' is overwritten", path);
} }
if (out.Create(path, true /* overwriting */)) fs::file out(path, o_write | o_create | o_trunc);
{
dec_pkg_f.Seek(entry.file_offset); if (out)
{
dec_pkg_f.seek(entry.file_offset);
for (u64 size = 0; size < entry.file_size;)
{
size += dec_pkg_f.read(buf, BUF_SIZE);
for (u64 size = 0; size < entry.file_size;) {
size += dec_pkg_f.Read(buf, BUF_SIZE);
if (size > entry.file_size) if (size > entry.file_size)
out.Write(buf, BUF_SIZE - (size - entry.file_size)); {
out.write(buf, BUF_SIZE - (size - entry.file_size));
}
else else
out.Write(buf, BUF_SIZE); {
out.write(buf, BUF_SIZE);
}
} }
out.Close();
return true; return true;
} }
else else
{ {
LOG_ERROR(LOADER, "PKG Loader: Could not create file: %s", path.c_str()); LOG_ERROR(LOADER, "PKG Loader: Could not create file '%s'", path);
return false; return false;
} }
} }
case PKG_FILE_ENTRY_FOLDER: case PKG_FILE_ENTRY_FOLDER:
{ {
auto path = dir + std::string(buf, entry.name_size); const std::string path = dir + std::string(buf, entry.name_size);
if (!rExists(path) && !rMkdir(path))
if (!fs::is_dir(path) && !fs::create_dir(path))
{ {
LOG_ERROR(LOADER, "PKG Loader: Could not create directory: %s", path.c_str()); LOG_ERROR(LOADER, "PKG Loader: Could not create directory: %s", path);
return false; return false;
} }
@ -220,41 +243,44 @@ bool UnpackEntry(rFile& dec_pkg_f, const PKGEntry& entry, std::string dir)
} }
} }
int Unpack(rFile& pkg_f, std::string src, std::string dst) int Unpack(const fs::file& pkg_f, std::string src, std::string dst)
{ {
PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader)); PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader));
rFile dec_pkg_f;
// TODO: This shouldn't use current dir // TODO: This shouldn't use current dir
std::string decryptedFile = "./dev_hdd1/" + src + ".dec"; std::string decryptedFile = "./dev_hdd1/" + src + ".dec";
dec_pkg_f.Create(decryptedFile, true); fs::file dec_pkg_f(decryptedFile, o_read | o_write | o_create | o_trunc);
if (Decrypt(pkg_f, dec_pkg_f, m_header) < 0) if (Decrypt(pkg_f, dec_pkg_f, m_header) < 0)
{
return -1; return -1;
}
dec_pkg_f.Close(); dec_pkg_f.seek(0);
rFile n_dec_pkg_f(decryptedFile, rFile::read);
std::vector<PKGEntry> m_entries; std::vector<PKGEntry> m_entries;
m_entries.resize(m_header->file_count); m_entries.resize(m_header->file_count);
PKGEntry *m_entries_ptr = &m_entries[0]; auto m_entries_ptr = m_entries.data();
if (!LoadEntries(n_dec_pkg_f, m_header, m_entries_ptr))
if (!LoadEntries(dec_pkg_f, m_header, m_entries_ptr))
{
return -1; return -1;
}
wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, unpacking...", m_entries.size(), 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL); wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, unpacking...", m_entries.size(), 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);
for (const PKGEntry& entry : m_entries) for (const auto& entry : m_entries)
{ {
UnpackEntry(n_dec_pkg_f, entry, dst + src + "/"); UnpackEntry(dec_pkg_f, entry, dst + src + "/");
pdlg.Update(pdlg.GetValue() + 1); pdlg.Update(pdlg.GetValue() + 1);
} }
pdlg.Update(m_entries.size()); pdlg.Update(m_entries.size());
n_dec_pkg_f.Close(); dec_pkg_f.close();
wxRemoveFile(decryptedFile); fs::remove_file(decryptedFile);
return 0; return 0;
} }

View file

@ -1,21 +1,32 @@
#pragma once #pragma once
// Constants // Constants
#define PKG_HEADER_SIZE 0xC0 //sizeof(pkg_header) + sizeof(pkg_unk_checksum) enum
#define PKG_RELEASE_TYPE_RELEASE 0x8000 {
#define PKG_RELEASE_TYPE_DEBUG 0x0000 HASH_LEN = 16,
#define PKG_PLATFORM_TYPE_PS3 0x0001 BUF_SIZE = 4096,
#define PKG_PLATFORM_TYPE_PSP 0x0002 PKG_HEADER_SIZE = 0xC0, //sizeof(pkg_header) + sizeof(pkg_unk_checksum)
};
#define PKG_FILE_ENTRY_NPDRM 0x0001 enum : u16
#define PKG_FILE_ENTRY_NPDRMEDAT 0x0002 {
#define PKG_FILE_ENTRY_REGULAR 0x0003 PKG_RELEASE_TYPE_RELEASE = 0x8000,
#define PKG_FILE_ENTRY_FOLDER 0x0004 PKG_RELEASE_TYPE_DEBUG = 0x0000,
#define PKG_FILE_ENTRY_SDAT 0x0009
#define PKG_FILE_ENTRY_OVERWRITE 0x80000000
#define HASH_LEN 16 PKG_PLATFORM_TYPE_PS3 = 0x0001,
#define BUF_SIZE 4096 PKG_PLATFORM_TYPE_PSP = 0x0002,
};
enum : u32
{
PKG_FILE_ENTRY_NPDRM = 1,
PKG_FILE_ENTRY_NPDRMEDAT = 2,
PKG_FILE_ENTRY_REGULAR = 3,
PKG_FILE_ENTRY_FOLDER = 4,
PKG_FILE_ENTRY_SDAT = 9,
PKG_FILE_ENTRY_OVERWRITE = 0x80000000,
};
// Structs // Structs
struct PKGHeader struct PKGHeader
@ -45,6 +56,6 @@ struct PKGEntry
be_t<u32> pad; // Padding (zeros) be_t<u32> pad; // Padding (zeros)
}; };
class rFile; namespace fs { struct file; }
extern int Unpack(rFile& dec_pkg_f, std::string src, std::string dst); int Unpack(const fs::file& dec_pkg_f, std::string src, std::string dst);

View file

@ -1,63 +1,187 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "aes.h" #include "aes.h"
#include "sha1.h" #include "sha1.h"
#include "utils.h" #include "utils.h"
#include "Emu/FS/vfsLocalFile.h" #include "Emu/FS/vfsLocalFile.h"
#include "unself.h" #include "unself.h"
#pragma warning(push)
#pragma message("TODO: remove wx dependencies: <wx/mstream.h> <wx/zstream.h>")
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/zstream.h> #include <wx/zstream.h>
#pragma warning(pop)
__forceinline u8 Read8(vfsStream& f)
{
u8 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr) __forceinline u16 Read16(vfsStream& f)
{ {
Write32(f, ehdr.e_magic); be_t<u16> ret;
Write8(f, ehdr.e_class); f.Read(&ret, sizeof(ret));
Write8(f, ehdr.e_data); return ret;
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write64(f, ehdr.e_entry);
Write64(f, ehdr.e_phoff);
Write64(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
} }
void WritePhdr(rFile& f, Elf64_Phdr& phdr)
__forceinline u32 Read32(vfsStream& f)
{ {
Write32(f, phdr.p_type); be_t<u32> ret;
Write32(f, phdr.p_flags); f.Read(&ret, sizeof(ret));
Write64(f, phdr.p_offset); return ret;
Write64(f, phdr.p_vaddr);
Write64(f, phdr.p_paddr);
Write64(f, phdr.p_filesz);
Write64(f, phdr.p_memsz);
Write64(f, phdr.p_align);
} }
void WriteShdr(rFile& f, Elf64_Shdr& shdr)
__forceinline u64 Read64(vfsStream& f)
{ {
Write32(f, shdr.sh_name); be_t<u64> ret;
Write32(f, shdr.sh_type); f.Read(&ret, sizeof(ret));
Write64(f, shdr.sh_flags); return ret;
Write64(f, shdr.sh_addr);
Write64(f, shdr.sh_offset);
Write64(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write64(f, shdr.sh_addralign);
Write64(f, shdr.sh_entsize);
} }
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
__forceinline u16 Read16LE(vfsStream& f)
{
u16 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
__forceinline u32 Read32LE(vfsStream& f)
{
u32 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
__forceinline u64 Read64LE(vfsStream& f)
{
u64 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
__forceinline void Write8(vfsStream& f, const u8 data)
{
f.Write(&data, sizeof(data));
}
__forceinline void Write8(const fs::file& f, const u8 data)
{
f.write(&data, sizeof(data));
}
__forceinline void Write16LE(vfsStream& f, const u16 data)
{
f.Write(&data, sizeof(data));
}
__forceinline void Write16LE(const fs::file& f, const u16 data)
{
f.write(&data, sizeof(data));
}
__forceinline void Write32LE(vfsStream& f, const u32 data)
{
f.Write(&data, sizeof(data));
}
__forceinline void Write32LE(const fs::file& f, const u32 data)
{
f.write(&data, sizeof(data));
}
__forceinline void Write64LE(vfsStream& f, const u64 data)
{
f.Write(&data, sizeof(data));
}
__forceinline void Write64LE(const fs::file& f, const u64 data)
{
f.write(&data, sizeof(data));
}
__forceinline void Write16(vfsStream& f, const u16 data)
{
Write16LE(f, re16(data));
}
__forceinline void Write16(const fs::file& f, const u16 data)
{
Write16LE(f, re16(data));
}
__forceinline void Write32(vfsStream& f, const u32 data)
{
Write32LE(f, re32(data));
}
__forceinline void Write32(const fs::file& f, const u32 data)
{
Write32LE(f, re32(data));
}
__forceinline void Write64(vfsStream& f, const u64 data)
{
Write64LE(f, re64(data));
}
__forceinline void Write64(const fs::file& f, const u64 data)
{
Write64LE(f, re64(data));
}
void WriteEhdr(const fs::file& f, Elf64_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write64(f, ehdr.e_entry);
Write64(f, ehdr.e_phoff);
Write64(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(const fs::file& f, Elf64_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_flags);
Write64(f, phdr.p_offset);
Write64(f, phdr.p_vaddr);
Write64(f, phdr.p_paddr);
Write64(f, phdr.p_filesz);
Write64(f, phdr.p_memsz);
Write64(f, phdr.p_align);
}
void WriteShdr(const fs::file& f, Elf64_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write64(f, shdr.sh_flags);
Write64(f, shdr.sh_addr);
Write64(f, shdr.sh_offset);
Write64(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write64(f, shdr.sh_addralign);
Write64(f, shdr.sh_entsize);
}
void WriteEhdr(const fs::file& f, Elf32_Ehdr& ehdr)
{ {
Write32(f, ehdr.e_magic); Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class); Write8(f, ehdr.e_class);
@ -79,7 +203,8 @@ void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
Write16(f, ehdr.e_shnum); Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx); Write16(f, ehdr.e_shstrndx);
} }
void WritePhdr(rFile& f, Elf32_Phdr& phdr)
void WritePhdr(const fs::file& f, Elf32_Phdr& phdr)
{ {
Write32(f, phdr.p_type); Write32(f, phdr.p_type);
Write32(f, phdr.p_offset); Write32(f, phdr.p_offset);
@ -90,7 +215,8 @@ void WritePhdr(rFile& f, Elf32_Phdr& phdr)
Write32(f, phdr.p_flags); Write32(f, phdr.p_flags);
Write32(f, phdr.p_align); Write32(f, phdr.p_align);
} }
void WriteShdr(rFile& f, Elf32_Shdr& shdr)
void WriteShdr(const fs::file& f, Elf32_Shdr& shdr)
{ {
Write32(f, shdr.sh_name); Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type); Write32(f, shdr.sh_type);
@ -408,8 +534,164 @@ void SelfSection::Load(vfsStream& f)
offset = Read64(f); offset = Read64(f);
} }
void Elf32_Ehdr::Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
if (IsLittleEndian())
{
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
else
{
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
}
void Elf32_Shdr::Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read32(f);
sh_addr = Read32(f);
sh_offset = Read32(f);
sh_size = Read32(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read32(f);
sh_entsize = Read32(f);
}
void Elf32_Shdr::LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Elf32_Phdr::Load(vfsStream& f)
{
p_type = Read32(f);
p_offset = Read32(f);
p_vaddr = Read32(f);
p_paddr = Read32(f);
p_filesz = Read32(f);
p_memsz = Read32(f);
p_flags = Read32(f);
p_align = Read32(f);
}
void Elf32_Phdr::LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Elf64_Ehdr::Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read64(f);
e_phoff = Read64(f);
e_shoff = Read64(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
void Elf64_Shdr::Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read64(f);
sh_addr = Read64(f);
sh_offset = Read64(f);
sh_size = Read64(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read64(f);
sh_entsize = Read64(f);
}
void Elf64_Phdr::Load(vfsStream& f)
{
p_type = Read32(f);
p_flags = Read32(f);
p_offset = Read64(f);
p_vaddr = Read64(f);
p_paddr = Read64(f);
p_filesz = Read64(f);
p_memsz = Read64(f);
p_align = Read64(f);
}
void SceHeader::Load(vfsStream& f)
{
se_magic = Read32(f);
se_hver = Read32(f);
se_flags = Read16(f);
se_type = Read16(f);
se_meta = Read32(f);
se_hsize = Read64(f);
se_esize = Read64(f);
}
void SelfHeader::Load(vfsStream& f)
{
se_htype = Read64(f);
se_appinfooff = Read64(f);
se_elfoff = Read64(f);
se_phdroff = Read64(f);
se_shdroff = Read64(f);
se_secinfoff = Read64(f);
se_sceveroff = Read64(f);
se_controloff = Read64(f);
se_controlsize = Read64(f);
pad = Read64(f);
}
SELFDecrypter::SELFDecrypter(vfsStream& s) SELFDecrypter::SELFDecrypter(vfsStream& s)
: self_f(s), key_v(), data_buf_length(0) : self_f(s)
, key_v()
, data_buf_length(0)
{ {
} }
@ -794,8 +1076,8 @@ bool SELFDecrypter::DecryptData()
bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32) bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
{ {
// Create a new ELF file. // Create a new ELF file.
rFile e(elf.c_str(), rFile::write); fs::file e(elf, o_write | o_create | o_trunc);
if(!e.IsOpened()) if(!e)
{ {
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
return false; return false;
@ -819,8 +1101,8 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
if (meta_shdr[i].type == 2) if (meta_shdr[i].type == 2)
{ {
// Seek to the program header data offset and write the data. // Seek to the program header data offset and write the data.
e.Seek(phdr32_arr[meta_shdr[i].program_idx].p_offset); e.seek(phdr32_arr[meta_shdr[i].program_idx].p_offset);
e.Write(data_buf + data_buf_offset, meta_shdr[i].data_size); e.write(data_buf + data_buf_offset, meta_shdr[i].data_size);
// Advance the data buffer offset by data size. // Advance the data buffer offset by data size.
data_buf_offset += meta_shdr[i].data_size; data_buf_offset += meta_shdr[i].data_size;
@ -830,7 +1112,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
// Write section headers. // Write section headers.
if(self_hdr.se_shdroff != 0) if(self_hdr.se_shdroff != 0)
{ {
e.Seek(elf32_hdr.e_shoff); e.seek(elf32_hdr.e_shoff);
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i) for(u32 i = 0; i < elf32_hdr.e_shnum; ++i)
WriteShdr(e, shdr32_arr[i]); WriteShdr(e, shdr32_arr[i]);
@ -870,8 +1152,8 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
decomp_stream_out.CopyTo(decomp_buf, phdr64_arr[meta_shdr[i].program_idx].p_filesz); decomp_stream_out.CopyTo(decomp_buf, phdr64_arr[meta_shdr[i].program_idx].p_filesz);
// Seek to the program header data offset and write the data. // Seek to the program header data offset and write the data.
e.Seek(phdr64_arr[meta_shdr[i].program_idx].p_offset); e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset);
e.Write(decomp_buf, phdr64_arr[meta_shdr[i].program_idx].p_filesz); e.write(decomp_buf, phdr64_arr[meta_shdr[i].program_idx].p_filesz);
// Release the decompression buffer. // Release the decompression buffer.
free(decomp_buf); free(decomp_buf);
@ -879,8 +1161,8 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
else else
{ {
// Seek to the program header data offset and write the data. // Seek to the program header data offset and write the data.
e.Seek(phdr64_arr[meta_shdr[i].program_idx].p_offset); e.seek(phdr64_arr[meta_shdr[i].program_idx].p_offset);
e.Write(data_buf + data_buf_offset, meta_shdr[i].data_size); e.write(data_buf + data_buf_offset, meta_shdr[i].data_size);
} }
// Advance the data buffer offset by data size. // Advance the data buffer offset by data size.
@ -891,14 +1173,13 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
// Write section headers. // Write section headers.
if(self_hdr.se_shdroff != 0) if(self_hdr.se_shdroff != 0)
{ {
e.Seek(elf64_hdr.e_shoff); e.seek(elf64_hdr.e_shoff);
for(u32 i = 0; i < elf64_hdr.e_shnum; ++i) for(u32 i = 0; i < elf64_hdr.e_shnum; ++i)
WriteShdr(e, shdr64_arr[i]); WriteShdr(e, shdr64_arr[i]);
} }
} }
e.Close();
return true; return true;
} }
@ -914,24 +1195,23 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap"); std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap");
// Check if we have a valid RAP file. // Check if we have a valid RAP file.
if (!rExists(rap_path)) if (!fs::is_file(rap_path))
{ {
LOG_ERROR(LOADER, "This application requires a valid RAP file for decryption!"); LOG_ERROR(LOADER, "This application requires a valid RAP file for decryption!");
return false; return false;
} }
// Open the RAP file and read the key. // Open the RAP file and read the key.
rFile rap_file(rap_path, rFile::read); fs::file rap_file(rap_path);
if (!rap_file.IsOpened()) if (!rap_file)
{ {
LOG_ERROR(LOADER, "Failed to load RAP file!"); LOG_ERROR(LOADER, "Failed to load RAP file!");
return false; return false;
} }
LOG_NOTICE(LOADER, "Loading RAP file %s", (ci_str + ".rap").c_str()); LOG_NOTICE(LOADER, "Loading RAP file %s.rap", ci_str);
rap_file.Read(rap_key, 0x10); rap_file.read(rap_key, 0x10);
rap_file.Close();
// Convert the RAP key. // Convert the RAP key.
rap_to_rif(rap_key, npdrm_key); rap_to_rif(rap_key, npdrm_key);
@ -975,18 +1255,18 @@ bool IsSelfElf32(const std::string& path)
bool CheckDebugSelf(const std::string& self, const std::string& elf) bool CheckDebugSelf(const std::string& self, const std::string& elf)
{ {
// Open the SELF file. // Open the SELF file.
rFile s(self); fs::file s(self);
if(!s.IsOpened()) if(!s)
{ {
LOG_ERROR(LOADER, "Could not open SELF file! (%s)", self.c_str()); LOG_ERROR(LOADER, "Could not open SELF file! (%s)", self.c_str());
return false; return false;
} }
// Get the key version. // Get the key version.
s.Seek(0x08); s.seek(0x08);
u16 key_version; u16 key_version;
s.Read(&key_version, sizeof(key_version)); s.read(&key_version, sizeof(key_version));
// Check for DEBUG version. // Check for DEBUG version.
if(swap16(key_version) == 0x8000) if(swap16(key_version) == 0x8000)
@ -994,17 +1274,17 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header..."); LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header...");
// Get the real elf offset. // Get the real elf offset.
s.Seek(0x10); s.seek(0x10);
u64 elf_offset; u64 elf_offset;
s.Read(&elf_offset, sizeof(elf_offset)); s.read(&elf_offset, sizeof(elf_offset));
// Start at the real elf offset. // Start at the real elf offset.
elf_offset = swap64(elf_offset); elf_offset = swap64(elf_offset);
s.Seek(elf_offset); s.seek(elf_offset);
// Write the real ELF file back. // Write the real ELF file back.
rFile e(elf, rFile::write); fs::file e(elf, o_write | o_create | o_trunc);
if(!e.IsOpened()) if(!e)
{ {
LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str());
return false; return false;
@ -1012,18 +1292,14 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
// Copy the data. // Copy the data.
char buf[2048]; char buf[2048];
while (ssize_t size = s.Read(buf, 2048)) while (ssize_t size = s.read(buf, 2048))
e.Write(buf, size); e.write(buf, size);
e.Close();
return true; return true;
} }
else
{ // Leave the file untouched.
// Leave the file untouched. return false;
s.Seek(0);
return false;
}
} }
bool DecryptSelf(const std::string& elf, const std::string& self) bool DecryptSelf(const std::string& elf, const std::string& self)

View file

@ -1,186 +1,187 @@
#pragma once #pragma once
#include "Loader/ELF64.h"
#include "Loader/ELF32.h"
#include "key_vault.h" #include "key_vault.h"
struct vfsStream;
struct AppInfo struct AppInfo
{ {
u64 authid; u64 authid;
u32 vendor_id; u32 vendor_id;
u32 self_type; u32 self_type;
u64 version; u64 version;
u64 padding; u64 padding;
void Load(vfsStream& f); void Load(vfsStream& f);
void Show();
void Show();
}; };
struct SectionInfo struct SectionInfo
{ {
u64 offset; u64 offset;
u64 size; u64 size;
u32 compressed; u32 compressed;
u32 unknown1; u32 unknown1;
u32 unknown2; u32 unknown2;
u32 encrypted; u32 encrypted;
void Load(vfsStream& f); void Load(vfsStream& f);
void Show();
void Show();
}; };
struct SCEVersionInfo struct SCEVersionInfo
{ {
u32 subheader_type; u32 subheader_type;
u32 present; u32 present;
u32 size; u32 size;
u32 unknown; u32 unknown;
void Load(vfsStream& f); void Load(vfsStream& f);
void Show();
void Show();
}; };
struct ControlInfo struct ControlInfo
{ {
u32 type; u32 type;
u32 size; u32 size;
u64 next; u64 next;
union { union
// type 1 0x30 bytes {
struct { // type 1 0x30 bytes
u32 ctrl_flag1; struct
u32 unknown1; {
u32 unknown2; u32 ctrl_flag1;
u32 unknown3; u32 unknown1;
u32 unknown4; u32 unknown2;
u32 unknown5; u32 unknown3;
u32 unknown6; u32 unknown4;
u32 unknown7; u32 unknown5;
} control_flags; u32 unknown6;
u32 unknown7;
// type 2 0x30 bytes } control_flags;
struct {
u8 digest[20];
u64 unknown;
} file_digest_30;
// type 2 0x40 bytes // type 2 0x30 bytes
struct { struct
u8 digest1[20]; {
u8 digest2[20]; u8 digest[20];
u64 unknown; u64 unknown;
} file_digest_40;
// type 3 0x90 bytes } file_digest_30;
struct {
u32 magic;
u32 unknown1;
u32 license;
u32 type;
u8 content_id[48];
u8 digest[16];
u8 invdigest[16];
u8 xordigest[16];
u64 unknown2;
u64 unknown3;
} npdrm;
};
void Load(vfsStream& f); // type 2 0x40 bytes
struct
{
u8 digest1[20];
u8 digest2[20];
u64 unknown;
void Show(); } file_digest_40;
// type 3 0x90 bytes
struct
{
u32 magic;
u32 unknown1;
u32 license;
u32 type;
u8 content_id[48];
u8 digest[16];
u8 invdigest[16];
u8 xordigest[16];
u64 unknown2;
u64 unknown3;
} npdrm;
};
void Load(vfsStream& f);
void Show();
}; };
struct MetadataInfo struct MetadataInfo
{ {
u8 key[0x10]; u8 key[0x10];
u8 key_pad[0x10]; u8 key_pad[0x10];
u8 iv[0x10]; u8 iv[0x10];
u8 iv_pad[0x10]; u8 iv_pad[0x10];
void Load(u8* in); void Load(u8* in);
void Show();
void Show();
}; };
struct MetadataHeader struct MetadataHeader
{ {
u64 signature_input_length; u64 signature_input_length;
u32 unknown1; u32 unknown1;
u32 section_count; u32 section_count;
u32 key_count; u32 key_count;
u32 opt_header_size; u32 opt_header_size;
u32 unknown2; u32 unknown2;
u32 unknown3; u32 unknown3;
void Load(u8* in); void Load(u8* in);
void Show();
void Show();
}; };
struct MetadataSectionHeader struct MetadataSectionHeader
{ {
u64 data_offset; u64 data_offset;
u64 data_size; u64 data_size;
u32 type; u32 type;
u32 program_idx; u32 program_idx;
u32 hashed; u32 hashed;
u32 sha1_idx; u32 sha1_idx;
u32 encrypted; u32 encrypted;
u32 key_idx; u32 key_idx;
u32 iv_idx; u32 iv_idx;
u32 compressed; u32 compressed;
void Load(u8* in); void Load(u8* in);
void Show();
void Show();
}; };
struct SectionHash struct SectionHash
{ {
u8 sha1[20]; u8 sha1[20];
u8 padding[12]; u8 padding[12];
u8 hmac_key[64]; u8 hmac_key[64];
void Load(vfsStream& f); void Load(vfsStream& f);
}; };
struct CapabilitiesInfo struct CapabilitiesInfo
{ {
u32 type; u32 type;
u32 capabilities_size; u32 capabilities_size;
u32 next; u32 next;
u32 unknown1; u32 unknown1;
u64 unknown2; u64 unknown2;
u64 unknown3; u64 unknown3;
u64 flags; u64 flags;
u32 unknown4; u32 unknown4;
u32 unknown5; u32 unknown5;
void Load(vfsStream& f); void Load(vfsStream& f);
}; };
struct Signature struct Signature
{ {
u8 r[21]; u8 r[21];
u8 s[21]; u8 s[21];
u8 padding[6]; u8 padding[6];
void Load(vfsStream& f); void Load(vfsStream& f);
}; };
struct SelfSection struct SelfSection
{ {
u8 *data; u8 *data;
u64 size; u64 size;
u64 offset; u64 offset;
void Load(vfsStream& f); void Load(vfsStream& f);
}; };
struct Elf32_Ehdr struct Elf32_Ehdr
@ -204,55 +205,10 @@ struct Elf32_Ehdr
u16 e_shentsize; u16 e_shentsize;
u16 e_shnum; u16 e_shnum;
u16 e_shstrndx; u16 e_shstrndx;
void Load(vfsStream& f);
void Show() {} void Show() {}
bool IsLittleEndian() const bool IsLittleEndian() const { return e_data == 1; }
{
return e_data == 1;
}
void Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
if (IsLittleEndian())
{
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
else
{
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
}
bool CheckMagic() const { return e_magic == 0x7F454C46; } bool CheckMagic() const { return e_magic == 0x7F454C46; }
u32 GetEntry() const { return e_entry; } u32 GetEntry() const { return e_entry; }
}; };
@ -269,25 +225,12 @@ struct Elf32_Shdr
u32 sh_info; u32 sh_info;
u32 sh_addralign; u32 sh_addralign;
u32 sh_entsize; u32 sh_entsize;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
sh_name = Read32(f); void LoadLE(vfsStream& f);
sh_type = Read32(f);
sh_flags = Read32(f);
sh_addr = Read32(f);
sh_offset = Read32(f);
sh_size = Read32(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read32(f);
sh_entsize = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {} void Show() {}
}; };
struct Elf32_Phdr struct Elf32_Phdr
{ {
u32 p_type; u32 p_type;
@ -298,21 +241,9 @@ struct Elf32_Phdr
u32 p_memsz; u32 p_memsz;
u32 p_flags; u32 p_flags;
u32 p_align; u32 p_align;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
p_type = Read32(f); void LoadLE(vfsStream& f);
p_offset = Read32(f);
p_vaddr = Read32(f);
p_paddr = Read32(f);
p_filesz = Read32(f);
p_memsz = Read32(f);
p_flags = Read32(f);
p_align = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {} void Show() {}
}; };
@ -337,28 +268,8 @@ struct Elf64_Ehdr
u16 e_shentsize; u16 e_shentsize;
u16 e_shnum; u16 e_shnum;
u16 e_shstrndx; u16 e_shstrndx;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read64(f);
e_phoff = Read64(f);
e_shoff = Read64(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
void Show() {} void Show() {}
bool CheckMagic() const { return e_magic == 0x7F454C46; } bool CheckMagic() const { return e_magic == 0x7F454C46; }
u64 GetEntry() const { return e_entry; } u64 GetEntry() const { return e_entry; }
@ -376,19 +287,8 @@ struct Elf64_Shdr
u32 sh_info; u32 sh_info;
u64 sh_addralign; u64 sh_addralign;
u64 sh_entsize; u64 sh_entsize;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read64(f);
sh_addr = Read64(f);
sh_offset = Read64(f);
sh_size = Read64(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read64(f);
sh_entsize = Read64(f);
}
void Show(){} void Show(){}
}; };
@ -402,17 +302,8 @@ struct Elf64_Phdr
u64 p_filesz; u64 p_filesz;
u64 p_memsz; u64 p_memsz;
u64 p_align; u64 p_align;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
p_type = Read32(f);
p_flags = Read32(f);
p_offset = Read64(f);
p_vaddr = Read64(f);
p_paddr = Read64(f);
p_filesz = Read64(f);
p_memsz = Read64(f);
p_align = Read64(f);
}
void Show(){} void Show(){}
}; };
@ -425,16 +316,8 @@ struct SceHeader
u32 se_meta; u32 se_meta;
u64 se_hsize; u64 se_hsize;
u64 se_esize; u64 se_esize;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
se_magic = Read32(f);
se_hver = Read32(f);
se_flags = Read16(f);
se_type = Read16(f);
se_meta = Read32(f);
se_hsize = Read64(f);
se_esize = Read64(f);
}
void Show(){} void Show(){}
bool CheckMagic() const { return se_magic == 0x53434500; } bool CheckMagic() const { return se_magic == 0x53434500; }
}; };
@ -451,23 +334,11 @@ struct SelfHeader
u64 se_controloff; u64 se_controloff;
u64 se_controlsize; u64 se_controlsize;
u64 pad; u64 pad;
void Load(vfsStream& f)
{ void Load(vfsStream& f);
se_htype = Read64(f);
se_appinfooff = Read64(f);
se_elfoff = Read64(f);
se_phdroff = Read64(f);
se_shdroff = Read64(f);
se_secinfoff = Read64(f);
se_sceveroff = Read64(f);
se_controloff = Read64(f);
se_controlsize = Read64(f);
pad = Read64(f);
}
void Show(){} void Show(){}
}; };
class SELFDecrypter class SELFDecrypter
{ {
// Main SELF file stream. // Main SELF file stream.

View file

@ -64,7 +64,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pAr
{ {
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock); sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {
@ -106,7 +106,7 @@ s32 sceKernelDeleteThread(s32 threadId)
{ {
sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId); sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {
@ -264,7 +264,7 @@ s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv:
{ {
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout); sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); const auto t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
if (!t) if (!t)
{ {

View file

@ -259,7 +259,7 @@ namespace sce_libc_func
psv_log_base sceLibc("SceLibc", []() psv_log_base sceLibc("SceLibc", []()
{ {
g_dso.set(0); g_dso = vm::null;
g_atexit.clear(); g_atexit.clear();
sceLibc.on_load = nullptr; sceLibc.on_load = nullptr;

View file

@ -46,7 +46,7 @@ namespace psv_func_detail
ARG_STACK, ARG_STACK,
}; };
static const auto FIXED_STACK_FRAME_SIZE = 0x100; // described in CB_FUNC.h static const auto FIXED_STACK_FRAME_SIZE = 0x80; // described in CB_FUNC.h
template<typename T, arg_class type, int g_count, int f_count, int v_count> template<typename T, arg_class type, int g_count, int f_count, int v_count>
struct bind_arg; struct bind_arg;

View file

@ -12,7 +12,7 @@ AudioDumper::~AudioDumper()
bool AudioDumper::Init(u8 ch) bool AudioDumper::Init(u8 ch)
{ {
if ((m_init = m_output.Open("audio.wav", rFile::write))) if ((m_init = m_output.open("audio.wav", o_write | o_create | o_trunc)))
{ {
m_header = WAVHeader(ch); m_header = WAVHeader(ch);
WriteHeader(); WriteHeader();
@ -25,7 +25,7 @@ void AudioDumper::WriteHeader()
{ {
if (m_init) if (m_init)
{ {
m_output.Write(&m_header, sizeof(m_header)); // write file header m_output.write(&m_header, sizeof(m_header)); // write file header
} }
} }
@ -47,7 +47,7 @@ size_t AudioDumper::WriteData(const void* buffer, size_t size)
if (m_init) if (m_init)
#endif #endif
{ {
size_t ret = m_output.Write(buffer, size); size_t ret = m_output.write(buffer, size);
m_header.Size += (u32)ret; m_header.Size += (u32)ret;
m_header.RIFF.Size += (u32)ret; m_header.RIFF.Size += (u32)ret;
return ret; return ret;
@ -60,8 +60,8 @@ void AudioDumper::Finalize()
{ {
if (m_init) if (m_init)
{ {
m_output.Seek(0); m_output.seek(0);
m_output.Write(&m_header, sizeof(m_header)); // write fixed file header m_output.write(&m_header, sizeof(m_header)); // write fixed file header
m_output.Close(); m_output.close();
} }
} }

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "Utilities/File.h"
#include "Utilities/rFile.h"
struct WAVHeader struct WAVHeader
{ {
@ -56,7 +55,7 @@ struct WAVHeader
class AudioDumper class AudioDumper
{ {
WAVHeader m_header; WAVHeader m_header;
rFile m_output; fs::file m_output;
bool m_init; bool m_init;
public: public:

View file

@ -77,7 +77,7 @@ public:
std::string GetName() const { return NamedThreadBase::GetThreadName(); } std::string GetName() const { return NamedThreadBase::GetThreadName(); }
std::string GetFName() const std::string GetFName() const
{ {
return fmt::format("%s[%d] Thread (%s)", GetTypeString(), m_id, GetName()); return fmt::format("%s[0x%x] Thread (%s)", GetTypeString(), m_id, GetName());
} }
static std::string CPUThreadTypeToString(CPUThreadType type) static std::string CPUThreadTypeToString(CPUThreadType type)

View file

@ -112,26 +112,14 @@ void CPUThreadManager::RemoveThread(u32 id)
std::shared_ptr<CPUThread> CPUThreadManager::GetThread(u32 id) std::shared_ptr<CPUThread> CPUThreadManager::GetThread(u32 id)
{ {
std::shared_ptr<CPUThread> res; return Emu.GetIdManager().GetIDData<CPUThread>(id);
if (!id) return nullptr;
if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr;
return res;
} }
std::shared_ptr<CPUThread> CPUThreadManager::GetThread(u32 id, CPUThreadType type) std::shared_ptr<CPUThread> CPUThreadManager::GetThread(u32 id, CPUThreadType type)
{ {
std::shared_ptr<CPUThread> res; const auto res = GetThread(id);
if (!id) return nullptr; return res && res->GetType() == type ? res : nullptr;
if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr;
if (res->GetType() != type) return nullptr;
return res;
} }
std::shared_ptr<CPUThread> CPUThreadManager::GetRawSPUThread(u32 index) std::shared_ptr<CPUThread> CPUThreadManager::GetRawSPUThread(u32 index)

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
class CPUThread; class CPUThread;
class RawSPUThread;
enum CPUThreadType : unsigned char; enum CPUThreadType : unsigned char;
class CPUThreadManager class CPUThreadManager

View file

@ -4,6 +4,7 @@
#ifdef LLVM_AVAILABLE #ifdef LLVM_AVAILABLE
#define PPU_LLVM_RECOMPILER 1 #define PPU_LLVM_RECOMPILER 1
#include <list>
#include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPUInterpreter.h"

View file

@ -1,6 +1,6 @@
#include "stdafx_gui.h" #include "stdafx_gui.h"
#include "PPUProgramCompiler.h" #include "PPUProgramCompiler.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
/* /*
using namespace PPU_instr; using namespace PPU_instr;

View file

@ -663,7 +663,7 @@ void PPUThread::FastCall2(u32 addr, u32 rtoc)
{ {
auto old_status = m_status; auto old_status = m_status;
auto old_PC = PC; auto old_PC = PC;
auto old_stack = GPR[1]; // only saved and restored (may be wrong) auto old_stack = GPR[1];
auto old_rtoc = GPR[2]; auto old_rtoc = GPR[2];
auto old_LR = LR; auto old_LR = LR;
auto old_thread = GetCurrentNamedThread(); auto old_thread = GetCurrentNamedThread();
@ -680,7 +680,13 @@ void PPUThread::FastCall2(u32 addr, u32 rtoc)
m_status = old_status; m_status = old_status;
PC = old_PC; PC = old_PC;
GPR[1] = old_stack;
if (GPR[1] != old_stack && !Emu.IsStopped()) // GPR[1] shouldn't change
{
LOG_ERROR(PPU, "PPUThread::FastCall2(0x%x,0x%x): stack inconsistency (SP=0x%llx, old=0x%llx)", addr, rtoc, GPR[1], old_stack);
GPR[1] = old_stack;
}
GPR[2] = old_rtoc; GPR[2] = old_rtoc;
LR = old_LR; LR = old_LR;
SetCurrentNamedThread(old_thread); SetCurrentNamedThread(old_thread);

View file

@ -18,26 +18,6 @@
#define rotl32(x,r) (((u32)(x) << (r)) | ((u32)(x) >> (32 - (r)))) #define rotl32(x,r) (((u32)(x) << (r)) | ((u32)(x) >> (32 - (r))))
#endif #endif
class spu_scale_table_t
{
std::array<__m128, 155 + 174> m_data;
public:
spu_scale_table_t()
{
for (s32 i = -155; i < 174; i++)
{
m_data[i + 155] = _mm_set1_ps(static_cast<float>(exp2(i)));
}
}
__forceinline __m128 operator [] (s32 scale) const
{
return m_data[scale + 155];
}
}
const g_spu_scale_table;
void spu_interpreter::DEFAULT(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::DEFAULT(SPUThread& CPU, spu_opcode_t op)
{ {
@ -405,17 +385,17 @@ void spu_interpreter::GBB(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::FSM(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FSM(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = g_imm_table.fsm_table[CPU.GPR[op.ra]._u32[3] & 0xf]; CPU.GPR[op.rt] = g_spu_imm.fsm[CPU.GPR[op.ra]._u32[3] & 0xf];
} }
void spu_interpreter::FSMH(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FSMH(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = g_imm_table.fsmh_table[CPU.GPR[op.ra]._u32[3] & 0xff]; CPU.GPR[op.rt] = g_spu_imm.fsmh[CPU.GPR[op.ra]._u32[3] & 0xff];
} }
void spu_interpreter::FSMB(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FSMB(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = g_imm_table.fsmb_table[CPU.GPR[op.ra]._u32[3] & 0xffff]; CPU.GPR[op.rt] = g_spu_imm.fsmb[CPU.GPR[op.ra]._u32[3] & 0xffff];
} }
void spu_interpreter::FREST(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FREST(SPUThread& CPU, spu_opcode_t op)
@ -436,17 +416,17 @@ void spu_interpreter::LQX(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::ROTQBYBI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQBYBI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.rldq_pshufb[CPU.GPR[op.rb]._u32[3] >> 3 & 0xf]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.rldq_pshufb[CPU.GPR[op.rb]._u32[3] >> 3 & 0xf].vi);
} }
void spu_interpreter::ROTQMBYBI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQMBYBI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.srdq_pshufb[-(CPU.GPR[op.rb]._s32[3] >> 3) & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.srdq_pshufb[-(CPU.GPR[op.rb]._s32[3] >> 3) & 0x1f].vi);
} }
void spu_interpreter::SHLQBYBI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::SHLQBYBI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.sldq_pshufb[CPU.GPR[op.rb]._u32[3] >> 3 & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.sldq_pshufb[CPU.GPR[op.rb]._u32[3] >> 3 & 0x1f].vi);
} }
void spu_interpreter::CBX(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CBX(SPUThread& CPU, spu_opcode_t op)
@ -500,17 +480,17 @@ void spu_interpreter::SHLQBI(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::ROTQBY(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQBY(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.rldq_pshufb[CPU.GPR[op.rb]._u32[3] & 0xf]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.rldq_pshufb[CPU.GPR[op.rb]._u32[3] & 0xf].vi);
} }
void spu_interpreter::ROTQMBY(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQMBY(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.srdq_pshufb[-CPU.GPR[op.rb]._s32[3] & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.srdq_pshufb[-CPU.GPR[op.rb]._s32[3] & 0x1f].vi);
} }
void spu_interpreter::SHLQBY(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::SHLQBY(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.sldq_pshufb[CPU.GPR[op.rb]._u32[3] & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.sldq_pshufb[CPU.GPR[op.rb]._u32[3] & 0x1f].vi);
} }
void spu_interpreter::ORX(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ORX(SPUThread& CPU, spu_opcode_t op)
@ -569,17 +549,17 @@ void spu_interpreter::SHLQBII(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::ROTQBYI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQBYI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.rldq_pshufb[op.i7 & 0xf]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.rldq_pshufb[op.i7 & 0xf].vi);
} }
void spu_interpreter::ROTQMBYI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ROTQMBYI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.srdq_pshufb[-op.si7 & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.srdq_pshufb[-op.si7 & 0x1f].vi);
} }
void spu_interpreter::SHLQBYI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::SHLQBYI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_imm_table.sldq_pshufb[op.i7 & 0x1f]); CPU.GPR[op.rt].vi = _mm_shuffle_epi8(CPU.GPR[op.ra].vi, g_spu_imm.sldq_pshufb[op.i7 & 0x1f].vi);
} }
void spu_interpreter::NOP(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::NOP(SPUThread& CPU, spu_opcode_t op)
@ -770,9 +750,9 @@ void spu_interpreter::CEQ(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::MPYHHU(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::MPYHHU(SPUThread& CPU, spu_opcode_t op)
{ {
const auto a = _mm_srli_epi32(CPU.GPR[op.ra].vi, 16); const auto a = CPU.GPR[op.ra].vi;
const auto b = _mm_srli_epi32(CPU.GPR[op.rb].vi, 16); const auto b = CPU.GPR[op.rb].vi;
CPU.GPR[op.rt].vi = _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, b), 16), _mm_mullo_epi16(a, b)); CPU.GPR[op.rt].vi = _mm_or_si128(_mm_srli_epi32(_mm_mullo_epi16(a, b), 16), _mm_and_si128(_mm_mulhi_epu16(a, b), _mm_set1_epi32(0xffff0000)));
} }
void spu_interpreter::ADDX(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::ADDX(SPUThread& CPU, spu_opcode_t op)
@ -810,9 +790,9 @@ void spu_interpreter::MPYHHA(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::MPYHHAU(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::MPYHHAU(SPUThread& CPU, spu_opcode_t op)
{ {
const auto a = _mm_srli_epi32(CPU.GPR[op.ra].vi, 16); const auto a = CPU.GPR[op.ra].vi;
const auto b = _mm_srli_epi32(CPU.GPR[op.rb].vi, 16); const auto b = CPU.GPR[op.rb].vi;
CPU.GPR[op.rt].vi = _mm_add_epi32(CPU.GPR[op.rt].vi, _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, b), 16), _mm_mullo_epi16(a, b))); CPU.GPR[op.rt].vi = _mm_add_epi32(CPU.GPR[op.rt].vi, _mm_or_si128(_mm_srli_epi32(_mm_mullo_epi16(a, b), 16), _mm_and_si128(_mm_mulhi_epu16(a, b), _mm_set1_epi32(0xffff0000))));
} }
void spu_interpreter::FSCRRD(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FSCRRD(SPUThread& CPU, spu_opcode_t op)
@ -890,9 +870,9 @@ void spu_interpreter::DFCMEQ(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::MPYU(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::MPYU(SPUThread& CPU, spu_opcode_t op)
{ {
const auto a = _mm_and_si128(CPU.GPR[op.ra].vi, _mm_set1_epi32(0xffff)); const auto a = CPU.GPR[op.ra].vi;
const auto b = _mm_and_si128(CPU.GPR[op.rb].vi, _mm_set1_epi32(0xffff)); const auto b = CPU.GPR[op.rb].vi;
CPU.GPR[op.rt].vi = _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, b), 16), _mm_mullo_epi16(a, b)); CPU.GPR[op.rt].vi = _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, b), 16), _mm_and_si128(_mm_mullo_epi16(a, b), _mm_set1_epi32(0xffff)));
} }
void spu_interpreter::CEQB(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CEQB(SPUThread& CPU, spu_opcode_t op)
@ -907,8 +887,8 @@ void spu_interpreter::FI(SPUThread& CPU, spu_opcode_t op)
const auto mask_sf = _mm_set1_epi32(0x000003ff); // step fraction mask const auto mask_sf = _mm_set1_epi32(0x000003ff); // step fraction mask
const auto mask_yf = _mm_set1_epi32(0x0007ffff); // Y fraction mask (bits 13..31) const auto mask_yf = _mm_set1_epi32(0x0007ffff); // Y fraction mask (bits 13..31)
const auto base = _mm_or_ps(_mm_and_ps(CPU.GPR[op.rb].vf, mask_bf), _mm_castsi128_ps(_mm_set1_epi32(0x3f800000))); const auto base = _mm_or_ps(_mm_and_ps(CPU.GPR[op.rb].vf, mask_bf), _mm_castsi128_ps(_mm_set1_epi32(0x3f800000)));
const auto step = _mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(CPU.GPR[op.rb].vi, mask_sf)), g_spu_scale_table[-13]); const auto step = _mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(CPU.GPR[op.rb].vi, mask_sf)), _mm_set1_ps(exp2f(-13)));
const auto y = _mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(CPU.GPR[op.ra].vi, mask_yf)), g_spu_scale_table[-19]); const auto y = _mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(CPU.GPR[op.ra].vi, mask_yf)), _mm_set1_ps(exp2f(-19)));
CPU.GPR[op.rt].vf = _mm_or_ps(_mm_and_ps(mask_se, CPU.GPR[op.rb].vf), _mm_andnot_ps(mask_se, _mm_sub_ps(base, _mm_mul_ps(step, y)))); CPU.GPR[op.rt].vf = _mm_or_ps(_mm_and_ps(mask_se, CPU.GPR[op.rb].vf), _mm_andnot_ps(mask_se, _mm_sub_ps(base, _mm_mul_ps(step, y))));
} }
@ -923,27 +903,27 @@ void spu_interpreter::HEQ(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::CFLTS(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CFLTS(SPUThread& CPU, spu_opcode_t op)
{ {
const auto scaled = _mm_mul_ps(CPU.GPR[op.ra].vf, g_spu_scale_table[173 - op.i8]); const auto scaled = _mm_mul_ps(CPU.GPR[op.ra].vf, g_spu_imm.scale[173 - op.i8]);
CPU.GPR[op.rt].vi = _mm_xor_si128(_mm_cvttps_epi32(scaled), _mm_castps_si128(_mm_cmpge_ps(scaled, _mm_set1_ps(0x80000000)))); CPU.GPR[op.rt].vi = _mm_xor_si128(_mm_cvttps_epi32(scaled), _mm_castps_si128(_mm_cmpge_ps(scaled, _mm_set1_ps(0x80000000))));
} }
void spu_interpreter::CFLTU(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CFLTU(SPUThread& CPU, spu_opcode_t op)
{ {
const auto scaled1 = _mm_max_ps(_mm_mul_ps(CPU.GPR[op.ra].vf, g_spu_scale_table[173 - op.i8]), _mm_set1_ps(0.0f)); const auto scaled1 = _mm_max_ps(_mm_mul_ps(CPU.GPR[op.ra].vf, g_spu_imm.scale[173 - op.i8]), _mm_set1_ps(0.0f));
const auto scaled2 = _mm_and_ps(_mm_sub_ps(scaled1, _mm_set1_ps(0x80000000)), _mm_cmpge_ps(scaled1, _mm_set1_ps(0x80000000))); const auto scaled2 = _mm_and_ps(_mm_sub_ps(scaled1, _mm_set1_ps(0x80000000)), _mm_cmpge_ps(scaled1, _mm_set1_ps(0x80000000)));
CPU.GPR[op.rt].vi = _mm_or_si128(_mm_or_si128(_mm_cvttps_epi32(scaled1), _mm_cvttps_epi32(scaled2)), _mm_castps_si128(_mm_cmpge_ps(scaled1, _mm_set1_ps(0x100000000)))); CPU.GPR[op.rt].vi = _mm_or_si128(_mm_or_si128(_mm_cvttps_epi32(scaled1), _mm_cvttps_epi32(scaled2)), _mm_castps_si128(_mm_cmpge_ps(scaled1, _mm_set1_ps(0x100000000))));
} }
void spu_interpreter::CSFLT(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CSFLT(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vf = _mm_mul_ps(_mm_cvtepi32_ps(CPU.GPR[op.ra].vi), g_spu_scale_table[op.i8 - 155]); CPU.GPR[op.rt].vf = _mm_mul_ps(_mm_cvtepi32_ps(CPU.GPR[op.ra].vi), g_spu_imm.scale[op.i8 - 155]);
} }
void spu_interpreter::CUFLT(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::CUFLT(SPUThread& CPU, spu_opcode_t op)
{ {
const auto a = CPU.GPR[op.ra].vi; const auto a = CPU.GPR[op.ra].vi;
const auto fix = _mm_and_ps(_mm_castsi128_ps(_mm_srai_epi32(a, 31)), _mm_set1_ps(0x80000000)); const auto fix = _mm_and_ps(_mm_castsi128_ps(_mm_srai_epi32(a, 31)), _mm_set1_ps(0x80000000));
CPU.GPR[op.rt].vf = _mm_mul_ps(_mm_add_ps(_mm_cvtepi32_ps(_mm_and_si128(a, _mm_set1_epi32(0x7fffffff))), fix), g_spu_scale_table[op.i8 - 155]); CPU.GPR[op.rt].vf = _mm_mul_ps(_mm_add_ps(_mm_cvtepi32_ps(_mm_and_si128(a, _mm_set1_epi32(0x7fffffff))), fix), g_spu_imm.scale[op.i8 - 155]);
} }
@ -1013,7 +993,7 @@ void spu_interpreter::BR(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::FSMBI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::FSMBI(SPUThread& CPU, spu_opcode_t op)
{ {
CPU.GPR[op.rt].vi = g_imm_table.fsmb_table[op.i16]; CPU.GPR[op.rt] = g_spu_imm.fsmb[op.i16];
} }
void spu_interpreter::BRSL(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::BRSL(SPUThread& CPU, spu_opcode_t op)
@ -1177,7 +1157,7 @@ void spu_interpreter::MPYI(SPUThread& CPU, spu_opcode_t op)
void spu_interpreter::MPYUI(SPUThread& CPU, spu_opcode_t op) void spu_interpreter::MPYUI(SPUThread& CPU, spu_opcode_t op)
{ {
const auto a = _mm_and_si128(CPU.GPR[op.ra].vi, _mm_set1_epi32(0xffff)); const auto a = CPU.GPR[op.ra].vi;
const auto i = _mm_set1_epi32(op.si10 & 0xffff); const auto i = _mm_set1_epi32(op.si10 & 0xffff);
CPU.GPR[op.rt].vi = _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, i), 16), _mm_mullo_epi16(a, i)); CPU.GPR[op.rt].vi = _mm_or_si128(_mm_slli_epi32(_mm_mulhi_epu16(a, i), 16), _mm_mullo_epi16(a, i));
} }

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "Emu/SysCalls/lv2/sys_time.h" #include "Emu/SysCalls/lv2/sys_time.h"
@ -13,8 +13,6 @@
#include "SPUInterpreter.h" #include "SPUInterpreter.h"
#include "SPURecompiler.h" #include "SPURecompiler.h"
const g_imm_table_struct g_imm_table;
SPURecompilerCore::SPURecompilerCore(SPUThread& cpu) SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
: m_enc(new SPURecompiler(cpu, *this)) : m_enc(new SPURecompiler(cpu, *this))
, inter(new SPUInterpreter(cpu)) , inter(new SPUInterpreter(cpu))
@ -25,11 +23,6 @@ SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
memset(entry, 0, sizeof(entry)); memset(entry, 0, sizeof(entry));
X86CpuInfo inf; X86CpuInfo inf;
X86CpuUtil::detect(&inf); X86CpuUtil::detect(&inf);
if (!inf.hasFeature(kX86CpuFeatureSSE4_1))
{
LOG_ERROR(SPU, "SPU JIT requires SSE4.1 instruction set support");
Emu.Pause();
}
} }
SPURecompilerCore::~SPURecompilerCore() SPURecompilerCore::~SPURecompilerCore()
@ -45,22 +38,22 @@ void SPURecompilerCore::Decode(const u32 code) // decode instruction and run wit
void SPURecompilerCore::Compile(u16 pos) void SPURecompilerCore::Compile(u16 pos)
{ {
const u64 stamp0 = get_system_time(); //const u64 stamp0 = get_system_time();
u64 time0 = 0; //u64 time0 = 0;
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); //SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
dis_asm.offset = vm::get_ptr<u8>(CPU.offset); //dis_asm.offset = vm::get_ptr<u8>(CPU.offset);
StringLogger stringLogger; //StringLogger stringLogger;
stringLogger.setOption(kLoggerOptionBinaryForm, true); //stringLogger.setOption(kLoggerOptionBinaryForm, true);
X86Compiler compiler(&runtime); X86Compiler compiler(&runtime);
m_enc->compiler = &compiler; m_enc->compiler = &compiler;
compiler.setLogger(&stringLogger); //compiler.setLogger(&stringLogger);
compiler.addFunc(kFuncConvHost, FuncBuilder4<u32, void*, void*, void*, u32>()); compiler.addFunc(kFuncConvHost, FuncBuilder4<u32, void*, void*, void*, u32>());
const u16 start = pos; const u16 start = pos;
u32 excess = 0; //u32 excess = 0;
entry[start].count = 0; entry[start].count = 0;
X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu"); X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu");
@ -107,11 +100,11 @@ void SPURecompilerCore::Compile(u16 pos)
m_enc->do_finalize = false; m_enc->do_finalize = false;
if (opcode) if (opcode)
{ {
const u64 stamp1 = get_system_time(); //const u64 stamp1 = get_system_time();
// disasm for logging: // disasm for logging:
dis_asm.dump_pc = pos * 4; //dis_asm.dump_pc = pos * 4;
(*SPU_instr::rrr_list)(&dis_asm, opcode); //(*SPU_instr::rrr_list)(&dis_asm, opcode);
compiler.addComment(fmt::Format("SPU data: PC=0x%05x %s", pos * 4, dis_asm.last_opcode.c_str()).c_str()); //compiler.addComment(fmt::Format("SPU data: PC=0x%05x %s", pos * 4, dis_asm.last_opcode.c_str()).c_str());
// compile single opcode: // compile single opcode:
(*SPU_instr::rrr_list)(m_enc, opcode); (*SPU_instr::rrr_list)(m_enc, opcode);
// force finalization between every slice using absolute alignment // force finalization between every slice using absolute alignment
@ -121,17 +114,17 @@ void SPURecompilerCore::Compile(u16 pos)
m_enc->do_finalize = true; m_enc->do_finalize = true;
}*/ }*/
entry[start].count++; entry[start].count++;
time0 += get_system_time() - stamp1; //time0 += get_system_time() - stamp1;
} }
else else
{ {
m_enc->do_finalize = true; m_enc->do_finalize = true;
} }
bool fin = m_enc->do_finalize; bool fin = m_enc->do_finalize;
if (entry[pos].valid == re32(opcode)) //if (entry[pos].valid == re32(opcode))
{ //{
excess++; // excess++;
} //}
entry[pos].valid = re32(opcode); entry[pos].valid = re32(opcode);
if (fin) break; if (fin) break;
@ -148,34 +141,28 @@ void SPURecompilerCore::Compile(u16 pos)
m_enc->xmm_var[i].data = nullptr; m_enc->xmm_var[i].data = nullptr;
} }
const u64 stamp1 = get_system_time(); //const u64 stamp1 = get_system_time();
compiler.ret(pos_var); compiler.ret(pos_var);
compiler.endFunc(); compiler.endFunc();
entry[start].pointer = compiler.make(); entry[start].pointer = compiler.make();
compiler.setLogger(nullptr); // crashes without it compiler.setLogger(nullptr); // crashes without it
rFile log; //std::string log = fmt::format("========== START POSITION 0x%x ==========\n\n", start * 4);
log.Open(fmt::Format("SPUjit_%d.log", GetCurrentSPUThread().GetId()), first ? rFile::write : rFile::write_append); //log += stringLogger.getString();
log.Write(fmt::Format("========== START POSITION 0x%x ==========\n\n", start * 4)); //if (!entry[start].pointer)
log.Write(std::string(stringLogger.getString())); //{
if (!entry[start].pointer) // LOG_ERROR(Log::SPU, "SPURecompilerCore::Compile(pos=0x%x) failed", start * sizeof(u32));
{ // log += "========== FAILED ============\n\n";
LOG_ERROR(Log::SPU, "SPURecompilerCore::Compile(pos=0x%x) failed", start * sizeof(u32)); // Emu.Pause();
log.Write("========== FAILED ============\n\n"); //}
Emu.Pause(); //else
} //{
else // log += fmt::format("========== COMPILED %d (excess %d), time: [start=%lld (decoding=%lld), finalize=%lld]\n\n",
{ // entry[start].count, excess, stamp1 - stamp0, time0, get_system_time() - stamp1);
log.Write(fmt::Format("========== COMPILED %d (excess %d), time: [start=%lld (decoding=%lld), finalize=%lld]\n\n", //}
entry[start].count, excess, stamp1 - stamp0, time0, get_system_time() - stamp1));
#ifdef _WIN32 //fs::file(fmt::Format("SPUjit_%d.log", this->CPU.GetId()), o_write | o_create | (first ? o_trunc : o_append)).write(log.c_str(), log.size());
//if (!RtlAddFunctionTable(&info, 1, (u64)entry[start].pointer))
//{
// LOG_ERROR(Log::SPU, "RtlAddFunctionTable() failed");
//}
#endif
}
log.Close();
m_enc->compiler = nullptr; m_enc->compiler = nullptr;
first = false; first = false;
} }
@ -217,9 +204,6 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address)
i < (u32)pos + (u32)entry[pos].count) i < (u32)pos + (u32)entry[pos].count)
{ {
runtime.release(entry[i].pointer); runtime.release(entry[i].pointer);
#ifdef _WIN32
//RtlDeleteFunctionTable(&entry[i].info);
#endif
entry[i].pointer = nullptr; entry[i].pointer = nullptr;
for (u32 j = i; j < i + (u32)entry[i].count; j++) for (u32 j = i; j < i + (u32)entry[i].count; j++)
{ {
@ -264,7 +248,7 @@ u32 SPURecompilerCore::DecodeMemory(const u32 address)
} }
u32 res = pos; u32 res = pos;
res = func(cpu, vm::get_ptr<void>(m_offset), imm_table.data(), &g_imm_table); res = func(cpu, vm::get_ptr<void>(m_offset), imm_table.data(), &g_spu_imm);
if (res & 0x1000000) if (res & 0x1000000)
{ {

View file

@ -22,6 +22,8 @@
#include <cfenv> #include <cfenv>
const g_spu_imm_table_t g_spu_imm;
class spu_inter_func_list_t class spu_inter_func_list_t
{ {
std::array<spu_inter_func_t, 2048> funcs; std::array<spu_inter_func_t, 2048> funcs;
@ -235,14 +237,14 @@ void SPUThread::FastCall(u32 ls_addr)
m_status = Running; m_status = Running;
PC = ls_addr; PC = ls_addr;
GPR[0]._u32[3] = 0x0; GPR[0]._u32[3] = 0x0;
m_custom_task.swap(m_custom_task); m_custom_task.swap(old_task);
SPUThread::Task(); SPUThread::Task();
PC = old_PC; PC = old_PC;
GPR[0]._u32[3] = old_LR; GPR[0]._u32[3] = old_LR;
GPR[1]._u32[3] = old_stack; GPR[1]._u32[3] = old_stack;
m_custom_task.swap(m_custom_task); m_custom_task.swap(old_task);
} }
void SPUThread::FastStop() void SPUThread::FastStop()
@ -271,12 +273,11 @@ void SPUThread::do_dma_transfer(u32 cmd, spu_mfc_arg_t args)
const u32 index = (eal - SYS_SPU_THREAD_BASE_LOW) / SYS_SPU_THREAD_OFFSET; // thread number in group const u32 index = (eal - SYS_SPU_THREAD_BASE_LOW) / SYS_SPU_THREAD_OFFSET; // thread number in group
const u32 offset = (eal - SYS_SPU_THREAD_BASE_LOW) % SYS_SPU_THREAD_OFFSET; // LS offset or MMIO register const u32 offset = (eal - SYS_SPU_THREAD_BASE_LOW) % SYS_SPU_THREAD_OFFSET; // LS offset or MMIO register
std::shared_ptr<spu_group_t> group = tg.lock(); const auto group = tg.lock();
std::shared_ptr<CPUThread> t;
if (group && index < group->num && (t = group->threads[index])) if (group && index < group->num && group->threads[index])
{ {
auto& spu = static_cast<SPUThread&>(*t); auto& spu = static_cast<SPUThread&>(*group->threads[index]);
if (offset + args.size - 1 < 0x40000) // LS access if (offset + args.size - 1 < 0x40000) // LS access
{ {
@ -487,6 +488,7 @@ u32 SPUThread::get_ch_count(u32 ch)
switch (ch) switch (ch)
{ {
//case MFC_Cmd: return 16;
//case SPU_WrSRR0: return 1; break; //case SPU_WrSRR0: return 1; break;
//case SPU_RdSRR0: return 1; break; //case SPU_RdSRR0: return 1; break;
case SPU_WrOutMbox: return ch_out_mbox.get_count() ^ 1; break; case SPU_WrOutMbox: return ch_out_mbox.get_count() ^ 1; break;
@ -671,7 +673,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue = this->spup[spup].lock(); const auto queue = this->spup[spup].lock();
if (!queue) if (!queue)
{ {
@ -684,7 +686,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
return ch_in_mbox.push_uncond(CELL_EBUSY); return ch_in_mbox.push_uncond(CELL_EBUSY);
} }
queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data); queue->push(lv2_lock, SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
return ch_in_mbox.push_uncond(CELL_OK); return ch_in_mbox.push_uncond(CELL_OK);
} }
@ -708,7 +710,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_queue_t> queue = this->spup[spup].lock(); const auto queue = this->spup[spup].lock();
if (!queue) if (!queue)
{ {
@ -723,7 +725,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
return; return;
} }
queue->push(SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data); queue->push(lv2_lock, SYS_SPU_THREAD_EVENT_USER_KEY, GetId(), ((u64)spup << 32) | (value & 0x00ffffff), data);
return; return;
} }
else if (code == 128) else if (code == 128)
@ -751,9 +753,9 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(data);
if (!Emu.GetIdManager().GetIDData(data, ef)) if (!ef)
{ {
return ch_in_mbox.push_uncond(CELL_ESRCH); return ch_in_mbox.push_uncond(CELL_ESRCH);
} }
@ -797,9 +799,9 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<event_flag_t> ef; const auto ef = Emu.GetIdManager().GetIDData<event_flag_t>(data);
if (!Emu.GetIdManager().GetIDData(data, ef)) if (!ef)
{ {
return; return;
} }
@ -1119,7 +1121,7 @@ void SPUThread::stop_and_signal(u32 code)
LV2_LOCK; LV2_LOCK;
std::shared_ptr<spu_group_t> group = tg.lock(); const auto group = tg.lock();
if (!group) if (!group)
{ {

View file

@ -315,51 +315,89 @@ public:
} }
}; };
#define mmToU64Ptr(x) ((u64*)(&x)) struct g_spu_imm_table_t
#define mmToU32Ptr(x) ((u32*)(&x))
#define mmToU16Ptr(x) ((u16*)(&x))
#define mmToU8Ptr(x) ((u8*)(&x))
struct g_imm_table_struct
{ {
__m128i fsmb_table[65536]; u128 fsmb[65536]; // table for FSMB, FSMBI instructions
__m128i fsmh_table[256]; u128 fsmh[256]; // table for FSMH instruction
__m128i fsm_table[16]; u128 fsm[16]; // table for FSM instruction
__m128i sldq_pshufb[32]; u128 sldq_pshufb[32]; // table for SHLQBYBI, SHLQBY, SHLQBYI instructions
__m128i srdq_pshufb[32]; u128 srdq_pshufb[32]; // table for ROTQMBYBI, ROTQMBY, ROTQMBYI instructions
__m128i rldq_pshufb[16]; u128 rldq_pshufb[16]; // table for ROTQBYBI, ROTQBY, ROTQBYI instructions
g_imm_table_struct() class scale_table_t
{ {
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++) std::array<__m128, 155 + 174> m_data;
public:
scale_table_t()
{ {
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0; for (s32 i = -155; i < 174; i++)
{
m_data[i + 155] = _mm_set1_ps(static_cast<float>(exp2(i)));
}
} }
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
__forceinline __m128 operator [] (s32 scale) const
{ {
for (u32 j = 0; j < 8; j++) mmToU16Ptr(fsmh_table[i])[j] = (i & (1 << j)) ? ~0 : 0; return m_data[scale + 155];
} }
for (u32 i = 0; i < sizeof(fsmb_table) / sizeof(fsmb_table[0]); i++) }
const scale;
g_spu_imm_table_t()
{
for (u32 i = 0; i < sizeof(fsm) / sizeof(fsm[0]); i++)
{ {
for (u32 j = 0; j < 16; j++) mmToU8Ptr(fsmb_table[i])[j] = (i & (1 << j)) ? ~0 : 0; for (u32 j = 0; j < 4; j++)
{
fsm[i]._u32[j] = (i & (1 << j)) ? 0xffffffff : 0;
}
} }
for (u32 i = 0; i < sizeof(fsmh) / sizeof(fsmh[0]); i++)
{
for (u32 j = 0; j < 8; j++)
{
fsmh[i]._u16[j] = (i & (1 << j)) ? 0xffff : 0;
}
}
for (u32 i = 0; i < sizeof(fsmb) / sizeof(fsmb[0]); i++)
{
for (u32 j = 0; j < 16; j++)
{
fsmb[i]._u8[j] = (i & (1 << j)) ? 0xff : 0;
}
}
for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++) for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++)
{ {
for (u32 j = 0; j < 16; j++) mmToU8Ptr(sldq_pshufb[i])[j] = (u8)(j - i); for (u32 j = 0; j < 16; j++)
{
sldq_pshufb[i]._u8[j] = static_cast<u8>(j - i);
}
} }
for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++) for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++)
{ {
for (u32 j = 0; j < 16; j++) mmToU8Ptr(srdq_pshufb[i])[j] = (j + i > 15) ? 0xff : (u8)(j + i); for (u32 j = 0; j < 16; j++)
{
srdq_pshufb[i]._u8[j] = (j + i > 15) ? 0xff : static_cast<u8>(j + i);
}
} }
for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++) for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++)
{ {
for (u32 j = 0; j < 16; j++) mmToU8Ptr(rldq_pshufb[i])[j] = (u8)(j - i) & 0xf; for (u32 j = 0; j < 16; j++)
{
rldq_pshufb[i]._u8[j] = static_cast<u8>((j - i) & 0xf);
}
} }
} }
}; };
extern const g_imm_table_struct g_imm_table; extern const g_spu_imm_table_t g_spu_imm;
enum FPSCR_EX enum FPSCR_EX
{ {

View file

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/lv2/sleep_queue.h" #include "Emu/SysCalls/lv2/sleep_queue.h"
#include "Emu/SysCalls/lv2/sys_event.h" #include "Emu/SysCalls/lv2/sys_event.h"

View file

@ -6,22 +6,20 @@
#include "Ini.h" #include "Ini.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include <sys/stat.h> // To check whether directory exists
#undef CreateFile
std::vector<std::string> simplify_path_blocks(const std::string& path) std::vector<std::string> simplify_path_blocks(const std::string& path)
{ {
// fmt::tolower() removed // fmt::tolower() removed
std::vector<std::string> path_blocks = std::move(fmt::split(path, { "/", "\\" })); std::vector<std::string> path_blocks = std::move(fmt::split(path, { "/", "\\" }));
for (size_t i = 0; i < path_blocks.size(); ++i) for (s32 i = 0; i < path_blocks.size(); ++i)
{ {
if (path_blocks[i] == ".") if (path_blocks[i] == "." || (i > 0 && path_blocks[i].empty()))
{ {
path_blocks.erase(path_blocks.begin() + i--); path_blocks.erase(path_blocks.begin() + i);
i--;
} }
else if (i && path_blocks[i] == "..") else if (i > 0 && path_blocks[i] == "..")
{ {
path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1)); path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1));
i--; i--;
@ -132,9 +130,10 @@ void VFS::UnMountAll()
m_devices.clear(); m_devices.clear();
} }
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const vfsFileBase* VFS::OpenFile(const std::string& ps3_path, u32 mode) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
if (vfsFileBase* res = dev->GetNewFileStream()) if (vfsFileBase* res = dev->GetNewFileStream())
@ -163,28 +162,13 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
return nullptr; return nullptr;
} }
bool VFS::CreateFile(const std::string& ps3_path, bool overwrite) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if (res)
{
return res->Create(path, overwrite);
}
}
return false;
}
bool VFS::CreateDir(const std::string& ps3_path) const bool VFS::CreateDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::unique_ptr<vfsDirBase> res(dev->GetNewDirStream());
if (res) if (res)
{ {
@ -195,12 +179,25 @@ bool VFS::CreateDir(const std::string& ps3_path) const
return false; return false;
} }
bool VFS::CreatePath(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
return fs::create_path(path);
}
return false;
}
bool VFS::RemoveFile(const std::string& ps3_path) const bool VFS::RemoveFile(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::unique_ptr<vfsFileBase> res(dev->GetNewFileStream());
if (res) if (res)
{ {
@ -214,9 +211,10 @@ bool VFS::RemoveFile(const std::string& ps3_path) const
bool VFS::RemoveDir(const std::string& ps3_path) const bool VFS::RemoveDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::unique_ptr<vfsDirBase> res(dev->GetNewDirStream());
if (res) if (res)
{ {
@ -230,9 +228,10 @@ bool VFS::RemoveDir(const std::string& ps3_path) const
bool VFS::ExistsFile(const std::string& ps3_path) const bool VFS::ExistsFile(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::unique_ptr<vfsFileBase> res(dev->GetNewFileStream());
if (res) if (res)
{ {
@ -246,9 +245,10 @@ bool VFS::ExistsFile(const std::string& ps3_path) const
bool VFS::ExistsDir(const std::string& ps3_path) const bool VFS::ExistsDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::unique_ptr<vfsDirBase> res(dev->GetNewDirStream());
if (res) if (res)
{ {
@ -267,7 +267,7 @@ bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_pa
{ {
if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to)) if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::unique_ptr<vfsFileBase> res(dev->GetNewFileStream());
if (res) if (res)
{ {
@ -287,7 +287,7 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
{ {
if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to)) if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::unique_ptr<vfsDirBase> res(dev->GetNewDirStream());
if (res) if (res)
{ {
@ -299,6 +299,33 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
return false; return false;
} }
bool VFS::CopyFile(const std::string& ps3_path_from, const std::string& ps3_path_to, bool overwrite) const
{
std::string path_from, path_to;
if (vfsDevice* dev = GetDevice(ps3_path_from, path_from))
{
if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to))
{
return fs::copy_file(path_from, path_to, overwrite);
}
}
return false;
}
bool VFS::TruncateFile(const std::string& ps3_path, u64 length) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
return fs::truncate_file(path, length);
}
return false;
}
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{ {
auto try_get_device = [this, &path](const std::string& ps3_path) -> vfsDevice* auto try_get_device = [this, &path](const std::string& ps3_path) -> vfsDevice*
@ -464,7 +491,6 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_flash/", "/dev_flash/"); res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_flash/", "/dev_flash/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb000/"); res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb000/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb/"); res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../../", "/dev_bdvd/");
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/"); res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");
return; return;
@ -478,33 +504,25 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entries_count.SaveValue(count); entries_count.SaveValue(count);
} }
// Custom EmulationDir. // Custom EmulationDir
// TODO:: should have a better log that would show results before loading a game?
if (Ini.SysEmulationDirPathEnable.GetValue()) if (Ini.SysEmulationDirPathEnable.GetValue())
{ {
std::string EmulationDir = Ini.SysEmulationDirPath.GetValue(); std::string dir = Ini.SysEmulationDirPath.GetValue();
if (EmulationDir.empty())
Ini.SysEmulationDirPath.SetValue(Emu.GetEmulatorPath()); if (dir.empty())
struct stat fstatinfo;
if ((stat(EmulationDir.c_str(), &fstatinfo)))
{ {
LOG_NOTICE(GENERAL, "Custom EmualtionDir: Tried %s but it doesn't exists. Maybe you add some not needed chars like '\"'?"); Ini.SysEmulationDirPath.SetValue(Emu.GetEmulatorPath());
Ini.SysEmulationDirPathEnable.SetValue(false); }
if (!fs::is_dir(dir))
{
LOG_ERROR(GENERAL, "Custom EmulationDir: directory '%s' not found", dir);
} }
else if (fstatinfo.st_mode & S_IFDIR)
LOG_NOTICE(GENERAL, "Custom EmualtionDir: On, Binded $(EmulatorDir) to %s.", EmulationDir);
else else
{ {
// If that is not directory turn back to use original one. LOG_NOTICE(GENERAL, "Custom EmulationDir: $(EmulatorDir) bound to '%s'", dir);
LOG_NOTICE(GENERAL, "Custom EmulationDir: Cause path %s is not a valid directory.", EmulationDir);
Ini.SysEmulationDirPathEnable.SetValue(false);
} }
} }
// I left this to check again just to catch those failed in directory checks.
if (!Ini.SysEmulationDirPathEnable.GetValue())
{
LOG_NOTICE(GENERAL, "Custom EmualtionDir: Off, Binded $(EmulatorDir) to %s.", Emu.GetEmulatorPath());
}
for(int i=0; i<count; ++i) for(int i=0; i<count; ++i)
{ {

View file

@ -4,7 +4,6 @@
class vfsDevice; class vfsDevice;
struct vfsFileBase; struct vfsFileBase;
class vfsDirBase; class vfsDirBase;
enum vfsOpenMode : u8;
enum vfsDeviceType enum vfsDeviceType
{ {
@ -76,16 +75,18 @@ struct VFS
std::string GetLinked(const std::string& ps3_path) const; std::string GetLinked(const std::string& ps3_path) const;
vfsFileBase* OpenFile(const std::string& ps3_path, vfsOpenMode mode) const; vfsFileBase* OpenFile(const std::string& ps3_path, u32 mode) const;
vfsDirBase* OpenDir(const std::string& ps3_path) const; vfsDirBase* OpenDir(const std::string& ps3_path) const;
bool CreateFile(const std::string& ps3_path, bool overwrite = false) const;
bool CreateDir(const std::string& ps3_path) const; bool CreateDir(const std::string& ps3_path) const;
bool CreatePath(const std::string& ps3_path) const;
bool RemoveFile(const std::string& ps3_path) const; bool RemoveFile(const std::string& ps3_path) const;
bool RemoveDir(const std::string& ps3_path) const; bool RemoveDir(const std::string& ps3_path) const;
bool ExistsFile(const std::string& ps3_path) const; bool ExistsFile(const std::string& ps3_path) const;
bool ExistsDir(const std::string& ps3_path) const; bool ExistsDir(const std::string& ps3_path) const;
bool RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const; bool RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const;
bool RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const; bool RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const;
bool CopyFile(const std::string& ps3_path_from, const std::string& ps3_path_to, bool overwrite = true) const;
bool TruncateFile(const std::string& ps3_path, u64 length) const;
vfsDevice* GetDevice(const std::string& ps3_path, std::string& path) const; vfsDevice* GetDevice(const std::string& ps3_path, std::string& path) const;
vfsDevice* GetDeviceLocal(const std::string& local_path, std::string& path) const; vfsDevice* GetDeviceLocal(const std::string& local_path, std::string& path) const;

View file

@ -1,6 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "vfsDevice.h" #include "vfsDevice.h"
#include "Utilities/rFile.h"
vfsDevice::vfsDevice(const std::string& ps3_path, const std::string& local_path) vfsDevice::vfsDevice(const std::string& ps3_path, const std::string& local_path)
: m_ps3_path(ps3_path) : m_ps3_path(ps3_path)
@ -46,16 +45,13 @@ u32 vfsDevice::CmpLocalPath(const std::string& local_path)
if(local_path.length() < m_local_path.length()) if(local_path.length() < m_local_path.length())
return 0; return 0;
rFileName path0(m_local_path);
path0.Normalize();
#ifdef _WIN32 #ifdef _WIN32
#define DL "\\" #define DL "\\"
#else #else
#define DL "/" #define DL "/"
#endif #endif
std::vector<std::string> arr0 = fmt::rSplit(path0.GetFullPath(), DL); std::vector<std::string> arr0 = fmt::rSplit(m_local_path, DL);
std::vector<std::string> arr1 = fmt::rSplit(local_path, DL); std::vector<std::string> arr1 = fmt::rSplit(local_path, DL);
const u32 lim = (u32)std::min(arr0.size(), arr1.size()); const u32 lim = (u32)std::min(arr0.size(), arr1.size());
@ -188,9 +184,7 @@ std::string vfsDevice::GetWinPath(const std::string& p, bool is_dir)
if(is_dir && ret[ret.length() - 1] != '/' && ret[ret.length() - 1] != '\\') ret += '/'; // ??? if(is_dir && ret[ret.length() - 1] != '/' && ret[ret.length() - 1] != '\\') ret += '/'; // ???
rFileName res(ret); return ret;
res.Normalize();
return res.GetFullPath();
} }
std::string vfsDevice::GetWinPath(const std::string& l, const std::string& r) std::string vfsDevice::GetWinPath(const std::string& l, const std::string& r)

View file

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "vfsDirBase.h" #include "vfsDirBase.h"
vfsDirBase::vfsDirBase(vfsDevice* device) vfsDirBase::vfsDirBase(vfsDevice* device)

View file

@ -16,12 +16,14 @@ struct DirEntryInfo
{ {
std::string name; std::string name;
u32 flags; u32 flags;
u64 size;
time_t create_time; time_t create_time;
time_t access_time; time_t access_time;
time_t modify_time; time_t modify_time;
DirEntryInfo() DirEntryInfo()
: flags(0) : flags(0)
, size(0)
, create_time(0) , create_time(0)
, access_time(0) , access_time(0)
, modify_time(0) , modify_time(0)

View file

@ -10,14 +10,14 @@ vfsFile::vfsFile()
{ {
} }
vfsFile::vfsFile(const std::string& path, vfsOpenMode mode) vfsFile::vfsFile(const std::string& path, u32 mode)
: vfsFileBase(nullptr) : vfsFileBase(nullptr)
, m_stream(nullptr) , m_stream(nullptr)
{ {
Open(path, mode); Open(path, mode);
} }
bool vfsFile::Open(const std::string& path, vfsOpenMode mode) bool vfsFile::Open(const std::string& path, u32 mode)
{ {
Close(); Close();
@ -26,11 +26,6 @@ bool vfsFile::Open(const std::string& path, vfsOpenMode mode)
return m_stream && m_stream->IsOpened(); return m_stream && m_stream->IsOpened();
} }
bool vfsFile::Create(const std::string& path, bool overwrite)
{
return m_stream->Create(path, overwrite);
}
bool vfsFile::Exists(const std::string& path) bool vfsFile::Exists(const std::string& path)
{ {
return m_stream->Exists(path); return m_stream->Exists(path);
@ -49,10 +44,11 @@ bool vfsFile::Remove(const std::string& path)
bool vfsFile::Close() bool vfsFile::Close()
{ {
m_stream.reset(); m_stream.reset();
return vfsFileBase::Close();
return true;
} }
u64 vfsFile::GetSize() u64 vfsFile::GetSize() const
{ {
return m_stream->GetSize(); return m_stream->GetSize();
} }
@ -67,7 +63,7 @@ u64 vfsFile::Read(void* dst, u64 size)
return m_stream->Read(dst, size); return m_stream->Read(dst, size);
} }
u64 vfsFile::Seek(s64 offset, vfsSeekMode mode) u64 vfsFile::Seek(s64 offset, u32 mode)
{ {
return m_stream->Seek(offset, mode); return m_stream->Seek(offset, mode);
} }
@ -79,5 +75,5 @@ u64 vfsFile::Tell() const
bool vfsFile::IsOpened() const bool vfsFile::IsOpened() const
{ {
return m_stream && m_stream->IsOpened() && vfsFileBase::IsOpened(); return m_stream && m_stream->IsOpened();
} }

View file

@ -8,21 +8,20 @@ private:
public: public:
vfsFile(); vfsFile();
vfsFile(const std::string& path, vfsOpenMode mode = vfsRead); vfsFile(const std::string& path, u32 mode = vfsRead);
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; virtual bool Open(const std::string& path, u32 mode = vfsRead) override;
virtual bool Create(const std::string& path, bool overwrite = false) override;
virtual bool Exists(const std::string& path) override; virtual bool Exists(const std::string& path) override;
virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override; virtual bool Remove(const std::string& path) override;
virtual bool Close() override; virtual bool Close() override;
virtual u64 GetSize() override; virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override; virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override; virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet) override; virtual u64 Seek(s64 offset, u32 mode = from_begin) override;
virtual u64 Tell() const override; virtual u64 Tell() const override;
virtual bool IsOpened() const override; virtual bool IsOpened() const override;

View file

@ -12,18 +12,11 @@ vfsFileBase::~vfsFileBase()
Close(); Close();
} }
bool Access(const std::string& path, vfsOpenMode mode) bool vfsFileBase::Open(const std::string& path, u32 mode)
{
return false;
}
bool vfsFileBase::Open(const std::string& path, vfsOpenMode mode)
{ {
m_path = path; m_path = path;
m_mode = mode; m_mode = mode;
vfsStream::Reset();
return true; return true;
} }
@ -39,7 +32,7 @@ std::string vfsFileBase::GetPath() const
return m_path; return m_path;
} }
vfsOpenMode vfsFileBase::GetOpenMode() const u32 vfsFileBase::GetOpenMode() const
{ {
return m_mode; return m_mode;
} }

View file

@ -1,15 +1,12 @@
#pragma once #pragma once
#include "vfsStream.h" #include "vfsStream.h"
enum vfsOpenMode : u8 enum vfsOpenMode : u32
{ {
vfsRead = 0x1, vfsRead = o_read,
vfsWrite = 0x2, vfsReadWrite = o_read | o_write,
vfsExcl = 0x4, vfsWriteNew = o_write | o_create | o_trunc,
vfsAppend = 0x8, vfsWriteExcl = o_write | o_create | o_excl,
vfsReadWrite = vfsRead | vfsWrite,
vfsWriteExcl = vfsWrite | vfsExcl,
vfsWriteAppend = vfsWrite | vfsAppend,
}; };
class vfsDevice; class vfsDevice;
@ -18,20 +15,20 @@ struct vfsFileBase : public vfsStream
{ {
protected: protected:
std::string m_path; std::string m_path;
vfsOpenMode m_mode; u32 m_mode;
vfsDevice* m_device; vfsDevice* m_device;
public: public:
vfsFileBase(vfsDevice* device); vfsFileBase(vfsDevice* device);
virtual ~vfsFileBase(); virtual ~vfsFileBase() override;
virtual bool Open(const std::string& path, vfsOpenMode mode); virtual bool Open(const std::string& path, u32 mode);
virtual bool Close() override; virtual bool Close() override;
virtual bool Create(const std::string& path, bool overwrite = false) { return false; }
virtual bool Exists(const std::string& path) { return false; } virtual bool Exists(const std::string& path) { return false; }
virtual bool Rename(const std::string& from, const std::string& to) { return false; } virtual bool Rename(const std::string& from, const std::string& to) { return false; }
virtual bool Remove(const std::string& path) { return false; } virtual bool Remove(const std::string& path) { return false; }
virtual bool IsOpened() const override { return !m_path.empty(); }
std::string GetPath() const; std::string GetPath() const;
vfsOpenMode GetOpenMode() const; u32 GetOpenMode() const;
}; };

View file

@ -12,30 +12,29 @@ vfsLocalDir::~vfsLocalDir()
bool vfsLocalDir::Open(const std::string& path) bool vfsLocalDir::Open(const std::string& path)
{ {
if(!vfsDirBase::Open(path)) if (!vfsDirBase::Open(path) || !dir.Open(path))
return false; {
if(!dir.Open(path))
return false; return false;
}
std::string name; std::string name;
for(bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name))
for (bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name))
{ {
std::string dir_path = path + "/" + name; fs::stat_t file_info;
fs::stat(path + "/" + name, file_info);
m_entries.emplace_back(); m_entries.emplace_back();
// TODO: Use same info structure as fileinfo?
DirEntryInfo& info = m_entries.back(); DirEntryInfo& info = m_entries.back();
info.name = name; info.name = name;
info.flags |= file_info.is_directory ? DirEntry_TypeDir | DirEntry_PermExecutable : DirEntry_TypeFile;
FileInfo fileinfo; info.flags |= file_info.is_writable ? DirEntry_PermWritable | DirEntry_PermReadable : DirEntry_PermReadable;
getFileInfo(dir_path.c_str(), &fileinfo); info.size = file_info.size;
info.access_time = file_info.atime;
// Not sure of purpose for below. I hope these don't need to be correct info.modify_time = file_info.mtime;
info.flags |= rIsDir(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile; info.create_time = file_info.ctime;
if(fileinfo.isWritable) info.flags |= DirEntry_PermWritable;
info.flags |= DirEntry_PermReadable; // Always?
info.flags |= DirEntry_PermExecutable; // Always?
} }
return true; return true;
@ -43,22 +42,22 @@ bool vfsLocalDir::Open(const std::string& path)
bool vfsLocalDir::Create(const std::string& path) bool vfsLocalDir::Create(const std::string& path)
{ {
return rMkdir(path); return fs::create_dir(path);
} }
bool vfsLocalDir::IsExists(const std::string& path) const bool vfsLocalDir::IsExists(const std::string& path) const
{ {
return rIsDir(path); return fs::is_dir(path);
} }
bool vfsLocalDir::Rename(const std::string& from, const std::string& to) bool vfsLocalDir::Rename(const std::string& from, const std::string& to)
{ {
return rRename(from, to); return fs::rename(from, to);
} }
bool vfsLocalDir::Remove(const std::string& path) bool vfsLocalDir::Remove(const std::string& path)
{ {
return rRmdir(path); return fs::remove_dir(path);
} }
bool vfsLocalDir::IsOpened() const bool vfsLocalDir::IsOpened() const

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "vfsDirBase.h" #include "vfsDirBase.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
class vfsLocalDir : public vfsDirBase class vfsLocalDir : public vfsDirBase
{ {

View file

@ -2,136 +2,63 @@
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "vfsLocalFile.h" #include "vfsLocalFile.h"
static const rFile::OpenMode vfs2wx_mode(vfsOpenMode mode)
{
switch(mode)
{
case vfsRead: return rFile::read;
case vfsWrite: return rFile::write;
case vfsReadWrite: return rFile::read_write;
case vfsWriteExcl: return rFile::write_excl;
case vfsWriteAppend: return rFile::write_append;
}
return rFile::read;
}
static const rSeekMode vfs2wx_seek(vfsSeekMode mode)
{
switch(mode)
{
case vfsSeekSet: return rFromStart;
case vfsSeekCur: return rFromCurrent;
case vfsSeekEnd: return rFromEnd;
}
return rFromStart;
}
vfsLocalFile::vfsLocalFile(vfsDevice* device) : vfsFileBase(device) vfsLocalFile::vfsLocalFile(vfsDevice* device) : vfsFileBase(device)
{ {
} }
bool vfsLocalFile::Open(const std::string& path, vfsOpenMode mode) bool vfsLocalFile::Open(const std::string& path, u32 mode)
{ {
Close(); Close();
// if(m_device) return m_file.open(path, mode) && vfsFileBase::Open(path, mode);
// {
// if(!m_file.Access(fmt::FromUTF8(vfsDevice::GetWinPath(m_device->GetLocalPath(), path)), vfs2wx_mode(mode))) return false;
// return m_file.Open(fmt::FromUTF8(vfsDevice::GetWinPath(m_device->GetLocalPath(), path)), vfs2wx_mode(mode)) &&
// vfsFileBase::Open(fmt::FromUTF8(vfsDevice::GetPs3Path(m_device->GetPs3Path(), path)), mode);
// }
// else
// {
if(!m_file.Access(path, vfs2wx_mode(mode))) return false;
return m_file.Open(path, vfs2wx_mode(mode)) && vfsFileBase::Open(path, mode);
// }
}
bool vfsLocalFile::Create(const std::string& path, bool overwrite)
{
LOG_WARNING(HLE, "vfsLocalFile::Create('%s', overwrite=%d)", path.c_str(), overwrite);
for(uint p=1; p < path.length() && path[p] != '\0' ; p++)
{
for(; p < path.length() && path[p] != '\0'; p++)
if(path[p] == '/' || path[p] == '\\') break; // ???
if(p == path.length() || path[p] == '\0')
break;
const std::string& dir = path.substr(0, p);
if(!rExists(dir))
{
LOG_NOTICE(HLE, "create dir: %s", dir.c_str());
rMkdir(dir);
}
}
//create file
const char m = path[path.length() - 1];
if(m != '/' && m != '\\' && !rExists(path)) // ???
{
rFile f;
if (!f.Create(path, overwrite)) {
if (overwrite) LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file");
return false;
}
else
return true;
}
return true;
} }
bool vfsLocalFile::Close() bool vfsLocalFile::Close()
{ {
return m_file.Close() && vfsFileBase::Close(); return m_file.close() && vfsFileBase::Close();
} }
u64 vfsLocalFile::GetSize() u64 vfsLocalFile::GetSize() const
{ {
return m_file.Length(); return m_file.size();
} }
u64 vfsLocalFile::Write(const void* src, u64 size) u64 vfsLocalFile::Write(const void* src, u64 size)
{ {
return m_file.Write(src, size); return m_file.write(src, size);
} }
u64 vfsLocalFile::Read(void* dst, u64 size) u64 vfsLocalFile::Read(void* dst, u64 size)
{ {
return m_file.Read(dst, size); return m_file.read(dst, size);
} }
u64 vfsLocalFile::Seek(s64 offset, vfsSeekMode mode) u64 vfsLocalFile::Seek(s64 offset, u32 mode)
{ {
return m_file.Seek(offset, vfs2wx_seek(mode)); return m_file.seek(offset, mode);
} }
u64 vfsLocalFile::Tell() const u64 vfsLocalFile::Tell() const
{ {
return m_file.Tell(); return m_file.seek(0, from_cur);
} }
bool vfsLocalFile::IsOpened() const bool vfsLocalFile::IsOpened() const
{ {
return m_file.IsOpened() && vfsFileBase::IsOpened(); return m_file && vfsFileBase::IsOpened();
} }
bool vfsLocalFile::Exists(const std::string& path) bool vfsLocalFile::Exists(const std::string& path)
{ {
return rExists(path); return fs::is_file(path);
} }
bool vfsLocalFile::Rename(const std::string& from, const std::string& to) bool vfsLocalFile::Rename(const std::string& from, const std::string& to)
{ {
return rRename(from, to); return fs::rename(from, to);
} }
bool vfsLocalFile::Remove(const std::string& path) bool vfsLocalFile::Remove(const std::string& path)
{ {
return rRemoveFile(path); return fs::remove_file(path);
} }

View file

@ -1,29 +1,29 @@
#pragma once #pragma once
#include "vfsFileBase.h" #include "vfsFileBase.h"
#include "Utilities/rFile.h"
class vfsLocalFile : public vfsFileBase class vfsLocalFile : public vfsFileBase
{ {
private: private:
rFile m_file; fs::file m_file;
public: public:
vfsLocalFile(vfsDevice* device); vfsLocalFile(vfsDevice* device);
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; virtual bool Open(const std::string& path, u32 mode = vfsRead) override;
virtual bool Create(const std::string& path, bool overwrite = false) override;
virtual bool Close() override; virtual bool Close() override;
virtual bool Exists(const std::string& path) override; virtual bool Exists(const std::string& path) override;
virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override; virtual bool Remove(const std::string& path) override;
virtual u64 GetSize() override; virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override; virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override; virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet) override; virtual u64 Seek(s64 offset, u32 mode = from_begin) override;
virtual u64 Tell() const override; virtual u64 Tell() const override;
virtual bool IsOpened() const override; virtual bool IsOpened() const override;
virtual const fs::file& GetFile() const { return m_file; }
}; };

View file

@ -1,80 +1,2 @@
#include "stdafx.h" #include "stdafx.h"
#include "vfsStream.h" #include "vfsStream.h"
vfsStream::vfsStream()
{
}
vfsStream::~vfsStream()
{
Close();
}
void vfsStream::Reset()
{
m_pos = 0;
}
bool vfsStream::Close()
{
Reset();
return true;
}
u64 vfsStream::GetSize()
{
u64 last_pos = Tell();
Seek(0, vfsSeekEnd);
u64 size = Tell();
Seek(last_pos, vfsSeekSet);
return size;
}
u64 vfsStream::Write(const void* src, u64 size)
{
m_pos += size;
return size;
}
u64 vfsStream::Read(void* dst, u64 size)
{
m_pos += size;
return size;
}
u64 vfsStream::Seek(s64 offset, vfsSeekMode mode)
{
switch(mode)
{
case vfsSeekSet:
m_pos = offset;
break;
case vfsSeekCur:
m_pos += offset;
break;
case vfsSeekEnd:
m_pos = GetSize() + offset;
break;
}
return m_pos;
}
u64 vfsStream::Tell() const
{
return m_pos;
}
bool vfsStream::Eof()
{
return Tell() >= GetSize();
}
bool vfsStream::IsOpened() const
{
return true;
}

View file

@ -1,33 +1,44 @@
#pragma once #pragma once
#include "Utilities/File.h"
enum vfsSeekMode
{
vfsSeekSet,
vfsSeekCur,
vfsSeekEnd,
};
struct vfsStream struct vfsStream
{ {
protected: vfsStream() = default;
u64 m_pos;
public: virtual ~vfsStream()
vfsStream(); {
Close();
}
virtual ~vfsStream(); virtual bool Close()
{
return true;
}
virtual void Reset(); virtual u64 GetSize() const = 0;
virtual bool Close();
virtual u64 GetSize(); virtual u64 Write(const void* src, u64 count) = 0;
virtual u64 Write(const void* src, u64 size); template<typename T> __forceinline bool SWrite(const T& data, u64 count = sizeof(T))
virtual u64 Read(void* dst, u64 size); {
return Write(&data, count) == count;
}
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet); virtual u64 Read(void* dst, u64 count) = 0;
virtual u64 Tell() const;
virtual bool Eof();
virtual bool IsOpened() const; template<typename T> __forceinline bool SRead(T& data, u64 count = sizeof(T))
{
return Read(&data, count) == count;
}
virtual u64 Seek(s64 offset, u32 mode = from_begin) = 0;
virtual u64 Tell() const = 0;
virtual bool Eof() const
{
return Tell() >= GetSize();
}
virtual bool IsOpened() const = 0;
}; };

View file

@ -2,48 +2,28 @@
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "vfsStreamMemory.h" #include "vfsStreamMemory.h"
vfsStreamMemory::vfsStreamMemory() : vfsStream() u64 vfsStreamMemory::Write(const void* src, u64 count)
{ {
} assert(m_pos < m_size);
if (m_pos + count > m_size)
vfsStreamMemory::vfsStreamMemory(u32 addr, u32 size) : vfsStream()
{
Open(addr, size);
}
void vfsStreamMemory::Open(u32 addr, u32 size)
{
m_addr = addr;
m_size = size ? size : 0x100000000ull - addr; // determine max possible size
vfsStream::Reset();
}
u64 vfsStreamMemory::GetSize()
{
return m_size;
}
u64 vfsStreamMemory::Write(const void* src, u64 size)
{
assert(Tell() < m_size);
if (Tell() + size > m_size)
{ {
size = m_size - Tell(); count = m_size - m_pos;
} }
memcpy(vm::get_ptr<void>(vm::cast(m_addr + Tell())), src, size); memcpy(vm::get_ptr<void>(vm::cast(m_addr + m_pos)), src, count);
return vfsStream::Write(src, size); m_pos += count;
return count;
} }
u64 vfsStreamMemory::Read(void* dst, u64 size) u64 vfsStreamMemory::Read(void* dst, u64 count)
{ {
assert(Tell() < GetSize()); assert(m_pos < m_size);
if (Tell() + size > GetSize()) if (m_pos + count > m_size)
{ {
size = GetSize() - Tell(); count = m_size - m_pos;
} }
memcpy(dst, vm::get_ptr<void>(vm::cast(m_addr + Tell())), size); memcpy(dst, vm::get_ptr<void>(vm::cast(m_addr + m_pos)), count);
return vfsStream::Read(dst, size); m_pos += count;
return count;
} }

View file

@ -1,19 +1,57 @@
#pragma once #pragma once
#include "vfsStream.h" #include "vfsStream.h"
struct vfsStreamMemory : public vfsStream class vfsStreamMemory : public vfsStream
{ {
u32 m_addr; u64 m_pos = 0;
u64 m_size; u32 m_addr = 0;
u64 m_size = 0;
public: public:
vfsStreamMemory(); vfsStreamMemory() = default;
vfsStreamMemory(u32 addr, u32 size = 0);
void Open(u32 addr, u32 size = 0); vfsStreamMemory(u32 addr, u32 size = 0)
{
Open(addr, size);
}
virtual u64 GetSize() override; void Open(u32 addr, u32 size = 0)
{
m_pos = 0;
m_addr = addr;
m_size = size ? size : 0x100000000ull - addr; // determine max possible size
}
virtual u64 Write(const void* src, u64 size) override; virtual u64 GetSize() const override
virtual u64 Read(void* dst, u64 size) override; {
return m_size;
}
virtual u64 Write(const void* src, u64 count) override;
virtual u64 Read(void* dst, u64 count) override;
virtual u64 Seek(s64 offset, u32 mode = from_begin) override
{
assert(mode < 3);
switch (mode)
{
case from_begin: return m_pos = offset;
case from_cur: return m_pos += offset;
case from_end: return m_pos = m_size + offset;
}
return m_pos;
}
virtual u64 Tell() const override
{
return m_pos;
}
virtual bool IsOpened() const override
{
return true;
}
}; };

View file

@ -21,7 +21,7 @@ void vfsHDDManager::CreateEntry(vfsHDD_Entry& entry)
void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size) void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size)
{ {
rFile f(path, rFile::write); fs::file f(path, o_write | o_create | o_trunc);
static const u64 cur_dir_block = 1; static const u64 cur_dir_block = 1;
@ -32,7 +32,7 @@ void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size)
hdr.version = g_hdd_version; hdr.version = g_hdd_version;
hdr.block_count = (size + block_size) / block_size; hdr.block_count = (size + block_size) / block_size;
hdr.block_size = block_size; hdr.block_size = block_size;
f.Write(&hdr, sizeof(vfsHDD_Hdr)); f.write(&hdr, sizeof(vfsHDD_Hdr));
{ {
vfsHDD_Entry entry; vfsHDD_Entry entry;
@ -41,14 +41,14 @@ void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size)
entry.data_block = hdr.next_block; entry.data_block = hdr.next_block;
entry.next_block = 0; entry.next_block = 0;
f.Seek(cur_dir_block * hdr.block_size); f.seek(cur_dir_block * hdr.block_size);
f.Write(&entry, sizeof(vfsHDD_Entry)); f.write(&entry, sizeof(vfsHDD_Entry));
f.Write("."); f.write(".", 1);
} }
u8 null = 0; u8 null = 0;
f.Seek(hdr.block_count * hdr.block_size - sizeof(null)); f.seek(hdr.block_count * hdr.block_size - sizeof(null));
f.Write(&null, sizeof(null)); f.write(&null, sizeof(null));
} }
void vfsHDDManager::Format() void vfsHDDManager::Format()
@ -599,7 +599,7 @@ bool vfsHDD::GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name)
return true; return true;
} }
bool vfsHDD::Open(const std::string& path, vfsOpenMode mode) bool vfsHDD::Open(const std::string& path, u32 mode)
{ {
const char* s = path.c_str(); const char* s = path.c_str();
u64 from = 0; u64 from = 0;
@ -737,47 +737,44 @@ bool vfsHDD::RemoveEntry(const std::string& name)
return true; return true;
} }
bool vfsHDD::Create(const std::string& path) u64 vfsHDD::Write(const void* src, u64 size)
{ {
return false; return m_file.Write(src, size); // ???
} }
u32 vfsHDD::Write(const void* src, u32 size) u64 vfsHDD::Read(void* dst, u64 size)
{ {
return vfsFileBase::Write(src, m_file.Write(src, size)); return m_file.Read(dst, size); // ???
} }
u32 vfsHDD::Read(void* dst, u32 size) u64 vfsHDD::Seek(s64 offset, u32 mode)
{
return vfsFileBase::Read(dst, m_file.Read(dst, size));
}
u64 vfsHDD::Seek(s64 offset, vfsSeekMode mode)
{ {
switch (mode) switch (mode)
{ {
case vfsSeekCur: case from_begin: return m_file.Seek(offset);
m_file.Seek(Tell() + offset); case from_cur: return m_file.Seek(Tell() + offset);
break; case from_end: return m_file.Seek(m_file.GetSize() + offset);
case vfsSeekSet:
m_file.Seek(offset);
break;
case vfsSeekEnd:
m_file.Seek(m_file.GetSize() + offset);
break;
} }
return vfsFileBase::Seek(offset, mode); return m_file.Tell(); // ???
} }
bool vfsHDD::Eof() u64 vfsHDD::Tell() const
{
return m_file.Tell(); // ???
}
bool vfsHDD::Eof() const
{ {
return m_file.Eof(); return m_file.Eof();
} }
u64 vfsHDD::GetSize() bool vfsHDD::IsOpened() const
{
return true; // ???
}
u64 vfsHDD::GetSize() const
{ {
return m_file.GetSize(); return m_file.GetSize();
} }

View file

@ -32,7 +32,7 @@ enum vfsHDD_EntryType : u8
struct vfsHDD_Entry : public vfsHDD_Block struct vfsHDD_Entry : public vfsHDD_Block
{ {
u64 data_block; u64 data_block;
vfsOpenMode access; u32 access;
vfsHDD_EntryType type; vfsHDD_EntryType type;
u64 size; u64 size;
u64 ctime; u64 ctime;
@ -109,6 +109,11 @@ public:
bool Seek(u64 pos); bool Seek(u64 pos);
u64 Tell() const
{
return m_cur_block * m_hdd_info.block_size + m_position; // ???
}
void SaveInfo(); void SaveInfo();
u64 Read(void* dst, u64 size); u64 Read(void* dst, u64 size);
@ -177,7 +182,7 @@ public:
bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name); bool GetNextEntry(u64& block, vfsHDD_Entry& entry, std::string& name);
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead); virtual bool Open(const std::string& path, u32 mode = vfsRead);
bool HasEntry(const std::string& name); bool HasEntry(const std::string& name);
@ -187,15 +192,17 @@ public:
bool RemoveEntry(const std::string& name); bool RemoveEntry(const std::string& name);
virtual bool Create(const std::string& path); virtual u64 Write(const void* src, u64 count) override;
virtual u32 Write(const void* src, u32 size); virtual u64 Read(void* dst, u64 count) override;
virtual u32 Read(void* dst, u32 size); virtual u64 Seek(s64 offset, u32 mode = from_begin) override;
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet); virtual u64 Tell() const override;
virtual bool Eof(); virtual bool Eof() const override;
virtual u64 GetSize(); virtual bool IsOpened() const override;
virtual u64 GetSize() const;
}; };

View file

@ -122,22 +122,6 @@ public:
return m_cur_id++; return m_cur_id++;
} }
template<typename T> bool GetIDData(const u32 id, std::shared_ptr<T>& result)
{
std::lock_guard<std::mutex> lock(m_mutex);
auto f = m_id_map.find(id);
if (f == m_id_map.end() || f->second.GetInfo() != typeid(T))
{
return false;
}
result = f->second.GetData<T>();
return true;
}
template<typename T> std::shared_ptr<T> GetIDData(const u32 id) template<typename T> std::shared_ptr<T> GetIDData(const u32 id)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);

View file

@ -628,27 +628,25 @@ namespace vm
u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos) u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos)
{ {
assert(align_v);
switch (CPU.GetType()) switch (CPU.GetType())
{ {
case CPU_THREAD_PPU: case CPU_THREAD_PPU:
{ {
PPUThread& PPU = static_cast<PPUThread&>(CPU); PPUThread& context = static_cast<PPUThread&>(CPU);
old_pos = vm::cast(PPU.GPR[1], "SP"); old_pos = vm::cast(context.GPR[1], "SP");
PPU.GPR[1] -= align(size, 8); // room minimal possible size context.GPR[1] -= align(size, 8); // room minimal possible size
PPU.GPR[1] &= ~(align_v - 1); // fix stack alignment context.GPR[1] &= ~(align_v - 1); // fix stack alignment
if (PPU.GPR[1] < CPU.GetStackAddr()) if (context.GPR[1] < CPU.GetStackAddr())
{ {
// stack overflow LOG_ERROR(PPU, "vm::stack_push(0x%x,%d): stack overflow (SP=0x%llx, stack=*0x%x)", size, align_v, context.GPR[1], CPU.GetStackAddr());
PPU.GPR[1] = old_pos; context.GPR[1] = old_pos;
return 0; return 0;
} }
else else
{ {
return (u32)PPU.GPR[1]; return static_cast<u32>(context.GPR[1]);
} }
} }
@ -669,7 +667,7 @@ namespace vm
if (context.SP < CPU.GetStackAddr()) if (context.SP < CPU.GetStackAddr())
{ {
// stack overflow LOG_ERROR(ARMv7, "vm::stack_push(0x%x,%d): stack overflow (SP=0x%x, stack=*0x%x)", size, align_v, context.SP, CPU.GetStackAddr());
context.SP = old_pos; context.SP = old_pos;
return 0; return 0;
} }
@ -693,10 +691,14 @@ namespace vm
{ {
case CPU_THREAD_PPU: case CPU_THREAD_PPU:
{ {
PPUThread& PPU = static_cast<PPUThread&>(CPU); PPUThread& context = static_cast<PPUThread&>(CPU);
assert(PPU.GPR[1] == addr); if (context.GPR[1] != addr && !Emu.IsStopped())
PPU.GPR[1] = old_pos; {
LOG_ERROR(PPU, "vm::stack_pop(*0x%x,*0x%x): stack inconsistency (SP=0x%llx)", addr, old_pos, context.GPR[1]);
}
context.GPR[1] = old_pos;
return; return;
} }
@ -711,7 +713,11 @@ namespace vm
{ {
ARMv7Context& context = static_cast<ARMv7Thread&>(CPU).context; ARMv7Context& context = static_cast<ARMv7Thread&>(CPU).context;
assert(context.SP == addr); if (context.SP != addr && !Emu.IsStopped())
{
LOG_ERROR(ARMv7, "vm::stack_pop(*0x%x,*0x%x): stack inconsistency (SP=0x%x)", addr, old_pos, context.SP);
}
context.SP = old_pos; context.SP = old_pos;
return; return;
} }

View file

@ -65,7 +65,7 @@ namespace vm
void dealloc(u32 addr, memory_location location = user_space); void dealloc(u32 addr, memory_location location = user_space);
template<typename T = void> template<typename T = void>
T* const get_ptr(u32 addr) T* get_ptr(u32 addr)
{ {
return reinterpret_cast<T*>(static_cast<u8*>(g_base_addr) + addr); return reinterpret_cast<T*>(static_cast<u8*>(g_base_addr) + addr);
} }
@ -77,7 +77,7 @@ namespace vm
} }
template<typename T = void> template<typename T = void>
T* const priv_ptr(u32 addr) T* priv_ptr(u32 addr)
{ {
return reinterpret_cast<T*>(static_cast<u8*>(g_priv_addr) + addr); return reinterpret_cast<T*>(static_cast<u8*>(g_priv_addr) + addr);
} }
@ -107,15 +107,11 @@ namespace vm
template<> template<>
struct cast_ptr<unsigned long> struct cast_ptr<unsigned long>
{ {
static_assert(sizeof(unsigned long) == 8, "Unexpected size of unsigned long");
__forceinline static u32 cast(const unsigned long addr, const char* func) __forceinline static u32 cast(const unsigned long addr, const char* func)
{ {
const u32 res = static_cast<u32>(addr); return cast_ptr<u64>::cast(addr, func);
if (res != addr)
{
vm::error(addr, func);
}
return res;
} }
}; };
#endif #endif

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
class CPUThread; class PPUThread;
struct ARMv7Context; struct ARMv7Context;
namespace vm namespace vm
@ -354,7 +354,7 @@ namespace vm
public: public:
typedef RT(type)(T...); typedef RT(type)(T...);
RT operator()(CPUThread& CPU, T... args) const; // defined in CB_FUNC.h, call using specified PPU thread context RT operator()(PPUThread& CPU, T... args) const; // defined in CB_FUNC.h, call using specified PPU thread context
RT operator()(ARMv7Context& context, T... args) const; // defined in ARMv7Callback.h, passing context is mandatory RT operator()(ARMv7Context& context, T... args) const; // defined in ARMv7Callback.h, passing context is mandatory
@ -410,35 +410,47 @@ namespace vm
static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)"); static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)");
}; };
//BE pointer to LE data // BE pointer to LE data
template<typename T, int lvl = 1, typename AT = u32> using bptrl = _ptr_base<T, lvl, typename to_be_t<AT>::type>; template<typename T, int lvl = 1, typename AT = u32> using bptrl = _ptr_base<T, lvl, typename to_be_t<AT>::type>;
//BE pointer to BE data // BE pointer to BE data
template<typename T, int lvl = 1, typename AT = u32> using bptrb = _ptr_base<typename to_be_t<T>::type, lvl, typename to_be_t<AT>::type>; template<typename T, int lvl = 1, typename AT = u32> using bptrb = _ptr_base<typename to_be_t<T>::type, lvl, typename to_be_t<AT>::type>;
//LE pointer to BE data // LE pointer to BE data
template<typename T, int lvl = 1, typename AT = u32> using lptrb = _ptr_base<typename to_be_t<T>::type, lvl, AT>; template<typename T, int lvl = 1, typename AT = u32> using lptrb = _ptr_base<typename to_be_t<T>::type, lvl, AT>;
//LE pointer to LE data // LE pointer to LE data
template<typename T, int lvl = 1, typename AT = u32> using lptrl = _ptr_base<T, lvl, AT>; template<typename T, int lvl = 1, typename AT = u32> using lptrl = _ptr_base<T, lvl, AT>;
namespace ps3 namespace ps3
{ {
//default pointer for HLE functions (LE pointer to BE data) // default pointer for HLE functions (LE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrb<T, lvl, AT>; template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrb<T, lvl, AT>;
//default pointer for HLE structures (BE pointer to BE data) // default pointer for HLE structures (BE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> using bptr = bptrb<T, lvl, AT>; template<typename T, int lvl = 1, typename AT = u32> using bptr = bptrb<T, lvl, AT>;
} }
namespace psv namespace psv
{ {
//default pointer for HLE functions & structures (LE pointer to LE data) // default pointer for HLE functions & structures (LE pointer to LE data)
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrl<T, lvl, AT>; template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrl<T, lvl, AT>;
} }
//PS3 emulation is main now, so lets it be as default // PS3 emulation is main now, so lets it be as default
using namespace ps3; using namespace ps3;
struct null_t
{
template<typename T, int lvl, typename AT> operator _ptr_base<T, lvl, AT>() const
{
const std::array<AT, 1> value = {};
return _ptr_base<T, lvl, AT>::make(value[0]);
}
};
// vm::null is convertible to any vm::ptr type as null pointer in virtual memory
static null_t null;
} }
namespace fmt namespace fmt

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <sstream> #include <sstream>
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/RSX/GL/GLVertexProgram.h" #include "Emu/RSX/GL/GLVertexProgram.h"
@ -182,14 +181,12 @@ public:
, m_arb_shader("") , m_arb_shader("")
, m_dst_reg_name("") , m_dst_reg_name("")
{ {
rFile f(path); fs::file f(path);
if (!f.IsOpened()) if (!f) return;
return;
m_buffer_size = f.Length(); m_buffer_size = f.size();
m_buffer = new u8[m_buffer_size]; m_buffer = new u8[m_buffer_size];
f.Read(m_buffer, m_buffer_size); f.read(m_buffer, m_buffer_size);
f.Close();
m_arb_shader += fmt::format("Loading... [%s]\n", path.c_str()); m_arb_shader += fmt::format("Loading... [%s]\n", path.c_str());
} }
@ -315,16 +312,13 @@ public:
{ {
u32 ptr; u32 ptr;
{ {
rFile f(m_path); fs::file f(m_path);
if (!f) return;
if (!f.IsOpened()) size_t size = f.size();
return;
size_t size = f.Length();
vm::ps3::init(); vm::ps3::init();
ptr = vm::alloc(size); ptr = vm::alloc(size);
f.Read(vm::get_ptr(ptr), size); f.read(vm::get_ptr(ptr), size);
f.Close();
} }
auto& vmprog = vm::get_ref<CgBinaryProgram>(ptr); auto& vmprog = vm::get_ref<CgBinaryProgram>(ptr);

View file

@ -1,7 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "rpcs3/Ini.h" #include "rpcs3/Ini.h"
#include "Utilities/rPlatform.h" // only for rImage #include "Utilities/rPlatform.h" // only for rImage
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
@ -580,10 +580,8 @@ void GLTexture::Save(RSXTexture& tex, const std::string& name)
return; return;
} }
{ fs::file(name + ".raw", o_write | o_create | o_trunc).write(alldata, texPixelCount * 4);
rFile f(name + ".raw", rFile::write);
f.Write(alldata, texPixelCount * 4);
}
u8* data = new u8[texPixelCount * 3]; u8* data = new u8[texPixelCount * 3];
u8* alpha = new u8[texPixelCount]; u8* alpha = new u8[texPixelCount];
@ -612,10 +610,10 @@ void GLTexture::Save(RSXTexture& tex)
static const std::string& dir_path = "textures"; static const std::string& dir_path = "textures";
static const std::string& file_fmt = dir_path + "/" + "tex[%d].png"; static const std::string& file_fmt = dir_path + "/" + "tex[%d].png";
if (!rExists(dir_path)) rMkdir(dir_path); if (!fs::exists(dir_path)) fs::create_dir(dir_path);
u32 count = 0; u32 count = 0;
while (rExists(fmt::Format(file_fmt.c_str(), count))) count++; while (fs::exists(fmt::Format(file_fmt.c_str(), count))) count++;
Save(tex, fmt::Format(file_fmt.c_str(), count)); Save(tex, fmt::Format(file_fmt.c_str(), count));
} }
@ -1136,8 +1134,7 @@ bool GLGSRender::LoadProgram()
checkForGlError("m_fragment_prog.Compile"); checkForGlError("m_fragment_prog.Compile");
// TODO: This shouldn't use current dir // TODO: This shouldn't use current dir
rFile f("./FragmentProgram.txt", rFile::write); fs::file("./FragmentProgram.txt", o_write | o_create | o_trunc).write(m_fragment_prog.shader.c_str(), m_fragment_prog.shader.size());
f.Write(m_fragment_prog.shader);
} }
if (m_vp_buf_num == -1) if (m_vp_buf_num == -1)
@ -1148,8 +1145,7 @@ bool GLGSRender::LoadProgram()
checkForGlError("m_vertex_prog.Compile"); checkForGlError("m_vertex_prog.Compile");
// TODO: This shouldn't use current dir // TODO: This shouldn't use current dir
rFile f("./VertexProgram.txt", rFile::write); fs::file("./VertexProgram.txt", o_write | o_create | o_trunc).write(m_vertex_prog.shader.c_str(), m_vertex_prog.shader.size());
f.Write(m_vertex_prog.shader);
} }
if (m_fp_buf_num != -1 && m_vp_buf_num != -1) if (m_fp_buf_num != -1 && m_vp_buf_num != -1)

View file

@ -2484,18 +2484,19 @@ void RSXThread::Task()
if (get_system_time() - start_time > m_vblank_count * 1000000 / 60) if (get_system_time() - start_time > m_vblank_count * 1000000 / 60)
{ {
m_vblank_count++; m_vblank_count++;
if (m_vblank_handler)
if (auto cb = m_vblank_handler)
{ {
auto cb = m_vblank_handler; Emu.GetCallbackManager().Async([=](PPUThread& CPU)
Emu.GetCallbackManager().Async([cb](PPUThread& CPU)
{ {
cb(CPU, 1); cb(CPU, 1);
}); });
} }
continue;
} }
else
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
} }
}); });

View file

@ -14,7 +14,7 @@ namespace cb_detail
// Current implementation can handle only fixed amount of stack arguments. // Current implementation can handle only fixed amount of stack arguments.
// This constant can be increased if necessary. // This constant can be increased if necessary.
// It's possible to calculate suitable stack frame size in template, but too complicated. // It's possible to calculate suitable stack frame size in template, but too complicated.
static const auto FIXED_STACK_FRAME_SIZE = 0x100; static const auto FIXED_STACK_FRAME_SIZE = 0x90;
template<typename T, _func_arg_type type, int g_count, int f_count, int v_count> template<typename T, _func_arg_type type, int g_count, int f_count, int v_count>
struct _func_arg; struct _func_arg;
@ -61,7 +61,7 @@ namespace cb_detail
__forceinline static void set_value(PPUThread& CPU, const T& arg) __forceinline static void set_value(PPUThread& CPU, const T& arg)
{ {
const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE; const int stack_pos = (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)"); static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::write64(CPU.GPR[1] + stack_pos, cast_to_ppu_gpr<T>(arg)); vm::write64(CPU.GPR[1] + stack_pos, cast_to_ppu_gpr<T>(arg));
} }
@ -132,10 +132,7 @@ namespace cb_detail
{ {
__forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) __forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args)
{ {
const bool stack = _bind_func_args<0, 0, 0, T...>(CPU, args...); _func_caller<void, T...>::call(CPU, pc, rtoc, args...);
if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE;
CPU.FastCall2(pc, rtoc);
if (stack) CPU.GPR[1] += FIXED_STACK_FRAME_SIZE;
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)"); static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid callback result type (reference)"); static_assert(!std::is_reference<RT>::value, "Invalid callback result type (reference)");
@ -154,7 +151,9 @@ namespace cb_detail
{ {
const bool stack = _bind_func_args<0, 0, 0, T...>(CPU, args...); const bool stack = _bind_func_args<0, 0, 0, T...>(CPU, args...);
if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE; if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE;
CPU.GPR[1] -= 0x70; // create reserved area
CPU.FastCall2(pc, rtoc); CPU.FastCall2(pc, rtoc);
CPU.GPR[1] += 0x70;
if (stack) CPU.GPR[1] += FIXED_STACK_FRAME_SIZE; if (stack) CPU.GPR[1] += FIXED_STACK_FRAME_SIZE;
} }
}; };
@ -163,14 +162,13 @@ namespace cb_detail
namespace vm namespace vm
{ {
template<typename AT, typename RT, typename... T> template<typename AT, typename RT, typename... T>
__forceinline RT _ptr_base<RT(T...), 1, AT>::operator()(CPUThread& CPU, T... args) const __forceinline RT _ptr_base<RT(T...), 1, AT>::operator()(PPUThread& CPU, T... args) const
{ {
auto data = vm::get_ptr<be_t<u32>>(vm::cast(m_addr)); const auto data = vm::get_ptr<be_t<u32>>(vm::cast(m_addr));
const u32 pc = data[0]; const u32 pc = data[0];
const u32 rtoc = data[1]; const u32 rtoc = data[1];
assert(CPU.GetType() == CPU_THREAD_PPU); return cb_detail::_func_caller<RT, T...>::call(CPU, pc, rtoc, args...);
return cb_detail::_func_caller<RT, T...>::call(static_cast<PPUThread&>(CPU), pc, rtoc, args...);
} }
template<typename AT, typename RT, typename... T> template<typename AT, typename RT, typename... T>

View file

@ -5,7 +5,7 @@
std::string SysCalls::GetFuncName(const u64 fid) std::string SysCalls::GetFuncName(const u64 fid)
{ {
// check syscalls // check syscalls
switch (fid) switch (~fid)
{ {
case 1: return "sys_process_getpid"; case 1: return "sys_process_getpid";
case 2: return "sys_process_wait_for_child"; case 2: return "sys_process_wait_for_child";
@ -26,7 +26,7 @@ std::string SysCalls::GetFuncName(const u64 fid)
case 29: return "sys_process_get_id"; case 29: return "sys_process_get_id";
case 30: return "_sys_process_get_paramsfo"; case 30: return "_sys_process_get_paramsfo";
case 31: return "sys_process_get_ppu_guid"; case 31: return "sys_process_get_ppu_guid";
case 41: return "sys_internal_ppu_thread_exit"; case 41: return "_sys_ppu_thread_exit";
case 43: return "sys_ppu_thread_yield"; case 43: return "sys_ppu_thread_yield";
case 44: return "sys_ppu_thread_join"; case 44: return "sys_ppu_thread_join";
case 45: return "sys_ppu_thread_detach"; case 45: return "sys_ppu_thread_detach";
@ -36,7 +36,7 @@ std::string SysCalls::GetFuncName(const u64 fid)
case 49: return "sys_ppu_thread_get_stack_information"; case 49: return "sys_ppu_thread_get_stack_information";
case 50: return "sys_ppu_thread_stop"; case 50: return "sys_ppu_thread_stop";
case 51: return "sys_ppu_thread_restart"; case 51: return "sys_ppu_thread_restart";
case 52: return "sys_ppu_thread_create"; case 52: return "_sys_ppu_thread_create";
case 53: return "sys_ppu_thread_start"; case 53: return "sys_ppu_thread_start";
case 56: return "sys_ppu_thread_rename"; case 56: return "sys_ppu_thread_rename";
case 57: return "sys_ppu_thread_recover_page_fault"; case 57: return "sys_ppu_thread_recover_page_fault";
@ -4414,5 +4414,5 @@ std::string SysCalls::GetFuncName(const u64 fid)
} }
} }
return fmt::format("0x%08llX", fid); return ~fid < 1024 ? fmt::format("syscall_%lld", ~fid) : fmt::format("0x%08llX", fid);
} }

View file

@ -106,12 +106,16 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index)
{ {
// call LLE function if available // call LLE function if available
const auto data = vm::get_ptr<be_t<u32>>(func->lle_func.addr());
const u32 pc = data[0];
const u32 rtoc = data[1];
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(HLE, "LLE function called: %s", SysCalls::GetFuncName(func->id)); LOG_NOTICE(HLE, "LLE function called: %s", SysCalls::GetFuncName(func->id));
} }
func->lle_func(CPU); CPU.FastCall2(pc, rtoc);
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {

View file

@ -33,7 +33,7 @@ struct ModuleFunc
{ {
} }
ModuleFunc(u32 id, u32 flags, Module* module, const char* name, ppu_func_caller func, vm::ptr<void()> lle_func = vm::ptr<void()>::make(0)) ModuleFunc(u32 id, u32 flags, Module* module, const char* name, ppu_func_caller func, vm::ptr<void()> lle_func = vm::null)
: id(id) : id(id)
, flags(flags) , flags(flags)
, module(module) , module(module)

View file

@ -226,7 +226,7 @@ u32 adecOpen(AudioDecoder* adec_ptr)
adec.id = adec_id; adec.id = adec_id;
adec.adecCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get()); adec.adecCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get());
adec.adecCb->SetName(fmt::format("AudioDecoder[%d] Callback", adec_id)); adec.adecCb->SetName(fmt::format("AudioDecoder[0x%x] Callback", adec_id));
adec.adecCb->SetEntry(0); adec.adecCb->SetEntry(0);
adec.adecCb->SetPrio(1001); adec.adecCb->SetPrio(1001);
adec.adecCb->SetStackSize(0x10000); adec.adecCb->SetStackSize(0x10000);
@ -234,7 +234,7 @@ u32 adecOpen(AudioDecoder* adec_ptr)
adec.adecCb->InitRegs(); adec.adecCb->InitRegs();
adec.adecCb->DoRun(); adec.adecCb->DoRun();
thread_t t(fmt::format("AudioDecoder[%d] Thread", adec_id), [adec_ptr, sptr]() thread_t t(fmt::format("AudioDecoder[0x%x] Thread", adec_id), [adec_ptr, sptr]()
{ {
AudioDecoder& adec = *adec_ptr; AudioDecoder& adec = *adec_ptr;
AdecTask& task = adec.task; AdecTask& task = adec.task;
@ -510,11 +510,14 @@ bool adecCheckType(AudioCodecType type)
return true; return true;
} }
int cellAdecQueryAttr(vm::ptr<CellAdecType> type, vm::ptr<CellAdecAttr> attr) s32 cellAdecQueryAttr(vm::ptr<CellAdecType> type, vm::ptr<CellAdecAttr> attr)
{ {
cellAdec.Warning("cellAdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.addr(), attr.addr()); cellAdec.Warning("cellAdecQueryAttr(type=*0x%x, attr=*0x%x)", type, attr);
if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; if (!adecCheckType(type->audioCodecType))
{
return CELL_ADEC_ERROR_ARG;
}
// TODO: check values // TODO: check values
attr->adecVerLower = 0x280000; // from dmux attr->adecVerLower = 0x280000; // from dmux
@ -524,36 +527,46 @@ int cellAdecQueryAttr(vm::ptr<CellAdecType> type, vm::ptr<CellAdecAttr> attr)
return CELL_OK; return CELL_OK;
} }
int cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::ptr<CellAdecCb> cb, vm::ptr<u32> handle) s32 cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::ptr<CellAdecCb> cb, vm::ptr<u32> handle)
{ {
cellAdec.Warning("cellAdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellAdec.Warning("cellAdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
type.addr(), res.addr(), cb.addr(), handle.addr());
if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; if (!adecCheckType(type->audioCodecType))
{
return CELL_ADEC_ERROR_ARG;
}
*handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res, vm::ptr<CellAdecCb> cb, vm::ptr<u32> handle) s32 cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res, vm::ptr<CellAdecCb> cb, vm::ptr<u32> handle)
{ {
cellAdec.Warning("cellAdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellAdec.Warning("cellAdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
type.addr(), res.addr(), cb.addr(), handle.addr());
if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; if (!adecCheckType(type->audioCodecType))
{
return CELL_ADEC_ERROR_ARG;
}
*handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellAdecClose(u32 handle) s32 _nid_df982d2c(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res, vm::ptr<CellAdecCb> cb, vm::ptr<u32> handle)
{ {
cellAdec.Warning("cellAdecClose(handle=%d)", handle); return cellAdecOpenEx(type, res, cb, handle);
}
std::shared_ptr<AudioDecoder> adec; s32 cellAdecClose(u32 handle)
if (!Emu.GetIdManager().GetIDData(handle, adec)) {
cellAdec.Warning("cellAdecClose(handle=0x%x)", handle);
const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -576,12 +589,13 @@ int cellAdecClose(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellAdecStartSeq(u32 handle, u32 param_addr) s32 cellAdecStartSeq(u32 handle, u32 param)
{ {
cellAdec.Warning("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); cellAdec.Warning("cellAdecStartSeq(handle=0x%x, param=*0x%x)", handle, param);
std::shared_ptr<AudioDecoder> adec; const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, adec))
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -595,25 +609,25 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
case CELL_ADEC_TYPE_ATRACX_6CH: case CELL_ADEC_TYPE_ATRACX_6CH:
case CELL_ADEC_TYPE_ATRACX_8CH: case CELL_ADEC_TYPE_ATRACX_8CH:
{ {
auto param = vm::ptr<const CellAdecParamAtracX>::make(param_addr); const auto atx = vm::ptr<const CellAdecParamAtracX>::make(param);
task.at3p.sample_rate = param->sampling_freq; task.at3p.sample_rate = atx->sampling_freq;
task.at3p.channel_config = param->ch_config_idx; task.at3p.channel_config = atx->ch_config_idx;
task.at3p.channels = param->nch_out; task.at3p.channels = atx->nch_out;
task.at3p.frame_size = param->nbytes; task.at3p.frame_size = atx->nbytes;
task.at3p.extra_config = param->extra_config_data; task.at3p.extra_config = atx->extra_config_data;
task.at3p.output = param->bw_pcm; task.at3p.output = atx->bw_pcm;
task.at3p.downmix = param->downmix_flag; task.at3p.downmix = atx->downmix_flag;
task.at3p.ats_header = param->au_includes_ats_hdr_flg; task.at3p.ats_header = atx->au_includes_ats_hdr_flg;
cellAdec.Todo("*** CellAdecParamAtracX: sr=%d, ch_cfg=%d(%d), frame_size=0x%x, extra=0x%x, output=%d, downmix=%d, ats_header=%d", cellAdec.Todo("*** CellAdecParamAtracX: sr=%d, ch_cfg=%d(%d), frame_size=0x%x, extra=0x%x, output=%d, downmix=%d, ats_header=%d",
task.at3p.sample_rate, task.at3p.channel_config, task.at3p.channels, task.at3p.frame_size, (u32&)task.at3p.extra_config, task.at3p.output, task.at3p.downmix, task.at3p.ats_header); task.at3p.sample_rate, task.at3p.channel_config, task.at3p.channels, task.at3p.frame_size, (u32&)task.at3p.extra_config, task.at3p.output, task.at3p.downmix, task.at3p.ats_header);
break; break;
} }
case CELL_ADEC_TYPE_MP3: case CELL_ADEC_TYPE_MP3:
{ {
auto param = vm::ptr<const CellAdecParamMP3>::make(param_addr); const auto mp3 = vm::ptr<const CellAdecParamMP3>::make(param);
cellAdec.Todo("*** CellAdecParamMP3: bw_pcm=%d", param->bw_pcm); cellAdec.Todo("*** CellAdecParamMP3: bw_pcm=%d", mp3->bw_pcm);
break; break;
} }
default: default:
@ -628,12 +642,13 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
return CELL_OK; return CELL_OK;
} }
int cellAdecEndSeq(u32 handle) s32 cellAdecEndSeq(u32 handle)
{ {
cellAdec.Warning("cellAdecEndSeq(handle=%d)", handle); cellAdec.Warning("cellAdecEndSeq(handle=0x%x)", handle);
std::shared_ptr<AudioDecoder> adec; const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, adec))
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -642,12 +657,13 @@ int cellAdecEndSeq(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo) s32 cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo)
{ {
cellAdec.Log("cellAdecDecodeAu(handle=%d, auInfo_addr=0x%x)", handle, auInfo.addr()); cellAdec.Log("cellAdecDecodeAu(handle=0x%x, auInfo=*0x%x)", handle, auInfo);
std::shared_ptr<AudioDecoder> adec; const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, adec))
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -664,12 +680,13 @@ int cellAdecDecodeAu(u32 handle, vm::ptr<CellAdecAuInfo> auInfo)
return CELL_OK; return CELL_OK;
} }
int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer) s32 cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
{ {
cellAdec.Log("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer.addr()); cellAdec.Log("cellAdecGetPcm(handle=0x%x, outBuffer=*0x%x)", handle, outBuffer);
std::shared_ptr<AudioDecoder> adec; const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, adec))
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -779,12 +796,13 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
return CELL_OK; return CELL_OK;
} }
int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr) s32 cellAdecGetPcmItem(u32 handle, vm::ptr<vm::bptr<CellAdecPcmItem>> pcmItem)
{ {
cellAdec.Log("cellAdecGetPcmItem(handle=%d, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr.addr()); cellAdec.Log("cellAdecGetPcmItem(handle=0x%x, pcmItem=**0x%x)", handle, pcmItem);
std::shared_ptr<AudioDecoder> adec; const auto adec = Emu.GetIdManager().GetIDData<AudioDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, adec))
if (!adec)
{ {
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
@ -798,7 +816,7 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr)
AVFrame* frame = af.data; AVFrame* frame = af.data;
auto pcm = vm::ptr<CellAdecPcmItem>::make(adec->memAddr + adec->memBias); const auto pcm = vm::ptr<CellAdecPcmItem>::make(adec->memAddr + adec->memBias);
adec->memBias += 512; adec->memBias += 512;
if (adec->memBias + 512 > adec->memSize) if (adec->memBias + 512 > adec->memSize)
@ -853,7 +871,7 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr)
memset(mp3.get_ptr(), 0, sizeof(CellAdecMP3Info)); memset(mp3.get_ptr(), 0, sizeof(CellAdecMP3Info));
} }
*pcmItem_ptr = pcm.addr(); *pcmItem = pcm;
return CELL_OK; return CELL_OK;
} }
@ -862,6 +880,7 @@ Module cellAdec("cellAdec", []()
REG_FUNC(cellAdec, cellAdecQueryAttr); REG_FUNC(cellAdec, cellAdecQueryAttr);
REG_FUNC(cellAdec, cellAdecOpen); REG_FUNC(cellAdec, cellAdecOpen);
REG_FUNC(cellAdec, cellAdecOpenEx); REG_FUNC(cellAdec, cellAdecOpenEx);
REG_UNNAMED(cellAdec, df982d2c);
REG_FUNC(cellAdec, cellAdecClose); REG_FUNC(cellAdec, cellAdecClose);
REG_FUNC(cellAdec, cellAdecStartSeq); REG_FUNC(cellAdec, cellAdecStartSeq);
REG_FUNC(cellAdec, cellAdecEndSeq); REG_FUNC(cellAdec, cellAdecEndSeq);

View file

@ -96,10 +96,10 @@ s32 cellAudioInit()
u16 buf_u16[out_buffer_size]; u16 buf_u16[out_buffer_size];
for (size_t i = 0; i < out_buffer_size; i += 8) for (size_t i = 0; i < out_buffer_size; i += 8)
{ {
static const __m128 float2u16 = { 0x8000, 0x8000, 0x8000, 0x8000 }; const auto scale = _mm_set1_ps(0x8000);
(__m128i&)(buf_u16[i]) = _mm_packs_epi32( (__m128i&)(buf_u16[i]) = _mm_packs_epi32(
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buffer[i]), float2u16)), _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(buffer + i), scale)),
_mm_cvtps_epi32(_mm_mul_ps((__m128&)(buffer[i + 4]), float2u16))); _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(buffer + i + 4), scale)));
} }
if (!opened) if (!opened)
@ -206,25 +206,17 @@ s32 cellAudioInit()
auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality auto step_volume = [](AudioPortConfig& port) // part of cellAudioSetPortLevel functionality
{ {
if (port.level_inc) const auto param = port.level_set.read_sync();
{
port.level += port.level_inc;
if (port.level_inc > 0.0f) if (param.inc != 0.0f)
{
port.level += param.inc;
const bool dec = param.inc < 0.0f;
if ((!dec && param.value - port.level <= 0.0f) || (dec && param.value - port.level >= 0.0f))
{ {
if (port.level_set - port.level <= 0.0f) port.level = param.value;
{ port.level_set.compare_and_swap(param, { param.value, 0.0f });
port.level = port.level_set;
port.level_inc = 0.0f;
}
}
else
{
if (port.level_set - port.level >= 0.0f)
{
port.level = port.level_set;
port.level_inc = 0.0f;
}
} }
} }
}; };
@ -397,9 +389,9 @@ s32 cellAudioInit()
for (auto key : g_audio.keys) for (auto key : g_audio.keys)
{ {
if (std::shared_ptr<event_queue_t> queue = Emu.GetEventManager().GetEventQueue(key)) if (const auto queue = Emu.GetEventManager().GetEventQueue(key))
{ {
queue->push(0, 0, 0, 0); // TODO: check arguments queue->push(lv2_lock, 0, 0, 0, 0); // TODO: check arguments
} }
} }
} }
@ -547,8 +539,7 @@ s32 cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32> portN
port.level = 1.0f; port.level = 1.0f;
} }
port.level_set = port.level; port.level_set.data = { port.level, 0.0f };
port.level_inc = 0.0f;
*portNum = port_index; *portNum = port_index;
cellAudio.Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index); cellAudio.Warning("*** audio port opened(nChannel=%d, nBlock=%d, attr=0x%llx, level=%f): port = %d", channel, block, attr, port.level, port_index);
@ -754,10 +745,7 @@ s32 cellAudioSetPortLevel(u32 portNum, float level)
if (level >= 0.0f) if (level >= 0.0f)
{ {
std::lock_guard<std::mutex> lock(g_audio.mutex); port.level_set.exchange({ level, (port.level - level) / 624.0f });
port.level_set = level;
port.level_inc = (port.level - level) / 624.0f;
} }
else else
{ {

View file

@ -108,9 +108,15 @@ struct AudioPortConfig
u32 addr; u32 addr;
u32 read_index_addr; u32 read_index_addr;
u32 size; u32 size;
struct level_set_t
{
float value;
float inc;
};
float level; float level;
float level_set; atomic_le_t<level_set_t> level_set;
float level_inc;
}; };
struct AudioConfig //custom structure struct AudioConfig //custom structure

View file

@ -6,15 +6,15 @@
extern Module cellAvconfExt; extern Module cellAvconfExt;
int cellVideoOutConvertCursorColor() s32 cellVideoOutConvertCursorColor()
{ {
UNIMPLEMENTED_FUNC(cellAvconfExt); UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK; return CELL_OK;
} }
int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize) s32 cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
{ {
cellAvconfExt.Warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize_addr=0x%x)", videoOut, screenSize.addr()); cellAvconfExt.Warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize=*0x%x)", videoOut, screenSize);
if (videoOut != CELL_VIDEO_OUT_PRIMARY) if (videoOut != CELL_VIDEO_OUT_PRIMARY)
{ {
@ -23,8 +23,8 @@ int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
//TODO: Use virtual screen size //TODO: Use virtual screen size
#ifdef _WIN32 #ifdef _WIN32
HDC screen = GetDC(NULL); //HDC screen = GetDC(NULL);
float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f); //float diagonal = roundf(sqrtf((powf(float(GetDeviceCaps(screen, HORZSIZE)), 2) + powf(float(GetDeviceCaps(screen, VERTSIZE)), 2))) * 0.0393f);
#else #else
// TODO: Linux implementation, without using wx // TODO: Linux implementation, without using wx
// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f); // float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f);
@ -32,22 +32,20 @@ int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
if (Ini.GS3DTV.GetValue()) if (Ini.GS3DTV.GetValue())
{ {
#ifdef _WIN32 *screenSize = 24.0f;
*screenSize = diagonal;
#endif
return CELL_OK; return CELL_OK;
} }
return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET; return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET;
} }
int cellVideoOutGetGamma() s32 cellVideoOutGetGamma()
{ {
UNIMPLEMENTED_FUNC(cellAvconfExt); UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK; return CELL_OK;
} }
int cellVideoOutSetGamma() s32 cellVideoOutSetGamma()
{ {
UNIMPLEMENTED_FUNC(cellAvconfExt); UNIMPLEMENTED_FUNC(cellAvconfExt);
return CELL_OK; return CELL_OK;

View file

@ -284,16 +284,18 @@ void dmuxQueryAttr(u32 info_addr /* may be 0 */, vm::ptr<CellDmuxAttr> attr)
attr->memSize = 0x10000; // 0x3e8e6 from ps3 attr->memSize = 0x10000; // 0x3e8e6 from ps3
} }
void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, vm::ptr<const CellCodecEsFilterId> esFilterId, void dmuxQueryEsAttr(u32 info /* may be 0 */, vm::ptr<const CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> attr)
const u32 esSpecificInfo_addr, vm::ptr<CellDmuxEsAttr> attr)
{ {
if (esFilterId->filterIdMajor >= 0xe0) if (esFilterId->filterIdMajor >= 0xe0)
{
attr->memSize = 0x500000; // 0x45fa49 from ps3 attr->memSize = 0x500000; // 0x45fa49 from ps3
}
else else
{
attr->memSize = 0x7000; // 0x73d9 from ps3 attr->memSize = 0x7000; // 0x73d9 from ps3
}
cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2);
(u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2);
} }
u32 dmuxOpen(Demuxer* dmux_ptr) u32 dmuxOpen(Demuxer* dmux_ptr)
@ -306,7 +308,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
dmux.id = dmux_id; dmux.id = dmux_id;
dmux.dmuxCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get()); dmux.dmuxCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get());
dmux.dmuxCb->SetName(fmt::format("Demuxer[%d] Callback", dmux_id)); dmux.dmuxCb->SetName(fmt::format("Demuxer[0x%x] Callback", dmux_id));
dmux.dmuxCb->SetEntry(0); dmux.dmuxCb->SetEntry(0);
dmux.dmuxCb->SetPrio(1001); dmux.dmuxCb->SetPrio(1001);
dmux.dmuxCb->SetStackSize(0x10000); dmux.dmuxCb->SetStackSize(0x10000);
@ -314,7 +316,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
dmux.dmuxCb->InitRegs(); dmux.dmuxCb->InitRegs();
dmux.dmuxCb->DoRun(); dmux.dmuxCb->DoRun();
thread_t t(fmt::format("Demuxer[%d] Thread", dmux_id), [dmux_ptr, sptr]() thread_t t(fmt::format("Demuxer[0x%x] Thread", dmux_id), [dmux_ptr, sptr]()
{ {
Demuxer& dmux = *dmux_ptr; Demuxer& dmux = *dmux_ptr;
@ -774,92 +776,92 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
return dmux_id; return dmux_id;
} }
int cellDmuxQueryAttr(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<CellDmuxAttr> demuxerAttr) s32 cellDmuxQueryAttr(vm::ptr<const CellDmuxType> type, vm::ptr<CellDmuxAttr> attr)
{ {
cellDmux.Warning("cellDmuxQueryAttr(demuxerType_addr=0x%x, demuxerAttr_addr=0x%x)", demuxerType.addr(), demuxerAttr.addr()); cellDmux.Warning("cellDmuxQueryAttr(type=*0x%x, attr=*0x%x)", type, attr);
if (demuxerType->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
dmuxQueryAttr(0, demuxerAttr); dmuxQueryAttr(0, attr);
return CELL_OK; return CELL_OK;
} }
int cellDmuxQueryAttr2(vm::ptr<const CellDmuxType2> demuxerType2, vm::ptr<CellDmuxAttr> demuxerAttr) s32 cellDmuxQueryAttr2(vm::ptr<const CellDmuxType2> type2, vm::ptr<CellDmuxAttr> attr)
{ {
cellDmux.Warning("cellDmuxQueryAttr2(demuxerType2_addr=0x%x, demuxerAttr_addr=0x%x)", demuxerType2.addr(), demuxerAttr.addr()); cellDmux.Warning("cellDmuxQueryAttr2(demuxerType2=*0x%x, demuxerAttr=*0x%x)", type2, attr);
if (demuxerType2->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type2->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
dmuxQueryAttr(demuxerType2->streamSpecificInfo_addr, demuxerAttr); dmuxQueryAttr(type2->streamSpecificInfo, attr);
return CELL_OK; return CELL_OK;
} }
int cellDmuxOpen(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDmuxResource> demuxerResource, s32 cellDmuxOpen(vm::ptr<const CellDmuxType> type, vm::ptr<const CellDmuxResource> res, vm::ptr<const CellDmuxCb> cb, vm::ptr<u32> handle)
vm::ptr<const CellDmuxCb> demuxerCb, vm::ptr<u32> demuxerHandle)
{ {
cellDmux.Warning("cellDmuxOpen(demuxerType_addr=0x%x, demuxerResource_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", cellDmux.Warning("cellDmuxOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
demuxerType.addr(), demuxerResource.addr(), demuxerCb.addr(), demuxerHandle.addr());
if (demuxerType->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
// TODO: check demuxerResource and demuxerCb arguments // TODO: check demuxerResource and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg)); *handle = dmuxOpen(new Demuxer(res->memAddr, res->memSize, cb->cbMsgFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellDmuxOpenEx(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellDmuxResourceEx> demuxerResourceEx, s32 cellDmuxOpenEx(vm::ptr<const CellDmuxType> type, vm::ptr<const CellDmuxResourceEx> resEx, vm::ptr<const CellDmuxCb> cb, vm::ptr<u32> handle)
vm::ptr<const CellDmuxCb> demuxerCb, vm::ptr<u32> demuxerHandle)
{ {
cellDmux.Warning("cellDmuxOpenEx(demuxerType_addr=0x%x, demuxerResourceEx_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", cellDmux.Warning("cellDmuxOpenEx(type=*0x%x, resEx=*0x%x, cb=*0x%x, handle=*0x%x)", type, resEx, cb, handle);
demuxerType.addr(), demuxerResourceEx.addr(), demuxerCb.addr(), demuxerHandle.addr());
if (demuxerType->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
// TODO: check demuxerResourceEx and demuxerCb arguments // TODO: check demuxerResourceEx and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg)); *handle = dmuxOpen(new Demuxer(resEx->memAddr, resEx->memSize, cb->cbMsgFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellDmuxOpen2(vm::ptr<const CellDmuxType2> demuxerType2, vm::ptr<const CellDmuxResource2> demuxerResource2, s32 _nid_e075fabc(vm::ptr<const CellDmuxType> type, vm::ptr<const CellDmuxResourceEx> resEx, vm::ptr<const CellDmuxCb> cb, vm::ptr<u32> handle)
vm::ptr<const CellDmuxCb> demuxerCb, vm::ptr<u32> demuxerHandle)
{ {
cellDmux.Warning("cellDmuxOpen2(demuxerType2_addr=0x%x, demuxerResource2_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", return cellDmuxOpenEx(type, resEx, cb, handle);
demuxerType2.addr(), demuxerResource2.addr(), demuxerCb.addr(), demuxerHandle.addr()); }
if (demuxerType2->streamType != CELL_DMUX_STREAM_TYPE_PAMF) s32 cellDmuxOpen2(vm::ptr<const CellDmuxType2> type2, vm::ptr<const CellDmuxResource2> res2, vm::ptr<const CellDmuxCb> cb, vm::ptr<u32> handle)
{
cellDmux.Warning("cellDmuxOpen2(type2=*0x%x, res2=*0x%x, cb=*0x%x, handle=*0x%x)", type2, res2, cb, handle);
if (type2->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
// TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments // TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments
*demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg)); *handle = dmuxOpen(new Demuxer(res2->memAddr, res2->memSize, cb->cbMsgFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellDmuxClose(u32 demuxerHandle) s32 cellDmuxClose(u32 handle)
{ {
cellDmux.Warning("cellDmuxClose(demuxerHandle=%d)", demuxerHandle); cellDmux.Warning("cellDmuxClose(handle=0x%x)", handle);
std::shared_ptr<Demuxer> dmux; const auto dmux = Emu.GetIdManager().GetIDData<Demuxer>(handle);
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
if (!dmux)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -871,7 +873,7 @@ int cellDmuxClose(u32 demuxerHandle)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
cellDmux.Warning("cellDmuxClose(%d) aborted", demuxerHandle); cellDmux.Warning("cellDmuxClose(%d) aborted", handle);
return CELL_OK; return CELL_OK;
} }
@ -879,17 +881,17 @@ int cellDmuxClose(u32 demuxerHandle)
} }
if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId()); if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId());
Emu.GetIdManager().RemoveID<Demuxer>(demuxerHandle); Emu.GetIdManager().RemoveID<Demuxer>(handle);
return CELL_OK; return CELL_OK;
} }
int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData) s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData)
{ {
cellDmux.Log("cellDmuxSetStream(demuxerHandle=%d, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx", cellDmux.Log("cellDmuxSetStream(handle=0x%x, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx)", handle, streamAddress, streamSize, discontinuity, userData);
demuxerHandle, streamAddress, streamSize, discontinuity, userData);
std::shared_ptr<Demuxer> dmux; const auto dmux = Emu.GetIdManager().GetIDData<Demuxer>(handle);
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
if (!dmux)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -911,12 +913,13 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
return CELL_OK; return CELL_OK;
} }
int cellDmuxResetStream(u32 demuxerHandle) s32 cellDmuxResetStream(u32 handle)
{ {
cellDmux.Warning("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle); cellDmux.Warning("cellDmuxResetStream(handle=0x%x)", handle);
std::shared_ptr<Demuxer> dmux; const auto dmux = Emu.GetIdManager().GetIDData<Demuxer>(handle);
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
if (!dmux)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -925,12 +928,13 @@ int cellDmuxResetStream(u32 demuxerHandle)
return CELL_OK; return CELL_OK;
} }
int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle) s32 cellDmuxResetStreamAndWaitDone(u32 handle)
{ {
cellDmux.Warning("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle); cellDmux.Warning("cellDmuxResetStreamAndWaitDone(handle=0x%x)", handle);
std::shared_ptr<Demuxer> dmux; const auto dmux = Emu.GetIdManager().GetIDData<Demuxer>(handle);
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
if (!dmux)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -948,7 +952,7 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
cellDmux.Warning("cellDmuxResetStreamAndWaitDone(%d) aborted", demuxerHandle); cellDmux.Warning("cellDmuxResetStreamAndWaitDone(%d) aborted", handle);
return CELL_OK; return CELL_OK;
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
@ -957,48 +961,41 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
return CELL_OK; return CELL_OK;
} }
int cellDmuxQueryEsAttr(vm::ptr<const CellDmuxType> demuxerType, vm::ptr<const CellCodecEsFilterId> esFilterId, s32 cellDmuxQueryEsAttr(vm::ptr<const CellDmuxType> type, vm::ptr<const CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
const u32 esSpecificInfo_addr, vm::ptr<CellDmuxEsAttr> esAttr)
{ {
cellDmux.Warning("cellDmuxQueryEsAttr(demuxerType_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)", cellDmux.Warning("cellDmuxQueryEsAttr(demuxerType=*0x%x, esFilterId=*0x%x, esSpecificInfo=*0x%x, esAttr=*0x%x)", type, esFilterId, esSpecificInfo, esAttr);
demuxerType.addr(), esFilterId.addr(), esSpecificInfo_addr, esAttr.addr());
if (demuxerType->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
// TODO: check esFilterId and esSpecificInfo correctly // TODO: check esFilterId and esSpecificInfo correctly
dmuxQueryEsAttr(0, esFilterId, esSpecificInfo_addr, esAttr); dmuxQueryEsAttr(0, esFilterId, esSpecificInfo, esAttr);
return CELL_OK; return CELL_OK;
} }
int cellDmuxQueryEsAttr2(vm::ptr<const CellDmuxType2> demuxerType2, vm::ptr<const CellCodecEsFilterId> esFilterId, s32 cellDmuxQueryEsAttr2(vm::ptr<const CellDmuxType2> type2, vm::ptr<const CellCodecEsFilterId> esFilterId, u32 esSpecificInfo, vm::ptr<CellDmuxEsAttr> esAttr)
const u32 esSpecificInfo_addr, vm::ptr<CellDmuxEsAttr> esAttr)
{ {
cellDmux.Warning("cellDmuxQueryEsAttr2(demuxerType2_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)", cellDmux.Warning("cellDmuxQueryEsAttr2(type2=*0x%x, esFilterId=*0x%x, esSpecificInfo=*0x%x, esAttr=*0x%x)", type2, esFilterId, esSpecificInfo, esAttr);
demuxerType2.addr(), esFilterId.addr(), esSpecificInfo_addr, esAttr.addr());
if (demuxerType2->streamType != CELL_DMUX_STREAM_TYPE_PAMF) if (type2->streamType != CELL_DMUX_STREAM_TYPE_PAMF)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
// TODO: check demuxerType2, esFilterId and esSpecificInfo correctly // TODO: check demuxerType2, esFilterId and esSpecificInfo correctly
dmuxQueryEsAttr(demuxerType2->streamSpecificInfo_addr, esFilterId, esSpecificInfo_addr, esAttr); dmuxQueryEsAttr(type2->streamSpecificInfo, esFilterId, esSpecificInfo, esAttr);
return CELL_OK; return CELL_OK;
} }
int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFilterId, s32 cellDmuxEnableEs(u32 handle, vm::ptr<const CellCodecEsFilterId> esFilterId, vm::ptr<const CellDmuxEsResource> esResourceInfo, vm::ptr<const CellDmuxEsCb> esCb, u32 esSpecificInfo, vm::ptr<u32> esHandle)
vm::ptr<const CellDmuxEsResource> esResourceInfo, vm::ptr<const CellDmuxEsCb> esCb,
const u32 esSpecificInfo_addr, vm::ptr<u32> esHandle)
{ {
cellDmux.Warning("cellDmuxEnableEs(demuxerHandle=%d, esFilterId_addr=0x%x, esResourceInfo_addr=0x%x, esCb_addr=0x%x, " cellDmux.Warning("cellDmuxEnableEs(handle=0x%x, esFilterId=*0x%x, esResourceInfo=*0x%x, esCb=*0x%x, esSpecificInfo=*0x%x, esHandle=*0x%x)", handle, esFilterId, esResourceInfo, esCb, esSpecificInfo, esHandle);
"esSpecificInfo_addr=0x%x, esHandle_addr=0x%x)", demuxerHandle, esFilterId.addr(), esResourceInfo.addr(),
esCb.addr(), esSpecificInfo_addr, esHandle.addr());
std::shared_ptr<Demuxer> dmux; const auto dmux = Emu.GetIdManager().GetIDData<Demuxer>(handle);
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
if (!dmux)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1007,14 +1004,14 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
std::shared_ptr<ElementaryStream> es(new ElementaryStream(dmux.get(), esResourceInfo->memAddr, esResourceInfo->memSize, std::shared_ptr<ElementaryStream> es(new ElementaryStream(dmux.get(), esResourceInfo->memAddr, esResourceInfo->memSize,
esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2, esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2,
esCb->cbEsMsgFunc, esCb->cbArg, esSpecificInfo_addr)); esCb->cbEsMsgFunc, esCb->cbArg, esSpecificInfo));
u32 id = Emu.GetIdManager().GetNewID(es); u32 id = Emu.GetIdManager().GetNewID(es);
es->id = id; es->id = id;
*esHandle = id; *esHandle = id;
cellDmux.Warning("*** New ES(dmux=%d, addr=0x%x, size=0x%x, filter(0x%x, 0x%x, 0x%x, 0x%x), cb=0x%x(arg=0x%x), spec=0x%x): id = %d", cellDmux.Warning("*** New ES(dmux=0x%x, addr=0x%x, size=0x%x, filter={0x%x, 0x%x, 0x%x, 0x%x}, cb=0x%x, arg=0x%x, spec=0x%x): id = %d",
demuxerHandle, es->memAddr, es->memSize, es->fidMajor, es->fidMinor, es->sup1, es->sup2, es->cbFunc, es->cbArg, es->spec, id); handle, es->memAddr, es->memSize, es->fidMajor, es->fidMinor, es->sup1, es->sup2, es->cbFunc, es->cbArg, es->spec, id);
DemuxerTask task(dmuxEnableEs); DemuxerTask task(dmuxEnableEs);
task.es.es = id; task.es.es = id;
@ -1024,12 +1021,13 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
return CELL_OK; return CELL_OK;
} }
int cellDmuxDisableEs(u32 esHandle) s32 cellDmuxDisableEs(u32 esHandle)
{ {
cellDmux.Warning("cellDmuxDisableEs(esHandle=0x%x)", esHandle); cellDmux.Warning("cellDmuxDisableEs(esHandle=0x%x)", esHandle);
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1042,12 +1040,13 @@ int cellDmuxDisableEs(u32 esHandle)
return CELL_OK; return CELL_OK;
} }
int cellDmuxResetEs(u32 esHandle) s32 cellDmuxResetEs(u32 esHandle)
{ {
cellDmux.Log("cellDmuxResetEs(esHandle=0x%x)", esHandle); cellDmux.Log("cellDmuxResetEs(esHandle=0x%x)", esHandle);
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1060,13 +1059,13 @@ int cellDmuxResetEs(u32 esHandle)
return CELL_OK; return CELL_OK;
} }
int cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecificInfo_ptr) s32 cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
{ {
cellDmux.Log("cellDmuxGetAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", cellDmux.Log("cellDmuxGetAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo);
esHandle, auInfo_ptr.addr(), auSpecificInfo_ptr.addr());
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1078,18 +1077,18 @@ int cellDmuxGetAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecific
return CELL_DMUX_ERROR_EMPTY; return CELL_DMUX_ERROR_EMPTY;
} }
*auInfo_ptr = info; *auInfo = info;
*auSpecificInfo_ptr = spec; *auSpecificInfo = spec;
return CELL_OK; return CELL_OK;
} }
int cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecificInfo_ptr) s32 cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo, vm::ptr<u32> auSpecificInfo)
{ {
cellDmux.Log("cellDmuxPeekAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", cellDmux.Log("cellDmuxPeekAu(esHandle=0x%x, auInfo=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfo, auSpecificInfo);
esHandle, auInfo_ptr.addr(), auSpecificInfo_ptr.addr());
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1101,18 +1100,18 @@ int cellDmuxPeekAu(u32 esHandle, vm::ptr<u32> auInfo_ptr, vm::ptr<u32> auSpecifi
return CELL_DMUX_ERROR_EMPTY; return CELL_DMUX_ERROR_EMPTY;
} }
*auInfo_ptr = info; *auInfo = info;
*auSpecificInfo_ptr = spec; *auSpecificInfo = spec;
return CELL_OK; return CELL_OK;
} }
int cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpecificInfo_ptr) s32 cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
{ {
cellDmux.Log("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", cellDmux.Log("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo);
esHandle, auInfoEx_ptr.addr(), auSpecificInfo_ptr.addr());
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1124,18 +1123,18 @@ int cellDmuxGetAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpec
return CELL_DMUX_ERROR_EMPTY; return CELL_DMUX_ERROR_EMPTY;
} }
*auInfoEx_ptr = info; *auInfoEx = info;
*auSpecificInfo_ptr = spec; *auSpecificInfo = spec;
return CELL_OK; return CELL_OK;
} }
int cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpecificInfo_ptr) s32 cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx, vm::ptr<u32> auSpecificInfo)
{ {
cellDmux.Log("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", cellDmux.Log("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx=**0x%x, auSpecificInfo=**0x%x)", esHandle, auInfoEx, auSpecificInfo);
esHandle, auInfoEx_ptr.addr(), auSpecificInfo_ptr.addr());
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1147,17 +1146,18 @@ int cellDmuxPeekAuEx(u32 esHandle, vm::ptr<u32> auInfoEx_ptr, vm::ptr<u32> auSpe
return CELL_DMUX_ERROR_EMPTY; return CELL_DMUX_ERROR_EMPTY;
} }
*auInfoEx_ptr = info; *auInfoEx = info;
*auSpecificInfo_ptr = spec; *auSpecificInfo = spec;
return CELL_OK; return CELL_OK;
} }
int cellDmuxReleaseAu(u32 esHandle) s32 cellDmuxReleaseAu(u32 esHandle)
{ {
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1169,12 +1169,13 @@ int cellDmuxReleaseAu(u32 esHandle)
return CELL_OK; return CELL_OK;
} }
int cellDmuxFlushEs(u32 esHandle) s32 cellDmuxFlushEs(u32 esHandle)
{ {
cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle); cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
std::shared_ptr<ElementaryStream> es; const auto es = Emu.GetIdManager().GetIDData<ElementaryStream>(esHandle);
if (!Emu.GetIdManager().GetIDData(esHandle, es))
if (!es)
{ {
return CELL_DMUX_ERROR_ARG; return CELL_DMUX_ERROR_ARG;
} }
@ -1193,6 +1194,7 @@ Module cellDmux("cellDmux", []()
REG_FUNC(cellDmux, cellDmuxQueryAttr2); REG_FUNC(cellDmux, cellDmuxQueryAttr2);
REG_FUNC(cellDmux, cellDmuxOpen); REG_FUNC(cellDmux, cellDmuxOpen);
REG_FUNC(cellDmux, cellDmuxOpenEx); REG_FUNC(cellDmux, cellDmuxOpenEx);
REG_UNNAMED(cellDmux, e075fabc);
REG_FUNC(cellDmux, cellDmuxOpen2); REG_FUNC(cellDmux, cellDmuxOpen2);
REG_FUNC(cellDmux, cellDmuxClose); REG_FUNC(cellDmux, cellDmuxClose);
REG_FUNC(cellDmux, cellDmuxSetStream); REG_FUNC(cellDmux, cellDmuxSetStream);

View file

@ -169,7 +169,7 @@ struct CellDmuxPamfSpecificInfo
struct CellDmuxType2 struct CellDmuxType2
{ {
be_t<CellDmuxStreamType> streamType; be_t<CellDmuxStreamType> streamType;
be_t<u32> streamSpecificInfo_addr; be_t<u32> streamSpecificInfo;
}; };
struct CellDmuxResource struct CellDmuxResource

View file

@ -84,7 +84,7 @@ vm::ptr<void> cellFiberPpuSelf()
cellFiber.Log("cellFiberPpuSelf() -> nullptr"); // TODO cellFiber.Log("cellFiberPpuSelf() -> nullptr"); // TODO
// returns fiber structure (zero for simple PPU thread) // returns fiber structure (zero for simple PPU thread)
return vm::ptr<void>::make(0); return vm::null;
} }
int cellFiberPpuSendSignal() int cellFiberPpuSendSignal()

View file

@ -210,38 +210,42 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32
{ {
cellFs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count); cellFs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count);
std::shared_ptr<vfsDirBase> directory; const auto directory = Emu.GetIdManager().GetIDData<vfsDirBase>(fd);
if (!Emu.GetIdManager().GetIDData(fd, directory)) if (!directory)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
const DirEntryInfo* info = directory->Read(); u32 count = 0;
if (info)
{
entries->attribute.mode =
CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR |
CELL_FS_S_IRGRP | CELL_FS_S_IWGRP | CELL_FS_S_IXGRP |
CELL_FS_S_IROTH | CELL_FS_S_IWOTH | CELL_FS_S_IXOTH;
entries->attribute.uid = 0; entries_size /= sizeof(CellFsDirectoryEntry);
entries->attribute.gid = 0;
entries->attribute.atime = 0; //TODO
entries->attribute.mtime = 0; //TODO
entries->attribute.ctime = 0; //TODO
entries->attribute.blksize = 4096;
entries->entry_name.d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; for (; count < entries_size; count++)
entries->entry_name.d_namlen = u8(std::min<size_t>(info->name.length(), CELL_FS_MAX_FS_FILE_NAME_LENGTH));
strcpy_trunc(entries->entry_name.d_name, info->name);
*data_count = 1;
}
else
{ {
*data_count = 0; if (const auto info = directory->Read())
{
entries[count].attribute.mode = info->flags & DirEntry_TypeDir ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666;
entries[count].attribute.uid = 1; // ???
entries[count].attribute.gid = 1; // ???
entries[count].attribute.atime = info->access_time;
entries[count].attribute.mtime = info->modify_time;
entries[count].attribute.ctime = info->create_time;
entries[count].attribute.size = info->size;
entries[count].attribute.blksize = 4096; // ???
entries[count].entry_name.d_type = info->flags & DirEntry_TypeFile ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY;
entries[count].entry_name.d_namlen = u8(std::min<size_t>(info->name.length(), CELL_FS_MAX_FS_FILE_NAME_LENGTH));
strcpy_trunc(entries[count].entry_name.d_name, info->name);
}
else
{
break;
}
} }
*data_count = count;
return CELL_OK; return CELL_OK;
} }
@ -251,9 +255,9 @@ s32 cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size,
// TODO: use single sys_fs_fcntl syscall // TODO: use single sys_fs_fcntl syscall
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file) || file->flags & CELL_FS_O_WRONLY) if (!file || file->flags & CELL_FS_O_WRONLY)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -282,9 +286,9 @@ s32 cellFsWriteWithOffset(u32 fd, u64 offset, vm::ptr<const void> buf, u64 data_
// TODO: use single sys_fs_fcntl syscall // TODO: use single sys_fs_fcntl syscall
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file) || !(file->flags & CELL_FS_O_ACCMODE)) if (!file || !(file->flags & CELL_FS_O_ACCMODE))
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -326,9 +330,9 @@ s32 cellFsStReadInit(u32 fd, vm::ptr<const CellFsRingBuffer> ringbuf)
return CELL_FS_EINVAL; return CELL_FS_EINVAL;
} }
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -364,9 +368,9 @@ s32 cellFsStReadFinish(u32 fd)
{ {
cellFs.Warning("cellFsStReadFinish(fd=0x%x)", fd); cellFs.Warning("cellFsStReadFinish(fd=0x%x)", fd);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; // ??? return CELL_FS_EBADF; // ???
} }
@ -387,9 +391,9 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
{ {
cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=*0x%x)", fd, ringbuf); cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=*0x%x)", fd, ringbuf);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -411,9 +415,9 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr<u64> status)
{ {
cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=*0x%x)", fd, status); cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=*0x%x)", fd, status);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -445,9 +449,9 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
{ {
cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=*0x%x)", fd, regid); cellFs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=*0x%x)", fd, regid);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -466,9 +470,9 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
{ {
cellFs.Warning("cellFsStReadStart(fd=0x%x, offset=0x%llx, size=0x%llx)", fd, offset, size); cellFs.Warning("cellFsStReadStart(fd=0x%x, offset=0x%llx, size=0x%llx)", fd, offset, size);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -548,9 +552,9 @@ s32 cellFsStReadStop(u32 fd)
{ {
cellFs.Warning("cellFsStReadStop(fd=0x%x)", fd); cellFs.Warning("cellFsStReadStop(fd=0x%x)", fd);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -579,9 +583,9 @@ s32 cellFsStRead(u32 fd, vm::ptr<u8> buf, u64 size, vm::ptr<u64> rsize)
{ {
cellFs.Warning("cellFsStRead(fd=0x%x, buf=*0x%x, size=0x%llx, rsize=*0x%x)", fd, buf, size, rsize); cellFs.Warning("cellFsStRead(fd=0x%x, buf=*0x%x, size=0x%llx, rsize=*0x%x)", fd, buf, size, rsize);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -613,9 +617,9 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<u32> addr, vm::ptr<u64> size)
{ {
cellFs.Warning("cellFsStReadGetCurrentAddr(fd=0x%x, addr=*0x%x, size=*0x%x)", fd, addr, size); cellFs.Warning("cellFsStReadGetCurrentAddr(fd=0x%x, addr=*0x%x, size=*0x%x)", fd, addr, size);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -646,9 +650,9 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr<u8> addr, u64 size)
{ {
cellFs.Warning("cellFsStReadPutCurrentAddr(fd=0x%x, addr=*0x%x, size=0x%llx)", fd, addr, size); cellFs.Warning("cellFsStReadPutCurrentAddr(fd=0x%x, addr=*0x%x, size=0x%llx)", fd, addr, size);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -673,9 +677,9 @@ s32 cellFsStReadWait(u32 fd, u64 size)
{ {
cellFs.Warning("cellFsStReadWait(fd=0x%x, size=0x%llx)", fd, size); cellFs.Warning("cellFsStReadWait(fd=0x%x, size=0x%llx)", fd, size);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -707,9 +711,9 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, fs_st_cb_t func)
{ {
cellFs.Warning("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=*0x%x)", fd, size, func); cellFs.Warning("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=*0x%x)", fd, size, func);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
return CELL_FS_EBADF; return CELL_FS_EBADF;
} }
@ -756,17 +760,17 @@ bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp)
int sdata_unpack(const std::string& packed_file, const std::string& unpacked_file) int sdata_unpack(const std::string& packed_file, const std::string& unpacked_file)
{ {
std::shared_ptr<vfsFileBase> packed_stream(Emu.GetVFS().OpenFile(packed_file, vfsRead)); std::shared_ptr<vfsFileBase> packed_stream(Emu.GetVFS().OpenFile(packed_file, vfsRead));
std::shared_ptr<vfsFileBase> unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, vfsWrite)); std::shared_ptr<vfsFileBase> unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, vfsWriteNew));
if (!packed_stream || !packed_stream->IsOpened()) if (!packed_stream || !packed_stream->IsOpened())
{ {
cellFs.Error("'%s' not found! flags: 0x%02x", packed_file.c_str(), vfsRead); cellFs.Error("File '%s' not found!", packed_file.c_str());
return CELL_ENOENT; return CELL_ENOENT;
} }
if (!unpacked_stream || !unpacked_stream->IsOpened()) if (!unpacked_stream || !unpacked_stream->IsOpened())
{ {
cellFs.Error("'%s' couldn't be created! flags: 0x%02x", unpacked_file.c_str(), vfsWrite); cellFs.Error("File '%s' couldn't be created!", unpacked_file.c_str());
return CELL_ENOENT; return CELL_ENOENT;
} }
@ -875,9 +879,9 @@ void fsAio(vm::ptr<CellFsAio> aio, bool write, s32 xid, fs_aio_cb_t func)
s32 error = CELL_OK; s32 error = CELL_OK;
u64 result = 0; u64 result = 0;
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(aio->fd);
if (!Emu.GetIdManager().GetIDData(aio->fd, file) || (!write && file->flags & CELL_FS_O_WRONLY) || (write && !(file->flags & CELL_FS_O_ACCMODE))) if (!file || (!write && file->flags & CELL_FS_O_WRONLY) || (write && !(file->flags & CELL_FS_O_ACCMODE)))
{ {
error = CELL_FS_EBADF; error = CELL_FS_EBADF;
} }
@ -970,20 +974,20 @@ s32 cellFsAioCancel(s32 id)
s32 cellFsSetDefaultContainer(u32 id, u32 total_limit) s32 cellFsSetDefaultContainer(u32 id, u32 total_limit)
{ {
cellFs.Todo("cellFsSetDefaultContainer(id=%d, total_limit=%d)", id, total_limit); cellFs.Todo("cellFsSetDefaultContainer(id=0x%x, total_limit=%d)", id, total_limit);
return CELL_OK; return CELL_OK;
} }
s32 cellFsSetIoBufferFromDefaultContainer(u32 fd, u32 buffer_size, u32 page_type) s32 cellFsSetIoBufferFromDefaultContainer(u32 fd, u32 buffer_size, u32 page_type)
{ {
cellFs.Todo("cellFsSetIoBufferFromDefaultContainer(fd=%d, buffer_size=%d, page_type=%d)", fd, buffer_size, page_type); cellFs.Todo("cellFsSetIoBufferFromDefaultContainer(fd=0x%x, buffer_size=%d, page_type=%d)", fd, buffer_size, page_type);
std::shared_ptr<fs_file_t> file; const auto file = Emu.GetIdManager().GetIDData<fs_file_t>(fd);
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!file)
{ {
CELL_FS_EBADF; return CELL_FS_EBADF;
} }
return CELL_OK; return CELL_OK;

View file

@ -8,18 +8,91 @@
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsFile.h"
#include "Loader/PSF.h" #include "Loader/PSF.h"
#include "cellSysutil.h"
#include "cellGame.h" #include "cellGame.h"
extern Module cellGame; extern Module cellGame;
std::string contentInfo = ""; std::string contentInfo;
std::string usrdir = ""; std::string usrdir;
bool path_set = false; bool path_set = false;
int cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGameContentSize> size, vm::ptr<char[CELL_GAME_DIRNAME_SIZE]> dirName) s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
{ {
cellGame.Warning("cellGameBootCheck(type_addr=0x%x, attributes_addr=0x%x, size_addr=0x%x, dirName_addr=0x%x)", cellGame.Warning("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
type.addr(), attributes.addr(), size.addr(), dirName.addr());
std::string dir = dirName.get_ptr();
if (dir.size() != 9)
{
return CELL_HDDGAME_ERROR_PARAM;
}
vm::var<CellHddGameSystemFileParam> param;
vm::var<CellHddGameCBResult> result;
vm::var<CellHddGameStatGet> get;
vm::var<CellHddGameStatSet> set;
get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST;
get->sysSizeKB = 0; // TODO
get->atime = 0; // TODO
get->ctime = 0; // TODO
get->mtime = 0; // TODO
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
strcpy_trunc(get->contentInfoPath, "/dev_hdd0/game/" + dir);
strcpy_trunc(get->hddGamePath, "/dev_hdd0/game/" + dir + "/USRDIR");
if (!Emu.GetVFS().ExistsDir("/dev_hdd0/game/" + dir))
{
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
}
else
{
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
vfsFile f("/dev_hdd0/game/" + dir + "/PARAM.SFO");
const PSFLoader psf(f);
if (!psf)
{
return CELL_HDDGAME_ERROR_BROKEN;
}
get->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
get->getParam.attribute = psf.GetInteger("ATTRIBUTE");
get->getParam.resolution = psf.GetInteger("RESOLUTION");
get->getParam.soundFormat = psf.GetInteger("SOUND_FORMAT");
std::string title = psf.GetString("TITLE");
strcpy_trunc(get->getParam.title, title);
std::string app_ver = psf.GetString("APP_VER");
strcpy_trunc(get->getParam.dataVersion, app_ver);
strcpy_trunc(get->getParam.titleId, dir);
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
{
char key[16];
sprintf(key, "TITLE_%02d", i);
title = psf.GetString(key);
strcpy_trunc(get->getParam.titleLang[i], title);
}
}
// TODO ?
//funcStat(result, get, set);
//if (result->result != CELL_HDDGAME_CBRESULT_OK && result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
//{
// return CELL_HDDGAME_ERROR_CBRESULT;
//}
// TODO ?
return CELL_OK;
}
s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGameContentSize> size, vm::ptr<char[CELL_GAME_DIRNAME_SIZE]> dirName)
{
cellGame.Warning("cellGameBootCheck(type=*0x%x, attributes=*0x%x, size=*0x%x, dirName=*0x%x)", type, attributes, size, dirName);
if (size) if (size)
{ {
@ -32,14 +105,8 @@ int cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
} }
vfsFile f("/app_home/../PARAM.SFO"); vfsFile f("/app_home/../PARAM.SFO");
if (!f.IsOpened()) const PSFLoader psf(f);
{ if (!psf)
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
PSFLoader psf(f);
if (!psf.Load(false))
{ {
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)"); cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR; return CELL_GAME_ERROR_ACCESS_ERROR;
@ -84,15 +151,9 @@ int cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
return CELL_GAME_RET_OK; return CELL_GAME_RET_OK;
} }
int cellGamePatchCheck(vm::ptr<CellGameContentSize> size, u32 reserved_addr) s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved)
{ {
cellGame.Warning("cellGamePatchCheck(size_addr=0x%x, reserved_addr=0x%x)", size.addr(), reserved_addr); cellGame.Warning("cellGamePatchCheck(size=*0x%x, reserved=*0x%x)", size, reserved);
if (reserved_addr != 0)
{
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_PARAM");
return CELL_GAME_ERROR_PARAM;
}
if (size) if (size)
{ {
@ -105,14 +166,8 @@ int cellGamePatchCheck(vm::ptr<CellGameContentSize> size, u32 reserved_addr)
} }
vfsFile f("/app_home/../PARAM.SFO"); vfsFile f("/app_home/../PARAM.SFO");
if (!f.IsOpened()) const PSFLoader psf(f);
{ if (!psf)
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
PSFLoader psf(f);
if (!psf.Load(false))
{ {
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)"); cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR; return CELL_GAME_ERROR_ACCESS_ERROR;
@ -133,9 +188,9 @@ int cellGamePatchCheck(vm::ptr<CellGameContentSize> size, u32 reserved_addr)
return CELL_GAME_RET_OK; return CELL_GAME_RET_OK;
} }
int cellGameDataCheck(u32 type, vm::ptr<const char> dirName, vm::ptr<CellGameContentSize> size) s32 cellGameDataCheck(u32 type, vm::ptr<const char> dirName, vm::ptr<CellGameContentSize> size)
{ {
cellGame.Warning("cellGameDataCheck(type=0x%x, dirName_addr=0x%x, size_addr=0x%x)", type, dirName.addr(), size.addr()); cellGame.Warning("cellGameDataCheck(type=%d, dirName=*0x%x, size=*0x%x)", type, dirName, size);
if ((type - 1) >= 3) if ((type - 1) >= 3)
{ {
@ -191,21 +246,33 @@ int cellGameDataCheck(u32 type, vm::ptr<const char> dirName, vm::ptr<CellGameCon
return CELL_GAME_RET_OK; return CELL_GAME_RET_OK;
} }
int cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> usrdirPath) s32 cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> usrdirPath)
{ {
cellGame.Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)", cellGame.Warning("cellGameContentPermit(contentInfoPath=*0x%x, usrdirPath=*0x%x)", contentInfoPath, usrdirPath);
contentInfoPath.addr(), usrdirPath.addr());
if (!contentInfoPath || !usrdirPath) if (!contentInfoPath && !usrdirPath)
{ {
return CELL_GAME_ERROR_PARAM; return CELL_GAME_ERROR_PARAM;
} }
cellGame.Warning("cellGameContentPermit(): path_set=%d, contentInfo='%s', usrdir='%s'", path_set, contentInfo, usrdir);
if (!path_set) if (!path_set)
{ {
return CELL_GAME_ERROR_FAILURE; return CELL_GAME_ERROR_FAILURE;
} }
if (contentInfo.size() == 9 && usrdir.empty())
{
if (Emu.GetVFS().RenameDir("/dev_hdd0/game/TMP_" + contentInfo, "/dev_hdd0/game/" + contentInfo))
{
cellGame.Success("cellGameContentPermit(): gamedata directory created ('/dev_hdd0/game/%s')", contentInfo);
}
contentInfo = "/dev_hdd0/game/" + contentInfo;
usrdir = contentInfo + "/USRDIR";
}
strcpy_trunc(*contentInfoPath, contentInfo); strcpy_trunc(*contentInfoPath, contentInfo);
strcpy_trunc(*usrdirPath, usrdir); strcpy_trunc(*usrdirPath, usrdir);
@ -216,15 +283,13 @@ int cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm:
return CELL_GAME_RET_OK; return CELL_GAME_RET_OK;
} }
int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, s32 cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
vm::ptr<void(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container)
{ {
cellGame.Warning("cellGameDataCheckCreate(2)(version=0x%x, dirName_addr=0x%x, errDialog=0x%x, funcStat_addr=0x%x, container=%d)", cellGame.Warning("cellGameDataCheckCreate2(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
version, dirName.addr(), errDialog, funcStat.addr(), container);
if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1) if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1)
{ {
cellGame.Error("cellGameDataCheckCreate(2)(): CELL_GAMEDATA_ERROR_PARAM"); cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_PARAM");
return CELL_GAMEDATA_ERROR_PARAM; return CELL_GAMEDATA_ERROR_PARAM;
} }
@ -234,22 +299,16 @@ int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> di
if (!Emu.GetVFS().ExistsDir(dir)) if (!Emu.GetVFS().ExistsDir(dir))
{ {
cellGame.Todo("cellGameDataCheckCreate(2)(): creating directory '%s'", dir.c_str()); cellGame.Todo("cellGameDataCheckCreate2(): creating directory '%s'", dir.c_str());
// TODO: create data // TODO: create data
return CELL_GAMEDATA_RET_OK; return CELL_GAMEDATA_RET_OK;
} }
vfsFile f(dir + "/PARAM.SFO"); vfsFile f("/app_home/../PARAM.SFO");
if (!f.IsOpened()) const PSFLoader psf(f);
if (!psf)
{ {
cellGame.Error("cellGameDataCheckCreate(2)(): CELL_GAMEDATA_ERROR_BROKEN (cannot open PARAM.SFO)"); cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN;
}
PSFLoader psf(f);
if (!psf.Load(false))
{
cellGame.Error("cellGameDataCheckCreate(2)(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN; return CELL_GAMEDATA_ERROR_BROKEN;
} }
@ -287,72 +346,100 @@ int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> di
if (cbSet->setParam) if (cbSet->setParam)
{ {
// TODO: write PARAM.SFO from cbSet // TODO: write PARAM.SFO from cbSet
cellGame.Todo("cellGameDataCheckCreate(2)(): writing PARAM.SFO parameters (addr=0x%x)", cbSet->setParam); cellGame.Todo("cellGameDataCheckCreate2(): writing PARAM.SFO parameters (addr=0x%x)", cbSet->setParam);
} }
switch ((s32)cbResult->result) switch ((s32)cbResult->result)
{ {
case CELL_GAMEDATA_CBRESULT_OK_CANCEL: case CELL_GAMEDATA_CBRESULT_OK_CANCEL:
// TODO: do not process game data // TODO: do not process game data
cellGame.Warning("cellGameDataCheckCreate(2)(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL"); cellGame.Warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL");
case CELL_GAMEDATA_CBRESULT_OK: case CELL_GAMEDATA_CBRESULT_OK:
return CELL_GAMEDATA_RET_OK; return CELL_GAMEDATA_RET_OK;
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result
cellGame.Error("cellGameDataCheckCreate(2)(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE"); cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE");
return CELL_GAMEDATA_ERROR_CBRESULT; return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN: case CELL_GAMEDATA_CBRESULT_ERR_BROKEN:
cellGame.Error("cellGameDataCheckCreate(2)(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN"); cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN");
return CELL_GAMEDATA_ERROR_CBRESULT; return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_NODATA: case CELL_GAMEDATA_CBRESULT_ERR_NODATA:
cellGame.Error("cellGameDataCheckCreate(2)(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA"); cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA");
return CELL_GAMEDATA_ERROR_CBRESULT; return CELL_GAMEDATA_ERROR_CBRESULT;
case CELL_GAMEDATA_CBRESULT_ERR_INVALID: case CELL_GAMEDATA_CBRESULT_ERR_INVALID:
cellGame.Error("cellGameDataCheckCreate(2)(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID"); cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID");
return CELL_GAMEDATA_ERROR_CBRESULT; return CELL_GAMEDATA_ERROR_CBRESULT;
default: default:
cellGame.Error("cellGameDataCheckCreate(2)(): callback returned unknown error (code=0x%x)"); cellGame.Error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x)");
return CELL_GAMEDATA_ERROR_CBRESULT; return CELL_GAMEDATA_ERROR_CBRESULT;
} }
} }
int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, s32 cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
vm::ptr<void(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container)
{ {
cellGame.Warning("cellGameDataCheckCreate(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
// TODO: almost identical, the only difference is that this function will always calculate the size of game data // TODO: almost identical, the only difference is that this function will always calculate the size of game data
return cellGameDataCheckCreate2(CPU, version, dirName, errDialog, funcStat, container); return cellGameDataCheckCreate2(CPU, version, dirName, errDialog, funcStat, container);
} }
int cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char> tmp_contentInfoPath, vm::ptr<char> tmp_usrdirPath) s32 cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_usrdirPath)
{ {
cellGame.Todo("cellGameCreateGameData(init_addr=0x%x, tmp_contentInfoPath_addr=0x%x, tmp_usrdirPath_addr=0x%x)", cellGame.Error("cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x)", init, tmp_contentInfoPath, tmp_usrdirPath);
init.addr(), tmp_contentInfoPath.addr(), tmp_usrdirPath.addr());
std::string dir = init->titleId;
std::string tmp_contentInfo = "/dev_hdd0/game/TMP_" + dir;
std::string tmp_usrdir = "/dev_hdd0/game/TMP_" + dir + "/USRDIR";
if (!Emu.GetVFS().CreateDir(tmp_contentInfo))
{
cellGame.Error("cellGameCreateGameData(): failed to create content directory ('%s')", tmp_contentInfo);
return CELL_GAME_ERROR_ACCESS_ERROR; // ???
}
if (!Emu.GetVFS().CreateDir(tmp_usrdir))
{
cellGame.Error("cellGameCreateGameData(): failed to create USRDIR directory ('%s')", tmp_usrdir);
return CELL_GAME_ERROR_ACCESS_ERROR; // ???
}
// TODO: create temporary game directory, set initial PARAM.SFO parameters
// cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement // cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement
strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo);
strcpy_trunc(*tmp_usrdirPath, tmp_usrdir);
contentInfo = dir;
usrdir.clear();
path_set = true;
cellGame.Success("cellGameCreateGameData(): temporary gamedata directory created ('%s')", tmp_contentInfo);
// TODO: set initial PARAM.SFO parameters
return CELL_OK; return CELL_OK;
} }
int cellGameDeleteGameData() s32 cellGameDeleteGameData()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameGetParamInt(u32 id, vm::ptr<u32> value) s32 cellGameGetParamInt(u32 id, vm::ptr<u32> value)
{ {
cellGame.Warning("cellGameGetParamInt(id=%d, value_addr=0x%x)", id, value.addr()); cellGame.Warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value);
// TODO: Access through cellGame***Check functions // TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO"); vfsFile f("/app_home/../PARAM.SFO");
PSFLoader psf(f); const PSFLoader psf(f);
if(!psf.Load(false)) if (!psf)
{
return CELL_GAME_ERROR_FAILURE; return CELL_GAME_ERROR_FAILURE;
}
switch(id) switch(id)
{ {
@ -367,15 +454,17 @@ int cellGameGetParamInt(u32 id, vm::ptr<u32> value)
return CELL_OK; return CELL_OK;
} }
int cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize) s32 cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
{ {
cellGame.Warning("cellGameGetParamString(id=%d, buf_addr=0x%x, bufsize=%d)", id, buf.addr(), bufsize); cellGame.Warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
// TODO: Access through cellGame***Check functions // TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO"); vfsFile f("/app_home/../PARAM.SFO");
PSFLoader psf(f); const PSFLoader psf(f);
if(!psf.Load(false)) if (!psf)
{
return CELL_GAME_ERROR_FAILURE; return CELL_GAME_ERROR_FAILURE;
}
std::string data; std::string data;
switch(id) switch(id)
@ -415,33 +504,33 @@ int cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
return CELL_OK; return CELL_OK;
} }
int cellGameSetParamString() s32 cellGameSetParamString()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameGetSizeKB() s32 cellGameGetSizeKB()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameGetDiscContentInfoUpdatePath() s32 cellGameGetDiscContentInfoUpdatePath()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameGetLocalWebContentPath() s32 cellGameGetLocalWebContentPath()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::ptr<const char> dirName) s32 cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::ptr<const char> dirName)
{ {
cellGame.Warning("cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName_addr=0x%x)", type, errNeedSizeKB, dirName.addr()); cellGame.Warning("cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName=*0x%x)", type, errNeedSizeKB, dirName);
std::string errorName; std::string errorName;
switch (type) switch (type)
@ -475,13 +564,13 @@ int cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::ptr<const char>
return CELL_OK; return CELL_OK;
} }
int cellGameThemeInstall() s32 cellGameThemeInstall()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
} }
int cellGameThemeInstallFromBuffer() s32 cellGameThemeInstallFromBuffer()
{ {
UNIMPLEMENTED_FUNC(cellGame); UNIMPLEMENTED_FUNC(cellGame);
return CELL_OK; return CELL_OK;
@ -517,3 +606,15 @@ Module cellGame("cellGame", []()
REG_FUNC(cellGame, cellGameThemeInstallFromBuffer); REG_FUNC(cellGame, cellGameThemeInstallFromBuffer);
//cellGame.AddFunc(, CellGameThemeInstallCallback); //cellGame.AddFunc(, CellGameThemeInstallCallback);
}); });
void cellSysutil_GameData_init()
{
REG_FUNC(cellGame, cellHddGameCheck);
//REG_FUNC(cellGame, cellHddGameCheck2);
//REG_FUNC(cellGame, cellHddGameGetSizeKB);
//REG_FUNC(cellGame, cellHddGameSetSystemVer);
//REG_FUNC(cellGame, cellHddGameExitBroken);
REG_FUNC(cellGame, cellGameDataCheckCreate);
REG_FUNC(cellGame, cellGameDataCheckCreate2);
}

View file

@ -200,3 +200,92 @@ struct CellGameDataStatSet
vm::bptr<CellGameDataSystemFileParam> setParam; vm::bptr<CellGameDataSystemFileParam> setParam;
be_t<u32> reserved; be_t<u32> reserved;
}; };
typedef void(CellGameDataStatCallback)(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set);
// cellSysutil: cellHddGame
enum
{
// Return Codes
CELL_HDDGAME_RET_CANCEL = 1,
CELL_HDDGAME_ERROR_CBRESULT = 0x8002ba01,
CELL_HDDGAME_ERROR_ACCESS_ERROR = 0x8002ba02,
CELL_HDDGAME_ERROR_INTERNAL = 0x8002ba03,
CELL_HDDGAME_ERROR_PARAM = 0x8002ba04,
CELL_HDDGAME_ERROR_NOSPACE = 0x8002ba05,
CELL_HDDGAME_ERROR_BROKEN = 0x8002ba06,
CELL_HDDGAME_ERROR_FAILURE = 0x8002ba07,
// Callback Result
CELL_HDDGAME_CBRESULT_OK_CANCEL = 1,
CELL_HDDGAME_CBRESULT_OK = 0,
CELL_HDDGAME_CBRESULT_ERR_NOSPACE = -1,
CELL_HDDGAME_CBRESULT_ERR_BROKEN = -3,
CELL_HDDGAME_CBRESULT_ERR_NODATA = -4,
CELL_HDDGAME_CBRESULT_ERR_INVALID = -5,
// Character Strings
CELL_HDDGAME_INVALIDMSG_MAX = 256,
CELL_HDDGAME_PATH_MAX = 1055,
CELL_HDDGAME_SYSP_TITLE_SIZE = 128,
CELL_HDDGAME_SYSP_TITLEID_SIZE = 10,
CELL_HDDGAME_SYSP_VERSION_SIZE = 6,
CELL_HDDGAME_SYSP_SYSTEMVER_SIZE = 8,
// HDD Directory exists
CELL_HDDGAME_ISNEWDATA_EXIST = 0,
CELL_HDDGAME_ISNEWDATA_NODIR = 1,
// Languages
CELL_HDDGAME_SYSP_LANGUAGE_NUM = 20,
// Stat Get
CELL_HDDGAME_SIZEKB_NOTCALC = -1,
};
struct CellHddGameSystemFileParam
{
char title[CELL_HDDGAME_SYSP_TITLE_SIZE];
char titleLang[CELL_HDDGAME_SYSP_LANGUAGE_NUM][CELL_HDDGAME_SYSP_TITLE_SIZE];
char titleId[CELL_HDDGAME_SYSP_TITLEID_SIZE];
char reserved0[2];
char dataVersion[CELL_HDDGAME_SYSP_VERSION_SIZE];
char reserved1[2];
be_t<u32> attribute;
be_t<u32> parentalLevel;
be_t<u32> resolution;
be_t<u32> soundFormat;
char reserved2[256];
};
struct CellHddGameCBResult
{
be_t<u32> result;
be_t<s32> errNeedSizeKB;
vm::bptr<char> invalidMsg;
vm::bptr<void> reserved;
};
struct CellHddGameStatGet
{
be_t<s32> hddFreeSizeKB;
be_t<u32> isNewData;
char contentInfoPath[CELL_HDDGAME_PATH_MAX];
char hddGamePath[CELL_HDDGAME_PATH_MAX];
char reserved0[2];
be_t<s64> atime;
be_t<s64> mtime;
be_t<s64> ctime;
CellHddGameSystemFileParam getParam;
be_t<s32> sizeKB;
be_t<s32> sysSizeKB;
char reserved1[68];
};
struct CellHddGameStatSet
{
vm::bptr<CellHddGameSystemFileParam> setParam;
vm::bptr<void> reserved;
};
typedef void(CellHddGameStatCallback)(vm::ptr<CellHddGameCBResult> cbResult, vm::ptr<CellHddGameStatGet> get, vm::ptr<CellHddGameStatSet> set);

View file

@ -86,7 +86,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
if (location == CELL_GCM_LOCATION_LOCAL) { if (location == CELL_GCM_LOCATION_LOCAL) {
if (index >= 2048) { if (index >= 2048) {
cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index); cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
return vm::ptr<CellGcmReportData>::make(0); return vm::null;
} }
return vm::ptr<CellGcmReportData>::make((u32)Memory.RSXFBMem.GetStartAddr() + index * 0x10); return vm::ptr<CellGcmReportData>::make((u32)Memory.RSXFBMem.GetStartAddr() + index * 0x10);
} }
@ -94,14 +94,14 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
if (location == CELL_GCM_LOCATION_MAIN) { if (location == CELL_GCM_LOCATION_MAIN) {
if (index >= 1024 * 1024) { if (index >= 1024 * 1024) {
cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index); cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index);
return vm::ptr<CellGcmReportData>::make(0); return vm::null;
} }
// TODO: It seems m_report_main_addr is not initialized // TODO: It seems m_report_main_addr is not initialized
return vm::ptr<CellGcmReportData>::make(Emu.GetGSManager().GetRender().m_report_main_addr + index * 0x10); return vm::ptr<CellGcmReportData>::make(Emu.GetGSManager().GetRender().m_report_main_addr + index * 0x10);
} }
cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong location (%d)", location); cellGcmSys.Error("cellGcmGetReportDataAddressLocation: Wrong location (%d)", location);
return vm::ptr<CellGcmReportData>::make(0); return vm::null;
} }
u64 cellGcmGetTimeStamp(u32 index) u64 cellGcmGetTimeStamp(u32 index)

View file

@ -4,8 +4,11 @@
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern "C"
{
#include "stblib/stb_image.h" #include "stblib/stb_image.h"
#include "stblib/stb_image.c" // (TODO: Should we put this elsewhere?) #include "stblib/stb_image.c"
}
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFileBase.h" #include "Emu/FS/vfsFileBase.h"
@ -15,22 +18,21 @@
extern Module cellGifDec; extern Module cellGifDec;
int cellGifDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam) s32 cellGifDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{ {
UNIMPLEMENTED_FUNC(cellGifDec); UNIMPLEMENTED_FUNC(cellGifDec);
return CELL_OK; return CELL_OK;
} }
int cellGifDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam) s32 cellGifDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam)
{ {
UNIMPLEMENTED_FUNC(cellGifDec); UNIMPLEMENTED_FUNC(cellGifDec);
return CELL_OK; return CELL_OK;
} }
int cellGifDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellGifDecSrc> src, vm::ptr<CellGifDecOpnInfo> openInfo) s32 cellGifDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellGifDecSrc> src, vm::ptr<CellGifDecOpnInfo> openInfo)
{ {
cellGifDec.Warning("cellGifDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", cellGifDec.Warning("cellGifDecOpen(mainHandle=0x%x, subHandle=*0x%x, src=*0x%x, openInfo=*0x%x)", mainHandle, subHandle, src, openInfo);
mainHandle, subHandle.addr(), src.addr(), openInfo.addr());
std::shared_ptr<CellGifDecSubHandle> current_subHandle(new CellGifDecSubHandle); std::shared_ptr<CellGifDecSubHandle> current_subHandle(new CellGifDecSubHandle);
current_subHandle->fd = 0; current_subHandle->fd = 0;
@ -60,14 +62,16 @@ int cellGifDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellGifDecSrc
return CELL_OK; return CELL_OK;
} }
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellGifDecInfo> info) s32 cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellGifDecInfo> info)
{ {
cellGifDec.Warning("cellGifDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", cellGifDec.Warning("cellGifDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info=*0x%x)", mainHandle, subHandle, info);
mainHandle, subHandle, info.addr());
std::shared_ptr<CellGifDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellGifDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_GIFDEC_ERROR_FATAL; return CELL_GIFDEC_ERROR_FATAL;
}
const u32& fd = subHandle_data->fd; const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize; const u64& fileSize = subHandle_data->fileSize;
@ -112,14 +116,16 @@ int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellGifDecInfo>
return CELL_OK; return CELL_OK;
} }
int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellGifDecInParam> inParam, vm::ptr<CellGifDecOutParam> outParam) s32 cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellGifDecInParam> inParam, vm::ptr<CellGifDecOutParam> outParam)
{ {
cellGifDec.Warning("cellGifDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", cellGifDec.Warning("cellGifDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam=*0x%x, outParam=*0x%x)", mainHandle, subHandle, inParam, outParam);
mainHandle, subHandle, inParam.addr(), outParam.addr());
std::shared_ptr<CellGifDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellGifDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_GIFDEC_ERROR_FATAL; return CELL_GIFDEC_ERROR_FATAL;
}
CellGifDecInfo& current_info = subHandle_data->info; CellGifDecInfo& current_info = subHandle_data->info;
CellGifDecOutParam& current_outParam = subHandle_data->outParam; CellGifDecOutParam& current_outParam = subHandle_data->outParam;
@ -142,16 +148,18 @@ int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellGifD
return CELL_OK; return CELL_OK;
} }
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellGifDecDataCtrlParam> dataCtrlParam, vm::ptr<CellGifDecDataOutInfo> dataOutInfo) s32 cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellGifDecDataCtrlParam> dataCtrlParam, vm::ptr<CellGifDecDataOutInfo> dataOutInfo)
{ {
cellGifDec.Warning("cellGifDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", cellGifDec.Warning("cellGifDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x)", mainHandle, subHandle, data, dataCtrlParam, dataOutInfo);
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr());
dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP; dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP;
std::shared_ptr<CellGifDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellGifDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_GIFDEC_ERROR_FATAL; return CELL_GIFDEC_ERROR_FATAL;
}
const u32& fd = subHandle_data->fd; const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize; const u64& fileSize = subHandle_data->fileSize;
@ -261,14 +269,16 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
return CELL_OK; return CELL_OK;
} }
int cellGifDecClose(u32 mainHandle, u32 subHandle) s32 cellGifDecClose(u32 mainHandle, u32 subHandle)
{ {
cellGifDec.Warning("cellGifDecClose(mainHandle=0x%x, subHandle=0x%x)", cellGifDec.Warning("cellGifDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle, subHandle);
mainHandle, subHandle);
std::shared_ptr<CellGifDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellGifDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_GIFDEC_ERROR_FATAL; return CELL_GIFDEC_ERROR_FATAL;
}
Emu.GetIdManager().RemoveID<fs_file_t>(subHandle_data->fd); Emu.GetIdManager().RemoveID<fs_file_t>(subHandle_data->fd);
Emu.GetIdManager().RemoveID<CellGifDecSubHandle>(subHandle); Emu.GetIdManager().RemoveID<CellGifDecSubHandle>(subHandle);
@ -276,7 +286,7 @@ int cellGifDecClose(u32 mainHandle, u32 subHandle)
return CELL_OK; return CELL_OK;
} }
int cellGifDecDestroy(u32 mainHandle) s32 cellGifDecDestroy(u32 mainHandle)
{ {
UNIMPLEMENTED_FUNC(cellGifDec); UNIMPLEMENTED_FUNC(cellGifDec);
return CELL_OK; return CELL_OK;

View file

@ -4,7 +4,10 @@
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern "C"
{
#include "stblib/stb_image.h" #include "stblib/stb_image.h"
}
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFileBase.h" #include "Emu/FS/vfsFileBase.h"
@ -14,28 +17,27 @@
extern Module cellJpgDec; extern Module cellJpgDec;
int cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam) s32 cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{ {
UNIMPLEMENTED_FUNC(cellJpgDec); UNIMPLEMENTED_FUNC(cellJpgDec);
return CELL_OK; return CELL_OK;
} }
int cellJpgDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam) s32 cellJpgDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam)
{ {
UNIMPLEMENTED_FUNC(cellJpgDec); UNIMPLEMENTED_FUNC(cellJpgDec);
return CELL_OK; return CELL_OK;
} }
int cellJpgDecDestroy(u32 mainHandle) s32 cellJpgDecDestroy(u32 mainHandle)
{ {
UNIMPLEMENTED_FUNC(cellJpgDec); UNIMPLEMENTED_FUNC(cellJpgDec);
return CELL_OK; return CELL_OK;
} }
int cellJpgDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellJpgDecSrc> src, vm::ptr<CellJpgDecOpnInfo> openInfo) s32 cellJpgDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellJpgDecSrc> src, vm::ptr<CellJpgDecOpnInfo> openInfo)
{ {
cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=*0x%x, src=*0x%x, openInfo=*0x%x)", mainHandle, subHandle, src, openInfo);
mainHandle, subHandle.addr(), src.addr(), openInfo.addr());
std::shared_ptr<CellJpgDecSubHandle> current_subHandle(new CellJpgDecSubHandle); std::shared_ptr<CellJpgDecSubHandle> current_subHandle(new CellJpgDecSubHandle);
@ -66,14 +68,16 @@ int cellJpgDecOpen(u32 mainHandle, vm::ptr<u32> subHandle, vm::ptr<CellJpgDecSrc
return CELL_OK; return CELL_OK;
} }
int cellJpgDecClose(u32 mainHandle, u32 subHandle) s32 cellJpgDecClose(u32 mainHandle, u32 subHandle)
{ {
cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x)", cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x)", mainHandle, subHandle);
mainHandle, subHandle);
std::shared_ptr<CellJpgDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellJpgDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_JPGDEC_ERROR_FATAL; return CELL_JPGDEC_ERROR_FATAL;
}
Emu.GetIdManager().RemoveID<fs_file_t>(subHandle_data->fd); Emu.GetIdManager().RemoveID<fs_file_t>(subHandle_data->fd);
Emu.GetIdManager().RemoveID<CellJpgDecSubHandle>(subHandle); Emu.GetIdManager().RemoveID<CellJpgDecSubHandle>(subHandle);
@ -81,13 +85,16 @@ int cellJpgDecClose(u32 mainHandle, u32 subHandle)
return CELL_OK; return CELL_OK;
} }
int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDecInfo> info) s32 cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDecInfo> info)
{ {
cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.addr()); cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info=*0x%x)", mainHandle, subHandle, info);
std::shared_ptr<CellJpgDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellJpgDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_JPGDEC_ERROR_FATAL; return CELL_JPGDEC_ERROR_FATAL;
}
const u32& fd = subHandle_data->fd; const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize; const u64& fileSize = subHandle_data->fileSize;
@ -150,15 +157,18 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDecInfo>
return CELL_OK; return CELL_OK;
} }
int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellJpgDecDataCtrlParam> dataCtrlParam, vm::ptr<CellJpgDecDataOutInfo> dataOutInfo) s32 cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::ptr<const CellJpgDecDataCtrlParam> dataCtrlParam, vm::ptr<CellJpgDecDataOutInfo> dataOutInfo)
{ {
cellJpgDec.Log("cellJpgDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", cellJpgDec.Log("cellJpgDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x)", mainHandle, subHandle, data, dataCtrlParam, dataOutInfo);
mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr());
dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP; dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP;
std::shared_ptr<CellJpgDecSubHandle> subHandle_data;
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) const auto subHandle_data = Emu.GetIdManager().GetIDData<CellJpgDecSubHandle>(subHandle);
if (!subHandle_data)
{
return CELL_JPGDEC_ERROR_FATAL; return CELL_JPGDEC_ERROR_FATAL;
}
const u32& fd = subHandle_data->fd; const u32& fd = subHandle_data->fd;
const u64& fileSize = subHandle_data->fileSize; const u64& fileSize = subHandle_data->fileSize;
@ -283,14 +293,16 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr<u8> data, vm::pt
return CELL_OK; return CELL_OK;
} }
int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellJpgDecInParam> inParam, vm::ptr<CellJpgDecOutParam> outParam) s32 cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr<const CellJpgDecInParam> inParam, vm::ptr<CellJpgDecOutParam> outParam)
{ {
cellJpgDec.Log("cellJpgDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", cellJpgDec.Log("cellJpgDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam=*0x%x, outParam=*0x%x)", mainHandle, subHandle, inParam, outParam);
mainHandle, subHandle, inParam.addr(), outParam.addr());
std::shared_ptr<CellJpgDecSubHandle> subHandle_data; const auto subHandle_data = Emu.GetIdManager().GetIDData<CellJpgDecSubHandle>(subHandle);
if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data))
if (!subHandle_data)
{
return CELL_JPGDEC_ERROR_FATAL; return CELL_JPGDEC_ERROR_FATAL;
}
CellJpgDecInfo& current_info = subHandle_data->info; CellJpgDecInfo& current_info = subHandle_data->info;
CellJpgDecOutParam& current_outParam = subHandle_data->outParam; CellJpgDecOutParam& current_outParam = subHandle_data->outParam;

View file

@ -5,52 +5,28 @@
#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/Callback.h"
#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/SysCalls/CB_FUNC.h"
#include "Utilities/Log.h"
#include "Utilities/rMsgBox.h"
#include "Emu/SysCalls/lv2/sys_time.h" #include "Emu/SysCalls/lv2/sys_time.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellMsgDialog.h" #include "cellMsgDialog.h"
extern Module cellSysutil; extern Module cellSysutil;
enum MsgDialogState std::unique_ptr<MsgDialogInstance> g_msg_dialog;
MsgDialogInstance::MsgDialogInstance()
: state(msgDialogNone)
{ {
msgDialogNone,
msgDialogOpen,
msgDialogClose,
msgDialogAbort,
};
std::atomic<MsgDialogState> g_msg_dialog_state(msgDialogNone);
u64 g_msg_dialog_status;
u64 g_msg_dialog_wait_until;
u32 g_msg_dialog_progress_bar_count;
MsgDialogCreateCb MsgDialogCreate = nullptr;
MsgDialogDestroyCb MsgDialogDestroy = nullptr;
MsgDialogProgressBarSetMsgCb MsgDialogProgressBarSetMsg = nullptr;
MsgDialogProgressBarResetCb MsgDialogProgressBarReset = nullptr;
MsgDialogProgressBarIncCb MsgDialogProgressBarInc = nullptr;
void SetMsgDialogCallbacks(MsgDialogCreateCb ccb, MsgDialogDestroyCb dcb, MsgDialogProgressBarSetMsgCb pbscb, MsgDialogProgressBarResetCb pbrcb, MsgDialogProgressBarIncCb pbicb)
{
MsgDialogCreate = ccb;
MsgDialogDestroy = dcb;
MsgDialogProgressBarSetMsg = pbscb;
MsgDialogProgressBarReset = pbrcb;
MsgDialogProgressBarInc = pbicb;
} }
void MsgDialogClose() void MsgDialogInstance::Close()
{ {
g_msg_dialog_state = msgDialogClose; state = msgDialogClose;
g_msg_dialog_wait_until = get_system_time(); wait_until = get_system_time();
} }
s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam) s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam)
{ {
cellSysutil.Warning("cellMsgDialogOpen2(type=0x%x, msgString_addr=0x%x, callback_addr=0x%x, userData=0x%x, extParam=0x%x)", cellSysutil.Warning("cellMsgDialogOpen2(type=0x%x, msgString=*0x%x, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", type, msgString, callback, userData, extParam);
type, msgString.addr(), callback.addr(), userData, extParam);
if (!msgString || strlen(msgString.get_ptr()) >= 0x200 || type & -0x33f8) if (!msgString || strlen(msgString.get_ptr()) >= 0x200 || type & -0x33f8)
{ {
@ -107,18 +83,24 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
} }
MsgDialogState old = msgDialogNone; MsgDialogState old = msgDialogNone;
if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogOpen)) if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogOpen))
{ {
return CELL_SYSUTIL_ERROR_BUSY; return CELL_SYSUTIL_ERROR_BUSY;
} }
g_msg_dialog_wait_until = get_system_time() + 31536000000000ull; // some big value g_msg_dialog->wait_until = get_system_time() + 31536000000000ull; // some big value
switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR) switch (type & CELL_MSGDIALOG_TYPE_PROGRESSBAR)
{ {
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: g_msg_dialog_progress_bar_count = 2; break; case CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE: g_msg_dialog->progress_bar_count = 2; break;
case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: g_msg_dialog_progress_bar_count = 1; break; case CELL_MSGDIALOG_TYPE_PROGRESSBAR_SINGLE: g_msg_dialog->progress_bar_count = 1; break;
default: g_msg_dialog_progress_bar_count = 0; break; default: g_msg_dialog->progress_bar_count = 0; break;
}
switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO
{
case CELL_MSGDIALOG_TYPE_SE_MUTE_OFF: break;
case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break;
} }
std::string msg = msgString.get_ptr(); std::string msg = msgString.get_ptr();
@ -127,24 +109,18 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
{ {
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE) switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
{ {
case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: LOG_WARNING(HLE, "%s", msg.c_str()); break; case CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL: cellSysutil.Warning("%s", msg); break;
case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: LOG_ERROR(HLE, "%s", msg.c_str()); break; case CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR: cellSysutil.Error("%s", msg); break;
} }
switch (type & CELL_MSGDIALOG_TYPE_SE_MUTE) // TODO g_msg_dialog->status = CELL_MSGDIALOG_BUTTON_NONE;
{
case CELL_MSGDIALOG_TYPE_SE_MUTE_OFF: break;
case CELL_MSGDIALOG_TYPE_SE_MUTE_ON: break;
}
g_msg_dialog_status = CELL_MSGDIALOG_BUTTON_NONE;
volatile bool m_signal = false; volatile bool m_signal = false;
CallAfter([type, msg, &m_signal]() CallAfter([type, msg, &m_signal]()
{ {
if (Emu.IsStopped()) return; if (Emu.IsStopped()) return;
MsgDialogCreate(type, msg.c_str(), g_msg_dialog_status); g_msg_dialog->Create(type, msg);
m_signal = true; m_signal = true;
}); });
@ -159,20 +135,21 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }
while (g_msg_dialog_state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog_wait_until) < 0) while (g_msg_dialog->state == msgDialogOpen || (s64)(get_system_time() - g_msg_dialog->wait_until) < 0)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped())
{ {
g_msg_dialog_state = msgDialogAbort; g_msg_dialog->state = msgDialogAbort;
break; break;
} }
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
} }
if (callback && (g_msg_dialog_state != msgDialogAbort)) if (callback && (g_msg_dialog->state != msgDialogAbort))
{ {
const s32 status = (s32)g_msg_dialog_status; const s32 status = g_msg_dialog->status;
Emu.GetCallbackManager().Register([callback, userData, status](PPUThread& PPU) -> s32
Emu.GetCallbackManager().Register([=](PPUThread& PPU) -> s32
{ {
callback(PPU, status, userData); callback(PPU, status, userData);
return CELL_OK; return CELL_OK;
@ -181,116 +158,93 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
CallAfter([]() CallAfter([]()
{ {
MsgDialogDestroy(); g_msg_dialog->Destroy();
g_msg_dialog->state = msgDialogNone;
g_msg_dialog_state = msgDialogNone;
}); });
}); });
return CELL_OK; return CELL_OK;
} }
s32 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam) s32 cellMsgDialogOpenErrorCode(PPUThread& CPU, u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam)
{ {
cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=0x%x, extParam=%d)", cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback=*0x%x, userData=*0x%x, extParam=*0x%x)", errorCode, callback, userData, extParam);
errorCode, callback.addr(), userData, extParam);
std::string error;
std::string errorMessage;
switch (errorCode) switch (errorCode)
{ {
// Generic errors case 0x80010001: error = "The resource is temporarily unavailable."; break;
case 0x80010001: errorMessage = "The resource is temporarily unavailable."; break; case 0x80010002: error = "Invalid argument or flag."; break;
case 0x80010002: errorMessage = "Invalid argument or flag."; break; case 0x80010003: error = "The feature is not yet implemented."; break;
case 0x80010003: errorMessage = "The feature is not yet implemented."; break; case 0x80010004: error = "Memory allocation failed."; break;
case 0x80010004: errorMessage = "Memory allocation failed."; break; case 0x80010005: error = "The resource with the specified identifier does not exist."; break;
case 0x80010005: errorMessage = "The resource with the specified identifier does not exist."; break; case 0x80010006: error = "The file does not exist."; break;
case 0x80010006: errorMessage = "The file does not exist."; break; case 0x80010007: error = "The file is in unrecognized format / The file is not a valid ELF file."; break;
case 0x80010007: errorMessage = "The file is in unrecognized format / The file is not a valid ELF file."; break; case 0x80010008: error = "Resource deadlock is avoided."; break;
case 0x80010008: errorMessage = "Resource deadlock is avoided."; break; case 0x80010009: error = "Operation not permitted."; break;
case 0x80010009: errorMessage = "Operation not permitted."; break; case 0x8001000A: error = "The device or resource is busy."; break;
case 0x8001000A: errorMessage = "The device or resource is busy."; break; case 0x8001000B: error = "The operation is timed out."; break;
case 0x8001000B: errorMessage = "The operation is timed out."; break; case 0x8001000C: error = "The operation is aborted."; break;
case 0x8001000C: errorMessage = "The operation is aborted."; break; case 0x8001000D: error = "Invalid memory access."; break;
case 0x8001000D: errorMessage = "Invalid memory access."; break; case 0x8001000F: error = "State of the target thread is invalid."; break;
case 0x8001000F: errorMessage = "State of the target thread is invalid."; break; case 0x80010010: error = "Alignment is invalid."; break;
case 0x80010010: errorMessage = "Alignment is invalid."; break; case 0x80010011: error = "Shortage of the kernel resources."; break;
case 0x80010011: errorMessage = "Shortage of the kernel resources."; break; case 0x80010012: error = "The file is a directory."; break;
case 0x80010012: errorMessage = "The file is a directory."; break; case 0x80010013: error = "Operation cancelled."; break;
case 0x80010013: errorMessage = "Operation cancelled."; break; case 0x80010014: error = "Entry already exists."; break;
case 0x80010014: errorMessage = "Entry already exists."; break; case 0x80010015: error = "Port is already connected."; break;
case 0x80010015: errorMessage = "Port is already connected."; break; case 0x80010016: error = "Port is not connected."; break;
case 0x80010016: errorMessage = "Port is not connected."; break; case 0x80010017: error = "Failure in authorizing SELF. Program authentication fail."; break;
case 0x80010017: errorMessage = "Failure in authorizing SELF. Program authentication fail."; break; case 0x80010018: error = "The file is not MSELF."; break;
case 0x80010018: errorMessage = "The file is not MSELF."; break; case 0x80010019: error = "System version error."; break;
case 0x80010019: errorMessage = "System version error."; break; case 0x8001001A: error = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break;
case 0x8001001A: errorMessage = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break; case 0x8001001B: error = "Math domain violation."; break;
case 0x8001001B: errorMessage = "Math domain violation."; break; case 0x8001001C: error = "Math range violation."; break;
case 0x8001001C: errorMessage = "Math range violation."; break; case 0x8001001D: error = "Illegal multi-byte sequence in input."; break;
case 0x8001001D: errorMessage = "Illegal multi-byte sequence in input."; break; case 0x8001001E: error = "File position error."; break;
case 0x8001001E: errorMessage = "File position error."; break; case 0x8001001F: error = "Syscall was interrupted."; break;
case 0x8001001F: errorMessage = "Syscall was interrupted."; break; case 0x80010020: error = "File too large."; break;
case 0x80010020: errorMessage = "File too large."; break; case 0x80010021: error = "Too many links."; break;
case 0x80010021: errorMessage = "Too many links."; break; case 0x80010022: error = "File table overflow."; break;
case 0x80010022: errorMessage = "File table overflow."; break; case 0x80010023: error = "No space left on device."; break;
case 0x80010023: errorMessage = "No space left on device."; break; case 0x80010024: error = "Not a TTY."; break;
case 0x80010024: errorMessage = "Not a TTY."; break; case 0x80010025: error = "Broken pipe."; break;
case 0x80010025: errorMessage = "Broken pipe."; break; case 0x80010026: error = "Read-only filesystem."; break;
case 0x80010026: errorMessage = "Read-only filesystem."; break; case 0x80010027: error = "Illegal seek."; break;
case 0x80010027: errorMessage = "Illegal seek."; break; case 0x80010028: error = "Arg list too long."; break;
case 0x80010028: errorMessage = "Arg list too long."; break; case 0x80010029: error = "Access violation."; break;
case 0x80010029: errorMessage = "Access violation."; break; case 0x8001002A: error = "Invalid file descriptor."; break;
case 0x8001002A: errorMessage = "Invalid file descriptor."; break; case 0x8001002B: error = "Filesystem mounting failed."; break;
case 0x8001002B: errorMessage = "Filesystem mounting failed."; break; case 0x8001002C: error = "Too many files open."; break;
case 0x8001002C: errorMessage = "Too many files open."; break; case 0x8001002D: error = "No device."; break;
case 0x8001002D: errorMessage = "No device."; break; case 0x8001002E: error = "Not a directory."; break;
case 0x8001002E: errorMessage = "Not a directory."; break; case 0x8001002F: error = "No such device or IO."; break;
case 0x8001002F: errorMessage = "No such device or IO."; break; case 0x80010030: error = "Cross-device link error."; break;
case 0x80010030: errorMessage = "Cross-device link error."; break; case 0x80010031: error = "Bad Message."; break;
case 0x80010031: errorMessage = "Bad Message."; break; case 0x80010032: error = "In progress."; break;
case 0x80010032: errorMessage = "In progress."; break; case 0x80010033: error = "Message size error."; break;
case 0x80010033: errorMessage = "Message size error."; break; case 0x80010034: error = "Name too long."; break;
case 0x80010034: errorMessage = "Name too long."; break; case 0x80010035: error = "No lock."; break;
case 0x80010035: errorMessage = "No lock."; break; case 0x80010036: error = "Not empty."; break;
case 0x80010036: errorMessage = "Not empty."; break; case 0x80010037: error = "Not supported."; break;
case 0x80010037: errorMessage = "Not supported."; break; case 0x80010038: error = "File-system specific error."; break;
case 0x80010038: errorMessage = "File-system specific error."; break; case 0x80010039: error = "Overflow occured."; break;
case 0x80010039: errorMessage = "Overflow occured."; break; case 0x8001003A: error = "Filesystem not mounted."; break;
case 0x8001003A: errorMessage = "Filesystem not mounted."; break; case 0x8001003B: error = "Not SData."; break;
case 0x8001003B: errorMessage = "Not SData."; break; case 0x8001003C: error = "Incorrect version in sys_load_param."; break;
case 0x8001003C: errorMessage = "Incorrect version in sys_load_param."; break; case 0x8001003D: error = "Pointer is null."; break;
case 0x8001003D: errorMessage = "Pointer is null."; break; case 0x8001003E: error = "Pointer is null."; break;
case 0x8001003E: errorMessage = "Pointer is null."; break; default: error = "An error has occurred."; break;
default: errorMessage = "An error has occurred."; break;
} }
char errorCodeHex[12]; error.append(fmt::format("\n(%08x)", errorCode));
#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE
sprintf_s(errorCodeHex, "\n(%08x)", errorCode);
#else
sprintf(errorCodeHex, "\n(%08x)", errorCode);
#endif
errorMessage.append(errorCodeHex);
u64 status; vm::stackvar<char> message(CPU, error.size() + 1);
int res = rMessageBox(errorMessage, "Error", rICON_ERROR | rOK);
switch (res)
{
case rOK: status = CELL_MSGDIALOG_BUTTON_OK; break;
default:
if (res)
{
status = CELL_MSGDIALOG_BUTTON_INVALID;
break;
}
status = CELL_MSGDIALOG_BUTTON_NONE; memcpy(message.get_ptr(), error.c_str(), message.size());
break;
}
if (callback) return cellMsgDialogOpen2(CELL_MSGDIALOG_DIALOG_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, message, callback, userData, extParam);
callback((s32)status, userData);
return CELL_OK;
} }
s32 cellMsgDialogClose(float delay) s32 cellMsgDialogClose(float delay)
@ -298,7 +252,8 @@ s32 cellMsgDialogClose(float delay)
cellSysutil.Warning("cellMsgDialogClose(delay=%f)", delay); cellSysutil.Warning("cellMsgDialogClose(delay=%f)", delay);
MsgDialogState old = msgDialogOpen; MsgDialogState old = msgDialogOpen;
if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogClose))
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogClose))
{ {
if (old == msgDialogNone) if (old == msgDialogNone)
{ {
@ -310,8 +265,8 @@ s32 cellMsgDialogClose(float delay)
} }
} }
if (delay < 0.0f) delay = 0.0f; g_msg_dialog->wait_until = get_system_time() + static_cast<u64>(std::max<float>(delay, 0.0f) * 1000);
g_msg_dialog_wait_until = get_system_time() + (u64)(delay * 1000);
return CELL_OK; return CELL_OK;
} }
@ -320,7 +275,8 @@ s32 cellMsgDialogAbort()
cellSysutil.Warning("cellMsgDialogAbort()"); cellSysutil.Warning("cellMsgDialogAbort()");
MsgDialogState old = msgDialogOpen; MsgDialogState old = msgDialogOpen;
if (!g_msg_dialog_state.compare_exchange_strong(old, msgDialogAbort))
if (!g_msg_dialog->state.compare_exchange_strong(old, msgDialogAbort))
{ {
if (old == msgDialogNone) if (old == msgDialogNone)
{ {
@ -332,31 +288,27 @@ s32 cellMsgDialogAbort()
} }
} }
g_msg_dialog_wait_until = get_system_time(); g_msg_dialog->wait_until = get_system_time();
return CELL_OK; return CELL_OK;
} }
s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString) s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString)
{ {
cellSysutil.Warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString_addr=0x%x ['%s'])", cellSysutil.Warning("cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString=*0x%x)", progressBarIndex, msgString);
progressBarIndex, msgString.addr(), msgString.get_ptr());
if (g_msg_dialog_state != msgDialogOpen) if (g_msg_dialog->state != msgDialogOpen)
{ {
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
} }
if (progressBarIndex >= g_msg_dialog_progress_bar_count) if (progressBarIndex >= g_msg_dialog->progress_bar_count)
{ {
return CELL_MSGDIALOG_ERROR_PARAM; return CELL_MSGDIALOG_ERROR_PARAM;
} }
std::string text = msgString.get_ptr(); g_msg_dialog->ProgressBarSetMsg(progressBarIndex, msgString.get_ptr());
CallAfter([text, progressBarIndex]()
{
MsgDialogProgressBarSetMsg(progressBarIndex, text.c_str());
});
return CELL_OK; return CELL_OK;
} }
@ -364,20 +316,18 @@ s32 cellMsgDialogProgressBarReset(u32 progressBarIndex)
{ {
cellSysutil.Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex); cellSysutil.Warning("cellMsgDialogProgressBarReset(progressBarIndex=%d)", progressBarIndex);
if (g_msg_dialog_state != msgDialogOpen) if (g_msg_dialog->state != msgDialogOpen)
{ {
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
} }
if (progressBarIndex >= g_msg_dialog_progress_bar_count) if (progressBarIndex >= g_msg_dialog->progress_bar_count)
{ {
return CELL_MSGDIALOG_ERROR_PARAM; return CELL_MSGDIALOG_ERROR_PARAM;
} }
CallAfter([=]() g_msg_dialog->ProgressBarReset(progressBarIndex);
{
MsgDialogProgressBarReset(progressBarIndex);
});
return CELL_OK; return CELL_OK;
} }
@ -385,19 +335,28 @@ s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta)
{ {
cellSysutil.Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta); cellSysutil.Warning("cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d)", progressBarIndex, delta);
if (g_msg_dialog_state != msgDialogOpen) if (g_msg_dialog->state != msgDialogOpen)
{ {
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
} }
if (progressBarIndex >= g_msg_dialog_progress_bar_count) if (progressBarIndex >= g_msg_dialog->progress_bar_count)
{ {
return CELL_MSGDIALOG_ERROR_PARAM; return CELL_MSGDIALOG_ERROR_PARAM;
} }
CallAfter([=]() g_msg_dialog->ProgressBarInc(progressBarIndex, delta);
{
MsgDialogProgressBarInc(progressBarIndex, delta);
});
return CELL_OK; return CELL_OK;
} }
void cellSysutil_MsgDialog_init()
{
REG_FUNC(cellSysutil, cellMsgDialogOpen2);
REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarSetMsg);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarReset);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarInc);
REG_FUNC(cellSysutil, cellMsgDialogClose);
REG_FUNC(cellSysutil, cellMsgDialogAbort);
}

View file

@ -6,7 +6,7 @@ enum
CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED = 0x8002b302, CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED = 0x8002b302,
}; };
enum CellMsgDialogType enum CellMsgDialogType : u32
{ {
CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000, CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000,
CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001, CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001,
@ -16,28 +16,28 @@ enum CellMsgDialogType
CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_SE_TYPE = 0x1, CELL_MSGDIALOG_TYPE_SE_TYPE = 0x1,
CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR = 0 << 0, CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR = 0 << 0,
CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL = 1 << 0, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL = 1 << 0,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_SE_MUTE = 0x2, CELL_MSGDIALOG_TYPE_SE_MUTE = 0x2,
CELL_MSGDIALOG_TYPE_SE_MUTE_OFF = 0 << 1, CELL_MSGDIALOG_TYPE_SE_MUTE_OFF = 0 << 1,
CELL_MSGDIALOG_TYPE_SE_MUTE_ON = 1 << 1, CELL_MSGDIALOG_TYPE_SE_MUTE_ON = 1 << 1,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_BG = 0x4, CELL_MSGDIALOG_TYPE_BG = 0x4,
CELL_MSGDIALOG_TYPE_BG_VISIBLE = 0 << 2, CELL_MSGDIALOG_TYPE_BG_VISIBLE = 0 << 2,
CELL_MSGDIALOG_TYPE_BG_INVISIBLE = 1 << 2, CELL_MSGDIALOG_TYPE_BG_INVISIBLE = 1 << 2,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_BUTTON_TYPE = 0x70, CELL_MSGDIALOG_TYPE_BUTTON_TYPE = 0x70,
CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE = 0 << 4, CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE = 0 << 4,
@ -45,14 +45,14 @@ enum
CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK = 2 << 4, CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK = 2 << 4,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL = 0x80, CELL_MSGDIALOG_TYPE_DISABLE_CANCEL = 0x80,
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF = 0 << 7, CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF = 0 << 7,
CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_ON = 1 << 7, CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_ON = 1 << 7,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR = 0x300, CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR = 0x300,
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NONE = 0 << 8, CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_NONE = 0 << 8,
@ -61,7 +61,7 @@ enum
CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_OK = 0 << 8, CELL_MSGDIALOG_TYPE_DEFAULT_CURSOR_OK = 0 << 8,
}; };
enum enum : u32
{ {
CELL_MSGDIALOG_TYPE_PROGRESSBAR = 0x3000, CELL_MSGDIALOG_TYPE_PROGRESSBAR = 0x3000,
CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE = 0 << 12, CELL_MSGDIALOG_TYPE_PROGRESSBAR_NONE = 0 << 12,
@ -69,7 +69,8 @@ enum
CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE = 2 << 12, CELL_MSGDIALOG_TYPE_PROGRESSBAR_DOUBLE = 2 << 12,
}; };
enum // MsgDialog Button Type
enum : s32
{ {
CELL_MSGDIALOG_BUTTON_NONE = -1, CELL_MSGDIALOG_BUTTON_NONE = -1,
CELL_MSGDIALOG_BUTTON_INVALID = 0, CELL_MSGDIALOG_BUTTON_INVALID = 0,
@ -79,22 +80,32 @@ enum
CELL_MSGDIALOG_BUTTON_ESCAPE = 3, CELL_MSGDIALOG_BUTTON_ESCAPE = 3,
}; };
typedef void(CellMsgDialogCallback)(s32 buttonType, u32 userData); typedef void(CellMsgDialogCallback)(s32 buttonType, vm::ptr<void> userData);
s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam); enum MsgDialogState
s32 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallback> callback, u32 userData, u32 extParam); {
msgDialogNone,
msgDialogOpen,
msgDialogClose,
msgDialogAbort,
};
s32 cellMsgDialogProgressBarSetMsg(u32 progressBarIndex, vm::ptr<const char> msgString); struct MsgDialogInstance
s32 cellMsgDialogProgressBarReset(u32 progressBarIndex); {
s32 cellMsgDialogProgressBarInc(u32 progressBarIndex, u32 delta); std::atomic<MsgDialogState> state;
s32 cellMsgDialogClose(float delay);
s32 cellMsgDialogAbort();
typedef void(*MsgDialogCreateCb)(u32 type, const char* msg, u64& status); s32 status = 0;
typedef void(*MsgDialogDestroyCb)(); u64 wait_until = 0;
typedef void(*MsgDialogProgressBarSetMsgCb)(u32 progressBarIndex, const char* msg); u32 progress_bar_count = 0;
typedef void(*MsgDialogProgressBarResetCb)(u32 progressBarIndex);
typedef void(*MsgDialogProgressBarIncCb)(u32 progressBarIndex, u32 delta);
void SetMsgDialogCallbacks(MsgDialogCreateCb ccb, MsgDialogDestroyCb dcb, MsgDialogProgressBarSetMsgCb pbscb, MsgDialogProgressBarResetCb pbrcb, MsgDialogProgressBarIncCb pbicb); MsgDialogInstance();
void MsgDialogClose(); virtual ~MsgDialogInstance() = default;
virtual void Close();
virtual void Create(u32 type, std::string msg) = 0;
virtual void Destroy() = 0;
virtual void ProgressBarSetMsg(u32 progressBarIndex, std::string msg) = 0;
virtual void ProgressBarReset(u32 progressBarIndex) = 0;
virtual void ProgressBarInc(u32 progressBarIndex, u32 delta) = 0;
};

View file

@ -4,7 +4,10 @@
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Modules.h"
extern "C"
{
#include "stblib/stb_image.h" #include "stblib/stb_image.h"
}
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Emu/FS/vfsFileBase.h" #include "Emu/FS/vfsFileBase.h"
@ -17,7 +20,7 @@ extern Module cellPngDec;
s32 pngDecCreate( s32 pngDecCreate(
vm::ptr<u32> mainHandle, vm::ptr<u32> mainHandle,
vm::ptr<const CellPngDecThreadInParam> param, vm::ptr<const CellPngDecThreadInParam> param,
vm::ptr<const CellPngDecExtThreadInParam> ext = vm::ptr<const CellPngDecExtThreadInParam>::make(0)) vm::ptr<const CellPngDecExtThreadInParam> ext = vm::null)
{ {
// alloc memory (should probably use param->cbCtrlMallocFunc) // alloc memory (should probably use param->cbCtrlMallocFunc)
auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128)); auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128));
@ -58,8 +61,8 @@ s32 pngDecOpen(
vm::ptr<u32> subHandle, vm::ptr<u32> subHandle,
vm::ptr<const CellPngDecSrc> src, vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo, vm::ptr<CellPngDecOpnInfo> openInfo,
vm::ptr<const CellPngDecCbCtrlStrm> cb = vm::ptr<const CellPngDecCbCtrlStrm>::make(0), vm::ptr<const CellPngDecCbCtrlStrm> cb = vm::null,
vm::ptr<const CellPngDecOpnParam> param = vm::ptr<const CellPngDecOpnParam>::make(0)) vm::ptr<const CellPngDecOpnParam> param = vm::null)
{ {
// alloc memory (should probably use dec->malloc) // alloc memory (should probably use dec->malloc)
auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128)); auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128));
@ -125,7 +128,7 @@ s32 pngDecClose(CellPngDecSubHandle stream)
s32 pngReadHeader( s32 pngReadHeader(
CellPngDecSubHandle stream, CellPngDecSubHandle stream,
vm::ptr<CellPngDecInfo> info, vm::ptr<CellPngDecInfo> info,
vm::ptr<CellPngDecExtInfo> extInfo = vm::ptr<CellPngDecExtInfo>::make(0)) vm::ptr<CellPngDecExtInfo> extInfo = vm::null)
{ {
CellPngDecInfo& current_info = stream->info; CellPngDecInfo& current_info = stream->info;
@ -191,8 +194,8 @@ s32 pngDecSetParameter(
CellPngDecSubHandle stream, CellPngDecSubHandle stream,
vm::ptr<const CellPngDecInParam> inParam, vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam, vm::ptr<CellPngDecOutParam> outParam,
vm::ptr<const CellPngDecExtInParam> extInParam = vm::ptr<const CellPngDecExtInParam>::make(0), vm::ptr<const CellPngDecExtInParam> extInParam = vm::null,
vm::ptr<CellPngDecExtOutParam> extOutParam = vm::ptr<CellPngDecExtOutParam>::make(0)) vm::ptr<CellPngDecExtOutParam> extOutParam = vm::null)
{ {
CellPngDecInfo& current_info = stream->info; CellPngDecInfo& current_info = stream->info;
CellPngDecOutParam& current_outParam = stream->outParam; CellPngDecOutParam& current_outParam = stream->outParam;
@ -237,8 +240,8 @@ s32 pngDecodeData(
vm::ptr<u8> data, vm::ptr<u8> data,
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam, vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo, vm::ptr<CellPngDecDataOutInfo> dataOutInfo,
vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp = vm::ptr<const CellPngDecCbCtrlDisp>::make(0), vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp = vm::null,
vm::ptr<CellPngDecDispParam> dispParam = vm::ptr<CellPngDecDispParam>::make(0)) vm::ptr<CellPngDecDispParam> dispParam = vm::null)
{ {
dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP;
@ -365,8 +368,7 @@ s32 pngDecodeData(
s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInParam> threadInParam, vm::ptr<CellPngDecThreadOutParam> threadOutParam) s32 cellPngDecCreate(vm::ptr<u32> mainHandle, vm::ptr<const CellPngDecThreadInParam> threadInParam, vm::ptr<CellPngDecThreadOutParam> threadOutParam)
{ {
cellPngDec.Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", cellPngDec.Warning("cellPngDecCreate(mainHandle=**0x%x, threadInParam=*0x%x, threadOutParam=*0x%x)", mainHandle, threadInParam, threadOutParam);
mainHandle.addr(), threadInParam.addr(), threadOutParam.addr());
// create decoder // create decoder
if (auto res = pngDecCreate(mainHandle, threadInParam)) return res; if (auto res = pngDecCreate(mainHandle, threadInParam)) return res;
@ -384,8 +386,8 @@ s32 cellPngDecExtCreate(
vm::ptr<const CellPngDecExtThreadInParam> extThreadInParam, vm::ptr<const CellPngDecExtThreadInParam> extThreadInParam,
vm::ptr<CellPngDecExtThreadOutParam> extThreadOutParam) vm::ptr<CellPngDecExtThreadOutParam> extThreadOutParam)
{ {
cellPngDec.Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x, extThreadInParam_addr=0x%x, extThreadOutParam_addr=0x%x)", cellPngDec.Warning("cellPngDecCreate(mainHandle=**0x%x, threadInParam=*0x%x, threadOutParam=*0x%x, extThreadInParam=*0x%x, extThreadOutParam=*0x%x)",
mainHandle.addr(), threadInParam.addr(), threadOutParam.addr(), extThreadInParam.addr(), extThreadOutParam.addr()); mainHandle, threadInParam, threadOutParam, extThreadInParam, extThreadOutParam);
// create decoder // create decoder
if (auto res = pngDecCreate(mainHandle, threadInParam, extThreadInParam)) return res; if (auto res = pngDecCreate(mainHandle, threadInParam, extThreadInParam)) return res;
@ -400,7 +402,7 @@ s32 cellPngDecExtCreate(
s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle) s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle)
{ {
cellPngDec.Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle.addr()); cellPngDec.Warning("cellPngDecDestroy(mainHandle=*0x%x)", mainHandle);
// destroy decoder // destroy decoder
return pngDecDestroy(mainHandle); return pngDecDestroy(mainHandle);
@ -412,8 +414,7 @@ s32 cellPngDecOpen(
vm::ptr<const CellPngDecSrc> src, vm::ptr<const CellPngDecSrc> src,
vm::ptr<CellPngDecOpnInfo> openInfo) vm::ptr<CellPngDecOpnInfo> openInfo)
{ {
cellPngDec.Warning("cellPngDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", cellPngDec.Warning("cellPngDecOpen(mainHandle=*0x%x, subHandle=**0x%x, src=*0x%x, openInfo=*0x%x)", mainHandle, subHandle, src, openInfo);
mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr());
// create stream handle // create stream handle
return pngDecOpen(mainHandle, subHandle, src, openInfo); return pngDecOpen(mainHandle, subHandle, src, openInfo);
@ -427,8 +428,7 @@ s32 cellPngDecExtOpen(
vm::ptr<const CellPngDecCbCtrlStrm> cbCtrlStrm, vm::ptr<const CellPngDecCbCtrlStrm> cbCtrlStrm,
vm::ptr<const CellPngDecOpnParam> opnParam) vm::ptr<const CellPngDecOpnParam> opnParam)
{ {
cellPngDec.Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x, cbCtrlStrm_addr=0x%x, opnParam_addr=0x%x)", cellPngDec.Warning("cellPngDecExtOpen(mainHandle=*0x%x, subHandle=**0x%x, src=*0x%x, openInfo=*0x%x, cbCtrlStrm=*0x%x, opnParam=*0x%x)", mainHandle, subHandle, src, openInfo, cbCtrlStrm, opnParam);
mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr(), cbCtrlStrm.addr(), opnParam.addr());
// create stream handle // create stream handle
return pngDecOpen(mainHandle, subHandle, src, openInfo, cbCtrlStrm, opnParam); return pngDecOpen(mainHandle, subHandle, src, openInfo, cbCtrlStrm, opnParam);
@ -436,15 +436,14 @@ s32 cellPngDecExtOpen(
s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle) s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle)
{ {
cellPngDec.Warning("cellPngDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle.addr(), subHandle.addr()); cellPngDec.Warning("cellPngDecClose(mainHandle=*0x%x, subHandle=*0x%x)", mainHandle, subHandle);
return pngDecClose(subHandle); return pngDecClose(subHandle);
} }
s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngDecInfo> info) s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr<CellPngDecInfo> info)
{ {
cellPngDec.Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", cellPngDec.Warning("cellPngDecReadHeader(mainHandle=*0x%x, subHandle=*0x%x, info=*0x%x)", mainHandle, subHandle, info);
mainHandle.addr(), subHandle.addr(), info.addr());
return pngReadHeader(subHandle, info); return pngReadHeader(subHandle, info);
} }
@ -455,8 +454,7 @@ s32 cellPngDecExtReadHeader(
vm::ptr<CellPngDecInfo> info, vm::ptr<CellPngDecInfo> info,
vm::ptr<CellPngDecExtInfo> extInfo) vm::ptr<CellPngDecExtInfo> extInfo)
{ {
cellPngDec.Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", cellPngDec.Warning("cellPngDecExtReadHeader(mainHandle=*0x%x, subHandle=*0x%x, info=*0x%x, extInfo=*0x%x)", mainHandle, subHandle, info, extInfo);
mainHandle.addr(), subHandle.addr(), info.addr(), extInfo.addr());
return pngReadHeader(subHandle, info, extInfo); return pngReadHeader(subHandle, info, extInfo);
} }
@ -467,8 +465,7 @@ s32 cellPngDecSetParameter(
vm::ptr<const CellPngDecInParam> inParam, vm::ptr<const CellPngDecInParam> inParam,
vm::ptr<CellPngDecOutParam> outParam) vm::ptr<CellPngDecOutParam> outParam)
{ {
cellPngDec.Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", cellPngDec.Warning("cellPngDecSetParameter(mainHandle=*0x%x, subHandle=*0x%x, inParam=*0x%x, outParam=*0x%x)", mainHandle, subHandle, inParam, outParam);
mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr());
return pngDecSetParameter(subHandle, inParam, outParam); return pngDecSetParameter(subHandle, inParam, outParam);
} }
@ -481,8 +478,7 @@ s32 cellPngDecExtSetParameter(
vm::ptr<const CellPngDecExtInParam> extInParam, vm::ptr<const CellPngDecExtInParam> extInParam,
vm::ptr<CellPngDecExtOutParam> extOutParam) vm::ptr<CellPngDecExtOutParam> extOutParam)
{ {
cellPngDec.Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x", cellPngDec.Warning("cellPngDecExtSetParameter(mainHandle=*0x%x, subHandle=*0x%x, inParam=*0x%x, outParam=*0x%x, extInParam=*0x%x, extOutParam=*0x%x", mainHandle, subHandle, inParam, outParam, extInParam, extOutParam);
mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr());
return pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam); return pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam);
} }
@ -494,8 +490,8 @@ s32 cellPngDecDecodeData(
vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam, vm::ptr<const CellPngDecDataCtrlParam> dataCtrlParam,
vm::ptr<CellPngDecDataOutInfo> dataOutInfo) vm::ptr<CellPngDecDataOutInfo> dataOutInfo)
{ {
cellPngDec.Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", cellPngDec.Warning("cellPngDecDecodeData(mainHandle=*0x%x, subHandle=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x)",
mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr()); mainHandle, subHandle, data, dataCtrlParam, dataOutInfo);
return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo); return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo);
} }
@ -509,8 +505,8 @@ s32 cellPngDecExtDecodeData(
vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp, vm::ptr<const CellPngDecCbCtrlDisp> cbCtrlDisp,
vm::ptr<CellPngDecDispParam> dispParam) vm::ptr<CellPngDecDispParam> dispParam)
{ {
cellPngDec.Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam_addr=0x%x)", cellPngDec.Warning("cellPngDecExtDecodeData(mainHandle=*0x%x, subHandle=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x, cbCtrlDisp=*0x%x, dispParam=*0x%x)",
mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr()); mainHandle, subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam);
return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam); return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam);
} }

View file

@ -603,7 +603,7 @@ void cellRescExit()
if (IsPalTemporal()) if (IsPalTemporal())
{ {
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE);
cellGcmSetVBlankHandler(vm::ptr<void(u32)>::make(0)); cellGcmSetVBlankHandler(vm::null);
//GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL);
if (IsPalInterpolate()) if (IsPalInterpolate())
@ -770,7 +770,7 @@ int cellRescSetDisplayMode(u32 displayMode)
videocfg->aspect = CELL_VIDEO_OUT_ASPECT_AUTO; videocfg->aspect = CELL_VIDEO_OUT_ASPECT_AUTO;
videocfg->pitch = s_rescInternalInstance->m_dstPitch; videocfg->pitch = s_rescInternalInstance->m_dstPitch;
cellVideoOutConfigure(CELL_VIDEO_OUT_PRIMARY, videocfg, vm::ptr<CellVideoOutOption>::make(0), 0); cellVideoOutConfigure(CELL_VIDEO_OUT_PRIMARY, videocfg, vm::null, 0);
if (IsPalInterpolate()) if (IsPalInterpolate())
{ {
@ -780,20 +780,20 @@ int cellRescSetDisplayMode(u32 displayMode)
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
//cellGcmSetVBlankHandler(IntrHandler50); //cellGcmSetVBlankHandler(IntrHandler50);
//cellGcmSetSecondVHandler(IntrHandler60); //cellGcmSetSecondVHandler(IntrHandler60);
cellGcmSetFlipHandler(vm::ptr<void(u32)>::make(0)); cellGcmSetFlipHandler(vm::null);
} }
else if (IsPalDrop()) else if (IsPalDrop())
{ {
//InitLabels(); //InitLabels();
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(vm::ptr<void(u32)>::make(0)); cellGcmSetVBlankHandler(vm::null);
//cellGcmSetSecondVHandler(IntrHandler60Drop); //cellGcmSetSecondVHandler(IntrHandler60Drop);
cellGcmSetFlipHandler(vm::ptr<void(u32)>::make(0)); cellGcmSetFlipHandler(vm::null);
} }
else if (IsPal60Hsync()) else if (IsPal60Hsync())
{ {
cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ);
cellGcmSetVBlankHandler(vm::ptr<void(u32)>::make(0)); cellGcmSetVBlankHandler(vm::null);
} }
if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler);

File diff suppressed because it is too large Load diff

View file

@ -85,6 +85,13 @@ enum
CELL_SAVEDATA_FILETYPE_CONTENT_ICON1 = 3, CELL_SAVEDATA_FILETYPE_CONTENT_ICON1 = 3,
CELL_SAVEDATA_FILETYPE_CONTENT_PIC1 = 4, CELL_SAVEDATA_FILETYPE_CONTENT_PIC1 = 4,
CELL_SAVEDATA_FILETYPE_CONTENT_SND0 = 5, CELL_SAVEDATA_FILETYPE_CONTENT_SND0 = 5,
// reCreateMode
CELL_SAVEDATA_RECREATE_NO = 0,
CELL_SAVEDATA_RECREATE_NO_NOBROKEN = 1,
CELL_SAVEDATA_RECREATE_YES = 2,
CELL_SAVEDATA_RECREATE_YES_RESET_OWNER = 3,
CELL_SAVEDATA_RECREATE_MASK = 0xffff,
}; };
@ -167,22 +174,22 @@ struct CellSaveDataSystemFileParam
struct CellSaveDataDirStat struct CellSaveDataDirStat
{ {
be_t<s64> st_atime_; be_t<s64> atime;
be_t<s64> st_mtime_; be_t<s64> mtime;
be_t<s64> st_ctime_; be_t<s64> ctime;
char dirName[CELL_SAVEDATA_DIRNAME_SIZE]; char dirName[CELL_SAVEDATA_DIRNAME_SIZE];
}; };
struct CellSaveDataFileStat struct CellSaveDataFileStat
{ {
be_t<u32> fileType; be_t<u32> fileType;
u8 reserved1[4]; char reserved1[4];
be_t<u64> st_size; be_t<u64> size;
be_t<s64> st_atime_; be_t<s64> atime;
be_t<s64> st_mtime_; be_t<s64> mtime;
be_t<s64> st_ctime_; be_t<s64> ctime;
char fileName[CELL_SAVEDATA_FILENAME_SIZE]; char fileName[CELL_SAVEDATA_FILENAME_SIZE];
u8 reserved2[3]; char reserved2[3];
}; };
struct CellSaveDataStatGet struct CellSaveDataStatGet
@ -271,11 +278,21 @@ struct SaveDataEntry
std::string title; std::string title;
std::string subtitle; std::string subtitle;
std::string details; std::string details;
u32 sizeKB; u64 size;
s64 st_atime_; s64 atime;
s64 st_mtime_; s64 mtime;
s64 st_ctime_; s64 ctime;
void* iconBuf; //void* iconBuf;
u32 iconBufSize; //u32 iconBufSize;
bool isNew; bool isNew;
}; };
struct SaveDataDialogInstance
{
std::mutex mutex;
SaveDataDialogInstance();
virtual ~SaveDataDialogInstance() = default;
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, vm::ptr<CellSaveDataListSet> listSet) = 0;
};

View file

@ -150,11 +150,12 @@ s32 spursInit(
name += "CellSpursKernel0"; name += "CellSpursKernel0";
for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++)
{ {
const u32 id = spu_thread_initialize(spurs->m.spuTG, num, vm::ptr<sys_spu_image>::make(spurs.addr() + offsetof(CellSpurs, m.spuImg)), name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, (u64)num << 32, spurs.addr(), 0, 0); spurs->m.spus[num] = spu_thread_initialize(spurs->m.spuTG, num, vm::ptr<sys_spu_image>::make(spurs.addr() + offsetof(CellSpurs, m.spuImg)),
name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, (u64)num << 32, spurs.addr(), 0, 0, [spurs](SPUThread& SPU)
static_cast<SPUThread&>(*Emu.GetCPU().GetThread(id).get()).RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelEntry); {
SPU.RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelEntry);
spurs->m.spus[num] = id; SPU.FastCall(spurs->m.spuImg.entry_point);
});
} }
if (flags & SAF_SPU_PRINTF_ENABLED) if (flags & SAF_SPU_PRINTF_ENABLED)
@ -305,7 +306,7 @@ s32 spursInit(
{ {
assert(!"sys_spu_thread_group_start() failed"); assert(!"sys_spu_thread_group_start() failed");
} }
if (s32 res = sys_spu_thread_group_join(spurs->m.spuTG, vm::ptr<u32>::make(0), vm::ptr<u32>::make(0))) if (s32 res = sys_spu_thread_group_join(spurs->m.spuTG, vm::null, vm::null))
{ {
if (res == CELL_ESTAT) if (res == CELL_ESTAT)
{ {
@ -474,7 +475,7 @@ s32 _cellSpursAttributeInitialize(vm::ptr<CellSpursAttribute> attr, u32 revision
s32 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr<CellSpursAttribute> attr, u32 container) s32 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr<CellSpursAttribute> attr, u32 container)
{ {
cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=%d)", attr.addr(), container); cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)", attr.addr(), container);
if (!attr) if (!attr)
{ {
@ -706,7 +707,7 @@ s32 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> po
s32 cellSpursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic) s32 cellSpursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> port, s32 isDynamic)
{ {
cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%d)",
spurs.addr(), queue, port.addr(), isDynamic); spurs.addr(), queue, port.addr(), isDynamic);
return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false);
@ -1050,10 +1051,10 @@ s32 cellSpursAddWorkload(
*priorityTable, *priorityTable,
minContention, minContention,
maxContention, maxContention,
vm::ptr<const char>::make(0), vm::null,
vm::ptr<const char>::make(0), vm::null,
vm::ptr<CellSpursShutdownCompletionEventHook>::make(0), vm::null,
vm::ptr<void>::make(0)); vm::null);
} }
s32 _cellSpursWorkloadAttributeInitialize( s32 _cellSpursWorkloadAttributeInitialize(
@ -1159,16 +1160,16 @@ s32 cellSpursAddWorkloadWithAttribute(vm::ptr<CellSpurs> spurs, const vm::ptr<u3
return spursAddWorkload( return spursAddWorkload(
spurs, spurs,
wid, wid,
vm::ptr<const void>::make(attr->m.pm.addr()), attr->m.pm,
attr->m.size, attr->m.size,
attr->m.data, attr->m.data,
attr->m.priority, attr->m.priority,
attr->m.minContention, attr->m.minContention,
attr->m.maxContention, attr->m.maxContention,
vm::ptr<const char>::make(attr->m.nameClass.addr()), attr->m.nameClass,
vm::ptr<const char>::make(attr->m.nameInstance.addr()), attr->m.nameInstance,
vm::ptr<CellSpursShutdownCompletionEventHook>::make(attr->m.hook.addr()), attr->m.hook,
vm::ptr<void>::make(attr->m.hookArg.addr())); attr->m.hookArg);
} }
s32 cellSpursRemoveWorkload() s32 cellSpursRemoveWorkload()
@ -2182,14 +2183,14 @@ s32 spursCreateTaskset(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> tasks
taskset.addr(), priority, 8 /*min_contention*/, max_contention); taskset.addr(), priority, 8 /*min_contention*/, max_contention);
// TODO: Check return code // TODO: Check return code
cellSpursWorkloadAttributeSetName(wkl_attr, vm::ptr<const char>::make(0), name); cellSpursWorkloadAttributeSetName(wkl_attr, vm::null, name);
// TODO: Check return code // TODO: Check return code
// TODO: cellSpursWorkloadAttributeSetShutdownCompletionEventHook(wkl_attr, hook, taskset); // TODO: cellSpursWorkloadAttributeSetShutdownCompletionEventHook(wkl_attr, hook, taskset);
// TODO: Check return code // TODO: Check return code
vm::var<be_t<u32>> wid; vm::var<be_t<u32>> wid;
cellSpursAddWorkloadWithAttribute(spurs, vm::ptr<u32>::make(wid.addr()), vm::ptr<const CellSpursWorkloadAttribute>::make(wkl_attr.addr())); cellSpursAddWorkloadWithAttribute(spurs, vm::ptr<u32>::make(wid.addr()), wkl_attr);
// TODO: Check return code // TODO: Check return code
taskset->m.wkl_flag_wait_task = 0x80; taskset->m.wkl_flag_wait_task = 0x80;
@ -2235,7 +2236,7 @@ s32 cellSpursCreateTaskset(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset> t
cellSpurs.Warning("cellSpursCreateTaskset(spurs_addr=0x%x, taskset_addr=0x%x, args=0x%llx, priority_addr=0x%x, maxContention=%d)", cellSpurs.Warning("cellSpursCreateTaskset(spurs_addr=0x%x, taskset_addr=0x%x, args=0x%llx, priority_addr=0x%x, maxContention=%d)",
spurs.addr(), taskset.addr(), args, priority.addr(), maxContention); spurs.addr(), taskset.addr(), args, priority.addr(), maxContention);
return spursCreateTaskset(spurs, taskset, args, priority, maxContention, vm::ptr<const char>::make(0), 6400/*CellSpursTaskset::size*/, 0); return spursCreateTaskset(spurs, taskset, args, priority, maxContention, vm::null, 6400/*CellSpursTaskset::size*/, 0);
} }
s32 cellSpursJoinTaskset(vm::ptr<CellSpursTaskset> taskset) s32 cellSpursJoinTaskset(vm::ptr<CellSpursTaskset> taskset)
@ -2395,8 +2396,8 @@ s32 spursTaskStart(vm::ptr<CellSpursTaskset> taskset, u32 taskId)
pendingReady._bit[taskId] = true; pendingReady._bit[taskId] = true;
taskset->m.pending_ready = pendingReady; taskset->m.pending_ready = pendingReady;
cellSpursSendWorkloadSignal(vm::ptr<CellSpurs>::make((u32)taskset->m.spurs.addr()), taskset->m.wid); cellSpursSendWorkloadSignal(taskset->m.spurs, taskset->m.wid);
auto rc = cellSpursWakeUp(GetCurrentPPUThread(), vm::ptr<CellSpurs>::make((u32)taskset->m.spurs.addr())); auto rc = cellSpursWakeUp(GetCurrentPPUThread(), taskset->m.spurs);
if (rc != CELL_OK) if (rc != CELL_OK)
{ {
if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT) if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT)
@ -2478,8 +2479,8 @@ s32 _cellSpursSendSignal(vm::ptr<CellSpursTaskset> taskset, u32 taskId)
taskset->m.signalled = signalled; taskset->m.signalled = signalled;
if (shouldSignal) if (shouldSignal)
{ {
cellSpursSendWorkloadSignal(vm::ptr<CellSpurs>::make((u32)taskset->m.spurs.addr()), taskset->m.wid); cellSpursSendWorkloadSignal(taskset->m.spurs, taskset->m.wid);
auto rc = cellSpursWakeUp(GetCurrentPPUThread(), vm::ptr<CellSpurs>::make((u32)taskset->m.spurs.addr())); auto rc = cellSpursWakeUp(GetCurrentPPUThread(), taskset->m.spurs);
if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT) if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT)
{ {
return CELL_SPURS_TASK_ERROR_STAT; return CELL_SPURS_TASK_ERROR_STAT;
@ -2565,7 +2566,7 @@ s32 _cellSpursTasksetAttribute2Initialize(vm::ptr<CellSpursTasksetAttribute2> at
memset(attribute.get_ptr(), 0, CellSpursTasksetAttribute2::size); memset(attribute.get_ptr(), 0, CellSpursTasksetAttribute2::size);
attribute->m.revision = revision; attribute->m.revision = revision;
attribute->m.name.set(0); attribute->m.name = vm::null;
attribute->m.args = 0; attribute->m.args = 0;
for (s32 i = 0; i < 8; i++) for (s32 i = 0; i < 8; i++)
@ -2665,7 +2666,7 @@ s32 cellSpursCreateTaskset2(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTaskset2>
auto rc = spursCreateTaskset(spurs, vm::ptr<CellSpursTaskset>::make(taskset.addr()), attr->m.args, auto rc = spursCreateTaskset(spurs, vm::ptr<CellSpursTaskset>::make(taskset.addr()), attr->m.args,
vm::ptr<const u8[8]>::make(attr.addr() + offsetof(CellSpursTasksetAttribute, m.priority)), vm::ptr<const u8[8]>::make(attr.addr() + offsetof(CellSpursTasksetAttribute, m.priority)),
attr->m.max_contention, vm::ptr<const char>::make(attr->m.name.addr()), CellSpursTaskset2::size, (u8)attr->m.enable_clear_ls); attr->m.max_contention, attr->m.name, CellSpursTaskset2::size, (u8)attr->m.enable_clear_ls);
if (rc != CELL_OK) if (rc != CELL_OK)
{ {
return rc; return rc;
@ -2773,7 +2774,7 @@ s32 cellSpursLookUpTasksetAddress(vm::ptr<CellSpurs> spurs, vm::ptr<CellSpursTas
} }
vm::var<be_t<u64>> data; vm::var<be_t<u64>> data;
auto rc = cellSpursGetWorkloadData(spurs, vm::ptr<u64>::make(data.addr()), id); auto rc = cellSpursGetWorkloadData(spurs, data, id);
if (rc != CELL_OK) if (rc != CELL_OK)
{ {
// Convert policy module error code to a task error code // Convert policy module error code to a task error code

View file

@ -289,7 +289,7 @@ s32 syncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer
} }
// prx: zeroize first u16 and second u16, write buffer_size in second u32, write buffer_addr in second u64 and sync // prx: zeroize first u16 and second u16, write buffer_size in second u32, write buffer_addr in second u64 and sync
rwm->m_size = be_t<u32>::make(buffer_size); rwm->m_size = buffer_size;
rwm->m_buffer = buffer; rwm->m_buffer = buffer;
rwm->data.exchange({}); rwm->data.exchange({});
@ -488,9 +488,9 @@ s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 si
} }
// prx: zeroize first u64, write size in third u32, write depth in fourth u32, write address in third u64 and sync // prx: zeroize first u64, write size in third u32, write depth in fourth u32, write address in third u64 and sync
queue->m_size = be_t<u32>::make(size); queue->m_size = size;
queue->m_depth = be_t<u32>::make(depth); queue->m_depth = depth;
queue->m_buffer.set(buffer.addr()); queue->m_buffer = buffer;
queue->data.exchange({}); queue->data.exchange({});
return CELL_OK; return CELL_OK;
@ -985,7 +985,7 @@ s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u3
if (old_value == 2) if (old_value == 2)
{ {
if (queue->m_size != size || queue->m_depth != depth || queue->m_buffer.addr().value() != buffer.addr()) if (queue->m_size != size || queue->m_depth != depth || queue->m_buffer != buffer)
{ {
return CELL_SYNC_ERROR_INVAL; return CELL_SYNC_ERROR_INVAL;
} }
@ -1104,7 +1104,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
} }
} }
if (s32 res = sys_event_queue_receive(GetCurrentPPUThread(), queue->m_eq_id, vm::ptr<sys_event_t>::make(0), 0)) if (s32 res = sys_event_queue_receive(GetCurrentPPUThread(), queue->m_eq_id, vm::null, 0))
{ {
assert(!"sys_event_queue_receive() failed"); assert(!"sys_event_queue_receive() failed");
} }
@ -1448,7 +1448,7 @@ s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 i
} }
} }
if (s32 res = sys_event_queue_receive(GetCurrentPPUThread(), queue->m_eq_id, vm::ptr<sys_event_t>::make(0), 0)) if (s32 res = sys_event_queue_receive(GetCurrentPPUThread(), queue->m_eq_id, vm::null, 0))
{ {
assert(!"sys_event_queue_receive() failed"); assert(!"sys_event_queue_receive() failed");
} }

View file

@ -16,11 +16,8 @@
#include "Emu/Audio/AudioManager.h" #include "Emu/Audio/AudioManager.h"
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "cellMsgDialog.h" #include "cellMsgDialog.h"
#include "cellGame.h"
#include "cellSysutil.h" #include "cellSysutil.h"
typedef void (CellHddGameStatCallback)(vm::ptr<CellHddGameCBResult> cbResult, vm::ptr<CellHddGameStatGet> get, vm::ptr<CellHddGameStatSet> set);
extern Module cellSysutil; extern Module cellSysutil;
int cellSysutilGetSystemParamInt(int id, vm::ptr<u32> value) int cellSysutilGetSystemParamInt(int id, vm::ptr<u32> value)
@ -688,76 +685,6 @@ int cellSysCacheMount(vm::ptr<CellSysCacheParam> param)
return CELL_SYSCACHE_RET_OK_RELAYED; return CELL_SYSCACHE_RET_OK_RELAYED;
} }
int cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
{
cellSysutil.Warning("cellHddGameCheck(version=%d, dirName_addr=0x%x, errDialog=%d, funcStat_addr=0x%x, container=%d)",
version, dirName.addr(), errDialog, funcStat.addr(), container);
std::string dir = dirName.get_ptr();
if (dir.size() != 9)
return CELL_HDDGAME_ERROR_PARAM;
vm::var<CellHddGameSystemFileParam> param;
vm::var<CellHddGameCBResult> result;
vm::var<CellHddGameStatGet> get;
vm::var<CellHddGameStatSet> set;
get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST;
get->sysSizeKB = 0; // TODO
get->st_atime__ = 0; // TODO
get->st_ctime__ = 0; // TODO
get->st_mtime__ = 0; // TODO
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
memcpy(get->contentInfoPath, ("/dev_hdd0/game/" + dir).c_str(), CELL_HDDGAME_PATH_MAX);
memcpy(get->hddGamePath, ("/dev_hdd0/game/" + dir + "/USRDIR").c_str(), CELL_HDDGAME_PATH_MAX);
if (!Emu.GetVFS().ExistsDir(("/dev_hdd0/game/" + dir).c_str()))
{
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
}
else
{
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
vfsFile f(("/dev_hdd0/game/" + dir + "/PARAM.SFO").c_str());
PSFLoader psf(f);
if (!psf.Load(false)) {
return CELL_HDDGAME_ERROR_BROKEN;
}
get->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
get->getParam.attribute = psf.GetInteger("ATTRIBUTE");
get->getParam.resolution = psf.GetInteger("RESOLUTION");
get->getParam.soundFormat = psf.GetInteger("SOUND_FORMAT");
std::string title = psf.GetString("TITLE");
strcpy_trunc(get->getParam.title, title);
std::string app_ver = psf.GetString("APP_VER");
strcpy_trunc(get->getParam.dataVersion, app_ver);
strcpy_trunc(get->getParam.titleId, dir);
for (u32 i=0; i<CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) {
char key [16];
sprintf(key, "TITLE_%02d", i);
title = psf.GetString(key);
strcpy_trunc(get->getParam.titleLang[i], title);
}
}
// TODO ?
funcStat(result, get, set);
if (result->result != CELL_HDDGAME_CBRESULT_OK &&
result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL) {
return CELL_HDDGAME_ERROR_CBRESULT;
}
// TODO ?
return CELL_OK;
}
bool bgm_playback_enabled = true; bool bgm_playback_enabled = true;
int cellSysutilEnableBgmPlayback() int cellSysutilEnableBgmPlayback()
@ -835,13 +762,9 @@ int cellWebBrowserEstimate2(const vm::ptr<const CellWebBrowserConfig2> config, v
return CELL_OK; return CELL_OK;
} }
extern int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container);
extern int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog,
vm::ptr<void(vm::ptr<CellGameDataCBResult> cbResult, vm::ptr<CellGameDataStatGet> get, vm::ptr<CellGameDataStatSet> set)> funcStat, u32 container);
extern void cellSysutil_SaveData_init(); extern void cellSysutil_SaveData_init();
extern void cellSysutil_GameData_init();
extern void cellSysutil_MsgDialog_init();
Module cellSysutil("cellSysutil", []() Module cellSysutil("cellSysutil", []()
{ {
@ -851,6 +774,10 @@ Module cellSysutil("cellSysutil", []()
v.arg.set(0); v.arg.set(0);
} }
cellSysutil_SaveData_init(); // cellSaveData functions
cellSysutil_GameData_init(); // cellGameData, cellHddGame functions
cellSysutil_MsgDialog_init(); // cellMsgDialog functions
REG_FUNC(cellSysutil, cellSysutilGetSystemParamInt); REG_FUNC(cellSysutil, cellSysutilGetSystemParamInt);
REG_FUNC(cellSysutil, cellSysutilGetSystemParamString); REG_FUNC(cellSysutil, cellSysutilGetSystemParamString);
@ -866,14 +793,6 @@ Module cellSysutil("cellSysutil", []()
REG_FUNC(cellSysutil, cellSysutilRegisterCallback); REG_FUNC(cellSysutil, cellSysutilRegisterCallback);
REG_FUNC(cellSysutil, cellSysutilUnregisterCallback); REG_FUNC(cellSysutil, cellSysutilUnregisterCallback);
REG_FUNC(cellSysutil, cellMsgDialogOpen2);
REG_FUNC(cellSysutil, cellMsgDialogOpenErrorCode);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarSetMsg);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarReset);
REG_FUNC(cellSysutil, cellMsgDialogProgressBarInc);
REG_FUNC(cellSysutil, cellMsgDialogClose);
REG_FUNC(cellSysutil, cellMsgDialogAbort);
REG_FUNC(cellSysutil, cellAudioOutGetState); REG_FUNC(cellSysutil, cellAudioOutGetState);
REG_FUNC(cellSysutil, cellAudioOutConfigure); REG_FUNC(cellSysutil, cellAudioOutConfigure);
REG_FUNC(cellSysutil, cellAudioOutGetSoundAvailability); REG_FUNC(cellSysutil, cellAudioOutGetSoundAvailability);
@ -893,22 +812,8 @@ Module cellSysutil("cellSysutil", []()
REG_FUNC(cellSysutil, cellSysCacheMount); REG_FUNC(cellSysutil, cellSysCacheMount);
REG_FUNC(cellSysutil, cellSysCacheClear); REG_FUNC(cellSysutil, cellSysCacheClear);
REG_FUNC(cellSysutil, cellHddGameCheck);
//REG_FUNC(cellSysutil, cellHddGameCheck2);
//REG_FUNC(cellSysutil, cellHddGameGetSizeKB);
//REG_FUNC(cellSysutil, cellHddGameSetSystemVer);
//REG_FUNC(cellSysutil, cellHddGameExitBroken);
//REG_FUNC(cellSysutil, cellSysutilRegisterCallbackDispatcher); //REG_FUNC(cellSysutil, cellSysutilRegisterCallbackDispatcher);
//REG_FUNC(cellSysutil, cellSysutilPacketWrite); //REG_FUNC(cellSysutil, cellSysutilPacketWrite);
//REG_FUNC(cellSysutil, doc.write);
//REG_FUNC(cellSysutil, packet_read);
// cellSaveData functions
cellSysutil_SaveData_init();
REG_FUNC(cellSysutil, cellWebBrowserEstimate2); REG_FUNC(cellSysutil, cellWebBrowserEstimate2);
REG_FUNC(cellSysutil, cellGameDataCheckCreate);
REG_FUNC(cellSysutil, cellGameDataCheckCreate2);
}); });

View file

@ -152,91 +152,6 @@ enum
CELL_SYSCACHE_ERROR_NOTMOUNTED = 0x8002bc04, // We don't really need to simulate the mounting, so this is probably useless CELL_SYSCACHE_ERROR_NOTMOUNTED = 0x8002bc04, // We don't really need to simulate the mounting, so this is probably useless
}; };
// cellSysutil: cellHddGame
enum
{
// Return Codes
CELL_HDDGAME_RET_CANCEL = 1,
CELL_HDDGAME_ERROR_CBRESULT = 0x8002ba01,
CELL_HDDGAME_ERROR_ACCESS_ERROR = 0x8002ba02,
CELL_HDDGAME_ERROR_INTERNAL = 0x8002ba03,
CELL_HDDGAME_ERROR_PARAM = 0x8002ba04,
CELL_HDDGAME_ERROR_NOSPACE = 0x8002ba05,
CELL_HDDGAME_ERROR_BROKEN = 0x8002ba06,
CELL_HDDGAME_ERROR_FAILURE = 0x8002ba07,
// Callback Result
CELL_HDDGAME_CBRESULT_OK_CANCEL = 1,
CELL_HDDGAME_CBRESULT_OK = 0,
CELL_HDDGAME_CBRESULT_ERR_NOSPACE = -1,
CELL_HDDGAME_CBRESULT_ERR_BROKEN = -3,
CELL_HDDGAME_CBRESULT_ERR_NODATA = -4,
CELL_HDDGAME_CBRESULT_ERR_INVALID = -5,
// Character Strings
CELL_HDDGAME_INVALIDMSG_MAX = 256,
CELL_HDDGAME_PATH_MAX = 1055,
CELL_HDDGAME_SYSP_TITLE_SIZE = 128,
CELL_HDDGAME_SYSP_TITLEID_SIZE = 10,
CELL_HDDGAME_SYSP_VERSION_SIZE = 6,
CELL_HDDGAME_SYSP_SYSTEMVER_SIZE = 8,
// HDD Directory exists
CELL_HDDGAME_ISNEWDATA_EXIST = 0,
CELL_HDDGAME_ISNEWDATA_NODIR = 1,
// Languages
CELL_HDDGAME_SYSP_LANGUAGE_NUM = 20,
// Stat Get
CELL_HDDGAME_SIZEKB_NOTCALC = -1,
};
struct CellHddGameSystemFileParam
{
char title[CELL_HDDGAME_SYSP_TITLE_SIZE];
char titleLang[CELL_HDDGAME_SYSP_LANGUAGE_NUM][CELL_HDDGAME_SYSP_TITLE_SIZE];
char titleId[CELL_HDDGAME_SYSP_TITLEID_SIZE];
u8 reserved0[2];
char dataVersion[CELL_HDDGAME_SYSP_VERSION_SIZE];
u8 reserved1[2];
be_t<u32> attribute;
be_t<u32> parentalLevel;
be_t<u32> resolution;
be_t<u32> soundFormat;
u8 reserved2[256];
};
struct CellHddGameStatGet
{
be_t<s32> hddFreeSizeKB;
be_t<u32> isNewData;
u8 contentInfoPath[CELL_HDDGAME_PATH_MAX];
u8 hddGamePath[CELL_HDDGAME_PATH_MAX];
u8 reserved0[2];
be_t<u64> st_atime__;
be_t<u64> st_mtime__;
be_t<u64> st_ctime__;
CellHddGameSystemFileParam getParam;
be_t<s32> sizeKB;
be_t<s32> sysSizeKB;
u8 reserved1[68];
};
struct CellHddGameStatSet
{
vm::bptr<CellHddGameSystemFileParam> setParam;
be_t<u32> reserved_addr; // void*
};
struct CellHddGameCBResult
{
be_t<u32> result;
be_t<s32> errNeedSizeKB;
be_t<u32> invalidMsg_addr; // char*
be_t<u32> reserved_addr; // void*
};
typedef s32 CellWebBrowserId; typedef s32 CellWebBrowserId;
typedef vm::ptr<void> CellWebBrowserClientSession; typedef vm::ptr<void> CellWebBrowserClientSession;
typedef void(CellWebBrowserCallback)(s32 cb_type, CellWebBrowserClientSession, vm::ptr<void> usrdata); typedef void(CellWebBrowserCallback)(s32 cb_type, CellWebBrowserClientSession, vm::ptr<void> usrdata);
@ -303,4 +218,3 @@ struct CellWebBrowserConfig2
be_t<float> resolution_factor; be_t<float> resolution_factor;
be_t<s32> magic_number_; be_t<s32> magic_number_;
}; };

View file

@ -12,6 +12,7 @@ extern "C"
#include "libavcodec/avcodec.h" #include "libavcodec/avcodec.h"
#include "libavformat/avformat.h" #include "libavformat/avformat.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libswscale/swscale.h"
} }
#include "Emu/CPU/CPUThreadManager.h" #include "Emu/CPU/CPUThreadManager.h"
@ -216,7 +217,7 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
vdec.id = vdec_id; vdec.id = vdec_id;
vdec.vdecCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get()); vdec.vdecCb = static_cast<PPUThread*>(Emu.GetCPU().AddThread(CPU_THREAD_PPU).get());
vdec.vdecCb->SetName(fmt::format("VideoDecoder[%d] Callback", vdec_id)); vdec.vdecCb->SetName(fmt::format("VideoDecoder[0x%x] Callback", vdec_id));
vdec.vdecCb->SetEntry(0); vdec.vdecCb->SetEntry(0);
vdec.vdecCb->SetPrio(1001); vdec.vdecCb->SetPrio(1001);
vdec.vdecCb->SetStackSize(0x10000); vdec.vdecCb->SetStackSize(0x10000);
@ -224,7 +225,7 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
vdec.vdecCb->InitRegs(); vdec.vdecCb->InitRegs();
vdec.vdecCb->DoRun(); vdec.vdecCb->DoRun();
thread_t t(fmt::format("VideoDecoder[%d] Thread", vdec_id), [vdec_ptr, sptr]() thread_t t(fmt::format("VideoDecoder[0x%x] Thread", vdec_id), [vdec_ptr, sptr]()
{ {
VideoDecoder& vdec = *vdec_ptr; VideoDecoder& vdec = *vdec_ptr;
VdecTask& task = vdec.task; VdecTask& task = vdec.task;
@ -269,12 +270,6 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
{ {
int err; int err;
if (task.mode != CELL_VDEC_DEC_MODE_NORMAL)
{
cellVdec.Error("vdecDecodeAu: unsupported decoding mode(%d)", task.mode);
break;
}
vdec.reader.addr = task.addr; vdec.reader.addr = task.addr;
vdec.reader.size = task.size; vdec.reader.size = task.size;
//LOG_NOTICE(HLE, "Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts); //LOG_NOTICE(HLE, "Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts);
@ -558,46 +553,45 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
return vdec_id; return vdec_id;
} }
int cellVdecQueryAttr(vm::ptr<const CellVdecType> type, vm::ptr<CellVdecAttr> attr) s32 cellVdecQueryAttr(vm::ptr<const CellVdecType> type, vm::ptr<CellVdecAttr> attr)
{ {
cellVdec.Warning("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.addr(), attr.addr()); cellVdec.Warning("cellVdecQueryAttr(type=*0x%x, attr=*0x%x)", type, attr);
return vdecQueryAttr(type->codecType, type->profileLevel, 0, attr); return vdecQueryAttr(type->codecType, type->profileLevel, 0, attr);
} }
int cellVdecQueryAttrEx(vm::ptr<const CellVdecTypeEx> type, vm::ptr<CellVdecAttr> attr) s32 cellVdecQueryAttrEx(vm::ptr<const CellVdecTypeEx> type, vm::ptr<CellVdecAttr> attr)
{ {
cellVdec.Warning("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.addr(), attr.addr()); cellVdec.Warning("cellVdecQueryAttrEx(type=*0x%x, attr=*0x%x)", type, attr);
return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr); return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr);
} }
int cellVdecOpen(vm::ptr<const CellVdecType> type, vm::ptr<const CellVdecResource> res, vm::ptr<const CellVdecCb> cb, vm::ptr<u32> handle) s32 cellVdecOpen(vm::ptr<const CellVdecType> type, vm::ptr<const CellVdecResource> res, vm::ptr<const CellVdecCb> cb, vm::ptr<u32> handle)
{ {
cellVdec.Warning("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellVdec.Warning("cellVdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
type.addr(), res.addr(), cb.addr(), handle.addr());
*handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellVdecOpenEx(vm::ptr<const CellVdecTypeEx> type, vm::ptr<const CellVdecResourceEx> res, vm::ptr<const CellVdecCb> cb, vm::ptr<u32> handle) s32 cellVdecOpenEx(vm::ptr<const CellVdecTypeEx> type, vm::ptr<const CellVdecResourceEx> res, vm::ptr<const CellVdecCb> cb, vm::ptr<u32> handle)
{ {
cellVdec.Warning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", cellVdec.Warning("cellVdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
type.addr(), res.addr(), cb.addr(), handle.addr());
*handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg));
return CELL_OK; return CELL_OK;
} }
int cellVdecClose(u32 handle) s32 cellVdecClose(u32 handle)
{ {
cellVdec.Warning("cellVdecClose(handle=%d)", handle); cellVdec.Warning("cellVdecClose(handle=0x%x)", handle);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -620,12 +614,13 @@ int cellVdecClose(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellVdecStartSeq(u32 handle) s32 cellVdecStartSeq(u32 handle)
{ {
cellVdec.Log("cellVdecStartSeq(handle=%d)", handle); cellVdec.Log("cellVdecStartSeq(handle=0x%x)", handle);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -634,12 +629,13 @@ int cellVdecStartSeq(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellVdecEndSeq(u32 handle) s32 cellVdecEndSeq(u32 handle)
{ {
cellVdec.Warning("cellVdecEndSeq(handle=%d)", handle); cellVdec.Warning("cellVdecEndSeq(handle=0x%x)", handle);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -648,16 +644,22 @@ int cellVdecEndSeq(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdecAuInfo> auInfo) s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdecAuInfo> auInfo)
{ {
cellVdec.Log("cellVdecDecodeAu(handle=%d, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.addr()); cellVdec.Log("cellVdecDecodeAu(handle=0x%x, mode=%d, auInfo=*0x%x)", handle, mode, auInfo);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec || mode > CELL_VDEC_DEC_MODE_PB_SKIP)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
if (mode != CELL_VDEC_DEC_MODE_NORMAL)
{
cellVdec.Fatal("cellVdecDecodeAu(): unsupported decoding mode (%d)", mode);
}
// TODO: check info // TODO: check info
VdecTask task(vdecDecodeAu); VdecTask task(vdecDecodeAu);
task.mode = mode; task.mode = mode;
@ -672,12 +674,13 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::ptr<const CellVdec
return CELL_OK; return CELL_OK;
} }
int cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::ptr<u8> outBuff) s32 cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::ptr<u8> outBuff)
{ {
cellVdec.Log("cellVdecGetPicture(handle=%d, format_addr=0x%x, outBuff_addr=0x%x)", handle, format.addr(), outBuff.addr()); cellVdec.Log("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec || !format)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -703,9 +706,25 @@ int cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::
if (outBuff) if (outBuff)
{ {
if (format->formatType != CELL_VDEC_PICFMT_YUV420_PLANAR) const auto f = vdec->ctx->pix_fmt;
const auto w = vdec->ctx->width;
const auto h = vdec->ctx->height;
auto out_f = AV_PIX_FMT_YUV420P;
std::unique_ptr<u8[]> alpha_plane;
switch (const u32 type = format->formatType)
{ {
cellVdec.Fatal("cellVdecGetPicture: unknown formatType(%d)", format->formatType); case CELL_VDEC_PICFMT_ARGB32_ILV: out_f = AV_PIX_FMT_ARGB; alpha_plane.reset(new u8[w * h]); break;
case CELL_VDEC_PICFMT_RGBA32_ILV: out_f = AV_PIX_FMT_RGBA; alpha_plane.reset(new u8[w * h]); break;
case CELL_VDEC_PICFMT_UYVY422_ILV: out_f = AV_PIX_FMT_UYVY422; break;
case CELL_VDEC_PICFMT_YUV420_PLANAR: out_f = AV_PIX_FMT_YUV420P; break;
default:
{
cellVdec.Fatal("cellVdecGetPicture: unknown formatType(%d)", type);
}
} }
if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709) if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709)
@ -713,26 +732,79 @@ int cellVdecGetPicture(u32 handle, vm::ptr<const CellVdecPicFormat> format, vm::
cellVdec.Fatal("cellVdecGetPicture: unknown colorMatrixType(%d)", format->colorMatrixType); cellVdec.Fatal("cellVdecGetPicture: unknown colorMatrixType(%d)", format->colorMatrixType);
} }
const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128); if (alpha_plane)
// TODO: zero padding bytes
int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame->data, frame->linesize, vdec->ctx->pix_fmt, frame->width, frame->height, 1);
if (err < 0)
{ {
cellVdec.Fatal("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err); memset(alpha_plane.get(), format->alpha, w * h);
} }
auto in_f = AV_PIX_FMT_YUV420P;
switch (f)
{
case AV_PIX_FMT_YUV420P: in_f = alpha_plane ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; break;
default:
{
cellVdec.Fatal("cellVdecGetPicture: unknown pix_fmt(%d)", f);
}
}
std::unique_ptr<SwsContext, void(*)(SwsContext*)> sws(sws_getContext(w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL), sws_freeContext);
u8* in_data[4] = { frame->data[0], frame->data[1], frame->data[2], alpha_plane.get() };
int in_line[4] = { frame->linesize[0], frame->linesize[1], frame->linesize[2], w * 1 };
u8* out_data[4] = { outBuff.get_ptr() };
int out_line[4] = { w * 4 };
if (!alpha_plane)
{
out_data[1] = out_data[0] + w * h;
out_data[2] = out_data[0] + w * h * 5 / 4;
out_line[0] = w;
out_line[1] = w / 2;
out_line[2] = w / 2;
}
sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line);
//const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128);
//// TODO: zero padding bytes
//int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame->data, frame->linesize, vdec->ctx->pix_fmt, frame->width, frame->height, 1);
//if (err < 0)
//{
// cellVdec.Fatal("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err);
//}
} }
return CELL_OK; return CELL_OK;
} }
int cellVdecGetPicItem(u32 handle, vm::ptr<u32> picItem_ptr) s32 _nid_a21aa896(PPUThread& CPU, u32 handle, vm::ptr<const CellVdecPicFormat2> format2, vm::ptr<u8> outBuff, u32 arg4)
{ {
cellVdec.Log("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.addr()); cellVdec.Warning("_nid_a21aa896(handle=0x%x, format2=*0x%x, outBuff=*0x%x, arg4=*0x%x)", handle, format2, outBuff, arg4);
std::shared_ptr<VideoDecoder> vdec; if (arg4 || format2->unk0 || format2->unk1)
if (!Emu.GetIdManager().GetIDData(handle, vdec)) {
cellVdec.Fatal("_nid_a21aa896(): unknown arguments (arg4=*0x%x, unk0=0x%x, unk1=0x%x)", arg4, format2->unk0, format2->unk1);
}
vm::stackvar<CellVdecPicFormat> format(CPU);
format->formatType = format2->formatType;
format->colorMatrixType = format2->colorMatrixType;
format->alpha = format2->alpha;
return cellVdecGetPicture(handle, format, outBuff);
}
s32 cellVdecGetPicItem(u32 handle, vm::ptr<vm::bptr<CellVdecPicItem>> picItem)
{
cellVdec.Log("cellVdecGetPicItem(handle=0x%x, picItem=**0x%x)", handle, picItem);
const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!vdec)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -746,7 +818,7 @@ int cellVdecGetPicItem(u32 handle, vm::ptr<u32> picItem_ptr)
AVFrame& frame = *vf.data; AVFrame& frame = *vf.data;
auto info = vm::ptr<CellVdecPicItem>::make(vdec->memAddr + vdec->memBias); const auto info = vm::ptr<CellVdecPicItem>::make(vdec->memAddr + vdec->memBias);
vdec->memBias += 512; vdec->memBias += 512;
if (vdec->memBias + 512 > vdec->memSize) if (vdec->memBias + 512 > vdec->memSize)
@ -867,16 +939,17 @@ int cellVdecGetPicItem(u32 handle, vm::ptr<u32> picItem_ptr)
cellVdec.Fatal("cellVdecGetPicItem(MPEG2)"); cellVdec.Fatal("cellVdecGetPicItem(MPEG2)");
} }
*picItem_ptr = info.addr(); *picItem = info;
return CELL_OK; return CELL_OK;
} }
int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc) s32 cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
{ {
cellVdec.Log("cellVdecSetFrameRate(handle=%d, frc=0x%x)", handle, frc); cellVdec.Log("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc);
std::shared_ptr<VideoDecoder> vdec; const auto vdec = Emu.GetIdManager().GetIDData<VideoDecoder>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vdec))
if (!vdec)
{ {
return CELL_VDEC_ERROR_ARG; return CELL_VDEC_ERROR_ARG;
} }
@ -900,6 +973,7 @@ Module cellVdec("cellVdec", []()
REG_FUNC(cellVdec, cellVdecEndSeq); REG_FUNC(cellVdec, cellVdecEndSeq);
REG_FUNC(cellVdec, cellVdecDecodeAu); REG_FUNC(cellVdec, cellVdecDecodeAu);
REG_FUNC(cellVdec, cellVdecGetPicture); REG_FUNC(cellVdec, cellVdecGetPicture);
REG_UNNAMED(cellVdec, a21aa896);
REG_FUNC(cellVdec, cellVdecGetPicItem); REG_FUNC(cellVdec, cellVdecGetPicItem);
REG_FUNC(cellVdec, cellVdecSetFrameRate); REG_FUNC(cellVdec, cellVdecSetFrameRate);
}); });

View file

@ -12,7 +12,7 @@ enum
CELL_VDEC_ERROR_FATAL = 0x80610180, CELL_VDEC_ERROR_FATAL = 0x80610180,
}; };
enum CellVdecCodecType enum CellVdecCodecType : u32
{ {
CELL_VDEC_CODEC_TYPE_MPEG2 = 0x00000000, CELL_VDEC_CODEC_TYPE_MPEG2 = 0x00000000,
CELL_VDEC_CODEC_TYPE_AVC = 0x00000001, CELL_VDEC_CODEC_TYPE_AVC = 0x00000001,
@ -20,7 +20,7 @@ enum CellVdecCodecType
}; };
// Callback Messages // Callback Messages
enum CellVdecMsgType enum CellVdecMsgType : u32
{ {
CELL_VDEC_MSG_TYPE_AUDONE, // decoding finished CELL_VDEC_MSG_TYPE_AUDONE, // decoding finished
CELL_VDEC_MSG_TYPE_PICOUT, // picture done CELL_VDEC_MSG_TYPE_PICOUT, // picture done
@ -37,7 +37,7 @@ enum CellVdecDecodeMode : u32
}; };
// Output Picture Format Type // Output Picture Format Type
enum CellVdecPicFormatType enum CellVdecPicFormatType : u32
{ {
CELL_VDEC_PICFMT_ARGB32_ILV, CELL_VDEC_PICFMT_ARGB32_ILV,
CELL_VDEC_PICFMT_RGBA32_ILV, CELL_VDEC_PICFMT_RGBA32_ILV,
@ -46,13 +46,13 @@ enum CellVdecPicFormatType
}; };
// Output Color Matrix Coef // Output Color Matrix Coef
enum CellVdecColorMatrixType enum CellVdecColorMatrixType : u32
{ {
CELL_VDEC_COLOR_MATRIX_TYPE_BT601, CELL_VDEC_COLOR_MATRIX_TYPE_BT601,
CELL_VDEC_COLOR_MATRIX_TYPE_BT709, CELL_VDEC_COLOR_MATRIX_TYPE_BT709,
}; };
enum CellVdecPicAttr enum CellVdecPicAttr : u32
{ {
CELL_VDEC_PICITEM_ATTR_NORMAL, CELL_VDEC_PICITEM_ATTR_NORMAL,
CELL_VDEC_PICITEM_ATTR_SKIPPED, CELL_VDEC_PICITEM_ATTR_SKIPPED,
@ -163,6 +163,15 @@ struct CellVdecPicFormat
u8 alpha; u8 alpha;
}; };
struct CellVdecPicFormat2
{
be_t<CellVdecPicFormatType> formatType;
be_t<CellVdecColorMatrixType> colorMatrixType;
be_t<u32> unk0;
u8 alpha;
be_t<u32> unk1;
};
typedef u32(CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg); typedef u32(CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg);
// Callback Function Information // Callback Function Information
@ -349,8 +358,6 @@ struct CellVdecAvcInfo
be_t<u64> reserved[2]; be_t<u64> reserved[2];
}; };
const int sz = sizeof(CellVdecAvcInfo);
// DIVX Profile // DIVX Profile
enum DIVX_level : u8 enum DIVX_level : u8
{ {

View file

@ -13,9 +13,9 @@ extern "C"
extern Module cellVpost; extern Module cellVpost;
int cellVpostQueryAttr(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<CellVpostAttr> attr) s32 cellVpostQueryAttr(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<CellVpostAttr> attr)
{ {
cellVpost.Warning("cellVpostQueryAttr(cfgParam_addr=0x%x, attr_addr=0x%x)", cfgParam.addr(), attr.addr()); cellVpost.Warning("cellVpostQueryAttr(cfgParam=*0x%x, attr=*0x%x)", cfgParam, attr);
// TODO: check cfgParam and output values // TODO: check cfgParam and output values
@ -37,32 +37,31 @@ u32 vpostOpen(VpostInstance* data)
return id; return id;
} }
int cellVpostOpen(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<const CellVpostResource> resource, vm::ptr<u32> handle) s32 cellVpostOpen(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<const CellVpostResource> resource, vm::ptr<u32> handle)
{ {
cellVpost.Warning("cellVpostOpen(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", cellVpost.Warning("cellVpostOpen(cfgParam=*0x%x, resource=*0x%x, handle=*0x%x)", cfgParam, resource, handle);
cfgParam.addr(), resource.addr(), handle.addr());
// TODO: check values // TODO: check values
*handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); *handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV));
return CELL_OK; return CELL_OK;
} }
int cellVpostOpenEx(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<const CellVpostResourceEx> resource, vm::ptr<u32> handle) s32 cellVpostOpenEx(vm::ptr<const CellVpostCfgParam> cfgParam, vm::ptr<const CellVpostResourceEx> resource, vm::ptr<u32> handle)
{ {
cellVpost.Warning("cellVpostOpenEx(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", cellVpost.Warning("cellVpostOpenEx(cfgParam=*0x%x, resource=*0x%x, handle=*0x%x)", cfgParam, resource, handle);
cfgParam.addr(), resource.addr(), handle.addr());
// TODO: check values // TODO: check values
*handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); *handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV));
return CELL_OK; return CELL_OK;
} }
int cellVpostClose(u32 handle) s32 cellVpostClose(u32 handle)
{ {
cellVpost.Warning("cellVpostClose(handle=0x%x)", handle); cellVpost.Warning("cellVpostClose(handle=0x%x)", handle);
std::shared_ptr<VpostInstance> vpost; const auto vpost = Emu.GetIdManager().GetIDData<VpostInstance>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vpost))
if (!vpost)
{ {
return CELL_VPOST_ERROR_C_ARG_HDL_INVALID; return CELL_VPOST_ERROR_C_ARG_HDL_INVALID;
} }
@ -71,14 +70,13 @@ int cellVpostClose(u32 handle)
return CELL_OK; return CELL_OK;
} }
int cellVpostExec(u32 handle, vm::ptr<const u8> inPicBuff, vm::ptr<const CellVpostCtrlParam> ctrlParam, s32 cellVpostExec(u32 handle, vm::ptr<const u8> inPicBuff, vm::ptr<const CellVpostCtrlParam> ctrlParam, vm::ptr<u8> outPicBuff, vm::ptr<CellVpostPictureInfo> picInfo)
vm::ptr<u8> outPicBuff, vm::ptr<CellVpostPictureInfo> picInfo)
{ {
cellVpost.Log("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)", cellVpost.Log("cellVpostExec(handle=0x%x, inPicBuff=*0x%x, ctrlParam=*0x%x, outPicBuff=*0x%x, picInfo=*0x%x)", handle, inPicBuff, ctrlParam, outPicBuff, picInfo);
handle, inPicBuff.addr(), ctrlParam.addr(), outPicBuff.addr(), picInfo.addr());
std::shared_ptr<VpostInstance> vpost; const auto vpost = Emu.GetIdManager().GetIDData<VpostInstance>(handle);
if (!Emu.GetIdManager().GetIDData(handle, vpost))
if (!vpost)
{ {
return CELL_VPOST_ERROR_E_ARG_HDL_INVALID; return CELL_VPOST_ERROR_E_ARG_HDL_INVALID;
} }

View file

@ -23,7 +23,7 @@ std::vector<SSPlayer> ssp;
int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, vm::ptr<float> addr, u32 samples) int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, vm::ptr<float> addr, u32 samples)
{ {
libmixer.Log("cellAANAddData(handle=%d, port=%d, offset=0x%x, addr_addr=0x%x, samples=%d)", aan_handle, aan_port, offset, addr.addr(), samples); libmixer.Log("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr_addr=0x%x, samples=%d)", aan_handle, aan_port, offset, addr.addr(), samples);
u32 type = aan_port >> 16; u32 type = aan_port >> 16;
u32 port = aan_port & 0xffff; u32 port = aan_port & 0xffff;
@ -44,7 +44,7 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, vm::ptr<float> addr
if (aan_handle != 0x11111111 || samples != 256 || !type || offset != 0) if (aan_handle != 0x11111111 || samples != 256 || !type || offset != 0)
{ {
libmixer.Error("cellAANAddData(handle=%d, port=%d, offset=0x%x, addr_addr=0x%x, samples=%d): invalid parameters", aan_handle, aan_port, offset, addr.addr(), samples); libmixer.Error("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr_addr=0x%x, samples=%d): invalid parameters", aan_handle, aan_port, offset, addr.addr(), samples);
return CELL_LIBMIXER_ERROR_INVALID_PARAMATER; return CELL_LIBMIXER_ERROR_INVALID_PARAMATER;
} }
@ -104,7 +104,7 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, vm::ptr<float> addr
int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
{ {
libmixer.Warning("cellAANConnect(receive=%d, receivePortNo=%d, source=%d, sourcePortNo=%d)", libmixer.Warning("cellAANConnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcePortNo=0x%x)",
receive, receivePortNo, source, sourcePortNo); receive, receivePortNo, source, sourcePortNo);
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -122,7 +122,7 @@ int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
{ {
libmixer.Warning("cellAANDisconnect(receive=%d, receivePortNo=%d, source=%d, sourcePortNo=%d)", libmixer.Warning("cellAANDisconnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcePortNo=0x%x)",
receive, receivePortNo, source, sourcePortNo); receive, receivePortNo, source, sourcePortNo);
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -165,7 +165,7 @@ int cellSSPlayerCreate(vm::ptr<u32> handle, vm::ptr<CellSSPlayerConfig> config)
int cellSSPlayerRemove(u32 handle) int cellSSPlayerRemove(u32 handle)
{ {
libmixer.Warning("cellSSPlayerRemove(handle=%d)", handle); libmixer.Warning("cellSSPlayerRemove(handle=0x%x)", handle);
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -184,7 +184,7 @@ int cellSSPlayerRemove(u32 handle)
int cellSSPlayerSetWave(u32 handle, vm::ptr<CellSSPlayerWaveParam> waveInfo, vm::ptr<CellSSPlayerCommonParam> commonInfo) int cellSSPlayerSetWave(u32 handle, vm::ptr<CellSSPlayerWaveParam> waveInfo, vm::ptr<CellSSPlayerCommonParam> commonInfo)
{ {
libmixer.Warning("cellSSPlayerSetWave(handle=%d, waveInfo_addr=0x%x, commonInfo_addr=0x%x)", libmixer.Warning("cellSSPlayerSetWave(handle=0x%x, waveInfo_addr=0x%x, commonInfo_addr=0x%x)",
handle, waveInfo.addr(), commonInfo.addr()); handle, waveInfo.addr(), commonInfo.addr());
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -208,7 +208,7 @@ int cellSSPlayerSetWave(u32 handle, vm::ptr<CellSSPlayerWaveParam> waveInfo, vm:
int cellSSPlayerPlay(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info) int cellSSPlayerPlay(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info)
{ {
libmixer.Warning("cellSSPlayerPlay(handle=%d, info_addr=0x%x)", handle, info.addr()); libmixer.Warning("cellSSPlayerPlay(handle=0x%x, info_addr=0x%x)", handle, info.addr());
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -232,7 +232,7 @@ int cellSSPlayerPlay(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info)
int cellSSPlayerStop(u32 handle, u32 mode) int cellSSPlayerStop(u32 handle, u32 mode)
{ {
libmixer.Warning("cellSSPlayerStop(handle=%d, mode=0x%x)", handle, mode); libmixer.Warning("cellSSPlayerStop(handle=0x%x, mode=0x%x)", handle, mode);
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -251,7 +251,7 @@ int cellSSPlayerStop(u32 handle, u32 mode)
int cellSSPlayerSetParam(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info) int cellSSPlayerSetParam(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info)
{ {
libmixer.Warning("cellSSPlayerSetParam(handle=%d, info_addr=0x%x)", handle, info.addr()); libmixer.Warning("cellSSPlayerSetParam(handle=0x%x, info_addr=0x%x)", handle, info.addr());
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -274,7 +274,7 @@ int cellSSPlayerSetParam(u32 handle, vm::ptr<CellSSPlayerRuntimeInfo> info)
int cellSSPlayerGetState(u32 handle) int cellSSPlayerGetState(u32 handle)
{ {
libmixer.Warning("cellSSPlayerGetState(handle=%d)", handle); libmixer.Warning("cellSSPlayerGetState(handle=0x%x)", handle);
std::lock_guard<std::mutex> lock(mixer_mutex); std::lock_guard<std::mutex> lock(mixer_mutex);
@ -319,8 +319,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float); port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float);
port.tag = 0; port.tag = 0;
port.level = 1.0f; port.level = 1.0f;
port.level_set = 1.0f; port.level_set.data = { 1.0f, 0.0f };
port.level_inc = 0.0f;
libmixer.Warning("*** audio port opened (port=%d)", g_surmx.audio_port); libmixer.Warning("*** audio port opened (port=%d)", g_surmx.audio_port);

View file

@ -5,7 +5,7 @@
#include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/SysCalls/lv2/sys_process.h"
#include "Emu/FS/VFS.h" #include "Emu/FS/VFS.h"
#include "Utilities/rFile.h" #include "Utilities/File.h"
#include "Emu/FS/vfsDir.h" #include "Emu/FS/vfsDir.h"
#include "Crypto/unedat.h" #include "Crypto/unedat.h"
#include "sceNp.h" #include "sceNp.h"
@ -140,8 +140,8 @@ int npDrmIsAvailable(u32 k_licensee_addr, vm::ptr<const char> drm_path)
if (DecryptEDAT(enc_drm_path_local, dec_drm_path_local, 8, rap_path_local, k_licensee, false) >= 0) if (DecryptEDAT(enc_drm_path_local, dec_drm_path_local, 8, rap_path_local, k_licensee, false) >= 0)
{ {
// If decryption succeeds, replace the encrypted file with it. // If decryption succeeds, replace the encrypted file with it.
rRemoveFile(enc_drm_path_local); fs::remove_file(enc_drm_path_local);
rRename(dec_drm_path_local, enc_drm_path_local); fs::rename(dec_drm_path_local, enc_drm_path_local);
} }
return CELL_OK; return CELL_OK;

View file

@ -79,7 +79,7 @@ static sceNpTrophyInternalContext& getContext(u32 context) {
// Functions // Functions
int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options) int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options)
{ {
sceNpTrophy.Log("sceNpTrophyInit(pool_addr=0x%x, poolSize=%d, containerId=%d, options=0x%llx)", pool_addr, poolSize, containerId, options); sceNpTrophy.Log("sceNpTrophyInit(pool_addr=0x%x, poolSize=%d, containerId=0x%x, options=0x%llx)", pool_addr, poolSize, containerId, options);
if (sceNpTrophyInstance.m_bInitialized) if (sceNpTrophyInstance.m_bInitialized)
return SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED; return SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED;
@ -145,7 +145,7 @@ int sceNpTrophyCreateHandle(vm::ptr<u32> handle)
int sceNpTrophyRegisterContext(u32 context, u32 handle, vm::ptr<SceNpTrophyStatusCallback> statusCb, u32 arg_addr, u64 options) int sceNpTrophyRegisterContext(u32 context, u32 handle, vm::ptr<SceNpTrophyStatusCallback> statusCb, u32 arg_addr, u64 options)
{ {
sceNpTrophy.Warning("sceNpTrophyRegisterContext(context=%d, handle=%d, statusCb_addr=0x%x, arg_addr=0x%x, options=0x%llx)", sceNpTrophy.Warning("sceNpTrophyRegisterContext(context=0x%x, handle=0x%x, statusCb_addr=0x%x, arg_addr=0x%x, options=0x%llx)",
context, handle, statusCb.addr(), arg_addr, options); context, handle, statusCb.addr(), arg_addr, options);
if (!(sceNpTrophyInstance.m_bInitialized)) if (!(sceNpTrophyInstance.m_bInitialized))
@ -224,7 +224,7 @@ int sceNpTrophySetSoundLevel()
int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64> reqspace, u64 options) int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64> reqspace, u64 options)
{ {
sceNpTrophy.Warning("sceNpTrophyGetRequiredDiskSpace(context=%d, handle=%d, reqspace_addr=0x%x, options=0x%llx)", sceNpTrophy.Warning("sceNpTrophyGetRequiredDiskSpace(context=0x%x, handle=0x%x, reqspace_addr=0x%x, options=0x%llx)",
context, handle, reqspace.addr(), options); context, handle, reqspace.addr(), options);
if (!sceNpTrophyInstance.m_bInitialized) if (!sceNpTrophyInstance.m_bInitialized)
@ -251,7 +251,7 @@ int sceNpTrophyDestroyContext()
int sceNpTrophyAbortHandle(u32 handle) int sceNpTrophyAbortHandle(u32 handle)
{ {
sceNpTrophy.Todo("sceNpTrophyAbortHandle(handle=%d)", handle); sceNpTrophy.Todo("sceNpTrophyAbortHandle(handle=0x%x)", handle);
// TODO: ? // TODO: ?
@ -263,7 +263,7 @@ int sceNpTrophyAbortHandle(u32 handle)
int sceNpTrophyGetGameInfo(u32 context, u32 handle, vm::ptr<SceNpTrophyGameDetails> details, vm::ptr<SceNpTrophyGameData> data) int sceNpTrophyGetGameInfo(u32 context, u32 handle, vm::ptr<SceNpTrophyGameDetails> details, vm::ptr<SceNpTrophyGameData> data)
{ {
sceNpTrophy.Warning("sceNpTrophyGetGameInfo(context=%d, handle=%d, details_addr=0x%x, data_addr=0x%x)", sceNpTrophy.Warning("sceNpTrophyGetGameInfo(context=0x%x, handle=0x%x, details_addr=0x%x, data_addr=0x%x)",
context, handle, details.addr(), data.addr()); context, handle, details.addr(), data.addr());
if (!sceNpTrophyInstance.m_bInitialized) if (!sceNpTrophyInstance.m_bInitialized)
@ -321,7 +321,7 @@ int sceNpTrophyDestroyHandle()
int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<u32> platinumId) int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<u32> platinumId)
{ {
sceNpTrophy.Warning("sceNpTrophyUnlockTrophy(context=%d, handle=%d, trophyId=%d, platinumId_addr=0x%x)", sceNpTrophy.Warning("sceNpTrophyUnlockTrophy(context=0x%x, handle=0x%x, trophyId=%d, platinumId_addr=0x%x)",
context, handle, trophyId, platinumId.addr()); context, handle, trophyId, platinumId.addr());
if (!sceNpTrophyInstance.m_bInitialized) if (!sceNpTrophyInstance.m_bInitialized)
@ -358,7 +358,7 @@ int sceNpTrophyTerm()
int sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceNpTrophyFlagArray> flags, vm::ptr<u32> count) int sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceNpTrophyFlagArray> flags, vm::ptr<u32> count)
{ {
sceNpTrophy.Warning("sceNpTrophyGetTrophyUnlockState(context=%d, handle=%d, flags_addr=0x%x, count_addr=0x%x)", sceNpTrophy.Warning("sceNpTrophyGetTrophyUnlockState(context=0x%x, handle=0x%x, flags_addr=0x%x, count_addr=0x%x)",
context, handle, flags.addr(), count.addr()); context, handle, flags.addr(), count.addr());
if (!sceNpTrophyInstance.m_bInitialized) if (!sceNpTrophyInstance.m_bInitialized)
@ -395,7 +395,7 @@ int sceNpTrophyGetTrophyIcon()
int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceNpTrophyDetails> details, vm::ptr<SceNpTrophyData> data) int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceNpTrophyDetails> details, vm::ptr<SceNpTrophyData> data)
{ {
sceNpTrophy.Warning("sceNpTrophyGetTrophyInfo(context=%d, handle=%d, trophyId=%d, details_addr=0x%x, data_addr=0x%x)", sceNpTrophy.Warning("sceNpTrophyGetTrophyInfo(context=0x%x, handle=0x%x, trophyId=%d, details_addr=0x%x, data_addr=0x%x)",
context, handle, trophyId, details.addr(), data.addr()); context, handle, trophyId, details.addr(), data.addr());
if (!sceNpTrophyInstance.m_bInitialized) if (!sceNpTrophyInstance.m_bInitialized)

View file

@ -117,7 +117,7 @@ s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attri
lwmutex->lock_var = { { lwmutex::free, lwmutex::zero } }; lwmutex->lock_var = { { lwmutex::free, lwmutex::zero } };
lwmutex->attribute = attr->recursive | attr->protocol; lwmutex->attribute = attr->recursive | attr->protocol;
lwmutex->recursive_count = 0; lwmutex->recursive_count = 0;
lwmutex->sleep_queue = Emu.GetIdManager().GetNewID(lw); lwmutex->sleep_queue = Emu.GetIdManager().GetNewID(lw, TYPE_LWMUTEX);
return CELL_OK; return CELL_OK;
} }
@ -501,7 +501,7 @@ s32 sys_lwcond_signal_all(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond)
s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id) s32 sys_lwcond_signal_to(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u32 ppu_thread_id)
{ {
sysPrxForUser.Log("sys_lwcond_signal_to(lwcond=*0x%x, ppu_thread_id=%d)", lwcond, ppu_thread_id); sysPrxForUser.Log("sys_lwcond_signal_to(lwcond=*0x%x, ppu_thread_id=0x%x)", lwcond, ppu_thread_id);
const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex; const vm::ptr<sys_lwmutex_t> lwmutex = lwcond->lwmutex;
@ -579,7 +579,7 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
lwmutex->recursive_count = 0; lwmutex->recursive_count = 0;
// call the syscall // call the syscall
s32 res = _sys_lwcond_queue_wait(lwcond->lwcond_queue, lwmutex->sleep_queue, timeout); s32 res = _sys_lwcond_queue_wait(CPU, lwcond->lwcond_queue, lwmutex->sleep_queue, timeout);
if (res == CELL_OK || res == CELL_ESRCH) if (res == CELL_OK || res == CELL_ESRCH)
{ {
@ -821,7 +821,7 @@ s64 _sys_process_at_Exitspawn()
s32 sys_interrupt_thread_disestablish(PPUThread& CPU, u32 ih) s32 sys_interrupt_thread_disestablish(PPUThread& CPU, u32 ih)
{ {
sysPrxForUser.Todo("sys_interrupt_thread_disestablish(ih=%d)", ih); sysPrxForUser.Todo("sys_interrupt_thread_disestablish(ih=0x%x)", ih);
return _sys_interrupt_thread_disestablish(ih, vm::stackvar<be_t<u64>>(CPU)); return _sys_interrupt_thread_disestablish(ih, vm::stackvar<be_t<u64>>(CPU));
} }
@ -982,6 +982,13 @@ vm::ptr<char> _sys_strcat(vm::ptr<char> dest, vm::ptr<const char> source)
return dest; return dest;
} }
vm::ptr<const char> _sys_strchr(vm::ptr<const char> str, s32 ch)
{
sysPrxForUser.Log("_sys_strchr(str=*0x%x, ch=0x%x)", str, ch);
return vm::ptr<const char>::make(vm::get_addr(strchr(str.get_ptr(), ch)));
}
vm::ptr<char> _sys_strncat(vm::ptr<char> dest, vm::ptr<const char> source, u32 len) vm::ptr<char> _sys_strncat(vm::ptr<char> dest, vm::ptr<const char> source, u32 len)
{ {
sysPrxForUser.Log("_sys_strncat(dest=*0x%x, source=*0x%x, len=%d)", dest, source, len); sysPrxForUser.Log("_sys_strncat(dest=*0x%x, source=*0x%x, len=%d)", dest, source, len);
@ -1012,7 +1019,7 @@ vm::ptr<char> _sys_strncpy(vm::ptr<char> dest, vm::ptr<const char> source, u32 l
if (!dest || !source) if (!dest || !source)
{ {
return vm::ptr<char>::make(0); return vm::null;
} }
if (strncpy(dest.get_ptr(), source.get_ptr(), len) != dest.get_ptr()) if (strncpy(dest.get_ptr(), source.get_ptr(), len) != dest.get_ptr())
@ -1053,7 +1060,7 @@ s32 _sys_spu_printf_finalize()
s32 _sys_spu_printf_attach_group(PPUThread& CPU, u32 group) s32 _sys_spu_printf_attach_group(PPUThread& CPU, u32 group)
{ {
sysPrxForUser.Warning("_sys_spu_printf_attach_group(group=%d)", group); sysPrxForUser.Warning("_sys_spu_printf_attach_group(group=0x%x)", group);
if (!spu_printf_agcb) if (!spu_printf_agcb)
{ {
@ -1065,7 +1072,7 @@ s32 _sys_spu_printf_attach_group(PPUThread& CPU, u32 group)
s32 _sys_spu_printf_detach_group(PPUThread& CPU, u32 group) s32 _sys_spu_printf_detach_group(PPUThread& CPU, u32 group)
{ {
sysPrxForUser.Warning("_sys_spu_printf_detach_group(group=%d)", group); sysPrxForUser.Warning("_sys_spu_printf_detach_group(group=0x%x)", group);
if (!spu_printf_dgcb) if (!spu_printf_dgcb)
{ {
@ -1077,7 +1084,7 @@ s32 _sys_spu_printf_detach_group(PPUThread& CPU, u32 group)
s32 _sys_spu_printf_attach_thread(PPUThread& CPU, u32 thread) s32 _sys_spu_printf_attach_thread(PPUThread& CPU, u32 thread)
{ {
sysPrxForUser.Warning("_sys_spu_printf_attach_thread(thread=%d)", thread); sysPrxForUser.Warning("_sys_spu_printf_attach_thread(thread=0x%x)", thread);
if (!spu_printf_atcb) if (!spu_printf_atcb)
{ {
@ -1089,7 +1096,7 @@ s32 _sys_spu_printf_attach_thread(PPUThread& CPU, u32 thread)
s32 _sys_spu_printf_detach_thread(PPUThread& CPU, u32 thread) s32 _sys_spu_printf_detach_thread(PPUThread& CPU, u32 thread)
{ {
sysPrxForUser.Warning("_sys_spu_printf_detach_thread(thread=%d)", thread); sysPrxForUser.Warning("_sys_spu_printf_detach_thread(thread=0x%x)", thread);
if (!spu_printf_dtcb) if (!spu_printf_dtcb)
{ {
@ -1149,7 +1156,7 @@ s32 _sys_printf(vm::ptr<const char> fmt) // va_args...
sysPrxForUser.Todo("_sys_printf(fmt=*0x%x, ...)", fmt); sysPrxForUser.Todo("_sys_printf(fmt=*0x%x, ...)", fmt);
// probably, assertion failed // probably, assertion failed
sysPrxForUser.Warning("_sys_printf: \n%s", fmt.get_ptr()); sysPrxForUser.Fatal("_sys_printf: \n%s", fmt.get_ptr());
Emu.Pause(); Emu.Pause();
return CELL_OK; return CELL_OK;
} }
@ -1210,6 +1217,65 @@ void sys_spinlock_unlock(vm::ptr<atomic_t<u32>> lock)
g_sys_spinlock_wm.notify(lock.addr()); g_sys_spinlock_wm.notify(lock.addr());
} }
s32 sys_ppu_thread_create(PPUThread& CPU, vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr<const char> threadname)
{
sysPrxForUser.Warning("sys_ppu_thread_create(thread_id=*0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=*0x%x)", thread_id, entry, arg, prio, stacksize, flags, threadname);
// (allocate TLS)
// (return CELL_ENOMEM if failed)
// ...
vm::stackvar<ppu_thread_param_t> attr(CPU);
attr->entry = entry;
attr->tls = 0;
// call the syscall
if (s32 res = _sys_ppu_thread_create(thread_id, attr, arg, 0, prio, stacksize, flags, threadname))
{
return res;
}
// run the thread
return flags & SYS_PPU_THREAD_CREATE_INTERRUPT ? CELL_OK : sys_ppu_thread_start(static_cast<u32>(*thread_id));
}
s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr<u64> thread_id)
{
sysPrxForUser.Log("sys_ppu_thread_get_id(thread_id=*0x%x)", thread_id);
*thread_id = CPU.GetId();
return CELL_OK;
}
void sys_ppu_thread_exit(PPUThread& CPU, u64 val)
{
sysPrxForUser.Log("sys_ppu_thread_exit(val=0x%llx)", val);
// (call registered atexit functions)
// (deallocate TLS)
// ...
// call the syscall
_sys_ppu_thread_exit(CPU, val);
}
std::mutex g_once_mutex;
void sys_ppu_thread_once(PPUThread& CPU, vm::ptr<atomic_t<u32>> once_ctrl, vm::ptr<void()> init)
{
sysPrxForUser.Warning("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init);
std::lock_guard<std::mutex> lock(g_once_mutex);
if (once_ctrl->compare_and_swap_test(be_t<u32>::make(SYS_PPU_THREAD_ONCE_INIT), be_t<u32>::make(SYS_PPU_THREAD_DONE_INIT)))
{
// call init function using current thread context
init(CPU);
}
}
Module sysPrxForUser("sysPrxForUser", []() Module sysPrxForUser("sysPrxForUser", []()
{ {
g_tls_start = 0; g_tls_start = 0;
@ -1304,6 +1370,7 @@ Module sysPrxForUser("sysPrxForUser", []()
REG_FUNC(sysPrxForUser, _sys_strcmp); REG_FUNC(sysPrxForUser, _sys_strcmp);
REG_FUNC(sysPrxForUser, _sys_strncmp); REG_FUNC(sysPrxForUser, _sys_strncmp);
REG_FUNC(sysPrxForUser, _sys_strcat); REG_FUNC(sysPrxForUser, _sys_strcat);
REG_FUNC(sysPrxForUser, _sys_strchr);
REG_FUNC(sysPrxForUser, _sys_strncat); REG_FUNC(sysPrxForUser, _sys_strncat);
REG_FUNC(sysPrxForUser, _sys_strcpy); REG_FUNC(sysPrxForUser, _sys_strcpy);
REG_FUNC(sysPrxForUser, _sys_strncpy); REG_FUNC(sysPrxForUser, _sys_strncpy);

View file

@ -19,7 +19,7 @@ extern "C"
extern Module sys_net; extern Module sys_net;
vm::ptr<s32> g_lastError = vm::ptr<s32>::make(0); vm::ptr<s32> g_lastError = vm::null;
// Auxiliary Functions // Auxiliary Functions
@ -478,7 +478,7 @@ s32 sys_net_finalize_network()
{ {
sys_net.Warning("sys_net_initialize_network_ex()"); sys_net.Warning("sys_net_initialize_network_ex()");
Memory.Free(g_lastError.addr()); Memory.Free(g_lastError.addr());
g_lastError = vm::ptr<s32>::make(0); g_lastError = vm::null;
#ifdef _WIN32 #ifdef _WIN32
WSACleanup(); WSACleanup();
#endif #endif

View file

@ -1,75 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Utilities/Thread.h"
#include "lv2/sleep_queue.h"
#include "lv2/sys_lwmutex.h"
#include "lv2/sys_lwcond.h"
#include "lv2/sys_mutex.h"
#include "lv2/sys_cond.h"
#include "lv2/sys_semaphore.h"
#include "SyncPrimitivesManager.h"
SemaphoreAttributes SyncPrimManager::GetSemaphoreData(u32 id)
{
std::shared_ptr<semaphore_t> sem;
if (!Emu.GetIdManager().GetIDData(id, sem))
{
return{};
}
return{ std::string((const char*)&sem->name, 8), sem->value, sem->max };
}
LwMutexAttributes SyncPrimManager::GetLwMutexData(u32 id)
{
std::shared_ptr<sleep_queue_t> sq;
if (!Emu.GetIdManager().GetIDData(id, sq))
{
return{};
}
return{ std::string((const char*)&sq->name, 8) };
}
std::string SyncPrimManager::GetSyncPrimName(u32 id, IDType type)
{
switch (type)
{
case TYPE_LWCOND:
{
std::shared_ptr<lwcond_t> lw;
if (Emu.GetIdManager().GetIDData(id, lw))
{
return std::string((const char*)&lw->name, 8);
}
break;
}
case TYPE_MUTEX:
{
std::shared_ptr<mutex_t> mutex;
if (Emu.GetIdManager().GetIDData(id, mutex))
{
return std::string((const char*)&mutex->name, 8);
}
break;
}
case TYPE_COND:
{
std::shared_ptr<cond_t> cond;
if (Emu.GetIdManager().GetIDData(id, cond))
{
return std::string((const char*)&cond->name, 8);
}
break;
}
default: break;
}
LOG_ERROR(GENERAL, "SyncPrimManager::GetSyncPrimName(id=%d, type=%d) failed", id, type);
return "NOT_FOUND";
}

View file

@ -1,27 +0,0 @@
#pragma once
struct SemaphoreAttributes
{
std::string name;
s32 count;
s32 max_count;
};
struct LwMutexAttributes
{
std::string name;
};
class SyncPrimManager
{
private:
public:
SemaphoreAttributes GetSemaphoreData(u32 id);
LwMutexAttributes GetLwMutexData(u32 id);
std::string GetSyncPrimName(u32 id, IDType type);
void Close()
{
}
};

View file

@ -75,7 +75,7 @@ const ppu_func_caller sc_table[1024] =
null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, //32-40 UNS null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, null_func, //32-40 UNS
bind_func(sys_internal_ppu_thread_exit), //41 (0x029) bind_func(_sys_ppu_thread_exit), //41 (0x029)
null_func, //42 (0x02A) UNS null_func, //42 (0x02A) UNS
bind_func(sys_ppu_thread_yield), //43 (0x02B) bind_func(sys_ppu_thread_yield), //43 (0x02B)
bind_func(sys_ppu_thread_join), //44 (0x02C) bind_func(sys_ppu_thread_join), //44 (0x02C)
@ -86,8 +86,8 @@ const ppu_func_caller sc_table[1024] =
bind_func(sys_ppu_thread_get_stack_information), //49 (0x031) bind_func(sys_ppu_thread_get_stack_information), //49 (0x031)
null_func,//bind_func(sys_ppu_thread_stop), //50 (0x032) ROOT null_func,//bind_func(sys_ppu_thread_stop), //50 (0x032) ROOT
null_func,//bind_func(sys_ppu_thread_restart), //51 (0x033) ROOT null_func,//bind_func(sys_ppu_thread_restart), //51 (0x033) ROOT
null_func,//bind_func(sys_ppu_thread_create), //52 (0x034) DBG bind_func(_sys_ppu_thread_create), //52 (0x034) DBG
null_func,//bind_func(sys_ppu_thread_start), //53 (0x035) bind_func(sys_ppu_thread_start), //53 (0x035)
null_func,//bind_func(sys_ppu_...), //54 (0x036) ROOT null_func,//bind_func(sys_ppu_...), //54 (0x036) ROOT
null_func,//bind_func(sys_ppu_...), //55 (0x037) ROOT null_func,//bind_func(sys_ppu_...), //55 (0x037) ROOT
bind_func(sys_ppu_thread_rename), //56 (0x038) bind_func(sys_ppu_thread_rename), //56 (0x038)
@ -888,34 +888,32 @@ const ppu_func_caller sc_table[1024] =
void null_func(PPUThread& CPU) void null_func(PPUThread& CPU)
{ {
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", CPU.GPR[11], SysCalls::GetFuncName(CPU.GPR[11])); const auto code = CPU.GPR[11];
LOG_ERROR(HLE, "Unimplemented syscall %lld: %s -> CELL_OK", code, SysCalls::GetFuncName(~code));
CPU.GPR[3] = 0; CPU.GPR[3] = 0;
return;
} }
void SysCalls::DoSyscall(PPUThread& CPU, u64 code) void SysCalls::DoSyscall(PPUThread& CPU, u64 code)
{ {
auto old_last_syscall = CPU.m_last_syscall;
CPU.m_last_syscall = code;
if (code >= 1024) if (code >= 1024)
{ {
CPU.m_last_syscall = code;
throw "Invalid syscall number"; throw "Invalid syscall number";
} }
//Auto Pause using simple singleton. auto old_last_syscall = CPU.m_last_syscall;
Debug::AutoPause::getInstance().TryPause(code); CPU.m_last_syscall = ~code;
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(PPU, "Syscall %d called: %s", code, SysCalls::GetFuncName(code)); LOG_NOTICE(PPU, "Syscall %lld called: %s", code, SysCalls::GetFuncName(~code));
} }
sc_table[code](CPU); sc_table[code](CPU);
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(PPU, "Syscall %d finished: %s -> 0x%llx", code, SysCalls::GetFuncName(code), CPU.GPR[3]); LOG_NOTICE(PPU, "Syscall %lld finished: %s -> 0x%llx", code, SysCalls::GetFuncName(~code), CPU.GPR[3]);
} }
CPU.m_last_syscall = old_last_syscall; CPU.m_last_syscall = old_last_syscall;

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