diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 1cc0ccb2190a..692993973c9e 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -59,6 +59,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "DisableAccurateDepth", &flags_.DisableAccurateDepth); CheckSetting(iniFile, gameID, "MGS2AcidHack", &flags_.MGS2AcidHack); CheckSetting(iniFile, gameID, "SonicRivalsHack", &flags_.SonicRivalsHack); + CheckSetting(iniFile, gameID, "BlockTransferAllowCreateFB", &flags_.BlockTransferAllowCreateFB); } void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index f65c68efda0c..97373b94182a 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -59,6 +59,7 @@ struct CompatFlags { bool DisableAccurateDepth; bool MGS2AcidHack; bool SonicRivalsHack; + bool BlockTransferAllowCreateFB; }; class IniFile; diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index d0ae91c2d005..8f61137448ef 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -418,8 +418,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // None found? Create one. if (!vfb) { - vfb = new VirtualFramebuffer(); - memset(vfb, 0, sizeof(VirtualFramebuffer)); + vfb = new VirtualFramebuffer{}; vfb->fbo = nullptr; vfb->fb_address = params.fb_address; vfb->fb_stride = params.fb_stride; @@ -1284,6 +1283,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // MotoGP workaround - it copies a framebuffer to memory and then displays it. // TODO: It's rare anyway, but the game could modify the RAM and then we'd display the wrong thing. // Unfortunately, that would force 1x render resolution. + // NOTE: With the BlockTransferAllowCreateFB hack, we might be able to remove this. if (Memory::IsRAMAddress(dst)) { knownFramebufferRAMCopies_.insert(std::pair(src, dst)); } @@ -1339,7 +1339,8 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, } } -void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const { +// Can't be const, in case it has to create a vfb unfortunately. +void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) { u32 dstYOffset = -1; u32 dstXOffset = -1; u32 srcYOffset = -1; @@ -1419,6 +1420,38 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst } } + if (!dstBuffer && PSP_CoreParameter().compat.flags().BlockTransferAllowCreateFB) { + float renderWidthFactor = renderWidth_ / 480.0f; + float renderHeightFactor = renderHeight_ / 272.0f; + // A target for the destination is missing - so just create one! + // Make sure this one would be found by the algorithm above so we wouldn't + // create a new one each frame. + VirtualFramebuffer *vfb = new VirtualFramebuffer{}; + vfb->fbo = nullptr; + vfb->fb_address = dstBasePtr; // NOTE - not necessarily in VRAM! + vfb->fb_stride = dstStride; + vfb->z_address = 0; + vfb->z_stride =0; + vfb->width = std::max(dstWidth, dstStride); + vfb->height = dstHeight; + vfb->newWidth = vfb->width; + vfb->newHeight = vfb->height; + vfb->lastFrameNewSize = gpuStats.numFlips; + vfb->renderWidth = (u16)(vfb->width * renderWidthFactor); + vfb->renderHeight = (u16)(vfb->height * renderHeightFactor); + vfb->bufferWidth = vfb->width; + vfb->bufferHeight = vfb->height; + vfb->format = bpp == 4 ? GE_FORMAT_8888 : GE_FORMAT_5551; // TODO: We don't really know the 16-bit format here.. at all. Can only guess when it gets used later! + vfb->drawnFormat = GE_FORMAT_8888; + vfb->usageFlags = FB_USAGE_RENDERTARGET; + SetColorUpdated(vfb, 0); + textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); + vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth }); + vfbs_.push_back(vfb); + dstBuffer = vfb; + } + dstBuffer->last_frame_used = gpuStats.numFlips; + if (dstYOffset != (u32)-1) { dstY += dstYOffset; dstX += dstXOffset; diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 4f19debd01f8..1853bea9ad32 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -346,7 +346,7 @@ class FramebufferManagerCommon { bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const; void DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb); - void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const; + void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp); VirtualFramebuffer *FindDownloadTempBuffer(VirtualFramebuffer *vfb); virtual bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0; virtual void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0; diff --git a/assets/compat.ini b/assets/compat.ini index 72ac34b4c946..69e6f10a695f 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -339,4 +339,10 @@ ULUS10077 = true ULES00622 = true # SR1 ULUS10195 = true # SR1 ULUS10323 = true # SR2 -ULES00940 = true # SR2 \ No newline at end of file +ULES00940 = true # SR2 + +[BlockTransferAllowCreateFB] +NPJH50686 = true # Digimon Adventures (JP) +ULJS00078 = true # MotoGP +ULUS10153 = true # MotoGP +UCES00373 = true # MotoGP