Merge branch 'main' into qt-style

This commit is contained in:
tomboylover93 2025-01-22 06:09:12 -08:00 committed by GitHub
commit e385636f38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 840 additions and 144 deletions

View File

@ -120,7 +120,7 @@ find_package(SDL3 3.1.2 CONFIG)
find_package(stb MODULE) find_package(stb MODULE)
find_package(toml11 4.2.0 CONFIG) find_package(toml11 4.2.0 CONFIG)
find_package(tsl-robin-map 1.3.0 CONFIG) find_package(tsl-robin-map 1.3.0 CONFIG)
find_package(VulkanHeaders 1.4.303 CONFIG) find_package(VulkanHeaders 1.4.305 CONFIG)
find_package(VulkanMemoryAllocator 3.1.0 CONFIG) find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
find_package(xbyak 7.07 CONFIG) find_package(xbyak 7.07 CONFIG)
find_package(xxHash 0.8.2 MODULE) find_package(xxHash 0.8.2 MODULE)
@ -557,6 +557,16 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/devices/logger.cpp src/core/devices/logger.cpp
src/core/devices/logger.h src/core/devices/logger.h
src/core/devices/nop_device.h src/core/devices/nop_device.h
src/core/devices/console_device.cpp
src/core/devices/console_device.h
src/core/devices/deci_tty6_device.cpp
src/core/devices/deci_tty6_device.h
src/core/devices/random_device.cpp
src/core/devices/random_device.h
src/core/devices/urandom_device.cpp
src/core/devices/urandom_device.h
src/core/devices/srandom_device.cpp
src/core/devices/srandom_device.h
src/core/file_format/pfs.h src/core/file_format/pfs.h
src/core/file_format/pkg.cpp src/core/file_format/pkg.cpp
src/core/file_format/pkg.h src/core/file_format/pkg.h

@ -1 +1 @@
Subproject commit 6a74a7d65cafa19e38ec116651436cce6efd5b2e Subproject commit a03d2f6d5753b365d704d58161825890baad0755

View File

@ -79,6 +79,7 @@ static std::string trophyKey;
static bool load_game_size = true; static bool load_game_size = true;
std::vector<std::filesystem::path> settings_install_dirs = {}; std::vector<std::filesystem::path> settings_install_dirs = {};
std::filesystem::path settings_addon_install_dir = {}; std::filesystem::path settings_addon_install_dir = {};
std::filesystem::path save_data_path = {};
u32 main_window_geometry_x = 400; u32 main_window_geometry_x = 400;
u32 main_window_geometry_y = 400; u32 main_window_geometry_y = 400;
u32 main_window_geometry_w = 1280; u32 main_window_geometry_w = 1280;
@ -111,6 +112,13 @@ bool GetLoadGameSizeEnabled() {
return load_game_size; return load_game_size;
} }
std::filesystem::path GetSaveDataPath() {
if (save_data_path.empty()) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir);
}
return save_data_path;
}
void setLoadGameSizeEnabled(bool enable) { void setLoadGameSizeEnabled(bool enable) {
load_game_size = enable; load_game_size = enable;
} }
@ -511,6 +519,10 @@ void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_insta
settings_install_dirs = settings_install_dirs_config; settings_install_dirs = settings_install_dirs_config;
} }
void setSaveDataPath(const std::filesystem::path& path) {
save_data_path = path;
}
u32 getMainWindowGeometryX() { u32 getMainWindowGeometryX() {
return main_window_geometry_x; return main_window_geometry_x;
} }
@ -699,6 +711,8 @@ void load(const std::filesystem::path& path) {
addGameInstallDir(std::filesystem::path{dir}); addGameInstallDir(std::filesystem::path{dir});
} }
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0); main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0); main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
@ -794,6 +808,7 @@ void save(const std::filesystem::path& path) {
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data}); install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
} }
data["GUI"]["installDirs"] = install_dirs; data["GUI"]["installDirs"] = install_dirs;
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
data["GUI"]["loadGameSizeEnabled"] = load_game_size; data["GUI"]["loadGameSizeEnabled"] = load_game_size;
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =

View File

@ -18,6 +18,7 @@ void saveMainWindow(const std::filesystem::path& path);
std::string getTrophyKey(); std::string getTrophyKey();
void setTrophyKey(std::string key); void setTrophyKey(std::string key);
bool GetLoadGameSizeEnabled(); bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable); void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen(); bool getIsFullscreen();
std::string getFullscreenMode(); std::string getFullscreenMode();
@ -83,6 +84,7 @@ void setUserName(const std::string& type);
void setUpdateChannel(const std::string& type); void setUpdateChannel(const std::string& type);
void setSeparateUpdateEnabled(bool use); void setSeparateUpdateEnabled(bool use);
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config); void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use); void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);

View File

