From 373d189edbde68735ac20a66e597dcbca2758bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Thu, 13 Feb 2014 12:13:05 +0100 Subject: [PATCH] Merge pull request #70 from Nekotekina/rpcs3 and conflicts fixed. --- Utilities/IdManager.h | 8 +- Utilities/SMutex.h | 14 +- Utilities/Thread.cpp | 2 +- rpcs3/Emu/CPU/CPUThreadManager.cpp | 2 + rpcs3/Emu/Cell/SPUThread.h | 9 +- rpcs3/Emu/Event.cpp | 61 ++++ rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 284 ++++++++++++------ rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 4 +- rpcs3/Emu/SysCalls/SysCalls.cpp | 16 +- rpcs3/Emu/SysCalls/SysCalls.h | 49 ++-- rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp | 7 +- rpcs3/Emu/SysCalls/lv2/SC_Event.cpp | 359 +++++++++++++++++++---- rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp | 24 +- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 34 +-- rpcs3/Emu/SysCalls/lv2/SC_Heap.cpp | 8 +- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp | 12 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 174 ++++++++++- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h | 168 +---------- rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp | 11 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 7 +- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp | 20 +- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 201 +++++++++---- rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp | 8 +- rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp | 2 +- rpcs3/Emu/System.cpp | 2 + rpcs3/Emu/System.h | 3 + rpcs3/Emu/event.h | 217 ++++++++++++-- rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 + 29 files changed, 1231 insertions(+), 479 deletions(-) create mode 100644 rpcs3/Emu/Event.cpp diff --git a/Utilities/IdManager.h b/Utilities/IdManager.h index 527fcb320f..d543769356 100644 --- a/Utilities/IdManager.h +++ b/Utilities/IdManager.h @@ -132,10 +132,12 @@ public: bool HasID(const s64 id) { - std::lock_guard lock(m_mtx_main); + { + std::lock_guard lock(m_mtx_main); - if(id == wxID_ANY) - return m_id_map.begin() != m_id_map.end(); + if(id == wxID_ANY) + return m_id_map.begin() != m_id_map.end(); + } return CheckID(id); } diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index ac5ec269e8..3746620526 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -1,5 +1,4 @@ #pragma once -#include extern void SM_Sleep(); extern DWORD SM_GetCurrentThreadId(); @@ -49,6 +48,10 @@ public: SMutexResult trylock(T tid) { + if (Emu.IsStopped()) + { + return SMR_ABORT; + } T old = (T)free_value; if (!owner.compare_exchange_strong(old, tid)) @@ -57,15 +60,10 @@ public: { return SMR_DEADLOCK; } - if (Emu.IsStopped()) - { - return SMR_ABORT; - } if (old == (T)dead_value) { return SMR_DESTROYED; } - return SMR_FAILED; } @@ -74,6 +72,10 @@ public: SMutexResult unlock(T tid, T to = (T)free_value) { + if (Emu.IsStopped()) + { + return SMR_ABORT; + } T old = tid; if (!owner.compare_exchange_strong(old, to)) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 17c58d3ef6..017562955f 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -111,7 +111,7 @@ thread::thread() } void thread::start(std::function func) -{ +{ // got a crash related with strings m_thr = std::thread([this, func]() { NamedThreadBase info(m_name); g_tls_this_thread = &info; func(); }); } diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index 389d6d894b..a3a60a365f 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -93,6 +93,8 @@ CPUThread* CPUThreadManager::GetThread(u32 id) { CPUThread* res; + if (!id) return nullptr; + if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr; return res; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index c0ca556aaa..85eb81c291 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -601,13 +601,16 @@ public: u32 GetChannelCount(u32 ch) { + u32 count; switch(ch) { case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); case SPU_RdInMbox: - return SPU.In_MBox.GetCount(); + count = SPU.In_MBox.GetCount(); + ConLog.Warning("GetChannelCount(%s) -> %d", spu_ch_name[ch], count); + return count; case SPU_WrOutIntrMbox: ConLog.Warning("GetChannelCount(%s) = 0", spu_ch_name[ch]); @@ -688,6 +691,8 @@ public: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } + + if (Emu.IsStopped()) ConLog.Warning("%s: %s writing aborted", __FUNCTION__, spu_ch_name[ch]); } void ReadChannel(SPU_GPR_hdr& r, u32 ch) @@ -725,6 +730,8 @@ public: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } + + if (Emu.IsStopped()) ConLog.Warning("%s: %s aborted", __FUNCTION__, spu_ch_name[ch]); } bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; } diff --git a/rpcs3/Emu/Event.cpp b/rpcs3/Emu/Event.cpp new file mode 100644 index 0000000000..d9efcc7267 --- /dev/null +++ b/rpcs3/Emu/Event.cpp @@ -0,0 +1,61 @@ +#include "stdafx.h" +#include "event.h" + +void EventManager::Init() +{ + +} + +void EventManager::Clear() +{ + key_map.clear(); +} + +bool EventManager::CheckKey(u64 key) +{ + if (!key) return true; + SMutexLocker lock(m_lock); + + return key_map.find(key) != key_map.end(); +} + +bool EventManager::RegisterKey(EventQueue* data, u64 key) +{ + if (!key) return true; + SMutexLocker lock(m_lock); + + if (key_map.find(key) != key_map.end()) return false; + + key_map[key] = data; + + return true; +} + +bool EventManager::GetEventQueue(u64 key, EventQueue*& data) +{ + data = nullptr; + if (!key) return false; + SMutexLocker lock(m_lock); + + auto f = key_map.find(key); + if (f != key_map.end()) + { + data = f->second; + return true; + } + return false; +} + +bool EventManager::UnregisterKey(u64 key) +{ + if (!key) return false; + SMutexLocker lock(m_lock); + + auto f = key_map.find(key); + if (f != key_map.end()) + { + key_map.erase(f); + return true; + } + return false; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 2cdafe3fe0..0e4e45186a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -4,8 +4,9 @@ #include "Emu/Audio/cellAudio.h" void cellAudio_init(); +void cellAudio_load(); void cellAudio_unload(); -Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload); +Module cellAudio(0x0011, cellAudio_init, cellAudio_load, cellAudio_unload); enum { @@ -80,16 +81,66 @@ struct CellAudioPortConfig be_t portAddr; }; -struct CellAudioConfig //custom structure +struct AudioPortConfig { - bool m_is_audio_initialized; - bool m_is_audio_port_opened; bool m_is_audio_port_started; + CellAudioPortParam m_param; + + const u32 m_buffer; // 64 KB or 128 KB with 8x16 config + const u32 m_index; + + AudioPortConfig(); + + ~AudioPortConfig(); }; -CellAudioPortParam* m_param = new CellAudioPortParam; +struct AudioConfig //custom structure +{ + Array m_ports; + bool m_is_audio_initialized; + u32 m_port_in_use; + u64 event_key; -CellAudioConfig* m_config = new CellAudioConfig; + AudioConfig() + : m_is_audio_initialized(false) + , m_port_in_use(0) + , event_key(0) + { + m_ports.SetCount(8); + for (u32 i = 0; i < m_ports.GetCount(); i++) + m_ports[i] = nullptr; + } + + void Clear() + { + for (u32 i = 0; i < m_ports.GetCount(); i++) + { + if (m_ports[i]) + { + delete m_ports[i]; + m_ports[i] = nullptr; + } + } + m_port_in_use = 0; + } +} m_config; + +AudioPortConfig::AudioPortConfig() + : m_is_audio_port_started(false) + , m_buffer(Memory.Alloc(1024 * 128, 1024)) + , m_index(Memory.Alloc(16, 16)) +{ + m_config.m_port_in_use++; + mem64_t index(m_index); + index = 0; +} + +AudioPortConfig::~AudioPortConfig() +{ + m_config.m_port_in_use--; + Memory.Free(m_buffer); + Memory.Free(m_index); +} //libmixer datatypes typedef void * CellAANHandle; @@ -197,68 +248,94 @@ struct CellSoundSynth2EffectAttr int cellAudioInit() { cellAudio.Warning("cellAudioInit()"); - if(m_config->m_is_audio_initialized == true) return CELL_AUDIO_ERROR_ALREADY_INIT; - m_config->m_is_audio_initialized = true; + if (m_config.m_is_audio_initialized) + { + return CELL_AUDIO_ERROR_ALREADY_INIT; + } + + m_config.m_is_audio_initialized = true; return CELL_OK; } int cellAudioQuit() { cellAudio.Warning("cellAudioQuit()"); - if (m_config->m_is_audio_initialized == false) return CELL_AUDIO_ERROR_NOT_INIT; - m_config->m_is_audio_initialized = false; + if (!m_config.m_is_audio_initialized) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + m_config.m_is_audio_initialized = false; return CELL_OK; } int cellAudioPortOpen(mem_ptr_t audioParam, mem32_t portNum) { - cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr()); + cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x, portNum_addr=0x%x)", audioParam.GetAddr(), portNum.GetAddr()); - if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN; - m_config->m_is_audio_port_opened = true; - - m_param->nChannel = audioParam->nChannel; - m_param->nBlock = audioParam->nBlock; - m_param->attr = audioParam->attr; - m_param->level = audioParam->level; - - //TODO: implementation of ring buffer - return CELL_OK; -} - -int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfig) -{ - cellAudio.Warning("cellAudioGetPortConfig(portNum=0x%x,portConfig_addr=0x%x)",portNum,portConfig.GetAddr()); - - if(!portConfig.IsGood()) + if(!audioParam.IsGood() || !portNum.IsGood()) { return CELL_AUDIO_ERROR_PARAM; } - //if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL; - - if(!m_config->m_is_audio_port_opened) + if (m_config.m_port_in_use >= m_config.m_ports.GetCount()) { - portConfig->status = CELL_AUDIO_STATUS_CLOSE; - return CELL_OK; + return CELL_AUDIO_ERROR_PORT_FULL; } - if(m_config->m_is_audio_port_started) + for (u32 i = 0; i < m_config.m_ports.GetCount(); i++) + { + if (m_config.m_ports[i] == nullptr) + { + CellAudioPortParam& ref = (m_config.m_ports[i] = new AudioPortConfig)->m_param; + + ref.nChannel = audioParam->nChannel; + ref.nBlock = audioParam->nBlock; + ref.attr = audioParam->attr; + ref.level = audioParam->level; + + portNum = i; + cellAudio.Warning("*** audio port opened(nChannel=%lld, nBlock=0x%llx, attr=0x%llx, level=%f): port = %d", + (u64)ref.nChannel, (u64)ref.nBlock, (u64)ref.attr, (float)ref.level, portNum.GetValue()); + //TODO: implementation of ring buffer + return CELL_OK; + } + } + + return CELL_AUDIO_ERROR_PORT_FULL; +} + +int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfig) +{ + cellAudio.Warning("cellAudioGetPortConfig(portNum=0x%x, portConfig_addr=0x%x)", portNum, portConfig.GetAddr()); + + if (!portConfig.IsGood() || portNum >= m_config.m_ports.GetCount()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum]) + { + portConfig->status = CELL_AUDIO_STATUS_CLOSE; + } + else if (m_config.m_ports[portNum]->m_is_audio_port_started) { portConfig->status = CELL_AUDIO_STATUS_RUN; } else { + CellAudioPortParam& ref = m_config.m_ports[portNum]->m_param; + portConfig->status = CELL_AUDIO_STATUS_READY; - portConfig->nChannel = m_param->nChannel; - portConfig->nBlock = m_param->nBlock; - portConfig->portSize = sizeof(float)*256*(m_param->nChannel)*(m_param->nBlock); - portConfig->portAddr = Memory.Alloc(portConfig->portSize, 4); // 0x20020000 WARNING: Memory leak. - portConfig->readIndexAddr = Memory.Alloc(m_param->nBlock, 4); // 0x20010010 on ps3 WARNING: Memory leak. + portConfig->nChannel = ref.nChannel; + portConfig->nBlock = ref.nBlock; + portConfig->portSize = ref.nChannel * ref.nBlock * 256; + portConfig->portAddr = m_config.m_ports[portNum]->m_buffer; // 0x20020000 + portConfig->readIndexAddr = m_config.m_ports[portNum]->m_index; // 0x20010010 on ps3 // portAddr - readIndexAddr == 0xFFF0 on ps3 - Memory.Write64(portConfig->readIndexAddr, 1); + // Memory.Write64(portConfig->readIndexAddr, 1); } return CELL_OK; @@ -266,23 +343,43 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t portConfi int cellAudioPortStart(u32 portNum) { - cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum); + cellAudio.Warning("cellAudioPortStart(portNum=0x%x)", portNum); - if (!m_config->m_is_audio_port_opened) + if (portNum >= m_config.m_ports.GetCount()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum]) + { return CELL_AUDIO_ERROR_PORT_OPEN; + } + + if (m_config.m_ports[portNum]->m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_ALREADY_RUN; + } - m_config->m_is_audio_port_started = true; + m_config.m_ports[portNum]->m_is_audio_port_started = true; return CELL_OK; } int cellAudioPortClose(u32 portNum) { - cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum); - - if (!m_config->m_is_audio_port_opened) + cellAudio.Warning("cellAudioPortClose(portNum=0x%x)", portNum); + + if (portNum >= m_config.m_ports.GetCount()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum]) + { return CELL_AUDIO_ERROR_PORT_NOT_OPEN; - - m_config->m_is_audio_port_opened = false; + } + + delete m_config.m_ports[portNum]; + m_config.m_ports[portNum] = nullptr; return CELL_OK; } @@ -290,123 +387,131 @@ int cellAudioPortStop(u32 portNum) { cellAudio.Warning("cellAudioPortStop(portNum=0x%x)",portNum); - if (m_config->m_is_audio_port_started == false) + if (portNum >= m_config.m_ports.GetCount()) + { + return CELL_AUDIO_ERROR_PARAM; + } + + if (!m_config.m_ports[portNum]) + { return CELL_AUDIO_ERROR_PORT_NOT_OPEN; + } + + if (!m_config.m_ports[portNum]->m_is_audio_port_started) + { + return CELL_AUDIO_ERROR_PORT_NOT_RUN; + } - m_config->m_is_audio_port_started = false; + m_config.m_ports[portNum]->m_is_audio_port_started = false; return CELL_OK; } int cellAudioGetPortTimestamp(u32 portNum, u64 tag, mem64_t stamp) { - cellAudio.Warning("cellAudioGetPortTimestamp(portNum=0x%x,tag=0x%x,stamp=0x%x)",portNum,tag,stamp.GetAddr()); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioGetPortTimestamp(portNum=0x%x, tag=0x%llx, stamp_addr=0x%x)", portNum, tag, stamp.GetAddr()); return CELL_OK; } int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, mem64_t tag) { - cellAudio.Warning("cellAudioGetPortBlockTag(portNum=0x%x,blockNo=0x%x,tag=0x%x)",portNum,blockNo,tag.GetAddr()); - UNIMPLEMENTED_FUNC (cellAudio); + cellAudio.Error("cellAudioGetPortBlockTag(portNum=0x%x, blockNo=0x%llx, tag_addr=0x%x)", portNum, blockNo, tag.GetAddr()); return CELL_OK; } int cellAudioSetPortLevel(u32 portNum, float level) { - cellAudio.Warning("cellAudioSetPortLevel(portNum=0x%x,level=0x%x)",portNum,level); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioSetPortLevel(portNum=0x%x, level=%f)", portNum, level); return CELL_OK; } // Utility Functions int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key) { - cellAudio.Warning("cellAudioCreateNotifyEventQueue(id=0x%x,key=0x%x)",id.GetAddr(),key.GetAddr()); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr()); return CELL_OK; } int cellAudioCreateNotifyEventQueueEx(mem32_t id, mem64_t key, u32 iFlags) { - cellAudio.Warning("cellAudioCreateNotifyEventQueueEx(id=0x%x,key=0x%x,iFlags=0x%x)",id.GetAddr(),key.GetAddr(),iFlags); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioCreateNotifyEventQueueEx(id_addr=0x%x, key_addr=0x%x, iFlags=0x%x)", id.GetAddr(), key.GetAddr(), iFlags); return CELL_OK; } int cellAudioSetNotifyEventQueue(u64 key) { - cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%x)",key); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key); + + m_config.event_key = key; + + EventQueue* eq; + if (!Emu.GetEventManager().GetEventQueue(key, eq)) + { + return CELL_AUDIO_ERROR_PARAM; + } + + eq->events.push(0, 0, 0, 0); + eq->events.push(0, 0, 0, 0); + return CELL_OK; } int cellAudioSetNotifyEventQueueEx(u64 key, u32 iFlags) { - cellAudio.Warning("cellAudioSetNotifyEventQueueEx(key=0x%x,iFlags=0x%x)",key,iFlags); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioSetNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); return CELL_OK; } int cellAudioRemoveNotifyEventQueue(u64 key) { - cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%x)",key); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key); return CELL_OK; } int cellAudioRemoveNotifyEventQueueEx(u64 key, u32 iFlags) { - cellAudio.Warning("cellAudioRemoveNotifyEventQueueEx(key=0x%x,iFlags=0x%x)",key,iFlags); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioRemoveNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags); return CELL_OK; } -int cellAudioAddData(u32 portNum, mem32_t src, uint samples, float volume) +int cellAudioAddData(u32 portNum, mem32_t src, u32 samples, float volume) { - cellAudio.Warning("cellAudioAddData(portNum=0x%x,src=0x%x,samples=0x%x,volume=0x%x)",portNum,src.GetAddr(),samples,volume); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioAddData(portNum=0x%x, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.GetAddr(), samples, volume); return CELL_OK; } -int cellAudioAdd2chData(u32 portNum, mem32_t src, uint samples, float volume) +int cellAudioAdd2chData(u32 portNum, mem32_t src, u32 samples, float volume) { - cellAudio.Warning("cellAudioAdd2chData(portNum=0x%x,src=0x%x,samples=0x%x,volume=0x%x)",portNum,src.GetAddr(),samples,volume); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioAdd2chData(portNum=0x%x, src_addr=0x%x, samples=%d, volume=%f)", portNum, src.GetAddr(), samples, volume); return CELL_OK; } int cellAudioAdd6chData(u32 portNum, mem32_t src, float volume) { - cellAudio.Warning("cellAudioAdd6chData(portNum=0x%x,src=0x%x,volume=0x%x)",portNum,src.GetAddr(),volume); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioAdd6chData(portNum=0x%x, src_addr=0x%x, volume=%f)", portNum, src.GetAddr(), volume); return CELL_OK; } int cellAudioMiscSetAccessoryVolume(u32 devNum, float volume) { - cellAudio.Warning("cellAudioMiscSetAccessoryVolume(devNum=0x%x,volume=0x%x)",devNum,volume); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioMiscSetAccessoryVolume(devNum=0x%x, volume=%f)", devNum, volume); return CELL_OK; } int cellAudioSendAck(u64 data3) { - cellAudio.Warning("cellAudioSendAck(data3=0x%x)",data3); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioSendAck(data3=0x%llx)", data3); return CELL_OK; } int cellAudioSetPersonalDevice(int iPersonalStream, int iDevice) { - cellAudio.Warning("cellAudioSetPersonalDevice(iPersonalStream=0x%x,iDevice=0x%x)",iPersonalStream,iDevice); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioSetPersonalDevice(iPersonalStream=0x%x, iDevice=0x%x)", iPersonalStream, iDevice); return CELL_OK; } int cellAudioUnsetPersonalDevice(int iPersonalStream) { - cellAudio.Warning("cellAudioUnsetPersonalDevice(iPersonalStream=0x%x)",iPersonalStream); - UNIMPLEMENTED_FUNC(cellAudio); + cellAudio.Error("cellAudioUnsetPersonalDevice(iPersonalStream=0x%x)", iPersonalStream); return CELL_OK; } @@ -1013,9 +1118,14 @@ void cellAudio_init() //TODO: Find addresses for libmixer, libsnd3 and libsynth2 functions } +void cellAudio_load() +{ + m_config.m_is_audio_initialized = false; + m_config.Clear(); +} + void cellAudio_unload() { - m_config->m_is_audio_initialized = false; - m_config->m_is_audio_port_opened = false; - m_config->m_is_audio_port_started = false; + m_config.m_is_audio_initialized = false; + m_config.Clear(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 6935e5df2b..a0b116e438 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -115,7 +115,7 @@ int sdata_unpack(wxString packed_file, wxString unpacked_file) int cellFsSdataOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) { const wxString& path = Memory.ReadString(path_addr); - sys_fs.Warning("cellFsSdataOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx)", + sys_fs.Warning("cellFsSdataOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx)", path.wx_str(), flags, fd.GetAddr(), arg.GetAddr(), size); if (!fd.IsGood() || (!arg.IsGood() && size)) @@ -179,7 +179,7 @@ void fsAioRead(u32 fd, mem_ptr_t aio, int xid, mem_func_ptr_toffset, buf_addr, (u64)aio->size, res, xid, path.wx_str()); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 3e8d38afdd..bb0c845b4f 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -86,9 +86,11 @@ static func_caller* sc_table[1024] = bind_func(sys_rwlock_trywlock), //126 (0x07E) bind_func(sys_rwlock_wunlock), //127 (0x07F) bind_func(sys_event_queue_create), //128 (0x080) - null_func, //129 (0x081) - bind_func(sys_event_queue_receive), null_func, bind_func(sys_event_flag_cancel), bind_func(sys_event_queue_drain), bind_func(sys_event_port_create), //134 - null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), bind_func(sys_event_flag_get), //139 + bind_func(sys_event_queue_destroy), //129 (0x081) + bind_func(sys_event_queue_receive), bind_func(sys_event_queue_tryreceive), // 131 + bind_func(sys_event_flag_cancel), bind_func(sys_event_queue_drain), bind_func(sys_event_port_create), //134 + bind_func(sys_event_port_destroy), bind_func(sys_event_port_connect_local), //136 + bind_func(sys_event_port_disconnect), bind_func(sys_event_port_send), bind_func(sys_event_flag_get), //139 null_func, bind_func(sys_timer_usleep), bind_func(sys_timer_sleep), null_func, bind_func(sys_time_get_timezone), //144 bind_func(sys_time_get_current_time), bind_func(sys_time_get_system_time), bind_func(sys_time_get_timebase_frequency), null_func, null_func, //149 null_func, null_func, null_func, null_func, null_func, //154 @@ -99,8 +101,10 @@ static func_caller* sc_table[1024] = bind_func(sys_spu_thread_group_start), bind_func(sys_spu_thread_group_suspend), //174 null_func, null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179 null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184 - null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189 - bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, bind_func(sys_spu_thread_bind_queue), null_func, //194 + bind_func(sys_spu_thread_group_connect_event), bind_func(sys_spu_thread_group_disconnect_event), //186 + bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189 + bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), bind_func(sys_spu_thread_disconnect_event), //192 + bind_func(sys_spu_thread_bind_queue), bind_func(sys_spu_thread_unbind_queue), //194 null_func, null_func, null_func, null_func, null_func, //199 null_func, null_func, null_func, null_func, null_func, //204 null_func, null_func, null_func, null_func, null_func, //209 @@ -112,7 +116,7 @@ static func_caller* sc_table[1024] = null_func, null_func, null_func, null_func, null_func, //239 null_func, null_func, null_func, null_func, null_func, //244 null_func, null_func, null_func, null_func, null_func, //249 - null_func, bind_func(sys_spu_thread_group_connect_event_all_threads), null_func, null_func, null_func, //254 + null_func, bind_func(sys_spu_thread_group_connect_event_all_threads), bind_func(sys_spu_thread_group_disconnect_event_all_threads), null_func, null_func, //254 null_func, null_func, null_func, null_func, null_func, //259 null_func, null_func, null_func, null_func, null_func, //264 null_func, null_func, null_func, null_func, null_func, //269 diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 380b732ad2..392b5f15e9 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -128,16 +128,20 @@ extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_add //sys_event extern int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t attr, u64 event_queue_key, int size); -extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout); -extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name); -extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id); -extern int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3); +extern int sys_event_queue_destroy(u32 equeue_id, int mode); +extern int sys_event_queue_receive(u32 equeue_id, mem_ptr_t _event, u64 timeout); +extern int sys_event_queue_tryreceive(u32 equeue_id, mem_ptr_t event_array, int size, mem32_t number); extern int sys_event_queue_drain(u32 event_queue_id); +extern int sys_event_port_create(mem32_t eport_id, int port_type, u64 name); +extern int sys_event_port_destroy(u32 eport_id); +extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id); +extern int sys_event_port_disconnect(u32 eport_id); +extern int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3); //sys_event_flag extern int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t attr, u64 init); extern int sys_event_flag_destroy(u32 eflag_id); -extern int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u32 timeout); +extern int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64 timeout); extern int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result); extern int sys_event_flag_set(u32 eflag_id, u64 bitptn); extern int sys_event_flag_clear(u32 eflag_id, u64 bitptn); @@ -181,6 +185,16 @@ extern int sys_mutex_lock(u32 mutex_id, u64 timeout); extern int sys_mutex_trylock(u32 mutex_id); extern int sys_mutex_unlock(u32 mutex_id); +//sys_rwlock +extern int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr); +extern int sys_rwlock_destroy(u32 rw_lock_id); +extern int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout); +extern int sys_rwlock_tryrlock(u32 rw_lock_id); +extern int sys_rwlock_runlock(u32 rw_lock_id); +extern int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout); +extern int sys_rwlock_trywlock(u32 rw_lock_id); +extern int sys_rwlock_wunlock(u32 rw_lock_id); + //ppu_thread extern void sys_ppu_thread_exit(int errorcode); extern int sys_ppu_thread_yield(); @@ -197,7 +211,7 @@ extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry); extern int sys_ppu_thread_get_id(const u32 id_addr); //memory -extern int sys_memory_container_create(u32 cid_addr, u32 yield_size); +extern int sys_memory_container_create(mem32_t cid, u32 yield_size); extern int sys_memory_container_destroy(u32 cid); extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr); extern int sys_memory_free(u32 start_addr); @@ -290,13 +304,13 @@ extern int cellMouseGetRawData(u32 port_no, mem_class_t data); extern int cellGcmCallback(u32 context_addr, u32 count); //sys_tty -extern int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr); -extern int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr); +extern int sys_tty_read(s32 ch, u64 buf_addr, u32 len, u64 preadlen_addr); +extern int sys_tty_write(s32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr); //sys_heap extern int sys_heap_create_heap(const u32 heap_addr, const u32 start_addr, const u32 size); extern int sys_heap_malloc(const u32 heap_addr, const u32 size); -extern int _sys_heap_memalign(u32 heap_id, u32 align, u32 size, u64 p4); +extern int _sys_heap_memalign(u32 heap_id, u32 align, u32 size); //sys_spu extern int sys_spu_image_open(mem_ptr_t img, u32 path_addr); @@ -307,9 +321,11 @@ extern int sys_spu_thread_group_start(u32 id); extern int sys_spu_thread_group_suspend(u32 id); extern int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t attr); extern int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); -extern int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup); extern int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status); +extern int sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et); +extern int sys_spu_thread_group_disconnect_event(u32 id, u32 et); extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr); +extern int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup); extern int sys_raw_spu_create(mem32_t id, u32 attr_addr); extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); @@ -318,7 +334,10 @@ extern int sys_spu_thread_write_spu_mb(u32 id, u32 value); extern int sys_spu_thread_set_spu_cfg(u32 id, u64 value); extern int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value); extern int sys_spu_thread_write_snr(u32 id, u32 number, u32 value); +extern int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup); +extern int sys_spu_thread_disconnect_event(u32 id, u32 event_type, u8 spup); extern int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num); +extern int sys_spu_thread_unbind_queue(u32 id, u32 spuq_num); extern int sys_spu_thread_get_exit_status(u32 id, mem32_t status); //sys_time @@ -350,16 +369,6 @@ extern int sys_trace_allocate_buffer(); extern int sys_trace_free_buffer(); extern int sys_trace_create2(); -//sys_rwlock -extern int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr); -extern int sys_rwlock_destroy(u32 rw_lock_id); -extern int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout); -extern int sys_rwlock_tryrlock(u32 rw_lock_id); -extern int sys_rwlock_runlock(u32 rw_lock_id); -extern int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout); -extern int sys_rwlock_trywlock(u32 rw_lock_id); -extern int sys_rwlock_wunlock(u32 rw_lock_id); - //sys_rsx extern int sys_rsx_device_open(); extern int sys_rsx_device_close(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index 92ebc62956..66d86c8026 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -72,7 +72,11 @@ int sys_cond_wait(u32 cond_id, u64 timeout) const u32 max_counter = timeout ? (timeout / 1000) : 20000; do { - if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (Emu.IsStopped()) + { + ConLog.Warning("sys_cond_wait(cond_id=%d, ...) aborted", cond_id); + return CELL_ETIMEDOUT; + } switch (cond_data->cond.WaitTimeout(1)) { @@ -85,7 +89,6 @@ int sys_cond_wait(u32 cond_id, u64 timeout) { if (!timeout) { - sys_cond.Warning("sys_cond_wait(cond_id=0x%x, timeout=0x%llx): TIMEOUT", cond_id, timeout); counter = 0; } else diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index 357f8cbfcf..1ba187a656 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -21,25 +21,201 @@ int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t at return CELL_EFAULT; } - equeue_id = sys_event.GetNewId(new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size)); - sys_event.Warning("*** event_queue created[%s] (protocol=0x%x, type=0x%x): id = %d", + switch (attr->protocol.ToBE()) + { + case se32(SYS_SYNC_PRIORITY): break; + case se32(SYS_SYNC_RETRY): sys_event.Error("Invalid SYS_SYNC_RETRY protocol attr"); return CELL_EINVAL; + case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL; + case se32(SYS_SYNC_FIFO): break; + default: sys_event.Error("Unknown 0x%x protocol attr", (u32)attr->protocol); return CELL_EINVAL; + } + + switch (attr->type.ToBE()) + { + case se32(SYS_PPU_QUEUE): break; + case se32(SYS_SPU_QUEUE): break; + default: sys_event.Error("Unknown 0x%x type attr", (u32)attr->type); return CELL_EINVAL; + } + + if (event_queue_key && Emu.GetEventManager().CheckKey(event_queue_key)) + { + return CELL_EEXIST; + } + + EventQueue* eq = new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size); + + if (event_queue_key && !Emu.GetEventManager().RegisterKey(eq, event_queue_key)) + { + delete eq; + return CELL_EAGAIN; + } + + equeue_id = sys_event.GetNewId(eq); + sys_event.Warning("*** event_queue created [%s] (protocol=0x%x, type=0x%x): id = %d", attr->name, (u32)attr->protocol, (int)attr->type, equeue_id.GetValue()); return CELL_OK; } -int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) +int sys_event_queue_destroy(u32 equeue_id, int mode) { - sys_event.Warning("sys_event_queue_receive(equeue_id=0x%x, event_addr=0x%x, timeout=0x%x)", - equeue_id, event_addr, timeout); + sys_event.Warning("sys_event_queue_destroy(equeue_id=%d, mode=0x%x)", equeue_id, mode); - if(!sys_event.CheckId(equeue_id)) + EventQueue* eq; + if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) { return CELL_ESRCH; } - int result; - auto queue_receive = [&](int status) -> bool + if (mode && mode != SYS_EVENT_QUEUE_DESTROY_FORCE) + { + return CELL_EINVAL; + } + + u32 tid = GetCurrentPPUThread().GetId(); + + eq->m_mutex.lock(tid); + eq->owner.lock(tid); + // check if some threads are waiting for an event + if (!mode && eq->list.GetCount()) + { + eq->owner.unlock(tid); + eq->m_mutex.unlock(tid); + return CELL_EBUSY; + } + eq->owner.unlock(tid, ~0); + eq->m_mutex.unlock(tid); + while (eq->list.GetCount()) + { + Sleep(1); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_event_queue_destroy(equeue=%d, ...) aborted", equeue_id); + break; + } + } + + Emu.GetEventManager().UnregisterKey(eq->key); + eq->ports.clear(); + Emu.GetIdManager().RemoveID(equeue_id); + + return CELL_OK; +} + +int sys_event_queue_tryreceive(u32 equeue_id, mem_ptr_t event_array, int size, mem32_t number) +{ + sys_event.Error("sys_event_queue_tryreceive(equeue_id=%d, event_array_addr=0x%x, size=%d, number_addr=0x%x)", + equeue_id, event_array.GetAddr(), size, number.GetAddr()); + + if (size < 0 || !number.IsGood()) + { + return CELL_EFAULT; + } + + if (size && !Memory.IsGoodAddr(event_array.GetAddr(), sizeof(sys_event_data) * size)) + { + return CELL_EFAULT; + } + + EventQueue* eq; + if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) + { + return CELL_ESRCH; + } + + if (eq->type != SYS_PPU_QUEUE) + { + return CELL_EINVAL; + } + + if (size == 0) + { + number = 0; + return CELL_OK; + } + + u32 tid = GetCurrentPPUThread().GetId(); + + eq->m_mutex.lock(tid); + eq->owner.lock(tid); + if (eq->list.GetCount()) + { + number = 0; + eq->owner.unlock(tid); + eq->m_mutex.unlock(tid); + return CELL_OK; + } + number = eq->events.pop_all((sys_event_data*)(Memory + event_array.GetAddr()), size); + eq->owner.unlock(tid); + eq->m_mutex.unlock(tid); + return CELL_OK; +} + +int sys_event_queue_receive(u32 equeue_id, mem_ptr_t event, u64 timeout) +{ + sys_event.Warning("sys_event_queue_receive(equeue_id=%d, event_addr=0x%x, timeout=%lld)", + equeue_id, event.GetAddr(), timeout); + + if (!event.IsGood()) + { + return CELL_EFAULT; + } + + EventQueue* eq; + if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) + { + return CELL_ESRCH; + } + + if (eq->type != SYS_PPU_QUEUE) + { + return CELL_EINVAL; + } + + u32 tid = GetCurrentPPUThread().GetId(); + + eq->push(tid); // add thread to sleep queue + + timeout = timeout ? (timeout / 1000) : ~0; + u64 counter = 0; + while (true) + { + switch (eq->owner.trylock(tid)) + { + case SMR_OK: + if (!eq->events.count()) + { + eq->owner.unlock(tid); + break; + } + else + { + u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->pop() : eq->pop_prio(); + if (next != tid) + { + eq->owner.unlock(tid, next); + break; + } + } + case SMR_SIGNAL: + { + eq->events.pop(*(sys_event_data*)(Memory + event)); + eq->owner.unlock(tid); + return CELL_OK; + } + case SMR_FAILED: break; + default: eq->invalidate(tid); return CELL_ECANCELED; + } + + Sleep(1); + if (counter++ > timeout || Emu.IsStopped()) + { + if (Emu.IsStopped()) ConLog.Warning("sys_event_queue_receive(equeue=%d, ...) aborted", equeue_id); + eq->invalidate(tid); + return CELL_ETIMEDOUT; + } + } + /* auto queue_receive = [&](int status) -> bool { if(status == CPUThread_Stopped) { @@ -48,7 +224,12 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) } EventQueue* equeue; - Emu.GetIdManager().GetIDData(equeue_id, equeue); + if (!Emu.GetIdManager().GetIDData(equeue_id, equeue)) + { + result = CELL_ESRCH; + return false; + } + for(int i=0; ipos; ++i) { if(!equeue->ports[i]->has_data && equeue->ports[i]->thread) @@ -71,12 +252,10 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) { if(equeue->ports[i]->has_data) { - auto dst = (sys_event_data&)Memory[event_addr]; - - dst.source = equeue->ports[i]->name; - dst.data1 = equeue->ports[i]->data1; - dst.data2 = equeue->ports[i]->data2; - dst.data3 = equeue->ports[i]->data3; + event->source = equeue->ports[i]->name; + event->data1 = equeue->ports[i]->data1; + event->data2 = equeue->ports[i]->data2; + event->data3 = equeue->ports[i]->data3; equeue->ports[i]->has_data = false; @@ -88,85 +267,167 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) return true; }; - GetCurrentPPUThread().WaitFor(queue_receive); - - return result; + GetCurrentPPUThread().WaitFor(queue_receive);*/ } -int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name) +int sys_event_queue_drain(u32 equeue_id) +{ + sys_event.Warning("sys_event_queue_drain(equeue_id=%d)", equeue_id); + + EventQueue* eq; + if (!Emu.GetIdManager().GetIDData(equeue_id, eq)) + { + return CELL_ESRCH; + } + + eq->events.clear(); + + return CELL_OK; +} + +int sys_event_port_create(mem32_t eport_id, int port_type, u64 name) { sys_event.Warning("sys_event_port_create(eport_id_addr=0x%x, port_type=0x%x, name=0x%llx)", - eport_id_addr, port_type, name); + eport_id.GetAddr(), port_type, name); - if(!Memory.IsGoodAddr(eport_id_addr, 4)) + if (!eport_id.IsGood()) { return CELL_EFAULT; } + if (port_type != SYS_EVENT_PORT_LOCAL) + { + sys_event.Error("sys_event_port_create: invalid port_type(0x%x)", port_type); + return CELL_EINVAL; + } + EventPort* eport = new EventPort(); u32 id = sys_event.GetNewId(eport); - eport->pos = 0; - eport->has_data = false; - eport->name = name ? name : id; - Memory.Write32(eport_id_addr, id); + eport->name = name ? name : ((u64)sys_process_getpid() << 32) | (u64)id; + eport_id = id; + sys_event.Warning("*** sys_event_port created: id = %d", id); return CELL_OK; } -int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id) +int sys_event_port_destroy(u32 eport_id) { - sys_event.Warning("sys_event_port_connect_local(event_port_id=0x%x, event_queue_id=0x%x)", - event_port_id, event_queue_id); + sys_event.Warning("sys_event_port_destroy(eport_id=%d)", eport_id); - if(!sys_event.CheckId(event_port_id) || !sys_event.CheckId(event_queue_id)) + EventPort* eport; + if (!Emu.GetIdManager().GetIDData(eport_id, eport)) { return CELL_ESRCH; } + u32 tid = GetCurrentPPUThread().GetId(); + + if (eport->mutex.trylock(tid) != SMR_OK) + { + return CELL_EISCONN; + } + + if (eport->eq) + { + eport->mutex.unlock(tid); + return CELL_EISCONN; + } + + eport->mutex.unlock(tid, ~0); + Emu.GetIdManager().RemoveID(eport_id); + return CELL_OK; +} + +int sys_event_port_connect_local(u32 eport_id, u32 equeue_id) +{ + sys_event.Warning("sys_event_port_connect_local(eport_id=%d, equeue_id=%d)", eport_id, equeue_id); + EventPort* eport; + if (!Emu.GetIdManager().GetIDData(eport_id, eport)) + { + return CELL_ESRCH; + } + + u32 tid = GetCurrentPPUThread().GetId(); + + if (eport->mutex.trylock(tid) != SMR_OK) + { + return CELL_EISCONN; + } + + if (eport->eq) + { + eport->mutex.unlock(tid); + return CELL_EISCONN; + } + EventQueue* equeue; - Emu.GetIdManager().GetIDData(event_port_id, eport); - Emu.GetIdManager().GetIDData(event_queue_id, equeue); - equeue->ports[equeue->pos++] = eport; - eport->queue[eport->pos++] = equeue; + if (!Emu.GetIdManager().GetIDData(equeue_id, equeue)) + { + sys_event.Error("sys_event_port_connect_local: event_queue(%d) not found!", equeue_id); + eport->mutex.unlock(tid); + return CELL_ESRCH; + } + else + { + equeue->ports.add(eport); + } + eport->eq = equeue; + eport->mutex.unlock(tid); return CELL_OK; } -int sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3) +int sys_event_port_disconnect(u32 eport_id) { - sys_event.Warning("sys_event_port_send(event_port_id=0x%x, data1=0x%llx, data2=0x%llx, data3=0x%llx)", - event_port_id, data1, data2, data3); + sys_event.Warning("sys_event_port_disconnect(eport_id=%d)", eport_id); - if(!sys_event.CheckId(event_port_id)) + EventPort* eport; + if (!Emu.GetIdManager().GetIDData(eport_id, eport)) { return CELL_ESRCH; } - EventPort* eport; - Emu.GetIdManager().GetIDData(event_port_id, eport); - - if(!eport->pos) + if (!eport->eq) { return CELL_ENOTCONN; } - if(eport->has_data) + u32 tid = GetCurrentPPUThread().GetId(); + + if (eport->mutex.trylock(tid) != SMR_OK) { return CELL_EBUSY; } - - eport->has_data = true; - eport->data1 = data1; - eport->data2 = data2; - eport->data3 = data3; + eport->eq->ports.remove(eport); + eport->eq = 0; + eport->mutex.unlock(tid); return CELL_OK; } -int sys_event_queue_drain(u32 event_queue_id) +int sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3) { - sys_event.Error("sys_event_queue_drain(event_queue_id=0x%x)", event_queue_id); + sys_event.Warning("sys_event_port_send(eport_id=%d, data1=0x%llx, data2=0x%llx, data3=0x%llx)", + eport_id, data1, data2, data3); + + EventPort* eport; + if (!Emu.GetIdManager().GetIDData(eport_id, eport)) + { + return CELL_ESRCH; + } + + SMutexLocker lock(eport->mutex); + + if (!eport->eq) + { + return CELL_ENOTCONN; + } + + if (!eport->eq->events.push(eport->name, data1, data2, data3)) + { + return CELL_EBUSY; + } return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp index 607d21aae2..3bca2ed1ff 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp @@ -6,7 +6,8 @@ SysCallBase sys_event_flag("sys_event_flag"); int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t attr, u64 init) { - sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", eflag_id.GetAddr(), attr.GetAddr(), init); + sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", + eflag_id.GetAddr(), attr.GetAddr(), init); if(!eflag_id.IsGood() || !attr.IsGood()) { @@ -16,7 +17,7 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t attr, switch (attr->protocol.ToBE()) { case se32(SYS_SYNC_PRIORITY): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY attr"); break; - case se32(SYS_SYNC_RETRY): break; + case se32(SYS_SYNC_RETRY): sys_event_flag.Warning("TODO: SYS_SYNC_RETRY attr"); break; case se32(SYS_SYNC_PRIORITY_INHERIT): sys_event_flag.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; case se32(SYS_SYNC_FIFO): sys_event_flag.Warning("TODO: SYS_SYNC_FIFO attr"); break; default: return CELL_EINVAL; @@ -36,14 +37,15 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t attr, eflag_id = sys_event_flag.GetNewId(new event_flag(init, (u32)attr->protocol, (int)attr->type)); - sys_event_flag.Warning("*** event_flag created[%s] (protocol=%d, type=%d): id = %d", attr->name, (u32)attr->protocol, (int)attr->type, eflag_id.GetValue()); + sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d", + attr->name, (u32)attr->protocol, (int)attr->type, eflag_id.GetValue()); return CELL_OK; } int sys_event_flag_destroy(u32 eflag_id) { - sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=0x%x)", eflag_id); + sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=%d)", eflag_id); event_flag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; @@ -53,23 +55,23 @@ int sys_event_flag_destroy(u32 eflag_id) return CELL_OK; } -int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u32 timeout) +int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64 timeout) { - sys_event_flag.Error("sys_event_flag_wait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=0x%x)", + sys_event_flag.Error("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)", eflag_id, bitptn, mode, result.GetAddr(), timeout); return CELL_OK; } int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result) { - sys_event_flag.Error("sys_event_flag_trywait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)", + sys_event_flag.Error("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)", eflag_id, bitptn, mode, result.GetAddr()); return CELL_OK; } int sys_event_flag_set(u32 eflag_id, u64 bitptn) { - sys_event_flag.Warning("sys_event_flag_set(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn); + sys_event_flag.Warning("sys_event_flag_set(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn); event_flag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; @@ -81,7 +83,7 @@ int sys_event_flag_set(u32 eflag_id, u64 bitptn) int sys_event_flag_clear(u32 eflag_id, u64 bitptn) { - sys_event_flag.Warning("sys_event_flag_clear(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn); + sys_event_flag.Warning("sys_event_flag_clear(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn); event_flag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; @@ -93,13 +95,13 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn) int sys_event_flag_cancel(u32 eflag_id, mem32_t num) { - sys_event_flag.Error("sys_event_flag_cancel(eflag_id=0x%x, num_addr=0x%x)", eflag_id, num.GetAddr()); + sys_event_flag.Error("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr()); return CELL_OK; } int sys_event_flag_get(u32 eflag_id, mem64_t flags) { - sys_event_flag.Warning("sys_event_flag_get(eflag_id=0x%x, flags_addr=0x%x)", eflag_id, flags.GetAddr()); + sys_event_flag.Warning("sys_event_flag_get(eflag_id=%d, flags_addr=0x%x)", eflag_id, flags.GetAddr()); if (!flags.IsGood()) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index 49103b58ca..6d0dcf7f4d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -7,7 +7,7 @@ extern Module sys_fs; int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) { const wxString& path = Memory.ReadString(path_addr); - sys_fs.Log("cellFsOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx)", + sys_fs.Log("cellFsOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx)", path.wx_str(), flags, fd.GetAddr(), arg.GetAddr(), size); const wxString& ppath = path; @@ -57,7 +57,7 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) if(_oflags != 0) { - sys_fs.Error("'%s' has unknown flags! flags: 0x%08x", ppath.wx_str(), flags); + sys_fs.Error("\"%s\" has unknown flags! flags: 0x%08x", ppath.wx_str(), flags); return CELL_EINVAL; } @@ -65,21 +65,21 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size) if(!stream || !stream->IsOpened()) { - sys_fs.Error("'%s' not found! flags: 0x%08x", ppath.wx_str(), flags); + sys_fs.Error("\"%s\" not found! flags: 0x%08x", ppath.wx_str(), flags); delete stream; return CELL_ENOENT; } fd = sys_fs.GetNewId(stream, flags); - ConLog.Warning("*** cellFsOpen(path: %s): fd=%d", path.wx_str(), fd.GetValue()); + ConLog.Warning("*** cellFsOpen(path=\"%s\"): fd = %d", path.wx_str(), fd.GetValue()); return CELL_OK; } int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread) { - sys_fs.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)", + sys_fs.Log("cellFsRead(fd=%d, buf_addr=0x%x, nbytes=0x%llx, nread_addr=0x%x)", fd, buf_addr, nbytes, nread.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; @@ -100,7 +100,7 @@ int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread) int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite) { - sys_fs.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)", + sys_fs.Log("cellFsWrite(fd=%d, buf_addr=0x%x, nbytes=0x%llx, nwrite_addr=0x%x)", fd, buf_addr, nbytes, nwrite.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; @@ -121,7 +121,7 @@ int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nwrite) int cellFsClose(u32 fd) { - sys_fs.Warning("cellFsClose(fd: %d)", fd); + sys_fs.Warning("cellFsClose(fd=%d)", fd); if(!Emu.GetIdManager().RemoveID(fd)) return CELL_ESRCH; @@ -186,7 +186,7 @@ int cellFsClosedir(u32 fd) int cellFsStat(const u32 path_addr, mem_ptr_t sb) { const wxString& path = Memory.ReadString(path_addr); - sys_fs.Log("cellFsStat(path: %s, sb_addr: 0x%x)", path.wx_str(), sb.GetAddr()); + sys_fs.Log("cellFsStat(path=\"%s\", sb_addr: 0x%x)", path.wx_str(), sb.GetAddr()); sb->st_mode = CELL_FS_S_IRUSR | CELL_FS_S_IWUSR | CELL_FS_S_IXUSR | @@ -205,7 +205,7 @@ int cellFsStat(const u32 path_addr, mem_ptr_t sb) { if(path.CmpNoCase(Emu.GetVFS().m_devices[i].GetPs3Path().RemoveLast(1)) == 0) { - sys_fs.Log("cellFsStat: '%s' is a mount point.", path.wx_str()); + sys_fs.Log("cellFsStat: \"%s\" is a mount point.", path.wx_str()); sb->st_mode |= CELL_FS_S_IFDIR; return CELL_OK; } @@ -230,7 +230,7 @@ int cellFsStat(const u32 path_addr, mem_ptr_t sb) } else { - sys_fs.Warning("cellFsStat: '%s' not found.", path.wx_str()); + sys_fs.Warning("cellFsStat: \"%s\" not found.", path.wx_str()); return CELL_ENOENT; } @@ -239,7 +239,7 @@ int cellFsStat(const u32 path_addr, mem_ptr_t sb) int cellFsFstat(u32 fd, mem_ptr_t sb) { - sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb.GetAddr()); + sys_fs.Log("cellFsFstat(fd=%d, sb_addr: 0x%x)", fd, sb.GetAddr()); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; @@ -315,14 +315,14 @@ int cellFsUnlink(u32 path_addr) int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos) { vfsSeekMode seek_mode; - sys_fs.Log("cellFsLseek(fd: %d, offset: 0x%llx, whence: %d, pos_addr: 0x%x)", fd, offset, whence, pos.GetAddr()); + sys_fs.Log("cellFsLseek(fd=%d, offset=0x%llx, whence=0x%x, pos_addr=0x%x)", fd, offset, whence, pos.GetAddr()); switch(whence) { case CELL_SEEK_SET: seek_mode = vfsSeekSet; break; case CELL_SEEK_CUR: seek_mode = vfsSeekCur; break; case CELL_SEEK_END: seek_mode = vfsSeekEnd; break; default: - sys_fs.Error(fd, "Unknown seek whence! (%d)", whence); + sys_fs.Error(fd, "Unknown seek whence! (0x%x)", whence); return CELL_EINVAL; } @@ -334,7 +334,7 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos) int cellFsFtruncate(u32 fd, u64 size) { - sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size); + sys_fs.Log("cellFsFtruncate(fd=%d, size=%lld)", fd, size); vfsStream* file; if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH; u64 initialSize = file->GetSize(); @@ -360,12 +360,12 @@ int cellFsFtruncate(u32 fd, u64 size) int cellFsTruncate(u32 path_addr, u64 size) { const wxString& path = Memory.ReadString(path_addr); - sys_fs.Log("cellFsTruncate(path: %s, size: %lld)", path.wx_str(), size); + sys_fs.Log("cellFsTruncate(path=\"%s\", size=%lld)", path.wx_str(), size); vfsFile f(path, vfsReadWrite); if(!f.IsOpened()) { - sys_fs.Warning("cellFsTruncate: '%s' not found.", path.wx_str()); + sys_fs.Warning("cellFsTruncate: \"%s\" not found.", path.wx_str()); return CELL_ENOENT; } u64 initialSize = f.GetSize(); @@ -390,7 +390,7 @@ int cellFsTruncate(u32 path_addr, u64 size) int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size) { - sys_fs.Log("cellFsFGetBlockSize(fd: %d, sector_size_addr: 0x%x, block_size_addr: 0x%x)", fd, sector_size.GetAddr(), block_size.GetAddr()); + sys_fs.Log("cellFsFGetBlockSize(fd=%d, sector_size_addr: 0x%x, block_size_addr: 0x%x)", fd, sector_size.GetAddr(), block_size.GetAddr()); sector_size = 4096; // ? block_size = 4096; // ? diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Heap.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Heap.cpp index eff04fb5cc..8f1b09dee1 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Heap.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Heap.cpp @@ -22,13 +22,13 @@ int sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size) sc_heap.Warning("sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size); u32 heap_id = sc_heap.GetNewId(new HeapInfo(heap_addr, align, size)); - sc_heap.Warning("*** sys_heap created(): id=0x%x", heap_id); + sc_heap.Warning("*** sys_heap created: id = %d", heap_id); return heap_id; } int sys_heap_malloc(const u32 heap_id, const u32 size) { - sc_heap.Warning("sys_heap_malloc(heap_id=0x%x, size=0x%x)", heap_id, size); + sc_heap.Warning("sys_heap_malloc(heap_id=%d, size=0x%x)", heap_id, size); HeapInfo* heap; if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH; @@ -36,9 +36,9 @@ int sys_heap_malloc(const u32 heap_id, const u32 size) return Memory.Alloc(size, 1); } -int _sys_heap_memalign(u32 heap_id, u32 align, u32 size, u64 p4) +int _sys_heap_memalign(u32 heap_id, u32 align, u32 size) { - sc_heap.Warning("_sys_heap_memalign(heap_id=0x%x, align=0x%x, size=0x%x, p4=0x%llx, ... ???)", heap_id, align, size, p4); + sc_heap.Warning("_sys_heap_memalign(heap_id=%d, align=0x%x, size=0x%x)", heap_id, align, size); HeapInfo* heap; if(!sc_heap.CheckId(heap_id, heap)) return CELL_ESRCH; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp index 33da310eea..d07636e1e2 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp @@ -7,7 +7,7 @@ SysCallBase sys_lwcond("sys_lwcond"); int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t lwmutex, mem_ptr_t attr) { - sys_lwcond.Log("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)", + sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)", lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr()); if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; @@ -15,7 +15,7 @@ int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t l lwcond->lwmutex = lwmutex.GetAddr(); lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64)); - sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id=0x%x", + sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id = %d", attr->name, (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue); return CELL_OK; } @@ -77,7 +77,7 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) { - sys_lwcond.Log("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout); + sys_lwcond.Log("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%lld)", lwcond.GetAddr(), timeout); if (!lwcond.IsGood()) return CELL_EFAULT; LWCond* lwc; @@ -95,7 +95,11 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) bool was_locked = true; do { - if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_wait(sq id=%d, ...) aborted", id); + return CELL_ETIMEDOUT; + } if (was_locked) lwmutex->unlock(tid); Sleep(1); if (was_locked = (lwmutex->trylock(tid) == CELL_OK)) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 386e99f5f9..e669ae2951 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/lv2/SC_Lwmutex.h" -#include SysCallBase sc_lwmutex("sys_lwmutex"); @@ -36,7 +35,7 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_tname_u64)); lwmutex->sleep_queue = sq_id; - sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x): sleep_queue=0x%x", + sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d", attr->name, (u32)lwmutex->attribute, sq_id); return CELL_OK; @@ -89,3 +88,174 @@ int sys_lwmutex_unlock(mem_ptr_t lwmutex) return lwmutex->unlock(GetCurrentPPUThread().GetId()); } +void SleepQueue::push(u32 tid) +{ + SMutexLocker lock(m_mutex); + list.AddCpy(tid); +} + +u32 SleepQueue::pop() // SYS_SYNC_FIFO +{ + SMutexLocker lock(m_mutex); + + while (true) + { + if (list.GetCount()) + { + u32 res = list[0]; + list.RemoveAt(0); + if (res && Emu.GetIdManager().CheckID(res)) + // check thread + { + return res; + } + } + return 0; + }; +} + +u32 SleepQueue::pop_prio() // SYS_SYNC_PRIORITY +{ + SMutexLocker lock(m_mutex); + + while (true) + { + if (list.GetCount()) + { + u64 max_prio = 0; + u32 sel = 0; + for (u32 i = 0; i < list.GetCount(); i++) + { + CPUThread* t = Emu.GetCPU().GetThread(list[i]); + if (!t) + { + list[i] = 0; + sel = i; + break; + } + u64 prio = t->GetPrio(); + if (prio > max_prio) + { + max_prio = prio; + sel = i; + } + } + u32 res = list[sel]; + list.RemoveAt(sel); + /* if (Emu.GetIdManager().CheckID(res)) */ + if (res) + // check thread + { + return res; + } + } + return 0; + } +} + +u32 SleepQueue::pop_prio_inherit() // (TODO) +{ + ConLog.Error("TODO: SleepQueue::pop_prio_inherit()"); + Emu.Pause(); + return 0; +} + +void SleepQueue::invalidate(u32 tid) +{ + SMutexLocker lock(m_mutex); + + for (u32 i = 0; i < list.GetCount(); i++) + { + if (list[i] = tid) + { + list[i] = 0; + return; + } + } +} + +int sys_lwmutex_t::trylock(be_t tid) +{ + if (!attribute.ToBE()) return CELL_EINVAL; + + if (tid == owner.GetOwner()) + { + if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE)) + { + recursive_count += 1; + if (!recursive_count.ToBE()) return CELL_EKRESOURCE; + return CELL_OK; + } + else + { + return CELL_EDEADLK; + } + } + + switch (owner.trylock(tid)) + { + case SMR_OK: recursive_count = 1; return CELL_OK; + case SMR_FAILED: return CELL_EBUSY; + default: return CELL_EINVAL; + } +} + +int sys_lwmutex_t::unlock(be_t tid) +{ + if (tid != owner.GetOwner()) + { + return CELL_EPERM; + } + else + { + recursive_count -= 1; + if (!recursive_count.ToBE()) + { + be_t target = 0; + switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) + { + case se32(SYS_SYNC_FIFO): + case se32(SYS_SYNC_PRIORITY): + SleepQueue* sq; + if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; + target = attribute.ToBE() & se32(SYS_SYNC_FIFO) ? sq->pop() : sq->pop_prio(); + case se32(SYS_SYNC_RETRY): default: owner.unlock(tid, target); break; + } + } + return CELL_OK; + } +} + +int sys_lwmutex_t::lock(be_t tid, u64 timeout) +{ + switch (int res = trylock(tid)) + { + case CELL_EBUSY: break; + default: return res; + } + + SleepQueue* sq; + if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; + + switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) + { + case se32(SYS_SYNC_PRIORITY): + case se32(SYS_SYNC_FIFO): + sq->push(tid); + default: break; + } + + switch (owner.lock(tid, timeout)) + { + case SMR_OK: + sq->invalidate(tid); + case SMR_SIGNAL: + recursive_count = 1; return CELL_OK; + case SMR_TIMEOUT: + sq->invalidate(tid); return CELL_ETIMEDOUT; + case SMR_ABORT: + if (Emu.IsStopped()) ConLog.Warning("sys_lwmutex_t::lock(sq=%d, ...) aborted", (u32)sleep_queue); + default: + sq->invalidate(tid); return CELL_EINVAL; + } +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 7275724b08..8898024a8b 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -38,7 +38,7 @@ struct sys_lwmutex_attribute_t }; }; -class SleepQueue +struct SleepQueue { /* struct q_rec { @@ -46,88 +46,20 @@ class SleepQueue u64 prio; q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {} }; */ - - SMutex m_mutex; Array list; + SMutex m_mutex; u64 m_name; -public: - SleepQueue(u64 name) + SleepQueue(u64 name = 0) : m_name(name) { } - void push(u32 tid) - { - SMutexLocker lock(m_mutex); - list.AddCpy(tid); - } - - u32 pop() // SYS_SYNC_FIFO - { - SMutexLocker lock(m_mutex); - - while (true) - { - if (list.GetCount()) - { - u32 res = list[0]; - list.RemoveAt(0); - if (Emu.GetIdManager().CheckID(res)) - // check thread - { - return res; - } - } - return 0; - }; - } - - u32 pop_prio() // SYS_SYNC_PRIORITY - { - SMutexLocker lock(m_mutex); - - while (true) - { - if (list.GetCount()) - { - u64 max_prio = 0; - u32 sel = 0; - for (u32 i = 0; i < list.GetCount(); i++) - { - CPUThread* t = Emu.GetCPU().GetThread(list[i]); - if (!t) - { - list[i] = 0; - sel = i; - break; - } - - u64 prio = t->GetPrio(); - if (prio > max_prio) - { - max_prio = prio; - sel = i; - } - } - u32 res = list[sel]; - list.RemoveAt(sel); - /* if (Emu.GetIdManager().CheckID(res)) */ - if (res) - // check thread - { - return res; - } - } - return 0; - } - } - - u32 pop_prio_inherit() // (TODO) - { - ConLog.Error("TODO: SleepQueue::pop_prio_inherit()"); - Emu.Pause(); - } + void push(u32 tid); + u32 pop(); // SYS_SYNC_FIFO + u32 pop_prio(); // SYS_SYNC_PRIORITY + u32 pop_prio_inherit(); // (TODO) + void invalidate(u32 tid); }; struct sys_lwmutex_t @@ -149,85 +81,11 @@ struct sys_lwmutex_t be_t sleep_queue; be_t pad; - int trylock(be_t tid) - { - if (!attribute.ToBE()) return CELL_EINVAL; - - if (tid == owner.GetOwner()) - { - if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE)) - { - recursive_count += 1; - if (!recursive_count.ToBE()) return CELL_EKRESOURCE; - return CELL_OK; - } - else - { - return CELL_EDEADLK; - } - } - - switch (owner.trylock(tid)) - { - case SMR_OK: recursive_count = 1; return CELL_OK; - case SMR_FAILED: return CELL_EBUSY; - default: return CELL_EINVAL; - } - } - - int unlock(be_t tid) - { - if (tid != owner.GetOwner()) - { - return CELL_EPERM; - } - else - { - recursive_count -= 1; - if (!recursive_count.ToBE()) - { - be_t target = 0; - switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) - { - case se32(SYS_SYNC_FIFO): - case se32(SYS_SYNC_PRIORITY): - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; - target = attribute.ToBE() & se32(SYS_SYNC_FIFO) ? sq->pop() : sq->pop_prio(); - case se32(SYS_SYNC_RETRY): default: owner.unlock(tid, target); break; - } - } - return CELL_OK; - } - } - - int lock(be_t tid, u64 timeout) - { - switch (int res = trylock(tid)) - { - case CELL_EBUSY: break; - default: return res; - } - - switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) - { - case se32(SYS_SYNC_PRIORITY): - case se32(SYS_SYNC_FIFO): - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; - sq->push(tid); - default: break; - } - - switch (owner.lock(tid, timeout)) - { - case SMR_OK: case SMR_SIGNAL: recursive_count = 1; return CELL_OK; - case SMR_TIMEOUT: return CELL_ETIMEDOUT; - default: return CELL_EINVAL; - } - } + int trylock(be_t tid); + int unlock(be_t tid); + int lock(be_t tid, u64 timeout); }; - +/* class lwmutex_locker { mem_ptr_t m_mutex; @@ -248,4 +106,4 @@ class lwmutex_locker { m_mutex->unlock(m_id); } -}; \ No newline at end of file +};*/ \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 526e1d56ab..32f623c6e9 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -4,11 +4,11 @@ SysCallBase sc_mem("memory"); -int sys_memory_container_create(u32 cid_addr, u32 yield_size) +int sys_memory_container_create(mem32_t cid, u32 yield_size) { - sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size); + sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size); - if(!Memory.IsGoodAddr(cid_addr, 4)) + if (!cid.IsGood()) { return CELL_EFAULT; } @@ -22,13 +22,14 @@ int sys_memory_container_create(u32 cid_addr, u32 yield_size) return CELL_ENOMEM; } - Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size))); + cid = sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)); + sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue()); return CELL_OK; } int sys_memory_container_destroy(u32 cid) { - sc_mem.Warning("sys_memory_container_destroy(cid=0x%x)", cid); + sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid); MemoryContainerInfo* ct; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index 2bd289413a..415d2f2ccc 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -53,7 +53,11 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) const u32 max_counter = timeout ? (timeout / 1000) : 20000; do { - if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (Emu.IsStopped()) + { + ConLog.Warning("sys_mutex_lock(mutex_id=%d, ...) aborted", mutex_id); + return CELL_ETIMEDOUT; + } if (mtx_data->mtx.TryLock() == wxMUTEX_NO_ERROR) return CELL_OK; Sleep(1); @@ -62,7 +66,6 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) { if (!timeout) { - sys_mtx.Warning("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx): TIMEOUT", mutex_id, timeout); counter = 0; } else diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp index d07ab05677..260f7ae28a 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp @@ -27,7 +27,7 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64)); - sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d", + sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id = %d", attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue()); return CELL_OK; @@ -51,7 +51,7 @@ int sys_rwlock_destroy(u32 rw_lock_id) int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) { - sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); + sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout); RWLock* rw; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; @@ -63,7 +63,11 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) const u32 max_counter = timeout ? (timeout / 1000) : 20000; do { - if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (Emu.IsStopped()) + { + ConLog.Warning("sys_rwlock_rlock(rw_lock_id=%d, ...) aborted", rw_lock_id); + return CELL_ETIMEDOUT; + } Sleep(1); if (rw->rlock_trylock(tid)) return CELL_OK; @@ -72,7 +76,6 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) { if (!timeout) { - sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d): TIMEOUT", rw_lock_id); counter = 0; } else @@ -109,7 +112,7 @@ int sys_rwlock_runlock(u32 rw_lock_id) int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) { - sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); + sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout); RWLock* rw; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; @@ -123,7 +126,11 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) const u32 max_counter = timeout ? (timeout / 1000) : 20000; do { - if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (Emu.IsStopped()) + { + ConLog.Warning("sys_rwlock_wlock(rw_lock_id=%d, ...) aborted", rw_lock_id); + return CELL_ETIMEDOUT; + } Sleep(1); if (rw->wlock_trylock(tid, true)) return CELL_OK; @@ -132,7 +139,6 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) { if (!timeout) { - sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d): TIMEOUT", rw_lock_id); counter = 0; } else diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 355d422542..b1f614a456 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -156,7 +156,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< //166 int sys_spu_thread_set_argument(u32 id, mem_ptr_t arg) { - sc_spu.Warning("sys_spu_thread_set_argument(id=0x%x, arg_addr=0x%x)", id, arg.GetAddr()); + sc_spu.Warning("sys_spu_thread_set_argument(id=%d, arg_addr=0x%x)", id, arg.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) @@ -180,7 +180,7 @@ int sys_spu_thread_set_argument(u32 id, mem_ptr_t arg) //165 int sys_spu_thread_get_exit_status(u32 id, mem32_t status) { - sc_spu.Warning("sys_spu_thread_get_exit_status(id=0x%x, status_addr=0x%x)", id, status.GetAddr()); + sc_spu.Warning("sys_spu_thread_get_exit_status(id=%d, status_addr=0x%x)", id, status.GetAddr()); if (!status.IsGood()) { @@ -207,7 +207,7 @@ int sys_spu_thread_get_exit_status(u32 id, mem32_t status) //171 int sys_spu_thread_group_destroy(u32 id) { - sc_spu.Warning("sys_spu_thread_group_destroy(id=0x%x)", id); + sc_spu.Warning("sys_spu_thread_group_destroy(id=%d)", id); SpuGroupInfo* group_info; if(!Emu.GetIdManager().GetIDData(id, group_info)) @@ -232,7 +232,7 @@ int sys_spu_thread_group_destroy(u32 id) //173 int sys_spu_thread_group_start(u32 id) { - sc_spu.Warning("sys_spu_thread_group_start(id=0x%x)", id); + sc_spu.Warning("sys_spu_thread_group_start(id=%d)", id); SpuGroupInfo* group_info; if(!Emu.GetIdManager().GetIDData(id, group_info)) @@ -255,7 +255,7 @@ int sys_spu_thread_group_start(u32 id) //174 int sys_spu_thread_group_suspend(u32 id) { - sc_spu.Warning("sys_spu_thread_group_suspend(id=0x%x)", id); + sc_spu.Warning("sys_spu_thread_group_suspend(id=%d)", id); SpuGroupInfo* group_info; if(!Emu.GetIdManager().GetIDData(id, group_info)) @@ -293,7 +293,7 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_ttype, attr->ct)); - sc_spu.Warning("*** SPU Thread Group created [%s] (type=%d, option.ct=%d): id=%d", + sc_spu.Warning("*** SPU Thread Group created [%s] (type=0x%x, option.ct=0x%x): id=%d", name.wx_str(), (int)attr->type, (u32)attr->ct, id.GetValue()); return CELL_OK; @@ -302,7 +302,7 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t 63) - { - return CELL_EINVAL; - } - - CPUThread* thr = Emu.GetCPU().GetThread(id); - - if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) - { - return CELL_ESRCH; - } - - for(int j=0; jpos; ++j) - { - if(!equeue->ports[j]->thread) - { - equeue->ports[j]->thread = thr; - return CELL_OK; - } - } - - return CELL_EISCONN; -} - //160 int sys_raw_spu_create(mem32_t id, u32 attr_addr) { @@ -414,7 +384,7 @@ int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) //181 int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) { - sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)", + sc_spu.Warning("sys_spu_thread_write_ls(id=%d, address=0x%x, value=0x%llx, type=0x%x)", id, address, value, type); CPUThread* thr = Emu.GetCPU().GetThread(id); @@ -424,15 +394,30 @@ int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) return CELL_ESRCH; } - (*(SPUThread*)thr).WriteLS64(address, value); + if (!thr->IsRunning()) + { + return CELL_ESTAT; + } - return CELL_OK; + if (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment + { + return CELL_EINVAL; + } + + switch (type) + { + case 1: (*(SPUThread*)thr).WriteLS8(address, value); return CELL_OK; + case 2: (*(SPUThread*)thr).WriteLS16(address, value); return CELL_OK; + case 4: (*(SPUThread*)thr).WriteLS32(address, value); return CELL_OK; + case 8: (*(SPUThread*)thr).WriteLS64(address, value); return CELL_OK; + default: return CELL_EINVAL; + } } //182 int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type) { - sc_spu.Warning("sys_spu_thread_read_ls(id=0x%x, address=0x%x, value_addr=0x%x, type=0x%x)", + sc_spu.Warning("sys_spu_thread_read_ls(id=%d, address=0x%x, value_addr=0x%x, type=0x%x)", id, address, value.GetAddr(), type); CPUThread* thr = Emu.GetCPU().GetThread(id); @@ -442,20 +427,35 @@ int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type) return CELL_ESRCH; } - if(!value.IsGood() || !(*(SPUThread*)thr).IsGoodLSA(address)) + if (!thr->IsRunning()) + { + return CELL_ESTAT; + } + + if(!value.IsGood()) { return CELL_EFAULT; } - value = (*(SPUThread*)thr).ReadLS64(address); + if (!(*(SPUThread*)thr).IsGoodLSA(address) || (address % type)) // +check alignment + { + return CELL_EINVAL; + } - return CELL_OK; + switch (type) + { + case 1: value = (*(SPUThread*)thr).ReadLS8(address); return CELL_OK; + case 2: value = (*(SPUThread*)thr).ReadLS16(address); return CELL_OK; + case 4: value = (*(SPUThread*)thr).ReadLS32(address); return CELL_OK; + case 8: value = (*(SPUThread*)thr).ReadLS64(address); return CELL_OK; + default: return CELL_EINVAL; + } } //190 int sys_spu_thread_write_spu_mb(u32 id, u32 value) { - sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value); + sc_spu.Warning("sys_spu_thread_write_spu_mb(id=%d, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); @@ -464,11 +464,7 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value) return CELL_ESRCH; } - if(!(*(SPUThread*)thr).SPU.In_MBox.Push(value)) - { - ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items."); - return CELL_EBUSY; //? - } + (*(SPUThread*)thr).SPU.In_MBox.PushUncond(value); return CELL_OK; } @@ -476,7 +472,7 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value) //187 int sys_spu_thread_set_spu_cfg(u32 id, u64 value) { - sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=0x%x, value=0x%x)", id, value); + sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=%d, value=0x%x)", id, value); CPUThread* thr = Emu.GetCPU().GetThread(id); @@ -498,7 +494,7 @@ int sys_spu_thread_set_spu_cfg(u32 id, u64 value) //188 int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) { - sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=0x%x, value_addr=0x%x)", id, value.GetAddr()); + sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=%d, value_addr=0x%x)", id, value.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(id); @@ -515,7 +511,7 @@ int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) //184 int sys_spu_thread_write_snr(u32 id, u32 number, u32 value) { - sc_spu.Log("sys_spu_thread_write_snr(id=0x%x, number=%d, value=0x%x)", id, number, value); + sc_spu.Log("sys_spu_thread_write_snr(id=%d, number=%d, value=0x%x)", id, number, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) @@ -540,9 +536,23 @@ int sys_spu_thread_write_snr(u32 id, u32 number, u32 value) return CELL_OK; } +int sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et) +{ + sc_spu.Error("sys_spu_thread_group_connect_event(id=%d, eq=%d, et=0x%x)", id, eq, et); + + return CELL_OK; +} + +int sys_spu_thread_group_disconnect_event(u32 id, u32 et) +{ + sc_spu.Error("sys_spu_thread_group_disconnect_event(id=%d, et=0x%x)", id, et); + + return CELL_OK; +} + int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr) { - sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=0x%x, eq=0x%x, req=0x%llx, spup_addr=0x%x)", + sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(id=%d, eq=%d, req=0x%llx, spup_addr=0x%x)", id, eq, req, spup_addr); EventQueue* equeue; @@ -562,6 +572,7 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 return CELL_ESRCH; } + /* for(u32 i=0; ilist.GetCount(); ++i) { CPUThread* t; @@ -582,13 +593,79 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 return CELL_EISCONN; } } - } + }*/ return CELL_OK; } -int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num) +int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup) { - sc_spu.Error("sys_spu_thread_bind_queue(id=0x%x, spuq=0x%x, spuq_num=0x%x)", id, spuq, spuq_num); + sc_spu.Error("sys_spu_thread_group_disconnect_event_all_threads(id=%d, spup=%d)", id, spup); + + return CELL_OK; +} + +int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup) +{ + sc_spu.Error("sys_spu_thread_connect_event(id=%d, eq=%d, et=0x%x, spup=%d)", id, eq, et, spup); + + EventQueue* equeue; + if(!sys_event.CheckId(eq, equeue)) + { + return CELL_ESRCH; + } + + if(spup > 63) + { + return CELL_EINVAL; + } + + CPUThread* thr = Emu.GetCPU().GetThread(id); + + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) + { + return CELL_ESRCH; + } + + /* + for(int j=0; jpos; ++j) + { + if(!equeue->ports[j]->thread) + { + equeue->ports[j]->thread = thr; + return CELL_OK; + } + } + */ + + return CELL_EISCONN; +} + +// +int sys_spu_thread_disconnect_event(u32 id, u32 event_type, u8 spup) +{ + sc_spu.Error("sys_spu_thread_disconnect_event(id=%d, event_type=0x%x, spup=%d", id, event_type, spup); + + return CELL_OK; +} + +/* +SPU-Side functions: +int sys_spu_thread_receive_event(u32 spuq_num, mem32_t d1, mem32_t d2, mem32_t d3); +int sys_spu_thread_send_event(u8 spup, u24 data0, u32 data1); +int sys_spu_thread_throw_event(u8 spup, u24 data0, u32 data1); +int sys_spu_thread_tryreceive_event(u32 spuq_num, mem32_t d1, mem32_t d2, mem32_t d3); +*/ + +int sys_spu_thread_bind_queue(u32 id, u32 equeue_id, u32 spuq_num) +{ + sc_spu.Error("sys_spu_thread_bind_queue(id=%d, equeue_id=%d, spuq_num=%d)", id, equeue_id, spuq_num); + + return CELL_OK; +} + +int sys_spu_thread_unbind_queue(u32 id, u32 spuq_num) +{ + sc_spu.Error("sys_spu_thread_unbind_queue(id=0x%x, spuq_num=%d)", id, spuq_num); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp index 0e4273a864..bd112bbea6 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp @@ -52,7 +52,7 @@ int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_count, int max int sys_semaphore_destroy(u32 sem) { - sys_sem.Log("sys_semaphore_destroy(sem=0x%x)", sem); + sys_sem.Log("sys_semaphore_destroy(sem=%d)", sem); if(!sys_sem.CheckId(sem)) return CELL_ESRCH; @@ -75,7 +75,7 @@ int sys_semaphore_wait(u32 sem, u64 timeout) int sys_semaphore_trywait(u32 sem) { - sys_sem.Log("sys_semaphore_trywait(sem=0x%x)", sem); + sys_sem.Log("sys_semaphore_trywait(sem=%d)", sem); semaphore* sem_data = nullptr; if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; @@ -88,7 +88,7 @@ int sys_semaphore_trywait(u32 sem) int sys_semaphore_post(u32 sem, int count) { - sys_sem.Log("sys_semaphore_post(sem=0x%x, count=%d)", sem, count); + sys_sem.Log("sys_semaphore_post(sem=%d, count=%d)", sem, count); semaphore* sem_data = nullptr; if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; @@ -104,7 +104,7 @@ int sys_semaphore_post(u32 sem, int count) int sys_semaphore_get_value(u32 sem, u32 count_addr) { - sys_sem.Log("sys_semaphore_get_value(sem=0x%x, count_addr=0x%x)", sem, count_addr); + sys_sem.Log("sys_semaphore_get_value(sem=%d, count_addr=0x%x)", sem, count_addr); semaphore* sem_data = nullptr; if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp b/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp index 70ee8e627e..2317aeb767 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" -int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr) +int sys_tty_read(s32 ch, u64 buf_addr, u32 len, u64 preadlen_addr) { ConLog.Warning("sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); Memory.Write32NN(preadlen_addr, len); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 312f66c98b..9cf0c1293a 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -355,6 +355,7 @@ void Emulator::Load() GetGSManager().Init(); GetCallbackManager().Init(); GetAudioManager().Init(); + GetEventManager().Init(); thread.Run(); @@ -448,6 +449,7 @@ void Emulator::Stop() GetGSManager().Close(); GetAudioManager().Close(); + GetEventManager().Clear(); GetCPU().Close(); //SysCallsManager.Close(); GetIdManager().Clear(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index d9523f1519..74ce4c0f74 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -13,6 +13,7 @@ #include "Loader/Loader.h" #include "SysCalls/Callback.h" #include "SysCalls/Modules.h" +#include "event.h" struct EmuInfo { @@ -89,6 +90,7 @@ class Emulator AudioManager m_audio_manager; CallbackManager m_callback_manager; CPUThread* m_ppu_callback_thr; + EventManager m_event_manager; VFS m_vfs; @@ -128,6 +130,7 @@ public: Array& GetBreakPoints() { return m_break_points; } Array& GetMarkedPoints() { return m_marked_points; } CPUThread& GetCallbackThread() { return *m_ppu_callback_thr; } + EventManager& GetEventManager() { return m_event_manager; } void AddModuleInit(ModuleInitializer* m) { diff --git a/rpcs3/Emu/event.h b/rpcs3/Emu/event.h index 516ea06ed7..bcbccc6c85 100644 --- a/rpcs3/Emu/event.h +++ b/rpcs3/Emu/event.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/SysCalls/lv2/SC_Lwmutex.h" enum EventQueueType { @@ -6,10 +7,33 @@ enum EventQueueType SYS_SPU_QUEUE = 2, }; +enum EventQueueDestroyMode +{ + // DEFAULT = 0, + SYS_EVENT_QUEUE_DESTROY_FORCE = 1, +}; + +enum EventPortType +{ + SYS_EVENT_PORT_LOCAL = 1, +}; + +enum EventSourceType +{ + SYS_SPU_THREAD_EVENT_USER = 1, + /* SYS_SPU_THREAD_EVENT_DMA = 2, */ // not supported +}; + +enum EventSourceKey : u64 +{ + SYS_SPU_THREAD_EVENT_USER_KEY = 0xFFFFFFFF53505501, + /* SYS_SPU_THREAD_EVENT_DMA_KEY = 0xFFFFFFFF53505502, */ +}; + struct sys_event_queue_attr { be_t protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO - be_t type; + be_t type; // SYS_PPU_QUEUE or SYS_SPU_QUEUE union { char name[8]; @@ -29,34 +53,171 @@ struct EventQueue; struct EventPort { - u64 name; - u64 data1; - u64 data2; - u64 data3; - bool has_data; - CPUThread* thread; - EventQueue* queue[127]; - int pos; -}; + u64 name; // generated or user-specified code that is passed to sys_event_data struct + EventQueue* eq; // event queue this port has been connected to + SMutex mutex; // may be locked until the event sending is finished -struct EventQueue -{ - EventPort* ports[127]; - int size; - int pos; - - u32 m_protocol; - int m_type; - u64 m_name; - u64 m_key; - - EventQueue(u32 protocol, int type, u64 name, u64 key, int size) - : m_type(type) - , m_protocol(protocol) - , m_name(name) - , m_key(key) - , size(size) - , pos(0) + EventPort(u64 name = 0) + : eq(nullptr) + , name(name) { } +}; + +class EventRingBuffer +{ + Array data; + SMutex m_lock; + u32 buf_pos; + u32 buf_count; + +public: + const u32 size; + + EventRingBuffer(u32 size) + : size(size) + , buf_pos(0) + , buf_count(0) + { + data.SetCount(size); + } + + void clear() + { + SMutexLocker lock(m_lock); + buf_count = 0; + buf_pos = 0; + } + + bool push(u64 name, u64 d1, u64 d2, u64 d3) + { + SMutexLocker lock(m_lock); + if (buf_count >= size) return false; + + sys_event_data& ref = data[(buf_pos + buf_count++) % size]; + ref.source = name; + ref.data1 = d1; + ref.data2 = d2; + ref.data3 = d3; + + return true; + } + + bool pop(sys_event_data& ref) + { + SMutexLocker lock(m_lock); + if (!buf_count) return false; + + sys_event_data& from = data[buf_pos]; + buf_pos = (buf_pos + 1) % size; + buf_count--; + ref.source = from.source; + ref.data1 = from.data1; + ref.data2 = from.data2; + ref.data3 = from.data3; + + return true; + } + + u32 pop_all(sys_event_data* ptr, u32 max) + { + SMutexLocker lock(m_lock); + + u32 res = 0; + while (buf_count && max) + { + sys_event_data& from = data[buf_pos]; + ptr->source = from.source; + ptr->data1 = from.data1; + ptr->data2 = from.data2; + ptr->data3 = from.data3; + buf_pos = (buf_pos + 1) % size; + buf_count--; + max--; + ptr++; + res++; + } + return res; + } + + u32 count() + { + return buf_count; + } +}; + +class EventPortList +{ + Array data; + SMutex m_lock; + +public: + + void clear() + { + SMutexLocker lock(m_lock); + for (u32 i = 0; i < data.GetCount(); i++) + { + data[i]->eq = nullptr; // force all ports to disconnect + } + data.Clear(); + } + + void add(EventPort* port) + { + SMutexLocker lock(m_lock); + data.AddCpy(port); + } + + void remove(EventPort* port) + { + SMutexLocker lock(m_lock); + for (u32 i = 0; i < data.GetCount(); i++) + { + if (data[i] == port) + { + data.RemoveAt(i); + return; + } + } + } +}; + +struct EventQueue : SleepQueue +{ + EventPortList ports; + EventRingBuffer events; + SMutex owner; + + const union + { + u64 name_u64; + char name[8]; + }; + const u32 protocol; + const int type; + const u64 key; + + EventQueue(u32 protocol, int type, u64 name, u64 key, int size) + : type(type) + , protocol(protocol) + , name_u64(name) + , key(key) + , events(size) // size: max event count this queue can hold + { + } +}; + +class EventManager +{ + SMutex m_lock; + std::unordered_map key_map; + +public: + void Init(); + void Clear(); + bool CheckKey(u64 key); + bool RegisterKey(EventQueue* data, u64 key); + bool GetEventQueue(u64 key, EventQueue*& data); + bool UnregisterKey(u64 key); }; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index a0d70bab51..7cb0d5564d 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -224,6 +224,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 49278953be..b4ddf4bb88 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -388,6 +388,9 @@ Emu\SysCalls\Modules + + Emu\SysCalls +