Merge branch 'main' into avplayer-improvements

This commit is contained in:
georgemoralis 2025-04-19 10:06:30 +03:00 committed by GitHub
commit 359c49a960
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 222 additions and 103 deletions

View file

@ -570,6 +570,8 @@ set(NP_LIBS src/core/libraries/np_common/np_common.cpp
src/core/libraries/np_web_api/np_web_api.h
src/core/libraries/np_party/np_party.cpp
src/core/libraries/np_party/np_party.h
src/core/libraries/np_auth/np_auth.cpp
src/core/libraries/np_auth/np_auth.h
)
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp

View file

@ -146,16 +146,13 @@ The following firmware modules are supported and must be placed in shadPS4's `us
# Main team
- [**georgemoralis**](https://github.com/georgemoralis)
- [**raphaelthegreat**](https://github.com/raphaelthegreat)
- [**psucien**](https://github.com/psucien)
- [**skmp**](https://github.com/skmp)
- [**wheremyfoodat**](https://github.com/wheremyfoodat)
- [**raziel1000**](https://github.com/raziel1000)
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
- [**roamic**](https://github.com/vladmikhalin)
- [**poly**](https://github.com/polybiusproxy)
- [**squidbus**](https://github.com/squidbus)
- [**frodo**](https://github.com/baggins183)
- [**Stephen Miller**](https://github.com/StevenMiller123)
- [**kalaposfos13**](https://github.com/kalaposfos13)
Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
@ -166,11 +163,11 @@ Open a PR and we'll check it :)
# Translations
If you want to translate shadPS4 to your language we use [**crowdin**](https://crowdin.com/project/shadps4-emulator).
If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator).
# Contributors
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=15">
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
</a>

View file

@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Lib, Ssl2) \
SUB(Lib, SysModule) \
SUB(Lib, Move) \
SUB(Lib, NpAuth) \
SUB(Lib, NpCommon) \
SUB(Lib, NpManager) \
SUB(Lib, NpScore) \

View file

@ -69,6 +69,7 @@ enum class Class : u8 {
Lib_Http2, ///< The LibSceHttp2 implementation.
Lib_SysModule, ///< The LibSceSysModule implementation
Lib_NpCommon, ///< The LibSceNpCommon implementation
Lib_NpAuth, ///< The LibSceNpAuth implementation
Lib_NpManager, ///< The LibSceNpManager implementation
Lib_NpScore, ///< The LibSceNpScore implementation
Lib_NpTrophy, ///< The LibSceNpTrophy implementation

View file

@ -2804,7 +2804,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
liverpool = std::make_unique<AmdGpu::Liverpool>();
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
const int result = sceKernelGetCompiledSdkVersion(&sdk_version);
const s32 result = sceKernelGetCompiledSdkVersion(&sdk_version);
if (result != ORBIS_OK) {
sdk_version = 0;
}

View file

@ -19,7 +19,7 @@
namespace Libraries::Kernel {
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
LOG_WARNING(Kernel_Vmm, "called");
LOG_TRACE(Kernel_Vmm, "called");
const auto* memory = Core::Memory::Instance();
return memory->GetTotalDirectSize();
}
@ -106,12 +106,6 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
if (physAddrOut == nullptr || sizeOut == nullptr) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (searchEnd > sceKernelGetDirectMemorySize()) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (searchEnd <= searchStart) {
return ORBIS_KERNEL_ERROR_ENOMEM;
}
auto* memory = Core::Memory::Instance();

View file

@ -27,6 +27,7 @@
#include "core/libraries/network/netctl.h"
#include "core/libraries/network/ssl.h"
#include "core/libraries/network/ssl2.h"
#include "core/libraries/np_auth/np_auth.h"
#include "core/libraries/np_common/np_common.h"
#include "core/libraries/np_manager/np_manager.h"
#include "core/libraries/np_party/np_party.h"
@ -88,6 +89,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::NpScore::RegisterlibSceNpScore(sym);
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);
Libraries::NpWebApi::RegisterlibSceNpWebApi(sym);
Libraries::NpAuth::RegisterlibSceNpAuth(sym);
Libraries::ScreenShot::RegisterlibSceScreenShot(sym);
Libraries::AppContent::RegisterlibSceAppContent(sym);
Libraries::PngDec::RegisterlibScePngDec(sym);

View file

@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/np_auth/np_auth.h"
namespace Libraries::NpAuth {
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthGetIdToken() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthAbortRequest() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthCreateRequest() {
LOG_WARNING(Lib_NpAuth, "(DUMMY) called");
return 1;
}
s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id) {
LOG_WARNING(Lib_NpAuth, "(DUMMY) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthPollAsync() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthSetTimeout() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpAuthWaitAsync() {
LOG_ERROR(Lib_NpAuth, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1,
sceNpAuthGetAuthorizationCode);
LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken);
LIB_FUNCTION("cE7wIsqXdZ8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthAbortRequest);
LIB_FUNCTION("N+mr7GjTvr8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
sceNpAuthCreateAsyncRequest);
LIB_FUNCTION("6bwFkosYRQg", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthCreateRequest);
LIB_FUNCTION("H8wG9Bk-nPc", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthDeleteRequest);
LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
sceNpAuthGetAuthorizationCode);
LIB_FUNCTION("qAUXQ9GdWp8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
sceNpAuthGetAuthorizationCodeA);
LIB_FUNCTION("KI4dHLlTNl0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1,
sceNpAuthGetAuthorizationCodeV3);
LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken);
LIB_FUNCTION("CocbHVIKPE8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenA);
LIB_FUNCTION("RdsFVsgSpZY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenV3);
LIB_FUNCTION("gjSyfzSsDcE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthPollAsync);
LIB_FUNCTION("PM3IZCw-7m0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthSetTimeout);
LIB_FUNCTION("SK-S7daqJSE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthWaitAsync);
};
} // namespace Libraries::NpAuth

View file

@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/types.h"
namespace Core::Loader {
class SymbolsResolver;
}
namespace Libraries::NpAuth {
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode();
s32 PS4_SYSV_ABI sceNpAuthGetIdToken();
s32 PS4_SYSV_ABI sceNpAuthAbortRequest();
s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest();
s32 PS4_SYSV_ABI sceNpAuthCreateRequest();
s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id);
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA();
s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3();
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA();
s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3();
s32 PS4_SYSV_ABI sceNpAuthPollAsync();
s32 PS4_SYSV_ABI sceNpAuthSetTimeout();
s32 PS4_SYSV_ABI sceNpAuthWaitAsync();
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpAuth

View file

@ -108,10 +108,22 @@ void Linker::Execute(const std::vector<std::string> args) {
static constexpr s64 InternalMemorySize = 0x1000000;
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(
&addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory");
s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(&addr_out, InternalMemorySize, 3,
0, "SceKernelInternalMemory");
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
// Simulate libSceGnmDriver initialization, which maps a chunk of direct memory.
// Some games fail without accurately emulating this behavior.
s64 phys_addr{};
ret = Libraries::Kernel::sceKernelAllocateDirectMemory(
0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr);
if (ret == 0) {
void* addr{reinterpret_cast<void*>(0xfe0000000)};
ret = Libraries::Kernel::sceKernelMapNamedDirectMemory(&addr, 0x10000, 0x13, 0, phys_addr,
0x10000, "SceGnmDriver");
}
ASSERT_MSG(ret == 0, "Unable to emulate libSceGnmDriver initialization");
main_thread.Run([this, module, args](std::stop_token) {
Common::SetCurrentThreadName("GAME_MainThread");
LoadSharedLibraries();

View file

@ -139,35 +139,35 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
alignment = alignment > 0 ? alignment : 16_KB;
auto dmem_area = FindDmemArea(search_start);
auto mapping_start = search_start > dmem_area->second.base
? Common::AlignUp(search_start, alignment)
: Common::AlignUp(dmem_area->second.base, alignment);
auto mapping_end = Common::AlignUp(mapping_start + size, alignment);
const auto is_suitable = [&] {
if (dmem_area == dmem_map.end()) {
return false;
}
const auto aligned_base = Common::AlignUp(dmem_area->second.base, alignment);
const auto alignment_size = aligned_base - dmem_area->second.base;
const auto remaining_size =
dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0;
return dmem_area->second.is_free && remaining_size >= size;
};
while (dmem_area != dmem_map.end() && !is_suitable() &&
dmem_area->second.GetEnd() <= search_end) {
++dmem_area;
// Find the first free, large enough dmem area in the range.
while ((!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) &&
dmem_area != dmem_map.end()) {
// The current dmem_area isn't suitable, move to the next one.
dmem_area++;
// Update local variables based on the new dmem_area
mapping_start = search_start > dmem_area->second.base
? Common::AlignUp(search_start, alignment)
: Common::AlignUp(dmem_area->second.base, alignment);
mapping_end = Common::AlignUp(mapping_start + size, alignment);
}
if (!is_suitable()) {
if (dmem_area == dmem_map.end()) {
// There are no suitable mappings in this range
LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size);
return -1;
}
// Align free position
PAddr free_addr = dmem_area->second.base;
free_addr = Common::AlignUp(free_addr, alignment);
// Add the allocated region to the list and commit its pages.
auto& area = CarveDmemArea(free_addr, size)->second;
auto& area = CarveDmemArea(mapping_start, size)->second;
area.memory_type = memory_type;
area.is_free = false;
return free_addr;
return mapping_start;
}
void MemoryManager::Free(PAddr phys_addr, size_t size) {
@ -632,17 +632,34 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si
auto dmem_area = FindDmemArea(search_start);
PAddr paddr{};
size_t max_size{};
while (dmem_area != dmem_map.end() && dmem_area->second.GetEnd() <= search_end) {
while (dmem_area != dmem_map.end()) {
if (!dmem_area->second.is_free) {
dmem_area++;
continue;
}
const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment)
: dmem_area->second.base;
auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment)
: dmem_area->second.base;
const auto alignment_size = aligned_base - dmem_area->second.base;
const auto remaining_size =
auto remaining_size =
dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0;
if (dmem_area->second.base < search_start) {
// We need to trim remaining_size to ignore addresses before search_start
remaining_size = remaining_size > (search_start - dmem_area->second.base)
? remaining_size - (search_start - dmem_area->second.base)
: 0;
aligned_base = alignment > 0 ? Common::AlignUp(search_start, alignment) : search_start;
}
if (dmem_area->second.GetEnd() > search_end) {
// We need to trim remaining_size to ignore addresses beyond search_end
remaining_size = remaining_size > (dmem_area->second.GetEnd() - search_end)
? remaining_size - (dmem_area->second.GetEnd() - search_end)
: 0;
}
if (remaining_size > max_size) {
paddr = aligned_base;
max_size = remaining_size;

View file

@ -127,58 +127,9 @@ tr("Do you want to overwrite existing mappings with the mappings from the Common
}
void KBMSettings::ButtonConnects() {
connect(ui->CrossButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->CrossButton); });
connect(ui->CircleButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->CircleButton); });
connect(ui->TriangleButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->TriangleButton); });
connect(ui->SquareButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->SquareButton); });
connect(ui->L1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L1Button); });
connect(ui->L2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L2Button); });
connect(ui->L3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L3Button); });
connect(ui->R1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R1Button); });
connect(ui->R2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R2Button); });
connect(ui->R3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R3Button); });
connect(ui->TouchpadButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->TouchpadButton); });
connect(ui->OptionsButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->OptionsButton); });
connect(ui->DpadUpButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->DpadUpButton); });
connect(ui->DpadDownButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->DpadDownButton); });
connect(ui->DpadLeftButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->DpadLeftButton); });
connect(ui->DpadRightButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->DpadRightButton); });
connect(ui->LStickUpButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->LStickUpButton); });
connect(ui->LStickDownButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->LStickDownButton); });
connect(ui->LStickLeftButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->LStickLeftButton); });
connect(ui->LStickRightButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->LStickRightButton); });
connect(ui->RStickUpButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->RStickUpButton); });
connect(ui->RStickDownButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->RStickDownButton); });
connect(ui->RStickLeftButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->RStickLeftButton); });
connect(ui->RStickRightButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->RStickRightButton); });
connect(ui->LHalfButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->LHalfButton); });
connect(ui->RHalfButton, &QPushButton::clicked, this,
[this]() { StartTimer(ui->RHalfButton); });
for (auto& button : ButtonsList) {
connect(button, &QPushButton::clicked, this, [this, &button]() { StartTimer(button); });
}
}
void KBMSettings::DisableMappingButtons() {

View file

@ -999,16 +999,13 @@ void Rasterizer::UpdateViewportScissorState() const {
boost::container::static_vector<vk::Viewport, Liverpool::NumViewports> viewports;
boost::container::static_vector<vk::Rect2D, Liverpool::NumViewports> scissors;
const auto& vp_ctl = regs.viewport_control;
const float reduce_z =
regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW ? 1.0f : 0.0f;
if (regs.polygon_control.enable_window_offset &&
(regs.window_offset.window_x_offset != 0 || regs.window_offset.window_y_offset != 0)) {
LOG_ERROR(Render_Vulkan,
"PA_SU_SC_MODE_CNTL.VTX_WINDOW_OFFSET_ENABLE support is not yet implemented.");
}
const auto& vp_ctl = regs.viewport_control;
for (u32 i = 0; i < Liverpool::NumViewports; i++) {
const auto& vp = regs.viewports[i];
const auto& vp_d = regs.viewport_depths[i];
@ -1019,16 +1016,32 @@ void Rasterizer::UpdateViewportScissorState() const {
const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f;
const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f;
vk::Viewport viewport = {
.minDepth = zoffset - zscale * reduce_z,
.maxDepth = zscale + zoffset,
};
vk::Viewport viewport{};
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_pipeline_graphics.c#L688-689
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_cmd_buffer.c#L3103-3109
// When the clip space is ranged [-1...1], the zoffset is centered.
// By reversing the above viewport calculations, we get the following:
if (regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW) {
viewport.minDepth = zoffset - zscale;
viewport.maxDepth = zoffset + zscale;
} else {
viewport.minDepth = zoffset;
viewport.maxDepth = zoffset + zscale;
}
if (!regs.depth_render_override.disable_viewport_clamp) {
// Apply depth clamp.
viewport.minDepth = std::max(viewport.minDepth, vp_d.zmin);
viewport.maxDepth = std::min(viewport.maxDepth, vp_d.zmax);
}
if (!instance.IsDepthRangeUnrestrictedSupported()) {
// Unrestricted depth range not supported by device. Make best attempt
// by restricting to valid range.
// Unrestricted depth range not supported by device. Restrict to valid range.
viewport.minDepth = std::max(viewport.minDepth, 0.f);
viewport.maxDepth = std::min(viewport.maxDepth, 1.f);
}
if (regs.IsClipDisabled()) {
// In case if clipping is disabled we patch the shader to convert vertex position
// from screen space coordinates to NDC by defining a render space as full hardware
@ -1048,6 +1061,7 @@ void Rasterizer::UpdateViewportScissorState() const {
viewport.width = xscale * 2.0f;
viewport.height = yscale * 2.0f;
}
viewports.push_back(viewport);
auto vp_scsr = scsr;