@ -67,28 +67,25 @@ struct AddressSpace::Impl {
static constexpr size_t ReductionOnFail = 1_GB; static constexpr size_t ReductionOnFail = 1_GB;
static constexpr size_t MaxReductions = 10; static constexpr size_t MaxReductions = 10;
size_t reduction = 0;
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize; size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
for (u32 i = 0; i < MaxReductions; i++) { for (u32 i = 0; i < MaxReductions; i++) {
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size - reduction, virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
PAGE_NOACCESS, &param, 1)); PAGE_NOACCESS, &param, 1));
if (virtual_base) { if (virtual_base) {
break; break;
} }
reduction += ReductionOnFail; virtual_size -= ReductionOnFail;
} }
ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}", ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}",
Common::GetLastErrorMsg()); Common::GetLastErrorMsg());
// Take the reduction off of the system managed area, and leave the others unchanged.
reduction = size_t(virtual_base - SYSTEM_MANAGED_MIN);
system_managed_base = virtual_base;
system_managed_size = SystemManagedSize - reduction;
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN); system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
system_reserved_size = SystemReservedSize; system_reserved_size = SystemReservedSize;
system_managed_base = virtual_base;
system_managed_size = system_reserved_base - virtual_base;
user_base = reinterpret_cast<u8*>(USER_MIN); user_base = reinterpret_cast<u8*>(USER_MIN);
user_size = UserSize; user_size = virtual_base + virtual_size - user_base;
LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}", LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}",
fmt::ptr(system_managed_base), fmt::ptr(system_managed_base),
@ -101,10 +98,8 @@ struct AddressSpace::Impl {
// Initializer placeholder tracker // Initializer placeholder tracker
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base); const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
const uintptr_t system_reserved_addr = reinterpret_cast<uintptr_t>(system_reserved_base);
const uintptr_t user_addr = reinterpret_cast<uintptr_t>(user_base);
regions.emplace(system_managed_addr, regions.emplace(system_managed_addr,
MemoryRegion{system_managed_addr, virtual_size - reduction, false}); MemoryRegion{system_managed_addr, virtual_size, false});
// Allocate backing file that represents the total physical memory. // Allocate backing file that represents the total physical memory.
backing_handle = backing_handle =

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "base_device.h" #include "base_device.h"

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "console_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, int, u16) {
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new ConsoleDevice(handle)));
}
int ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t ConsoleDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t ConsoleDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::read(void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 ConsoleDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class ConsoleDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit ConsoleDevice(u32 handle) : handle(handle) {}
~ConsoleDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "deci_tty6_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, int, u16) {
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new DeciTty6Device(handle)));
}
int DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t DeciTty6Device::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t DeciTty6Device::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::read(void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 DeciTty6Device::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class DeciTty6Device final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit DeciTty6Device(u32 handle) : handle(handle) {}
~DeciTty6Device() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/file_system.h"
@ -17,10 +17,12 @@ s64 Logger::write(const void* buf, size_t nbytes) {
} }
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) { size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
size_t total_written = 0;
for (int i = 0; i < iovcnt; i++) { for (int i = 0; i < iovcnt; i++) {
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len); log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
total_written += iov[i].iov_len;
} }
return iovcnt; return total_written;
} }
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) { s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "base_device.h" #include "base_device.h"
@ -17,36 +17,47 @@ public:
int ioctl(u64 cmd, Common::VaCtx* args) override { int ioctl(u64 cmd, Common::VaCtx* args) override {
return 0; return 0;
} }
s64 write(const void* buf, size_t nbytes) override { s64 write(const void* buf, size_t nbytes) override {
return 0; return 0;
} }
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override { size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
return 0; return 0;
} }
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override { size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
return 0; return 0;
} }
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override { s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override {
return 0; return 0;
} }
s64 lseek(s64 offset, int whence) override { s64 lseek(s64 offset, int whence) override {
return 0; return 0;
} }
s64 read(void* buf, size_t nbytes) override { s64 read(void* buf, size_t nbytes) override {
return 0; return 0;
} }
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override { int fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
return 0; return 0;
} }
s32 fsync() override { s32 fsync() override {
return 0; return 0;
} }
int ftruncate(s64 length) override { int ftruncate(s64 length) override {
return 0; return 0;
} }
int getdents(void* buf, u32 nbytes, s64* basep) override { int getdents(void* buf, u32 nbytes, s64* basep) override {
return 0; return 0;
} }
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override { s64 pwrite(const void* buf, size_t nbytes, u64 offset) override {
return 0; return 0;
} }

View File

@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "random_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new RandomDevice(handle)));
}
int RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t RandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t RandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::lseek(s64 offset, int whence) {
return 0;
}
s64 RandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand() & 0xFF;
}
return nbytes;
}
int RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 RandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int RandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class RandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit RandomDevice(u32 handle) : handle(handle) {}
~RandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "srandom_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new SRandomDevice(handle)));
}
int SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t SRandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t SRandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand();
}
return nbytes;
}
int SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 SRandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return s32();
}
int SRandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class SRandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit SRandomDevice(u32 handle) : handle(handle) {}
~SRandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "urandom_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new URandomDevice(handle)));
}
int URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t URandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t URandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand() & 0xFF;
}
return nbytes;
}
int URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 URandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int URandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class URandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit URandomDevice(u32 handle) : handle(handle) {}
~URandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -93,6 +93,12 @@ void L::DrawMenuBar() {
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
SameLine(ImGui::GetWindowWidth() - 30.0f);
if (Button("X", ImVec2(25, 25))) {
DebugState.IsShowingDebugMenuBar() = false;
}
EndMainMenuBar(); EndMainMenuBar();
} }

View File

