Add compat flag to allow virtual framebuffer readbacks (auto-create fb from readback destination). Does not yet work outside VRAM but should fix Digimon Adventure.

This commit is contained in:
Henrik Rydgård 2018-11-05 00:28:01 +01:00
parent cf653b7631
commit 7abbc1bebd
5 changed files with 46 additions and 5 deletions

View File

@ -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) {

View File

@ -59,6 +59,7 @@ struct CompatFlags {
bool DisableAccurateDepth;
bool MGS2AcidHack;
bool SonicRivalsHack;
bool BlockTransferAllowCreateFB;
};
class IniFile;

View File

@ -412,8 +412,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;
@ -1282,6 +1281,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<u32, u32>(src, dst));
}
@ -1337,7 +1337,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;
@ -1417,6 +1418,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;

View File

@ -344,7 +344,7 @@ protected:
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;

View File

@ -339,4 +339,10 @@ ULUS10077 = true
ULES00622 = true # SR1
ULUS10195 = true # SR1
ULUS10323 = true # SR2
ULES00940 = true # SR2
ULES00940 = true # SR2
[BlockTransferAllowCreateFB]
NPJH50686 = true # Digimon Adventures (JP)
ULJS00078 = true # MotoGP
ULUS10153 = true # MotoGP
UCES00373 = true # MotoGP