diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index 8c0201d257..d98f13d793 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -79,12 +79,12 @@ public: } } - volatile u32 GetCount() + volatile u32 GetCount() // may be not safe { return m_count; } - volatile bool IsEmpty() + volatile bool IsEmpty() // may be not safe { return !m_count; } @@ -97,7 +97,28 @@ public: T& Peek(u32 pos = 0) { - SMutexLocker lock(m_mutex); + while (true) + { + if (m_mutex.GetOwner() == m_mutex.GetDeadValue()) + { + break; + } + + if (!m_count) + { + if (Emu.IsStopped()) + { + break; + } + Sleep(1); + continue; + } + + { + SMutexLocker lock(m_mutex); + if (m_count) break; + } + } return m_data[(m_pos + pos) % SQSize]; } }; diff --git a/rpcs3/Emu/Audio/AudioDumper.cpp b/rpcs3/Emu/Audio/AudioDumper.cpp index f906b3531a..dbd282e7ae 100644 --- a/rpcs3/Emu/Audio/AudioDumper.cpp +++ b/rpcs3/Emu/Audio/AudioDumper.cpp @@ -23,16 +23,22 @@ void AudioDumper::WriteHeader() size_t AudioDumper::WriteData(const void* buffer, size_t size) { + for (u32 i = 0; i < size / 8; i++) + { + if (((u64*)buffer)[i]) goto process; + } + for (u32 i = 0; i < size % 8; i++) + { + if (((u8*)buffer)[i + (size & ~7)]) goto process; + } + return size; // ignore empty data +process: size_t ret = m_output.Write(buffer, size); + m_header.Size += ret; + m_header.RIFF.Size += ret; return ret; } -void AudioDumper::UpdateHeader(size_t size) -{ - m_header.Size += size; - m_header.RIFF.Size += size; -} - void AudioDumper::Finalize() { m_output.Seek(0); diff --git a/rpcs3/Emu/Audio/AudioDumper.h b/rpcs3/Emu/Audio/AudioDumper.h index 6d1d8568e1..f9ac030476 100644 --- a/rpcs3/Emu/Audio/AudioDumper.h +++ b/rpcs3/Emu/Audio/AudioDumper.h @@ -64,6 +64,5 @@ public: bool Init(); void WriteHeader(); size_t WriteData(const void* buffer, size_t size); - void UpdateHeader(size_t size); void Finalize(); }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 9df0cc6a9e..b4c6a5e025 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -58,7 +58,7 @@ void CPUThread::CloseStack() { if(m_stack_addr) { - Memory.Free(m_stack_addr); + Memory.StackMem.Free(m_stack_addr); m_stack_addr = 0; } diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index bef241c7b8..0cd0a5f43a 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -4,13 +4,16 @@ enum { MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22, + MFC_PUTR_CMD = 0x30, MFC_PUTRB_CMD = 0x31, MFC_PUTRF_CMD = 0x32, MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42, MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26, + MFC_PUTRL_CMD = 0x34, MFC_PUTRLB_CMD = 0x35, MFC_PUTRLF_CMD = 0x36, MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46, MFC_GETLLAR_CMD = 0xD0, MFC_PUTLLC_CMD = 0xB4, MFC_PUTLLUC_CMD = 0xB0, MFC_PUTQLLUC_CMD = 0xB8, + MFC_SNDSIG_CMD = 0xA0, MFC_SNDSIGB_CMD = 0xA1, MFC_SNDSIGF_CMD = 0xA2, MFC_BARRIER_CMD = 0xC0, MFC_EIEIO_CMD = 0xC8, @@ -19,6 +22,8 @@ enum MFC_BARRIER_MASK = 0x01, MFC_FENCE_MASK = 0x02, MFC_LIST_MASK = 0x04, + MFC_START_MASK = 0x08, // ??? + MFC_RESULT_MASK = 0x10, // ??? MFC_MASK_CMD = 0xffff, }; @@ -55,7 +60,7 @@ enum MFC_SPU_MAX_QUEUE_SPACE = 0x10, }; -struct DMAC_Queue +/*struct DMAC_Queue { bool is_valid; u64 ea; @@ -149,13 +154,14 @@ public: { return Memory.Read32(m_addr); } -}; +};*/ struct DMAC { - //DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet - DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24 u64 ls_offset; + + /*//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet + DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24 u32 queue_pos; u32 proxy_pos; long queue_lock; @@ -194,18 +200,6 @@ struct DMAC return MFC_PPU_DMA_QUEUE_FULL; } - /* while (std::atomic_exchange(&proxy_lock, 1)); - _mm_lfence(); - DMAC_Proxy& p = proxy[proxy_pos]; - p.cmd = cmd; - p.tag = tag; - p.lsa = lsa; - p.ea = ea; - p.size = size; - _mm_sfence(); //for DoCmd() - proxy_pos++; - _mm_sfence(); - proxy_lock = 0; */ ProcessCmd(cmd, tag, lsa, ea, size); return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; @@ -230,10 +224,10 @@ struct DMAC ClearCmd(); } } - } + }*/ }; -struct MFC +/*struct MFC { SPUReg<1> MFC_LSA; SPUReg<1> MFC_EAH; @@ -299,4 +293,4 @@ struct MFC MFC_QStatus.SetValue(mask); } } -}; +};*/ diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 49f2abfff2..4cb3d27354 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -283,7 +283,7 @@ void RawSPUThread::Task() continue; } - dmac.DoCmd(); + //dmac.DoCmd(); if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) { diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 0b3aba0c25..2b6a4d782a 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -113,14 +113,26 @@ private: } } break; - case 0x102: default: - if (!CPU.SPU.Out_MBox.GetCount()) // the real exit status + case 0x102: + if (!CPU.SPU.Out_MBox.GetCount()) { - ConLog.Warning("STOP: 0x%x (no message)", code); + ConLog.Error("sys_spu_thread_exit (no status, code 0x102)"); } - else if (Ini.HLELogging.GetValue() || code != 0x102) + else if (Ini.HLELogging.GetValue()) { - ConLog.Warning("STOP: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue()); + // the real exit status + ConLog.Write("sys_spu_thread_exit (status=0x%x)", CPU.SPU.Out_MBox.GetValue()); + } + CPU.Stop(); + break; + default: + if (!CPU.SPU.Out_MBox.GetCount()) + { + ConLog.Error("Unknown STOP code: 0x%x (no message)", code); + } + else + { + ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue()); } CPU.Stop(); break; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 2e32989e08..0d651af5f5 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -20,6 +20,8 @@ SPUThread::SPUThread(CPUThreadType type) : PPCThread(type) { assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU); + group = nullptr; + Reset(); } @@ -46,10 +48,10 @@ void SPUThread::InitRegs() cfg.Reset(); dmac.ls_offset = m_offset; - dmac.proxy_pos = 0; + /*dmac.proxy_pos = 0; dmac.queue_pos = 0; dmac.proxy_lock = 0; - dmac.queue_lock = 0; + dmac.queue_lock = 0;*/ SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP); SPU.Status.SetValue(SPU_STATUS_RUNNING); diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index cfed36752e..ba260eb360 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -119,6 +119,15 @@ enum SPU_STATUS_SINGLE_STEP = 0x10, }; +enum : u32 +{ + SYS_SPU_THREAD_BASE_LOW = 0xf0000000, + SYS_SPU_THREAD_BASE_MASK = 0xfffffff, + SYS_SPU_THREAD_OFFSET = 0x00100000, + SYS_SPU_THREAD_SNR1 = 0x05400c, + SYS_SPU_THREAD_SNR2 = 0x05C00c, +}; + //Floating point status and control register. Unsure if this is one of the GPRs or SPRs //Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused class FPSCR @@ -278,6 +287,7 @@ public: EventPort SPUPs[64]; // SPU Thread Event Ports EventManager SPUQs; // SPU Queue Mapping + SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu) template class Channel @@ -512,6 +522,18 @@ public: Channel<1> SNR[2]; } SPU; + void WriteSNR(bool number, u32 value) + { + if (cfg.value & ((u64)1 << (u64)number)) + { + SPU.SNR[number].PushUncond_OR(value); // logical OR + } + else + { + SPU.SNR[number].PushUncond(value); // overwrite + } + } + u32 LSA; union @@ -522,6 +544,81 @@ public: DMAC dmac; + bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) + { + if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); + + if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW) + { + if (group) + { + // SPU Thread Group MMIO (LS and SNR) + u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group + if (num >= group->list.GetCount() || !group->list[num]) + { + ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea); + return false; + } + + SPUThread* spu = (SPUThread*)Emu.GetCPU().GetThread(group->list[num]); + + u32 addr = (ea & SYS_SPU_THREAD_BASE_MASK) % SYS_SPU_THREAD_OFFSET; + if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) + { + // LS access + ea = spu->dmac.ls_offset + addr; + } + else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) + { + spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, Memory.Read32(dmac.ls_offset + lsa)); + return true; + } + else + { + ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd); + return false; + } + } + else + { + ConLog.Error("DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea); + return false; + } + } + + switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) + { + case MFC_PUT_CMD: + { + return Memory.Copy(ea, dmac.ls_offset + lsa, size); + } + + case MFC_GET_CMD: + { + return Memory.Copy(dmac.ls_offset + lsa, ea, size); + } + + default: + { + ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd."); + return false; + } + } + } + + u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) + { + /*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE) + { + return MFC_PPU_DMA_QUEUE_FULL; + }*/ + + if (ProcessCmd(cmd, tag, lsa, ea, size)) + return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; + else + return MFC_PPU_DMA_CMD_SEQUENCE_ERROR; + } + void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs) { u32 list_addr = ea & 0x3ffff; @@ -549,7 +646,7 @@ public: } u32 addr = rec->ea; - result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size); + result = dmacCmd(cmd, tag, lsa | (addr & 0xf), addr, size); if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR) { break; @@ -596,17 +693,19 @@ public: switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) { case MFC_PUT_CMD: + case MFC_PUTR_CMD: // ??? case MFC_GET_CMD: { - if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(), + if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(), + wxString(op & MFC_RESULT_MASK ? "R" : "").wx_str(), wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(), wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(), lsa, ea, tag, size, cmd); if (op & MFC_PUT_CMD) { SMutexLocker lock(reservation.mutex); // should be removed - MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size)); if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) || (ea + size > reservation.addr && ea <= reservation.addr + reservation.size)) { @@ -615,16 +714,18 @@ public: } else { - MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + MFCArgs.CMDStatus.SetValue(dmacCmd(cmd, tag, lsa, ea, size)); } } break; case MFC_PUTL_CMD: + case MFC_PUTRL_CMD: // ??? case MFC_GETL_CMD: { - if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", - wxString(op & MFC_PUT_CMD ? "PUTL" : "GETL").wx_str(), + if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + wxString(op & MFC_PUT_CMD ? "PUT" : "GET").wx_str(), + wxString(op & MFC_RESULT_MASK ? "RL" : "L").wx_str(), wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(), wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(), lsa, ea, tag, size, cmd); @@ -650,7 +751,7 @@ public: reservation.owner = lock.tid; reservation.addr = ea; reservation.size = 128; - dmac.ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128); + ProcessCmd(MFC_GET_CMD, tag, lsa, ea, 128); Prxy.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); } else if (op == MFC_PUTLLC_CMD) // store conditional @@ -660,7 +761,7 @@ public: { if (reservation.addr == ea && reservation.size == 128) { - dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); Prxy.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); } else @@ -677,7 +778,7 @@ public: else // store unconditional { SMutexLocker lock(reservation.mutex); - dmac.ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); if (op == MFC_PUTLLUC_CMD) { Prxy.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); @@ -795,9 +896,66 @@ public: SPU.In_MBox.PushUncond(CELL_OK); return; } + else if (code = 128) + { + /* ===== sys_event_flag_set_bit ===== */ + u32 flag = v & 0xffffff; + + u32 data; + if (!SPU.Out_MBox.Pop(data)) + { + ConLog.Error("sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag); + return; + } + + if (flag > 63) + { + ConLog.Error("sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag); + return; + } + + //if (Ini.HLELogging.GetValue()) + { + ConLog.Warning("sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag); + } + + EventFlag* ef; + if (!Emu.GetIdManager().GetIDData(data, ef)) + { + ConLog.Error("sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag); + SPU.In_MBox.PushUncond(CELL_ESRCH); + return; + } + + u32 tid = GetCurrentCPUThread()->GetId(); + + ef->m_mutex.lock(tid); + ef->flags |= (u64)1 << flag; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } + + SPU.In_MBox.PushUncond(CELL_OK); + return; + } else { - ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); + u32 data; + if (SPU.Out_MBox.Pop(data)) + { + ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data); + } + else + { + ConLog.Error("SPU_WrOutIntrMbox: unknown data (v=0x%x)", v); + } SPU.In_MBox.PushUncond(CELL_EINVAL); // ??? return; } diff --git a/rpcs3/Emu/FS/vfsDevice.cpp b/rpcs3/Emu/FS/vfsDevice.cpp index bc1014607b..d6af3341a7 100644 --- a/rpcs3/Emu/FS/vfsDevice.cpp +++ b/rpcs3/Emu/FS/vfsDevice.cpp @@ -48,8 +48,14 @@ u32 vfsDevice::CmpLocalPath(const wxString& local_path) wxFileName path0(m_local_path); path0.Normalize(); - wxArrayString arr0 = wxSplit(path0.GetFullPath(), '/'); - wxArrayString arr1 = wxSplit(local_path, '/'); +#ifdef _WIN32 +#define DL '\\' +#else +#define DL '/' +#endif + + wxArrayString arr0 = wxSplit(path0.GetFullPath(), DL); + wxArrayString arr1 = wxSplit(local_path, DL); const u32 lim = min(arr0.GetCount(), arr1.GetCount()); u32 ret = 0; @@ -179,7 +185,7 @@ wxString vfsDevice::GetWinPath(const wxString& p, bool is_dir) ret += p[i]; } - if(is_dir && ret[ret.Len() - 1] != '/') ret += '/'; + if(is_dir && ret[ret.Len() - 1] != '/' && ret[ret.Len() - 1] != '\\') ret += '/'; // ??? wxFileName res(ret); res.Normalize(); diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index ef953b4f49..8dedb87532 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -56,7 +56,7 @@ bool vfsLocalFile::Create(const wxString& path) for(uint p=1; p < path.Len() && path[p] != '\0' ; p++) { for(; p < path.Len() && path[p] != '\0'; p++) - if(path[p] == '/') break; + if(path[p] == '/' || path[p] == '\\') break; // ??? if(p == path.Len() || path[p] == '\0') break; @@ -70,7 +70,8 @@ bool vfsLocalFile::Create(const wxString& path) } //create file - if(path(path.Len() - 1, 1) != '/' && !wxFileExists(path)) + wxString m = path(path.Len() - 1, 1); + if(m != '/' && m != '\\' && !wxFileExists(path)) // ??? { wxFile f; return f.Create(path); diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index cabcd745d7..dd849d4623 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1144,6 +1144,14 @@ void GLGSRender::Flip() if(src_buffer) { + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + glDisable(GL_CLIP_PLANE4); + glDisable(GL_CLIP_PLANE5); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, g_flip_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); @@ -1163,6 +1171,7 @@ void GLGSRender::Flip() m_program.Use(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); + glColor3f(1, 1, 1); glBegin(GL_QUADS); glTexCoord2i(0, 1); glVertex2i(0, 0); diff --git a/rpcs3/Emu/HDD/HDD.h b/rpcs3/Emu/HDD/HDD.h index 0535a018c0..3271ed4605 100644 --- a/rpcs3/Emu/HDD/HDD.h +++ b/rpcs3/Emu/HDD/HDD.h @@ -695,7 +695,7 @@ public: do { - if(s[pos] == '/' || s[pos] == '\0') + if(s[pos] == '\\' || s[pos] == '/' || s[pos] == '\0') // ??? { if(file_pos != -1) { diff --git a/rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl b/rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl index 7af30bc435..33b80d2ecf 100644 --- a/rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl +++ b/rpcs3/Emu/Memory/DynamicMemoryBlockBase.inl @@ -210,6 +210,11 @@ bool DynamicMemoryBlockBase::Free(u64 addr) } } + ConLog.Error("DynamicMemoryBlock::Free(addr=0x%llx): failed", addr); + for (u32 i = 0; i < m_allocated.GetCount(); i++) + { + ConLog.Write("*** Memory Block: addr = 0x%llx, size = 0x%x", m_allocated[i].addr, m_allocated[i].size); + } return false; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index a2805567c4..fec5d753be 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -9,6 +9,7 @@ extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libswresample/swresample.h" } #include "cellAdec.h" @@ -16,7 +17,7 @@ extern "C" void cellAdec_init(); Module cellAdec(0x0006, cellAdec_init); -int adecRead(void* opaque, u8* buf, int buf_size) +int adecRawRead(void* opaque, u8* buf, int buf_size) { AudioDecoder& adec = *(AudioDecoder*)opaque; @@ -61,13 +62,14 @@ next: adec.reader.addr = adec.task.au.addr; adec.reader.size = adec.task.au.size; + //ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts); - adec.last_pts = adec.task.au.pts; + //if (adec.last_pts > adec.task.au.pts) adec.last_pts = adec.task.au.pts; } break; default: ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type); - return 0; + return -1; } goto next; @@ -95,6 +97,89 @@ next: } } +int adecRead(void* opaque, u8* buf, int buf_size) +{ + AudioDecoder& adec = *(AudioDecoder*)opaque; + + int res = 0; + + if (adec.reader.rem_size && adec.reader.rem) + { + if (buf_size < (int)adec.reader.rem_size) + { + ConLog.Error("adecRead: too small buf_size (rem_size = %d, buf_size = %d)", adec.reader.rem_size, buf_size); + Emu.Pause(); + return 0; + } + + memcpy(buf, adec.reader.rem, adec.reader.rem_size); + free(adec.reader.rem); + adec.reader.rem = nullptr; + buf += adec.reader.rem_size; + buf_size -= adec.reader.rem_size; + res += adec.reader.rem_size; + adec.reader.rem_size = 0; + } + + while (buf_size) + { + u8 header[8]; + if (adecRawRead(opaque, header, 8) < 8) break; + if (header[0] != 0x0f || header[1] != 0xd0) + { + ConLog.Error("adecRead: 0x0FD0 header not found"); + Emu.Pause(); + return -1; + } + + if (!adec.reader.init) + { + OMAHeader oma(1 /* atrac3p id */, header[2], header[3]); + if (buf_size < sizeof(oma) + 8) + { + ConLog.Error("adecRead: OMAHeader writing failed"); + Emu.Pause(); + return 0; + } + + memcpy(buf, &oma, sizeof(oma)); + buf += sizeof(oma); + buf_size -= sizeof(oma); + res += sizeof(oma); + + adec.reader.init = true; + } + else + { + } + + u32 size = (((header[2] & 0x3) << 8) | header[3]) * 8 + 8; // data to be read before next header + + //ConLog.Write("*** audio block read: size = 0x%x", size); + + if (buf_size < (int)size) + { + if (adecRawRead(opaque, buf, buf_size) < buf_size) break; // ??? + res += buf_size; + size -= buf_size; + buf_size = 0; + + adec.reader.rem = (u8*)malloc(size); + adec.reader.rem_size = size; + if (adecRawRead(opaque, adec.reader.rem, size) < (int)size) break; // ??? + } + else + { + if (adecRawRead(opaque, buf, size) < (int)size) break; // ??? + buf += size; + buf_size -= size; + res += size; + } + } + + return res; +} + u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; @@ -146,6 +231,10 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = 0; adec.reader.size = 0; + adec.reader.init = false; + if (adec.reader.rem) free(adec.reader.rem); + adec.reader.rem = nullptr; + adec.reader.rem_size = 0; adec.is_running = true; adec.just_started = true; } @@ -175,8 +264,10 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = task.au.addr; adec.reader.size = task.au.size; + //ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts); - adec.last_pts = task.au.pts; + //if (adec.last_pts > task.au.pts || adec.just_started) adec.last_pts = task.au.pts; + if (adec.just_started) adec.last_pts = task.au.pts; struct AVPacketHolder : AVPacket { @@ -212,11 +303,11 @@ u32 adecOpen(AudioDecoder* data) if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); - } + }*/ if (adec.just_started) // deferred initialization { - err = avformat_open_input(&adec.fmt, NULL, NULL, NULL); + err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_open_input() failed"); @@ -230,7 +321,7 @@ u32 adecOpen(AudioDecoder* data) Emu.Pause(); break; } - err = avformat_find_stream_info(adec.fmt, NULL); + /*err = avformat_find_stream_info(adec.fmt, NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed"); @@ -242,6 +333,12 @@ u32 adecOpen(AudioDecoder* data) ConLog.Error("adecDecodeAu: no stream found"); Emu.Pause(); break; + }*/ + if (!avformat_new_stream(adec.fmt, codec)) + { + ConLog.Error("adecDecodeAu: avformat_new_stream() failed"); + Emu.Pause(); + break; } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data @@ -259,7 +356,7 @@ u32 adecOpen(AudioDecoder* data) break; } adec.just_started = false; - }*/ + } bool last_frame = false; @@ -271,7 +368,7 @@ u32 adecOpen(AudioDecoder* data) return; } - if (!adec.ctx) // fake + /*if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; @@ -285,7 +382,7 @@ u32 adecOpen(AudioDecoder* data) adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; - } + }*/ last_frame = av_read_frame(adec.fmt, &au) < 0; if (last_frame) @@ -336,13 +433,30 @@ u32 adecOpen(AudioDecoder* data) if (got_frame) { - ConLog.Write("got_frame (%d, pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts); - - frame.pts = task.au.pts; // ??? + frame.pts = adec.last_pts; + adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ??? frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; - frame.size = 32768; // ???? + frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float); + + if (frame.data->format != AV_SAMPLE_FMT_FLTP) + { + ConLog.Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format); + Emu.Pause(); + break; + } + if (frame.data->channels != 2) + { + ConLog.Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels); + Emu.Pause(); + break; + } + + //ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)", + //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, + //av_get_bytes_per_sample((AVSampleFormat)frame.data->format)); + adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction @@ -569,26 +683,62 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) AdecFrame af; adec->frames.Pop(af); - //AVFrame& frame = *af.data; + AVFrame* frame = af.data; int result = CELL_OK; if (!Memory.IsGoodAddr(outBuffer_addr, af.size)) { result = CELL_ADEC_ERROR_FATAL; + goto end; } - else + + if (!af.data) // fake: empty data { - // copy data - if (!af.data) // fake: empty data - { - u8* buf = (u8*)malloc(4096); - memset(buf, 0, 4096); - Memory.CopyFromReal(outBuffer_addr, buf, 4096); - free(buf); - return CELL_OK; - } + /*u8* buf = (u8*)malloc(4096); + memset(buf, 0, 4096); + Memory.CopyFromReal(outBuffer_addr, buf, 4096); + free(buf);*/ + goto end; } + // copy data + SwrContext* swr = nullptr; + u8* out = nullptr; + + out = (u8*)malloc(af.size); + + /*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000, + frame->channel_layout, (AVSampleFormat)frame->format, frame->sample_rate, 0, NULL); + + if (!swr) + { + ConLog.Error("cellAdecGetPcm(%d): swr_alloc_set_opts() failed", handle); + Emu.Pause(); + goto end; + } + // something is wrong + swr_convert(swr, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples); */ + + // reverse byte order, extract data: + float* in_f[2]; + in_f[0] = (float*)frame->extended_data[0]; + in_f[1] = (float*)frame->extended_data[1]; + be_t* out_f = (be_t*)out; + for (u32 i = 0; i < af.size / 8; i++) + { + out_f[i*2] = in_f[0][i]; + out_f[i*2+1] = in_f[1][i]; + } + + if (!Memory.CopyFromReal(outBuffer_addr, out, af.size)) + { + ConLog.Error("cellAdecGetPcm(%d): data copying failed (addr=0x%x)", handle, outBuffer_addr); + Emu.Pause(); + } + +end: + if (out) free(out); + if (swr) swr_free(&swr); if (af.data) { @@ -620,7 +770,7 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) return CELL_ADEC_ERROR_EMPTY; } - //AVFrame& frame = *af.data; + AVFrame* frame = af.data; mem_ptr_t pcm(adec->memAddr + adec->memBias); @@ -635,15 +785,15 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) pcm->startAddr = 0x00000312; // invalid address (no output) pcm->size = af.size; pcm->status = CELL_OK; - pcm->auInfo.pts.lower = af.pts; // ??? + pcm->auInfo.pts.lower = af.pts; pcm->auInfo.pts.upper = af.pts >> 32; pcm->auInfo.size = af.auSize; pcm->auInfo.startAddr = af.auAddr; pcm->auInfo.userData = af.userdata; mem_ptr_t atx(pcm.GetAddr() + sizeof(CellAdecPcmItem)); - atx->samplingFreq = 48000; // ??? - atx->nbytes = 2048; // ??? + atx->samplingFreq = frame->sample_rate; // ??? + atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ??? atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? pcmItem_ptr = pcm.GetAddr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 793a78905a..66364a6084 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1036,6 +1036,40 @@ struct AdecFrame int adecRead(void* opaque, u8* buf, int buf_size); +struct OMAHeader // OMA Header +{ + u32 magic; // 0x01334145 + u16 size; // 96 << 8 + u16 unk0; // 0xffff + u64 unk1; // 0x00500f0100000000ULL + u64 unk2; // 0xcef5000000000400ULL + u64 unk3; // 0x1c458024329192d2ULL + u8 codecId; // 1 for ATRAC3P + u8 reserved0; // 0 + u8 code1; + u8 code2; + u32 reserved1; // 0 + u64 reserved[7]; // 0 + + OMAHeader(u8 id, u8 code1, u8 code2) + : magic(0x01334145) + , size(96 << 8) + , unk0(0xffff) + , unk1(0x00500f0100000000ULL) + , unk2(0xcef5000000000400ULL) + , unk3(0x1c458024329192d2ULL) + , codecId(id) + , reserved0(0) + , code1(code1) + , code2(code2) + , reserved1(0) + { + memset(reserved, 0, sizeof(reserved)); + } +}; + +static_assert(sizeof(OMAHeader) == 96, "Wrong OMAHeader size"); + class AudioDecoder { public: @@ -1053,6 +1087,21 @@ public: { u32 addr; u32 size; + bool init; + u8* rem; + u32 rem_size; + + AudioReader() + : rem(nullptr) + , rem_size(0) + { + } + + ~AudioReader() + { + if (rem) free(rem); + rem = nullptr; + } } reader; SQueue frames; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp b/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp index c29f7b1038..a73ab793d2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp @@ -5,32 +5,7 @@ void cellAtrac_init(); Module cellAtrac(0x0013, cellAtrac_init); -// Return Codes -enum -{ - CELL_ATRAC_OK = 0x00000000, - CELL_ATRAC_ERROR_API_FAIL = 0x80610301, - CELL_ATRAC_ERROR_READSIZE_OVER_BUFFER = 0x80610311, - CELL_ATRAC_ERROR_UNKNOWN_FORMAT = 0x80610312, - CELL_ATRAC_ERROR_READSIZE_IS_TOO_SMALL = 0x80610313, - CELL_ATRAC_ERROR_ILLEGAL_SAMPLING_RATE = 0x80610314, - CELL_ATRAC_ERROR_ILLEGAL_DATA = 0x80610315, - CELL_ATRAC_ERROR_NO_DECODER = 0x80610321, - CELL_ATRAC_ERROR_UNSET_DATA = 0x80610322, - CELL_ATRAC_ERROR_DECODER_WAS_CREATED = 0x80610323, - CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED = 0x80610331, - CELL_ATRAC_ERROR_NODATA_IN_BUFFER = 0x80610332, - CELL_ATRAC_ERROR_NOT_ALIGNED_OUT_BUFFER = 0x80610333, - CELL_ATRAC_ERROR_NEED_SECOND_BUFFER = 0x80610334, - CELL_ATRAC_ERROR_ALLDATA_IS_ONMEMORY = 0x80610341, - CELL_ATRAC_ERROR_ADD_DATA_IS_TOO_BIG = 0x80610342, - CELL_ATRAC_ERROR_NONEED_SECOND_BUFFER = 0x80610351, - CELL_ATRAC_ERROR_UNSET_LOOP_NUM = 0x80610361, - CELL_ATRAC_ERROR_ILLEGAL_SAMPLE = 0x80610371, - CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372, - CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381, - CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382, -}; +#include "cellAtrac.h" int cellAtracSetDataAndGetMemSize() { @@ -58,13 +33,13 @@ int cellAtracDeleteDecoder() int cellAtracDecode() { - UNIMPLEMENTED_FUNC(cellAtrac); + //UNIMPLEMENTED_FUNC(cellAtrac); return CELL_OK; } int cellAtracGetStreamDataInfo() { - UNIMPLEMENTED_FUNC(cellAtrac); + //UNIMPLEMENTED_FUNC(cellAtrac); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.h b/rpcs3/Emu/SysCalls/Modules/cellAtrac.h new file mode 100644 index 0000000000..3d1d652644 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellAtrac.h @@ -0,0 +1,28 @@ +#pragma once + +// Return Codes +enum +{ + CELL_ATRAC_OK = 0x00000000, + CELL_ATRAC_ERROR_API_FAIL = 0x80610301, + CELL_ATRAC_ERROR_READSIZE_OVER_BUFFER = 0x80610311, + CELL_ATRAC_ERROR_UNKNOWN_FORMAT = 0x80610312, + CELL_ATRAC_ERROR_READSIZE_IS_TOO_SMALL = 0x80610313, + CELL_ATRAC_ERROR_ILLEGAL_SAMPLING_RATE = 0x80610314, + CELL_ATRAC_ERROR_ILLEGAL_DATA = 0x80610315, + CELL_ATRAC_ERROR_NO_DECODER = 0x80610321, + CELL_ATRAC_ERROR_UNSET_DATA = 0x80610322, + CELL_ATRAC_ERROR_DECODER_WAS_CREATED = 0x80610323, + CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED = 0x80610331, + CELL_ATRAC_ERROR_NODATA_IN_BUFFER = 0x80610332, + CELL_ATRAC_ERROR_NOT_ALIGNED_OUT_BUFFER = 0x80610333, + CELL_ATRAC_ERROR_NEED_SECOND_BUFFER = 0x80610334, + CELL_ATRAC_ERROR_ALLDATA_IS_ONMEMORY = 0x80610341, + CELL_ATRAC_ERROR_ADD_DATA_IS_TOO_BIG = 0x80610342, + CELL_ATRAC_ERROR_NONEED_SECOND_BUFFER = 0x80610351, + CELL_ATRAC_ERROR_UNSET_LOOP_NUM = 0x80610361, + CELL_ATRAC_ERROR_ILLEGAL_SAMPLE = 0x80610371, + CELL_ATRAC_ERROR_ILLEGAL_RESET_BYTE = 0x80610372, + CELL_ATRAC_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610381, + CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382, +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index f6ff6404b2..59fc40a276 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -118,29 +118,37 @@ int cellAudioInit() index = (position + 1) % port.block; // write new value } + u32 k = port.channel / 2; + if (first_mix) { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) { // reverse byte order (TODO: use port.m_param.level) - buffer[i] = buffer2[i]; + buffer[i] = buffer2[i*k]; + buffer[i+1] = buffer2[i*k+1]; // convert the data from float to u16 assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f); + assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f); oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1)); + oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1)); } first_mix = false; } else { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) { - buffer[i] = (buffer[i] + buffer2[i]) * 0.5; // TODO: valid mixing + buffer[i] = (buffer[i] + buffer2[i*k]) * 0.5; // TODO: valid mixing + buffer[i+1] = (buffer[i+1] + buffer2[i*k+1]) * 0.5; // convert the data from float to u16 assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f); + assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f); oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1)); + oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1)); } } } @@ -176,8 +184,6 @@ int cellAudioInit() ConLog.Error("Port aborted: cannot write file!"); goto abort; } - - m_dump.UpdateHeader(sizeof(buffer)); } } ConLog.Write("Audio finished"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index bc09f6777b..2fac7e0bae 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x3000000; // 0x45fa49 from ps3 + attr->memSize = 0x500000; // 0x45fa49 from ps3 else - attr->memSize = 0x200000; // 0x73d9 from ps3 + attr->memSize = 0x8000; // 0x73d9 from ps3 cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); @@ -131,7 +131,7 @@ u32 dmuxOpen(Demuxer* data) } // read additional header: - stream.peek(ch); + stream.peek(ch); // ??? //stream.skip(4); //pes.size += 4; @@ -148,26 +148,18 @@ u32 dmuxOpen(Demuxer* data) Sleep(1); } - /*if (es.hasunseen()) // hack, probably useless + if (es.hasunseen()) // hack, probably useless { stream = backup; continue; - }*/ - - //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + } stream.skip(4); len -= 4; - u32 abc; - stream.peek(abc); - if (abc == 0x5548D00F) - { - stream.skip(8); - len -= 8; - } es.push(stream, len - pes.size - 3, pes); es.finish(stream); + //ConLog.Write("*** AT3+ AU sent (len=0x%x, pts=0x%llx)", len - pes.size - 3, pes.pts); mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; @@ -211,13 +203,18 @@ u32 dmuxOpen(Demuxer* data) stream.get(len); PesHeader pes(stream); + if (es.freespace() < (u32)(len + 6)) + { + pes.new_au = true; + } + if (pes.new_au && es.hasdata()) // new AU detected { - /*if (es.hasunseen()) // hack, probably useless + if (es.hasunseen()) // hack, probably useless { stream = backup; continue; - }*/ + } es.finish(stream); // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); @@ -298,8 +295,9 @@ u32 dmuxOpen(Demuxer* data) { case dmuxSetStream: { - if (stream.discontinuity) + if (task.stream.discontinuity) { + ConLog.Warning("dmuxSetStream (beginning)"); for (u32 i = 0; i < 192; i++) { if (esALL[i]) @@ -319,8 +317,8 @@ u32 dmuxOpen(Demuxer* data) updates_count++; stream = task.stream; - ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", - stream.addr, stream.size, stream.discontinuity, stream.userdata); + //ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", + //stream.addr, stream.size, stream.discontinuity, stream.userdata); dmux.is_running = true; dmux.fbSetStream.Push(task.stream.addr); // feedback @@ -652,7 +650,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize int cellDmuxResetStream(u32 demuxerHandle) { - cellDmux.Log("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle); + cellDmux.Warning("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle); Demuxer* dmux; if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux)) @@ -667,7 +665,7 @@ int cellDmuxResetStream(u32 demuxerHandle) int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle) { - cellDmux.Log("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle); + cellDmux.Warning("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle); Demuxer* dmux; if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux)) @@ -947,9 +945,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ int cellDmuxReleaseAu(u32 esHandle) { - cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle); - - return CELL_OK; + cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); ElementaryStream* es; if (!Emu.GetIdManager().GetIDData(esHandle, es)) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index ce55c27eb5..f138d56db6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -483,23 +483,29 @@ class ElementaryStream { SMutex mutex; - u32 first_addr; // AU that will be released - u32 last_addr; // AU that is being written now - u32 last_size; // number of bytes written (after 128b header) - u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) + SQueue entries; // AU starting addresses + u32 put_count; // number of AU written + u32 released; // number of AU released + u32 peek_count; // number of AU obtained by GetAu(Ex) + + u32 put; // AU that is being written now + u32 size; // number of bytes written (after 128b header) + //u32 first; // AU that will be released + //u32 peek; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) bool is_full() { - if (first_addr) + if (released < put_count) { - if (first_addr >= last_addr) + u32 first = entries.Peek(); + if (first >= put) { - return (first_addr - last_addr) <= GetMaxAU(); + return (first - put) < GetMaxAU(); } else { // probably, always false - return (last_addr + GetMaxAU()) > (memAddr + memSize); + return (put + GetMaxAU()) > (memAddr + memSize); } } else @@ -532,26 +538,42 @@ public: , cbFunc(cbFunc) , cbArg(cbArg) , spec(spec) - , first_addr(0) - , peek_addr(0) - , last_addr(memAddr) - , last_size(0) + //, first(0) + //, peek(0) + , put(memAddr) + , size(0) + , put_count(0) + , released(0) + , peek_count(0) { } const u32 GetMaxAU() const { - return 640 * 1024 + 128; + return (fidMajor == 0xbd) ? 4096 : 640 * 1024 + 128; // TODO } - volatile bool hasunseen() + u32 freespace() { - return peek_addr; + if (size > GetMaxAU()) + { + ConLog.Error("es::freespace(): last_size too big (size=0x%x, max_au=0x%x)", size, GetMaxAU()); + Emu.Pause(); + return 0; + } + return GetMaxAU() - size; } - volatile bool hasdata() + bool hasunseen() { - return last_size; + SMutexLocker lock(mutex); + return peek_count < put_count; + } + + bool hasdata() + { + SMutexLocker lock(mutex); + return size; } bool isfull() @@ -562,54 +584,70 @@ public: void finish(DemuxerStream& stream) // not multithread-safe { - SMutexLocker lock(mutex); - //ConLog.Write("es::finish(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - if (!first_addr) + u32 addr; { - first_addr = last_addr; - } - if (!peek_addr) - { - peek_addr = last_addr; - } + SMutexLocker lock(mutex); + //if (fidMajor != 0xbd) ConLog.Write(">>> es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); - u32 new_addr = a128(last_addr + 128 + last_size); - if ((new_addr + GetMaxAU()) > (memAddr + memSize)) - { - last_addr = memAddr; + addr = put; + /*if (!first) + { + first = put; + } + if (!peek) + { + peek = put; + }*/ + + mem_ptr_t info(put); + //if (fidMajor != 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x", + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), + //(u32)info->auSize, put, (u32)info->ptsLower); + + u32 new_addr = a128(put + 128 + size); + if ((new_addr + GetMaxAU()) > (memAddr + memSize)) + { + put = memAddr; + } + else + { + put = new_addr; + } + size = 0; + + put_count++; + //if (fidMajor != 0xbd) ConLog.Write("<<< es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); } - else + if (!entries.Push(addr)) { - last_addr = new_addr; + ConLog.Error("es::finish() aborted (no space)"); } - last_size = 0; } - void push(DemuxerStream& stream, u32 size, PesHeader& pes) + void push(DemuxerStream& stream, u32 sz, PesHeader& pes) { SMutexLocker lock(mutex); - //ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); if (is_full()) { - ConLog.Error("ElementaryStream::push(): buffer is full"); + ConLog.Error("es::push(): buffer is full"); Emu.Pause(); return; } - u32 data_addr = last_addr + 128 + last_size; - last_size += size; - if (!Memory.Copy(data_addr, stream.addr, size)) + u32 data_addr = put + 128 + size; + size += sz; + if (!Memory.Copy(data_addr, stream.addr, sz)) { - ConLog.Error("ElementaryStream::push(): data copying failed"); + ConLog.Error("es::push(): data copying failed"); Emu.Pause(); return; } - stream.skip(size); + stream.skip(sz); - mem_ptr_t info(last_addr); - info->auAddr = last_addr + 128; - info->auSize = last_size; + mem_ptr_t info(put); + info->auAddr = put + 128; + info->auSize = size; if (pes.new_au) { info->dts.lower = (u32)pes.dts; @@ -621,12 +659,12 @@ public: info->userData = stream.userdata; } - mem_ptr_t tail(last_addr + sizeof(CellDmuxAuInfoEx)); + mem_ptr_t tail(put + sizeof(CellDmuxAuInfoEx)); tail->reserved1 = 0; - mem_ptr_t inf(last_addr + 64); - inf->auAddr = last_addr + 128; - inf->auSize = last_size; + mem_ptr_t inf(put + 64); + inf->auAddr = put + 128; + inf->auSize = size; if (pes.new_au) { inf->dtsLower = (u32)pes.dts; @@ -641,76 +679,107 @@ public: bool release() { SMutexLocker lock(mutex); - //ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - if (!first_addr) + //if (fidMajor != 0xbd) ConLog.Write(">>> es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); + if (released >= put_count) { - ConLog.Error("ElementaryStream::release(): buffer is empty"); + ConLog.Error("es::release(): buffer is empty"); return false; } - u32 size = a128(Memory.Read32(first_addr + 4) + 128); - u32 new_addr = first_addr + size; + u32 addr = entries.Peek(); - if (peek_addr == first_addr) + mem_ptr_t info(addr); + //if (fidMajor != 0xbd) ConLog.Warning("es::release(): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, first, (u32)info->ptsLower); + + if (released >= peek_count) { - ConLog.Error("ElementaryStream::release(): buffer has not been seen yet"); + ConLog.Error("es::release(): buffer has not been seen yet"); return false; } - //if (peek_addr <= first_addr) peek_addr = new_addr; - if (new_addr == last_addr) + /*u32 new_addr = a128(info.GetAddr() + 128 + info->auSize); + + if (new_addr == put) { - first_addr = 0; + first = 0; } else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { - first_addr = memAddr; + first = memAddr; } else { - first_addr = new_addr; - } + first = new_addr; + }*/ + released++; + if (!entries.Pop(addr)) + { + ConLog.Error("es::release(): entries.Pop() aborted (no entries found)"); + return false; + } + //if (fidMajor != 0xbd) ConLog.Write("<<< es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); return true; } bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index) { SMutexLocker lock(mutex); - /*ConLog.Write("es::peek(%sAu%s): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), - wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/ - if (!peek_addr) return false; + //if (fidMajor != 0xbd) ConLog.Write(">>> es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size); + if (peek_count >= put_count) return false; - out_data = peek_addr; + if (peek_count < released) + { + ConLog.Error("es::peek(): sequence error: peek_count < released (peek_count=%d, released=%d)", peek_count, released); + Emu.Pause(); + return false; + } + + u32 addr = entries.Peek(peek_count - released); + mem_ptr_t info(addr); + //if (fidMajor != 0xbd) ConLog.Warning("es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", + //wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek, (u32)info->ptsLower); + + out_data = addr; out_spec = out_data + sizeof(CellDmuxAuInfoEx); if (no_ex) out_data += 64; if (update_index) { - u32 size = a128(Memory.Read32(peek_addr + 4) + 128); - u32 new_addr = peek_addr + size; - if (new_addr = last_addr) + /*u32 new_addr = a128(peek + 128 + info->auSize); + if (new_addr = put) { - peek_addr = 0; + peek = 0; } else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { - peek_addr = memAddr; + peek = memAddr; } else { - peek_addr = new_addr; - } + peek = new_addr; + }*/ + peek_count++; } + + //if (fidMajor != 0xbd) ConLog.Write("<<< es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size); return true; } void reset() { SMutexLocker lock(mutex); - first_addr = 0; - peek_addr = 0; - last_addr = memAddr; - last_size = 0; + //first = 0; + //peek = 0; + put = memAddr; + size = 0; + entries.Clear(); + put_count = 0; + released = 0; + peek_count = 0; } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 6133a6b111..877075b86f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -37,6 +37,7 @@ uint32_t cellGcmGetMaxIoMapSize(); void cellGcmGetOffsetTable(mem_ptr_t table); int32_t cellGcmIoOffsetToAddress(u32 ioOffset, u64 address); int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size); +int32_t cellGcmMapEaIoAddressWithFlags(const u32 ea, const u32 io, const u32 size, const u32 flags); int32_t cellGcmMapMainMemory(u64 ea, u32 size, mem32_t offset); int32_t cellGcmReserveIoMapSize(const u32 size); int32_t cellGcmUnmapEaIoAddress(u64 ea); @@ -68,6 +69,14 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size); + InitOffsetTable(); + Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase + if(cellGcmMapEaIoAddress(ioAddress, 0, ioSize) != CELL_OK) + { + Memory.MemoryBlocks.pop_back(); + return CELL_GCM_ERROR_FAILURE; + } + map_offset_addr = 0; map_offset_pos = 0; current_config.ioSize = ioSize; @@ -77,10 +86,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) current_config.memoryFrequency = 650000000; current_config.coreFrequency = 500000000; - InitOffsetTable(); Memory.RSXCMDMem.AllocAlign(cmdSize); - Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0x50000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase - cellGcmMapEaIoAddress(ioAddress, 0, ioSize); u32 ctx_begin = ioAddress/* + 0x1000*/; u32 ctx_size = 0x6ffc; @@ -677,6 +683,12 @@ int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) return CELL_OK; } +int32_t cellGcmMapEaIoAddressWithFlags(const u32 ea, const u32 io, const u32 size, const u32 flags) +{ + cellGcmSys.Warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags); + return cellGcmMapEaIoAddress(ea, io, size); // TODO: strict ordering +} + int32_t cellGcmMapLocalMemory(u64 address, u64 size) { if(!local_size && !local_addr) @@ -855,6 +867,7 @@ void cellGcmSys_init() cellGcmSys.AddFunc(0x2922aed0, cellGcmGetOffsetTable); cellGcmSys.AddFunc(0x2a6fba9c, cellGcmIoOffsetToAddress); cellGcmSys.AddFunc(0x63441cb4, cellGcmMapEaIoAddress); + cellGcmSys.AddFunc(0x626e8518, cellGcmMapEaIoAddressWithFlags); cellGcmSys.AddFunc(0xdb769b32, cellGcmMapLocalMemory); cellGcmSys.AddFunc(0xa114ec67, cellGcmMapMainMemory); cellGcmSys.AddFunc(0xa7ede268, cellGcmReserveIoMapSize); diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp index 7745ed224d..b783b58727 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp @@ -19,6 +19,19 @@ enum ConverterUnknown, }; +// detection result +enum +{ + L10N_STR_UNKNOWN = (1 << 0), + L10N_STR_ASCII = (1 << 1), + L10N_STR_JIS = (1 << 2), + L10N_STR_EUCJP = (1 << 3), + L10N_STR_SJIS = (1 << 4), + L10N_STR_UTF8 = (1 << 5), + L10N_STR_ILLEGAL = (1 << 16), + L10N_STR_ERROR = (1 << 17), +}; + int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) { cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", @@ -43,6 +56,13 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t return ConversionOK; } +int jstrchk(mem8_ptr_t jstr) +{ + cellL10n.Log("jstrchk(jstr_addr=0x%x [%s])", jstr.GetAddr(), "omitted" /*Memory.ReadString(jstr.GetAddr()).wx_str()*/); + + return L10N_STR_UTF8; +} + void cellL10n_init() { // NOTE: I think this module should be LLE'd instead of implementing all its functions @@ -132,7 +152,7 @@ void cellL10n_init() // cellL10n.AddFunc(0x73f2cd21, SJISstoJISs); // cellL10n.AddFunc(0x74496718, SBCStoUTF8); // cellL10n.AddFunc(0x74871fe0, UTF8toUTF32); - // cellL10n.AddFunc(0x750c363d, jstrchk); + cellL10n.AddFunc(0x750c363d, jstrchk); // cellL10n.AddFunc(0x7c5bde1c, UHCtoEUCKR); // cellL10n.AddFunc(0x7c912bda, kuten2jis); // cellL10n.AddFunc(0x7d07a1c2, UTF8toEUCCN); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 5ea762662f..1e49e653d5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -66,9 +66,10 @@ next: vdec.reader.addr = vdec.task.addr; vdec.reader.size = vdec.task.size; + //ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", vdec.task.size, vdec.task.pts, vdec.task.dts); - vdec.last_pts = vdec.task.pts; - vdec.last_dts = vdec.task.dts; + //if (vdec.last_pts > vdec.task.pts) vdec.last_pts = vdec.task.pts; + //if (vdec.last_dts > vdec.task.dts) vdec.last_dts = vdec.task.dts; } break; default: @@ -205,9 +206,15 @@ u32 vdecOpen(VideoDecoder* data) vdec.reader.addr = task.addr; vdec.reader.size = task.size; + //ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts); - vdec.last_pts = task.pts; - vdec.last_dts = task.dts; + //if (vdec.last_pts > task.pts || vdec.just_started) vdec.last_pts = task.pts; + //if (vdec.last_dts > task.dts || vdec.just_started) vdec.last_dts = task.dts; + if (vdec.just_started) + { + vdec.last_pts = task.pts; + vdec.last_dts = task.dts; + } struct AVPacketHolder : AVPacket { @@ -350,11 +357,12 @@ u32 vdecOpen(VideoDecoder* data) if (got_picture) { - //ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts); - frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration??? frame.pts = vdec.last_pts; vdec.last_pts += 3003; frame.userdata = task.userData; + + //ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts); + vdec.frames.Push(frame); // !!!!!!!! frame.data = nullptr; // to prevent destruction diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 92ead9c6a4..31faab3f8d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -1,6 +1,12 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" + +extern "C" +{ +#include "libswscale/swscale.h" +} + #include "cellVpost.h" void cellVpost_init(); @@ -93,13 +99,15 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinWidth; u32 h = ctrlParam->inHeight; + u32 ow = ctrlParam->outWidth; + u32 oh = ctrlParam->outHeight; if (!Memory.IsGoodAddr(inPicBuff_addr, w*h*3/2)) { return CELL_VPOST_ERROR_E_ARG_INPICBUF_INVALID; } - if (!Memory.IsGoodAddr(outPicBuff_addr, w*h*4)) + if (!Memory.IsGoodAddr(outPicBuff_addr, ow*oh*4)) { return CELL_VPOST_ERROR_E_ARG_OUTPICBUF_INVALID; } @@ -110,13 +118,21 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinWindow; // ignored + if (ctrlParam->inWindow.x) ConLog.Warning("*** inWindow.x = %d", (u32)ctrlParam->inWindow.x); + if (ctrlParam->inWindow.y) ConLog.Warning("*** inWindow.y = %d", (u32)ctrlParam->inWindow.y); + if (ctrlParam->inWindow.width != w) ConLog.Warning("*** inWindow.width = %d", (u32)ctrlParam->inWindow.width); + if (ctrlParam->inWindow.height != h) ConLog.Warning("*** inWindow.height = %d", (u32)ctrlParam->inWindow.height); ctrlParam->outWindow; // ignored + if (ctrlParam->outWindow.x) ConLog.Warning("*** outWindow.x = %d", (u32)ctrlParam->outWindow.x); + if (ctrlParam->outWindow.y) ConLog.Warning("*** outWindow.y = %d", (u32)ctrlParam->outWindow.y); + if (ctrlParam->outWindow.width != ow) ConLog.Warning("*** outWindow.width = %d", (u32)ctrlParam->outWindow.width); + if (ctrlParam->outWindow.height != oh) ConLog.Warning("*** outWindow.height = %d", (u32)ctrlParam->outWindow.height); ctrlParam->execType; // ignored ctrlParam->scalerType; // ignored ctrlParam->ipcType; // ignored - picInfo->inWidth = ctrlParam->inWidth; // copy - picInfo->inHeight = ctrlParam->inHeight; // copy + picInfo->inWidth = w; // copy + picInfo->inHeight = h; // copy picInfo->inDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->inScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->inPicFmt = CELL_VPOST_PIC_FMT_IN_YUV420_PLANAR; // fixed @@ -125,24 +141,25 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinQuantRange = ctrlParam->inQuantRange; // copy picInfo->inColorMatrix = ctrlParam->inColorMatrix; // copy - picInfo->outWidth = picInfo->inWidth; // TODO (resampling) - picInfo->outHeight = picInfo->inHeight; // TODO + picInfo->outWidth = ow; // copy + picInfo->outHeight = oh; // copy picInfo->outDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->outScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->outPicFmt = CELL_VPOST_PIC_FMT_OUT_RGBA_ILV; // TODO - picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ??? - picInfo->outPicStruct = picInfo->inPicStruct; // ??? - picInfo->outQuantRange = ctrlParam->inQuantRange; // ??? - picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ??? + picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ignored + picInfo->outPicStruct = picInfo->inPicStruct; // ignored + picInfo->outQuantRange = ctrlParam->inQuantRange; // ignored + picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ignored picInfo->userData = ctrlParam->userData; // copy picInfo->reserved1 = 0; picInfo->reserved2 = 0; - + u8* pY = (u8*)malloc(w*h); // color planes u8* pU = (u8*)malloc(w*h/4); u8* pV = (u8*)malloc(w*h/4); - u32* res = (u32*)malloc(w*h*4); // RGBA interleaved output + u8* pA = (u8*)malloc(w*h); + u32* res = (u32*)malloc(ow*oh*4); // RGBA interleaved output const u8 alpha = ctrlParam->outAlpha; if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h)) @@ -163,6 +180,20 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t 255) B = 255; res[i*w+j] = ((u32)alpha << 24) | (B << 16) | (G << 8) | (R); - } + }*/ - if (!Memory.CopyFromReal(outPicBuff_addr, res, w*h*4)) + if (!Memory.CopyFromReal(outPicBuff_addr, res, ow*oh*4)) { cellVpost.Error("cellVpostExec: data copying failed(result)"); Emu.Pause(); @@ -190,6 +221,7 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const 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_group_join(u32 id, mem32_t cause, mem32_t status); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index cc6a1d7c9d..71d4ac0de9 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -74,7 +74,7 @@ int sys_cond_signal(u32 cond_id) if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) { - cond->cond.lock(target); + cond->signal.lock(target); if (Emu.IsStopped()) { @@ -99,7 +99,7 @@ int sys_cond_signal_all(u32 cond_id) while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop())) { - cond->cond.lock(target); + cond->signal.lock(target); if (Emu.IsStopped()) { @@ -134,7 +134,7 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id) u32 target = thread_id; { - cond->cond.lock(target); + cond->signal.lock(target); } if (Emu.IsStopped()) @@ -160,24 +160,46 @@ int sys_cond_wait(u32 cond_id, u64 timeout) if (mutex->m_mutex.GetOwner() != tid) { + sys_cond.Warning("sys_cond_wait(cond_id=%d) failed (EPERM)", cond_id); return CELL_EPERM; } cond->m_queue.push(tid); + if (mutex->recursive != 1) + { + sys_cond.Warning("sys_cond_wait(cond_id=%d): associated mutex had wrong recursive value (%d)", cond_id, mutex->recursive); + } mutex->recursive = 0; - mutex->m_mutex.unlock(tid); + mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()); u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : ~0; while (true) { - if (cond->cond.GetOwner() == tid) + if (cond->signal.unlock(tid, tid) == SMR_OK) { - mutex->m_mutex.lock(tid); + if (SMutexResult res = mutex->m_mutex.trylock(tid)) + { + if (res != SMR_FAILED) + { + goto abort; + } + mutex->m_queue.push(tid); + + switch (mutex->m_mutex.lock(tid)) + { + case SMR_OK: + mutex->m_queue.invalidate(tid); + case SMR_SIGNAL: + break; + default: + goto abort; + } + } mutex->recursive = 1; - cond->cond.unlock(tid); + cond->signal.unlock(tid); return CELL_OK; } @@ -186,13 +208,16 @@ int sys_cond_wait(u32 cond_id, u64 timeout) if (counter++ > max_counter) { cond->m_queue.invalidate(tid); - GetCurrentPPUThread().owned_mutexes--; + GetCurrentPPUThread().owned_mutexes--; // ??? return CELL_ETIMEDOUT; } if (Emu.IsStopped()) { - ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id); - return CELL_OK; + goto abort; } } + +abort: + ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id); + return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h index 460923a504..a8d7472c63 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h @@ -16,7 +16,7 @@ struct sys_cond_attribute struct Cond { Mutex* mutex; // associated with mutex - SMutex cond; + SMutex signal; SleepQueue m_queue; Cond(Mutex* mutex, u64 name) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp index 4e7bc265af..72ac3ebef6 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.cpp @@ -16,10 +16,10 @@ 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_PRIORITY): 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; + case se32(SYS_SYNC_FIFO): break; default: return CELL_EINVAL; } @@ -30,12 +30,12 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t attr, switch (attr->type.ToBE()) { - case se32(SYS_SYNC_WAITER_SINGLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_SINGLE type"); break; - case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break; + case se32(SYS_SYNC_WAITER_SINGLE): break; + case se32(SYS_SYNC_WAITER_MULTIPLE): break; default: return CELL_EINVAL; } - eflag_id = sys_event_flag.GetNewId(new event_flag(init, (u32)attr->protocol, (int)attr->type)); + eflag_id = sys_event_flag.GetNewId(new EventFlag(init, (u32)attr->protocol, (int)attr->type)); sys_event_flag.Warning("*** event_flag created [%s] (protocol=0x%x, type=0x%x): id = %d", wxString(attr->name, 8).wx_str(), (u32)attr->protocol, (int)attr->type, eflag_id.GetValue()); @@ -47,9 +47,14 @@ int sys_event_flag_destroy(u32 eflag_id) { sys_event_flag.Warning("sys_event_flag_destroy(eflag_id=%d)", eflag_id); - event_flag* ef; + EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + if (ef->waiters.GetCount()) // ??? + { + return CELL_EBUSY; + } + Emu.GetIdManager().RemoveID(eflag_id); return CELL_OK; @@ -57,26 +62,220 @@ int sys_event_flag_destroy(u32 eflag_id) 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=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)", + sys_event_flag.Warning("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; + + if (result.IsGood()) result = 0; + + switch (mode & 0xf) + { + case SYS_EVENT_FLAG_WAIT_AND: break; + case SYS_EVENT_FLAG_WAIT_OR: break; + default: return CELL_EINVAL; + } + + switch (mode & ~0xf) + { + case 0: break; // ??? + case SYS_EVENT_FLAG_WAIT_CLEAR: break; + case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break; + default: return CELL_EINVAL; + } + + EventFlag* ef; + if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + + u32 tid = GetCurrentPPUThread().GetId(); + + { + SMutexLocker lock(ef->m_mutex); + if (ef->m_type == SYS_SYNC_WAITER_SINGLE && ef->waiters.GetCount() > 0) + { + return CELL_EPERM; + } + EventFlagWaiter rec; + rec.bitptn = bitptn; + rec.mode = mode; + rec.tid = tid; + ef->waiters.AddCpy(rec); + + if (ef->check() == tid) + { + u64 flags = ef->flags; + + ef->waiters.RemoveAt(ef->waiters.GetCount() - 1); + + if (mode & SYS_EVENT_FLAG_WAIT_CLEAR) + { + ef->flags &= ~bitptn; + } + else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL) + { + ef->flags = 0; + } + + if (result.IsGood()) + { + result = flags; + return CELL_OK; + } + + if (!result.GetAddr()) + { + return CELL_OK; + } + return CELL_EFAULT; + } + } + + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : ~0; + + while (true) + { + if (ef->signal.GetOwner() == tid) + { + SMutexLocker lock(ef->m_mutex); + + ef->signal.unlock(tid); + + u64 flags = ef->flags; + + for (u32 i = 0; i < ef->waiters.GetCount(); i++) + { + if (ef->waiters[i].tid == tid) + { + ef->waiters.RemoveAt(i); + + if (mode & SYS_EVENT_FLAG_WAIT_CLEAR) + { + ef->flags &= ~bitptn; + } + else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL) + { + ef->flags = 0; + } + + if (result.IsGood()) + { + result = flags; + return CELL_OK; + } + + if (!result.GetAddr()) + { + return CELL_OK; + } + return CELL_EFAULT; + } + } + + return CELL_ECANCELED; + } + + Sleep(1); + + if (counter++ > max_counter) + { + SMutexLocker lock(ef->m_mutex); + + for (u32 i = 0; i < ef->waiters.GetCount(); i++) + { + if (ef->waiters[i].tid == tid) + { + ef->waiters.RemoveAt(i); + break; + } + } + + return CELL_ETIMEDOUT; + } + if (Emu.IsStopped()) + { + ConLog.Warning("sys_event_flag_wait(id=%d) aborted", eflag_id); + 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=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)", + sys_event_flag.Warning("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; + + if (result.IsGood()) result = 0; + + switch (mode & 0xf) + { + case SYS_EVENT_FLAG_WAIT_AND: break; + case SYS_EVENT_FLAG_WAIT_OR: break; + default: return CELL_EINVAL; + } + + switch (mode & ~0xf) + { + case 0: break; // ??? + case SYS_EVENT_FLAG_WAIT_CLEAR: break; + case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break; + default: return CELL_EINVAL; + } + + EventFlag* ef; + if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + + SMutexLocker lock(ef->m_mutex); + + u64 flags = ef->flags; + + if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) || + ((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn))) + { + if (mode & SYS_EVENT_FLAG_WAIT_CLEAR) + { + ef->flags &= ~bitptn; + } + else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL) + { + ef->flags = 0; + } + + if (result.IsGood()) + { + result = flags; + return CELL_OK; + } + + if (!result.GetAddr()) + { + return CELL_OK; + } + return CELL_EFAULT; + } + + return CELL_EBUSY; } int sys_event_flag_set(u32 eflag_id, u64 bitptn) { sys_event_flag.Warning("sys_event_flag_set(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn); - event_flag* ef; + EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + u32 tid = GetCurrentPPUThread().GetId(); + + ef->m_mutex.lock(tid); ef->flags |= bitptn; + if (u32 target = ef->check()) + { + // if signal, leave both mutexes locked... + ef->signal.lock(target); + ef->m_mutex.unlock(tid, target); + } + else + { + ef->m_mutex.unlock(tid); + } return CELL_OK; } @@ -85,9 +284,10 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn) { sys_event_flag.Warning("sys_event_flag_clear(eflag_id=%d, bitptn=0x%llx)", eflag_id, bitptn); - event_flag* ef; + EventFlag* ef; if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + SMutexLocker lock(ef->m_mutex); ef->flags &= bitptn; return CELL_OK; @@ -95,23 +295,61 @@ 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=%d, num_addr=0x%x)", eflag_id, num.GetAddr()); - return CELL_OK; + sys_event_flag.Warning("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr()); + + EventFlag* ef; + if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + + Array tids; + + { + SMutexLocker lock(ef->m_mutex); + tids.SetCount(ef->waiters.GetCount()); + for (u32 i = 0; i < ef->waiters.GetCount(); i++) + { + tids[i] = ef->waiters[i].tid; + } + ef->waiters.Clear(); + } + + for (u32 i = 0; i < tids.GetCount(); i++) + { + if (Emu.IsStopped()) break; + ef->signal.lock(tids[i]); + } + + if (Emu.IsStopped()) + { + ConLog.Warning("sys_event_flag_cancel(id=%d) aborted", eflag_id); + return CELL_OK; + } + + if (num.IsGood()) + { + num = tids.GetCount(); + return CELL_OK; + } + + if (!num.GetAddr()) + { + return CELL_OK; + } + return CELL_EFAULT; } int sys_event_flag_get(u32 eflag_id, mem64_t flags) { sys_event_flag.Warning("sys_event_flag_get(eflag_id=%d, flags_addr=0x%x)", eflag_id, flags.GetAddr()); + EventFlag* ef; + if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; + if (!flags.IsGood()) { return CELL_EFAULT; } - - event_flag* ef; - if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH; - flags = ef->flags; + flags = ef->flags; // ??? return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h index 80983e6a6d..97209f335a 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event_flag.h @@ -4,6 +4,12 @@ enum { SYS_SYNC_WAITER_SINGLE = 0x10000, SYS_SYNC_WAITER_MULTIPLE = 0x20000, + + SYS_EVENT_FLAG_WAIT_AND = 0x01, + SYS_EVENT_FLAG_WAIT_OR = 0x02, + + SYS_EVENT_FLAG_WAIT_CLEAR = 0x10, + SYS_EVENT_FLAG_WAIT_CLEAR_ALL = 0x20, }; struct sys_event_flag_attr @@ -16,16 +22,54 @@ struct sys_event_flag_attr char name[8]; }; -struct event_flag +struct EventFlagWaiter { - std::atomic flags; + u32 tid; + u32 mode; + u64 bitptn; +}; + +struct EventFlag +{ + SMutex m_mutex; + u64 flags; + Array waiters; + SMutex signal; const u32 m_protocol; const int m_type; - event_flag(u64 pattern, u32 protocol, int type) + EventFlag(u64 pattern, u32 protocol, int type) : flags(pattern) , m_protocol(protocol) , m_type(type) { } + + u32 check() + { + SleepQueue sq; // TODO: implement without SleepQueue + + u32 target = 0; + + for (u32 i = 0; i < waiters.GetCount(); i++) + { + if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & waiters[i].bitptn) == waiters[i].bitptn) || + ((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & waiters[i].bitptn))) + { + if (m_protocol == SYS_SYNC_FIFO) + { + target = waiters[i].tid; + break; + } + sq.list.AddCpy(waiters[i].tid); + } + } + + if (m_protocol == SYS_SYNC_PRIORITY) + { + target = sq.pop_prio(); + } + + return target; + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp index 2b02cd1276..1a359c5ed8 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp @@ -16,7 +16,7 @@ int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t l } lwcond->lwmutex = lwmutex.GetAddr(); - lwcond->lwcond_queue = sys_lwcond.GetNewId(new SleepQueue(attr->name_u64)); + lwcond->lwcond_queue = sys_lwcond.GetNewId(new Lwcond(attr->name_u64)); if (lwmutex.IsGood()) { @@ -49,20 +49,20 @@ int sys_lwcond_destroy(mem_ptr_t lwcond) return CELL_EFAULT; } - u32 lwc = lwcond->lwcond_queue; + u32 id = lwcond->lwcond_queue; - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(lwc, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData(id, lw)) { return CELL_ESRCH; } - if (!sq->finalize()) + if (!lw->m_queue.finalize()) { return CELL_EBUSY; } - Emu.GetIdManager().RemoveID(lwc); + Emu.GetIdManager().RemoveID(id); return CELL_OK; } @@ -75,37 +75,23 @@ int sys_lwcond_signal(mem_ptr_t lwcond) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - bool was_locked = (mutex->mutex.GetOwner() == tid); - - if (be_t target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())) + if (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal(sq=%d) aborted", (u32)lwcond->lwcond_queue); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; + } } return CELL_OK; @@ -120,37 +106,23 @@ int sys_lwcond_signal_all(mem_ptr_t lwcond) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - bool was_locked = (mutex->mutex.GetOwner() == tid); - - while (be_t target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())) + while (u32 target = (mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? lw->m_queue.pop_prio() : lw->m_queue.pop())) { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal_all(sq=%d) aborted", (u32)lwcond->lwcond_queue); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal_all(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; + } } return CELL_OK; @@ -165,8 +137,8 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } @@ -176,36 +148,20 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) return CELL_ESRCH; } - if (!sq->invalidate(ppu_thread_id)) + if (!lw->m_queue.invalidate(ppu_thread_id)) { return CELL_EPERM; } - mem_ptr_t mutex(lwcond->lwmutex); - be_t tid = GetCurrentPPUThread().GetId(); - - bool was_locked = (mutex->mutex.GetOwner() == tid); - - be_t target = ppu_thread_id; + u32 target = ppu_thread_id; { - if (!was_locked) - { - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - } - else - { - mutex->recursive_count = 1; - mutex->mutex.unlock(tid, target); - mutex->mutex.lock(tid); - mutex->recursive_count = 1; - } - } + lw->signal.lock(target); - if (Emu.IsStopped()) - { - ConLog.Warning("sys_lwcond_signal_to(sq=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_lwcond_signal_to(id=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id); + return CELL_OK; + } } return CELL_OK; @@ -220,8 +176,8 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) return CELL_EFAULT; } - SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq)) + Lwcond* lw; + if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, lw)) { return CELL_ESRCH; } @@ -230,29 +186,57 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) u32 tid_le = GetCurrentPPUThread().GetId(); be_t tid = tid_le; + SleepQueue* sq = nullptr; + Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq); + if (mutex->mutex.GetOwner() != tid) { + sys_lwcond.Warning("sys_lwcond_wait(id=%d) failed (EPERM)", (u32)lwcond->lwcond_queue); return CELL_EPERM; // caller must own this lwmutex } - sq->push(tid_le); + lw->m_queue.push(tid_le); + if (mutex->recursive_count.ToBE() != se32(1)) + { + sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had wrong recursive value (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->recursive_count); + } mutex->recursive_count = 0; - mutex->mutex.unlock(tid); + + if (sq) + { + mutex->mutex.unlock(tid, mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop()); + } + else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY)) + { + mutex->mutex.unlock(tid); // SYS_SYNC_RETRY + } + else + { + sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); + } u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : ~0; + while (true) { - /* switch (mutex->trylock(tid)) + if (lw->signal.unlock(tid, tid) == SMR_OK) { - case SMR_OK: mutex->unlock(tid); break; - case SMR_SIGNAL: return CELL_OK; - } */ - if (mutex->mutex.GetOwner() == tid) - { - _mm_mfence(); + switch (mutex->lock(tid, 0)) + { + case CELL_OK: break; + case CELL_EDEADLK: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex was locked", + (u32)lwcond->lwcond_queue); return CELL_OK; + case CELL_ESRCH: sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex not found (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); return CELL_ESRCH; + case CELL_EINVAL: goto abort; + } + mutex->recursive_count = 1; + lw->signal.unlock(tid); return CELL_OK; } @@ -260,13 +244,16 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) if (counter++ > max_counter) { - sq->invalidate(tid_le); + lw->m_queue.invalidate(tid_le); return CELL_ETIMEDOUT; } if (Emu.IsStopped()) { - ConLog.Warning("sys_lwcond_wait(sq=%d) aborted", (u32)lwcond->lwcond_queue); - return CELL_OK; + goto abort; } } + +abort: + ConLog.Warning("sys_lwcond_wait(id=%d) aborted", (u32)lwcond->lwcond_queue); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h index f7d8369c13..16e92548e6 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h @@ -13,4 +13,15 @@ struct sys_lwcond_t { be_t lwmutex; be_t lwcond_queue; +}; + +struct Lwcond +{ + SMutex signal; + SleepQueue m_queue; + + Lwcond(u64 name) + : m_queue(name) + { + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index ab987cb8cd..31fedbd349 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -177,7 +177,7 @@ bool SleepQueue::invalidate(u32 tid) { if (list[i] = tid) { - list[i] = 0; + list.RemoveAt(i); return true; } } @@ -206,10 +206,11 @@ int sys_lwmutex_t::trylock(be_t tid) { if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL; - be_t owner_tid = mutex.GetOwner(); + be_t owner_tid = mutex.GetFreeValue(); - if (owner_tid != mutex.GetFreeValue()) + if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value { + owner_tid = mutex.GetOwner(); if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid)) { if (!tt->IsAlive()) @@ -263,7 +264,7 @@ int sys_lwmutex_t::trylock(be_t tid) int sys_lwmutex_t::unlock(be_t tid) { - if (tid != mutex.GetOwner()) + if (mutex.unlock(tid, tid) != SMR_OK) { return CELL_EPERM; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index d0d2b3f962..e09bc1874e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -63,7 +63,7 @@ int sys_mutex_destroy(u32 mutex_id) return CELL_ESRCH; } - if ((u32&)mutex->cond_count) // check if associated condition variable exists + if (mutex->cond_count) // check if associated condition variable exists { return CELL_EPERM; } @@ -99,9 +99,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - u32 owner = mutex->m_mutex.GetOwner(); - if (owner == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (mutex->is_recursive) { @@ -116,7 +114,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) return CELL_EDEADLK; } } - else if (owner) + else if (u32 owner = mutex->m_mutex.GetOwner()) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { @@ -170,9 +168,7 @@ int sys_mutex_trylock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - u32 owner = mutex->m_mutex.GetOwner(); - if (owner == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (mutex->is_recursive) { @@ -187,7 +183,7 @@ int sys_mutex_trylock(u32 mutex_id) return CELL_EDEADLK; } } - else if (owner) + else if (u32 owner = mutex->m_mutex.GetOwner()) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { @@ -219,8 +215,7 @@ int sys_mutex_unlock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - if (mutex->m_mutex.GetOwner() == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index 30c31bea17..5cf8fa52bd 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -158,6 +158,9 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 new_thread.SetStackSize(stacksize); //new_thread.flags = flags; new_thread.SetName(Memory.ReadString(threadname_addr).ToStdString()); + + ConLog.Write("*** New PPU Thread [%s] (): id = %d", wxString(new_thread.GetName()).wx_str(), new_thread.GetId()); + new_thread.Run(); new_thread.Exec(); @@ -177,7 +180,7 @@ void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry) new_thread.Run(); new_thread.Exec(); - GetCurrentPPUThread().Wait(new_thread); + //GetCurrentPPUThread().Wait(new_thread); } } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 170343883c..1c66afe102 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -83,9 +83,12 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< return CELL_EFAULT; } - if(!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) + if (attr->name_addr) { - return CELL_EFAULT; + if(!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) + { + return CELL_EFAULT; + } } if(spu_num >= group_info->list.GetCount()) @@ -99,7 +102,13 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< } u32 spu_ep = (u32)img->entry_point; - std::string name = Memory.ReadString(attr->name_addr, attr->name_len).ToStdString(); + + std::string name = "SPUThread"; + if (attr->name_addr) + { + name = Memory.ReadString(attr->name_addr, attr->name_len).ToStdString(); + } + u64 a1 = arg->arg1; u64 a2 = arg->arg2; u64 a3 = arg->arg3; @@ -120,9 +129,10 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< new_thread.Run(); thread = group_info->list[spu_num] = new_thread.GetId(); + (*(SPUThread*)&new_thread).group = group_info; sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", - wxString(name).wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue()); + wxString(attr->name_addr ? name : "").wx_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue()); return CELL_OK; } @@ -216,6 +226,8 @@ int sys_spu_thread_group_start(u32 id) return CELL_ESRCH; } + // TODO: check group state + for (u32 i = 0; i < group_info->list.GetCount(); i++) { CPUThread* t; @@ -239,7 +251,8 @@ int sys_spu_thread_group_suspend(u32 id) return CELL_ESRCH; } - //Emu.Pause(); + // TODO: check group state + for (u32 i = 0; i < group_info->list.GetCount(); i++) { if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) @@ -251,6 +264,30 @@ int sys_spu_thread_group_suspend(u32 id) return CELL_OK; } +//175 +int sys_spu_thread_group_resume(u32 id) +{ + sc_spu.Log("sys_spu_thread_group_resume(id=%d)", id); + + SpuGroupInfo* group_info; + if(!Emu.GetIdManager().GetIDData(id, group_info)) + { + return CELL_ESRCH; + } + + // TODO: check group state + + for (u32 i = 0; i < group_info->list.GetCount(); i++) + { + if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) + { + t->Resume(); + } + } + + return CELL_OK; +} + //170 int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t attr) { @@ -500,14 +537,7 @@ int sys_spu_thread_write_snr(u32 id, u32 number, u32 value) return CELL_EINVAL; } - if ((*(SPUThread*)thr).cfg.value & ((u64)1< lock) { sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr()); +again: switch (lock->mutex.unlock(lock->mutex.GetOwner())) { + case SMR_PERMITTED: goto again; default: break; } } \ No newline at end of file diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 9e73da3995..7c92cb7e3d 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -141,7 +141,7 @@ void Emulator::Load() m_path = elf_path; } - ConLog.Write("Loading '%s'...", m_path.ToStdString().c_str()); + ConLog.Write("Loading '%s'...", m_path.wx_str()); GetInfo().Reset(); m_vfs.Init(m_path); @@ -149,7 +149,7 @@ void Emulator::Load() ConLog.Write("Mount info:"); for(uint i=0; i %s", m_vfs.m_devices[i].GetPs3Path().ToStdString().c_str(), m_vfs.m_devices[i].GetLocalPath().ToStdString().c_str()); + ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().wx_str(), m_vfs.m_devices[i].GetLocalPath().wx_str()); } ConLog.SkipLn(); @@ -162,7 +162,7 @@ void Emulator::Load() if(!f.IsOpened()) { - ConLog.Error("Elf not found! (%s - %s)", m_path.ToStdString().c_str(), m_elf_path.ToStdString().c_str()); + ConLog.Error("Elf not found! (%s - %s)", m_path.wx_str(), m_elf_path.wx_str()); return; } @@ -441,7 +441,7 @@ void Emulator::LoadPoints(const std::string& path) if(version != bpdb_version || (sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != length) { - ConLog.Error("'%s' is broken", path.c_str()); + ConLog.Error("'%s' is broken", wxString(path).wx_str()); return; } diff --git a/rpcs3/Gui/ConLog.cpp b/rpcs3/Gui/ConLog.cpp index e284983695..4895d74113 100644 --- a/rpcs3/Gui/ConLog.cpp +++ b/rpcs3/Gui/ConLog.cpp @@ -14,18 +14,18 @@ std::mutex g_cs_conlog; static const uint max_item_count = 500; static const uint buffer_size = 1024 * 64; -static const std::string g_log_colors[] = +static const wxString g_log_colors[] = { "Black", "Green", "White", "Yellow", "Red", }; struct LogPacket { - std::string m_prefix; - std::string m_text; - std::string m_colour; + wxString m_prefix; + wxString m_text; + wxString m_colour; - LogPacket(const std::string& prefix, const std::string& text, const std::string& colour) + LogPacket(const wxString& prefix, const wxString& text, const wxString& colour) : m_prefix(prefix) , m_text(text) , m_colour(colour) @@ -46,9 +46,9 @@ struct _LogBuffer : public MTPacketBuffer void _push(const LogPacket& data) { - const u32 sprefix = data.m_prefix.length(); - const u32 stext = data.m_text.length(); - const u32 scolour = data.m_colour.length(); + const u32 sprefix = data.m_prefix.length() * sizeof(wxChar); + const u32 stext = data.m_text.length() * sizeof(wxChar); + const u32 scolour = data.m_colour.length() * sizeof(wxChar); m_buffer.Reserve( sizeof(u32) + sprefix + @@ -59,17 +59,17 @@ struct _LogBuffer : public MTPacketBuffer memcpy(&m_buffer[c_put], &sprefix, sizeof(u32)); c_put += sizeof(u32); - memcpy(&m_buffer[c_put], data.m_prefix.c_str(), sprefix); + memcpy(&m_buffer[c_put], data.m_prefix.wx_str(), sprefix); c_put += sprefix; memcpy(&m_buffer[c_put], &stext, sizeof(u32)); c_put += sizeof(u32); - memcpy(&m_buffer[c_put], data.m_text.c_str(), stext); + memcpy(&m_buffer[c_put], data.m_text.wx_str(), stext); c_put += stext; memcpy(&m_buffer[c_put], &scolour, sizeof(u32)); c_put += sizeof(u32); - memcpy(&m_buffer[c_put], data.m_colour.c_str(), scolour); + memcpy(&m_buffer[c_put], data.m_colour.wx_str(), scolour); c_put += scolour; m_put = c_put; @@ -84,20 +84,17 @@ struct _LogBuffer : public MTPacketBuffer const u32& sprefix = *(u32*)&m_buffer[c_get]; c_get += sizeof(u32); - ret.m_prefix.resize(sprefix); - if(sprefix) memcpy((void*)ret.m_prefix.c_str(), &m_buffer[c_get], sprefix); + ret.m_prefix = wxString((wxChar*)&m_buffer[c_get], sprefix / sizeof(wxChar)); c_get += sprefix; const u32& stext = *(u32*)&m_buffer[c_get]; c_get += sizeof(u32); - ret.m_text.resize(stext); - if(stext) memcpy((void*)ret.m_text.c_str(), &m_buffer[c_get], stext); + ret.m_text = wxString((wxChar*)&m_buffer[c_get], stext / sizeof(wxChar)); c_get += stext; const u32& scolour = *(u32*)&m_buffer[c_get]; c_get += sizeof(u32); - ret.m_colour.resize(scolour); - if(scolour) memcpy((void*)ret.m_colour.c_str(), &m_buffer[c_get], scolour); + ret.m_colour = wxString((wxChar*)&m_buffer[c_get], scolour / sizeof(wxChar)); c_get += scolour; m_get = c_get; @@ -117,7 +114,7 @@ LogWriter::LogWriter() } } -void LogWriter::WriteToLog(std::string prefix, std::string value, u8 lvl/*, wxColour bgcolour*/) +void LogWriter::WriteToLog(wxString prefix, wxString value, u8 lvl/*, wxColour bgcolour*/) { if(!prefix.empty()) { @@ -127,8 +124,8 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, u8 lvl/*, wxCo } } - if(m_logfile.IsOpened()) - m_logfile.Write(wxString(prefix.empty() ? "" : std::string("[" + prefix + "]: ") + value + "\n").wx_str()); + if(m_logfile.IsOpened() && !prefix.empty()) + m_logfile.Write(wxString("[") + prefix + "]: " + value + "\n"); if(!ConLogFrame || Ini.HLELogLvl.GetValue() == 4 || (lvl != 0 && lvl <= Ini.HLELogLvl.GetValue())) return; @@ -175,7 +172,7 @@ void LogWriter::Write(const wxString fmt, ...) va_end(list); - WriteToLog("!", (const char *)frmt.ToAscii(), 2); + WriteToLog("!", frmt, 2); } void LogWriter::Error(const wxString fmt, ...) @@ -188,7 +185,7 @@ void LogWriter::Error(const wxString fmt, ...) va_end(list); - WriteToLog("E", static_cast(frmt), 4); + WriteToLog("E", frmt, 4); } void LogWriter::Warning(const wxString fmt, ...) @@ -201,7 +198,7 @@ void LogWriter::Warning(const wxString fmt, ...) va_end(list); - WriteToLog("W", static_cast(frmt), 3); + WriteToLog("W", frmt, 3); } void LogWriter::Success(const wxString fmt, ...) @@ -214,7 +211,7 @@ void LogWriter::Success(const wxString fmt, ...) va_end(list); - WriteToLog("S", static_cast(frmt), 1); + WriteToLog("S", frmt, 1); } void LogWriter::SkipLn() @@ -279,9 +276,9 @@ void LogFrame::Task() const int cur_item = m_log.GetItemCount(); - m_log.InsertItem(cur_item, wxString(item.m_prefix).wx_str()); - m_log.SetItem(cur_item, 1, wxString(item.m_text).wx_str()); - m_log.SetItemTextColour(cur_item, wxString(item.m_colour).wx_str()); + m_log.InsertItem(cur_item, item.m_prefix); + m_log.SetItem(cur_item, 1, item.m_text); + m_log.SetItemTextColour(cur_item, item.m_colour); m_log.SetColumnWidth(0, -1); // crashes on exit m_log.SetColumnWidth(1, -1); diff --git a/rpcs3/Gui/ConLog.h b/rpcs3/Gui/ConLog.h index fec015d43a..79aec07cf1 100644 --- a/rpcs3/Gui/ConLog.h +++ b/rpcs3/Gui/ConLog.h @@ -8,10 +8,10 @@ class LogWriter wxFile m_logfile; wxColour m_txtcolour; - std::string m_prefix; - std::string m_value; + //wxString m_prefix; + //wxString m_value; - virtual void WriteToLog(std::string prefix, std::string value, u8 lvl); + virtual void WriteToLog(wxString prefix, wxString value, u8 lvl); public: LogWriter(); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index f66c4e89a8..269cfd0ce4 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -202,7 +202,7 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) } else { - ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().ToStdString().c_str()); + ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().wx_str()); } } diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index da64180a17..383acdad94 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -286,6 +286,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 4a3e8de4da..01ebc7bc58 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -475,6 +475,9 @@ Emu\SysCalls\Modules + + Emu\SysCalls\Modules + diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 3a9515c24f..3e08c96092 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -34,6 +34,11 @@ #include #endif +#ifndef _WIN32 +//hack, disabled +//#define wx_str() ToStdString().c_str() +#endif + #include typedef unsigned int uint; @@ -68,6 +73,12 @@ union u128 operator bool() const { return _u64[0] != 0 || _u64[1] != 0; } + static u128 From128( u64 hi, u64 lo ) + { + u128 ret = {hi, lo}; + return ret; + } + static u128 From64( u64 src ) { u128 ret = {0, src}; @@ -84,6 +95,27 @@ union u128 return ret; } + static u128 FromBit ( u32 bit ) + { + u128 ret; + if (bit < 64) + { + ret.hi = 0; + ret.lo = (u64)1 << bit; + } + else if (bit < 128) + { + ret.hi = (u64)1 << (bit - 64); + ret.lo = 0; + } + else + { + ret.hi = 0; + ret.lo = 0; + } + return ret; + } + bool operator == ( const u128& right ) const { return (lo == right.lo) && (hi == right.hi); @@ -93,6 +125,26 @@ union u128 { return (lo != right.lo) || (hi != right.hi); } + + u128 operator | ( const u128& right ) const + { + return From128(hi | right.hi, lo | right.lo); + } + + u128 operator & ( const u128& right ) const + { + return From128(hi & right.hi, lo & right.lo); + } + + u128 operator ^ ( const u128& right ) const + { + return From128(hi ^ right.hi, lo ^ right.lo); + } + + u128 operator ~ () const + { + return From128(~hi, ~lo); + } }; union s128