@ -233,7 +233,7 @@ void HandleTable::CreateStdHandles() {
std::shared_ptr<Devices::BaseDevice>{reinterpret_cast<Devices::BaseDevice*>(device)}; std::shared_ptr<Devices::BaseDevice>{reinterpret_cast<Devices::BaseDevice*>(device)};
}; };
// order matters // order matters
setup("/dev/stdin", new Devices::NopDevice(0)); // stdin setup("/dev/stdin", new Devices::Logger("stdin", false)); // stdin
setup("/dev/stdout", new Devices::Logger("stdout", false)); // stdout setup("/dev/stdout", new Devices::Logger("stdout", false)); // stdout
setup("/dev/stderr", new Devices::Logger("stderr", true)); // stderr setup("/dev/stderr", new Devices::Logger("stderr", true)); // stderr
} }

View File

@ -8,8 +8,13 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/devices/console_device.h"
#include "core/devices/deci_tty6_device.h"
#include "core/devices/logger.h" #include "core/devices/logger.h"
#include "core/devices/nop_device.h" #include "core/devices/nop_device.h"
#include "core/devices/random_device.h"
#include "core/devices/srandom_device.h"
#include "core/devices/urandom_device.h"
#include "core/file_sys/fs.h" #include "core/file_sys/fs.h"
#include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/file_system.h"
#include "core/libraries/kernel/orbis_error.h" #include "core/libraries/kernel/orbis_error.h"
@ -41,6 +46,12 @@ static std::map<std::string, FactoryDevice> available_device = {
{"/dev/deci_stderr", GET_DEVICE_FD(2)}, {"/dev/deci_stderr", GET_DEVICE_FD(2)},
{"/dev/null", GET_DEVICE_FD(0)}, // fd0 (stdin) is a nop device {"/dev/null", GET_DEVICE_FD(0)}, // fd0 (stdin) is a nop device
{"/dev/urandom", &D::URandomDevice::Create },
{"/dev/random", &D::RandomDevice::Create },
{"/dev/srandom", &D::SRandomDevice::Create },
{"/dev/console", &D::ConsoleDevice::Create },
{"/dev/deci_tty6",&D::DeciTty6Device::Create }
// clang-format on // clang-format on
}; };
@ -67,17 +78,6 @@ int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0; bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
std::string_view path{raw_path}; std::string_view path{raw_path};
if (path == "/dev/console") {
return 2000;
}
if (path == "/dev/deci_tty6") {
return 2001;
}
if (path == "/dev/urandom") {
return 2003;
}
u32 handle = h->CreateHandle(); u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle); auto* file = h->GetFile(handle);
@ -167,9 +167,6 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
if (d < 3) { // d probably hold an error code if (d < 3) { // d probably hold an error code
return ORBIS_KERNEL_ERROR_EPERM; return ORBIS_KERNEL_ERROR_EPERM;
} }
if (d == 2003) { // dev/urandom case
return ORBIS_OK;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d); auto* file = h->GetFile(d);
if (file == nullptr) { if (file == nullptr) {
@ -273,13 +270,6 @@ size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
} }
size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) { size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) {
if (fd == 1) {
size_t total_written = 0;
for (int i = 0; i < iovcn; i++) {
total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout);
}
return total_written;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(fd); auto* file = h->GetFile(fd);
if (file == nullptr) { if (file == nullptr) {
@ -337,13 +327,6 @@ s64 PS4_SYSV_ABI posix_lseek(int d, s64 offset, int whence) {
} }
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) { s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
if (d == 2003) // dev urandom case
{
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++)
rbuf[i] = std::rand() & 0xFF;
return nbytes;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d); auto* file = h->GetFile(d);
if (file == nullptr) { if (file == nullptr) {
@ -757,7 +740,6 @@ s32 PS4_SYSV_ABI sceKernelRename(const char* from, const char* to) {
} }
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
std::srand(std::time(nullptr));
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen); LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, open); LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, open);

View File

