diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index f948836ef5..4267e56f91 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -28,6 +28,7 @@ CPUThread::CPUThread(CPUThreadType type) , m_is_step(false) , m_is_branch(false) , m_status(Stopped) + , m_last_syscall(0) { } @@ -284,7 +285,8 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) // TODO: allow recovering from a page fault //GetCurrentPPUThread().Stop(); Emu.Pause(); - throw fmt::Format("Access violation: addr = 0x%x", (u32)addr); + throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx)", + (u32)addr, (u64)GetCurrentCPUThread()->m_last_syscall); } else { diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 343f992d8f..2ecd40ad4a 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -133,6 +133,7 @@ public: bool m_is_interrupt; bool m_has_interrupt; u64 m_interrupt_arg; + u64 m_last_syscall; protected: CPUThread(CPUThreadType type); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 2f793db9c9..3f27b769ca 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -66,6 +66,7 @@ private: void SysCall() { + CPU.m_last_syscall = CPU.GPR[11]; SysCalls::DoSyscall(CPU.GPR[11]); if(Ini.HLELogging.GetValue()) @@ -81,6 +82,8 @@ private: #ifdef HLE_CALL_DEBUG LOG_NOTICE(PPU, "SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); #endif + + CPU.m_last_syscall = 0; } void NULL_OP() diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 6146a3fcc1..c19f1e27db 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1025,113 +1025,219 @@ s32 cellSyncQueueClear(mem_ptr_t queue) int cellSyncLFQueueGetEntrySize() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("cellSyncLFQueueGetEntrySize()"); return CELL_OK; } + int cellSyncLFQueueSize() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("cellSyncLFQueueSize()"); return CELL_OK; } int cellSyncLFQueueClear() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("cellSyncLFQueueClear()"); return CELL_OK; } + int _cellSyncLFQueueCompletePushPointer2() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueCompletePushPointer2()"); return CELL_OK; } int _cellSyncLFQueueGetPopPointer2() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueGetPopPointer2()"); return CELL_OK; } int _cellSyncLFQueueCompletePushPointer() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueCompletePushPointer()"); return CELL_OK; } int _cellSyncLFQueueAttachLv2EventQueue() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueAttachLv2EventQueue()"); return CELL_OK; } int _cellSyncLFQueueGetPushPointer2() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueGetPushPointer2()"); return CELL_OK; } int _cellSyncLFQueueGetPopPointer() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueGetPopPointer()"); return CELL_OK; } int _cellSyncLFQueueCompletePopPointer2() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueCompletePopPointer2()"); return CELL_OK; } int _cellSyncLFQueueDetachLv2EventQueue() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueDetachLv2EventQueue()"); return CELL_OK; } -int cellSyncLFQueueInitialize() +void syncLFQueueInitialize(mem_ptr_t ea, u32 buffer_addr, u32 size, u32 depth, CellSyncQueueDirection direction, u32 eaSignal_addr) { - UNIMPLEMENTED_FUNC(cellSync); + +} + +int cellSyncLFQueueInitialize(mem_ptr_t ea, u32 buffer_addr, u32 size, u32 depth, CellSyncQueueDirection direction, u32 eaSignal_addr) +{ + cellSync->Todo("cellSyncLFQueueInitialize(ea_addr=0x%x, buffer_addr=0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal_addr=0x%x)", + ea.GetAddr(), buffer_addr, size, depth, direction, eaSignal_addr); + + if (!ea) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (size) + { + if (!buffer_addr) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (size > 0x4000 || size % 16) + { + return CELL_SYNC_ERROR_INVAL; + } + } + if (!depth || (depth >> 15) || direction > 3) + { + return CELL_SYNC_ERROR_INVAL; + } + if (ea.GetAddr() % 128 || buffer_addr % 16) + { + return CELL_SYNC_ERROR_ALIGN; + } + + // prx: get sdk version of current process, return non-zero result of sys_process_get_sdk_version + s32 sdk_ver; + s32 ret = process_get_sdk_version(process_getpid(), sdk_ver); + if (ret != CELL_OK) + { + return ret; + } + if (sdk_ver == -1) + { + sdk_ver = 0x460000; + } + + // prx: reserve u32 at 0x2c offset + u32 old_value; + while (true) + { + const u32 old_data = ea->m_data1(); + CellSyncLFQueue new_data; + new_data.m_data1() = old_data; + + if (old_data) + { + if (sdk_ver > 0x17ffff && old_data != se32(2)) + { + return CELL_SYNC_ERROR_STAT; + } + old_value = old_data; + } + else + { + if (sdk_ver > 0x17ffff) + { + for (u32 i = 0; i < sizeof(CellSyncLFQueue) / sizeof(u64); i++) + { + if ((u64&)Memory[ea.GetAddr() + i * sizeof(u64)]) + { + return CELL_SYNC_ERROR_STAT; + } + } + } + new_data.m_data1() = se32(1); + old_value = se32(1); + } + + if (InterlockedCompareExchange(&ea->m_data1(), new_data.m_data1(), old_data) == old_data) break; + } + + if (old_value == se32(2)) + { + if ((u32)ea->m_size != size || (u32)ea->m_depth != depth || (u64)ea->m_buffer != (u64)buffer_addr) + { + return CELL_SYNC_ERROR_INVAL; + } + if (sdk_ver > 0x17ffff) + { + if ((u64)ea->m_eaSignal != (u64)eaSignal_addr || (u32)ea->m_direction != direction) + { + return CELL_SYNC_ERROR_INVAL; + } + } + } + else + { + // prx: call internal function with same arguments + + + // prx: sync, zeroize u32 at 0x2c offset + InterlockedCompareExchange(&ea->m_data1(), 0, 0); + ea->m_data1() = 0; + } + + // prx: sync + InterlockedCompareExchange(&ea->m_data1(), 0, 0); return CELL_OK; } int _cellSyncLFQueueGetSignalAddress() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueGetSignalAddress()"); return CELL_OK; } int _cellSyncLFQueuePushBody() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueuePushBody()"); return CELL_OK; } int cellSyncLFQueueGetDirection() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("cellSyncLFQueueGetDirection()"); return CELL_OK; } int cellSyncLFQueueDepth() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("cellSyncLFQueueDepth()"); return CELL_OK; } int _cellSyncLFQueuePopBody() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueuePopBody()"); return CELL_OK; } int _cellSyncLFQueueGetPushPointer() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueGetPushPointer()"); return CELL_OK; } int _cellSyncLFQueueCompletePopPointer() { - UNIMPLEMENTED_FUNC(cellSync); + cellSync->Todo("_cellSyncLFQueueCompletePopPointer()"); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.h b/rpcs3/Emu/SysCalls/Modules/cellSync.h index 4e24b4cbad..ff941b65d4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.h @@ -85,4 +85,41 @@ struct CellSyncQueue }; }; -static_assert(sizeof(CellSyncQueue) == 32, "CellSyncQueue: wrong size"); \ No newline at end of file +static_assert(sizeof(CellSyncQueue) == 32, "CellSyncQueue: wrong size"); + +enum CellSyncQueueDirection : u32 +{ + CELL_SYNC_QUEUE_SPU2SPU = 0, // SPU to SPU + CELL_SYNC_QUEUE_SPU2PPU = 1, // SPU to PPU + CELL_SYNC_QUEUE_PPU2SPU = 2, // PPU to SPU + CELL_SYNC_QUEUE_ANY2ANY = 3, // SPU/PPU to SPU/PPU +}; + +struct CellSyncLFQueue +{ + be_t m_v1; + be_t m_v2; + be_t m_size; + be_t m_depth; + be_t m_buffer; + be_t m_v5; + be_t m_direction; + be_t m_v6; + be_t m_v7; + be_t m_v8; + be_t m_v9; + be_t m_v10; + be_t m_v11; + be_t m_v12; + be_t m_v13; + be_t m_v14; + be_t m_eaSignal; + be_t reserved; + + volatile u32& m_data1() + { + return *reinterpret_cast((u8*)this + 0x2c); + } +}; + +static_assert(sizeof(CellSyncLFQueue) == 128, "CellSyncLFQueue: wrong size"); \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp index ecb7f302bc..f36e417ec2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp @@ -10,10 +10,16 @@ SysCallBase sc_p("Process"); sysProcessObjects_t procObjects; +s32 process_getpid() +{ + // TODO: get current process id + return 1; +} + s32 sys_process_getpid() { sc_p.Log("sys_process_getpid() -> 1"); - return 1; + return process_getpid(); } s32 sys_process_getppid() @@ -228,12 +234,29 @@ s32 sys_process_get_paramsfo(mem8_ptr_t buffer) return CELL_OK;*/ } +s32 process_get_sdk_version(u32 pid, s32& ver) +{ + // TODO: get correct SDK version for selected pid + ver = Emu.m_sdk_version; + + return CELL_OK; +} + s32 sys_process_get_sdk_version(u32 pid, mem32_t version) { sc_p.Warning("sys_process_get_sdk_version(pid=%d, version_addr=0x%x)", pid, version.GetAddr()); - version = 0x360001; // TODO - return CELL_OK; + s32 sdk_ver; + s32 ret = process_get_sdk_version(pid, sdk_ver); + if (ret != CELL_OK) + { + return ret; // error code + } + else + { + version = sdk_ver; + return CELL_OK; + } } s32 sys_process_kill(u32 pid) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.h b/rpcs3/Emu/SysCalls/lv2/sys_process.h index 3ec275818b..8d14099c05 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.h @@ -51,6 +51,10 @@ struct sysProcessObjects_t // Extern extern sysProcessObjects_t procObjects; +// Auxiliary functions +s32 process_getpid(); +s32 process_get_sdk_version(u32 pid, s32& ver); + // SysCalls s32 sys_process_getpid(); s32 sys_process_getppid(); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp index f1eb9d6936..98d8dd60b2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp @@ -10,11 +10,6 @@ s32 sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr { sys_rwlock.Warning("sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr()); - if (!rw_lock_id.GetAddr() || !attr.GetAddr()) - { - return CELL_EFAULT; - } - switch (attr->attr_protocol.ToBE()) { case se(attr->attr_protocol, SYS_SYNC_PRIORITY): sys_rwlock.Todo("SYS_SYNC_PRIORITY"); break; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 0d393eaec1..efb280d2c0 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -298,7 +298,7 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) } if (Emu.IsStopped()) { - LOG_WARNING(Log::SPU, "sys_spu_thread_group_join(id=%d, ...) aborted", id); + LOG_WARNING(Log::SPU, "sys_spu_thread_group_join(id=%d) aborted", id); return CELL_OK; } std::this_thread::sleep_for(std::chrono::milliseconds(1)); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 87d9b12369..0745e1c49c 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -16,7 +16,7 @@ #include "Emu/CPU/CPUThreadManager.h" //gui dependency -#include "../Loader/PSF.h" +#include "Loader/PSF.h" #include "../Crypto/unself.h" #include @@ -270,6 +270,26 @@ void Emulator::Load() return; } + // setting default values + Emu.m_sdk_version = -1; // possibly "unknown" value + + // trying to load some info from PARAM.SFO + vfsFile f2("/app_home/PARAM.SFO"); + if (f2.IsOpened()) + { + PSFLoader psf(f2); + if (psf.Load(false)) + { + std::string version = psf.GetString("PS3_SYSTEM_VER"); + + const size_t dot = version.find('.'); + if (dot != std::string::npos) + { + Emu.m_sdk_version = (std::stoi(version, nullptr, 16) << 20) | ((std::stoi(version.substr(dot + 1), nullptr, 16) & 0xffff) << 4) | 1; + } + } + } + LoadPoints(BreakPointsDBName); CPUThread& thread = GetCPU().AddThread(thread_type); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 7052d05118..f2500878ac 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -106,6 +106,7 @@ public: std::string m_path; std::string m_elf_path; std::string m_title_id; + s32 m_sdk_version; Emulator();