From b4a76843444cbebc00cfe7d604609387ef4bc505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Sun, 18 May 2014 12:46:01 +0200 Subject: [PATCH 01/23] Check pointers in cellPamf --- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 0d0b5de06e..d961b805cd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -112,6 +112,9 @@ int cellPamfGetHeaderSize(mem_ptr_t pAddr, u64 fileSize, mem64_t pSi cellPamf.Warning("cellPamfGetHeaderSize(pAddr=0x%x, fileSize=%d, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, pSize.GetAddr()); + if (!pAddr.IsGood() || !pSize.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + //if ((u32)pAddr->magic != 0x464d4150) //return CELL_PAMF_ERROR_UNKNOWN_TYPE; @@ -125,6 +128,9 @@ int cellPamfGetHeaderSize2(mem_ptr_t pAddr, u64 fileSize, u32 attrib cellPamf.Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, attribute, pSize.GetAddr()); + if (!pAddr.IsGood() || !pSize.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + //if ((u32)pAddr->magic != 0x464d4150) //return CELL_PAMF_ERROR_UNKNOWN_TYPE; @@ -138,6 +144,9 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, me cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr()); + if (!pAddr.IsGood() || !pOffset.IsGood() || !pSize.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + //if ((u32)pAddr->magic != 0x464d4150) //return CELL_PAMF_ERROR_UNKNOWN_TYPE; @@ -151,6 +160,10 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, me int cellPamfVerify(mem_ptr_t pAddr, u64 fileSize) { cellPamf.Warning("cellPamfVerify(pAddr=0x%x, fileSize=%d)", pAddr.GetAddr(), fileSize); + + if (!pAddr.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + return CELL_OK; } @@ -159,6 +172,9 @@ int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_tpAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + if (fileSize) { pSelf->fileSize = fileSize; @@ -183,6 +199,9 @@ int cellPamfReaderGetPresentationStartTime(mem_ptr_t pSelf, mem_ cellPamf.Warning("cellPamfReaderGetPresentationStartTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", pSelf.GetAddr(), pTimeStamp.GetAddr()); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); const u32 upper = (u16)pAddr->start_pts_high; pTimeStamp->upper = upper; @@ -195,6 +214,9 @@ int cellPamfReaderGetPresentationEndTime(mem_ptr_t pSelf, mem_pt cellPamf.Warning("cellPamfReaderGetPresentationEndTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", pSelf.GetAddr(), pTimeStamp.GetAddr()); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); const u32 upper = (u16)pAddr->end_pts_high; pTimeStamp->upper = upper; @@ -206,6 +228,9 @@ int cellPamfReaderGetMuxRateBound(mem_ptr_t pSelf) { cellPamf.Warning("cellPamfReaderGetMuxRateBound(pSelf=0x%x)", pSelf.GetAddr()); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); return pAddr->mux_rate_max; } @@ -214,6 +239,9 @@ int cellPamfReaderGetNumberOfStreams(mem_ptr_t pSelf) { cellPamf.Warning("cellPamfReaderGetNumberOfStreams(pSelf=0x%x)", pSelf.GetAddr()); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); return pAddr->stream_count; } @@ -223,6 +251,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 cellPamf.Warning("cellPamfReaderGetNumberOfSpecificStreams(pSelf=0x%x, streamType=%d)", pSelf.GetAddr(), streamType); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); int counts[6] = {0, 0, 0, 0, 0, 0}; @@ -256,6 +287,9 @@ int cellPamfReaderSetStreamWithIndex(mem_ptr_t pSelf, u8 streamI cellPamf.Warning("cellPamfReaderSetStreamWithIndex(pSelf=0x%x, streamIndex=%d)", pSelf.GetAddr(), streamIndex); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); if (streamIndex < pAddr->stream_count) @@ -274,6 +308,9 @@ int cellPamfReaderSetStreamWithTypeAndChannel(mem_ptr_t pSelf, u cellPamf.Warning("cellPamfReaderSetStreamWithTypeAndChannel(pSelf=0x%x, streamType=%d, ch=%d)", pSelf.GetAddr(), streamType, ch); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); if (streamType > 5) @@ -303,6 +340,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 cellPamf.Warning("cellPamfReaderSetStreamWithTypeAndIndex(pSelf=0x%x, streamType=%d, streamIndex=%d)", pSelf.GetAddr(), streamType, streamIndex); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); u32 found = 0; @@ -351,6 +391,9 @@ int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t pSelf) { cellPamf.Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.GetAddr()); + if (!pSelf.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + return pSelf->stream; } @@ -366,6 +412,9 @@ int cellPamfReaderGetStreamTypeAndChannel(mem_ptr_t pSelf, mem8_ cellPamf.Warning("cellPamfReaderGetStreamTypeAndChannel(pSelf=0x%x (stream=%d), pType_addr=0x%x, pCh_addr=0x%x", pSelf.GetAddr(), pSelf->stream, pType.GetAddr(), pCh.GetAddr()); + if (!pSelf.IsGood() || !pCh.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + pType = pamfGetStreamType(pSelf, pSelf->stream); pCh = pamfGetStreamChannel(pSelf, pSelf->stream); return CELL_OK; @@ -376,6 +425,9 @@ int cellPamfReaderGetEsFilterId(mem_ptr_t pSelf, mem_ptr_tstream, pEsFilterId.GetAddr()); + if (!pSelf.IsGood() || !pEsFilterId.IsGood()) + return CELL_PAMF_ERROR_INVALID_ARG; + return pamfStreamTypeToEsFilterId(pamfGetStreamType(pSelf, pSelf->stream), pamfGetStreamChannel(pSelf, pSelf->stream), pEsFilterId); } @@ -385,6 +437,9 @@ int cellPamfReaderGetStreamInfo(mem_ptr_t pSelf, u32 pInfo_addr, cellPamf.Warning("cellPamfReaderGetStreamInfo(pSelf=0x%x (stream=%d), pInfo_addr=0x%x, size=%d)", pSelf.GetAddr(), pSelf->stream, pInfo_addr, size); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); memset(Memory + pInfo_addr, 0, size); @@ -493,6 +548,9 @@ int cellPamfReaderGetNumberOfEp(mem_ptr_t pSelf) cellPamf.Warning("cellPamfReaderGetNumberOfEp(pSelf=0x%x (stream=%d))", pSelf.GetAddr(), pSelf->stream); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); return pAddr->stream_headers[pSelf->stream].ep_num; } @@ -502,6 +560,9 @@ int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t pSelf, u32 ep cellPamf.Error("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)", pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr()); + if (!pSelf.IsGood() || !Memory.IsGoodAddr(pSelf->pAddr)) + return CELL_PAMF_ERROR_INVALID_ARG; + const mem_ptr_t pAddr(pSelf->pAddr); //TODO: return CELL_OK; From 06c4c4520096ea32a828f87252a2a6b10857c60c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 14:21:41 -0700 Subject: [PATCH 02/23] GL: Fix half-float texture formats. This matches the ps3 output/channels for these textures per the rsx/texture_formats test. --- rpcs3/Emu/GS/GL/GLGSRender.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index 1cb8869ab2..db728b910b 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -288,8 +288,14 @@ public: break; case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_HALF_FLOAT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_HALF_FLOAT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D"); + + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); break; case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values @@ -336,10 +342,16 @@ public: case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values { + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_HALF_FLOAT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D"); - static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + + static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; glRemap = swizzleMaskX32_Y16_X16_FLOAT; } break; From 612e515317b3149bf4f46139dc791ea5768d8900 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 14:39:04 -0700 Subject: [PATCH 03/23] GL: Fix X16 / Y16_X16 texture formats. Per the rsx/texture_formats test. Not sure about pitch, may need to deal with UNPACK_ROW_LENGTH... --- rpcs3/Emu/GS/GL/GLGSRender.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index db728b910b..79da1ff8ac 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -258,19 +258,31 @@ public: case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_SHORT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D"); - static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE }; + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + + static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE }; glRemap = swizzleMaskX16; } break; case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_SHORT, pixels); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D"); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + checkForGlError("GLTexture::Init() -> glPixelStorei"); + static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; glRemap = swizzleMaskX32_Y16_X16; } From 7948f376fb0bf2db5d845fdbcaf70082d01e4ffa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 15:24:12 -0700 Subject: [PATCH 04/23] GL: Fix the compressed R8B8 / B8R8 type formats. The not-swizzled bit is always set for them. --- rpcs3/Emu/GS/GL/GLGSRender.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index 79da1ff8ac..819d95ff1c 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -368,9 +368,8 @@ public: } break; - case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: + case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): { - // TODO: Probably need to actually unswizzle if is_swizzled. const u32 numPixels = tex.GetWidth() * tex.GetHeight(); unswizzledPixels = (u8 *)malloc(numPixels * 4); // TODO: Speed. @@ -394,9 +393,8 @@ public: } break; - case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: + case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): { - // TODO: Probably need to actually unswizzle if is_swizzled. const u32 numPixels = tex.GetWidth() * tex.GetHeight(); unswizzledPixels = (u8 *)malloc(numPixels * 4); // TODO: Speed. From 9e791da7bd3f900d9e11e670a67002c0fd66e19c Mon Sep 17 00:00:00 2001 From: Michael Yu Date: Sun, 18 May 2014 23:12:28 -0700 Subject: [PATCH 05/23] virtual memory block reads/writes properly fail if address is out of bounds. Fixes Solar v2.1 http://puu.sh/8ScXK.jpg --- rpcs3/Emu/GS/RSXThread.cpp | 5 +- rpcs3/Emu/Memory/Memory.cpp | 65 +++++++++++++++-------- rpcs3/Emu/Memory/MemoryBlock.h | 5 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 18 +++---- rpcs3/Gui/RSXDebugger.cpp | 24 ++++++--- 5 files changed, 73 insertions(+), 44 deletions(-) diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index c5a9233279..2cffe4ce16 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -11,7 +11,10 @@ u32 GetAddress(u32 offset, u8 location) switch(location) { case CELL_GCM_LOCATION_LOCAL: return Memory.RSXFBMem.GetStartAddr() + offset; - case CELL_GCM_LOCATION_MAIN: return Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + offset); + case CELL_GCM_LOCATION_MAIN: + u64 realAddr; + Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + offset, realAddr); // TODO: Error Check? + return realAddr; } ConLog.Error("GetAddress(offset=0x%x, location=0x%x)", location); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 755dd389f5..349c7606fd 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -614,21 +614,25 @@ u32 VirtualMemoryBlock::UnmapAddress(u64 addr) bool VirtualMemoryBlock::Read8(const u64 addr, u8* value) { u64 realAddr; - *value = Memory.Read8(realAddr = getRealAddr(addr)); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + *value = Memory.Read8(realAddr); + return true; } bool VirtualMemoryBlock::Read16(const u64 addr, u16* value) { u64 realAddr; - *value = Memory.Read16(realAddr = getRealAddr(addr)); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + *value = Memory.Read16(realAddr); + return true; } bool VirtualMemoryBlock::Read32(const u64 addr, u32* value) { - u64 realAddr = getRealAddr(addr); - if (realAddr == 0) + u64 realAddr; + if (!getRealAddr(addr, realAddr)) return false; *value = Memory.Read32(realAddr); return true; @@ -637,63 +641,78 @@ bool VirtualMemoryBlock::Read32(const u64 addr, u32* value) bool VirtualMemoryBlock::Read64(const u64 addr, u64* value) { u64 realAddr; - *value = Memory.Read64(realAddr = getRealAddr(addr)); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + *value = Memory.Read64(realAddr); + return true; } bool VirtualMemoryBlock::Read128(const u64 addr, u128* value) { u64 realAddr; - *value = Memory.Read128(realAddr = getRealAddr(addr)); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + *value = Memory.Read128(realAddr); + return true; } bool VirtualMemoryBlock::Write8(const u64 addr, const u8 value) { u64 realAddr; - Memory.Write8(realAddr = getRealAddr(addr), value); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + Memory.Write8(realAddr, value); + return true; } bool VirtualMemoryBlock::Write16(const u64 addr, const u16 value) { u64 realAddr; - Memory.Write16(realAddr = getRealAddr(addr), value); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + Memory.Write16(realAddr, value); + return true; } bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value) { u64 realAddr; - Memory.Write32(realAddr = getRealAddr(addr), value); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + Memory.Write32(realAddr, value); + return true; } bool VirtualMemoryBlock::Write64(const u64 addr, const u64 value) { u64 realAddr; - Memory.Write64(realAddr = getRealAddr(addr), value); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + Memory.Write64(realAddr, value); + return true; } bool VirtualMemoryBlock::Write128(const u64 addr, const u128 value) { u64 realAddr; - Memory.Write128(realAddr = getRealAddr(addr), value); - return realAddr != 0; + if(!getRealAddr(addr, realAddr)) + return false; + Memory.Write128(realAddr, value); + return true; } -u64 VirtualMemoryBlock::getRealAddr(u64 addr) +bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result) { for(u32 i=0; i= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) { - return m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr); + result = m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr); + return true; } } - return 0; + return false; } u64 VirtualMemoryBlock::getMappedAddress(u64 realAddress) diff --git a/rpcs3/Emu/Memory/MemoryBlock.h b/rpcs3/Emu/Memory/MemoryBlock.h index 144055716c..1709214878 100644 --- a/rpcs3/Emu/Memory/MemoryBlock.h +++ b/rpcs3/Emu/Memory/MemoryBlock.h @@ -281,8 +281,9 @@ public: virtual bool Write64(const u64 addr, const u64 value); virtual bool Write128(const u64 addr, const u128 value); - // return the real address given a mapped address, if not mapped return 0 - u64 getRealAddr(u64 addr); + // try to get the real address given a mapped address + // return true for success + bool getRealAddr(u64 addr, u64& result); // return the mapped address given a real address, if not mapped return 0 u64 getMappedAddress(u64 realAddress); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 2a463daa48..55a01b8af2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -339,16 +339,16 @@ int cellGcmSetPrepareFlip(mem_ptr_t ctxt, u32 id) { ConLog.Warning("bad flip!"); //cellGcmCallback(ctxt.GetAddr(), current + 8 - end); - //copied: + //copied: - CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; + CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; - const s32 res = ctxt->current - ctxt->begin - ctrl.put; + const s32 res = ctxt->current - ctxt->begin - ctrl.put; - if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res); - ctxt->current = ctxt->begin + res; - ctrl.put = res; - ctrl.get = 0; + if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res); + ctxt->current = ctxt->begin + res; + ctrl.put = res; + ctrl.get = 0; } current = ctxt->current; @@ -575,9 +575,7 @@ int32_t cellGcmIoOffsetToAddress(u32 ioOffset, u64 address) { u64 realAddr; - realAddr = Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ioOffset); - - if (!realAddr) + if (!Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ioOffset, realAddr)) return CELL_GCM_ERROR_FAILURE; Memory.Write64(address, realAddr); diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index 505f67395e..cdc5b31e50 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -322,20 +322,28 @@ void RSXDebugger::GoToGet(wxCommandEvent& event) { if (!RSXReady()) return; CellGcmControl* ctrl = (CellGcmControl*)&Memory[Emu.GetGSManager().GetRender().m_ctrlAddress]; - m_addr = Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ctrl->get); - t_addr->SetValue(wxString::Format("%08x", m_addr)); - UpdateInformation(); - event.Skip(); + u64 realAddr; + if (Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ctrl->get, realAddr)) { + m_addr = realAddr; // WARNING: Potential Truncation? Cast from u64 to u32 + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); + } + // TODO: We should probably throw something? } void RSXDebugger::GoToPut(wxCommandEvent& event) { if (!RSXReady()) return; CellGcmControl* ctrl = (CellGcmControl*)&Memory[Emu.GetGSManager().GetRender().m_ctrlAddress]; - m_addr = Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ctrl->put); - t_addr->SetValue(wxString::Format("%08x", m_addr)); - UpdateInformation(); - event.Skip(); + u64 realAddr; + if (Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + ctrl->put, realAddr)) { + m_addr = realAddr; // WARNING: Potential Truncation? Cast from u64 to u32 + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); + } + // TODO: We should probably throw something? } void RSXDebugger::UpdateInformation() From c2f3f048083ac01c03c135142096e24978d410fb Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 19 May 2014 15:43:41 +0800 Subject: [PATCH 06/23] Add support for m_surface_depth_format 0 --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 8a12c70c60..fd1e6d8bf4 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -719,6 +719,11 @@ void GLGSRender::ExecCMD() switch(m_surface_depth_format) { + case 0: + m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height); + checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)"); + break; + case 1: m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); From e280d54f3f6abd4e1ce540bf08812f346f5a4f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Mon, 19 May 2014 15:05:53 +0200 Subject: [PATCH 07/23] Fix pointers issue in cellUserInfoGetList Solves GetMemFromAddr(0x0) on NPEB01894. --- rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp b/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp index 088eaa1d1c..5fba6b71a0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellUserInfo.cpp @@ -60,9 +60,17 @@ int cellUserInfoGetList(mem32_t listNum, mem_ptr_t listBuf cellUserInfo.Warning("cellUserInfoGetList(listNum_addr=0x%x, listBuf_addr=0x%x, currentUserId_addr=0x%x)", listNum.GetAddr(), listBuf.GetAddr(), currentUserId.GetAddr()); - listNum = 1; - listBuf->userId[0] = 1; - currentUserId = 1; + // If only listNum is NULL, an should will be returned + if (listBuf.IsGood() && !listNum.IsGood()) + return CELL_USERINFO_ERROR_PARAM; + if (listNum.IsGood()) + listNum = 1; + if (listBuf.IsGood()) + listBuf->userId[0] = 1; + + if (currentUserId.IsGood()) + currentUserId = 1; + return CELL_OK; } From 4f961c9e0b7d16363b7121003e3b8f1fdb19d56b Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 19 May 2014 21:14:30 +0800 Subject: [PATCH 08/23] Add comment for depth format 0 --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index fd1e6d8bf4..187d945932 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -719,6 +719,10 @@ void GLGSRender::ExecCMD() switch(m_surface_depth_format) { + // case 0 found in BLJM60410-[Suzukaze no Melt - Days in the Sanctuary] + // [E : RSXThread]: Bad depth format! (0) + // [E : RSXThread]: glEnable: opengl error 0x0506 + // [E : RSXThread]: glDrawArrays: opengl error 0x0506 case 0: m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)"); From 0ba5bb4e7a7631d08ffc106ac1f538096179abf5 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 19 May 2014 22:48:59 +0800 Subject: [PATCH 09/23] Regress fix cellPamf --- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index d961b805cd..617676d2aa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -172,7 +172,7 @@ int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_tpAddr)) + if (!pSelf.IsGood() || !pAddr.IsGood()) return CELL_PAMF_ERROR_INVALID_ARG; if (fileSize) @@ -617,4 +617,4 @@ void cellPamf_init() cellPamf.AddFunc(0x439fba17, cellPamfReaderGetEpIteratorWithTimeStamp); cellPamf.AddFunc(0x1abeb9d6, cellPamfEpIteratorGetEp); cellPamf.AddFunc(0x50b83205, cellPamfEpIteratorMove); -} \ No newline at end of file +} From 4c02c20d841ca72e95473295898d93529b6f201f Mon Sep 17 00:00:00 2001 From: Michael Yu Date: Mon, 19 May 2014 14:56:58 -0700 Subject: [PATCH 10/23] Improve Memory Viewer: There are bugs in text representation. Char display now only displays printable ascii characters. Anything non-printable is printed as '.' as is standard. Additionally, displayed lines are properly delineated with newlines so that we don't wrap on spaces. --- rpcs3/Gui/MemoryViewer.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/rpcs3/Gui/MemoryViewer.cpp b/rpcs3/Gui/MemoryViewer.cpp index ff56509bcf..db9a10901b 100644 --- a/rpcs3/Gui/MemoryViewer.cpp +++ b/rpcs3/Gui/MemoryViewer.cpp @@ -191,20 +191,26 @@ void MemoryViewerPanel::ShowMemory() t_mem_addr_str += wxString::Format("%08x ", addr); } - for(u32 addr = m_addr; addr != m_addr + m_rowcount * m_colcount; addr++) + for (int row = 0; row < m_rowcount; row++) { - if (Memory.IsGoodAddr(addr)) + for (int col = 0; col < m_colcount; col++) { - const u8 rmem = Memory.Read8(addr); - t_mem_hex_str += wxString::Format("%02x ", rmem); - const wxString c_rmem = wxString::Format("%c", rmem); - t_mem_ascii_str += c_rmem.IsEmpty() ? "." : c_rmem; - } - else - { - t_mem_hex_str += "?? "; - t_mem_ascii_str += "?"; + u32 addr = m_addr + row * m_colcount + col; + + if (Memory.IsGoodAddr(addr)) + { + const u8 rmem = Memory.Read8(addr); + t_mem_hex_str += wxString::Format("%02x ", rmem); + const bool isPrintable = rmem >= 32 && rmem <= 126; + t_mem_ascii_str += isPrintable ? std::string(1, rmem) : "."; + } + else + { + t_mem_hex_str += "?? "; + t_mem_ascii_str += "?"; + } } + t_mem_ascii_str += "\r\n"; } t_mem_addr->SetValue(t_mem_addr_str); From 85785b471e28a79bec648fd78b94df11598180bf Mon Sep 17 00:00:00 2001 From: Michael Yu Date: Mon, 19 May 2014 14:58:01 -0700 Subject: [PATCH 11/23] MEMORY: Fixed IsMyAddress bound error (GetEndAddr returns an inclusive value) --- rpcs3/Emu/Memory/Memory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 755dd389f5..cc1c3add1a 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -87,7 +87,7 @@ MemoryBlock* MemoryBlock::SetRange(const u64 start, const u32 size) bool MemoryBlock::IsMyAddress(const u64 addr) { - return mem && addr >= GetStartAddr() && addr < GetEndAddr(); + return mem && addr >= GetStartAddr() && addr <= GetEndAddr(); } template From f67d30571b404b497afceb6a01b54153e2dcd593 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 20 May 2014 21:33:45 +0800 Subject: [PATCH 12/23] Add NV4097_SET_BACK_POLYGON_MODE --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 8 +++++++- rpcs3/Emu/GS/RSXThread.cpp | 5 +++++ rpcs3/Emu/GS/RSXThread.h | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 187d945932..21f62b562a 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -862,9 +862,15 @@ void GLGSRender::ExecCMD() if(m_set_front_polygon_mode) { glPolygonMode(GL_FRONT, m_front_polygon_mode); - checkForGlError("glPolygonMode"); + checkForGlError("glPolygonMode(Front)"); } + if (m_set_back_polygon_mode) + { + glPolygonMode(GL_BACK, m_back_polygon_mode); + checkForGlError("glPolygonMode(Back)"); + } + Enable(m_depth_test_enable, GL_DEPTH_TEST); Enable(m_set_alpha_test, GL_ALPHA_TEST); Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index c5a9233279..814684b30c 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -477,6 +477,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 m_front_polygon_mode = ARGS(0); break; + case NV4097_SET_BACK_POLYGON_MODE: + m_set_back_polygon_mode = true; + m_back_polygon_mode = ARGS(0); + break; + case NV4097_CLEAR_ZCULL_SURFACE: { u32 a0 = ARGS(0); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 7fd5e46bd3..8525193110 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -195,7 +195,9 @@ public: bool m_set_front_polygon_mode; u32 m_front_polygon_mode; - + bool m_set_back_polygon_mode; + u32 m_back_polygon_mode; + u32 m_clear_surface_mask; u32 m_clear_surface_z; u8 m_clear_surface_s; From e0f89beb7dcbb420a29a713dd9472d8e5b3675c7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 21 May 2014 02:08:49 +0800 Subject: [PATCH 13/23] Set default polygon_mode as GL_FILL --- rpcs3/Emu/GS/RSXThread.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 8525193110..7d1e503882 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -430,6 +430,9 @@ protected: m_depth_bounds_max = 1.0; m_restart_index = 0xffffffff; + m_front_polygon_mode = 0x1B02; // GL_FILL + m_back_polygon_mode = 0x1B02; // GL_FILL + m_point_x = 0; m_point_y = 0; @@ -457,6 +460,7 @@ protected: m_set_scissor_horizontal = false; m_set_scissor_vertical = false; m_set_front_polygon_mode = false; + m_set_back_polygon_mode = false; m_set_blend_sfactor = false; m_set_blend_dfactor = false; m_set_stencil_mask = false; From 233b179f65d4fc55128db2d42d28b86e8e7f42dc Mon Sep 17 00:00:00 2001 From: Jake Date: Tue, 20 May 2014 19:54:08 -0500 Subject: [PATCH 14/23] cellPad: Fix logic error in setPressMode and setSensorMode --- rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index f94653db1d..7e3f7bec59 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -353,9 +353,9 @@ int cellPadInfoSensorMode(u32 port_no) int cellPadSetPressMode(u32 port_no, u32 mode) { - sys_io.Log("cellPadSetPressMode(port_no=%d)", port_no); + sys_io.Log("cellPadSetPressMode(port_no=%u, mode=%u)", port_no, mode); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; - if (mode != 0 || mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; + if (mode != 0 && mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; @@ -372,9 +372,9 @@ int cellPadSetPressMode(u32 port_no, u32 mode) int cellPadSetSensorMode(u32 port_no, u32 mode) { - sys_io.Log("cellPadSetPressMode(port_no=%d)", port_no); + sys_io.Log("cellPadSetSensorMode(port_no=%u, mode=%u)", port_no, mode); if (!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; - if (mode != 0 || mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; + if (mode != 0 && mode != 1) return CELL_PAD_ERROR_INVALID_PARAMETER; const PadInfo& rinfo = Emu.GetPadManager().GetInfo(); if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; From afc5294016e78c1e1322337d4f99e3bb74f77513 Mon Sep 17 00:00:00 2001 From: Jake Date: Tue, 20 May 2014 19:56:36 -0500 Subject: [PATCH 15/23] cellPad: Changes to report 0 length if theres no changes --- rpcs3/Emu/Io/PadHandler.h | 4 +- rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp | 115 ++++++++++++++++++++++++------ 2 files changed, 95 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 207d2ae3aa..050a5fce3f 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -126,6 +126,7 @@ struct AnalogStick struct Pad { + bool m_buffer_cleared; u32 m_port_status; u32 m_port_setting; u32 m_device_capability; @@ -165,7 +166,8 @@ struct Pad u16 m_sensor_g; Pad(u32 port_status, u32 port_setting, u32 device_capability, u32 device_type) - : m_port_status(port_status) + : m_buffer_cleared(true) + , m_port_status(port_status) , m_port_setting(port_setting) , m_device_capability(device_capability) , m_device_type(device_type) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index 7e3f7bec59..403fce0ca2 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -75,13 +75,13 @@ int cellPadClearBuf(u32 port_no) if (port_no >= rinfo.max_connect) return CELL_PAD_ERROR_INVALID_PARAMETER; if (port_no >= rinfo.now_connect) return CELL_PAD_ERROR_NO_DEVICE; - //It seems the system is supposed keeps track of previous values, and reports paddata with len 0 if - //nothing has changed. + //Set 'm_buffer_cleared' to force a resend of everything + //might as well also reset everything in our pad 'buffer' to nothing as well - //We can at least reset the pad back to its default values for now std::vector& pads = Emu.GetPadManager().GetPads(); Pad& pad = pads[port_no]; + pad.m_buffer_cleared = true; pad.m_analog_left_x = pad.m_analog_left_y = pad.m_analog_right_x = pad.m_analog_right_y = 128; pad.m_digital_1 = pad.m_digital_2 = 0; @@ -110,10 +110,14 @@ int cellPadGetData(u32 port_no, u32 data_addr) CellPadData data; memset(&data, 0, sizeof(CellPadData)); + u16 d1Initial, d2Initial; + d1Initial = pad.m_digital_1; + d2Initial = pad.m_digital_2; + bool btnChanged = false; for(Button& button : pad.m_buttons) { - //using an if/else here, not doing switch in switch - //plus side is this gives us the ability to check if anything changed eventually + //here we check btns, and set pad accordingly, + //if something changed, set btnChanged if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) { @@ -122,10 +126,22 @@ int cellPadGetData(u32 port_no, u32 data_addr) switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_LEFT: pad.m_press_left = button.m_value; break; - case CELL_PAD_CTRL_DOWN: pad.m_press_down = button.m_value; break; - case CELL_PAD_CTRL_RIGHT: pad.m_press_right = button.m_value; break; - case CELL_PAD_CTRL_UP: pad.m_press_up = button.m_value; break; + case CELL_PAD_CTRL_LEFT: + if (pad.m_press_left != button.m_value) btnChanged = true; + pad.m_press_left = button.m_value; + break; + case CELL_PAD_CTRL_DOWN: + if (pad.m_press_down != button.m_value) btnChanged = true; + pad.m_press_down = button.m_value; + break; + case CELL_PAD_CTRL_RIGHT: + if (pad.m_press_right != button.m_value) btnChanged = true; + pad.m_press_right = button.m_value; + break; + case CELL_PAD_CTRL_UP: + if (pad.m_press_up != button.m_value) btnChanged = true; + pad.m_press_up = button.m_value; + break; //These arent pressure btns case CELL_PAD_CTRL_R3: case CELL_PAD_CTRL_L3: @@ -141,14 +157,38 @@ int cellPadGetData(u32 port_no, u32 data_addr) switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_SQUARE: pad.m_press_square = button.m_value; break; - case CELL_PAD_CTRL_CROSS: pad.m_press_cross = button.m_value; break; - case CELL_PAD_CTRL_CIRCLE: pad.m_press_circle = button.m_value; break; - case CELL_PAD_CTRL_TRIANGLE: pad.m_press_triangle = button.m_value; break; - case CELL_PAD_CTRL_R1: pad.m_press_R1 = button.m_value; break; - case CELL_PAD_CTRL_L1: pad.m_press_L1 = button.m_value; break; - case CELL_PAD_CTRL_R2: pad.m_press_R2 = button.m_value; break; - case CELL_PAD_CTRL_L2: pad.m_press_L2 = button.m_value; break; + case CELL_PAD_CTRL_SQUARE: + if (pad.m_press_square != button.m_value) btnChanged = true; + pad.m_press_square = button.m_value; + break; + case CELL_PAD_CTRL_CROSS: + if (pad.m_press_cross != button.m_value) btnChanged = true; + pad.m_press_cross = button.m_value; + break; + case CELL_PAD_CTRL_CIRCLE: + if (pad.m_press_circle != button.m_value) btnChanged = true; + pad.m_press_circle = button.m_value; + break; + case CELL_PAD_CTRL_TRIANGLE: + if (pad.m_press_triangle != button.m_value) btnChanged = true; + pad.m_press_triangle = button.m_value; + break; + case CELL_PAD_CTRL_R1: + if (pad.m_press_R1 != button.m_value) btnChanged = true; + pad.m_press_R1 = button.m_value; + break; + case CELL_PAD_CTRL_L1: + if (pad.m_press_L1 != button.m_value) btnChanged = true; + pad.m_press_L1 = button.m_value; + break; + case CELL_PAD_CTRL_R2: + if (pad.m_press_R2 != button.m_value) btnChanged = true; + pad.m_press_R2 = button.m_value; + break; + case CELL_PAD_CTRL_L2: + if (pad.m_press_L2 != button.m_value) btnChanged = true; + pad.m_press_L2 = button.m_value; + break; default: break; } } @@ -165,15 +205,44 @@ int cellPadGetData(u32 port_no, u32 data_addr) { switch (stick.m_offset) { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: pad.m_analog_left_x = stick.m_value; break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: pad.m_analog_left_y = stick.m_value; break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: pad.m_analog_right_x = stick.m_value; break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: pad.m_analog_right_y = stick.m_value; break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: + if (pad.m_analog_left_x != stick.m_value) btnChanged = true; + pad.m_analog_left_x = stick.m_value; + break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: + if (pad.m_analog_left_y != stick.m_value) btnChanged = true; + pad.m_analog_left_y = stick.m_value; + break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: + if (pad.m_analog_right_x != stick.m_value) btnChanged = true; + pad.m_analog_right_x = stick.m_value; + break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: + if (pad.m_analog_right_y != stick.m_value) btnChanged = true; + pad.m_analog_right_y = stick.m_value; + break; default: break; } } - - data.len = pad.m_buttons.size(); + if (d1Initial != pad.m_digital_1 || d2Initial != pad.m_digital_2) + { + btnChanged = true; + } + + //not sure if this should officially change with capabilities/portsettings :( + data.len = CELL_PAD_MAX_CODES; + + //report len 0 if nothing changed and if we havent recently cleared buffer + if (pad.m_buffer_cleared) + { + pad.m_buffer_cleared = false; + } + else if (!btnChanged) + { + data.len = 0; + } + + //lets still send new data anyway, not sure whats expected still data.button[CELL_PAD_BTN_OFFSET_DIGITAL1] = pad.m_digital_1; data.button[CELL_PAD_BTN_OFFSET_DIGITAL2] = pad.m_digital_2; data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = pad.m_analog_right_x; From 967935d3893ce1c4ec58e8d11190da15c176ee68 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 21 May 2014 17:55:44 +0800 Subject: [PATCH 16/23] Enable GL_SCISSOR_TEST and add glLogicOp --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 43 ++++++++++++++++++++-------------- rpcs3/Emu/GS/RSXThread.cpp | 4 ++++ rpcs3/Emu/GS/RSXThread.h | 4 +++- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 21f62b562a..70c263493a 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -821,12 +821,6 @@ void GLGSRender::ExecCMD() //checkForGlError("glViewport"); } - if(m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - checkForGlError("glScissor"); - } - if(m_clear_surface_mask) { GLbitfield f = 0; @@ -859,18 +853,6 @@ void GLGSRender::ExecCMD() glClear(f); } - if(m_set_front_polygon_mode) - { - glPolygonMode(GL_FRONT, m_front_polygon_mode); - checkForGlError("glPolygonMode(Front)"); - } - - if (m_set_back_polygon_mode) - { - glPolygonMode(GL_BACK, m_back_polygon_mode); - checkForGlError("glPolygonMode(Back)"); - } - Enable(m_depth_test_enable, GL_DEPTH_TEST); Enable(m_set_alpha_test, GL_ALPHA_TEST); Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); @@ -879,6 +861,7 @@ void GLGSRender::ExecCMD() Enable(m_set_cull_face_enable, GL_CULL_FACE); Enable(m_set_dither, GL_DITHER); Enable(m_set_stencil_test, GL_STENCIL_TEST); + Enable(m_set_scissor_horizontal && m_set_scissor_vertical, GL_SCISSOR_TEST); Enable(m_set_line_smooth, GL_LINE_SMOOTH); Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH); Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL); @@ -900,6 +883,30 @@ void GLGSRender::ExecCMD() checkForGlError("glEnable"); + + if (m_set_front_polygon_mode) + { + glPolygonMode(GL_FRONT, m_front_polygon_mode); + checkForGlError("glPolygonMode(Front)"); + } + + if (m_set_back_polygon_mode) + { + glPolygonMode(GL_BACK, m_back_polygon_mode); + checkForGlError("glPolygonMode(Back)"); + } + + if (m_set_logic_op) + { + glLogicOp(m_logic_op); + checkForGlError("glLogicOp"); + } + + if (m_set_scissor_horizontal && m_set_scissor_vertical) + { + glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + checkForGlError("glScissor"); + } if(m_set_two_sided_stencil_test_enable) { if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 814684b30c..bbdd53d382 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -762,6 +762,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 m_set_logic_op = ARGS(0) ? true : false; break; + case NV4097_SET_LOGIC_OP: + m_logic_op = ARGS(0); + break; + case NV4097_SET_CULL_FACE_ENABLE: m_set_cull_face_enable = ARGS(0) ? true : false; break; diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 7d1e503882..6a4030a89c 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -166,7 +166,6 @@ public: bool m_set_blend; bool m_set_depth_bounds_test; bool m_depth_test_enable; - bool m_set_logic_op; bool m_set_cull_face_enable; bool m_set_dither; bool m_set_stencil_test; @@ -198,6 +197,9 @@ public: bool m_set_back_polygon_mode; u32 m_back_polygon_mode; + bool m_set_logic_op; + u32 m_logic_op; + u32 m_clear_surface_mask; u32 m_clear_surface_z; u8 m_clear_surface_s; From b95667563faa2d29f8dfaeecf08aaa97ccc72ffb Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 22 May 2014 00:20:13 +0800 Subject: [PATCH 17/23] Code cleanup and added glPolygonOffset --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 29 +++++++++++++++++++++-------- rpcs3/Emu/GS/GL/GLGSRender.h | 2 +- rpcs3/Emu/GS/RSXThread.h | 11 +++++++++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 70c263493a..8ba1410e4c 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -581,7 +581,7 @@ void GLGSRender::WriteColourBufferD() checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); } -void GLGSRender::WriteBuffers() +void GLGSRender::WriteColorBuffers() { glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_ALIGNMENT, 4); @@ -641,7 +641,6 @@ void GLGSRender::OnInitThread() InitProcTable(); glEnable(GL_TEXTURE_2D); - glEnable(GL_SCISSOR_TEST); #ifdef _WIN32 glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); @@ -773,8 +772,10 @@ void GLGSRender::ExecCMD() } m_fbo.Bind(); + if(Ini.GSDumpDepthBuffer.GetValue()) WriteDepthBuffer(); + static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; switch(m_surface_colour_target) @@ -813,8 +814,6 @@ void GLGSRender::ExecCMD() checkForGlError("glColorMask"); } - //glFrontFace(m_front_face); - if(m_set_viewport_horizontal && m_set_viewport_vertical) { //glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); @@ -859,6 +858,7 @@ void GLGSRender::ExecCMD() Enable(m_set_blend, GL_BLEND); Enable(m_set_logic_op, GL_LOGIC_OP); Enable(m_set_cull_face_enable, GL_CULL_FACE); + //Enable(m_set_front_face, GL_FRONT_FACE); // glEnable : OpenGL error 0x0500 Enable(m_set_dither, GL_DITHER); Enable(m_set_stencil_test, GL_STENCIL_TEST); Enable(m_set_scissor_horizontal && m_set_scissor_vertical, GL_SCISSOR_TEST); @@ -867,7 +867,7 @@ void GLGSRender::ExecCMD() Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL); Enable(m_set_poly_offset_line, GL_POLYGON_OFFSET_LINE); Enable(m_set_poly_offset_point, GL_POLYGON_OFFSET_POINT); - //Enable(m_set_restart_index, GL_PRIMITIVE_RESTART); //Requires OpenGL 3.1+ + //Enable(m_set_restart_index, GL_PRIMITIVE_RESTART); // Requires OpenGL 3.1+ if(m_set_clip_plane) { @@ -896,6 +896,12 @@ void GLGSRender::ExecCMD() checkForGlError("glPolygonMode(Back)"); } + if (m_set_poly_offset_scale_factor && m_set_poly_offset_bias) + { + glPolygonOffset(m_set_poly_offset_scale_factor, m_set_poly_offset_bias); + checkForGlError("glPolygonOffset"); + } + if (m_set_logic_op) { glLogicOp(m_logic_op); @@ -907,6 +913,7 @@ void GLGSRender::ExecCMD() glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); checkForGlError("glScissor"); } + if(m_set_two_sided_stencil_test_enable) { if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) @@ -1029,6 +1036,12 @@ void GLGSRender::ExecCMD() checkForGlError("glCullFace"); } + if (m_set_front_face) + { + //glFrontFace(m_front_face); // glFrontFace : OpenGL error 0x0500 + checkForGlError("glFrontFace"); + } + if(m_set_alpha_func && m_set_alpha_ref) { glAlphaFunc(m_alpha_func, m_alpha_ref/255.0f); @@ -1052,7 +1065,7 @@ void GLGSRender::ExecCMD() if(m_set_restart_index) { ConLog.Warning("m_set_restart_index requires glPrimitiveRestartIndex()"); - //glPrimitiveRestartIndex(m_restart_index); //Requires OpenGL 3.1+ + //glPrimitiveRestartIndex(m_restart_index); // Requires OpenGL 3.1+ //checkForGlError("glPrimitiveRestartIndex"); } @@ -1117,8 +1130,8 @@ void GLGSRender::ExecCMD() DisableVertexData(); } - if(Ini.GSDumpColorBuffers.GetValue()) - WriteBuffers(); + if (Ini.GSDumpColorBuffers.GetValue()) + WriteColorBuffers(); } void GLGSRender::Flip() diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index 819d95ff1c..8839d578ea 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -827,11 +827,11 @@ private: virtual void Close(); bool LoadProgram(); void WriteDepthBuffer(); + void WriteColorBuffers(); void WriteColourBufferA(); void WriteColourBufferB(); void WriteColourBufferC(); void WriteColourBufferD(); - void WriteBuffers(); void DrawObjects(); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 6a4030a89c..1b2a675002 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -175,6 +175,11 @@ public: bool m_set_poly_offset_line; bool m_set_poly_offset_point; + bool m_set_poly_offset_scale_factor; + u32 m_poly_offset_scale_factor; + bool m_set_poly_offset_bias; + u32 m_poly_offset_bias; + bool m_set_restart_index; u32 m_restart_index; @@ -384,6 +389,7 @@ public: u32 m_surface_colour_target; + bool m_set_front_face; u32 m_front_face; u8 m_begin_end; @@ -428,6 +434,9 @@ protected: m_clear_z = 0xffffff; m_clear_s = 0; + m_poly_offset_scale_factor = 0; + m_poly_offset_bias = 0; + m_depth_bounds_min = 0.0; m_depth_bounds_max = 1.0; m_restart_index = 0xffffffff; @@ -500,6 +509,8 @@ protected: m_set_poly_offset_fill = false; m_set_poly_offset_line = false; m_set_poly_offset_point = false; + m_set_poly_offset_scale_factor = false; + m_set_poly_offset_bias = false; m_set_restart_index = false; m_clear_surface_mask = 0; From 3445f8a49f0a4f3ca33fec15123b8504ed879a3f Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 22 May 2014 00:48:25 +0800 Subject: [PATCH 18/23] There is no glEnable(GL_FRONT_FACE) --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 8ba1410e4c..60a72dcee7 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -858,7 +858,6 @@ void GLGSRender::ExecCMD() Enable(m_set_blend, GL_BLEND); Enable(m_set_logic_op, GL_LOGIC_OP); Enable(m_set_cull_face_enable, GL_CULL_FACE); - //Enable(m_set_front_face, GL_FRONT_FACE); // glEnable : OpenGL error 0x0500 Enable(m_set_dither, GL_DITHER); Enable(m_set_stencil_test, GL_STENCIL_TEST); Enable(m_set_scissor_horizontal && m_set_scissor_vertical, GL_SCISSOR_TEST); From 94393ff4ea0b52f439ffa5857ddd2dd0a90187c3 Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 22 May 2014 01:08:46 +0800 Subject: [PATCH 19/23] Re-enable glFrontFace with sanity check --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 60a72dcee7..26620efacc 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1037,8 +1037,12 @@ void GLGSRender::ExecCMD() if (m_set_front_face) { - //glFrontFace(m_front_face); // glFrontFace : OpenGL error 0x0500 - checkForGlError("glFrontFace"); + // Sanity check . Disgaea 3 return 0x1d0 here and cause openGL 0x0500 + if (m_front_face == GL_CW || m_front_face == GL_CCW) + { + glFrontFace(m_front_face); + checkForGlError("glFrontFace"); + } } if(m_set_alpha_func && m_set_alpha_ref) From a2af749e717ed0596c96c53198acac2c2f350592 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 23 May 2014 01:39:56 +0800 Subject: [PATCH 20/23] Replace slow glReadpixels routine with glBlitframebuffer for non-MRT --- rpcs3/Emu/GS/GL/GLGSRender.cpp | 40 +++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 26620efacc..26df787b92 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1139,6 +1139,28 @@ void GLGSRender::ExecCMD() void GLGSRender::Flip() { + // Fast path for non-MRT using glBlitFramebuffer + // TODO: check for MRT samples + if (m_fbo.IsCreated() && (m_surface_colour_target == CELL_GCM_SURFACE_TARGET_0 || m_surface_colour_target == CELL_GCM_SURFACE_TARGET_1)) + { + GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); + // Renderbuffer is upside turn , swapped srcY0 and srcY1 + GLfbo::Blit(0, RSXThread::m_height, RSXThread::m_width, 0, 0, 0, RSXThread::m_width, RSXThread::m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_fbo.Bind(); + + for (uint i = 0; iFlip(m_context); + + m_fbo.Bind(); + + return; + } + if(m_set_scissor_horizontal && m_set_scissor_vertical) { glScissor(0, 0, RSXThread::m_width, RSXThread::m_height); @@ -1228,24 +1250,6 @@ void GLGSRender::Flip() glEnd(); } - /*GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); - GLfbo::Blit( - m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h, - m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h, - GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);*/ - if(m_fbo.IsCreated()) - m_fbo.Bind(); - - for(uint i=0; iFlip(m_context); - - if(m_fbo.IsCreated()) - m_fbo.Bind(); - if(m_set_scissor_horizontal && m_set_scissor_vertical) { glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); From 6520b8f06d1022112ef314766dabd3521d169243 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 23 May 2014 23:51:55 +0800 Subject: [PATCH 21/23] Add 960x540 natvie resolution support --- rpcs3/Emu/GS/sysutil_video.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/GS/sysutil_video.h b/rpcs3/Emu/GS/sysutil_video.h index ce92847a29..3488427c25 100644 --- a/rpcs3/Emu/GS/sysutil_video.h +++ b/rpcs3/Emu/GS/sysutil_video.h @@ -232,6 +232,7 @@ static const CellVideoOutResolution ResolutionTable[] = {1440, 1080}, //11 - 6 {1280, 1080}, //12 - 7 {960, 1080}, //13 - 8 + {960, 540}, //14 - 9 }; inline static u32 ResolutionIdToNum(u32 id) @@ -252,9 +253,10 @@ inline static u32 ResolutionIdToNum(u32 id) 6, //11 7, //12 8, //13 + 9, //14 }; - return id <= 13 ? res[id] : 0; + return id <= 14 ? res[id] : 0; } inline static u32 ResolutionNumToId(u32 num) @@ -270,7 +272,8 @@ inline static u32 ResolutionNumToId(u32 num) 11, 12, 13, + 14, }; - return num <= 8 ? res[num] : 0; + return num <= 9 ? res[num] : 0; } From 493bf93a5ae587c1cf328f5352d5a9560f904279 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 23 May 2014 09:18:29 -0700 Subject: [PATCH 22/23] Update LR only when cond passes. It should not be updated otherwise. In most cases, won't matter. Also, reorder slightly so SetBranch() can safely set PC directly. --- rpcs3/Emu/Cell/PPUInterpreter.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 421f7603a4..544b8b5303 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2084,9 +2084,10 @@ private: { if (CheckCondition(bo, bi)) { + const u64 nextLR = CPU.PC + 4; CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd), lk); + if(lk) CPU.LR = nextLR; } - if(lk) CPU.LR = CPU.PC + 4; } void SC(u32 sc_code) { @@ -2108,8 +2109,9 @@ private: } void B(s32 ll, u32 aa, u32 lk) { + const u64 nextLR = CPU.PC + 4; CPU.SetBranch(branchTarget(aa ? 0 : CPU.PC, ll), lk); - if(lk) CPU.LR = CPU.PC + 4; + if(lk) CPU.LR = nextLR; } void MCRF(u32 crfd, u32 crfs) { @@ -2119,9 +2121,10 @@ private: { if (CheckCondition(bo, bi)) { + const u64 nextLR = CPU.PC + 4; CPU.SetBranch(branchTarget(0, CPU.LR), true); + if(lk) CPU.LR = nextLR; } - if(lk) CPU.LR = CPU.PC + 4; } void CRNOR(u32 crbd, u32 crba, u32 crbb) { @@ -2171,9 +2174,10 @@ private: { if(bo & 0x10 || CPU.IsCR(bi) == (bo & 0x8)) { + const u64 nextLR = CPU.PC + 4; CPU.SetBranch(branchTarget(0, CPU.CTR), true); + if(lk) CPU.LR = nextLR; } - if(lk) CPU.LR = CPU.PC + 4; } void RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { From 82d60ee48ddd2375bd0d9594877345c8a27fb39e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 23 May 2014 09:19:18 -0700 Subject: [PATCH 23/23] Do not set the CA bit in ADD(). Thanks Ashe`. --- rpcs3/Emu/Cell/PPUInterpreter.h | 1 - 1 file changed, 1 deletion(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 544b8b5303..0f38781fa2 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2820,7 +2820,6 @@ private: const u64 RA = CPU.GPR[ra]; const u64 RB = CPU.GPR[rb]; CPU.GPR[rd] = RA + RB; - CPU.XER.CA = CPU.IsCarry(RA, RB); if(oe) UNK("addo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); }