@ -5,6 +5,7 @@
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/np_manager/np_manager.h" #include "core/libraries/np_manager/np_manager.h"
#include "core/libraries/np_manager/np_manager_error.h"
#include "core/tls.h" #include "core/tls.h"
namespace Libraries::NpManager { namespace Libraries::NpManager {
@ -935,14 +936,22 @@ int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetAccountId() { int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "called");
return ORBIS_OK; if (online_id == nullptr || account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*account_id = 0;
return ORBIS_NP_ERROR_SIGNED_OUT;
} }
int PS4_SYSV_ABI sceNpGetAccountIdA() { int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
return ORBIS_OK; if (account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*account_id = 0;
return ORBIS_NP_ERROR_SIGNED_OUT;
} }
int PS4_SYSV_ABI sceNpGetAccountLanguage() { int PS4_SYSV_ABI sceNpGetAccountLanguage() {
@ -972,6 +981,9 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatusA() {
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) { int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) {
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
if (np_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
return ORBIS_NP_ERROR_SIGNED_OUT; return ORBIS_NP_ERROR_SIGNED_OUT;
} }
@ -980,8 +992,11 @@ int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetOnlineId(s32 user_id, OrbisNpOnlineId* online_id) { int PS4_SYSV_ABI sceNpGetOnlineId(OrbisUserServiceUserId user_id, OrbisNpOnlineId* online_id) {
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
if (online_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
return ORBIS_NP_ERROR_SIGNED_OUT; return ORBIS_NP_ERROR_SIGNED_OUT;
} }
@ -995,7 +1010,10 @@ int PS4_SYSV_ABI sceNpGetParentalControlInfoA() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state) { int PS4_SYSV_ABI sceNpGetState(OrbisUserServiceUserId user_id, OrbisNpState* state) {
if (state == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*state = OrbisNpState::SignedOut; *state = OrbisNpState::SignedOut;
LOG_DEBUG(Lib_NpManager, "Signed out"); LOG_DEBUG(Lib_NpManager, "Signed out");
return ORBIS_OK; return ORBIS_OK;
@ -1011,8 +1029,12 @@ int PS4_SYSV_ABI sceNpGetUserIdByOnlineId() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpHasSignedUp() { int PS4_SYSV_ABI sceNpHasSignedUp(OrbisUserServiceUserId user_id, bool* has_signed_up) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "called");
if (has_signed_up == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*has_signed_up = false;
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -11,8 +11,6 @@ class SymbolsResolver;
namespace Libraries::NpManager { namespace Libraries::NpManager {
constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006;
enum class OrbisNpState : u32 { Unknown = 0, SignedOut, SignedIn }; enum class OrbisNpState : u32 { Unknown = 0, SignedOut, SignedIn };
using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state, using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state,
@ -220,22 +218,22 @@ int PS4_SYSV_ABI sceNpGetAccountCountry();
int PS4_SYSV_ABI sceNpGetAccountCountryA(); int PS4_SYSV_ABI sceNpGetAccountCountryA();
int PS4_SYSV_ABI sceNpGetAccountDateOfBirth(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirth();
int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA();
int PS4_SYSV_ABI sceNpGetAccountId(); int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id);
int PS4_SYSV_ABI sceNpGetAccountIdA(); int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id);
int PS4_SYSV_ABI sceNpGetAccountLanguage(); int PS4_SYSV_ABI sceNpGetAccountLanguage();
int PS4_SYSV_ABI sceNpGetAccountLanguage2(); int PS4_SYSV_ABI sceNpGetAccountLanguage2();
int PS4_SYSV_ABI sceNpGetAccountLanguageA(); int PS4_SYSV_ABI sceNpGetAccountLanguageA();
int PS4_SYSV_ABI sceNpGetGamePresenceStatus(); int PS4_SYSV_ABI sceNpGetGamePresenceStatus();
int PS4_SYSV_ABI sceNpGetGamePresenceStatusA(); int PS4_SYSV_ABI sceNpGetGamePresenceStatusA();
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId userId, OrbisNpId* npId); int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id);
int PS4_SYSV_ABI sceNpGetNpReachabilityState(); int PS4_SYSV_ABI sceNpGetNpReachabilityState();
int PS4_SYSV_ABI sceNpGetOnlineId(s32 userId, OrbisNpOnlineId* onlineId); int PS4_SYSV_ABI sceNpGetOnlineId(OrbisUserServiceUserId user_id, OrbisNpOnlineId* online_id);
int PS4_SYSV_ABI sceNpGetParentalControlInfo(); int PS4_SYSV_ABI sceNpGetParentalControlInfo();
int PS4_SYSV_ABI sceNpGetParentalControlInfoA(); int PS4_SYSV_ABI sceNpGetParentalControlInfoA();
int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state); int PS4_SYSV_ABI sceNpGetState(OrbisUserServiceUserId user_id, OrbisNpState* state);
int PS4_SYSV_ABI sceNpGetUserIdByAccountId(); int PS4_SYSV_ABI sceNpGetUserIdByAccountId();
int PS4_SYSV_ABI sceNpGetUserIdByOnlineId(); int PS4_SYSV_ABI sceNpGetUserIdByOnlineId();
int PS4_SYSV_ABI sceNpHasSignedUp(); int PS4_SYSV_ABI sceNpHasSignedUp(OrbisUserServiceUserId user_id, bool* has_signed_up);
int PS4_SYSV_ABI sceNpIdMapperAbortRequest(); int PS4_SYSV_ABI sceNpIdMapperAbortRequest();
int PS4_SYSV_ABI sceNpIdMapperAccountIdToNpId(); int PS4_SYSV_ABI sceNpIdMapperAccountIdToNpId();
int PS4_SYSV_ABI sceNpIdMapperAccountIdToOnlineId(); int PS4_SYSV_ABI sceNpIdMapperAccountIdToOnlineId();

View File

@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/libraries/error_codes.h"
constexpr int ORBIS_NP_ERROR_INVALID_ARGUMENT = 0x80550003;
constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006;

View File

@ -47,15 +47,13 @@ namespace Libraries::SaveData {
std::filesystem::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id, std::filesystem::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id,
std::string_view game_serial) { std::string_view game_serial) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / return Config::GetSaveDataPath() / std::to_string(user_id) / game_serial;
game_serial;
} }
std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_id, std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_id,
std::string_view game_serial, std::string_view game_serial,
std::string_view dir_name) { std::string_view dir_name) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / return Config::GetSaveDataPath() / std::to_string(user_id) / game_serial / dir_name;
game_serial / dir_name;
} }
uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) { uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) {

View File

@ -205,6 +205,21 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
delete selected_item; delete selected_item;
} }
}); });
connect(ui->browseButton, &QPushButton::clicked, this, [this]() {
const auto save_data_path = Config::GetSaveDataPath();
QString initial_path;
Common::FS::PathToQString(initial_path, save_data_path);
QString save_data_path_string =
QFileDialog::getExistingDirectory(this, tr("Directory to save data"), initial_path);
auto file_path = Common::FS::PathFromQString(save_data_path_string);
if (!file_path.empty()) {
Config::setSaveDataPath(file_path);
ui->currentSaveDataPath->setText(save_data_path_string);
}
});
} }
// DEBUG TAB // DEBUG TAB
@ -260,6 +275,10 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
ui->addFolderButton->installEventFilter(this); ui->addFolderButton->installEventFilter(this);
ui->removeFolderButton->installEventFilter(this); ui->removeFolderButton->installEventFilter(this);
ui->saveDataGroupBox->installEventFilter(this);
ui->currentSaveDataPath->installEventFilter(this);
ui->browseButton->installEventFilter(this);
// Debug // Debug
ui->debugDump->installEventFilter(this); ui->debugDump->installEventFilter(this);
ui->vkValidationCheckBox->installEventFilter(this); ui->vkValidationCheckBox->installEventFilter(this);
@ -290,6 +309,11 @@ void SettingsDialog::LoadValuesFromConfig() {
const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9, const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9,
15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28}; 15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28};
const auto save_data_path = Config::GetSaveDataPath();
QString save_data_path_string;
Common::FS::PathToQString(save_data_path_string, save_data_path);
ui->currentSaveDataPath->setText(save_data_path_string);
ui->consoleLanguageComboBox->setCurrentIndex( ui->consoleLanguageComboBox->setCurrentIndex(
std::distance(languageIndexes.begin(), std::distance(languageIndexes.begin(),
std::find(languageIndexes.begin(), languageIndexes.end(), std::find(languageIndexes.begin(), languageIndexes.end(),
@ -507,6 +531,13 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
text = tr("removeFolderButton"); text = tr("removeFolderButton");
} }
// Save Data
if (elementName == "saveDataGroupBox" || elementName == "currentSaveDataPath") {
text = tr("saveDataBox");
} else if (elementName == "browseButton") {
text = tr("browseButton");
}
// Debug // Debug
if (elementName == "debugDump") { if (elementName == "debugDump") {
text = tr("debugDump"); text = tr("debugDump");
@ -624,4 +655,4 @@ void SettingsDialog::ResetInstallFolders() {
} }
Config::setGameInstallDirs(settings_install_dirs_config); Config::setGameInstallDirs(settings_install_dirs_config);
} }
} }

View File

@ -53,7 +53,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>3</number>
</property> </property>
<widget class="QScrollArea" name="generalTab"> <widget class="QScrollArea" name="generalTab">
<property name="widgetResizable"> <property name="widgetResizable">
@ -1256,41 +1256,74 @@
</property> </property>
<layout class="QVBoxLayout" name="pathsTabLayout" stretch="0"> <layout class="QVBoxLayout" name="pathsTabLayout" stretch="0">
<item> <item>
<layout class="QHBoxLayout" name="pathsTabVLayout"> <widget class="QGroupBox" name="gameFoldersGroupBox">
<item> <property name="title">
<widget class="QGroupBox" name="gameFoldersGroupBox"> <string>Game Folders</string>
<property name="title"> </property>
<string>Game Folders</string> <layout class="QVBoxLayout" name="verticalLayout">
</property> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="addFolderButton"> <widget class="QPushButton" name="addFolderButton">
<property name="text"> <property name="text">
<string>Add...</string> <string>Add...</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="removeFolderButton"> <widget class="QPushButton" name="removeFolderButton">
<property name="text"> <property name="text">
<string>Remove</string> <string>Remove</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> <item>
</item> <spacer name="horizontalSpacer">
<item> <property name="orientation">
<widget class="QListWidget" name="gameFoldersListWidget"/> <enum>Qt::Horizontal</enum>
</item> </property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </item>
</item> <item>
</layout> <widget class="QListWidget" name="gameFoldersListWidget"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="saveDataGroupBox">
<property name="title">
<string>Save Data Path</string>
</property>
<layout class="QVBoxLayout" name="saveDataLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="currentSaveDataPath">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -912,6 +912,14 @@
<source>rdocCheckBox</source> <source>rdocCheckBox</source>
<translation>Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame.</translation> <translation>Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame.</translation>
</message> </message>
<message>
<source>saveDataBox</source>
<translation>Save Data Path:\nThe folder where game save data will be saved.</translation>
</message>
<message>
<source>browseButton</source>
<translation>Browse:\nBrowse for a folder to set as the save data path.</translation>
</message>
</context> </context>
<context> <context>
<name>CheatsPatches</name> <name>CheatsPatches</name>

View File

@ -3420,8 +3420,8 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
{InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
ScalarType::Uint32}, ScalarType::Uint32},
// 15 = IMAGE_ATOMIC_SWAP // 15 = IMAGE_ATOMIC_SWAP
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
ScalarType::Undefined}, ScalarType::Uint32},
// 16 = IMAGE_ATOMIC_CMPSWAP // 16 = IMAGE_ATOMIC_CMPSWAP
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
ScalarType::Undefined}, ScalarType::Undefined},

