diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 58258e30..1cae9bc3 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -95,7 +95,7 @@ DepthBufferToRDRAM g_dbToRDRAM; #endif RDRAMtoFrameBuffer g_RDRAMtoFB; -FrameBuffer::FrameBuffer() : m_cleared(false), m_changed(false), m_isDepthBuffer(false), m_copiedToRDRAM(false), m_pLoadTile(NULL), m_pDepthBuffer(NULL), m_pResolveTexture(NULL), m_resolveFBO(0), m_resolved(false) +FrameBuffer::FrameBuffer() : m_cleared(false), m_changed(false), m_isDepthBuffer(false), m_copiedToRDRAM(false), m_needHeightCorrection(false), m_pLoadTile(NULL), m_pDepthBuffer(NULL), m_pResolveTexture(NULL), m_resolveFBO(0), m_resolved(false) { m_pTexture = textureCache().addFrameBufferTexture(); glGenFramebuffers(1, &m_FBO); @@ -104,7 +104,8 @@ FrameBuffer::FrameBuffer() : m_cleared(false), m_changed(false), m_isDepthBuffer FrameBuffer::FrameBuffer(FrameBuffer && _other) : m_startAddress(_other.m_startAddress), m_endAddress(_other.m_endAddress), m_size(_other.m_size), m_width(_other.m_width), m_height(_other.m_height), m_fillcolor(_other.m_fillcolor), - m_scaleX(_other.m_scaleX), m_scaleY(_other.m_scaleY), m_cleared(_other.m_cleared), m_changed(_other.m_changed), m_cfb(_other.m_cfb), m_isDepthBuffer(_other.m_isDepthBuffer), m_copiedToRDRAM(_other.m_copiedToRDRAM), + m_scaleX(_other.m_scaleX), m_scaleY(_other.m_scaleY), m_cleared(_other.m_cleared), m_changed(_other.m_changed), m_cfb(_other.m_cfb), m_isDepthBuffer(_other.m_isDepthBuffer), + m_copiedToRDRAM(_other.m_copiedToRDRAM), m_needHeightCorrection(_other.m_needHeightCorrection), m_FBO(_other.m_FBO), m_pLoadTile(_other.m_pLoadTile), m_pTexture(_other.m_pTexture), m_pDepthBuffer(_other.m_pDepthBuffer), m_pResolveTexture(_other.m_pResolveTexture), m_resolveFBO(_other.m_resolveFBO), m_resolved(_other.m_resolved) { @@ -250,6 +251,28 @@ void FrameBufferList::setBufferChanged() m_pCurrent->m_changed = true; } +void FrameBufferList::setNeedHeightCorrection(bool _needCorrection) +{ + if (m_pCurrent != NULL) + m_pCurrent->m_needHeightCorrection = _needCorrection; +} + +void FrameBufferList::correctHeight() +{ + if (m_pCurrent == NULL) + return; + if (m_pCurrent->m_changed) { + m_pCurrent->m_needHeightCorrection = false; + return; + } + if (m_pCurrent->m_needHeightCorrection && m_pCurrent->m_width == gDP.scissor.lrx) { + m_pCurrent->m_height = (u32)gDP.scissor.lry; + m_pCurrent->m_needHeightCorrection = false; + gSP.changed |= CHANGED_VIEWPORT; + } +} + + void FrameBufferList::clearBuffersChanged() { gDP.colorImage.changed = FALSE; diff --git a/FrameBuffer.h b/FrameBuffer.h index 4d184add..eb146fbf 100644 --- a/FrameBuffer.h +++ b/FrameBuffer.h @@ -25,6 +25,7 @@ struct FrameBuffer bool m_cfb; bool m_isDepthBuffer; bool m_copiedToRDRAM; + bool m_needHeightCorrection; GLuint m_FBO; gDPTile *m_pLoadTile; @@ -54,6 +55,8 @@ public: void renderBuffer(u32 _address); bool isFboMode() const {return m_drawBuffer == GL_FRAMEBUFFER;} void setBufferChanged(); + void setNeedHeightCorrection(bool _needCorrection); + void correctHeight(); void clearBuffersChanged(); static FrameBufferList & get() diff --git a/gDP.cpp b/gDP.cpp index a1b86e58..2682ba6e 100644 --- a/gDP.cpp +++ b/gDP.cpp @@ -265,6 +265,7 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) address = RSP_SegmentToPhysical( address ); if (gDP.colorImage.address != address || gDP.colorImage.width != width || gDP.colorImage.size != size) { + bool bNeedHeightCorrection = false; u32 height = 1; if (width == VI.width) height = VI.height; @@ -275,12 +276,15 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) height = gDP.scissor.lry; else if (width <= 64) height = width; - else + else { height = gSP.viewport.height; + bNeedHeightCorrection = true; + } if (config.frameBufferEmulation.enable) // && address != gDP.depthImageAddress) { frameBufferList().saveBuffer(address, (u16)format, (u16)size, (u16)width, height, false); + frameBufferList().setNeedHeightCorrection(bNeedHeightCorrection); gDP.colorImage.height = 0; } else gDP.colorImage.height = height; @@ -843,6 +847,8 @@ void gDPSetScissor( u32 mode, f32 ulx, f32 uly, f32 lrx, f32 lry ) gDP.changed |= CHANGED_SCISSOR; + frameBufferList().correctHeight(); + #ifdef DEBUG DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPSetScissor( %s, %.2f, %.2f, %.2f, %.2f );\n", ScissorModeText[gDP.scissor.mode],