code: Misc fixes

This commit is contained in:
GPUCode 2024-02-27 20:57:51 +02:00
parent 06a19ac130
commit 29be8273d4
19 changed files with 60 additions and 299 deletions

4
.gitmodules vendored
View File

@ -6,10 +6,6 @@
path = third-party/fmt
url = https://github.com/fmtlib/fmt.git
shallow = true
[submodule "third-party/spdlog"]
path = third-party/spdlog
url = https://github.com/gabime/spdlog
shallow = true
[submodule "third-party/magic_enum"]
path = third-party/magic_enum
url = https://github.com/Neargye/magic_enum.git

View File

@ -228,7 +228,7 @@ add_executable(shadps4
create_target_directory_groups(shadps4)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt spdlog::spdlog toml11::toml11)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11)
target_link_libraries(shadps4 PRIVATE discord-rpc SDL3-shared vulkan-1 xxhash Zydis)
if (WIN32)
target_link_libraries(shadps4 PRIVATE mincore winpthread clang_rt.builtins-x86_64.lib)

View File

@ -4,13 +4,7 @@
#include "common/assert.h"
#include "common/logging/backend.h"
#if defined(ARCHITECTURE_x86_64)
#define Crash() __asm__ __volatile__("int $3")
#elif defined(ARCHITECTURE_arm64)
#define Crash() __asm__ __volatile__("brk #0")
#else
#define Crash() exit(1)
#endif
void assert_fail_impl() {
Common::Log::Stop();
@ -18,7 +12,7 @@ void assert_fail_impl() {
}
[[noreturn]] void unreachable_impl() {
Common::Log::Stop();
/*Common::Log::Stop();
Crash();
throw std::runtime_error("Unreachable code");
throw std::runtime_error("Unreachable code");*/
}

View File

@ -28,14 +28,6 @@ namespace {
#ifdef _WIN32
/**
* Converts the file access mode and file type enums to a file access mode wide string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a wide string representing the file access mode.
*/
[[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) {
switch (type) {
case FileType::BinaryFile:
@ -71,13 +63,6 @@ namespace {
return L"";
}
/**
* Converts the file-share access flag enum to a Windows defined file-share access flag.
*
* @param flag File-share access flag
*
* @returns Windows defined file-share access flag.
*/
[[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) {
switch (flag) {
case FileShareFlag::ShareNone:
@ -94,14 +79,6 @@ namespace {
#else
/**
* Converts the file access mode and file type enums to a file access mode string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a string representing the file access mode.
*/
[[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) {
switch (type) {
case FileType::BinaryFile:
@ -139,13 +116,6 @@ namespace {
#endif
/**
* Converts the seek origin enum to a seek origin integer.
*
* @param origin Seek origin
*
* @returns Seek origin integer.
*/
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
switch (origin) {
case SeekOrigin::SetOrigin:

View File

@ -72,16 +72,6 @@ public:
explicit IOFile(std::string_view path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
/**
* An IOFile is a lightweight wrapper on C Library file operations.
* Automatically closes an open file on the destruction of an IOFile object.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
explicit IOFile(const std::filesystem::path& path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
@ -94,74 +84,37 @@ public:
IOFile(IOFile&& other) noexcept;
IOFile& operator=(IOFile&& other) noexcept;
/**
* Gets the path of the file.
*
* @returns The path of the file.
*/
std::filesystem::path GetPath() const {
return file_path;
}
/**
* Gets the access mode of the file.
*
* @returns The access mode of the file.
*/
FileAccessMode GetAccessMode() const {
return file_access_mode;
}
/**
* Gets the type of the file.
*
* @returns The type of the file.
*/
FileType GetType() const {
return file_type;
}
/**
* Opens a file at path with the specified file access mode.
* This function behaves differently depending on the FileAccessMode.
* These behaviors are documented in each enum value of FileAccessMode.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
void Open(const std::filesystem::path& path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
/// Closes the file if it is opened.
void Close();
/**
* Checks whether the file is open.
* Use this to check whether the calls to Open() or Close() succeeded.
*
* @returns True if the file is open, false otherwise.
*/
bool IsOpen() const {
return file != nullptr;
}
/**
* Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
* If T is not a contiguous container as defined by the concept IsContiguousContainer, this
* calls ReadObject and T must be a trivially copyable object.
*
* See ReadSpan for more details if T is a contiguous container.
* See ReadObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or reference to object
*
* @returns Count of T::value_type data or objects successfully read.
*/
void Open(const std::filesystem::path& path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
void Close();
bool Flush() const;
bool Commit() const;
bool SetSize(u64 size) const;
u64 GetSize() const;
bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const;
s64 Tell() const;
template <typename T>
size_t Read(T& data) const {
if constexpr (IsContiguousContainer<T>) {
@ -174,20 +127,6 @@ public:
}
}
/**
* Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
* If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this
* calls WriteObject and T must be a trivially copyable object.
*
* See WriteSpan for more details if T is a contiguous container.
* See WriteObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or const reference to object
*
* @returns Count of T::value_type data or objects successfully written.
*/
template <typename T>
size_t Write(const T& data) const {
if constexpr (IsContiguousContainer<T>) {
@ -201,22 +140,6 @@ public:
}
}
/**
* Reads a span of T data from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully read.
*/
template <typename T>
size_t ReadSpan(std::span<T> data) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@ -228,31 +151,11 @@ public:
return ReadRaw<T>(data.data(), data.size());
}
/**
* Reads data from a file sequentially to a provided memory address.
* This function reads from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully read.
*/
template <typename T>
size_t ReadRaw(void* data, size_t size) const {
return std::fread(data, sizeof(T), size, file);
}
/**
* Writes a span of T data to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully written.
*/
template <typename T>
size_t WriteSpan(std::span<const T> data) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@ -264,22 +167,6 @@ public:
return std::fwrite(data.data(), sizeof(T), data.size(), file);
}
/**
* Reads a T object from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param object Reference to object
*
* @returns True if the object is successfully read from the file, false otherwise.
*/
template <typename T>
bool ReadObject(T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@ -292,21 +179,6 @@ public:
return std::fread(&object, sizeof(T), 1, file) == 1;
}
/**
* Writes a T object to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param object Const reference to object
*
* @returns True if the object is successfully written to the file, false otherwise.
*/
template <typename T>
bool WriteObject(const T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@ -319,88 +191,12 @@ public:
return std::fwrite(&object, sizeof(T), 1, file) == 1;
}
/**
* Specialized function to read a string of a given length from a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully read.
* The size of the returned string may not match length if not all bytes are successfully read.
*
* @param length Length of the string
*
* @returns A string read from the file.
*/
std::string ReadString(size_t length) const;
/**
* Specialized function to write a string to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully written.
*
* @param string Span of const char backed std::string or std::string_view
*
* @returns Number of characters successfully written.
*/
size_t WriteString(std::span<const char> string) const {
return WriteSpan(string);
}
/**
* Attempts to flush any unwritten buffered data into the file.
*
* @returns True if the flush was successful, false otherwise.
*/
bool Flush() const;
/**
* Attempts to commit the file into the disk.
* Note that this is an expensive operation as this forces the operating system to write
* the contents of the file associated with the file descriptor into the disk.
*
* @returns True if the commit was successful, false otherwise.
*/
bool Commit() const;
/**
* Resizes the file to a given size.
* If the file is resized to a smaller size, the remainder of the file is discarded.
* If the file is resized to a larger size, the new area appears as if zero-filled.
*
* Failures occur when:
* - The file is not open
*
* @param size File size in bytes
*
* @returns True if the file resize succeeded, false otherwise.
*/
bool SetSize(u64 size) const;
/**
* Gets the size of the file.
*
* Failures occur when:
* - The file is not open
*
* @returns The file size in bytes of the file. Returns 0 on failure.
*/
u64 GetSize() const;
/**
* Moves the current position of the file pointer with the specified offset and seek origin.
*
* @param offset Offset from seek origin
* @param origin Seek origin
*
* @returns True if the file pointer has moved to the specified offset, false otherwise.
*/
bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const;
/**
* Gets the current position of the file pointer.
*
* @returns The current position of the file pointer.
*/
s64 Tell() const;
private:
std::filesystem::path file_path;
FileAccessMode file_access_mode{};

View File

@ -60,18 +60,8 @@ private:
*/
class FileBackend {
public:
explicit FileBackend(const std::filesystem::path& filename) {
auto old_filename = filename;
old_filename += ".old.txt";
std::filesystem::remove(old_filename);
std::filesystem::rename(filename, old_filename);
// _SH_DENYWR allows read only access to the file for other programs.
// It is #defined to 0 on other platforms
file = std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write,
FS::FileType::TextFile);
}
explicit FileBackend(const std::filesystem::path& filename) : file{filename, FS::FileAccessMode::Write,
FS::FileType::TextFile} {}
~FileBackend() = default;
@ -80,7 +70,7 @@ public:
return;
}
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n'));
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
const auto write_limit = 100_MB;
@ -91,16 +81,16 @@ public:
// Don't close the file so we can print a stacktrace if necessary
enabled = false;
}
file->Flush();
file.Flush();
}
}
void Flush() {
file->Flush();
file.Flush();
}
private:
std::unique_ptr<Common::FS::IOFile> file;
Common::FS::IOFile file;
bool enabled = true;
std::size_t bytes_written = 0;
};
@ -258,7 +248,6 @@ private:
void Initialize(std::string_view log_file) {
Impl::Initialize(log_file.empty() ? LOG_FILE : log_file);
Impl::Start();
}
void Start() {
@ -280,7 +269,7 @@ void SetColorConsoleBackendEnabled(bool enabled) {
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, const char* format,
const fmt::format_args& args) {
if (!initialization_in_progress_suppress_logging) {
if (!initialization_in_progress_suppress_logging) [[likely]] {
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
fmt::vformat(format, args));
}

View File

@ -35,6 +35,8 @@ static auto UserPaths = [] {
create_path(PathType::LogDir, user_dir / LOG_DIR);
create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR);
create_path(PathType::ShaderDir, user_dir / SHADER_DIR);
create_path(PathType::App0, user_dir / APP0_DIR);
return paths;
}();

View File

@ -13,6 +13,7 @@ enum class PathType {
LogDir, // Where log files are stored.
ScreenshotsDir, // Where screenshots are stored.
ShaderDir, // Where shaders are stored.
App0, // Where guest application data is stored.
};
constexpr auto PORTABLE_DIR = "user";
@ -21,6 +22,7 @@ constexpr auto PORTABLE_DIR = "user";
constexpr auto LOG_DIR = "log";
constexpr auto SCREENSHOTS_DIR = "screenshots";
constexpr auto SHADER_DIR = "shader";
constexpr auto APP0_DIR = "app0";
// Filenames
constexpr auto LOG_FILE = "shad_log.txt";

View File

@ -22,12 +22,12 @@ namespace Core::AeroLib {
constexpr u32 MAX_STUBS = 128;
u64 UnresolvedStub() {
LOG_ERROR(Core, "Returning zero to {}\n", __builtin_return_address(0));
LOG_ERROR(Core, "Returning zero to {}", __builtin_return_address(0));
return 0;
}
static u64 UnknownStub() {
LOG_ERROR(Core, "Returning zero to {}\n", __builtin_return_address(0));
LOG_ERROR(Core, "Returning zero to {}", __builtin_return_address(0));
return 0;
}
@ -38,10 +38,10 @@ template <int stub_index>
static u64 CommonStub() {
auto entry = stub_nids[stub_index];
if (entry) {
LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}\n", entry->name,
LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}", entry->name,
entry->nid, __builtin_return_address(0));
} else {
LOG_ERROR(Core, "Stub: Unknown (nid: {}) called, returning zero to {}\n",
LOG_ERROR(Core, "Stub: Unknown (nid: {}) called, returning zero to {}",
stub_nids_unknown[stub_index], __builtin_return_address(0));
}
return 0;

View File

@ -457,6 +457,7 @@ void libcSymbolsRegister(Loader::SymbolsResolver* sym) {
LIB_FUNCTION("8zTFvBIAIN8", "libc", 1, "libc", 1, 1, ps4_memset);
// stdio functions
LIB_FUNCTION("xeYO4u7uyJ0", "libc", 1, "libc", 1, 1, ps4_fopen);
LIB_FUNCTION("hcuQgD53UxM", "libc", 1, "libc", 1, 1, ps4_printf);
LIB_FUNCTION("Q2V+iqvjgC0", "libc", 1, "libc", 1, 1, ps4_vsnprintf);
LIB_FUNCTION("YQ0navp+YIc", "libc", 1, "libc", 1, 1, ps4_puts);

View File

@ -2,10 +2,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "common/singleton.h"
#include "core/file_sys/fs.h"
#include "core/hle/libraries/libc/libc_stdio.h"
namespace Core::Libraries::LibC {
std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) {
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
return std::fopen(mnt->GetHostFile(filename).c_str(), mode);
}
int PS4_SYSV_ABI ps4_printf(VA_ARGS) {
VA_CTX(ctx);
return printf_ctx(&ctx);
@ -17,6 +24,7 @@ int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) {
VA_CTX(ctx);
return printf_ctx(&ctx);
}
UNREACHABLE_MSG("Unimplemented fprintf case");
return 0;
}

View File

@ -8,6 +8,7 @@
namespace Core::Libraries::LibC {
std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode);
int PS4_SYSV_ABI ps4_printf(VA_ARGS);
int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg);
int PS4_SYSV_ABI ps4_puts(const char* s);

View File

@ -59,6 +59,7 @@
#include <cstdbool>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "va_ctx.h"

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <Zydis/Zydis.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/aerolib/aerolib.h"
@ -56,9 +57,14 @@ Linker::Linker() = default;
Linker::~Linker() = default;
Module* Linker::LoadModule(const std::string& elf_name) {
Module* Linker::LoadModule(const std::filesystem::path& elf_name) {
std::scoped_lock lock{m_mutex};
if (!std::filesystem::exists(elf_name)) {
LOG_ERROR(Core_Linker, "Provided module {} does not exist", elf_name.string());
return nullptr;
}
auto& m = m_modules.emplace_back();
m = std::make_unique<Module>();
m->linker = this;

View File

@ -116,7 +116,7 @@ public:
Linker();
virtual ~Linker();
Module* LoadModule(const std::string& elf_name);
Module* LoadModule(const std::filesystem::path& elf_name);
Module* FindModule(/*u32 id*/);
void LoadModuleToMemory(Module* m);
void LoadDynamicInfo(Module* m);

View File

@ -101,6 +101,10 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode
return true;
#else
int ret = mprotect(reinterpret_cast<void*>(address), size, convertMemoryMode(mode));
if (ret != 0) {
const auto error = Common::GetLastErrorMsg();
ASSERT(false);
}
return true;
#endif
}
@ -121,7 +125,7 @@ bool memory_flush(u64 address, u64 size) {
}
bool memory_patch(u64 vaddr, u64 value) {
MemoryMode old_mode{};
memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode);
//memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode);
auto* ptr = reinterpret_cast<uint64_t*>(vaddr);
@ -129,7 +133,7 @@ bool memory_patch(u64 vaddr, u64 value) {
*ptr = value;
memory_protect(vaddr, 8, old_mode, nullptr);
//memory_protect(vaddr, 8, old_mode, nullptr);
// if mode is executable flush it so insure that cpu finds it
if (containsExecuteMode(old_mode)) {

View File

@ -30,6 +30,7 @@ int main(int argc, char* argv[]) {
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::load(config_dir / "config.toml");
Common::Log::Initialize();
Common::Log::Start();
Core::Libraries::LibKernel::init_pthreads();
auto width = Config::getScreenWidth();
auto height = Config::getScreenHeight();
@ -41,7 +42,7 @@ int main(int argc, char* argv[]) {
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
std::filesystem::path p = std::string(path);
mnt->Mount(p.parent_path().string(), "/app0");
mnt->Mount(config_dir / "app0", "/app0");
auto linker = Common::Singleton<Core::Linker>::Instance();
Core::Libraries::InitHLELibs(&linker->getHLESymbols());
@ -53,7 +54,6 @@ int main(int argc, char* argv[]) {
discordRPC.update(Discord::RPCStatus::Idling, "");
Emu::emuRun();
Common::Log::Stop();
discordRPC.stop();
return 0;
}

View File

@ -12,14 +12,6 @@ add_subdirectory(fmt EXCLUDE_FROM_ALL)
# MagicEnum
add_subdirectory(magic_enum EXCLUDE_FROM_ALL)
# Spdlog
set(SPDLOG_WCHAR_FILENAMES ON CACHE BOOL "")
set(SPDLOG_NO_THREAD_ID ON CACHE BOOL "")
set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "")
add_subdirectory(spdlog EXCLUDE_FROM_ALL)
add_library(stb INTERFACE)
target_include_directories(stb INTERFACE ./stb)
# SDL3
add_subdirectory(SDL EXCLUDE_FROM_ALL)

1
third-party/spdlog vendored

@ -1 +0,0 @@
Subproject commit 134f9194bb93072b72b8cfa27ac3bb30a0fb5b57