mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-12 20:55:56 +00:00
Merge branch 'main' into fontlib
This commit is contained in:
commit
479bca9c59
154 changed files with 7597 additions and 2130 deletions
|
@ -125,7 +125,6 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
|||
.count();
|
||||
count = WaitForSmallTimer(ev, num, std::max(0l, long(micros - time_waited)));
|
||||
}
|
||||
small_timer_event.event.data = 0;
|
||||
}
|
||||
|
||||
if (ev->flags & SceKernelEvent::Flags::OneShot) {
|
||||
|
@ -179,39 +178,46 @@ int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
|
|||
}
|
||||
|
||||
bool EqueueInternal::AddSmallTimer(EqueueEvent& ev) {
|
||||
// We assume that only one timer event (with the same ident across calls)
|
||||
// can be posted to the queue, based on observations so far. In the opposite case,
|
||||
// the small timer storage and wait logic should be reworked.
|
||||
ASSERT(!HasSmallTimer() || small_timer_event.event.ident == ev.event.ident);
|
||||
ev.time_added = std::chrono::steady_clock::now();
|
||||
small_timer_event = std::move(ev);
|
||||
SmallTimer st;
|
||||
st.event = ev.event;
|
||||
st.added = std::chrono::steady_clock::now();
|
||||
st.interval = std::chrono::microseconds{ev.event.data};
|
||||
{
|
||||
std::scoped_lock lock{m_mutex};
|
||||
m_small_timers[st.event.ident] = std::move(st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int EqueueInternal::WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros) {
|
||||
int count{};
|
||||
|
||||
ASSERT(num == 1);
|
||||
ASSERT(num >= 1);
|
||||
|
||||
auto curr_clock = std::chrono::steady_clock::now();
|
||||
const auto wait_end_us = (micros == 0) ? std::chrono::steady_clock::time_point::max()
|
||||
: curr_clock + std::chrono::microseconds{micros};
|
||||
|
||||
int count = 0;
|
||||
do {
|
||||
curr_clock = std::chrono::steady_clock::now();
|
||||
{
|
||||
std::scoped_lock lock{m_mutex};
|
||||
if ((curr_clock - small_timer_event.time_added) >
|
||||
std::chrono::microseconds{small_timer_event.event.data}) {
|
||||
ev[count++] = small_timer_event.event;
|
||||
small_timer_event.event.data = 0;
|
||||
break;
|
||||
for (auto it = m_small_timers.begin(); it != m_small_timers.end() && count < num;) {
|
||||
const SmallTimer& st = it->second;
|
||||
|
||||
if (curr_clock - st.added >= st.interval) {
|
||||
ev[count++] = st.event;
|
||||
it = m_small_timers.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
return count;
|
||||
}
|
||||
std::this_thread::yield();
|
||||
} while (curr_clock < wait_end_us);
|
||||
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EqueueInternal::EventExists(u64 id, s16 filter) {
|
||||
|
@ -326,6 +332,11 @@ s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec*
|
|||
// `HrTimerSpinlockThresholdUs`) and fall back to boost asio timers if the time to tick is
|
||||
// large. Even for large delays, we truncate a small portion to complete the wait
|
||||
// using the spinlock, prioritizing precision.
|
||||
|
||||
if (eq->EventExists(event.event.ident, event.event.filter)) {
|
||||
eq->RemoveEvent(id, SceKernelEvent::Filter::HrTimer);
|
||||
}
|
||||
|
||||
if (total_us < HrTimerSpinlockThresholdUs) {
|
||||
return eq->AddSmallTimer(event) ? ORBIS_OK : ORBIS_KERNEL_ERROR_ENOMEM;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <vector>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include "common/rdtsc.h"
|
||||
#include "common/types.h"
|
||||
|
||||
|
@ -135,6 +136,12 @@ private:
|
|||
};
|
||||
|
||||
class EqueueInternal {
|
||||
struct SmallTimer {
|
||||
SceKernelEvent event;
|
||||
std::chrono::steady_clock::time_point added;
|
||||
std::chrono::microseconds interval;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit EqueueInternal(std::string_view name) : m_name(name) {}
|
||||
|
||||
|
@ -151,13 +158,14 @@ public:
|
|||
int GetTriggeredEvents(SceKernelEvent* ev, int num);
|
||||
|
||||
bool AddSmallTimer(EqueueEvent& event);
|
||||
bool HasSmallTimer() const {
|
||||
return small_timer_event.event.data != 0;
|
||||
bool HasSmallTimer() {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
return !m_small_timers.empty();
|
||||
}
|
||||
bool RemoveSmallTimer(u64 id) {
|
||||
if (HasSmallTimer() && small_timer_event.event.ident == id) {
|
||||
small_timer_event = {};
|
||||
return true;
|
||||
if (HasSmallTimer()) {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
return m_small_timers.erase(id) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -170,8 +178,8 @@ private:
|
|||
std::string m_name;
|
||||
std::mutex m_mutex;
|
||||
std::vector<EqueueEvent> m_events;
|
||||
EqueueEvent small_timer_event{};
|
||||
std::condition_variable m_cond;
|
||||
std::unordered_map<u64, SmallTimer> m_small_timers;
|
||||
};
|
||||
|
||||
u64 PS4_SYSV_ABI sceKernelGetEventData(const SceKernelEvent* ev);
|
||||
|
|
|
@ -293,6 +293,7 @@ s64 PS4_SYSV_ABI write(s32 fd, const void* buf, size_t nbytes) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return file->f.WriteRaw<u8>(buf, nbytes);
|
||||
}
|
||||
|
||||
|
@ -750,7 +751,24 @@ s32 PS4_SYSV_ABI posix_rename(const char* from, const char* to) {
|
|||
*__Error() = POSIX_ENOTEMPTY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// On Windows, std::filesystem::rename will error if the file has been opened before.
|
||||
std::filesystem::copy(src_path, dst_path, std::filesystem::copy_options::overwrite_existing);
|
||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||
auto file = h->GetFile(src_path);
|
||||
if (file) {
|
||||
// We need to force ReadWrite if the file had Write access before
|
||||
// Otherwise f.Open will clear the file contents.
|
||||
auto access_mode = file->f.GetAccessMode() == Common::FS::FileAccessMode::Write
|
||||
? Common::FS::FileAccessMode::ReadWrite
|
||||
: file->f.GetAccessMode();
|
||||
file->f.Close();
|
||||
std::filesystem::remove(src_path);
|
||||
file->f.Open(dst_path, access_mode);
|
||||
} else {
|
||||
std::filesystem::remove(src_path);
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -1050,6 +1068,7 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
|
||||
LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, readv);
|
||||
LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, writev);
|
||||
LIB_FUNCTION("kAt6VDbHmro", "libkernel", 1, "libkernel", 1, 1, sceKernelWritev);
|
||||
LIB_FUNCTION("Oy6IpwgtYOk", "libScePosix", 1, "libkernel", 1, 1, posix_lseek);
|
||||
LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, posix_lseek);
|
||||
LIB_FUNCTION("oib76F-12fk", "libkernel", 1, "libkernel", 1, 1, sceKernelLseek);
|
||||
|
|
|
@ -273,6 +273,10 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ...
|
||||
LIB_FUNCTION("4n51s0zEf0c", "libScePosix", 1, "libkernel", 1, 1,
|
||||
Libraries::Net::sceNetInetPton); // TODO fix it to sys_ ...
|
||||
LIB_FUNCTION("XVL8So3QJUk", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_connect);
|
||||
LIB_FUNCTION("3e+4Iv7IJ8U", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_accept);
|
||||
LIB_FUNCTION("aNeavPDNKzA", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_sendmsg);
|
||||
LIB_FUNCTION("pxnCmagrtao", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_listen);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -99,8 +99,8 @@ s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len) {
|
|||
s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchEnd,
|
||||
size_t alignment, u64* physAddrOut,
|
||||
size_t* sizeOut) {
|
||||
LOG_WARNING(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}",
|
||||
searchStart, searchEnd, alignment);
|
||||
LOG_INFO(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}",
|
||||
searchStart, searchEnd, alignment);
|
||||
|
||||
if (physAddrOut == nullptr || sizeOut == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
|
@ -222,9 +222,10 @@ s32 PS4_SYSV_ABI sceKernelMapDirectMemory2(void** addr, u64 len, s32 type, s32 p
|
|||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags, const char* name) {
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags,
|
||||
const char* name) {
|
||||
LOG_INFO(Kernel_Vmm, "in_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, name = '{}'",
|
||||
fmt::ptr(*addr_in_out), len, prot, flags, name);
|
||||
if (len == 0 || !Common::Is16KBAligned(len)) {
|
||||
LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
|
@ -243,18 +244,14 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t
|
|||
const VAddr in_addr = reinterpret_cast<VAddr>(*addr_in_out);
|
||||
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
||||
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
|
||||
SCOPE_EXIT {
|
||||
LOG_INFO(Kernel_Vmm,
|
||||
"in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}",
|
||||
in_addr, fmt::ptr(*addr_in_out), len, prot, flags);
|
||||
};
|
||||
auto* memory = Core::Memory::Instance();
|
||||
return memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
|
||||
Core::VMAType::Flexible, name);
|
||||
const auto ret = memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
|
||||
Core::VMAType::Flexible, name);
|
||||
LOG_INFO(Kernel_Vmm, "out_addr = {}", fmt::ptr(*addr_in_out));
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags) {
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags) {
|
||||
return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "anon");
|
||||
}
|
||||
|
||||
|
@ -290,7 +287,7 @@ s32 PS4_SYSV_ABI sceKernelMtypeprotect(const void* addr, u64 size, s32 mtype, s3
|
|||
|
||||
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
|
||||
size_t infoSize) {
|
||||
LOG_WARNING(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags);
|
||||
LOG_INFO(Kernel_Vmm, "called offset = {:#x}, flags = {:#x}", offset, flags);
|
||||
auto* memory = Core::Memory::Instance();
|
||||
return memory->DirectMemoryQuery(offset, flags == 1, query_info);
|
||||
}
|
||||
|
@ -663,6 +660,9 @@ int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) {
|
|||
"PRT aperture id = {}, address = {:#x}, size = {:#x} is set but not used", id,
|
||||
address, size);
|
||||
|
||||
auto* memory = Core::Memory::Instance();
|
||||
memory->SetPrtArea(id, address, size);
|
||||
|
||||
PrtApertures[id] = {address, size};
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
|
|
@ -141,10 +141,9 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
|
|||
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info,
|
||||
size_t infoSize);
|
||||
s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment);
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot,
|
||||
int flags, const char* name);
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
|
||||
int flags);
|
||||
s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags,
|
||||
const char* name);
|
||||
s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags);
|
||||
int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot);
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelMprotect(const void* addr, u64 size, s32 prot);
|
||||
|
|
|
@ -426,6 +426,7 @@ void RegisterMutex(Core::Loader::SymbolsResolver* sym) {
|
|||
// Posix
|
||||
LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init);
|
||||
LIB_FUNCTION("7H0iTOciTLo", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_lock);
|
||||
LIB_FUNCTION("Io9+nTKXZtA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_timedlock);
|
||||
LIB_FUNCTION("2Z+PpY6CaJg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_unlock);
|
||||
LIB_FUNCTION("ltCfaGr2JGE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_destroy);
|
||||
LIB_FUNCTION("dQHWEsJtoE4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutexattr_init);
|
||||
|
|
|
@ -164,10 +164,12 @@ s32 PS4_SYSV_ABI sceNpTrophyCreateContext(OrbisNpTrophyContext* context, int32_t
|
|||
}
|
||||
|
||||
const auto ctx_id = trophy_contexts.insert(user_id, service_label);
|
||||
contexts_internal[key].context_id = ctx_id.index;
|
||||
LOG_INFO(Lib_NpTrophy, "New context = {}, user_id = {} service label = {}", ctx_id.index,
|
||||
user_id, service_label);
|
||||
*context = ctx_id.index;
|
||||
|
||||
*context = ctx_id.index + 1;
|
||||
contexts_internal[key].context_id = *context;
|
||||
LOG_INFO(Lib_NpTrophy, "New context = {}, user_id = {} service label = {}", *context, user_id,
|
||||
service_label);
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -179,21 +181,23 @@ s32 PS4_SYSV_ABI sceNpTrophyCreateHandle(OrbisNpTrophyHandle* handle) {
|
|||
if (trophy_handles.size() >= MaxTrophyHandles) {
|
||||
return ORBIS_NP_TROPHY_ERROR_HANDLE_EXCEEDS_MAX;
|
||||
}
|
||||
const auto handle_id = trophy_handles.insert();
|
||||
LOG_INFO(Lib_NpTrophy, "New handle = {}", handle_id.index);
|
||||
|
||||
*handle = handle_id.index;
|
||||
const auto handle_id = trophy_handles.insert();
|
||||
|
||||
*handle = handle_id.index + 1;
|
||||
LOG_INFO(Lib_NpTrophy, "New handle = {}", *handle);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNpTrophyDestroyContext(OrbisNpTrophyContext context) {
|
||||
LOG_INFO(Lib_NpTrophy, "Destroyed Context {}", context);
|
||||
|
||||
if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT)
|
||||
if (context == ORBIS_NP_TROPHY_INVALID_CONTEXT) {
|
||||
return ORBIS_NP_TROPHY_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
Common::SlotId contextId;
|
||||
contextId.index = context;
|
||||
contextId.index = context - 1;
|
||||
|
||||
ContextKey contextkey = trophy_contexts[contextId];
|
||||
trophy_contexts.erase(contextId);
|
||||
|
@ -206,15 +210,17 @@ s32 PS4_SYSV_ABI sceNpTrophyDestroyHandle(OrbisNpTrophyHandle handle) {
|
|||
if (handle == ORBIS_NP_TROPHY_INVALID_HANDLE)
|
||||
return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE;
|
||||
|
||||
if (handle >= trophy_handles.size()) {
|
||||
s32 handle_index = handle - 1;
|
||||
if (handle_index >= trophy_handles.size()) {
|
||||
LOG_ERROR(Lib_NpTrophy, "Invalid handle {}", handle);
|
||||
return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (!trophy_handles.is_allocated({static_cast<u32>(handle)})) {
|
||||
|
||||
if (!trophy_handles.is_allocated({static_cast<u32>(handle_index)})) {
|
||||
return ORBIS_NP_TROPHY_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
trophy_handles.erase({static_cast<u32>(handle)});
|
||||
trophy_handles.erase({static_cast<u32>(handle_index)});
|
||||
LOG_INFO(Lib_NpTrophy, "Handle {} destroyed", handle);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ s32 PS4_SYSV_ABI sceVideodec2Flush(OrbisVideodec2Decoder decoder,
|
|||
return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
if (frameBuffer->thisSize != sizeof(OrbisVideodec2FrameBuffer) ||
|
||||
outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
(outputInfo->thisSize | 8) != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp
|
|||
LOG_ERROR(Lib_Vdec2, "Invalid arguments");
|
||||
return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
||||
}
|
||||
if (outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
if ((outputInfo->thisSize | 8) != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp
|
|||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2AvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2AvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if (picInfo->thisSize != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
if ((picInfo->thisSize | 16) != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,10 @@ struct OrbisVideodec2OutputInfo {
|
|||
u32 frameHeight;
|
||||
void* frameBuffer;
|
||||
u64 frameBufferSize;
|
||||
u32 frameFormat;
|
||||
u32 framePitchInBytes;
|
||||
};
|
||||
static_assert(sizeof(OrbisVideodec2OutputInfo) == 0x30);
|
||||
static_assert(sizeof(OrbisVideodec2OutputInfo) == 0x38);
|
||||
|
||||
struct OrbisVideodec2FrameBuffer {
|
||||
u64 thisSize;
|
||||
|
|
|
@ -55,6 +55,23 @@ struct OrbisVideodec2AvcPictureInfo {
|
|||
u8 pic_struct;
|
||||
u8 field_pic_flag;
|
||||
u8 bottom_field_flag;
|
||||
|
||||
u8 sequenceParameterSetPresentFlag;
|
||||
u8 pictureParameterSetPresentFlag;
|
||||
u8 auDelimiterPresentFlag;
|
||||
u8 endOfSequencePresentFlag;
|
||||
u8 endOfStreamPresentFlag;
|
||||
u8 fillerDataPresentFlag;
|
||||
u8 pictureTimingSeiPresentFlag;
|
||||
u8 bufferingPeriodSeiPresentFlag;
|
||||
|
||||
u8 constraint_set0_flag;
|
||||
u8 constraint_set1_flag;
|
||||
u8 constraint_set2_flag;
|
||||
u8 constraint_set3_flag;
|
||||
u8 constraint_set4_flag;
|
||||
u8 constraint_set5_flag;
|
||||
};
|
||||
static_assert(sizeof(OrbisVideodec2AvcPictureInfo) == 0x78);
|
||||
|
||||
} // namespace Libraries::Vdec2
|
|
@ -44,11 +44,15 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData,
|
|||
OrbisVideodec2FrameBuffer& frameBuffer,
|
||||
OrbisVideodec2OutputInfo& outputInfo) {
|
||||
frameBuffer.isAccepted = false;
|
||||
outputInfo.thisSize = sizeof(OrbisVideodec2OutputInfo);
|
||||
outputInfo.isValid = false;
|
||||
outputInfo.isErrorFrame = true;
|
||||
outputInfo.pictureCount = 0;
|
||||
|
||||
// Only set frameFormat if the game uses the newer struct version.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
outputInfo.frameFormat = 0;
|
||||
}
|
||||
|
||||
if (!inputData.auData) {
|
||||
return ORBIS_VIDEODEC2_ERROR_ACCESS_UNIT_POINTER;
|
||||
}
|
||||
|
@ -113,6 +117,11 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData,
|
|||
outputInfo.isErrorFrame = false;
|
||||
outputInfo.pictureCount = 1; // TODO: 2 pictures for interlaced video
|
||||
|
||||
// Only set framePitchInBytes if the game uses the newer struct version.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
outputInfo.framePitchInBytes = frame->linesize[0];
|
||||
}
|
||||
|
||||
if (outputInfo.isValid) {
|
||||
OrbisVideodec2AvcPictureInfo pictureInfo = {};
|
||||
|
||||
|
@ -140,11 +149,15 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData,
|
|||
s32 VdecDecoder::Flush(OrbisVideodec2FrameBuffer& frameBuffer,
|
||||
OrbisVideodec2OutputInfo& outputInfo) {
|
||||
frameBuffer.isAccepted = false;
|
||||
outputInfo.thisSize = sizeof(OrbisVideodec2OutputInfo);
|
||||
outputInfo.isValid = false;
|
||||
outputInfo.isErrorFrame = true;
|
||||
outputInfo.pictureCount = 0;
|
||||
|
||||
// Only set frameFormat if the game uses the newer struct version.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
outputInfo.frameFormat = 0;
|
||||
}
|
||||
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
if (!frame) {
|
||||
LOG_ERROR(Lib_Vdec2, "Failed to allocate frame");
|
||||
|
@ -182,6 +195,11 @@ s32 VdecDecoder::Flush(OrbisVideodec2FrameBuffer& frameBuffer,
|
|||
outputInfo.isErrorFrame = false;
|
||||
outputInfo.pictureCount = 1; // TODO: 2 pictures for interlaced video
|
||||
|
||||
// Only set framePitchInBytes if the game uses the newer struct version.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
outputInfo.framePitchInBytes = frame->linesize[0];
|
||||
}
|
||||
|
||||
// FIXME: Should we add picture info here too?
|
||||
}
|
||||
|
||||
|
|
|
@ -282,7 +282,12 @@ s32 PS4_SYSV_ABI sceVideoOutGetVblankStatus(int handle, SceVideoOutVblankStatus*
|
|||
|
||||
s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status) {
|
||||
LOG_INFO(Lib_VideoOut, "called");
|
||||
*status = driver->GetPort(handle)->resolution;
|
||||
auto* port = driver->GetPort(handle);
|
||||
if (!port || !port->is_open) {
|
||||
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
*status = port->resolution;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ void ZlibTaskThread(const std::stop_token& stop) {
|
|||
if (!task_queue_cv.wait(lock, stop, [&] { return !task_queue.empty(); })) {
|
||||
break;
|
||||
}
|
||||
task = task_queue.back();
|
||||
task = task_queue.front();
|
||||
task_queue.pop();
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ s32 PS4_SYSV_ABI sceZlibWaitForDone(u64* request_id, const u32* timeout) {
|
|||
} else {
|
||||
done_queue_cv.wait(lock, pred);
|
||||
}
|
||||
*request_id = done_queue.back();
|
||||
*request_id = done_queue.front();
|
||||
done_queue.pop();
|
||||
}
|
||||
return ORBIS_OK;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue