diff --git a/bin/dev_usb000/.gitignore b/bin/dev_usb000/.gitignore new file mode 100644 index 0000000000..86d0cb2726 --- /dev/null +++ b/bin/dev_usb000/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 36848ab401..ee0cf6c4b3 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -67,10 +67,10 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); while(!SPU.Out_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break; - case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break; + case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break; case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); - SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1); - SPU.MBox_Status.SetValue((SPU.MBox_Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8)); + //SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1); + SPU.MBox_Status.SetValue((SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8)); *value = SPU.MBox_Status.GetValue(); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break; @@ -156,38 +156,9 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break; case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break; case MFC_CMDStatus_offs: - { ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value); MFC.CMDStatus.SetValue(value); - u16 op = value & MFC_MASK_CMD; - - switch(op) - { - case MFC_PUT_CMD: - case MFC_GET_CMD: - { - u32 lsa = MFC.LSA.GetValue(); - u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32); - u32 size_tag = MFC.Size_Tag.GetValue(); - u16 tag = (u16)size_tag; - u16 size = size_tag >> 16; - - ConLog.Warning("RawSPUThread[%d]: DMA %s:", m_index, op == MFC_PUT_CMD ? "PUT" : "GET"); - ConLog.Warning("*** lsa = 0x%x", lsa); - ConLog.Warning("*** ea = 0x%llx", ea); - ConLog.Warning("*** tag = 0x%x", tag); - ConLog.Warning("*** size = 0x%x", size); - ConLog.SkipLn(); - - MFC.CMDStatus.SetValue(dmac.Cmd(value, tag, lsa, ea, size)); - } - break; - - default: - ConLog.Error("RawSPUThread[%d]: Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", m_index, op, value); - break; - } - } + DoMfcCmd(); break; case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break; case Prxy_QueryType_offs: @@ -213,7 +184,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break; - case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); break; + case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); while(!SPU.In_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break; case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break; case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break; @@ -284,7 +255,8 @@ void RawSPUThread::Task() } } - bool is_last_paused = SPU.RunCntl.GetValue() == SPU_RUNCNTL_STOP; + bool is_last_paused = true; + while(true) { int status = ThreadStatus(); @@ -306,11 +278,9 @@ void RawSPUThread::Task() { if(!is_last_paused) { - if(is_last_paused = SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) - { - SPU.NPC.SetValue(PC); - SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); - } + is_last_paused = true; + SPU.NPC.SetValue(PC); + SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); } Sleep(1); @@ -322,6 +292,7 @@ void RawSPUThread::Task() is_last_paused = false; PC = SPU.NPC.GetValue(); SPU.Status.SetValue(SPU_STATUS_RUNNING); + ConLog.Warning("Starting RawSPU..."); } Step(); @@ -330,7 +301,7 @@ void RawSPUThread::Task() if(status == CPUThread_Step) { m_is_step = false; - break; + continue; } for(uint i=0; i> w)) ? ~0 : 0; + CPU.GPR[rt]._u32[w] = (pref & (1 << w)) ? ~0 : 0; } void FSMH(u32 rt, u32 ra) { + const u32 pref = CPU.GPR[ra]._u32[3]; for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u32[0] & (128 >> h)) ? ~0 : 0; + CPU.GPR[rt]._u16[h] = (pref & (1 << h)) ? ~0 : 0; } void FSMB(u32 rt, u32 ra) { + const u32 pref = CPU.GPR[ra]._u32[3]; for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = (CPU.GPR[ra]._u32[0] & (32768 >> b)) ? ~0 : 0; + CPU.GPR[rt]._u8[b] = (pref & (1 << b)) ? ~0 : 0; } void FREST(u32 rt, u32 ra) { - UNIMPLEMENTED(); + //(SSE) RCPPS - Compute Reciprocals of Packed Single-Precision Floating-Point Values + //rt = approximate(1/ra) + CPU.GPR[rt]._m128 = _mm_rcp_ps(CPU.GPR[ra]._m128); } void FRSQEST(u32 rt, u32 ra) { - UNIMPLEMENTED(); + //(SSE) RSQRTPS - Compute Reciprocals of Square Roots of Packed Single-Precision Floating-Point Values + //rt = approximate(1/sqrt(abs(ra))) + //abs(ra) === ra & FloatAbsMask + const __u32x4 FloatAbsMask = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; + CPU.GPR[rt]._m128 = _mm_rsqrt_ps(_mm_and_ps(CPU.GPR[ra]._m128, FloatAbsMask.m128)); } void LQX(u32 rt, u32 ra, u32 rb) { - u32 lsa = CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]; + u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3]; + + if(b & 0xf) + { + ConLog.Warning("LQX HACK (a[0x%x] + b[0x%x(0x%x)])", a, b << 3, b); + b <<= 3; + } + + u32 lsa = (a + b) & 0x3fff0; + if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("LQX: bad lsa (0x%x)", lsa); @@ -393,238 +423,196 @@ private: } void ROTQBYBI(u32 rt, u32 ra, u32 rb) { - const int s = (CPU.GPR[rb]._u32[0] >> 3) & 0xf; - - for (int b = 0; b < 8; b++) - { - if(b + s < 16) - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; - } - else - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s - 16]; - } - } + const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0xf; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBYBI(u32 rt, u32 ra, u32 rb) { - const int nShift = ((0 - CPU.GPR[rb]._u32[0]) >> 3) & 0x1f; - - for (int b = 0; b < 16; b++) - { - if (b >= nShift) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; - else - CPU.GPR[rt]._u8[b] = 0; - } + const int s = (0 - (CPU.GPR[rb]._u32[3] >> 3)) & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + for (int b = 0; b < 16 - s; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBYBI(u32 rt, u32 ra, u32 rb) { - const int nShift = (CPU.GPR[rb]._u32[0] >> 3) & 0x1f; - - for (int b = 0; b < 16; b++) - { - if ((b + nShift) < 16) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + nShift]; - else - CPU.GPR[rt]._u8[b] = 0; - } + const int s = (CPU.GPR[rb]._u32[3] >> 3) & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + for (int b = s; b < 16; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } void CBX(u32 rt, u32 ra, u32 rb) { - int n = (CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0xf; + const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xF; - for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = b == n ? 3 : b | 0x10; + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u8[15 - t] = 0x03; } void CHX(u32 rt, u32 ra, u32 rb) { - int n = ((CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0xf) >> 1; + const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xE; - for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = h == n ? 0x0203 : (h * 2 * 0x0101 + 0x1011); + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203; } void CWX(u32 rt, u32 ra, u32 rb) { - const u32 t = ((CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]) & 0xc) / 4; - for(u32 i=0; i<16; ++i) CPU.GPR[rt]._i8[i] = 0x10 + i; - CPU.GPR[rt]._u32[t] = 0x10203; + const u32 t = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0xC; + + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203; } void CDX(u32 rt, u32 ra, u32 rb) { - int n = ((CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0x8) >> 2; + const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0x8; - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = (w == n) ? 0x00010203 : (w == (n + 1)) ? 0x04050607 : (0x01010101 * (w * 4) + 0x10111213); + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607; } void ROTQBI(u32 rt, u32 ra, u32 rb) { - int nShift = CPU.GPR[rb]._u32[0] & 0x7; - - CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); - CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << nShift) | (CPU.GPR[ra]._u32[0] >> (32 - nShift)); + const int t = CPU.GPR[rb]._u32[3] & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << t) | (temp._u32[3] >> (32 - t)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); } void ROTQMBI(u32 rt, u32 ra, u32 rb) { - int nShift = (0 - CPU.GPR[rb]._u32[0]) % 8; - - CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] >> nShift; - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> nShift) | (CPU.GPR[ra]._u32[0] << (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> nShift) | (CPU.GPR[ra]._u32[1] << (32 - nShift)); - CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> nShift) | (CPU.GPR[ra]._u32[2] << (32 - nShift)); + const int t = (0 - CPU.GPR[rb]._u32[3]) & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] >> t) | (temp._u32[1] << (32 - t)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] >> t) | (temp._u32[2] << (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] >> t) | (temp._u32[3] << (32 - t)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> t); } void SHLQBI(u32 rt, u32 ra, u32 rb) { - const int nShift = CPU.GPR[rb]._u32[0] & 0x7; - - CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); - CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] << nShift; + const int t = CPU.GPR[rb]._u32[3] & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << t); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << t) | (temp._u32[0] >> (32 - t)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << t) | (temp._u32[1] >> (32 - t)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << t) | (temp._u32[2] >> (32 - t)); } void ROTQBY(u32 rt, u32 ra, u32 rb) { - const s32 s = CPU.GPR[rb]._u8[0] & 0xf; - - for(u32 b = 0; b < 16; ++b) - { - if(b + s < 16) - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; - } - else - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s - 16]; - } - } + const int s = CPU.GPR[rb]._u32[3] & 0xf; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + for (int b = 0; b < 16; ++b) + CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBY(u32 rt, u32 ra, u32 rb) { - const int nShift = (0 - CPU.GPR[rb]._u32[0]) % 32; - - for (int b = 0; b < 16; b++) - if (b >= nShift) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; - else - CPU.GPR[rt]._u8[b] = 0; + const int s = (0 - CPU.GPR[rb]._u32[3]) & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + for (int b = 0; b < 16 - s; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBY(u32 rt, u32 ra, u32 rb) { - const int nShift = CPU.GPR[rb]._u32[0] & 0x1f; - - for (int b = 0; b < 16; b++) - if (b + nShift < 16) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + nShift]; - else - CPU.GPR[rt]._u8[b] = 0; + const int s = CPU.GPR[rb]._u32[3] & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + for (int b = s; b < 16; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } void ORX(u32 rt, u32 ra) { - CPU.GPR[rt].Reset(); - - CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] | CPU.GPR[ra]._u32[1] | CPU.GPR[ra]._u32[2] | CPU.GPR[ra]._u32[3]; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[0] | CPU.GPR[ra]._u32[1] | CPU.GPR[ra]._u32[2] | CPU.GPR[ra]._u32[3]; + CPU.GPR[rt]._u32[2] = 0; + CPU.GPR[rt]._u64[0] = 0; } void CBD(u32 rt, u32 ra, s32 i7) { - const int n = (CPU.GPR[ra]._u32[0] + i7) & 0xf; + const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xF; - for (int b = 0; b < 16; b++) - if (b == n) - CPU.GPR[rt]._u8[b] = 0x3; - else - CPU.GPR[rt]._u8[b] = b | 0x10; + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u8[15 - t] = 0x03; } void CHD(u32 rt, u32 ra, s32 i7) { - int n = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 1; + const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xE; - for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = h == n ? 0x0203 : (h * 2 * 0x0101 + 0x1011); + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203; } void CWD(u32 rt, u32 ra, s32 i7) { - const int t = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 2; + const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xC; - for (int i=0; i<16; ++i) - CPU.GPR[rt]._u8[i] = 0x10 + i; - - CPU.GPR[rt]._u32[t] = 0x10203; + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203; } void CDD(u32 rt, u32 ra, s32 i7) { - const int t = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 3; + const int t = (CPU.GPR[ra]._u32[3] + i7) & 0x8; - for (int i=0; i<16; ++i) - CPU.GPR[rt]._u8[i] = 0x10 + i; - - CPU.GPR[rt]._u64[t] = (u64)0x0001020304050607; + CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F; + CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; + CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607; } void ROTQBII(u32 rt, u32 ra, s32 i7) { - int nShift = i7 & 0x7; - - CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); - CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << nShift) | (CPU.GPR[ra]._u32[0] >> (32 - nShift)); + const int s = i7 & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << s) | (temp._u32[3] >> (32 - s)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); } void ROTQMBII(u32 rt, u32 ra, s32 i7) { - int nShift = (0 - i7) % 8; - - CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] >> nShift; - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> nShift) | (CPU.GPR[ra]._u32[0] << (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> nShift) | (CPU.GPR[ra]._u32[1] << (32 - nShift)); - CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> nShift) | (CPU.GPR[ra]._u32[2] << (32 - nShift)); + const int s = (0 - i7) & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] >> s) | (temp._u32[1] << (32 - s)); + CPU.GPR[rt]._u32[1] = (temp._u32[1] >> s) | (temp._u32[2] << (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] >> s) | (temp._u32[3] << (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] >> s); } void SHLQBII(u32 rt, u32 ra, s32 i7) { - const int nShift = i7 & 0x7; - - CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); - CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); - CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); - CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] << nShift; + const int s = i7 & 0x7; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt]._u32[0] = (temp._u32[0] << s); + CPU.GPR[rt]._u32[1] = (temp._u32[1] << s) | (temp._u32[0] >> (32 - s)); + CPU.GPR[rt]._u32[2] = (temp._u32[2] << s) | (temp._u32[1] >> (32 - s)); + CPU.GPR[rt]._u32[3] = (temp._u32[3] << s) | (temp._u32[2] >> (32 - s)); } void ROTQBYI(u32 rt, u32 ra, s32 i7) { - const u16 s = i7 & 0xf; - - for(u32 b = 0; b < 16; ++b) - { - if(b + s < 16) - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; - } - else - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s - 16]; - } - } + const int s = i7 & 0xf; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = temp._u8[(b - s) & 0xf]; } void ROTQMBYI(u32 rt, u32 ra, s32 i7) { - const int nShift = (0 - i7) % 32; - - for (int b = 0; b < 16; b++) - if (b >= nShift) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; - else - CPU.GPR[rt]._u8[b] = 0; + const int s = (0 - i7) & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + for (int b = 0; b < 16 - s; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b + s]; } void SHLQBYI(u32 rt, u32 ra, s32 i7) { - const u16 s = i7 & 0x1f; - + const int s = i7 & 0x1f; + const SPU_GPR_hdr temp = CPU.GPR[ra]; CPU.GPR[rt].Reset(); - - for(u32 b = 0; b + s < 16; ++b) - { - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; - } + for (int b = s; b < 16; b++) + CPU.GPR[rt]._u8[b] = temp._u8[b - s]; } void NOP(u32 rt) { @@ -647,7 +635,7 @@ private: void EQV(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[w] & CPU.GPR[rb]._u32[w]) | ~(CPU.GPR[ra]._u32[w] | CPU.GPR[rb]._u32[w]); + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] ^ (~CPU.GPR[rb]._u32[w]); } void CGTB(u32 rt, u32 ra, u32 rb) { @@ -656,19 +644,18 @@ private: } void SUMB(u32 rt, u32 ra, u32 rb) { + const SPU_GPR_hdr _a = CPU.GPR[ra]; + const SPU_GPR_hdr _b = CPU.GPR[rb]; for (int w = 0; w < 4; w++) { - CPU.GPR[rt]._u16[w*2] = CPU.GPR[ra]._u8[w*4] + CPU.GPR[ra]._u8[w*4 + 1] + CPU.GPR[ra]._u8[w*4 + 2] + CPU.GPR[ra]._u8[w*4 + 3]; - CPU.GPR[rt]._u16[w*2 + 1] = CPU.GPR[rb]._u8[w*4] + CPU.GPR[rb]._u8[w*4 + 1] + CPU.GPR[rb]._u8[w*4 + 2] + CPU.GPR[rb]._u8[w*4 + 3]; + CPU.GPR[rt]._u16[w*2] = _a._u8[w*4] + _a._u8[w*4 + 1] + _a._u8[w*4 + 2] + _a._u8[w*4 + 3]; + CPU.GPR[rt]._u16[w*2 + 1] = _b._u8[w*4] + _b._u8[w*4 + 1] + _b._u8[w*4 + 2] + _b._u8[w*4 + 3]; } } //HGT uses signed values. HLGT uses unsigned values void HGT(u32 rt, s32 ra, s32 rb) { - if(CPU.GPR[ra]._i32[0] > CPU.GPR[rb]._i32[0]) - { - CPU.Stop(); - } + if(CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3]) CPU.Stop(); } void CLZ(u32 rt, u32 ra) { @@ -685,26 +672,26 @@ private: } void XSWD(u32 rt, u32 ra) { - CPU.GPR[rt]._i64[0] = (s64)CPU.GPR[ra]._i32[1]; - CPU.GPR[rt]._i64[1] = (s64)CPU.GPR[ra]._i32[3]; + CPU.GPR[rt]._i64[0] = (s64)CPU.GPR[ra]._i32[0]; + CPU.GPR[rt]._i64[1] = (s64)CPU.GPR[ra]._i32[2]; } void XSHW(u32 rt, u32 ra) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = (s32)CPU.GPR[ra]._i16[w*2 + 1]; + CPU.GPR[rt]._i32[w] = (s32)CPU.GPR[ra]._i16[w*2]; } void CNTB(u32 rt, u32 ra) { + const SPU_GPR_hdr temp = CPU.GPR[ra]; CPU.GPR[rt].Reset(); - for (int b = 0; b < 16; b++) for (int i = 0; i < 8; i++) - CPU.GPR[rt]._u8[b] += (CPU.GPR[ra]._u8[b] & (1 << i)) ? 1 : 0; + CPU.GPR[rt]._u8[b] += (temp._u8[b] & (1 << i)) ? 1 : 0; } void XSBH(u32 rt, u32 ra) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._i16[h] = (s16)CPU.GPR[ra]._i8[h*2 + 1]; + CPU.GPR[rt]._i16[h] = (s16)CPU.GPR[ra]._i8[h*2]; } void CLGT(u32 rt, u32 ra, u32 rb) { @@ -795,10 +782,7 @@ private: } void HLGT(u32 rt, u32 ra, u32 rb) { - if(CPU.GPR[ra]._u32[0] > CPU.GPR[rb]._u32[0]) - { - CPU.Stop(); - } + if(CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) CPU.Stop(); } void DFMA(u32 rt, u32 ra, u32 rb) { @@ -817,8 +801,8 @@ private: } void DFNMA(u32 rt, u32 ra, u32 rb) { - CPU.GPR[rt]._d[0] = - CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] - CPU.GPR[rt]._d[0] ; - CPU.GPR[rt]._d[1] = - CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] - CPU.GPR[rt]._d[1] ; + CPU.GPR[rt]._d[0] = -(CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] + CPU.GPR[rt]._d[0]); + CPU.GPR[rt]._d[1] = -(CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] + CPU.GPR[rt]._d[1]); } void CEQ(u32 rt, u32 ra, u32 rb) { @@ -828,7 +812,7 @@ private: void MPYHHU(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2+1] * CPU.GPR[rb]._u16[w*2+1]; } void ADDX(u32 rt, u32 ra, u32 rb) { @@ -843,7 +827,7 @@ private: void CGX(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[w] + CPU.GPR[rb]._u32[w] + (CPU.GPR[rt]._u32[w] & 1)) < CPU.GPR[ra]._u32[w] ? 1 : 0; + CPU.GPR[rt]._u32[w] = ((u64)CPU.GPR[ra]._u32[w] + (u64)CPU.GPR[rb]._u32[w] + (u64)(CPU.GPR[rt]._u32[w] & 1)) >> 32; } void BGX(u32 rt, u32 ra, u32 rb) { @@ -851,19 +835,19 @@ private: for (int w = 0; w < 4; w++) { - nResult = (u64)CPU.GPR[rb]._u32[w] - (u64)CPU.GPR[ra]._u32[w] - (1 - (CPU.GPR[rt]._u32[w] & 1)); + nResult = (u64)CPU.GPR[rb]._u32[w] - (u64)CPU.GPR[ra]._u32[w] - (u64)(1 - (CPU.GPR[rt]._u32[w] & 1)); CPU.GPR[rt]._u32[w] = nResult < 0 ? 0 : 1; } } void MPYHHA(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] += CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; + CPU.GPR[rt]._i32[w] += CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2+1]; } void MPYHHAU(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] += CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; + CPU.GPR[rt]._u32[w] += CPU.GPR[ra]._u16[w*2+1] * CPU.GPR[rb]._u16[w*2+1]; } //Forced bits to 0, hence the shift: @@ -876,15 +860,15 @@ private: } void FESD(u32 rt, u32 ra) { - CPU.GPR[rt]._d[0] = (double)CPU.GPR[ra]._f[0]; - CPU.GPR[rt]._d[1] = (double)CPU.GPR[ra]._f[2]; + CPU.GPR[rt]._d[0] = (double)CPU.GPR[ra]._f[1]; + CPU.GPR[rt]._d[1] = (double)CPU.GPR[ra]._f[3]; } void FRDS(u32 rt, u32 ra) { - CPU.GPR[rt]._f[0] = (float)CPU.GPR[ra]._d[0]; - CPU.GPR[rt]._f[1] = 0x00000000; - CPU.GPR[rt]._f[2] = (float)CPU.GPR[ra]._d[1]; - CPU.GPR[rt]._f[3] = 0x00000000; + CPU.GPR[rt]._f[1] = (float)CPU.GPR[ra]._d[0]; + CPU.GPR[rt]._u32[0] = 0x00000000; + CPU.GPR[rt]._f[3] = (float)CPU.GPR[ra]._d[1]; + CPU.GPR[rt]._u32[1] = 0x00000000; } void FSCRWR(u32 rt, u32 ra) { @@ -892,7 +876,56 @@ private: } void DFTSV(u32 rt, u32 ra, s32 i7) { - UNIMPLEMENTED(); + const u64 DoubleExpMask = 0x7ff0000000000000; + const u64 DoubleFracMask = 0x000fffffffffffff; + const u64 DoubleSignMask = 0x8000000000000000; + const SPU_GPR_hdr temp = CPU.GPR[ra]; + CPU.GPR[rt].Reset(); + if (i7 & 1) //Negative Denorm Check (-, exp is zero, frac is non-zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] & DoubleFracMask) + if ((temp._u64[i] & (DoubleSignMask | DoubleExpMask)) == DoubleSignMask) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 2) //Positive Denorm Check (+, exp is zero, frac is non-zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] & DoubleFracMask) + if ((temp._u64[i] & (DoubleSignMask | DoubleExpMask)) == 0) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 4) //Negative Zero Check (-, exp is zero, frac is zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] == DoubleSignMask) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 8) //Positive Zero Check (+, exp is zero, frac is zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] == 0) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 16) //Negative Infinity Check (-, exp is 0x7ff, frac is zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] == (DoubleSignMask | DoubleExpMask)) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 32) //Positive Infinity Check (+, exp is 0x7ff, frac is zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] == DoubleExpMask) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } + if (i7 & 64) //Not-a-Number Check (any sign, exp is 0x7ff, frac is non-zero) + for (int i = 0; i < 2; i++) + { + if (temp._u64[i] & DoubleFracMask) + if ((temp._u64[i] & DoubleExpMask) == DoubleExpMask) + CPU.GPR[rt]._u64[i] = 0xffffffffffffffff; + } } void FCEQ(u32 rt, u32 ra, u32 rb) { @@ -909,22 +942,22 @@ private: void MPY(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1]; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; } void MPYH(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = ((CPU.GPR[ra]._i32[w] >> 16) * (CPU.GPR[rb]._i32[w] & 0xffff)) << 16; + CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2]) << 16; } void MPYHH(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2+1] * CPU.GPR[rb]._i16[w*2+1]; } void MPYS(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1]) >> 16; + CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]) >> 16; } void CEQH(u32 rt, u32 ra, u32 rb) { @@ -955,39 +988,93 @@ private: } void FI(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + //Floating Interpolation: ra will be ignored. + //It should work correctly if result of preceding FREST or FRSQEST is sufficiently exact + CPU.GPR[rt] = CPU.GPR[rb]; } void HEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3]) CPU.Stop(); } //0 - 9 void CFLTS(u32 rt, u32 ra, s32 i8) { - UNIMPLEMENTED(); + const u32 scale = 173 - (i8 & 0xff); //unsigned immediate + for (int i = 0; i < 4; i++) + { + u32 exp = ((CPU.GPR[ra]._u32[i] >> 23) & 0xff) + scale; + + if (exp > 255) + exp = 255; + + CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._u32[i] & 0x807fffff) | (exp << 23); + } + //(SSE2) CVTTPS2DQ - Convert with Truncation Packed Single FP to Packed Dword Int + CPU.GPR[rt]._m128i = _mm_cvttps_epi32(CPU.GPR[rt]._m128); } void CFLTU(u32 rt, u32 ra, s32 i8) { - UNIMPLEMENTED(); + const u32 scale = 173 - (i8 & 0xff); //unsigned immediate + for (int i = 0; i < 4; i++) + { + u32 exp = ((CPU.GPR[ra]._u32[i] >> 23) & 0xff) + scale; + + if (exp > 255) + exp = 255; + + if (CPU.GPR[ra]._u32[i] & 0x80000000) //if negative, result = 0 + CPU.GPR[rt]._u32[i] = 0; + else + { + CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._u32[i] & 0x807fffff) | (exp << 23); + + if (CPU.GPR[rt]._f[i] > 0xffffffff) //if big, result = max + CPU.GPR[rt]._u32[i] = 0xffffffff; + else + CPU.GPR[rt]._u32[i] = floor(CPU.GPR[rt]._f[i]); + } + } } void CSFLT(u32 rt, u32 ra, s32 i8) { - UNIMPLEMENTED(); + //(SSE2) CVTDQ2PS - Convert Packed Dword Integers to Packed Single-Precision FP Values + CPU.GPR[rt]._m128 = _mm_cvtepi32_ps(CPU.GPR[ra]._m128i); + const u32 scale = 155 - (i8 & 0xff); //unsigned immediate + for (int i = 0; i < 4; i++) + { + u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; + + if (exp > 255) //< 0 + exp = 0; + + CPU.GPR[rt]._u32[i] = (CPU.GPR[rt]._u32[i] & 0x807fffff) | (exp << 23); + } } void CUFLT(u32 rt, u32 ra, s32 i8) { - UNIMPLEMENTED(); + const u32 scale = 155 - (i8 & 0xff); //unsigned immediate + for (int i = 0; i < 4; i++) + { + CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i]; + u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; + + if (exp > 255) //< 0 + exp = 0; + + CPU.GPR[rt]._u32[i] = (CPU.GPR[rt]._u32[i] & 0x807fffff) | (exp << 23); + } } //0 - 8 void BRZ(u32 rt, s32 i16) { - if(!CPU.GPR[rt]._u32[3]) CPU.SetBranch(branchTarget(CPU.PC, i16)); + if (CPU.GPR[rt]._u32[3] == 0) + CPU.SetBranch(branchTarget(CPU.PC, i16)); } void STQA(u32 rt, s32 i16) { - u32 lsa = i16 << 2; + u32 lsa = (i16 << 2) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("STQA: bad lsa (0x%x)", lsa); @@ -999,20 +1086,22 @@ private: } void BRNZ(u32 rt, s32 i16) { - if(CPU.GPR[rt]._u32[3] != 0) + if (CPU.GPR[rt]._u32[3] != 0) CPU.SetBranch(branchTarget(CPU.PC, i16)); } void BRHZ(u32 rt, s32 i16) { - if(!CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16)); + if (CPU.GPR[rt]._u16[6] == 0) + CPU.SetBranch(branchTarget(CPU.PC, i16)); } void BRHNZ(u32 rt, s32 i16) { - if(CPU.GPR[rt]._u16[7]) CPU.SetBranch(branchTarget(CPU.PC, i16)); + if (CPU.GPR[rt]._u16[6] != 0) + CPU.SetBranch(branchTarget(CPU.PC, i16)); } void STQR(u32 rt, s32 i16) { - u32 lsa = branchTarget(CPU.PC, i16); + u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("STQR: bad lsa (0x%x)", lsa); @@ -1024,11 +1113,11 @@ private: } void BRA(s32 i16) { - CPU.SetBranch(i16 << 2); + CPU.SetBranch(branchTarget(0, i16)); } void LQA(u32 rt, s32 i16) { - u32 lsa = i16 << 2; + u32 lsa = (i16 << 2) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("LQA: bad lsa (0x%x)", lsa); @@ -1041,8 +1130,8 @@ private: void BRASL(u32 rt, s32 i16) { CPU.GPR[rt].Reset(); - CPU.GPR[rt]._u32[0] = CPU.PC + 4; - CPU.SetBranch(i16 << 2); + CPU.GPR[rt]._u32[3] = CPU.PC + 4; + CPU.SetBranch(branchTarget(0, i16)); } void BR(s32 i16) { @@ -1072,7 +1161,7 @@ private: } void LQR(u32 rt, s32 i16) { - u32 lsa = branchTarget(CPU.PC, i16); + u32 lsa = branchTarget(CPU.PC, i16) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("LQR: bad lsa (0x%x)", lsa); @@ -1084,25 +1173,25 @@ private: } void IL(u32 rt, s32 i16) { - CPU.GPR[rt]._u32[0] = i16; - CPU.GPR[rt]._u32[1] = i16; - CPU.GPR[rt]._u32[2] = i16; - CPU.GPR[rt]._u32[3] = i16; + CPU.GPR[rt]._i32[0] = + CPU.GPR[rt]._i32[1] = + CPU.GPR[rt]._i32[2] = + CPU.GPR[rt]._i32[3] = i16; } void ILHU(u32 rt, s32 i16) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u16[w*2 + 1] = i16; + CPU.GPR[rt]._i32[w] = i16 << 16; } void ILH(u32 rt, s32 i16) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = i16; + CPU.GPR[rt]._i16[h] = i16; } void IOHL(u32 rt, s32 i16) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] |= i16; + CPU.GPR[rt]._i32[w] |= (i16 & 0xFFFF); } @@ -1110,19 +1199,17 @@ private: void ORI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 4; ++i) - { - CPU.GPR[rt]._u32[i] = CPU.GPR[ra]._u32[i] | i10; - } + CPU.GPR[rt]._i32[i] = CPU.GPR[ra]._i32[i] | i10; } void ORHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] | i10; + CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] | i10; } void ORBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] | (i10 & 0xff); + CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] | i10; } void SFI(u32 rt, u32 ra, s32 i10) { @@ -1137,35 +1224,33 @@ private: void ANDI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] & i10; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i32[w] & i10; } void ANDHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] & i10; + CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] & i10; } void ANDBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] & (i10 & 0xff); + CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] & i10; } void AI(u32 rt, u32 ra, s32 i10) { - for(u32 i = 0; i < 4; ++i) - { - CPU.GPR[rt]._u32[i] = CPU.GPR[ra]._u32[i] + i10; - } + CPU.GPR[rt]._i32[0] = CPU.GPR[ra]._i32[0] + i10; + CPU.GPR[rt]._i32[1] = CPU.GPR[ra]._i32[1] + i10; + CPU.GPR[rt]._i32[2] = CPU.GPR[ra]._i32[2] + i10; + CPU.GPR[rt]._i32[3] = CPU.GPR[ra]._i32[3] + i10; } void AHI(u32 rt, u32 ra, s32 i10) { - for(u32 i = 0; i < 8; ++i) - { - CPU.GPR[rt]._u16[i] = CPU.GPR[ra]._u16[i] + i10; - } + for(u32 h = 0; h < 8; ++h) + CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] + i10; } - void STQD(u32 rt, s32 i10, u32 ra) + void STQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding { - u32 lsa = CPU.GPR[ra]._u32[3] + i10; + const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("STQD: bad lsa (0x%x)", lsa); @@ -1174,9 +1259,9 @@ private: } CPU.WriteLS128(lsa, CPU.GPR[rt]._u128); } - void LQD(u32 rt, s32 i10, u32 ra) + void LQD(u32 rt, s32 i10, u32 ra) //i10 is shifted left by 4 while decoding { - u32 lsa = CPU.GPR[ra]._u32[3] + i10; + const u32 lsa = (CPU.GPR[ra]._i32[3] + i10) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) { ConLog.Error("LQD: bad lsa (0x%x)", lsa); @@ -1189,17 +1274,17 @@ private: void XORI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] ^ i10; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i32[w] ^ i10; } void XORHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] ^ i10; + CPU.GPR[rt]._i16[h] = CPU.GPR[ra]._i16[h] ^ i10; } void XORBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] ^ (i10 & 0xff); + CPU.GPR[rt]._i8[b] = CPU.GPR[ra]._i8[b] ^ i10; } void CGTI(u32 rt, u32 ra, s32 i10) { @@ -1218,20 +1303,20 @@ private: } void HGTI(u32 rt, u32 ra, s32 i10) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._i32[3] > i10) CPU.Stop(); } void CLGTI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 4; ++i) { - CPU.GPR[rt]._u32[i] = (CPU.GPR[rt]._u32[i] > (u32)i10) ? 0xffffffff : 0x00000000; + CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._u32[i] > (u32)i10) ? 0xffffffff : 0x00000000; } } void CLGTHI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 8; ++i) { - CPU.GPR[rt]._u16[i] = (CPU.GPR[rt]._u16[i] > (u16)i10) ? 0xffff : 0x0000; + CPU.GPR[rt]._u16[i] = (CPU.GPR[ra]._u16[i] > (u16)i10) ? 0xffff : 0x0000; } } void CLGTBI(u32 rt, u32 ra, s32 i10) @@ -1241,96 +1326,117 @@ private: } void HLGTI(u32 rt, u32 ra, s32 i10) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._u32[3] > (u32)i10) CPU.Stop(); } void MPYI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[rt]._i16[w*2 + 1] * i10; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * i10; } void MPYUI(u32 rt, u32 ra, s32 i10) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[rt]._u16[w*2 + 1] * (u16)(i10 & 0xffff); + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * (u16)(i10 & 0xffff); } void CEQI(u32 rt, u32 ra, s32 i10) { for(u32 i = 0; i < 4; ++i) - { - CPU.GPR[rt]._u32[i] = (CPU.GPR[rt]._u32[i] == (u32)i10) ? 0xffffffff : 0x00000000; - } + CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._i32[i] == i10) ? 0xffffffff : 0x00000000; } void CEQHI(u32 rt, u32 ra, s32 i10) { for (int h = 0; h < 8; h++) - CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] == (s16)i10 ? 0xffff : 0; + CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._i16[h] == (s16)i10) ? 0xffff : 0; } void CEQBI(u32 rt, u32 ra, s32 i10) { for (int b = 0; b < 16; b++) - CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] == (u8)(i10 & 0xff) ? 0xff : 0; + CPU.GPR[rt]._i8[b] = (CPU.GPR[ra]._i8[b] == (s8)(i10 & 0xff)) ? 0xff : 0; } void HEQI(u32 rt, u32 ra, s32 i10) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._i32[3] == i10) CPU.Stop(); } //0 - 6 void HBRA(s32 ro, s32 i16) - { - UNIMPLEMENTED(); + { //i16 is shifted left by 2 while decoding } void HBRR(s32 ro, s32 i16) { } - void ILA(u32 rt, s32 i18) + void ILA(u32 rt, u32 i18) { - CPU.GPR[rt]._u32[0] = i18; - CPU.GPR[rt]._u32[1] = i18; - CPU.GPR[rt]._u32[2] = i18; - CPU.GPR[rt]._u32[3] = i18; + CPU.GPR[rt]._u32[0] = + CPU.GPR[rt]._u32[1] = + CPU.GPR[rt]._u32[2] = + CPU.GPR[rt]._u32[3] = i18 & 0x3FFFF; } //0 - 3 void SELB(u32 rt, u32 ra, u32 rb, u32 rc) { - for(u32 i = 0; i < 4; ++i) + for(u64 i = 0; i < 2; ++i) { - CPU.GPR[rt]._u32[i] = - ( CPU.GPR[rc]._u32[i] & CPU.GPR[rb]._u32[i]) | - (~CPU.GPR[rc]._u32[i] & CPU.GPR[ra]._u32[i]); + CPU.GPR[rt]._u64[i] = + ( CPU.GPR[rc]._u64[i] & CPU.GPR[rb]._u64[i]) | + (~CPU.GPR[rc]._u64[i] & CPU.GPR[ra]._u64[i]); } } void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) { - //ConLog.Warning("SHUFB"); + const SPU_GPR_hdr _a = CPU.GPR[ra]; + const SPU_GPR_hdr _b = CPU.GPR[rb]; + for (int i = 0; i < 16; i++) + { + u8 b = CPU.GPR[rc]._u8[i]; + if(b & 0x80) + { + if(b & 0x40) + { + if(b & 0x20) + CPU.GPR[rt]._u8[i] = 0x80; + else + CPU.GPR[rt]._u8[i] = 0xFF; + } + else + CPU.GPR[rt]._u8[i] = 0x00; + } + else + { + if(b & 0x10) + CPU.GPR[rt]._u8[i] = _b._u8[15 - (b & 0x0F)]; + else + CPU.GPR[rt]._u8[i] = _a._u8[15 - (b & 0x0F)]; + } + } } void MPYA(u32 rc, u32 ra, u32 rb, u32 rt) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1] + CPU.GPR[rc]._i32[w]; + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2] + CPU.GPR[rc]._i32[w]; } void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) { - CPU.GPR[rt]._f[0] -= CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] -= CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] -= CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] -= CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; + CPU.GPR[rt]._f[0] = CPU.GPR[rc]._f[0] - CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[rc]._f[1] - CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[rc]._f[2] - CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[rc]._f[3] - CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void FMA(u32 rc, u32 ra, u32 rb, u32 rt) { - CPU.GPR[rt]._f[0] += CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; - CPU.GPR[rt]._f[1] += CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; - CPU.GPR[rt]._f[2] += CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; - CPU.GPR[rt]._f[3] += CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] + CPU.GPR[rc]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] + CPU.GPR[rc]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] + CPU.GPR[rc]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] + CPU.GPR[rc]._f[3]; } void FMS(u32 rc, u32 ra, u32 rb, u32 rt) { - CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rt]._f[0]; - CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rt]._f[1]; - CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] - CPU.GPR[rt]._f[2]; - CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] - CPU.GPR[rt]._f[3]; + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rc]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rc]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] - CPU.GPR[rc]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] - CPU.GPR[rc]._f[3]; } void UNK(u32 code, u32 opcode, u32 gcode) diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index 2b0a48744c..6b85300298 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -435,7 +435,7 @@ public: //0 - 6 virtual void HBRA(s32 ro, s32 i16) = 0; virtual void HBRR(s32 ro, s32 i16) = 0; - virtual void ILA(u32 rt, s32 i18) = 0; + virtual void ILA(u32 rt, u32 i18) = 0; //0 - 3 virtual void SELB(u32 rc, u32 ra, u32 rb, u32 rt) = 0; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 8bc5a30dbc..2faacb49bd 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -51,7 +51,7 @@ void SPUThread::InitRegs() SPU.Status.SetValue(SPU_STATUS_RUNNING); Prxy.QueryType.SetValue(0); MFC.CMDStatus.SetValue(0); - PC = SPU.NPC.GetValue(); + //PC = SPU.NPC.GetValue(); } u64 SPUThread::GetFreeStackSize() const diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 4cda6c586b..020882af20 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -3,7 +3,7 @@ #include "Emu/event.h" #include "MFC.h" -static const wxString spu_reg_name[128] = +static const char* spu_reg_name[128] = { "$LR", "$SP", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", @@ -23,7 +23,7 @@ static const wxString spu_reg_name[128] = "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", }; //SPU reg $0 is a dummy reg, and is used for certain instructions. -static const wxString spu_specialreg_name[128] = { +static const char* spu_specialreg_name[128] = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", @@ -42,7 +42,7 @@ static const wxString spu_specialreg_name[128] = { "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", }; -static const wxString spu_ch_name[128] = +static const char* spu_ch_name[128] = { "$SPU_RdEventStat", "$SPU_WrEventMask", "$SPU_WrEventAck", "$SPU_RdSigNotify1", "$SPU_RdSigNotify2", "$ch5", "$ch6", "$SPU_WrDec", "$SPU_RdDec", @@ -204,6 +204,8 @@ union SPU_GPR_hdr { u128 _u128; s128 _i128; + __m128 _m128; + __m128i _m128i; u64 _u64[2]; s64 _i64[2]; u32 _u32[4]; @@ -232,13 +234,13 @@ union SPU_SPR_hdr { u128 _u128; s128 _i128; - + u32 _u32[4]; SPU_SPR_hdr() {} wxString ToString() const { - return wxString::Format("%16%16", _u128.hi, _u128.lo); + return wxString::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); } void Reset() @@ -351,10 +353,72 @@ public: DMAC dmac; + void DoMfcCmd() + { + u32 cmd = MFC.CMDStatus.GetValue(); + u16 op = cmd & MFC_MASK_CMD; + + switch(op & (MFC_PUT_CMD | MFC_GET_CMD)) + { + case MFC_PUT_CMD: + case MFC_GET_CMD: + { + u32 lsa = MFC.LSA.GetValue(); + u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32); + u32 size_tag = MFC.Size_Tag.GetValue(); + u16 tag = (u16)size_tag; + u16 size = size_tag >> 16; + + ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET"); + ConLog.Warning("*** lsa = 0x%x", lsa); + ConLog.Warning("*** ea = 0x%llx", ea); + ConLog.Warning("*** tag = 0x%x", tag); + ConLog.Warning("*** size = 0x%x", size); + ConLog.Warning("*** cmd = 0x%x", cmd); + ConLog.SkipLn(); + + MFC.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + } + break; + + default: + ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd); + break; + } + } + u32 GetChannelCount(u32 ch) { switch(ch) { + case SPU_RdEventStat: //Read event status with mask applied + case SPU_WrEventMask: //Write event mask + case SPU_WrEventAck: //Write end of event processing + case SPU_RdSigNotify1: //Signal notification 1 + case SPU_RdSigNotify2: //Signal notification 2 + case SPU_WrDec: //Write decrementer count + case SPU_RdDec: //Read decrementer count + case SPU_RdEventMask: //Read event mask + case SPU_RdMachStat: //Read SPU run status + case SPU_WrSRR0: //Write SPU machine state save/restore register 0 (SRR0) + case SPU_RdSRR0: //Read SPU machine state save/restore register 0 (SRR0) + case MFC_WrMSSyncReq: //Write multisource synchronization request + case MFC_RdTagMask: //Read tag mask + case MFC_LSA: //Write local memory address command parameter + case MFC_EAH: //Write high order DMA effective address command parameter + case MFC_EAL: //Write low order DMA effective address command parameter + case MFC_Size: //Write DMA transfer size command parameter + case MFC_TagID: //Write tag identifier command parameter + case MFC_Cmd: //Write and enqueue DMA command with associated class ID + case MFC_WrTagMask: //Write tag mask + case MFC_WrTagUpdate: //Write request for conditional or unconditional tag status update + case MFC_RdTagStat: //Read tag status with mask applied + case MFC_RdListStallStat: //Read DMA list stall-and-notify status + case MFC_WrListStallAck: //Write DMA list stall-and-notify acknowledge + case MFC_RdAtomicStat: //Read completion status of last completed immediate MFC atomic update command + ConLog.Error("%s error: unimplemented channel (%s).", __FUNCTION__, spu_ch_name[ch]); + break; + case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); @@ -365,7 +429,7 @@ public: return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } @@ -376,11 +440,11 @@ public: { const u32 v = r._u32[3]; + ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); + switch(ch) { case SPU_WrOutIntrMbox: - ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v); - while(!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped()) { Sleep(1); @@ -388,16 +452,47 @@ public: break; case SPU_WrOutMbox: - ConLog.Warning("SPU_WrOutMbox = 0x%x", v); - while(!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) { Sleep(1); } break; + case MFC_WrTagMask: + Prxy.QueryMask.SetValue(v); + break; + + case MFC_WrTagUpdate: + Prxy.TagStatus.SetValue(Prxy.QueryMask.GetValue()); + break; + + case MFC_LSA: + MFC.LSA.SetValue(v); + break; + + case MFC_EAH: + MFC.EAH.SetValue(v); + break; + + case MFC_EAL: + MFC.EAL.SetValue(v); + break; + + case MFC_Size: + MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & 0xffff) | (v << 16)); + break; + + case MFC_TagID: + MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + break; + + case MFC_Cmd: + MFC.CMDStatus.SetValue(v); + DoMfcCmd(); + break; + default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } } @@ -411,13 +506,18 @@ public: { case SPU_RdInMbox: if(!SPU.In_MBox.Pop(v)) v = 0; - ConLog.Warning("%s: SPU_RdInMbox(0x%x).", __FUNCTION__, v); + break; + + case MFC_RdTagStat: + v = Prxy.TagStatus.GetValue(); break; default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } + + ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); } bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; } diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 24141c5ff4..148a6b15eb 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -175,17 +175,16 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) res[idx].path = "$(EmulatorDir)\\dev_hdd1\\"; res[idx].mount = "/dev_hdd1/"; res[idx].device = vfsDevice_LocalFile; - /* + idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(GameDir)"; - res[idx].mount = ""; + res[idx].path = "$(EmulatorDir)\\dev_usb000\\"; + res[idx].mount = "/dev_usb000/"; res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(GameDir)"; - res[idx].mount = "/"; + res[idx].path = "$(EmulatorDir)\\dev_usb000\\"; + res[idx].mount = "/dev_usb/"; res[idx].device = vfsDevice_LocalFile; - */ idx = res.Move(new VFSManagerEntry()); res[idx].path = "$(GameDir)"; @@ -196,6 +195,12 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) res[idx].path = ""; res[idx].mount = "/host_root/"; res[idx].device = vfsDevice_LocalFile; + + idx = res.Move(new VFSManagerEntry()); + res[idx].path = "$(GameDir)"; + res[idx].mount = "/"; + res[idx].device = vfsDevice_LocalFile; + return; } diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 21074093bd..0fbb8f2eeb 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1051,7 +1051,30 @@ void GLGSRender::ExecCMD() void GLGSRender::Flip() { - if(m_fbo.IsCreated()) + if(m_read_buffer) + { + gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); + u32 width = re(buffers[m_gcm_current_buffer].width); + u32 height = re(buffers[m_gcm_current_buffer].height); + u32 addr = GetAddress(re(buffers[m_gcm_current_buffer].offset), CELL_GCM_LOCATION_LOCAL); + + if(Memory.IsGoodAddr(addr)) + { + //TODO + //buffer rotating + static Array pixels; + pixels.SetCount(width * height * 4); + u8* src = (u8*)Memory.VirtualToRealAddr(addr); + + for(u32 y=0; y::Free(u64 addr) { if(addr == m_used_mem[i].addr) { + if(IsLocked(m_used_mem[i].addr)) return false; m_used_mem.RemoveAt(i); return true; } @@ -158,3 +159,68 @@ u8* DynamicMemoryBlockBase::GetMem(u64 addr) const assert(0); return nullptr; } + +template +bool DynamicMemoryBlockBase::IsLocked(const u64 addr) +{ + for(u32 i=0; i +void DynamicMemoryBlockBase::AppendLockedMem(u64 addr, u32 size) +{ + m_locked_mem.Move(new MemBlockInfo(addr, size)); +} + +template +bool DynamicMemoryBlockBase::Lock(u64 addr, u32 size) +{ + if(!IsInMyRange(addr, size)) + { + assert(0); + return false; + } + + if(IsMyAddress(addr) || IsMyAddress(addr + size - 1)) + { + return false; + } + + AppendLockedMem(addr, size); + + return true; +} + +template +bool DynamicMemoryBlockBase::Unlock(u64 addr , u32 size) +{ + for(u32 i=0; i size) + { + m_locked_mem.Get(i).size -= size; + } + else if(m_locked_mem.Get(i).size == size) + { + m_locked_mem.RemoveAt(i); + } + else + { + return false; + } + return true; + } + } + + return false; +} diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index d9e7f0bd4f..6fcea3252f 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -210,7 +210,7 @@ __forceinline void MemoryBlock::FastWrite128(const u64 addr, const u128 value) bool MemoryBlock::Write8(const u64 addr, const u8 value) { - if(!IsMyAddress(addr)) return false; + if(!IsMyAddress(addr) || IsLocked(addr)) return false; FastWrite8(FixAddr(addr), value); return true; @@ -218,7 +218,7 @@ bool MemoryBlock::Write8(const u64 addr, const u8 value) bool MemoryBlock::Write16(const u64 addr, const u16 value) { - if(!IsMyAddress(addr)) return false; + if(!IsMyAddress(addr) || IsLocked(addr)) return false; FastWrite16(FixAddr(addr), value); return true; @@ -226,7 +226,7 @@ bool MemoryBlock::Write16(const u64 addr, const u16 value) bool MemoryBlock::Write32(const u64 addr, const u32 value) { - if(!IsMyAddress(addr)) return false; + if(!IsMyAddress(addr) || IsLocked(addr)) return false; FastWrite32(FixAddr(addr), value); return true; @@ -234,7 +234,7 @@ bool MemoryBlock::Write32(const u64 addr, const u32 value) bool MemoryBlock::Write64(const u64 addr, const u64 value) { - if(!IsMyAddress(addr)) return false; + if(!IsMyAddress(addr) || IsLocked(addr)) return false; FastWrite64(FixAddr(addr), value); return true; @@ -242,7 +242,7 @@ bool MemoryBlock::Write64(const u64 addr, const u64 value) bool MemoryBlock::Write128(const u64 addr, const u128 value) { - if(!IsMyAddress(addr)) return false; + if(!IsMyAddress(addr) || IsLocked(addr)) return false; FastWrite128(FixAddr(addr), value); return true; diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 66123e36ca..34b1426e52 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -356,6 +356,16 @@ public: return UserMemory->Free(addr); } + bool Lock(const u64 addr, const u32 size) + { + return UserMemory->Lock(addr, size); + } + + bool Unlock(const u64 addr, const u32 size) + { + return UserMemory->Unlock(addr, size); + } + bool Map(const u64 dst_addr, const u64 src_addr, const u32 size) { if(IsGoodAddr(dst_addr) || !IsGoodAddr(src_addr)) diff --git a/rpcs3/Emu/Memory/MemoryBlock.h b/rpcs3/Emu/Memory/MemoryBlock.h index a35757468e..7d497bb1c4 100644 --- a/rpcs3/Emu/Memory/MemoryBlock.h +++ b/rpcs3/Emu/Memory/MemoryBlock.h @@ -70,6 +70,7 @@ public: virtual MemoryBlock* SetRange(const u64 start, const u32 size); virtual bool IsMyAddress(const u64 addr); + virtual bool IsLocked(const u64 addr) { return false; } __forceinline const u8 FastRead8(const u64 addr) const; __forceinline const u16 FastRead16(const u64 addr) const; @@ -106,6 +107,8 @@ public: virtual u64 Alloc(u32 size) { return 0; } virtual bool Alloc() { return false; } virtual bool Free(u64 addr) { return false; } + virtual bool Lock(u64 addr, u32 size) { return false; } + virtual bool Unlock(u64 addr, u32 size) { return false; } }; class MemoryBlockLE : public MemoryBlock @@ -171,6 +174,7 @@ template class DynamicMemoryBlockBase : public PT { Array m_used_mem; + Array m_locked_mem; u32 m_max_size; public: @@ -182,6 +186,7 @@ public: virtual bool IsInMyRange(const u64 addr); virtual bool IsInMyRange(const u64 addr, const u32 size); virtual bool IsMyAddress(const u64 addr); + virtual bool IsLocked(const u64 addr); virtual MemoryBlock* SetRange(const u64 start, const u32 size); @@ -191,11 +196,14 @@ public: virtual u64 Alloc(u32 size); virtual bool Alloc(); virtual bool Free(u64 addr); + virtual bool Lock(u64 addr, u32 size); + virtual bool Unlock(u64 addr, u32 size); virtual u8* GetMem(u64 addr) const; private: void AppendUsedMem(u64 addr, u32 size); + void AppendLockedMem(u64 addr, u32 size); }; #include "DynamicMemoryBlockBase.inl" diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 2b8c47f63e..6a9c2a9258 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -107,12 +107,14 @@ int cellGameBootCheck(mem32_t type, mem32_t attributes, mem_ptr_thddFreeSizeKB = 40000000; //40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. size->sizeKB = CELL_GAME_SIZEKB_NOTCALC; size->sysSizeKB = 0; - //TODO: dirName + Memory.WriteString(dirName.GetAddr(), dir); return CELL_OK; } @@ -129,9 +131,14 @@ int cellGameDataCheck() return CELL_OK; } -int cellGameContentPermit() +int cellGameContentPermit(mem_list_ptr_t contentInfoPath, mem_list_ptr_t usrdirPath) { - UNIMPLEMENTED_FUNC(cellGame); + cellGame.Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)", + contentInfoPath.GetAddr(), usrdirPath.GetAddr()); + + if (!contentInfoPath.IsGood() || !usrdirPath.IsGood()) + return CELL_GAME_ERROR_PARAM; + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 9c7e503c2c..0eef3bd6c8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -39,13 +39,24 @@ int cellGcmMapMainMemory(u32 address, u32 size, mem32_t offset) return CELL_OK; } +int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) +{ + cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); + //Memory.Map(io, ea, size); + //Emu.GetGSManager().GetRender().m_ioAddress = io; + Emu.GetGSManager().GetRender().m_report_main_addr = ea; + return CELL_OK; +} + int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) { - cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); + cellGcmSys.Warning("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); const u32 local_size = 0xf900000; //TODO const u32 local_addr = Memory.RSXFBMem.GetStartAddr(); + cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size); + map_offset_addr = 0; map_offset_pos = 0; current_config.ioSize = re32(ioSize); @@ -144,6 +155,7 @@ int cellGcmAddressToOffset(u32 address, mem32_t offset) } offset = address - sa; + //ConLog.Warning("Address To Offset: 0x%x -> 0x%x", address, address - sa); //Memory.Write16(map_offset_addr + map_offset_pos + 0, ea); //Memory.Write16(map_offset_addr + map_offset_pos + 2, offset); //map_offset_pos += 4; @@ -153,7 +165,7 @@ int cellGcmAddressToOffset(u32 address, mem32_t offset) int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height) { - cellGcmSys.Log("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", + cellGcmSys.Warning("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", id, offset, width ? pitch/width : pitch, width, height); if(id > 7) return CELL_EINVAL; @@ -284,6 +296,12 @@ u32 cellGcmGetTiledPitchSize(u32 size) return size; } +u32 cellGcmSetUserHandler(u32 handler) +{ + cellGcmSys.Warning("cellGcmSetUserHandler(handler=0x%x)", handler); + return handler; +} + u32 cellGcmGetDefaultCommandWordSize() { cellGcmSys.Warning("cellGcmGetDefaultCommandWordSize()"); @@ -302,14 +320,6 @@ int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize) return CELL_OK; } -int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) -{ - cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); - Memory.Map(io, ea, size); - Emu.GetGSManager().GetRender().m_report_main_addr = ea; - return CELL_OK; -} - int cellGcmUnbindZcull(u8 index) { cellGcmSys.Warning("cellGcmUnbindZcull(index=%d)", index); @@ -347,7 +357,23 @@ int cellGcmSetFlipCommandWithWaitLabel(u32 ctx, u32 id, u32 label_index, u32 lab { int res = cellGcmSetPrepareFlip(ctx, id); Memory.Write32(Memory.RSXCMDMem.GetStartAddr() + 0x10 * label_index, label_value); - return res == CELL_GCM_ERROR_FAILURE ? CELL_GCM_ERROR_FAILURE : CELL_OK; + return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; +} + +int cellGcmSetFlip(mem_ptr_t ctxt, u32 id) +{ + cellGcmSys.Log("cellGcmSetFlip(ctx=0x%x, id=0x%x)", ctxt.GetAddr(), id); + + int res = cellGcmSetPrepareFlip(ctxt, id); + return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; +} + +int cellGcmSetWaitFlip(mem_ptr_t ctxt) +{ + cellGcmSys.Log("cellGcmSetWaitFlip(ctx=0x%x)", ctxt.GetAddr()); + + GSLockCurrent lock(GS_LOCK_WAIT_FLIP); + return CELL_OK; } int cellGcmInitCursor() @@ -525,6 +551,8 @@ int cellGcmSetDebugOutputLevel (int level) default: return CELL_EINVAL; } + + return CELL_OK; } int cellGcmSetSecondVFrequency (u32 freq) @@ -541,11 +569,14 @@ int cellGcmSetSecondVFrequency (u32 freq) default: return CELL_EINVAL; } + + return CELL_OK; } void cellGcmSys_init() { cellGcmSys.AddFunc(0x055bd74d, cellGcmGetTiledPitchSize); + cellGcmSys.AddFunc(0x06edea9e, cellGcmSetUserHandler); cellGcmSys.AddFunc(0x15bae46b, cellGcmInit); cellGcmSys.AddFunc(0x21397818, cellGcmSetFlipCommand); cellGcmSys.AddFunc(0x21ac3697, cellGcmAddressToOffset); @@ -589,4 +620,6 @@ void cellGcmSys_init() cellGcmSys.AddFunc(0x8572bce2, cellGcmGetReportDataAddressLocation); cellGcmSys.AddFunc(0x51c9d62b, cellGcmSetDebugOutputLevel); cellGcmSys.AddFunc(0x4d7ce993, cellGcmSetSecondVFrequency); + cellGcmSys.AddFunc(0xdc09357e, cellGcmSetFlip); + cellGcmSys.AddFunc(0x983fb9aa, cellGcmSetWaitFlip); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index 700f51ef03..55700fd4fc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -600,6 +600,7 @@ int cellRescGetBufferSize(mem32_t colorBuffers, mem32_t vertexArray, mem32_t fra colorBuffersSize = s_rescInternalInstance->m_dstBufInterval * GetNumColorBuffers(); vertexArraySize = 0x180; //sizeof(RescVertex_t) * VERTEX_NUMBER_RESERVED; //fragmentUcodeSize = m_pCFragmentShader->GetUcodeSize(); + fragmentUcodeSize = 0x300; } else //CELL_RESC_CONSTANT_VRAM { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 46ff1d3965..e3bc93c238 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -386,17 +386,32 @@ int cellVideoOutGetConfiguration(u32 videoOut, u32 config_addr, u32 option_addr) int cellVideoOutGetDeviceInfo(u32 videoOut, u32 deviceIndex, mem_ptr_t info) { - cellSysutil.Error("Unimplemented function: cellVideoOutGetDeviceInfo(videoOut=%u, deviceIndex=%u, info_addr=0x%x)", + cellSysutil.Warning("cellVideoOutGetDeviceInfo(videoOut=%u, deviceIndex=%u, info_addr=0x%x)", videoOut, deviceIndex, info.GetAddr()); if(deviceIndex) return CELL_VIDEO_OUT_ERROR_DEVICE_NOT_FOUND; + // Use standard dummy values for now. info->portType = CELL_VIDEO_OUT_PORT_HDMI; info->colorSpace = Emu.GetGSManager().GetColorSpace(); - //info->latency = ; - //info->availableModeCount = ; + info->latency = 1000; + info->availableModeCount = 1; info->state = CELL_VIDEO_OUT_DEVICE_STATE_AVAILABLE; - //info->rgbOutputRange = ; + info->rgbOutputRange = 1; + info->colorInfo.blueX = 0xFFFF; + info->colorInfo.blueY = 0xFFFF; + info->colorInfo.greenX = 0xFFFF; + info->colorInfo.greenY = 0xFFFF; + info->colorInfo.redX = 0xFFFF; + info->colorInfo.redY = 0xFFFF; + info->colorInfo.whiteX = 0xFFFF; + info->colorInfo.whiteY = 0xFFFF; + info->colorInfo.gamma = 100; + info->availableModes[0].aspect = 0; + info->availableModes[0].conversion = 0; + info->availableModes[0].refreshRates = 0xF; + info->availableModes[0].resolutionId = 1; + info->availableModes[0].scanMode = 0; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index dd53ba1d89..424b0139e1 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -28,9 +28,9 @@ int sys_spu_printf_initialize(int a1, int a2, int a3, int a4, int a5) return 0; } -s64 sys_prx_register_library() +s64 sys_prx_register_library(u32 lib_addr) { - sysPrxForUser.Error("sys_prx_register_library()"); + sysPrxForUser.Error("sys_prx_register_library(lib_addr=0x%x)", lib_addr); return 0; } @@ -79,4 +79,7 @@ void sysPrxForUser_init() //sysPrxForUser.AddFunc(0xaede4b03, sys_heap_free); //sysPrxForUser.AddFunc(0x8a561d92, sys_heap_delete_heap); sysPrxForUser.AddFunc(0xb2fcf2c8, sys_heap_create_heap); + + sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory); + sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory); } diff --git a/rpcs3/Emu/SysCalls/Modules/sys_io.cpp b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp index db6e727c0e..9485b6f440 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_io.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp @@ -13,6 +13,7 @@ void sys_io_init() sys_io.AddFunc(0x8b72cda1, cellPadGetData); sys_io.AddFunc(0x6bc09c61, cellPadGetDataExtra); sys_io.AddFunc(0xf65544ee, cellPadSetActDirect); + sys_io.AddFunc(0x3aaad464, cellPadGetInfo); sys_io.AddFunc(0xa703a51d, cellPadGetInfo2); sys_io.AddFunc(0x578e3c98, cellPadSetPortSetting); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 6cbc20a907..686e5e78b7 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -52,8 +52,8 @@ static func_caller* sc_table[1024] = null_func, //77 (0x04D) null_func, //78 (0x04E) null_func, //79 (0x04F) - null_func, null_func, null_func, null_func, null_func, //84 - null_func, null_func, null_func, null_func, null_func, //89 + null_func, null_func, bind_func(sys_event_flag_create), bind_func(sys_event_flag_destroy), null_func, //84 + bind_func(sys_event_flag_wait), bind_func(sys_event_flag_trywait), bind_func(sys_event_flag_set), null_func, null_func, //89 bind_func(sys_semaphore_create), //90 (0x05A) bind_func(sys_semaphore_destroy), //91 (0x05B) bind_func(sys_semaphore_wait), //92 (0x05C) @@ -76,7 +76,7 @@ static func_caller* sc_table[1024] = bind_func(sys_cond_signal_all), //109 (0x06D) null_func, null_func, null_func, null_func, //113 (0x071) bind_func(sys_semaphore_get_value), //114 (0x072) - null_func, null_func, null_func, null_func, null_func, //119 (0x077) + null_func, null_func, null_func, bind_func(sys_event_flag_clear), null_func, //119 (0x077) bind_func(sys_rwlock_create), //120 (0x078) bind_func(sys_rwlock_destroy), //121 (0x079) bind_func(sys_rwlock_rlock), //122 (0x07A) @@ -87,8 +87,8 @@ static func_caller* sc_table[1024] = 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, null_func, null_func, bind_func(sys_event_port_create), //134 - null_func, bind_func(sys_event_port_connect_local), null_func, bind_func(sys_event_port_send), null_func, //139 + bind_func(sys_event_queue_receive), null_func, bind_func(sys_event_flag_cancel), null_func, 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 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 @@ -121,15 +121,15 @@ static func_caller* sc_table[1024] = null_func, null_func, null_func, null_func, null_func, //289 null_func, null_func, null_func, null_func, null_func, //294 null_func, null_func, null_func, null_func, null_func, //299 - null_func, null_func, null_func, null_func, null_func, //304 - null_func, null_func, null_func, null_func, null_func, //309 - null_func, null_func, null_func, null_func, null_func, //314 + bind_func(sys_vm_memory_map), bind_func(sys_vm_unmap), bind_func(sys_vm_append_memory), bind_func(sys_vm_return_memory), bind_func(sys_vm_lock), //304 + bind_func(sys_vm_unlock), bind_func(sys_vm_touch), bind_func(sys_vm_flush), bind_func(sys_vm_invalidate), bind_func(sys_vm_store), //309 + bind_func(sys_vm_sync), bind_func(sys_vm_test), bind_func(sys_vm_get_statistics), null_func, null_func, //314 null_func, null_func, null_func, null_func, null_func, //319 null_func, null_func, null_func, null_func, bind_func(sys_memory_container_create), //324 bind_func(sys_memory_container_destroy), null_func, null_func, null_func, null_func, //329 bind_func(sys_mmapper_allocate_address), null_func, null_func, null_func, null_func, //334 null_func, null_func, null_func, null_func, null_func, //339 - null_func, null_func, null_func, null_func, null_func, //344 + null_func, bind_func(sys_memory_container_create), bind_func(sys_memory_container_destroy), null_func, null_func, //344 null_func, null_func, null_func, bind_func(sys_memory_allocate), bind_func(sys_memory_free), //349 null_func, null_func, bind_func(sys_memory_get_user_memory_size), null_func, null_func, //354 null_func, null_func, null_func, null_func, null_func, //359 diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 20c54bb211..7dfb90e6cf 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -122,6 +122,14 @@ extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_add u32 data, u32 data_size, int prio, u64 flags ); //sys_event +extern int sys_event_flag_create(u32 eflag_id_addr, u32 attr_addr, u64 init); +extern int sys_event_flag_destroy(u32 eflag_id); +extern int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr, u32 timeout); +extern int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr); +extern int sys_event_flag_set(u32 eflag_id, u64 bitptn); +extern int sys_event_flag_clear(u32 eflag_id, u64 bitptn); +extern int sys_event_flag_cancel(u32 eflag_id, u32 num_addr); +extern int sys_event_flag_get(u32 eflag_id, u32 flag_addr); extern int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, 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); @@ -183,6 +191,21 @@ extern int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 extern int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr); extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags); +//vm +extern int sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr); +extern int sys_vm_unmap(u32 addr); +extern int sys_vm_append_memory(u32 addr, u32 size); +extern int sys_vm_return_memory(u32 addr, u32 size); +extern int sys_vm_lock(u32 addr, u32 size); +extern int sys_vm_unlock(u32 addr, u32 size); +extern int sys_vm_touch(u32 addr, u32 size); +extern int sys_vm_flush(u32 addr, u32 size); +extern int sys_vm_invalidate(u32 addr, u32 size); +extern int sys_vm_store(u32 addr, u32 size); +extern int sys_vm_sync(u32 addr, u32 size); +extern int sys_vm_test(u32 addr, u32 size, u32 result_addr); +extern int sys_vm_get_statistics(u32 addr, u32 stat_addr); + //cellFs extern int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size); extern int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread); @@ -210,9 +233,6 @@ extern int cellVideoOutGetConfiguration(u32 videoOut, u32 config_addr, u32 optio extern int cellVideoOutGetNumberOfDevice(u32 videoOut); extern int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option); -//cellMsgDialog -extern int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 userData, u32 extParam); - //cellPad extern int cellPadInit(u32 max_connect); extern int cellPadEnd(); @@ -220,6 +240,7 @@ extern int cellPadClearBuf(u32 port_no); extern int cellPadGetData(u32 port_no, u32 data_addr); extern int cellPadGetDataExtra(u32 port_no, u32 device_type_addr, u32 data_addr); extern int cellPadSetActDirect(u32 port_no, u32 param_addr); +extern int cellPadGetInfo(u32 info_addr); extern int cellPadGetInfo2(u32 info_addr); extern int cellPadSetPortSetting(u32 port_no, u32 port_setting); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index 28044cdc06..f423c778fa 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -5,6 +5,103 @@ SysCallBase sys_event("sys_event"); +int sys_event_flag_create(u32 eflag_id_addr, u32 attr_addr, u64 init) +{ + sys_event.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)", eflag_id_addr, attr_addr, init); + + if(!Memory.IsGoodAddr(eflag_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_flag_attr))) + { + return CELL_EFAULT; + } + + sys_event_flag_attr attr = (sys_event_flag_attr&)Memory[attr_addr]; + attr.protocol = re(attr.protocol); + attr.pshared = re(attr.pshared); + attr.ipc_key = re(attr.ipc_key); + attr.flags = re(attr.flags); + attr.type = re(attr.type); + + sys_event.Warning("name = %s", attr.name); + sys_event.Warning("type = %d", attr.type); + + Memory.Write32(eflag_id_addr, sys_event.GetNewId(new event_flag(init, attr))); + + return CELL_OK; +} + +int sys_event_flag_destroy(u32 eflag_id) +{ + sys_event.Warning("sys_event_flag_destroy(eflag_id=0x%x)", eflag_id); + + if(!sys_event.CheckId(eflag_id)) return CELL_ESRCH; + + Emu.GetIdManager().RemoveID(eflag_id); + + return CELL_OK; +} + +int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr, u32 timeout) +{ + sys_event.Warning("Unimplemented function: sys_event_flag_wait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=0x%x)" + , eflag_id, bitptn, mode, result_addr, timeout); + return CELL_OK; +} + +int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, u32 result_addr) +{ + sys_event.Warning("Unimplemented function: sys_event_flag_trywait(eflag_id=0x%x, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)" + , eflag_id, bitptn, mode, result_addr); + return CELL_OK; +} + +int sys_event_flag_set(u32 eflag_id, u64 bitptn) +{ + sys_event.Warning("sys_event_flag_set(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn); + + event_flag* event_flag_data = nullptr; + if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH; + + event_flag_data->pattern |= bitptn; + + return CELL_OK; +} + +int sys_event_flag_clear(u32 eflag_id, u64 bitptn) +{ + sys_event.Warning("sys_event_flag_clear(eflag_id=0x%x, bitptn=0x%llx)", eflag_id, bitptn); + + event_flag* event_flag_data = nullptr; + if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH; + + event_flag_data->pattern &= bitptn; + + return CELL_OK; +} + +int sys_event_flag_cancel(u32 eflag_id, u32 num_addr) +{ + sys_event.Warning("Unimplemented function: sys_event_flag_cancel(eflag_id=0x%x, num_addr=0x%x)" + , eflag_id, num_addr); + return CELL_OK; +} + +int sys_event_flag_get(u32 eflag_id, u32 flag_addr) +{ + sys_event.Warning("sys_event_flag_get(eflag_id=0x%x, flag_addr=0x%x)", eflag_id, flag_addr); + + if(!Memory.IsGoodAddr(flag_addr, 4)) + { + return CELL_EFAULT; + } + + event_flag* event_flag_data = nullptr; + if(!sys_event.CheckId(eflag_id, event_flag_data)) return CELL_ESRCH; + + Memory.Write64(flag_addr, event_flag_data->pattern); + + return CELL_OK; +} + //128 int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 65e98f195c..be8a6ecb5d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -1,26 +1,9 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" +#include "SC_Memory.h" SysCallBase sc_mem("memory"); -enum -{ - SYS_MEMORY_PAGE_SIZE_1M = 0x400, - SYS_MEMORY_PAGE_SIZE_64K = 0x200, -}; - -struct MemoryContainerInfo -{ - u64 addr; - u32 size; - - MemoryContainerInfo(u64 addr, u32 size) - : addr(addr) - , size(size) - { - } -}; - int sys_memory_container_create(u32 cid_addr, u32 yield_size) { sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size); @@ -93,29 +76,32 @@ int sys_memory_free(u32 start_addr) return CELL_OK; } -struct mmapper_info -{ - u64 addr; - u32 size; - u32 flags; - - mmapper_info(u64 _addr, u32 _size, u32 _flags) - : addr(_addr) - , size(_size) - , flags(_flags) - { - } - - mmapper_info() - { - } -}; - int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr) { sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", size, flags, alignment, alloc_addr); - Memory.Write32(alloc_addr, Memory.Alloc(size, 4)); + if(!Memory.IsGoodAddr(alloc_addr)) return CELL_EFAULT; + + if(!alignment) + alignment = 1; + + u32 addr; + + switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) + { + default: + case SYS_MEMORY_PAGE_SIZE_1M: + if(Memory.AlignAddr(size, alignment) & 0xfffff) return CELL_EALIGN; + addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(Memory.AlignAddr(size, alignment) & 0xffff) return CELL_EALIGN; + addr = Memory.Alloc(size, 0x10000); + break; + } + + Memory.Write32(alloc_addr, addr); return CELL_OK; } @@ -126,7 +112,22 @@ int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr) if(!Memory.IsGoodAddr(mem_id_addr)) return CELL_EFAULT; - u64 addr = Memory.Alloc(size, 1); + u32 addr; + switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) + { + case SYS_MEMORY_PAGE_SIZE_1M: + if(size & 0xfffff) return CELL_EALIGN; + addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(size & 0xffff) return CELL_EALIGN; + addr = Memory.Alloc(size, 0x10000); + break; + + default: + return CELL_EINVAL; + } if(!addr) return CELL_ENOMEM; @@ -147,17 +148,10 @@ int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) { sc_mem.Error("sys_mmapper_map_memory failed!"); } - //Memory.MemoryBlocks.Add((new MemoryBlock())->SetRange(start_addr, info->size)); return CELL_OK; } -struct sys_memory_info -{ - u32 total_user_memory; - u32 available_user_memory; -}; - int sys_memory_get_user_memory_size(u32 mem_info_addr) { sys_memory_info info; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.h b/rpcs3/Emu/SysCalls/lv2/SC_Memory.h new file mode 100644 index 0000000000..88837dcb4e --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.h @@ -0,0 +1,59 @@ +#pragma once + +#define SYS_MEMORY_CONTAINER_ID_INVALID 0xFFFFFFFF +#define SYS_VM_TEST_INVALID 0x0000ULL +#define SYS_VM_TEST_UNUSED 0x0001ULL +#define SYS_VM_TEST_ALLOCATED 0x0002ULL +#define SYS_VM_TEST_STORED 0x0004ULL + +enum +{ + SYS_MEMORY_PAGE_SIZE_1M = 0x400, + SYS_MEMORY_PAGE_SIZE_64K = 0x200, +}; + +struct MemoryContainerInfo +{ + u64 addr; + u32 size; + + MemoryContainerInfo(u64 addr, u32 size) + : addr(addr) + , size(size) + { + } +}; + +struct mmapper_info +{ + u64 addr; + u32 size; + u32 flags; + + mmapper_info(u64 _addr, u32 _size, u32 _flags) + : addr(_addr) + , size(_size) + , flags(_flags) + { + } + + mmapper_info() + { + } +}; + +struct sys_memory_info +{ + u32 total_user_memory; + u32 available_user_memory; +}; + +struct sys_vm_statistics { + u64 vm_crash_ppu; + u64 vm_crash_spu; + u64 vm_read; + u64 vm_write; + u32 physical_mem_size; + u32 physical_mem_used; + u64 timestamp; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index a052cd041b..7ff708405c 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -24,6 +24,16 @@ struct CellPadData u16 button[CELL_PAD_MAX_CODES]; }; +struct CellPadInfo +{ + u32 max_connect; + u32 now_connect; + u32 system_info; + u16 vendor_id[CELL_MAX_PADS]; + u16 product_id[CELL_MAX_PADS]; + u8 status[CELL_MAX_PADS]; +}; + struct CellPadInfo2 { u32 max_connect; @@ -142,6 +152,35 @@ int cellPadSetActDirect(u32 port_no, u32 param_addr) return CELL_OK; } +int cellPadGetInfo(u32 info_addr) +{ + sys_io.Log("cellPadGetInfo(info_addr=0x%x)", info_addr); + if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; + + CellPadInfo info; + memset(&info, 0, sizeof(CellPadInfo)); + + const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); + info.max_connect = re(rinfo.max_connect); + info.now_connect = re(rinfo.now_connect); + info.system_info = re(rinfo.system_info); + + const Array& pads = Emu.GetPadManager().GetPads(); + + for(u32 i=0; i= pads.GetCount()) break; + + info.status[i] = re(pads[i].m_port_status); + info.product_id[i] = const_se_t::value; + info.vendor_id[i] = const_se_t::value; + } + + Memory.WriteData(info_addr, info); + + return CELL_OK; +} + int cellPadGetInfo2(u32 info_addr) { sys_io.Log("cellPadGetInfo2(info_addr=0x%x)", info_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_VM.cpp b/rpcs3/Emu/SysCalls/lv2/SC_VM.cpp new file mode 100644 index 0000000000..307dcaf75c --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_VM.cpp @@ -0,0 +1,286 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "SC_Memory.h" + +SysCallBase sc_vm("vm"); +MemoryContainerInfo* current_ct; + +int sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr) +{ + sc_vm.Warning("sys_vm_memory_map(vsize=0x%x,psize=0x%x,cidr=0x%x,flags=0x%llx,policy=0x%llx,addr=0x%x)", + vsize, psize, cid, flag, policy, addr); + + // Check output address. + if(!Memory.IsGoodAddr(addr, 4)) + { + return CELL_EFAULT; + } + + // Check virtual size. + if((vsize < (0x100000 * 32)) || (vsize > (0x100000 * 256))) + { + return CELL_EINVAL; + } + + // Check physical size. + if(psize > (0x100000 * 256)) + { + return CELL_ENOMEM; + } + + // If container ID is SYS_MEMORY_CONTAINER_ID_INVALID, allocate directly. + if(cid == SYS_MEMORY_CONTAINER_ID_INVALID) + { + u32 new_addr; + switch(flag) + { + case SYS_MEMORY_PAGE_SIZE_1M: + new_addr = Memory.Alloc(psize, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + new_addr = Memory.Alloc(psize, 0x10000); + break; + + default: return CELL_EINVAL; + } + + if(!new_addr) return CELL_ENOMEM; + + // Create a new MemoryContainerInfo to act as default container with vsize. + current_ct = new MemoryContainerInfo(new_addr, vsize); + } + else + { + // Check memory container. + MemoryContainerInfo* ct; + if(!sc_vm.CheckId(cid, ct)) return CELL_ESRCH; + + current_ct = ct; + } + + // Write a pointer for the allocated memory. + Memory.Write32(addr, current_ct->addr); + + return CELL_OK; +} + +int sys_vm_unmap(u32 addr) +{ + sc_vm.Warning("sys_vm_unmap(addr=0x%x)", addr); + + // Simply free the memory to unmap. + if(!Memory.Free(addr)) return CELL_EINVAL; + + return CELL_OK; +} + +int sys_vm_append_memory(u32 addr, u32 size) +{ + sc_vm.Warning("sys_vm_append_memory(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (size <= 0)) + { + return CELL_EINVAL; + } + + // Total memory size must not be superior to 256MB. + if((current_ct->size + size) > (0x100000 * 256)) + { + return CELL_ENOMEM; + } + + // The size is added to the virtual size, which should be inferior to the physical size allocated. + current_ct->size += size; + + return CELL_OK; +} + +int sys_vm_return_memory(u32 addr, u32 size) +{ + sc_vm.Warning("sys_vm_return_memory(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (size <= 0)) + { + return CELL_EINVAL; + } + + // The memory size to return should not be superior to the virtual size in use minus 1MB. + if((current_ct->size - size - 0x100000) < 0) + { + return CELL_EBUSY; + } + + // The size is returned to physical memory and is subtracted to the virtual size. + current_ct->size -= size; + + return CELL_OK; +} + +int sys_vm_lock(u32 addr, u32 size) +{ + sc_vm.Warning("sys_vm_lock(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // The memory size to return should not be superior to the virtual size to lock minus 1MB. + if((current_ct->size - size - 0x100000) < 0) + { + return CELL_EBUSY; + } + + // The locked memory area keeps allocated and unchanged until sys_vm_unlocked is called. + Memory.Lock(addr, size); + + return CELL_OK; +} + +int sys_vm_unlock(u32 addr, u32 size) +{ + sc_vm.Warning("sys_vm_unlock(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + Memory.Unlock(addr, size); + + return CELL_OK; +} + +int sys_vm_touch(u32 addr, u32 size) +{ + sc_vm.Warning("Unimplemented function: sys_vm_touch(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_touch allocates physical memory for a virtual memory address. + // This function is asynchronous, so it may not complete immediately. + + return CELL_OK; +} + +int sys_vm_flush(u32 addr, u32 size) +{ + sc_vm.Warning("Unimplemented function: sys_vm_flush(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_flush frees physical memory for a virtual memory address and creates a backup if the memory area is dirty. + // This function is asynchronous, so it may not complete immediately. + + return CELL_OK; +} + +int sys_vm_invalidate(u32 addr, u32 size) +{ + sc_vm.Warning("Unimplemented function: sys_vm_invalidate(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_invalidate frees physical memory for a virtual memory address. + // This function is asynchronous, so it may not complete immediately. + + return CELL_OK; +} + +int sys_vm_store(u32 addr, u32 size) +{ + sc_vm.Warning("Unimplemented function: sys_vm_store(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_store creates a backup for a dirty virtual memory area and marks it as clean. + // This function is asynchronous, so it may not complete immediately. + + return CELL_OK; +} + +int sys_vm_sync(u32 addr, u32 size) +{ + sc_vm.Warning("Unimplemented function: sys_vm_sync(addr=0x%x,size=0x%x)", addr, size); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_sync stalls execution until all asynchronous vm calls finish. + + return CELL_OK; +} + +int sys_vm_test(u32 addr, u32 size, u32 result_addr) +{ + sc_vm.Warning("Unimplemented function: sys_vm_test(addr=0x%x,size=0x%x,result_addr=0x%x)", addr, size, result_addr); + + // Check address and size. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr) || (current_ct->size < size) || (size <= 0)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_test checks the state of a portion of the virtual memory area. + + // Faking. + Memory.Write64(result_addr, SYS_VM_TEST_ALLOCATED); + + return CELL_OK; +} + +int sys_vm_get_statistics(u32 addr, u32 stat_addr) +{ + sc_vm.Warning("Unimplemented function: sys_vm_get_statistics(addr=0x%x,stat_addr=0x%x)", addr, stat_addr); + + // Check address. + if(!Memory.IsGoodAddr(addr, 4) || (current_ct->addr != addr)) + { + return CELL_EINVAL; + } + + // TODO + // sys_vm_get_statistics collects virtual memory management stats. + + sys_vm_statistics stats; + stats.physical_mem_size = current_ct->size; // Total physical memory allocated for the virtual memory area. + stats.physical_mem_used = 0; // Physical memory in use by the virtual memory area. + stats.timestamp = 0; // Current time. + stats.vm_crash_ppu = 0; // Number of bad virtual memory accesses from a PPU thread. + stats.vm_crash_spu = 0; // Number of bad virtual memory accesses from a SPU thread. + stats.vm_read = 0; // Number of virtual memory backup reading operations. + stats.vm_write = 0; // Number of virtual memory backup writing operations. + Memory.WriteData(stat_addr, stats); // Faking. + + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index d81b93dcae..f3903bcbea 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -6,6 +6,10 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" #include "Emu/Cell/PPUInstrTable.h" + +#include "scetool/scetool.h" + +#include "Loader/SELF.h" #include #include using namespace PPU_instr; @@ -21,7 +25,7 @@ ModuleInitializer::ModuleInitializer() Emulator::Emulator() : m_status(Stopped) , m_mode(DisAsm) - , m_dbg_console(NULL) + , m_dbg_console(nullptr) , m_rsx_callback(0) { } @@ -43,6 +47,11 @@ void Emulator::SetPath(const wxString& path, const wxString& elf_path) m_elf_path = elf_path; } +void Emulator::SetTitleID(const wxString& id) +{ + m_title_id = id; +} + void Emulator::CheckStatus() { ArrayF& threads = GetCPU().GetThreads(); @@ -80,16 +89,126 @@ void Emulator::CheckStatus() } } +bool Emulator::IsSelf(const std::string& path) +{ + vfsLocalFile f(path); + + if(!f.IsOpened()) + return false; + + SceHeader hdr; + hdr.Load(f); + + return hdr.CheckMagic(); +} + +bool Emulator::DecryptSelf(const std::string& elf, const std::string& self) +{ + // Check if the data really needs to be decrypted. + wxFile f(self.c_str()); + + if(!f.IsOpened()) + { + ConLog.Error("Could not open SELF file! (%s)", self.c_str()); + return false; + } + + // Get the key version. + f.Seek(0x08); + be_t key_version; + f.Read(&key_version, sizeof(key_version)); + + if(key_version.ToBE() == const_se_t::value) + { + ConLog.Warning("Debug SELF detected! Removing fake header..."); + + // Get the real elf offset. + f.Seek(0x10); + be_t elf_offset; + f.Read(&elf_offset, sizeof(elf_offset)); + + // Start at the real elf offset. + f.Seek(elf_offset); + + wxFile out(elf.c_str(), wxFile::write); + + if(!out.IsOpened()) + { + ConLog.Error("Could not create ELF file! (%s)", elf.c_str()); + return false; + } + + // Copy the data. + char buf[2048]; + while (ssize_t size = f.Read(buf, 2048)) + out.Write(buf, size); + } + else + { + if (!scetool_decrypt((scetool::s8 *)self.c_str(), (scetool::s8 *)elf.c_str())) + { + ConLog.Write("SELF: Could not decrypt file"); + return false; + } + } + + return true; +} + +bool Emulator::BootGame(const std::string& path) +{ + static const char* elf_path[6] = + { + "\\PS3_GAME\\USRDIR\\BOOT.BIN", + "\\USRDIR\\BOOT.BIN", + "\\BOOT.BIN", + "\\PS3_GAME\\USRDIR\\EBOOT.BIN", + "\\USRDIR\\EBOOT.BIN", + "\\EBOOT.BIN", + }; + + for(int i=0; i OpenFile(const wxString& path, vfsOpenMode mode = vfsRead) { @@ -144,6 +146,10 @@ public: void CheckStatus(); + bool IsSelf(const std::string& path); + bool DecryptSelf(const std::string& elf, const std::string& self); + bool BootGame(const std::string& path); + void Load(); void Run(); void Pause(); diff --git a/rpcs3/Emu/event.h b/rpcs3/Emu/event.h index ed4084bc32..8c5d94c360 100644 --- a/rpcs3/Emu/event.h +++ b/rpcs3/Emu/event.h @@ -1,5 +1,27 @@ #pragma once +struct sys_event_flag_attr +{ + u32 protocol; + u32 pshared; + u64 ipc_key; + int flags; + int type; + char name[8]; +}; + +struct event_flag +{ + sys_event_flag_attr attr; + u64 pattern; + + event_flag(u64 pattern, sys_event_flag_attr attr) + : pattern(pattern) + , attr(attr) + { + } +}; + struct sys_event_queue_attr { u32 attr_protocol; diff --git a/rpcs3/Gui/GameViewer.cpp b/rpcs3/Gui/GameViewer.cpp index 14dc7ad303..a040eb9f9a 100644 --- a/rpcs3/Gui/GameViewer.cpp +++ b/rpcs3/Gui/GameViewer.cpp @@ -8,7 +8,7 @@ GameViewer::GameViewer(wxWindow* parent) : wxListView(parent) LoadSettings(); m_columns.Show(this); - m_path = wxGetCwd(); //TODO + m_path = wxGetCwd() + "\\dev_hdd0\\game\\"; //TODO Connect(GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(GameViewer::DClick)); @@ -34,16 +34,13 @@ void GameViewer::LoadGames() if(!dir.HasSubDirs()) return; wxString buf; - if(!dir.GetFirst(&buf)) return; - if(wxDirExists(buf)) m_games.Add(buf); - - for(;;) + for(bool ok = dir.GetFirst(&buf); ok; ok = dir.GetNext(&buf)) { - if(!dir.GetNext(&buf)) break; - if(wxDirExists(buf)) m_games.Add(buf); + if(wxDirExists(m_path + buf)) + m_games.Add(buf); } - //ConLog.Write("path: %s", m_path); + //ConLog.Write("path: %s", m_path.c_str()); //ConLog.Write("folders count: %d", m_games.GetCount()); } @@ -52,7 +49,7 @@ void GameViewer::LoadPSF() m_game_data.Clear(); for(uint i=0; i - -#include "scetool/scetool.cpp" -#include "unpkg/unpkg.c" - -BEGIN_EVENT_TABLE(MainFrame, FrameBase) - EVT_CLOSE(MainFrame::OnQuit) -END_EVENT_TABLE() - -enum IDs -{ - id_boot_elf = 0x555, - id_boot_self, - id_boot_game, - id_boot_pkg, - id_sys_pause, - id_sys_stop, - id_sys_send_open_menu, - id_sys_send_exit, - id_config_emu, - id_config_vfs_manager, - id_config_vhdd_manager, - id_tools_compiler, - id_tools_memory_viewer, - id_help_about, - id_update_dbg, -}; - -wxString GetPaneName() -{ - static int pane_num = 0; - - return wxString::Format("Pane_%d", pane_num++); -} - -MainFrame::MainFrame() - : FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(800, 600)) - , m_aui_mgr(this) - , m_sys_menu_opened(false) -{ - -#ifdef _DEBUG - SetLabel(wxString::Format(_PRGNAME_ " git-" RPCS3_GIT_VERSION)); -#else - SetLabel(wxString::Format(_PRGNAME_ " " _PRGVER_)); -#endif - - wxMenuBar& menubar(*new wxMenuBar()); - - wxMenu& menu_boot(*new wxMenu()); - wxMenu& menu_sys(*new wxMenu()); - wxMenu& menu_conf(*new wxMenu()); - wxMenu& menu_tools(*new wxMenu()); - wxMenu& menu_help(*new wxMenu()); - - menubar.Append(&menu_boot, "Boot"); - menubar.Append(&menu_sys, "System"); - menubar.Append(&menu_conf, "Config"); - menubar.Append(&menu_tools, "Tools"); - menubar.Append(&menu_help, "Help"); - - menu_boot.Append(id_boot_game, "Boot game"); - menu_boot.Append(id_boot_pkg, "Install PKG"); - menu_boot.AppendSeparator(); - menu_boot.Append(id_boot_elf, "Boot ELF"); - menu_boot.Append(id_boot_self, "Boot SELF"); - - menu_sys.Append(id_sys_pause, "Pause")->Enable(false); - menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false); - menu_sys.AppendSeparator(); - menu_sys.Append(id_sys_send_open_menu, "Send open system menu cmd")->Enable(false); - menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false); - - menu_conf.Append(id_config_emu, "Settings"); - menu_conf.AppendSeparator(); - menu_conf.Append(id_config_vfs_manager, "Virtual File System Manager"); - menu_conf.Append(id_config_vhdd_manager, "Virtual HDD Manager"); - - menu_tools.Append(id_tools_compiler, "ELF Compiler"); - menu_tools.Append(id_tools_memory_viewer, "Memory Viewer"); - - menu_help.Append(id_help_about, "About..."); - - SetMenuBar(&menubar); - - m_game_viewer = new GameViewer(this); - AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM); - - Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) ); - Connect( id_boot_pkg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootPkg) ); - Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) ); - Connect( id_boot_self, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootSelf) ); - - Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) ); - Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) ); - Connect( id_sys_send_open_menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendOpenCloseSysMenu) ); - Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) ); - - Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); - Connect( id_config_vfs_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVFS) ); - Connect( id_config_vhdd_manager,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVHDD) ); - - Connect( id_tools_compiler, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenELFCompiler)); - Connect( id_tools_memory_viewer,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenMemoryViewer)); - - Connect( id_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::AboutDialogHandler) ); - - Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) ); - - m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); - m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this); -} - -MainFrame::~MainFrame() -{ - m_aui_mgr.UnInit(); -} - -void MainFrame::AddPane(wxWindow* wind, const wxString& caption, int flags) -{ - wind->SetSize(-1, 300); - m_aui_mgr.AddPane(wind, wxAuiPaneInfo().Name(GetPaneName()).Caption(caption).Direction(flags).CloseButton(false).MaximizeButton()); -} - -void MainFrame::DoSettings(bool load) -{ - IniEntry ini; - ini.Init("Settings", "MainFrameAui"); - - if(load) - { - m_aui_mgr.LoadPerspective(ini.LoadValue(m_aui_mgr.SavePerspective())); - } - else - { - ini.SaveValue(m_aui_mgr.SavePerspective()); - } -} - -void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) -{ - bool stopped = false; - - if(Emu.IsRunning()) - { - Emu.Pause(); - stopped = true; - } - - wxDirDialog ctrl(this, L"Select game folder", wxEmptyString); - - if(ctrl.ShowModal() == wxID_CANCEL) - { - if(stopped) Emu.Resume(); - return; - } - - Emu.Stop(); - - wxString elf[6] = { - "\\PS3_GAME\\USRDIR\\BOOT.BIN", - "\\USRDIR\\BOOT.BIN", - "\\BOOT.BIN", - "\\PS3_GAME\\USRDIR\\EBOOT.BIN", - "\\USRDIR\\EBOOT.BIN", - "\\EBOOT.BIN" - }; - - for(int i=0;i<6;i++) - { - if(wxFile::Access(ctrl.GetPath() + elf[i], wxFile::read)) - { - ConLog.Write("SELF: booting..."); - - Emu.Stop(); - - wxString fileIn = ctrl.GetPath()+elf[i]; - wxString fileOut = (ctrl.GetPath()+elf[i])+".elf"; - - // Check if the data really needs to be decrypted. - if(!wxFileExists(fileIn)) - { - ConLog.Error("Could not open game boot file!"); - return; - } - - wxFile f(fileIn); - // Get the key version. - f.Seek(0x08); - be_t key_version; - f.Read(&key_version, sizeof(key_version)); - - if(key_version.ToBE() == const_se_t::value) - { - ConLog.Warning("Debug SELF detected! Removing fake header..."); - - // Get the real elf offset. - f.Seek(0x10); - be_t elf_offset; - f.Read(&elf_offset, sizeof(elf_offset)); - - // Start at the real elf offset. - f.Seek(elf_offset); - - wxFile out(fileOut, wxFile::write); - - // Copy the data. - char buf[2048]; - while (ssize_t size = f.Read(buf, 2048)) - out.Write(buf, size); - } - else - { - if (!scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str())) - { - ConLog.Write("Could not decrypt game boot file"); - return; - } - } - - f.Close(); - - Emu.SetPath(fileOut); - Emu.Load(); - if (!wxRemoveFile(fileOut)) - ConLog.Warning("Could not delete the decrypted ELF file"); - - ConLog.Write("Game: boot done."); - return; - } - } - - ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().mb_str()); - return; -} - - -void MainFrame::BootPkg(wxCommandEvent& WXUNUSED(event)) -{ - bool stopped = false; - - if(Emu.IsRunning()) - { - Emu.Pause(); - stopped = true; - } - - wxFileDialog ctrl (this, L"Select PKG", wxEmptyString, wxEmptyString, "*.*", - wxFD_OPEN | wxFD_FILE_MUST_EXIST); - - if(ctrl.ShowModal() == wxID_CANCEL) - { - if(stopped) Emu.Resume(); - return; - } - - ConLog.Write("PKG: extracting..."); - - Emu.Stop(); - - wxString fileName = ctrl.GetPath(); - pkg_unpack((const char *)fileName.mb_str()); - - if (!wxRemoveFile(ctrl.GetPath()+".dec")) - ConLog.Warning("Could not delete the decoded DEC file"); - - ConLog.Write("PKG: extract done."); -} - -void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event)) -{ - bool stopped = false; - - if(Emu.IsRunning()) - { - Emu.Pause(); - stopped = true; - } - - wxFileDialog ctrl(this, L"Select ELF", wxEmptyString, wxEmptyString, "*.*", - wxFD_OPEN | wxFD_FILE_MUST_EXIST); - - if(ctrl.ShowModal() == wxID_CANCEL) - { - if(stopped) Emu.Resume(); - return; - } - - ConLog.Write("ELF: booting..."); - - Emu.Stop(); - - Emu.SetPath(ctrl.GetPath()); - Emu.Load(); - - ConLog.Write("ELF: boot done."); -} - -void MainFrame::BootSelf(wxCommandEvent& WXUNUSED(event)) -{ - bool stopped = false; - - if(Emu.IsRunning()) - { - Emu.Pause(); - stopped = true; - } - - wxFileDialog ctrl(this, L"Select SELF", wxEmptyString, wxEmptyString, "*.*", - wxFD_OPEN | wxFD_FILE_MUST_EXIST); - - if(ctrl.ShowModal() == wxID_CANCEL) - { - if(stopped) Emu.Resume(); - return; - } - - ConLog.Write("SELF: booting..."); - - Emu.Stop(); - - wxString fileIn = ctrl.GetPath(); - wxString fileOut = ctrl.GetPath()+".elf"; - - // Check if the data really needs to be decrypted. - if(!wxFileExists(fileIn)) - { - ConLog.Error("Could not open SELF file!"); - return; - } - - wxFile f(fileIn); - // Get the key version. - f.Seek(0x08); - be_t key_version; - f.Read(&key_version, sizeof(key_version)); - - if(key_version.ToBE() == const_se_t::value) - { - ConLog.Warning("Debug SELF detected! Removing fake header..."); - - // Get the real elf offset. - f.Seek(0x10); - be_t elf_offset; - f.Read(&elf_offset, sizeof(elf_offset)); - - // Start at the real elf offset. - f.Seek(elf_offset); - - wxFile out(fileOut, wxFile::write); - - // Copy the data. - char buf[2048]; - while (ssize_t size = f.Read(buf, 2048)) - out.Write(buf, size); - } - else - { - if (!scetool_decrypt((scetool::s8 *)fileIn.mb_str(), (scetool::s8 *)fileOut.mb_str())) - { - ConLog.Write("SELF: Could not decrypt file"); - return; - } - } - - f.Close(); - - Emu.SetPath(fileOut); - Emu.Load(); - if (!wxRemoveFile(fileOut)) - ConLog.Warning("Could not delete the decrypted ELF file"); - - ConLog.Write("SELF: boot done."); -} - -void MainFrame::Pause(wxCommandEvent& WXUNUSED(event)) -{ - if(Emu.IsReady()) - { - Emu.Run(); - } - else if(Emu.IsPaused()) - { - Emu.Resume(); - } - else if(Emu.IsRunning()) - { - Emu.Pause(); - } -} - -void MainFrame::Stop(wxCommandEvent& WXUNUSED(event)) -{ - Emu.Stop(); -} - -void MainFrame::SendExit(wxCommandEvent& event) -{ - Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0); -} - -void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event) -{ - Emu.GetCallbackManager().m_exit_callback.Handle(m_sys_menu_opened ? 0x0132 : 0x0131, 0); - m_sys_menu_opened = !m_sys_menu_opened; - wxCommandEvent ce; - UpdateUI(ce); -} - -void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) -{ - //TODO - - bool paused = false; - - if(Emu.IsRunning()) - { - Emu.Pause(); - paused = true; - } - - wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); - - wxBoxSizer* s_panel(new wxBoxSizer(wxHORIZONTAL)); - wxBoxSizer* s_subpanel1(new wxBoxSizer(wxVERTICAL)); - wxBoxSizer* s_subpanel2(new wxBoxSizer(wxVERTICAL)); - - wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) ); - wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) ); - - wxStaticBoxSizer* s_round_gs( new wxStaticBoxSizer( wxVERTICAL, &diag, _("GS") ) ); - wxStaticBoxSizer* s_round_gs_render( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Render") ) ); - wxStaticBoxSizer* s_round_gs_res( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default resolution") ) ); - wxStaticBoxSizer* s_round_gs_aspect( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default aspect ratio") ) ); - - wxStaticBoxSizer* s_round_io( new wxStaticBoxSizer( wxVERTICAL, &diag, _("IO") ) ); - wxStaticBoxSizer* s_round_pad_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Pad Handler") ) ); - wxStaticBoxSizer* s_round_keyboard_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Keyboard Handler") ) ); - wxStaticBoxSizer* s_round_mouse_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Mouse Handler") ) ); - - wxComboBox* cbox_cpu_decoder = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_gs_render = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_gs_resolution = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_gs_aspect = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_pad_handler = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_keyboard_handler = new wxComboBox(&diag, wxID_ANY); - wxComboBox* cbox_mouse_handler = new wxComboBox(&diag, wxID_ANY); - - wxCheckBox* chbox_cpu_ignore_rwerrors = new wxCheckBox(&diag, wxID_ANY, "Ignore Read/Write errors"); - wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(&diag, wxID_ANY, "Dump Depth Buffer"); - wxCheckBox* chbox_gs_dump_color = new wxCheckBox(&diag, wxID_ANY, "Dump Color Buffers"); - wxCheckBox* chbox_gs_vsync = new wxCheckBox(&diag, wxID_ANY, "VSync"); - - //cbox_cpu_decoder->Append("DisAsm"); - cbox_cpu_decoder->Append("Interpreter & DisAsm"); - cbox_cpu_decoder->Append("Interpreter"); - - for(int i=1; iAppend(wxString::Format("%dx%d", ResolutionTable[i].width, ResolutionTable[i].height)); - } - - cbox_gs_aspect->Append("4:3"); - cbox_gs_aspect->Append("16:9"); - - cbox_gs_render->Append("Null"); - cbox_gs_render->Append("OpenGL"); - //cbox_gs_render->Append("Software"); - - cbox_pad_handler->Append("Null"); - cbox_pad_handler->Append("Windows"); - //cbox_pad_handler->Append("DirectInput"); - - cbox_keyboard_handler->Append("Null"); - cbox_keyboard_handler->Append("Windows"); - //cbox_keyboard_handler->Append("DirectInput"); - - cbox_mouse_handler->Append("Null"); - cbox_mouse_handler->Append("Windows"); - //cbox_mouse_handler->Append("DirectInput"); - - chbox_cpu_ignore_rwerrors->SetValue(Ini.CPUIgnoreRWErrors.GetValue()); - chbox_gs_dump_depth->SetValue(Ini.GSDumpDepthBuffer.GetValue()); - chbox_gs_dump_color->SetValue(Ini.GSDumpColorBuffers.GetValue()); - chbox_gs_vsync->SetValue(Ini.GSVSyncEnable.GetValue()); - - cbox_cpu_decoder->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0); - cbox_gs_render->SetSelection(Ini.GSRenderMode.GetValue()); - cbox_gs_resolution->SetSelection(ResolutionIdToNum(Ini.GSResolution.GetValue()) - 1); - cbox_gs_aspect->SetSelection(Ini.GSAspectRatio.GetValue() - 1); - cbox_pad_handler->SetSelection(Ini.PadHandlerMode.GetValue()); - cbox_keyboard_handler->SetSelection(Ini.KeyboardHandlerMode.GetValue()); - cbox_mouse_handler->SetSelection(Ini.MouseHandlerMode.GetValue()); - - s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_cpu->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_cpu->Add(chbox_cpu_ignore_rwerrors, wxSizerFlags().Border(wxALL, 5).Expand()); - - s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5)); - s_round_gs->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5)); - s_round_gs->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5)); - - s_round_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_mouse_handler->Add(cbox_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_io->Add(s_round_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_io->Add(s_round_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_io->Add(s_round_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); - - wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); - - s_b_panel->Add(new wxButton(&diag, wxID_OK), wxSizerFlags().Border(wxALL, 5).Center()); - s_b_panel->Add(new wxButton(&diag, wxID_CANCEL), wxSizerFlags().Border(wxALL, 5).Center()); - - //wxBoxSizer* s_conf_panel(new wxBoxSizer(wxHORIZONTAL)); - - s_subpanel1->Add(s_round_cpu, wxSizerFlags().Border(wxALL, 5).Expand()); - s_subpanel1->Add(s_round_gs, wxSizerFlags().Border(wxALL, 5).Expand()); - s_subpanel2->Add(s_round_io, wxSizerFlags().Border(wxALL, 5).Expand()); - s_subpanel1->Add(s_b_panel, wxSizerFlags().Border(wxALL, 8).Expand()); - - s_subpanel2->AddSpacer(180); - s_panel->Add(s_subpanel1, wxSizerFlags().Border(wxALL, 5).Expand()); - s_panel->Add(s_subpanel2, wxSizerFlags().Border(wxALL, 5).Expand()); - - diag.SetSizerAndFit( s_panel ); - - if(diag.ShowModal() == wxID_OK) - { - Ini.CPUDecoderMode.SetValue(cbox_cpu_decoder->GetSelection() + 1); - Ini.CPUIgnoreRWErrors.SetValue(chbox_cpu_ignore_rwerrors->GetValue()); - Ini.GSRenderMode.SetValue(cbox_gs_render->GetSelection()); - Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1)); - Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); - Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); - Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); - Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); - Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection()); - Ini.KeyboardHandlerMode.SetValue(cbox_keyboard_handler->GetSelection()); - Ini.MouseHandlerMode.SetValue(cbox_mouse_handler->GetSelection()); - - Ini.Save(); - } - - if(paused) Emu.Resume(); -} - -void MainFrame::ConfigVFS(wxCommandEvent& WXUNUSED(event)) -{ - VFSManagerDialog(this).ShowModal(); -} - -void MainFrame::ConfigVHDD(wxCommandEvent& WXUNUSED(event)) -{ - VHDDManagerDialog(this).ShowModal(); -} - -void MainFrame::OpenELFCompiler(wxCommandEvent& WXUNUSED(event)) -{ - (new CompilerELF(this)) -> Show(); -} - -void MainFrame::OpenMemoryViewer(wxCommandEvent& WXUNUSED(event)) -{ - (new MemoryViewerPanel(this)) -> Show(); -} - -void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event)) -{ - AboutDialog(this).ShowModal(); -} - -void MainFrame::UpdateUI(wxCommandEvent& event) -{ - event.Skip(); - - bool is_running, is_stopped, is_ready; - - if(event.GetEventType() == wxEVT_DBG_COMMAND) - { - switch(event.GetId()) - { - case DID_START_EMU: - case DID_STARTED_EMU: - is_running = true; - is_stopped = false; - is_ready = false; - break; - - case DID_STOP_EMU: - case DID_STOPPED_EMU: - is_running = false; - is_stopped = true; - is_ready = false; - m_sys_menu_opened = false; - break; - - case DID_PAUSE_EMU: - case DID_PAUSED_EMU: - is_running = false; - is_stopped = false; - is_ready = false; - break; - - case DID_RESUME_EMU: - case DID_RESUMED_EMU: - is_running = true; - is_stopped = false; - is_ready = false; - break; - - case DID_READY_EMU: - is_running = false; - is_stopped = false; - is_ready = true; - break; - - case DID_REGISTRED_CALLBACK: - is_running = Emu.IsRunning(); - is_stopped = Emu.IsStopped(); - is_ready = Emu.IsReady(); - break; - - default: - return; - } - } - else - { - is_running = Emu.IsRunning(); - is_stopped = Emu.IsStopped(); - is_ready = Emu.IsReady(); - } - - wxMenuBar& menubar( *GetMenuBar() ); - wxMenuItem& pause = *menubar.FindItem( id_sys_pause ); - wxMenuItem& stop = *menubar.FindItem( id_sys_stop ); - wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); - wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu ); - pause.SetText(is_running ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + C" : "Resume\tCtrl + C"); - pause.Enable(!is_stopped); - stop.Enable(!is_stopped); - //send_exit.Enable(false); - bool enable_commands = !is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount(); - - send_open_menu.SetText(wxString::Format("Send %s system menu cmd", m_sys_menu_opened ? "close" : "open")); - send_open_menu.Enable(enable_commands); - send_exit.Enable(enable_commands); - - //m_aui_mgr.Update(); - - //wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg ); - //GetEventHandler()->AddPendingEvent( refit ); -} - -void MainFrame::OnQuit(wxCloseEvent& event) -{ - DoSettings(false); - TheApp->Exit(); -} - -struct state_hdr -{ - u32 magic; - u16 version; - u32 mem_count; - u32 mem_offset; - u32 mem_size; - u32 hle_count; - u32 hle_offset; -}; - -static const u32 state_magic = *(u32*)"R3SS"; -static const u32 state_version = 0x1000; - -void MakeSaveState(wxFile& f) -{ - const ArrayF& mb = Memory.MemoryBlocks; - - state_hdr state; - memset(&state, 0, sizeof(state_hdr)); - - state.magic = state_magic; - state.version = state_version; - state.mem_count = mb.GetCount(); - //state.hle_count = mb.GetCount(); - - state.mem_offset = sizeof(state_hdr) + 4; - - f.Seek(state.mem_offset); - for(u32 i=0; i + +#include "unpkg/unpkg.c" + +BEGIN_EVENT_TABLE(MainFrame, FrameBase) + EVT_CLOSE(MainFrame::OnQuit) +END_EVENT_TABLE() + +enum IDs +{ + id_boot_elf = 0x555, + id_boot_game, + id_install_pkg, + id_sys_pause, + id_sys_stop, + id_sys_send_open_menu, + id_sys_send_exit, + id_config_emu, + id_config_vfs_manager, + id_config_vhdd_manager, + id_tools_compiler, + id_tools_memory_viewer, + id_help_about, + id_update_dbg, +}; + +wxString GetPaneName() +{ + static int pane_num = 0; + + return wxString::Format("Pane_%d", pane_num++); +} + +bool wxMoveDir(wxString sFrom, wxString sTo) +{ + if (sFrom[sFrom.Len() - 1] != '\\' && sFrom[sFrom.Len() - 1] != '/') sFrom += wxFILE_SEP_PATH; + if (sTo[sTo.Len() - 1] != '\\' && sTo[sTo.Len() - 1] != '/') sTo += wxFILE_SEP_PATH; + + if (!::wxDirExists(sFrom)) { + ::wxLogError(wxT("%s does not exist!\r\nCan not copy directory"), sFrom.c_str()); + return false; + } + if (!wxDirExists(sTo)) { + if (!wxFileName::Mkdir(sTo, 0777, wxPATH_MKDIR_FULL)) { + ::wxLogError(wxT("%s could not be created!"), sTo.c_str()); + return false; + } + } + + wxDir fDir(sFrom); + wxString sNext = wxEmptyString; + bool bIsFile = fDir.GetFirst(&sNext); + while (bIsFile) { + const wxString sFileFrom = sFrom + sNext; + const wxString sFileTo = sTo + sNext; + if (::wxDirExists(sFileFrom)) { + wxMoveDir(sFileFrom, sFileTo); + ::wxRmdir(sFileFrom); + } + else { + if (!::wxFileExists(sFileTo)) { + if (!::wxCopyFile(sFileFrom, sFileTo)) { + ::wxLogError(wxT("Could not copy %s to %s !"), sFileFrom.c_str(), sFileTo.c_str()); + return false; + } + } + ::wxRemoveFile(sFileFrom); + } + bIsFile = fDir.GetNext(&sNext); + } + ::wxRmdir(sFrom); + return true; +} + +MainFrame::MainFrame() + : FrameBase(nullptr, wxID_ANY, "", "MainFrame", wxSize(800, 600)) + , m_aui_mgr(this) + , m_sys_menu_opened(false) +{ + +#ifdef _DEBUG + SetLabel(wxString::Format(_PRGNAME_ " git-" RPCS3_GIT_VERSION)); +#else + SetLabel(wxString::Format(_PRGNAME_ " " _PRGVER_)); +#endif + + wxMenuBar& menubar(*new wxMenuBar()); + + wxMenu& menu_boot(*new wxMenu()); + wxMenu& menu_sys(*new wxMenu()); + wxMenu& menu_conf(*new wxMenu()); + wxMenu& menu_tools(*new wxMenu()); + wxMenu& menu_help(*new wxMenu()); + + menubar.Append(&menu_boot, "Boot"); + menubar.Append(&menu_sys, "System"); + menubar.Append(&menu_conf, "Config"); + menubar.Append(&menu_tools, "Tools"); + menubar.Append(&menu_help, "Help"); + + menu_boot.Append(id_boot_game, "Boot game"); + menu_boot.Append(id_install_pkg, "Install PKG"); + menu_boot.AppendSeparator(); + menu_boot.Append(id_boot_elf, "Boot (S)ELF"); + + menu_sys.Append(id_sys_pause, "Pause")->Enable(false); + menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false); + menu_sys.AppendSeparator(); + menu_sys.Append(id_sys_send_open_menu, "Send open system menu cmd")->Enable(false); + menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false); + + menu_conf.Append(id_config_emu, "Settings"); + menu_conf.AppendSeparator(); + menu_conf.Append(id_config_vfs_manager, "Virtual File System Manager"); + menu_conf.Append(id_config_vhdd_manager, "Virtual HDD Manager"); + + menu_tools.Append(id_tools_compiler, "ELF Compiler"); + menu_tools.Append(id_tools_memory_viewer, "Memory Viewer"); + + menu_help.Append(id_help_about, "About..."); + + SetMenuBar(&menubar); + + m_game_viewer = new GameViewer(this); + AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM); + + Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) ); + Connect( id_install_pkg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::InstallPkg) ); + Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) ); + + Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) ); + Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) ); + Connect( id_sys_send_open_menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendOpenCloseSysMenu) ); + Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) ); + + Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); + Connect( id_config_vfs_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVFS) ); + Connect( id_config_vhdd_manager,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVHDD) ); + + Connect( id_tools_compiler, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenELFCompiler)); + Connect( id_tools_memory_viewer,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenMemoryViewer)); + + Connect( id_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::AboutDialogHandler) ); + + Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) ); + + m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this); +} + +MainFrame::~MainFrame() +{ + m_aui_mgr.UnInit(); +} + +void MainFrame::AddPane(wxWindow* wind, const wxString& caption, int flags) +{ + wind->SetSize(-1, 300); + m_aui_mgr.AddPane(wind, wxAuiPaneInfo().Name(GetPaneName()).Caption(caption).Direction(flags).CloseButton(false).MaximizeButton()); +} + +void MainFrame::DoSettings(bool load) +{ + IniEntry ini; + ini.Init("Settings", "MainFrameAui"); + + if(load) + { + m_aui_mgr.LoadPerspective(ini.LoadValue(m_aui_mgr.SavePerspective())); + } + else + { + ini.SaveValue(m_aui_mgr.SavePerspective()); + } +} + +void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) +{ + bool stopped = false; + + if(Emu.IsRunning()) + { + Emu.Pause(); + stopped = true; + } + + wxDirDialog ctrl(this, L"Select game folder", wxEmptyString); + + if(ctrl.ShowModal() == wxID_CANCEL) + { + if(stopped) Emu.Resume(); + return; + } + + Emu.Stop(); + + if(Emu.BootGame(ctrl.GetPath().c_str())) + { + ConLog.Write("Game: boot done."); + } + else + { + ConLog.Error("Ps3 executable not found in selected folder (%s)", ctrl.GetPath().mb_str()); + } +} + +void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event)) +{ + //TODO: progress bar + bool stopped = false; + + if(Emu.IsRunning()) + { + Emu.Pause(); + stopped = true; + } + + wxFileDialog ctrl (this, L"Select PKG", wxEmptyString, wxEmptyString, "*.pkg", + wxFD_OPEN | wxFD_FILE_MUST_EXIST); + + if(ctrl.ShowModal() == wxID_CANCEL) + { + if(stopped) Emu.Resume(); + return; + } + + ConLog.Write("PKG: extracting..."); + + Emu.Stop(); + + wxString fileName = ctrl.GetPath(); + pkg_unpack((const char *)fileName.mb_str()); + + if (!wxRemoveFile(ctrl.GetPath()+".dec")) + ConLog.Warning("Could not delete the decoded DEC file"); + + // Copy the PKG to dev_hdd0 and format the path to be identical to the PS3. + wxString gamePath = "\\dev_hdd0\\game\\"; + pkg_header *header; + pkg_info((const char *)fileName.mb_str(), &header); + + // Get the PKG title ID from the header and format it (should match TITLE ID from PARAM.SFO). + wxString titleID_full (header->title_id); + wxString titleID = titleID_full.SubString(7, 15); + + // Travel to bin folder. + wxSetWorkingDirectory(wxGetCwd() + "\\..\\"); + + // Save the main dir. + wxString mainDir = wxGetCwd(); + + // Set PKG dir. + wxString oldPkgDir = wxT(mainDir + "\\" + titleID_full); + wxString newPkgDir = wxT(mainDir + gamePath + titleID); + + // Move the final folder. + wxMoveDir(oldPkgDir, newPkgDir); + + // Save the title ID. + Emu.SetTitleID(titleID); + + ConLog.Write("PKG: extract done."); + + // Travel to the main dir. + wxSetWorkingDirectory(mainDir); + + m_game_viewer->Refresh(); + Emu.BootGame(newPkgDir.c_str()); +} + +void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event)) +{ + bool stopped = false; + + if(Emu.IsRunning()) + { + Emu.Pause(); + stopped = true; + } + + wxFileDialog ctrl(this, L"Select (S)ELF", wxEmptyString, wxEmptyString, "*.*", + wxFD_OPEN | wxFD_FILE_MUST_EXIST); + + if(ctrl.ShowModal() == wxID_CANCEL) + { + if(stopped) Emu.Resume(); + return; + } + + ConLog.Write("(S)ELF: booting..."); + + Emu.Stop(); + + Emu.SetPath(ctrl.GetPath()); + Emu.Load(); + + ConLog.Write("(S)ELF: boot done."); +} + +void MainFrame::Pause(wxCommandEvent& WXUNUSED(event)) +{ + if(Emu.IsReady()) + { + Emu.Run(); + } + else if(Emu.IsPaused()) + { + Emu.Resume(); + } + else if(Emu.IsRunning()) + { + Emu.Pause(); + } +} + +void MainFrame::Stop(wxCommandEvent& WXUNUSED(event)) +{ + Emu.Stop(); +} + +void MainFrame::SendExit(wxCommandEvent& event) +{ + Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0); +} + +void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event) +{ + Emu.GetCallbackManager().m_exit_callback.Handle(m_sys_menu_opened ? 0x0132 : 0x0131, 0); + m_sys_menu_opened = !m_sys_menu_opened; + wxCommandEvent ce; + UpdateUI(ce); +} + +void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) +{ + //TODO + + bool paused = false; + + if(Emu.IsRunning()) + { + Emu.Pause(); + paused = true; + } + + wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); + + wxBoxSizer* s_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_subpanel1(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_subpanel2(new wxBoxSizer(wxVERTICAL)); + + wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) ); + wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) ); + + wxStaticBoxSizer* s_round_gs( new wxStaticBoxSizer( wxVERTICAL, &diag, _("GS") ) ); + wxStaticBoxSizer* s_round_gs_render( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Render") ) ); + wxStaticBoxSizer* s_round_gs_res( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default resolution") ) ); + wxStaticBoxSizer* s_round_gs_aspect( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default aspect ratio") ) ); + + wxStaticBoxSizer* s_round_io( new wxStaticBoxSizer( wxVERTICAL, &diag, _("IO") ) ); + wxStaticBoxSizer* s_round_pad_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Pad Handler") ) ); + wxStaticBoxSizer* s_round_keyboard_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Keyboard Handler") ) ); + wxStaticBoxSizer* s_round_mouse_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Mouse Handler") ) ); + + wxComboBox* cbox_cpu_decoder = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_render = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_resolution = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_aspect = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_pad_handler = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_keyboard_handler = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_mouse_handler = new wxComboBox(&diag, wxID_ANY); + + wxCheckBox* chbox_cpu_ignore_rwerrors = new wxCheckBox(&diag, wxID_ANY, "Ignore Read/Write errors"); + wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(&diag, wxID_ANY, "Dump Depth Buffer"); + wxCheckBox* chbox_gs_dump_color = new wxCheckBox(&diag, wxID_ANY, "Dump Color Buffers"); + wxCheckBox* chbox_gs_vsync = new wxCheckBox(&diag, wxID_ANY, "VSync"); + + //cbox_cpu_decoder->Append("DisAsm"); + cbox_cpu_decoder->Append("Interpreter & DisAsm"); + cbox_cpu_decoder->Append("Interpreter"); + + for(int i=1; iAppend(wxString::Format("%dx%d", ResolutionTable[i].width, ResolutionTable[i].height)); + } + + cbox_gs_aspect->Append("4:3"); + cbox_gs_aspect->Append("16:9"); + + cbox_gs_render->Append("Null"); + cbox_gs_render->Append("OpenGL"); + //cbox_gs_render->Append("Software"); + + cbox_pad_handler->Append("Null"); + cbox_pad_handler->Append("Windows"); + //cbox_pad_handler->Append("DirectInput"); + + cbox_keyboard_handler->Append("Null"); + cbox_keyboard_handler->Append("Windows"); + //cbox_keyboard_handler->Append("DirectInput"); + + cbox_mouse_handler->Append("Null"); + cbox_mouse_handler->Append("Windows"); + //cbox_mouse_handler->Append("DirectInput"); + + chbox_cpu_ignore_rwerrors->SetValue(Ini.CPUIgnoreRWErrors.GetValue()); + chbox_gs_dump_depth->SetValue(Ini.GSDumpDepthBuffer.GetValue()); + chbox_gs_dump_color->SetValue(Ini.GSDumpColorBuffers.GetValue()); + chbox_gs_vsync->SetValue(Ini.GSVSyncEnable.GetValue()); + + cbox_cpu_decoder->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0); + cbox_gs_render->SetSelection(Ini.GSRenderMode.GetValue()); + cbox_gs_resolution->SetSelection(ResolutionIdToNum(Ini.GSResolution.GetValue()) - 1); + cbox_gs_aspect->SetSelection(Ini.GSAspectRatio.GetValue() - 1); + cbox_pad_handler->SetSelection(Ini.PadHandlerMode.GetValue()); + cbox_keyboard_handler->SetSelection(Ini.KeyboardHandlerMode.GetValue()); + cbox_mouse_handler->SetSelection(Ini.MouseHandlerMode.GetValue()); + + s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_cpu->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_cpu->Add(chbox_cpu_ignore_rwerrors, wxSizerFlags().Border(wxALL, 5).Expand()); + + s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5)); + s_round_gs->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5)); + s_round_gs->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5)); + + s_round_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_keyboard_handler->Add(cbox_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_mouse_handler->Add(cbox_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_io->Add(s_round_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_io->Add(s_round_keyboard_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_io->Add(s_round_mouse_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + s_b_panel->Add(new wxButton(&diag, wxID_OK), wxSizerFlags().Border(wxALL, 5).Center()); + s_b_panel->Add(new wxButton(&diag, wxID_CANCEL), wxSizerFlags().Border(wxALL, 5).Center()); + + //wxBoxSizer* s_conf_panel(new wxBoxSizer(wxHORIZONTAL)); + + s_subpanel1->Add(s_round_cpu, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel1->Add(s_round_gs, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel2->Add(s_round_io, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel1->Add(s_b_panel, wxSizerFlags().Border(wxALL, 8).Expand()); + + s_subpanel2->AddSpacer(180); + s_panel->Add(s_subpanel1, wxSizerFlags().Border(wxALL, 5).Expand()); + s_panel->Add(s_subpanel2, wxSizerFlags().Border(wxALL, 5).Expand()); + + diag.SetSizerAndFit( s_panel ); + + if(diag.ShowModal() == wxID_OK) + { + Ini.CPUDecoderMode.SetValue(cbox_cpu_decoder->GetSelection() + 1); + Ini.CPUIgnoreRWErrors.SetValue(chbox_cpu_ignore_rwerrors->GetValue()); + Ini.GSRenderMode.SetValue(cbox_gs_render->GetSelection()); + Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1)); + Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); + Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); + Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue()); + Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue()); + Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection()); + Ini.KeyboardHandlerMode.SetValue(cbox_keyboard_handler->GetSelection()); + Ini.MouseHandlerMode.SetValue(cbox_mouse_handler->GetSelection()); + + Ini.Save(); + } + + if(paused) Emu.Resume(); +} + +void MainFrame::ConfigVFS(wxCommandEvent& WXUNUSED(event)) +{ + VFSManagerDialog(this).ShowModal(); +} + +void MainFrame::ConfigVHDD(wxCommandEvent& WXUNUSED(event)) +{ + VHDDManagerDialog(this).ShowModal(); +} + +void MainFrame::OpenELFCompiler(wxCommandEvent& WXUNUSED(event)) +{ + (new CompilerELF(this)) -> Show(); +} + +void MainFrame::OpenMemoryViewer(wxCommandEvent& WXUNUSED(event)) +{ + (new MemoryViewerPanel(this)) -> Show(); +} + +void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event)) +{ + AboutDialog(this).ShowModal(); +} + +void MainFrame::UpdateUI(wxCommandEvent& event) +{ + event.Skip(); + + bool is_running, is_stopped, is_ready; + + if(event.GetEventType() == wxEVT_DBG_COMMAND) + { + switch(event.GetId()) + { + case DID_START_EMU: + case DID_STARTED_EMU: + is_running = true; + is_stopped = false; + is_ready = false; + break; + + case DID_STOP_EMU: + case DID_STOPPED_EMU: + is_running = false; + is_stopped = true; + is_ready = false; + m_sys_menu_opened = false; + break; + + case DID_PAUSE_EMU: + case DID_PAUSED_EMU: + is_running = false; + is_stopped = false; + is_ready = false; + break; + + case DID_RESUME_EMU: + case DID_RESUMED_EMU: + is_running = true; + is_stopped = false; + is_ready = false; + break; + + case DID_READY_EMU: + is_running = false; + is_stopped = false; + is_ready = true; + break; + + case DID_REGISTRED_CALLBACK: + is_running = Emu.IsRunning(); + is_stopped = Emu.IsStopped(); + is_ready = Emu.IsReady(); + break; + + default: + return; + } + } + else + { + is_running = Emu.IsRunning(); + is_stopped = Emu.IsStopped(); + is_ready = Emu.IsReady(); + } + + wxMenuBar& menubar( *GetMenuBar() ); + wxMenuItem& pause = *menubar.FindItem( id_sys_pause ); + wxMenuItem& stop = *menubar.FindItem( id_sys_stop ); + wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); + wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu ); + pause.SetText(is_running ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + C" : "Resume\tCtrl + C"); + pause.Enable(!is_stopped); + stop.Enable(!is_stopped); + //send_exit.Enable(false); + bool enable_commands = !is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount(); + + send_open_menu.SetText(wxString::Format("Send %s system menu cmd", m_sys_menu_opened ? "close" : "open")); + send_open_menu.Enable(enable_commands); + send_exit.Enable(enable_commands); + + //m_aui_mgr.Update(); + + //wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg ); + //GetEventHandler()->AddPendingEvent( refit ); +} + +void MainFrame::OnQuit(wxCloseEvent& event) +{ + DoSettings(false); + TheApp->Exit(); +} + +struct state_hdr +{ + u32 magic; + u16 version; + u32 mem_count; + u32 mem_offset; + u32 mem_size; + u32 hle_count; + u32 hle_offset; +}; + +static const u32 state_magic = *(u32*)"R3SS"; +static const u32 state_version = 0x1000; + +void MakeSaveState(wxFile& f) +{ + const ArrayF& mb = Memory.MemoryBlocks; + + state_hdr state; + memset(&state, 0, sizeof(state_hdr)); + + state.magic = state_magic; + state.version = state_version; + state.mem_count = mb.GetCount(); + //state.hle_count = mb.GetCount(); + + state.mem_offset = sizeof(state_hdr) + 4; + + f.Seek(state.mem_offset); + for(u32 i=0; iLoad(nid)) { ConLog.Warning("Unknown function 0x%08x in '%s' module", nid, module_name.mb_str()); + SysCalls::DoFunc(nid); } } #ifdef LOADER_DEBUG diff --git a/rpcs3/Loader/PSF.cpp b/rpcs3/Loader/PSF.cpp index adb1b29c5f..efe900fc2b 100644 --- a/rpcs3/Loader/PSF.cpp +++ b/rpcs3/Loader/PSF.cpp @@ -5,6 +5,17 @@ PSFLoader::PSFLoader(vfsStream& f) : psf_f(f) { } +PsfEntry* PSFLoader::SearchEntry(const std::string& key) +{ + for(uint i=0; i= sizeof(m_entries[i].name) || c == '\0') + break; } - m_table[m_table.GetCount() - 1].Append(c); - } - - if(m_table.GetCount() != psfhdr.psf_entries_num) - { - if(m_show_log) ConLog.Error("PSF error: Entries loaded with error! [%d - %d]", m_table.GetCount(), psfhdr.psf_entries_num); - m_table.Clear(); - return false; } return true; } -struct PsfHelper +bool PSFLoader::LoadDataTable() { - static wxString ReadString(vfsStream& f, const u32 size) + for(u32 i=0; iFormat(); + if(PsfEntry* entry = SearchEntry("TITLE")) m_info.name = entry->Format(); + if(PsfEntry* entry = SearchEntry("APP_VER")) m_info.app_ver = entry->Format(); + if(PsfEntry* entry = SearchEntry("CATEGORY")) m_info.category = entry->Format(); + if(PsfEntry* entry = SearchEntry("PS3_SYSTEM_VER")) m_info.fw = entry->Format(); + if(PsfEntry* entry = SearchEntry("SOUND_FORMAT")) m_info.sound_format = entry->FormatInteger(); + if(PsfEntry* entry = SearchEntry("RESOLUTION")) m_info.resolution = entry->FormatInteger(); + if(PsfEntry* entry = SearchEntry("PARENTAL_LEVEL")) m_info.parental_lvl = entry->FormatInteger(); + if(m_info.serial.Length() == 9) { diff --git a/rpcs3/Loader/PSF.h b/rpcs3/Loader/PSF.h index c665734408..1deb1e639a 100644 --- a/rpcs3/Loader/PSF.h +++ b/rpcs3/Loader/PSF.h @@ -6,7 +6,7 @@ struct PsfHeader u32 psf_magic; u32 psf_version; u32 psf_offset_key_table; - u32 psf_offset_values_table; + u32 psf_offset_data_table; u32 psf_entries_num; bool CheckMagic() const { return psf_magic == *(u32*)"\0PSF"; } @@ -14,13 +14,44 @@ struct PsfHeader struct PsfDefTbl { - u16 psf_name_tbl_offset; - u16 psf_data_type; - u32 psf_data_size; - u32 psf_data_fsize; + u16 psf_key_table_offset; + u16 psf_param_fmt; + u32 psf_param_len; + u32 psf_param_max_len; u32 psf_data_tbl_offset; }; +struct PsfEntry +{ + char name[128]; + u16 fmt; + char param[4096]; + + std::string Format() const + { + switch(fmt) + { + default: + case 0x0400: + case 0x0402: + return FormatString(); + + case 0x0404: + return wxString::Format("0x%x", FormatInteger()).c_str(); + } + } + + u32 FormatInteger() const + { + return *(u32*)param; + } + + char* FormatString() const + { + return (char*)param; + } +}; + class PSFLoader { vfsStream& psf_f; @@ -29,14 +60,19 @@ class PSFLoader public: PSFLoader(vfsStream& f); - wxArrayString m_table; + Array m_entries; + + PsfEntry* SearchEntry(const std::string& key); + + //wxArrayString m_table; GameInfo m_info; PsfHeader psfhdr; + Array m_psfindxs; virtual bool Load(bool show = true); virtual bool Close(); private: bool LoadHdr(); bool LoadKeyTable(); - bool LoadValuesTable(); + bool LoadDataTable(); }; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index ccf7032d20..7ab3caffda 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -199,6 +199,12 @@ + + NotUsing + NotUsing + NotUsing + NotUsing + @@ -257,6 +263,7 @@ + @@ -323,6 +330,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 787be8cded..8dd7906d15 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -53,6 +53,9 @@ {bee6a4b4-6371-4c1b-8558-fc7888b1574e} + + {52b11fe8-a967-4d52-bf88-a3210d4ffb27} + @@ -340,6 +343,12 @@ Emu\SysCalls\Modules + + Emu\SysCalls\lv2 + + + Utilities\scetool + Emu\SysCalls\Modules @@ -513,5 +522,8 @@ Utilities + + Include + \ No newline at end of file diff --git a/scetool/elf_inlines.h b/scetool/elf_inlines.h index ce36290552..79d9660099 100644 --- a/scetool/elf_inlines.h +++ b/scetool/elf_inlines.h @@ -8,6 +8,7 @@ #include +#define NOCOMPILE #include "types.h" #include "elf.h" diff --git a/scetool/scetool.cpp b/scetool/scetool.cpp index 57dbf40946..8f6df226c3 100644 --- a/scetool/scetool.cpp +++ b/scetool/scetool.cpp @@ -3,6 +3,8 @@ * This file is released under the GPLv2. */ +#include "stdafx.h" + #include #include diff --git a/scetool/scetool.h b/scetool/scetool.h new file mode 100644 index 0000000000..00ce0ea159 --- /dev/null +++ b/scetool/scetool.h @@ -0,0 +1,5 @@ +#pragma once + +#include "types.h" + +bool scetool_decrypt(scetool::s8 *_file_in, scetool::s8 *_file_out); \ No newline at end of file