1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Check for overlapping frame buffers in FrameBufferList::removeIntersections()

Fixed Mario Tennis - missing bottom half of scoreboard #1564

Problem:
Top Gear Hyper Bike has overlapping frame buffers.
That is start address of a buffer points on last line in previous buffer.
When new buffer intersects with prevois one, plugin removes old buffer.
That causes black screen in case of Top Gear Hyper Bike.

FrameBuffer::updateEndAddress() was modified in commit 17eb8696ea to fix it.
It sets buffer end address using buffer height - 1.
This fix causes issue with Mario Tennis scoreboard #1564
HW buffer is not detected because end address is wrong.

Solution:
Add another test for intersecting buffers.
It checks that the buffers are not just arbitrary intersected ones,
but it is sequence of two slighly overlapping buffers.
In that case buffer is not removed, but its end address is corrected,
because buffers address space must not intersect.
This commit is contained in:
Sergey Lipskiy 2017-09-25 22:24:30 +07:00
parent 032da85357
commit 57da925a14

View File

@ -182,7 +182,7 @@ void FrameBuffer::init(u32 _address, u16 _format, u16 _size, u16 _width, bool _c
void FrameBuffer::updateEndAddress()
{
const u32 height = max(1U, m_height - 1);
const u32 height = max(1U, m_height);
m_endAddress = min(RDRAMSize, m_startAddress + (((m_width * height) << m_size >> 1) - 1));
}
@ -515,6 +515,20 @@ FrameBuffer * FrameBufferList::findBuffer(u32 _startAddress)
return nullptr;
}
inline
bool isOverlapping(const FrameBuffer * _buf1, const FrameBuffer * _buf2)
{
if (_buf1->m_endAddress < _buf2->m_endAddress && _buf1->m_width == _buf2->m_width && _buf1->m_size == _buf2->m_size) {
const u32 diff = _buf1->m_endAddress - _buf2->m_startAddress + 1;
const u32 stride = _buf1->m_width << _buf1->m_size >> 1;
if ((diff % stride == 0) && (diff / stride < 5))
return true;
else
return false;
}
return false;
}
void FrameBufferList::removeIntersections()
{
assert(!m_list.empty());
@ -524,8 +538,17 @@ void FrameBufferList::removeIntersections()
--iter;
if (&(*iter) == m_pCurrent)
continue;
if ((iter->m_startAddress <= m_pCurrent->m_startAddress && iter->m_endAddress >= m_pCurrent->m_startAddress) || // [ { ]
(m_pCurrent->m_startAddress <= iter->m_startAddress && m_pCurrent->m_endAddress >= iter->m_startAddress)) { // { [ }
if (iter->m_startAddress <= m_pCurrent->m_startAddress && iter->m_endAddress >= m_pCurrent->m_startAddress) { // [ { ]
if (isOverlapping(&(*iter), m_pCurrent)) {
iter->m_endAddress = m_pCurrent->m_startAddress - 1;
continue;
}
iter = m_list.erase(iter);
} else if (m_pCurrent->m_startAddress <= iter->m_startAddress && m_pCurrent->m_endAddress >= iter->m_startAddress) { // { [ }
if (isOverlapping(m_pCurrent, &(*iter))) {
m_pCurrent->m_endAddress = iter->m_startAddress - 1;
continue;
}
iter = m_list.erase(iter);
}
} while (iter != m_list.begin());