View File

@ -107,6 +107,8 @@ void Translator::EmitVectorMemory(const GcnInst& inst) {
return IMAGE_GET_RESINFO(inst); return IMAGE_GET_RESINFO(inst);
// Image atomic operations // Image atomic operations
case Opcode::IMAGE_ATOMIC_SWAP:
return IMAGE_ATOMIC(AtomicOp::Swap, inst);
case Opcode::IMAGE_ATOMIC_ADD: case Opcode::IMAGE_ATOMIC_ADD:
return IMAGE_ATOMIC(AtomicOp::Add, inst); return IMAGE_ATOMIC(AtomicOp::Add, inst);
case Opcode::IMAGE_ATOMIC_SMIN: case Opcode::IMAGE_ATOMIC_SMIN:

View File

@ -283,8 +283,7 @@ inline CompMapping RemapSwizzle(const DataFormat format, const CompMapping swizz
result.a = swizzle.a; result.a = swizzle.a;
return result; return result;
} }
case DataFormat::Format10_10_10_2: case DataFormat::Format10_10_10_2: {
case DataFormat::Format5_5_5_1: {
CompMapping result; CompMapping result;
result.r = swizzle.a; result.r = swizzle.a;
result.g = swizzle.b; result.g = swizzle.b;
@ -292,6 +291,14 @@ inline CompMapping RemapSwizzle(const DataFormat format, const CompMapping swizz
result.a = swizzle.r; result.a = swizzle.r;
return result; return result;
} }
case DataFormat::Format1_5_5_5: {
CompMapping result;
result.r = swizzle.b;
result.g = swizzle.g;
result.b = swizzle.r;
result.a = swizzle.a;
return result;
}
default: default:
return swizzle; return swizzle;
} }

