mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +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:
parent
032da85357
commit
57da925a14
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue
Block a user