From e2e17f575c5aeb0f062d74aa77f4c828a01527b8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Mar 2017 13:25:17 +0200 Subject: [PATCH] - added safeguards to all 2D drawing functions to throw an exception if used outside a valid 2D draw context. This is necessary because the hardware accelerated renderers will hide the problem, but with pure software rendering to a locked hardware surface, like DirectDraw can result in a crash. Note that ANY mod that gets caught in this did something wrong! --- src/g_statusbar/shared_sbar.cpp | 4 ++++ src/v_draw.cpp | 4 ++++ src/v_text.cpp | 2 ++ src/win32/win32gliface.cpp | 2 +- wadsrc/static/zscript/statusbar/heretic_sbar.txt | 2 +- wadsrc/static/zscript/statusbar/hexen_sbar.txt | 2 +- 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 8b6b23170..fe4028091 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1700,6 +1700,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawTexture) PARAM_FLOAT_DEF(h); PARAM_FLOAT_DEF(scaleX); PARAM_FLOAT_DEF(scaleY); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->DrawGraphic(FSetTextureID(texid), x, y, flags, alpha, w, h, scaleX, scaleY); return 0; } @@ -1716,6 +1717,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawImage) PARAM_FLOAT_DEF(h); PARAM_FLOAT_DEF(scaleX); PARAM_FLOAT_DEF(scaleY); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->DrawGraphic(TexMan.CheckForTexture(texid, FTexture::TEX_Any), x, y, flags, alpha, w, h, scaleX, scaleY); return 0; } @@ -1908,6 +1910,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawString) PARAM_INT_DEF(wrapwidth); PARAM_INT_DEF(linespacing); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); // resolve auto-alignment before making any adjustments to the position values. if (!(flags & DI_SCREEN_MANUAL_ALIGN)) @@ -2012,6 +2015,7 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, Fill) PARAM_FLOAT(w); PARAM_FLOAT(h); PARAM_INT_DEF(flags); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); self->Fill(color, x, y, w, h); return 0; } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index a2caded53..a45cbddac 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -137,6 +137,8 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture) PARAM_FLOAT(x); PARAM_FLOAT(y); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + FTexture *tex = animate ? TexMan(FSetTextureID(texid)) : TexMan[FSetTextureID(texid)]; VMVa_List args = { param + 4, 0, numparam - 4 }; screen->DrawTexture(tex, x, y, args); @@ -959,6 +961,7 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) PARAM_INT(y2); PARAM_INT(color); PARAM_INT_DEF(palcol); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); screen->Clear(x1, y1, x2, y2, palcol, color); return 0; } @@ -1010,6 +1013,7 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim) PARAM_INT(y1); PARAM_INT(w); PARAM_INT(h); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); screen->Dim(color, float(amount), x1, y1, w, h); return 0; } diff --git a/src/v_text.cpp b/src/v_text.cpp index ca445913f..fa04da365 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -116,6 +116,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar) PARAM_FLOAT(y); PARAM_INT(chr); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); VMVa_List args = { param + 5, 0, numparam - 5 }; screen->DrawChar(font, cr, x, y, chr, args); return 0; @@ -241,6 +242,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawText) PARAM_FLOAT(y); PARAM_STRING(chr); + if (!screen->IsLocked()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); VMVa_List args = { param + 5, 0, numparam - 5 }; const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); screen->DrawText(font, cr, x, y, txt, args); diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index b8e8cc53a..2074a17d8 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -1153,7 +1153,7 @@ void Win32GLFrameBuffer::Unlock () bool Win32GLFrameBuffer::IsLocked () { - return m_Lock>0;// true; + return m_Lock > 0; } //========================================================================== diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index e2f761501..1273ad4ce 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -189,7 +189,7 @@ class HereticStatusBar : BaseStatusBar y -= 40; } - if (!isInventoryBarVisible() && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar && CPlayer.mo.InvSel != null) { // This code was changed to always fit the item into the box, regardless of alignment or sprite size. // Heretic's ARTIBOX is 30x30 pixels. diff --git a/wadsrc/static/zscript/statusbar/hexen_sbar.txt b/wadsrc/static/zscript/statusbar/hexen_sbar.txt index 6f8318b27..f1ff81693 100644 --- a/wadsrc/static/zscript/statusbar/hexen_sbar.txt +++ b/wadsrc/static/zscript/statusbar/hexen_sbar.txt @@ -69,7 +69,7 @@ class HexenStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(CPlayer.FragCount, 3), (70, -16)); } - if (!isInventoryBarVisible() && !level.NoInventoryBar) + if (!isInventoryBarVisible() && !level.NoInventoryBar && CPlayer.mo.InvSel != null) { // This code was changed to always fit the item into the box, regardless of alignment or sprite size. // Heretic's ARTIBOX is 30x30 pixels.