View File

@ -210,7 +210,6 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo
return; return;
} }
scheduler.EndRendering(); scheduler.EndRendering();
const auto cmdbuf = scheduler.CommandBuffer();
const Buffer* buffer = [&] { const Buffer* buffer = [&] {
if (is_gds) { if (is_gds) {
return &gds_buffer; return &gds_buffer;
@ -218,6 +217,7 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo
const BufferId buffer_id = FindBuffer(address, num_bytes); const BufferId buffer_id = FindBuffer(address, num_bytes);
return &slot_buffers[buffer_id]; return &slot_buffers[buffer_id];
}(); }();
const auto cmdbuf = scheduler.CommandBuffer();
const vk::BufferMemoryBarrier2 pre_barrier = { const vk::BufferMemoryBarrier2 pre_barrier = {
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
.srcAccessMask = vk::AccessFlagBits2::eMemoryRead, .srcAccessMask = vk::AccessFlagBits2::eMemoryRead,

View File

@ -612,11 +612,13 @@ std::span<const SurfaceFormatInfo> SurfaceFormats() {
vk::Format::eB5G6R5UnormPack16), vk::Format::eB5G6R5UnormPack16),
// 1_5_5_5 // 1_5_5_5
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm, CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm,
vk::Format::eA1R5G5B5UnormPack16),
// 5_5_5_1
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_5_5_1, AmdGpu::NumberFormat::Unorm,
vk::Format::eR5G5B5A1UnormPack16), vk::Format::eR5G5B5A1UnormPack16),
// 5_5_5_1 - Remapped to 1_5_5_5.
// 4_4_4_4 // 4_4_4_4
CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format4_4_4_4, AmdGpu::NumberFormat::Unorm, CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format4_4_4_4, AmdGpu::NumberFormat::Unorm,
vk::Format::eR4G4B4A4UnormPack16), vk::Format::eA4B4G4R4UnormPack16),
// 8_24 // 8_24
// 24_8 // 24_8
// X24_8_32 // X24_8_32

View File

@ -283,6 +283,7 @@ bool Instance::CreateDevice() {
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
add_extension(VK_EXT_4444_FORMATS_EXTENSION_NAME);
#ifdef __APPLE__ #ifdef __APPLE__
// Required by Vulkan spec if supported. // Required by Vulkan spec if supported.

View File

@ -28,19 +28,19 @@ static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
static const char* const CRASH_DIAGNOSTIC_LAYER_NAME = "VK_LAYER_LUNARG_crash_diagnostic"; static const char* const CRASH_DIAGNOSTIC_LAYER_NAME = "VK_LAYER_LUNARG_crash_diagnostic";
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback( static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, vk::DebugUtilsMessageSeverityFlagBitsEXT severity, vk::DebugUtilsMessageTypeFlagsEXT type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { const vk::DebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) {
Common::Log::Level level{}; Common::Log::Level level{};
switch (severity) { switch (severity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
level = Common::Log::Level::Error; level = Common::Log::Level::Error;
break; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
level = Common::Log::Level::Info; level = Common::Log::Level::Info;
break; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
level = Common::Log::Level::Debug; level = Common::Log::Level::Debug;
break; break;
default: default:

View File

@ -825,6 +825,9 @@ void Presenter::Present(Frame* frame, bool is_reusing_frame) {
{ // Draw the game { // Draw the game
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{0.0f}); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{0.0f});
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once); ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once);
ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav); ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav);
@ -840,7 +843,8 @@ void Presenter::Present(Frame* frame, bool is_reusing_frame) {
static_cast<float>(imgRect.extent.height), static_cast<float>(imgRect.extent.height),
}); });
ImGui::End(); ImGui::End();
ImGui::PopStyleVar(); ImGui::PopStyleVar(3);
ImGui::PopStyleColor();
} }
ImGui::Core::Render(cmdbuf, swapchain_image_view, swapchain.GetExtent()); ImGui::Core::Render(cmdbuf, swapchain_image_view, swapchain.GetExtent());

View File

