Improve match of MxRegion::vtable18 (#266)

* Match MxRegionTopBottom::FUN_100c5280

* Resolve OtherAppend/Append

* Remove old code

* MxRegion::vtable18 up to 80%, refactor MxRect
This commit is contained in:
Christian Semmler 2023-11-06 18:12:09 -05:00 committed by GitHub
parent d5cf23bada
commit 23f4fda304
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 123 additions and 107 deletions

View file

@ -82,8 +82,8 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam)
}
if (this->m_videoParam.flags().GetFullScreen()) {
MxS32 width = this->m_videoParam.GetRect().m_right - this->m_videoParam.GetRect().m_left + 1;
MxS32 height = this->m_videoParam.GetRect().m_bottom - this->m_videoParam.GetRect().m_top + 1;
MxS32 width = this->m_videoParam.GetRect().GetWidth();
MxS32 height = this->m_videoParam.GetRect().GetHeight();
if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))
goto done;
@ -129,8 +129,8 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam)
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
ddsd.dwWidth = this->m_videoParam.GetRect().m_right - this->m_videoParam.GetRect().m_left + 1;
ddsd.dwHeight = this->m_videoParam.GetRect().m_bottom - this->m_videoParam.GetRect().m_top + 1;
ddsd.dwWidth = this->m_videoParam.GetRect().GetWidth();
ddsd.dwHeight = this->m_videoParam.GetRect().GetHeight();
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN;
if (!this->m_videoParam.flags().GetBackBuffers())

View file

@ -23,6 +23,14 @@ public:
this->m_bottom = p_size.m_height;
}
MxRect32(const MxRect32& p_a, const MxRect32& p_b)
{
m_left = Max(p_a.m_left, p_b.m_left);
m_top = Max(p_a.m_top, p_b.m_top);
m_right = Min(p_a.m_right, p_b.m_right);
m_bottom = Min(p_a.m_bottom, p_b.m_bottom);
}
inline void SetPoint(const MxPoint32& p_point)
{
this->m_left = p_point.m_x;
@ -35,10 +43,39 @@ public:
this->m_bottom = p_size.m_height;
}
inline MxBool IsValid() { return m_left < m_right && m_top < m_bottom; }
inline MxBool IntersectsWith(const MxRect32& p_rect)
{
return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom;
}
inline void UpdateBounds(const MxRect32& p_rect)
{
m_left = Min(m_left, p_rect.m_left);
m_top = Min(m_top, p_rect.m_top);
m_right = Max(m_right, p_rect.m_right);
m_bottom = Max(m_bottom, p_rect.m_bottom);
}
inline MxS32 GetWidth() { return (m_right - m_left) + 1; }
inline MxS32 GetHeight() { return (m_bottom - m_top) + 1; }
inline MxPoint32 GetPoint() { return MxPoint32(this->m_left, this->m_top); }
inline MxSize32 GetSize() { return MxSize32(this->m_right, this->m_bottom); }
inline MxS32 GetLeft() { return m_left; }
inline MxS32 GetTop() { return m_top; }
inline MxS32 GetRight() { return m_right; }
inline MxS32 GetBottom() { return m_bottom; }
inline void SetLeft(MxS32 p_left) { m_left = p_left; }
inline void SetTop(MxS32 p_top) { m_top = p_top; }
inline void SetRight(MxS32 p_right) { m_right = p_right; }
inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; }
private:
static inline MxS32 Min(MxS32 a, MxS32 b) { return a <= b ? a : b; };
static inline MxS32 Max(MxS32 a, MxS32 b) { return a <= b ? b : a; };
MxS32 m_left;
MxS32 m_top;

View file