@ -166,6 +166,7 @@ void ImageInfo::UpdateSize() {
mip_w = std::max(mip_w, 1u); mip_w = std::max(mip_w, 1u);
mip_h = std::max(mip_h, 1u); mip_h = std::max(mip_h, 1u);
auto mip_d = std::max(size.depth >> mip, 1u); auto mip_d = std::max(size.depth >> mip, 1u);
auto thickness = 1;
if (props.is_pow2) { if (props.is_pow2) {
mip_w = std::bit_ceil(mip_w); mip_w = std::bit_ceil(mip_w);
@ -177,35 +178,35 @@ void ImageInfo::UpdateSize() {
case AmdGpu::TilingMode::Display_Linear: { case AmdGpu::TilingMode::Display_Linear: {
std::tie(mip_info.pitch, mip_info.size) = std::tie(mip_info.pitch, mip_info.size) =
ImageSizeLinearAligned(mip_w, mip_h, bpp, num_samples); ImageSizeLinearAligned(mip_w, mip_h, bpp, num_samples);
mip_info.height = mip_h;
break; break;
} }
case AmdGpu::TilingMode::Texture_Volume: case AmdGpu::TilingMode::Texture_Volume:
mip_d += (-mip_d) & 3u; thickness = 4;
mip_d += (-mip_d) & (thickness - 1);
[[fallthrough]]; [[fallthrough]];
case AmdGpu::TilingMode::Display_MicroTiled: case AmdGpu::TilingMode::Display_MicroTiled:
case AmdGpu::TilingMode::Texture_MicroTiled: { case AmdGpu::TilingMode::Texture_MicroTiled: {
std::tie(mip_info.pitch, mip_info.size) = std::tie(mip_info.pitch, mip_info.size) =
ImageSizeMicroTiled(mip_w, mip_h, bpp, num_samples); ImageSizeMicroTiled(mip_w, mip_h, thickness, bpp, num_samples);
mip_info.height = std::max(mip_h, 8u);
if (props.is_block) {
mip_info.pitch = std::max(mip_info.pitch * 4, 32u);
mip_info.height = std::max(mip_info.height * 4, 32u);
}
break; break;
} }
case AmdGpu::TilingMode::Display_MacroTiled: case AmdGpu::TilingMode::Display_MacroTiled:
case AmdGpu::TilingMode::Texture_MacroTiled: case AmdGpu::TilingMode::Texture_MacroTiled:
case AmdGpu::TilingMode::Depth_MacroTiled: { case AmdGpu::TilingMode::Depth_MacroTiled: {
ASSERT(!props.is_block); ASSERT(!props.is_block);
std::tie(mip_info.pitch, mip_info.size) = std::tie(mip_info.pitch, mip_info.size) = ImageSizeMacroTiled(
ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, tiling_idx, mip, alt_tile); mip_w, mip_h, thickness, bpp, num_samples, tiling_idx, mip, alt_tile);
break; break;
} }
default: { default: {
UNREACHABLE(); UNREACHABLE();
} }
} }
mip_info.height = mip_h;
if (props.is_block) {
mip_info.pitch = std::max(mip_info.pitch * 4, 32u);
mip_info.height = std::max(mip_info.height * 4, 32u);
}
mip_info.size *= mip_d; mip_info.size *= mip_d;
mip_info.offset = guest_size; mip_info.offset = guest_size;
mips_layout.emplace_back(mip_info); mips_layout.emplace_back(mip_info);

View File

@ -60,15 +60,13 @@ void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
void TextureCache::InvalidateMemory(VAddr addr, size_t size) { void TextureCache::InvalidateMemory(VAddr addr, size_t size) {
std::scoped_lock lock{mutex}; std::scoped_lock lock{mutex};
const auto end = addr + size;
const auto pages_start = PageManager::GetPageAddr(addr); const auto pages_start = PageManager::GetPageAddr(addr);
const auto pages_end = PageManager::GetNextPageAddr(addr + size - 1); const auto pages_end = PageManager::GetNextPageAddr(addr + size - 1);
ForEachImageInRegion(pages_start, pages_end - pages_start, [&](ImageId image_id, Image& image) { ForEachImageInRegion(pages_start, pages_end - pages_start, [&](ImageId image_id, Image& image) {
const auto image_begin = image.info.guest_address; const auto image_begin = image.info.guest_address;
const auto image_end = image.info.guest_address + image.info.guest_size; const auto image_end = image.info.guest_address + image.info.guest_size;
if (image_begin < end && addr < image_end) { if (image.Overlaps(addr, size)) {
// Start or end of the modified region is in the image, or the image is entirely within // Modified region overlaps image, so the image was definitely accessed by this fault.
// the modified region, so the image was definitely accessed by this page fault.
// Untrack the image, so that the range is unprotected and the guest can write freely. // Untrack the image, so that the range is unprotected and the guest can write freely.
image.flags |= ImageFlagBits::CpuDirty; image.flags |= ImageFlagBits::CpuDirty;
UntrackImage(image_id); UntrackImage(image_id);
@ -545,12 +543,12 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
auto* sched_ptr = custom_scheduler ? custom_scheduler : &scheduler; auto* sched_ptr = custom_scheduler ? custom_scheduler : &scheduler;
sched_ptr->EndRendering(); sched_ptr->EndRendering();
const auto cmdbuf = sched_ptr->CommandBuffer();
const VAddr image_addr = image.info.guest_address; const VAddr image_addr = image.info.guest_address;
const size_t image_size = image.info.guest_size; const size_t image_size = image.info.guest_size;
const auto [vk_buffer, buf_offset] = const auto [vk_buffer, buf_offset] =
buffer_cache.ObtainViewBuffer(image_addr, image_size, is_gpu_dirty); buffer_cache.ObtainViewBuffer(image_addr, image_size, is_gpu_dirty);
const auto cmdbuf = sched_ptr->CommandBuffer();
// The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW // The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW
// hazard // hazard
if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead, if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead,
@ -643,6 +641,9 @@ void TextureCache::UnregisterImage(ImageId image_id) {
void TextureCache::TrackImage(ImageId image_id) { void TextureCache::TrackImage(ImageId image_id) {
auto& image = slot_images[image_id]; auto& image = slot_images[image_id];
if (!(image.flags & ImageFlagBits::Registered)) {
return;
}
const auto image_begin = image.info.guest_address; const auto image_begin = image.info.guest_address;
const auto image_end = image.info.guest_address + image.info.guest_size; const auto image_end = image.info.guest_address + image.info.guest_size;
if (image_begin == image.track_addr && image_end == image.track_addr_end) { if (image_begin == image.track_addr && image_end == image.track_addr_end) {
@ -666,6 +667,9 @@ void TextureCache::TrackImage(ImageId image_id) {
void TextureCache::TrackImageHead(ImageId image_id) { void TextureCache::TrackImageHead(ImageId image_id) {
auto& image = slot_images[image_id]; auto& image = slot_images[image_id];
if (!(image.flags & ImageFlagBits::Registered)) {
return;
}
const auto image_begin = image.info.guest_address; const auto image_begin = image.info.guest_address;
if (image_begin == image.track_addr) { if (image_begin == image.track_addr) {
return; return;
@ -678,6 +682,9 @@ void TextureCache::TrackImageHead(ImageId image_id) {
void TextureCache::TrackImageTail(ImageId image_id) { void TextureCache::TrackImageTail(ImageId image_id) {
auto& image = slot_images[image_id]; auto& image = slot_images[image_id];
if (!(image.flags & ImageFlagBits::Registered)) {
return;
}
const auto image_end = image.info.guest_address + image.info.guest_size; const auto image_end = image.info.guest_address + image.info.guest_size;
if (image_end == image.track_addr_end) { if (image_end == image.track_addr_end) {
return; return;

View File

@ -118,6 +118,7 @@ public:
/// Updates image contents if it was modified by CPU. /// Updates image contents if it was modified by CPU.
void UpdateImage(ImageId image_id, Vulkan::Scheduler* custom_scheduler = nullptr) { void UpdateImage(ImageId image_id, Vulkan::Scheduler* custom_scheduler = nullptr) {
std::scoped_lock lock{mutex};
Image& image = slot_images[image_id]; Image& image = slot_images[image_id];
TrackImage(image_id); TrackImage(image_id);
RefreshImage(image, custom_scheduler); RefreshImage(image, custom_scheduler);

View File

@ -308,20 +308,20 @@ constexpr std::pair<u32, size_t> ImageSizeLinearAligned(u32 pitch, u32 height, u
return {pitch_aligned, (log_sz * bpp + 7) / 8}; return {pitch_aligned, (log_sz * bpp + 7) / 8};
} }
constexpr std::pair<u32, size_t> ImageSizeMicroTiled(u32 pitch, u32 height, u32 bpp, constexpr std::pair<u32, size_t> ImageSizeMicroTiled(u32 pitch, u32 height, u32 thickness, u32 bpp,
u32 num_samples) { u32 num_samples) {
const auto& [pitch_align, height_align] = micro_tile_extent; const auto& [pitch_align, height_align] = micro_tile_extent;
auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1);
const auto height_aligned = (height + height_align - 1) & ~(height_align - 1); const auto height_aligned = (height + height_align - 1) & ~(height_align - 1);
size_t log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; size_t log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8;
while (log_sz % 256) { while ((log_sz * thickness) % 256) {
pitch_aligned += 8; pitch_aligned += pitch_align;
log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8; log_sz = (pitch_aligned * height_aligned * bpp * num_samples + 7) / 8;
} }
return {pitch_aligned, log_sz}; return {pitch_aligned, log_sz};
} }
constexpr std::pair<u32, size_t> ImageSizeMacroTiled(u32 pitch, u32 height, u32 bpp, constexpr std::pair<u32, size_t> ImageSizeMacroTiled(u32 pitch, u32 height, u32 thickness, u32 bpp,
u32 num_samples, u32 tiling_idx, u32 mip_n, u32 num_samples, u32 tiling_idx, u32 mip_n,
bool alt) { bool alt) {
const auto& [pitch_align, height_align] = const auto& [pitch_align, height_align] =
@ -335,7 +335,7 @@ constexpr std::pair<u32, size_t> ImageSizeMacroTiled(u32 pitch, u32 height, u32
} }
if (downgrade_to_micro) { if (downgrade_to_micro) {
return ImageSizeMicroTiled(pitch, height, bpp, num_samples); return ImageSizeMicroTiled(pitch, height, thickness, bpp, num_samples);
} }
const auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1); const auto pitch_aligned = (pitch + pitch_align - 1) & ~(pitch_align - 1);