@ -38,78 +38,67 @@ void MxRegion::Reset()
// OFFSET: LEGO1 0x100c3750
void MxRegion::vtable18(MxRect32& p_rect)
{
MxRect32 rectCopy(p_rect.GetPoint(), MxSize32(p_rect.m_right, p_rect.m_bottom));
MxRect32 rect(p_rect.GetPoint(), MxSize32(p_rect.GetRight(), p_rect.GetBottom()));
MxRegionListCursor cursor(m_list);
MxRegionTopBottom* topBottom;
if (rectCopy.m_left < rectCopy.m_right) {
while (rectCopy.m_top < rectCopy.m_bottom) {
MxRegionTopBottom* topBottom;
if (!cursor.Next(topBottom))
break;
if (topBottom->m_top >= rectCopy.m_bottom) {
cursor.Prepend(new MxRegionTopBottom(rectCopy));
rectCopy.m_top = rectCopy.m_bottom;
while (rect.IsValid() && cursor.Next(topBottom)) {
if (topBottom->GetTop() >= rect.GetBottom()) {
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rect);
cursor.Prepend(newTopBottom);
rect.SetTop(rect.GetBottom());
}
else if (rect.GetTop() < topBottom->GetBottom()) {
if (rect.GetTop() < topBottom->GetTop()) {
MxRect32 newRect(rect);
newRect.SetBottom(topBottom->GetTop());
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(newRect);
cursor.Prepend(newTopBottom);
rect.SetTop(topBottom->GetTop());
}
else if (rectCopy.m_top < topBottom->m_bottom) {
if (rectCopy.m_top < topBottom->m_top) {
MxRect32 topBottomRect(rectCopy.GetPoint(), MxSize32(rectCopy.m_right, topBottom->m_top));
cursor.Prepend(new MxRegionTopBottom(topBottomRect));
rectCopy.m_top = topBottom->m_top;
}
else if (topBottom->m_top < rectCopy.m_top) {
MxRegionTopBottom* newTopBottom = topBottom->Clone();
newTopBottom->m_bottom = rectCopy.m_top;
topBottom->m_top = rectCopy.m_top;
cursor.Prepend(newTopBottom);
}
if (rectCopy.m_bottom < topBottom->m_bottom) {
MxRegionTopBottom* newTopBottom = topBottom->Clone();
newTopBottom->m_bottom = rectCopy.m_bottom;
topBottom->m_top = rectCopy.m_bottom;
newTopBottom->FUN_100c5280(rectCopy.m_left, rectCopy.m_right);
// TODO: _InsertEntry currently inlined, shouldn't be
cursor.Prepend(newTopBottom);
rectCopy.m_top = rectCopy.m_bottom;
}
else {
topBottom->FUN_100c5280(rectCopy.m_left, rectCopy.m_right);
rectCopy.m_top = topBottom->m_bottom;
}
else if (topBottom->GetTop() < rect.GetTop()) {
MxRegionTopBottom* newTopBottom = topBottom->Clone();
newTopBottom->SetBottom(rect.GetTop());
topBottom->SetTop(rect.GetTop());
cursor.Prepend(newTopBottom);
}
if (rectCopy.m_right <= rectCopy.m_left)
break;
if (rect.GetBottom() < topBottom->GetBottom()) {
MxRegionTopBottom* newTopBottom = topBottom->Clone();
newTopBottom->SetBottom(rect.GetBottom());
topBottom->SetTop(rect.GetBottom());
newTopBottom->FUN_100c5280(rect.GetLeft(), rect.GetRight());
cursor.Prepend(newTopBottom);
rect.SetTop(rect.GetBottom());
}
else {
topBottom->FUN_100c5280(rect.GetLeft(), rect.GetRight());
rect.SetTop(topBottom->GetBottom());
}
}
}
if (rectCopy.m_left < rectCopy.m_right && rectCopy.m_top < rectCopy.m_bottom) {
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rectCopy);
if (rect.IsValid()) {
MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rect);
m_list->Append(newTopBottom);
}
m_rect.m_left = m_rect.m_left <= p_rect.m_left ? m_rect.m_left : p_rect.m_left;
m_rect.m_top = m_rect.m_top <= p_rect.m_top ? m_rect.m_top : p_rect.m_top;
m_rect.m_right = m_rect.m_right <= p_rect.m_right ? p_rect.m_right : m_rect.m_right;
m_rect.m_bottom = m_rect.m_bottom <= p_rect.m_bottom ? p_rect.m_bottom : m_rect.m_bottom;
m_rect.UpdateBounds(p_rect);
}
// OFFSET: LEGO1 0x100c3e20
MxBool MxRegion::vtable1c(MxRect32& p_rect)
{
if (m_rect.m_left >= p_rect.m_right || p_rect.m_left >= m_rect.m_right || m_rect.m_top >= p_rect.m_bottom ||
p_rect.m_top >= m_rect.m_bottom)
if (!m_rect.IntersectsWith(p_rect))
return FALSE;
MxRegionListCursor cursor(m_list);
MxRegionTopBottom* topBottom;
while (cursor.Next(topBottom)) {
if (topBottom->m_top >= p_rect.m_bottom)
if (topBottom->GetTop() >= p_rect.GetBottom())
return FALSE;
if (topBottom->m_bottom > p_rect.m_top && topBottom->FUN_100c57b0(p_rect))
if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect))
return TRUE;
}
@ -127,11 +116,11 @@ MxRegionTopBottom::MxRegionTopBottom(MxS32 p_top, MxS32 p_bottom)
// OFFSET: LEGO1 0x100c50e0
MxRegionTopBottom::MxRegionTopBottom(MxRect32& p_rect)
{
m_top = p_rect.m_top;
m_bottom = p_rect.m_bottom;
m_top = p_rect.GetTop();
m_bottom = p_rect.GetBottom();
m_leftRightList = new MxRegionLeftRightList;
MxRegionLeftRight* leftRight = new MxRegionLeftRight(p_rect.m_left, p_rect.m_right);
MxRegionLeftRight* leftRight = new MxRegionLeftRight(p_rect.GetLeft(), p_rect.GetRight());
m_leftRightList->Append(leftRight);
}
@ -142,7 +131,7 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
MxRegionLeftRightListCursor b(m_leftRightList);
MxRegionLeftRight* leftRight;
while (a.Next(leftRight) && leftRight->m_right < p_left)
while (a.Next(leftRight) && leftRight->GetRight() < p_left)
;
if (!a.HasMatch()) {
@ -150,12 +139,12 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
m_leftRightList->Append(copy);
}
else {
if (p_left > leftRight->m_left)
p_left = leftRight->m_left;
if (p_left > leftRight->GetLeft())
p_left = leftRight->GetLeft();
while (leftRight->m_left < p_right) {
if (p_right < leftRight->m_right)
p_right = leftRight->m_right;
while (leftRight->GetLeft() < p_right) {
if (p_right < leftRight->GetRight())
p_right = leftRight->GetRight();
b = a;
b.Advance();
@ -199,9 +188,9 @@ MxBool MxRegionTopBottom::FUN_100c57b0(MxRect32& p_rect)
MxRegionLeftRight* leftRight;
while (cursor.Next(leftRight)) {
if (p_rect.m_right <= leftRight->m_left)
if (p_rect.GetRight() <= leftRight->GetLeft())
return FALSE;
if (leftRight->m_right > p_rect.m_left)
if (leftRight->GetRight() > p_rect.GetLeft())
return TRUE;
}

View file

@ -15,6 +15,15 @@ struct MxRegionTopBottom {
void FUN_100c5280(MxS32 p_left, MxS32 p_right);
MxBool FUN_100c57b0(MxRect32& p_rect);
inline MxS32 GetTop() { return m_top; }
inline MxS32 GetBottom() { return m_bottom; }
inline void SetTop(MxS32 p_top) { m_top = p_top; }
inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; }
friend class MxRegionListParent;
private:
MxS32 m_top;
MxS32 m_bottom;
MxRegionLeftRightList* m_leftRightList;
@ -30,6 +39,13 @@ struct MxRegionLeftRight {
MxRegionLeftRight* Clone() { return new MxRegionLeftRight(m_left, m_right); }
inline MxS32 GetLeft() { return m_left; }
inline MxS32 GetRight() { return m_right; }
inline void SetLeft(MxS32 p_left) { m_left = p_left; }
inline void SetRight(MxS32 p_right) { m_right = p_right; }
private:
MxS32 m_left;
MxS32 m_right;
};

View file

@ -75,26 +75,9 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor)
void MxVideoManager::UpdateRegion()
{
if (m_region->vtable20() == FALSE) {
MxS32 left, top, right, bottom;
MxRect32& regionRect = m_region->GetRect();
left = m_videoParam.GetRect().m_left;
if (left <= regionRect.m_left)
left = regionRect.m_left;
top = regionRect.m_top;
if (top <= m_videoParam.GetRect().m_top)
top = m_videoParam.GetRect().m_top;
right = regionRect.m_right;
if (right >= m_videoParam.GetRect().m_right)
right = m_videoParam.GetRect().m_right;
bottom = m_videoParam.GetRect().m_bottom;
if (bottom >= regionRect.m_bottom)
bottom = regionRect.m_bottom;
m_displaySurface->Display(left, top, left, top, right - left + 1, bottom - top + 1);
MxRect32 rect(m_region->GetRect(), m_videoParam.GetRect());
m_displaySurface
->Display(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
}
}

View file

@ -6,14 +6,14 @@
// OFFSET: LEGO1 0x100bec70
MxVideoParam::MxVideoParam()
{
this->m_rect.m_right = 640;
this->m_rect.m_bottom = 480;
this->m_rect.m_left = 0;
this->m_rect.m_top = 0;
this->m_palette = 0;
this->m_rect.SetRight(640);
this->m_rect.SetBottom(480);
this->m_rect.SetLeft(0);
this->m_rect.SetTop(0);
this->m_palette = NULL;
this->m_backBuffers = 0;
this->m_unk1c = 0;
this->m_deviceId = 0;
this->m_deviceId = NULL;
}
// OFFSET: LEGO1 0x100beca0
@ -24,10 +24,7 @@ MxVideoParam::MxVideoParam(
COMPAT_CONST MxVideoParamFlags& p_flags
)
{
this->m_rect.m_left = p_rect.m_left;
this->m_rect.m_top = p_rect.m_top;
this->m_rect.m_right = p_rect.m_right;
this->m_rect.m_bottom = p_rect.m_bottom;
this->m_rect = p_rect;
this->m_palette = p_pal;
this->m_backBuffers = p_backBuffers;
this->m_flags = p_flags;
@ -38,10 +35,7 @@ MxVideoParam::MxVideoParam(
// OFFSET: LEGO1 0x100becf0
MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam)
{
this->m_rect.m_left = p_videoParam.m_rect.m_left;
this->m_rect.m_top = p_videoParam.m_rect.m_top;
this->m_rect.m_right = p_videoParam.m_rect.m_right;
this->m_rect.m_bottom = p_videoParam.m_rect.m_bottom;
this->m_rect = p_videoParam.m_rect;
this->m_palette = p_videoParam.m_palette;
this->m_backBuffers = p_videoParam.m_backBuffers;
this->m_flags = p_videoParam.m_flags;
@ -53,10 +47,7 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam)
// OFFSET: LEGO1 0x100bede0
MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam)
{
this->m_rect.m_left = p_videoParam.m_rect.m_left;
this->m_rect.m_top = p_videoParam.m_rect.m_top;
this->m_rect.m_right = p_videoParam.m_rect.m_right;
this->m_rect.m_bottom = p_videoParam.m_rect.m_bottom;
this->m_rect = p_videoParam.m_rect;
this->m_palette = p_videoParam.m_palette;
this->m_backBuffers = p_videoParam.m_backBuffers;
this->m_flags = p_videoParam.m_flags;
@ -69,24 +60,24 @@ MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam)
// OFFSET: LEGO1 0x100bed70
void MxVideoParam::SetDeviceName(char* id)
{
if (this->m_deviceId != 0)
if (this->m_deviceId != NULL)
delete[] this->m_deviceId;
if (id != 0) {
this->m_deviceId = new char[strlen(id) + 1];
if (this->m_deviceId != 0) {
if (this->m_deviceId != NULL) {
strcpy(this->m_deviceId, id);
}
}
else {
this->m_deviceId = 0;
this->m_deviceId = NULL;
}
}
// OFFSET: LEGO1 0x100bed50
MxVideoParam::~MxVideoParam()
{
if (this->m_deviceId != 0)
if (this->m_deviceId != NULL)
delete[] this->m_deviceId;
}

View file

@ -220,7 +220,7 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor)
MxRect32 rect(x, y, x + width, y + height);
MVideoManager()->InvalidateRect(rect);
MVideoManager()->vtable0x34(rect.m_left, rect.m_top, rect.GetWidth(), rect.GetHeight());
MVideoManager()->vtable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
}
delete m_bitmap;