From d3d8180f578924b275defd937e10cd3cb370922e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:04:36 +0200 Subject: [PATCH 01/30] Resize framebuffer in windowed mode to match the client area --- src/v_video.cpp | 42 ++++++++++++++++++++++++++++++++++++------ src/v_video.h | 4 ++++ src/win32/fb_d3d9.cpp | 18 ++++++++++++++++++ src/win32/i_input.cpp | 16 ++++++++++++---- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index b9917a1cb..9d377b7fd 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -725,6 +725,21 @@ void DCanvas::CalcGamma (float gamma, BYTE gammalookup[256]) DSimpleCanvas::DSimpleCanvas (int width, int height) : DCanvas (width, height) { + MemBuffer = nullptr; + Resize(width, height); +} + +void DSimpleCanvas::Resize(int width, int height) +{ + Width = width; + Height = height; + + if (MemBuffer != NULL) + { + delete[] MemBuffer; + MemBuffer = NULL; + } + // Making the pitch a power of 2 is very bad for performance // Try to maximize the number of cache lines that can be filled // for each column drawing operation by making the pitch slightly @@ -761,7 +776,7 @@ DSimpleCanvas::DSimpleCanvas (int width, int height) } } MemBuffer = new BYTE[Pitch * height]; - memset (MemBuffer, 0, Pitch * height); + memset(MemBuffer, 0, Pitch * height); } //========================================================================== @@ -1259,7 +1274,6 @@ CCMD(clean) bool V_DoModeSetup (int width, int height, int bits) { DFrameBuffer *buff = I_SetMode (width, height, screen); - int cx1, cx2; if (buff == NULL) { @@ -1274,6 +1288,17 @@ bool V_DoModeSetup (int width, int height, int bits) // if D3DFB is being used for the display. FFont::StaticPreloadFonts(); + DisplayBits = bits; + V_UpdateModeSize(width, height); + + M_RefreshModesList (); + + return true; +} + +void V_UpdateModeSize (int width, int height) +{ + int cx1, cx2; V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2); CleanWidth = width / CleanXfac; @@ -1314,14 +1339,19 @@ bool V_DoModeSetup (int width, int height, int bits) DisplayWidth = width; DisplayHeight = height; - DisplayBits = bits; R_OldBlend = ~0; Renderer->OnModeSet(); - - M_RefreshModesList (); +} - return true; +void V_OutputResized (int width, int height) +{ + V_UpdateModeSize(width, height); + setsizeneeded = true; + if (StatusBar != NULL) + { + StatusBar->ScreenSizeChanged(); + } } void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) diff --git a/src/v_video.h b/src/v_video.h index 4f0a78675..11a10c8d8 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -47,6 +47,8 @@ extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1; extern int DisplayWidth, DisplayHeight, DisplayBits; bool V_DoModeSetup (int width, int height, int bits); +void V_UpdateModeSize (int width, int height); +void V_OutputResized (int width, int height); void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *cx1=NULL, int *cx2=NULL); class FTexture; @@ -300,6 +302,8 @@ public: void Unlock (); protected: + void Resize(int width, int height); + BYTE *MemBuffer; DSimpleCanvas() {} diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index efdced151..06bfa0569 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1220,6 +1220,24 @@ void D3DFB::Flip() CurrRenderTexture ^= RenderTextureToggle; TempRenderTexture = RenderTexture[CurrRenderTexture]; } + + if (Windowed) + { + RECT box; + GetClientRect(Window, &box); + if (box.right > 0 && box.right > 0 && (Width != box.right || Height != box.bottom)) + { + Resize(box.right, box.bottom); + + TrueHeight = Height; + PixelDoubling = 0; + LBOffsetI = 0; + LBOffset = 0.0f; + Reset(); + + V_OutputResized(Width, Height); + } + } } //========================================================================== diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 2b0659c83..1e6390392 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -537,10 +537,18 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (screen && !VidResizing) { LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - RECT rect = { 0, 0, screen->GetWidth(), screen->GetHeight() }; - AdjustWindowRectEx(&rect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); - mmi->ptMinTrackSize.x = rect.right - rect.left; - mmi->ptMinTrackSize.y = rect.bottom - rect.top; + if (screen->IsFullscreen()) + { + RECT rect = { 0, 0, screen->GetWidth(), screen->GetHeight() }; + AdjustWindowRectEx(&rect, WS_VISIBLE | WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); + mmi->ptMinTrackSize.x = rect.right - rect.left; + mmi->ptMinTrackSize.y = rect.bottom - rect.top; + } + else + { + mmi->ptMinTrackSize.x = 320; + mmi->ptMinTrackSize.y = 200; + } return 0; } break; From b003c47e3e02bed94b76757a512b195b1d7d70c8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:37:05 +0200 Subject: [PATCH 02/30] Improve CheckRatio to always return the closest ratio --- src/v_video.cpp | 77 +++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index 9d377b7fd..78995f300 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1610,13 +1610,36 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // 2: 16:10 // 3: 17:10 // 4: 5:4 -// 5: 17:10 (redundant) +// 5: 17:10 (redundant, never returned) // 6: 21:9 int CheckRatio (int width, int height, int *trueratio) { - int fakeratio = -1; - int ratio; + float aspect = width / (float)height; + static std::pair ratioTypes[] = + { + { 21 / 9.0f , 6 }, + { 16 / 9.0f , 1 }, + { 17 / 10.0f , 3 }, + { 16 / 10.0f , 2 }, + { 4 / 3.0f , 0 }, + { 5 / 4.0f , 4 }, + { 0.0f, 0 } + }; + + int ratio = ratioTypes[0].second; + float distance = abs(ratioTypes[0].first - aspect); + for (int i = 1; ratioTypes[i].first != 0.0f; i++) + { + float d = abs(ratioTypes[i].first - aspect); + if (d < distance) + { + ratio = ratioTypes[i].second; + distance = d; + } + } + + int fakeratio = ratio; if ((vid_aspect >= 1) && (vid_aspect <= 6)) { // [SP] User wants to force aspect ratio; let them. @@ -1628,7 +1651,7 @@ int CheckRatio (int width, int height, int *trueratio) else if (fakeratio == 5) { fakeratio = 3; - } + } } if (vid_nowidescreen) { @@ -1638,53 +1661,13 @@ int CheckRatio (int width, int height, int *trueratio) } else { - fakeratio = (height * 5/4 == width) ? 4 : 0; + fakeratio = (height * 5 / 4 == width) ? 4 : 0; } } - // If the size is approximately 16:9, consider it so. - if (abs (height * 16/9 - width) < 10) - { - ratio = 1; - } - // Consider 17:10 as well. - else if (abs (height * 17/10 - width) < 10) - { - ratio = 3; - } - // 16:10 has more variance in the pixel dimensions. Grr. - else if (abs (height * 16/10 - width) < 60) - { - // 320x200 and 640x400 are always 4:3, not 16:10 - if ((width == 320 && height == 200) || (width == 640 && height == 400)) - { - ratio = 0; - } - else - { - ratio = 2; - } - } - // Unless vid_tft is set, 1280x1024 is 4:3, not 5:4. - else if (height * 5/4 == width && vid_tft) - { - ratio = 4; - } - // test for 21:9 (actually 64:27, 21:9 is a semi-accurate ratio used in marketing) - else if (abs (height * 64/27 - width) < 30) - { - ratio = 6; - } - // Assume anything else is 4:3. (Which is probably wrong these days...) - else - { - ratio = 0; - } - if (trueratio != NULL) - { + if (trueratio) *trueratio = ratio; - } - return (fakeratio >= 0) ? fakeratio : ratio; + return fakeratio; } // First column: Base width From 5720634045b0812bc838eb4671a4039917582a94 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:59:01 +0200 Subject: [PATCH 03/30] Add ActiveRatio to be used where CheckRatio is used today --- src/v_video.cpp | 81 ++++++++++++++++++++++++++++++++++--------------- src/v_video.h | 2 ++ 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index 78995f300..dcc5789ee 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1603,6 +1603,59 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) } } +// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none. +int ActiveFakeRatio(int width, int height) +{ + int fakeratio = -1; + if ((vid_aspect >= 1) && (vid_aspect <= 6)) + { + // [SP] User wants to force aspect ratio; let them. + fakeratio = int(vid_aspect); + if (fakeratio == 3) + { + fakeratio = 0; + } + else if (fakeratio == 5) + { + fakeratio = 3; + } + } + if (vid_nowidescreen) + { + if (!vid_tft) + { + fakeratio = 0; + } + else + { + fakeratio = (height * 5 / 4 == width) ? 4 : 0; + } + } + return fakeratio; +} + +// Active screen ratio based on cvars and size +float ActiveRatio(int width, int height, float *trueratio) +{ + static float forcedRatioTypes[] = + { + 4 / 3.0f, + 16 / 9.0f, + 16 / 10.0f, + 17 / 10.0f, + 5 / 4.0f, + 17 / 10.0f, + 21 / 9.0f + }; + + float ratio = width / (float)height; + int fakeratio = ActiveFakeRatio(width, height); + + if (trueratio) + *trueratio = ratio; + return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : ratio; +} + // Tries to guess the physical dimensions of the screen based on the // screen's pixel dimensions. Can return: // 0: 4:3 @@ -1639,31 +1692,9 @@ int CheckRatio (int width, int height, int *trueratio) } } - int fakeratio = ratio; - if ((vid_aspect >= 1) && (vid_aspect <= 6)) - { - // [SP] User wants to force aspect ratio; let them. - fakeratio = int(vid_aspect); - if (fakeratio == 3) - { - fakeratio = 0; - } - else if (fakeratio == 5) - { - fakeratio = 3; - } - } - if (vid_nowidescreen) - { - if (!vid_tft) - { - fakeratio = 0; - } - else - { - fakeratio = (height * 5 / 4 == width) ? 4 : 0; - } - } + int fakeratio = ActiveFakeRatio(width, height); + if (fakeratio == -1) + fakeratio = ratio; if (trueratio) *trueratio = ratio; diff --git a/src/v_video.h b/src/v_video.h index 11a10c8d8..6b46fa278 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -516,6 +516,8 @@ extern "C" void ASM_PatchPitch (void); int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } +float ActiveRatio (int width, int height, float *trueratio = NULL); +static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } extern const int BaseRatioSizes[7][4]; inline bool IsRatioWidescreen(int ratio) { From 6d4e4dad25ffa3978f5bf54d0fc60dd59b29d119 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 14:37:10 +0200 Subject: [PATCH 04/30] BaseRatioSizes replacement functions --- src/v_video.cpp | 20 ++++++++++++++++++++ src/v_video.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/src/v_video.cpp b/src/v_video.cpp index dcc5789ee..acd34f37f 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1721,6 +1721,26 @@ const int BaseRatioSizes[7][4] = { 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three }; +int AspectBaseWidth(float aspect) +{ + return (int)round(240.0f * aspect * 3.0f); +} + +int AspectBaseHeight(float aspect) +{ + return (int)round(200.0f * (320.0f / (240.0f * aspect)) * 3.0f); +} + +int AspectPspriteOffset(float aspect) +{ + return aspect < 1.3f ? (int)(6.5*FRACUNIT) : 0; +} + +int AspectMultiplier(float aspect) +{ + return (int)round(320.0f / (240.0f * aspect) * 48.0f); +} + void IVideo::DumpAdapters () { Printf("Multi-monitor support unavailable.\n"); diff --git a/src/v_video.h b/src/v_video.h index 6b46fa278..2dc3bbddc 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -518,6 +518,11 @@ int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } float ActiveRatio (int width, int height, float *trueratio = NULL); static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } + +int AspectBaseWidth(float aspect); +int AspectBaseHeight(float aspect); +int AspectPspriteOffset(float aspect); +int AspectMultiplier(float aspect); extern const int BaseRatioSizes[7][4]; inline bool IsRatioWidescreen(int ratio) { From 5b438d220f918e4d5b604e970f0f45f96963e8d1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 15:51:50 +0200 Subject: [PATCH 05/30] Switch from ratio enum to float --- src/g_shared/shared_hud.cpp | 6 +++--- src/g_shared/shared_sbar.cpp | 17 +++++++++-------- src/r_main.cpp | 16 ++++++++-------- src/r_renderer.h | 2 +- src/r_swrenderer.cpp | 4 ++-- src/r_swrenderer.h | 2 +- src/r_things.cpp | 2 +- src/r_utility.cpp | 11 +++++------ src/r_utility.h | 2 +- src/v_draw.cpp | 34 +++++++++++++++++----------------- src/v_video.cpp | 30 +++++------------------------- src/v_video.h | 11 ++--------- 12 files changed, 55 insertions(+), 82 deletions(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 25a88cb35..e40233def 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -1108,13 +1108,13 @@ void DrawHUD() } else { - if (WidescreenRatio == 4) + if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) == 4) { - hudheight = hudwidth * 30 / BaseRatioSizes[WidescreenRatio][3]; // BaseRatioSizes is inverted for this mode + hudheight = hudwidth * 30 / AspectMultiplier(WidescreenRatio); // BaseRatioSizes is inverted for this mode } else { - hudheight = hudwidth * 30 / (48*48/BaseRatioSizes[WidescreenRatio][3]); + hudheight = hudwidth * 30 / (48*48/AspectMultiplier(WidescreenRatio)); } } } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 4631a99aa..3c41d18ca 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -299,14 +299,15 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) { ST_X = 0; ST_Y = VirticalResolution - RelTop; - if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) != 4) + float aspect = ActiveRatio(SCREENWIDTH, SCREENHEIGHT); + if (aspect >= 1.3f) { // Normal resolution ::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution); } else { // 5:4 resolution - ::ST_Y = Scale(ST_Y - VirticalResolution/2, SCREENHEIGHT*3, Scale(VirticalResolution, BaseRatioSizes[4][1], 200)) + SCREENHEIGHT/2 - + (SCREENHEIGHT - SCREENHEIGHT * BaseRatioSizes[4][3] / 48) / 2; + ::ST_Y = Scale(ST_Y - VirticalResolution/2, SCREENHEIGHT*3, Scale(VirticalResolution, AspectBaseHeight(aspect), 200)) + SCREENHEIGHT/2 + + (SCREENHEIGHT - SCREENHEIGHT * AspectMultiplier(aspect) / 48) / 2; } Displacement = 0; } @@ -1035,10 +1036,10 @@ void DBaseStatusBar::DrSmallNumberOuter (int val, int x, int y, bool center) con void DBaseStatusBar::RefreshBackground () const { - int x, x2, y, ratio; + int x, x2, y; - ratio = CheckRatio (SCREENWIDTH, SCREENHEIGHT); - x = (!IsRatioWidescreen(ratio) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2); + float ratio = ActiveRatio (SCREENWIDTH, SCREENHEIGHT); + x = (ratio < 1.5f || !Scaled) ? ST_X : SCREENWIDTH*(48-AspectMultiplier(ratio))/(48*2); y = x == ST_X && x > 0 ? ST_Y : ::ST_Y; if(!CompleteBorder) @@ -1058,8 +1059,8 @@ void DBaseStatusBar::RefreshBackground () const { if(!CompleteBorder) { - x2 = !IsRatioWidescreen(ratio) || !Scaled ? ST_X+HorizontalResolution : - SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2); + x2 = ratio < 1.5f || !Scaled ? ST_X+HorizontalResolution : + SCREENWIDTH - (SCREENWIDTH*(48-AspectMultiplier(ratio))+48*2-1)/(48*2); } else { diff --git a/src/r_main.cpp b/src/r_main.cpp index ecbd4cb34..d84698b7c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -232,7 +232,7 @@ void R_SetVisibility(double vis) else r_WallVisibility = r_BaseVisibility; - r_WallVisibility = (InvZtoScale * SCREENWIDTH*BaseRatioSizes[WidescreenRatio][1] / + r_WallVisibility = (InvZtoScale * SCREENWIDTH*AspectBaseHeight(WidescreenRatio) / (viewwidth*SCREENHEIGHT*3)) * (r_WallVisibility * FocalTangent); // Prevent overflow on floors/ceilings. Note that the calculation of @@ -295,7 +295,7 @@ CCMD (r_visibility) // //========================================================================== -void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) +void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) { int virtheight, virtwidth, virtwidth2, virtheight2; @@ -318,22 +318,22 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; - if (Is54Aspect(trueratio)) + if (trueratio < 1.3f) { - virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48; + virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48; } else { - virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48; + virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48; } - if (Is54Aspect(WidescreenRatio)) + if (WidescreenRatio < 1.3f) { - virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48; + virtheight = virtheight * AspectMultiplier(WidescreenRatio) / 48; } else { - virtwidth = virtwidth * BaseRatioSizes[WidescreenRatio][3] / 48; + virtwidth = virtwidth * AspectMultiplier(WidescreenRatio) / 48; } BaseYaspectMul = 320.0 * virtheight2 / (r_Yaspect * virtwidth2); diff --git a/src/r_renderer.h b/src/r_renderer.h index 6c65fc12f..a39520b49 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -55,7 +55,7 @@ struct FRenderer virtual void ErrorCleanup () {} virtual void ClearBuffer(int color) = 0; virtual void Init() = 0; - virtual void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) {} + virtual void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) {} virtual void SetupFrame(player_t *player) {} virtual void CopyStackedViewParameters() {} virtual void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) = 0; diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index 07edf25e9..4d1fd0371 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -45,7 +45,7 @@ class FArchive; -void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio); +void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); void R_SetupColormap(player_t *); void R_SetupFreelook(); void R_InitRenderer(); @@ -275,7 +275,7 @@ void FSoftwareRenderer::ClearBuffer(int color) // //=========================================================================== -void FSoftwareRenderer::SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) +void FSoftwareRenderer::SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) { R_SWRSetWindow(windowSize, fullWidth, fullHeight, stHeight, trueratio); } diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 3e5fed9bc..2856d9586 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -30,7 +30,7 @@ struct FSoftwareRenderer : public FRenderer void ErrorCleanup (); void ClearBuffer(int color); void Init(); - void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio); + void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); void SetupFrame(player_t *player); void CopyStackedViewParameters(); void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov); diff --git a/src/r_things.cpp b/src/r_things.cpp index 28b52129b..a62525d08 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1393,7 +1393,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double } if (pspr->GetID() < PSP_TARGETCENTER) { // Move the weapon down for 1280x1024. - vis->texturemid -= BaseRatioSizes[WidescreenRatio][2]; + vis->texturemid -= AspectPspriteOffset(WidescreenRatio); } vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth : x2; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 00ac91c97..8e4284b7e 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -138,7 +138,7 @@ angle_t LocalViewAngle; int LocalViewPitch; bool LocalKeyboardTurner; -int WidescreenRatio; +float WidescreenRatio; int setblocks; int extralight; bool setsizeneeded; @@ -200,7 +200,7 @@ void R_SetViewSize (int blocks) void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) { - int trueratio; + float trueratio; if (windowSize >= 11) { @@ -220,8 +220,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) freelookviewheight = ((setblocks*fullHeight)/10)&~7; } - // If the screen is approximately 16:9 or 16:10, consider it widescreen. - WidescreenRatio = CheckRatio (fullWidth, fullHeight, &trueratio); + WidescreenRatio = ActiveRatio (fullWidth, fullHeight, &trueratio); DrawFSHUD = (windowSize == 11); @@ -230,13 +229,13 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) centery = viewheight/2; centerx = viewwidth/2; - if (Is54Aspect(WidescreenRatio)) + if (WidescreenRatio < 1.3f) { centerxwide = centerx; } else { - centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48; + centerxwide = centerx * AspectMultiplier(WidescreenRatio) / 48; } diff --git a/src/r_utility.h b/src/r_utility.h index 8cabfa600..e9fd436e5 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -33,7 +33,7 @@ extern int validcount; extern angle_t LocalViewAngle; // [RH] Added to consoleplayer's angle extern int LocalViewPitch; // [RH] Used directly instead of consoleplayer's pitch extern bool LocalKeyboardTurner; // [RH] The local player used the keyboard to turn, so interpolate -extern int WidescreenRatio; +extern float WidescreenRatio; extern double r_TicFracF; extern DWORD r_FrameTime; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index dada0cd57..a33fd618b 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -863,37 +863,37 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect) const { - int myratio = handleaspect ? CheckRatio (Width, Height) : 0; + float myratio = handleaspect ? ActiveRatio (Width, Height) : (4.0f / 3.0f); // if 21:9 AR, map to 16:9 for all callers. // this allows for black bars and stops the stretching of fullscreen images - if (myratio == 6) { - myratio = 2; + if (myratio > 1.7f) { + myratio = 16.0f / 9.0f; } double right = x + w; double bottom = y + h; - if (myratio != 0 && myratio != 4) + if (myratio > 1.4f) { // The target surface is either 16:9 or 16:10, so expand the // specified virtual size to avoid undesired stretching of the // image. Does not handle non-4:3 virtual sizes. I'll worry about // those if somebody expresses a desire to use them. - x = (x - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5; - w = (right - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5 - x; + x = (x - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5; + w = (right - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5 - x; } else { x = x * Width / vwidth; w = right * Width / vwidth - x; } - if (myratio == 4) + if (myratio < 1.3f) { // The target surface is 5:4 - y = (y - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5; - h = (bottom - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5 - y; + y = (y - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5; + h = (bottom - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5 - y; if (vbottom) { - y += (Height - Height * BaseRatioSizes[myratio][3] / 48.0) * 0.5; + y += (Height - Height * AspectMultiplier(myratio) / 48.0) * 0.5; } } else @@ -937,30 +937,30 @@ void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, void DCanvas::FillBorder (FTexture *img) { - int myratio = CheckRatio (Width, Height); + float myratio = ActiveRatio (Width, Height); // if 21:9 AR, fill borders akin to 16:9, since all fullscreen // images are being drawn to that scale. - if (myratio == 6) { - myratio = 2; + if (myratio > 1.7f) { + myratio = 16 / 9.0f; } - if (myratio == 0) + if (myratio >= 1.3f && myratio <= 1.4f) { // This is a 4:3 display, so no border to show return; } int bordtop, bordbottom, bordleft, bordright, bord; - if (Is54Aspect(myratio)) + if (myratio < 1.3f) { // Screen is taller than it is wide bordleft = bordright = 0; - bord = Height - Height * BaseRatioSizes[myratio][3] / 48; + bord = Height - Height * AspectMultiplier(myratio) / 48; bordtop = bord / 2; bordbottom = bord - bordtop; } else { // Screen is wider than it is tall bordtop = bordbottom = 0; - bord = Width - Width * BaseRatioSizes[myratio][3] / 48; + bord = Width - Width * AspectMultiplier(myratio) / 48; bordleft = bord / 2; bordright = bord - bordleft; } diff --git a/src/v_video.cpp b/src/v_video.cpp index acd34f37f..43458dc63 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1356,20 +1356,20 @@ void V_OutputResized (int width, int height) void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) { - int ratio; + float ratio; int cwidth; int cheight; int cx1, cy1, cx2, cy2; - ratio = CheckRatio(realwidth, realheight); - if (Is54Aspect(ratio)) + ratio = ActiveRatio(realwidth, realheight); + if (ratio < 1.3f) { cwidth = realwidth; - cheight = realheight * BaseRatioSizes[ratio][3] / 48; + cheight = realheight * AspectMultiplier(ratio) / 48; } else { - cwidth = realwidth * BaseRatioSizes[ratio][3] / 48; + cwidth = realwidth * AspectMultiplier(ratio) / 48; cheight = realheight; } // Use whichever pair of cwidth/cheight or width/height that produces less difference @@ -1701,26 +1701,6 @@ int CheckRatio (int width, int height, int *trueratio) return fakeratio; } -// First column: Base width -// Second column: Base height (used for wall visibility multiplier) -// Third column: Psprite offset (needed for "tallscreen" modes) -// Fourth column: Width or height multiplier - -// For widescreen aspect ratio x:y ... -// base_width = 240 * x / y -// multiplier = 320 / base_width -// base_height = 200 * multiplier -const int BaseRatioSizes[7][4] = -{ - { 960, 600, 0, 48 }, // 4:3 320, 200, multiplied by three - { 1280, 450, 0, 48*3/4 }, // 16:9 426.6667, 150, multiplied by three - { 1152, 500, 0, 48*5/6 }, // 16:10 386, 166.6667, multiplied by three - { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three - { 960, 640, (int)(6.5*FRACUNIT), 48*15/16 }, // 5:4 320, 213.3333, multiplied by three - { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three (REDUNDANT) - { 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three -}; - int AspectBaseWidth(float aspect) { return (int)round(240.0f * aspect * 3.0f); diff --git a/src/v_video.h b/src/v_video.h index 2dc3bbddc..8d785e43f 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -516,6 +516,8 @@ extern "C" void ASM_PatchPitch (void); int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } +inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; } + float ActiveRatio (int width, int height, float *trueratio = NULL); static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } @@ -523,15 +525,6 @@ int AspectBaseWidth(float aspect); int AspectBaseHeight(float aspect); int AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); -extern const int BaseRatioSizes[7][4]; - -inline bool IsRatioWidescreen(int ratio) { - return (ratio & 3)!=0; -} - -inline bool Is54Aspect(int ratio) { - return ratio == 4; -} EXTERN_CVAR(Int, uiscale); From 4e58e6626cf0372a3fbca5649a66aa7e2441554c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 16:05:42 +0200 Subject: [PATCH 06/30] Fix buffer overrun in CommandAspectRatio for 21:9 aspect ratio --- src/g_shared/sbarinfo_commands.cpp | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index a9fac2ee1..47785076e 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1914,7 +1914,7 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl { SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); - SetTruth(ratioMap[CheckRatio(screen->GetWidth(), screen->GetHeight())] == ratio, block, statusBar); + SetTruth(ratioMap[FindRatio()] == ratio, block, statusBar); } protected: enum Ratio @@ -1931,6 +1931,37 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl static Ratio ratioMap[5]; Ratio ratio; + + private: + int FindRatio() + { + float aspect = ActiveRatio(screen->GetWidth(), screen->GetHeight()); + + static std::pair ratioTypes[] = + { + { 21 / 9.0f , ASPECTRATIO_16_9 }, + { 16 / 9.0f , ASPECTRATIO_16_9 }, + { 17 / 10.0f , ASPECTRATIO_17_10 }, + { 16 / 10.0f , ASPECTRATIO_16_10 }, + { 4 / 3.0f , ASPECTRATIO_4_3 }, + { 5 / 4.0f , ASPECTRATIO_5_4 }, + { 0.0f, 0 } + }; + + int ratio = ratioTypes[0].second; + float distance = abs(ratioTypes[0].first - aspect); + for (int i = 1; ratioTypes[i].first != 0.0f; i++) + { + float d = abs(ratioTypes[i].first - aspect); + if (d < distance) + { + ratio = ratioTypes[i].second; + distance = d; + } + } + + return ratio; + } }; CommandAspectRatio::Ratio CommandAspectRatio::ratioMap[5] = {ASPECTRATIO_4_3,ASPECTRATIO_16_9,ASPECTRATIO_16_10,ASPECTRATIO_16_10,ASPECTRATIO_5_4}; From 01b1efe9eec9877a409d14f749b9934a10224a58 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 18:44:04 +0200 Subject: [PATCH 07/30] Switch from abs to fabs --- src/g_shared/sbarinfo_commands.cpp | 4 ++-- src/v_video.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 47785076e..b7827f6bd 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1949,10 +1949,10 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl }; int ratio = ratioTypes[0].second; - float distance = abs(ratioTypes[0].first - aspect); + float distance = fabs(ratioTypes[0].first - aspect); for (int i = 1; ratioTypes[i].first != 0.0f; i++) { - float d = abs(ratioTypes[i].first - aspect); + float d = fabs(ratioTypes[i].first - aspect); if (d < distance) { ratio = ratioTypes[i].second; diff --git a/src/v_video.cpp b/src/v_video.cpp index 43458dc63..20e1f526c 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1681,10 +1681,10 @@ int CheckRatio (int width, int height, int *trueratio) }; int ratio = ratioTypes[0].second; - float distance = abs(ratioTypes[0].first - aspect); + float distance = fabs(ratioTypes[0].first - aspect); for (int i = 1; ratioTypes[i].first != 0.0f; i++) { - float d = abs(ratioTypes[i].first - aspect); + float d = fabs(ratioTypes[i].first - aspect); if (d < distance) { ratio = ratioTypes[i].second; From a2a1d2a36d0b8e7c921f5310ca478f16ccf9034c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 11:55:29 +0300 Subject: [PATCH 08/30] Fixed significant distortion of sound effects with FMOD Studio API --- src/sound/fmodsound.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 2db5a98a1..81bbfb8c1 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -2758,6 +2758,16 @@ std::pair FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int l exinfo.defaultfrequency = frequency; switch (bits) { +#if FMOD_STUDIO + case -8: + // Need to convert sample data from signed to unsigned. + for (int i = 0; i < length; i++) + { + sfxdata[i] ^= 0x80; + } + + case 8: +#else // !FMOD_STUDIO case 8: // Need to convert sample data from unsigned to signed. for (int i = 0; i < length; ++i) @@ -2766,6 +2776,7 @@ std::pair FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int l } case -8: +#endif // FMOD_STUDIO exinfo.format = FMOD_SOUND_FORMAT_PCM8; numsamples = length; break; From 764705a8e065889c2b896076642091b21e3ce46b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 11:34:15 +0300 Subject: [PATCH 09/30] Fixed 'Could not set resampler method. Defaults will be used. (Error 31)' message with FMOD Studio API --- src/sound/fmodsound.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 81bbfb8c1..e45385210 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -971,6 +971,7 @@ bool FMODSoundRenderer::Init() #if FMOD_STUDIO FMOD_ADVANCEDSETTINGS advSettings = {}; + advSettings.cbSize = sizeof advSettings; advSettings.resamplerMethod = resampler; result = Sys->setAdvancedSettings(&advSettings); if (result != FMOD_OK) From c88eec3d7361f2fd83a445cfcf08c18effe2a53d Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 10:23:12 +0300 Subject: [PATCH 10/30] Fixed 'unreferenced local variable' warnings when building with FMOD Studio API --- src/sound/fmodsound.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index e45385210..c130b7e6a 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1371,11 +1371,8 @@ void FMODSoundRenderer::PrintStatus() { FMOD_OUTPUTTYPE output; FMOD_SPEAKERMODE speakermode; - FMOD_SOUND_FORMAT format; - FMOD_DSP_RESAMPLER resampler; int driver; int samplerate; - int numoutputchannels; unsigned int bufferlength; int numbuffers; @@ -1414,6 +1411,9 @@ void FMODSoundRenderer::PrintStatus() #endif } #if !FMOD_STUDIO + FMOD_SOUND_FORMAT format; + FMOD_DSP_RESAMPLER resampler; + int numoutputchannels; if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &format, &numoutputchannels, NULL, &resampler, NULL)) { Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: " TEXTCOLOR_GREEN "%d\n", samplerate); From 7e61a1ce2b8108375e7089f26548e70ce4c7cc0b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 12:35:22 +0300 Subject: [PATCH 11/30] Added simple detection for FMOD Studio API in CMake --- src/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 190a9560a..025d651c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -272,6 +272,10 @@ if( NOT NO_FMOD ) if( FMOD_INCLUDE_DIR ) message( STATUS "FMOD include files found at ${FMOD_INCLUDE_DIR}" ) include_directories( "${FMOD_INCLUDE_DIR}" ) + + if( EXISTS "${FMOD_INCLUDE_DIR}/fmod_common.h" ) + set( FMOD_STUDIO YES ) + endif() else() message( STATUS "Could not find FMOD include files" ) set( NO_FMOD ON ) From 9c91686e0fa2fc1af18c06e05ac9f6e33e0dc068 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 12:36:30 +0300 Subject: [PATCH 12/30] Set delay loading for proper .dll depending on FMOD version (Studio vs. Ex) --- src/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 025d651c3..841c06a6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1343,7 +1343,16 @@ endif() if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) - set( LINKERSTUFF "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"" ) + set( LINKERSTUFF "/MANIFEST:NO" ) + + if( NOT NO_FMOD ) + if( FMOD_STUDIO ) + set( LINKERSTUFF "${LINKERSTUFF} /DELAYLOAD:\"fmod${X64}.dll\"" ) + else() + set( LINKERSTUFF "${LINKERSTUFF} /DELAYLOAD:\"fmodex${X64}.dll\"" ) + endif() + endif() + if( ZDOOM_GENERATE_MAPFILE ) set( LINKERSTUFF "${LINKERSTUFF} /MAP" ) endif() From b308a7df52dc9d6a223ddb53365a1852f0205d54 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 6 Sep 2016 12:43:57 +0300 Subject: [PATCH 13/30] Proper name of FMOD .dylib in loading path adjustment for macOS --- src/CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 841c06a6f..bb5f21308 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1392,17 +1392,23 @@ if( APPLE ) MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/posix/osx/zdoom-info.plist" ) if( NOT NO_FMOD ) + if( FMOD_STUDIO ) + set( FMOD_DYLIB libfmod.dylib ) + else() + set( FMOD_DYLIB libfmodex.dylib ) + endif() + # Fix fmod link so that it can be found in the app bundle. find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) find_program( INSTALL_NAME_TOOL install_name_tool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" ) execute_process( COMMAND "${OTOOL}" -L "${FMOD_LIBRARY}" - COMMAND grep "libfmodex.dylib (compat" + COMMAND grep "${FMOD_DYLIB} (compat" COMMAND head -n1 COMMAND awk "{print $1}" OUTPUT_VARIABLE FMOD_LINK OUTPUT_STRIP_TRAILING_WHITESPACE ) add_custom_command( TARGET zdoom POST_BUILD - COMMAND "${INSTALL_NAME_TOOL}" -change "${FMOD_LINK}" @executable_path/../Frameworks/libfmodex.dylib "$" + COMMAND "${INSTALL_NAME_TOOL}" -change "${FMOD_LINK}" @executable_path/../Frameworks/${FMOD_DYLIB} "$" COMMENT "Relinking FMOD Ex" ) endif() endif() From 823f75e59239093a0947667ead7fbefa484cb851 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Sep 2016 21:32:17 +0200 Subject: [PATCH 14/30] - fixed: UDMF user value lists need to be sorted for binary search to work but weren't. --- src/p_udmf.cpp | 5 +++++ src/r_defs.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 0b054247e..c09debc51 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -309,6 +309,11 @@ void FUDMFKeys::Sort() FUDMFKey *FUDMFKeys::Find(FName key) { + if (!mSorted) + { + mSorted = true; + Sort(); + } int min = 0, max = Size()-1; while (min <= max) diff --git a/src/r_defs.h b/src/r_defs.h index f27ac2716..59b1fe0d3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -220,6 +220,7 @@ struct FUDMFKey class FUDMFKeys : public TArray { + bool mSorted = false; public: void Sort(); FUDMFKey *Find(FName key); From e10abcad067b7786cabec0e723c7c61def64b6a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Sep 2016 10:43:53 +0200 Subject: [PATCH 15/30] - fixed: The TabCommands array needs to be cleared before the NameManager is destroyed. TabCommands use an FName to store the command's name so once the NameManager is destroyed its data will become invalid. This is a problem because C_RemoveTabCommand is being called from FBaseCVar's destructor and most CVARs are global variables. --- src/name.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/name.cpp b/src/name.cpp index 8140829c6..ecedcf0f3 100644 --- a/src/name.cpp +++ b/src/name.cpp @@ -35,6 +35,7 @@ #include #include "name.h" #include "c_dispatch.h" +#include "c_console.h" // MACROS ------------------------------------------------------------------ @@ -268,6 +269,8 @@ FName::NameManager::~NameManager() { NameBlock *block, *next; + C_ClearTabCommands(); + for (block = Blocks; block != NULL; block = next) { next = block->NextBlock; From ba68cfd61153ed260ae1cf3c8dc7e4986ee4fa69 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Sep 2016 21:01:50 +0200 Subject: [PATCH 16/30] - do not even allow creation of names in C_RemoveTabCommands if there are no tab commands, so that FindName cannot be called after the NameManager has been destroyed. --- src/c_console.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/c_console.cpp b/src/c_console.cpp index 086861229..2d164c478 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1747,6 +1747,14 @@ void C_AddTabCommand (const char *name) void C_RemoveTabCommand (const char *name) { + if (TabCommands.Size() == 0) + { + // There are no tab commands that can be removed. + // This is important to skip construction of aname + // in case the NameManager has already been destroyed. + return; + } + FName aname(name, true); if (aname == NAME_None) From 172f58c1655848df85d35676a4a5aeb094d05b2c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 13 Sep 2016 11:46:05 +0200 Subject: [PATCH 17/30] Fix 5:4 aspect ratio gun and status bar --- src/g_shared/shared_sbar.cpp | 2 +- src/r_main.cpp | 4 ++-- src/r_utility.cpp | 2 +- src/v_draw.cpp | 4 ++-- src/v_video.cpp | 19 +++++++++++++------ src/v_video.h | 3 ++- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 3c41d18ca..22171a4bb 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -300,7 +300,7 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) ST_X = 0; ST_Y = VirticalResolution - RelTop; float aspect = ActiveRatio(SCREENWIDTH, SCREENHEIGHT); - if (aspect >= 1.3f) + if (!Is54Aspect(aspect)) { // Normal resolution ::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution); } diff --git a/src/r_main.cpp b/src/r_main.cpp index d84698b7c..6094f70de 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -318,7 +318,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; - if (trueratio < 1.3f) + if (Is54Aspect(trueratio)) { virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48; } @@ -327,7 +327,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48; } - if (WidescreenRatio < 1.3f) + if (Is54Aspect(WidescreenRatio)) { virtheight = virtheight * AspectMultiplier(WidescreenRatio) / 48; } diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 8e4284b7e..76cf05e9b 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -229,7 +229,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) centery = viewheight/2; centerx = viewwidth/2; - if (WidescreenRatio < 1.3f) + if (Is54Aspect(WidescreenRatio)) { centerxwide = centerx; } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index a33fd618b..3075cd92d 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -887,7 +887,7 @@ void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, x = x * Width / vwidth; w = right * Width / vwidth - x; } - if (myratio < 1.3f) + if (Is54Aspect(myratio)) { // The target surface is 5:4 y = (y - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5; h = (bottom - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5 - y; @@ -950,7 +950,7 @@ void DCanvas::FillBorder (FTexture *img) return; } int bordtop, bordbottom, bordleft, bordright, bord; - if (myratio < 1.3f) + if (Is54Aspect(myratio)) { // Screen is taller than it is wide bordleft = bordright = 0; bord = Height - Height * AspectMultiplier(myratio) / 48; diff --git a/src/v_video.cpp b/src/v_video.cpp index 20e1f526c..710d8b1cf 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1362,7 +1362,7 @@ void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int real int cx1, cy1, cx2, cy2; ratio = ActiveRatio(realwidth, realheight); - if (ratio < 1.3f) + if (Is54Aspect(ratio)) { cwidth = realwidth; cheight = realheight * AspectMultiplier(ratio) / 48; @@ -1703,22 +1703,29 @@ int CheckRatio (int width, int height, int *trueratio) int AspectBaseWidth(float aspect) { - return (int)round(240.0f * aspect * 3.0f); + return !Is54Aspect(aspect) ? (int)round(240.0f * aspect * 3.0f) : 960; } int AspectBaseHeight(float aspect) { - return (int)round(200.0f * (320.0f / (240.0f * aspect)) * 3.0f); + return !Is54Aspect(aspect) ? (int)round(200.0f * (320.0f / (240.0f * aspect)) * 3.0f) : 640; } -int AspectPspriteOffset(float aspect) +double AspectPspriteOffset(float aspect) { - return aspect < 1.3f ? (int)(6.5*FRACUNIT) : 0; + return !Is54Aspect(aspect) ? 0.0 : 6.5; } int AspectMultiplier(float aspect) { - return (int)round(320.0f / (240.0f * aspect) * 48.0f); + return !Is54Aspect(aspect) ? (int)round(320.0f / (240.0f * aspect) * 48.0f) : 48 * 15 / 16; +} + +bool Is54Aspect(float aspect) +{ + // The 5:4 aspect ratio redefined all the values to mean something else.. + // Limit the range this is active to try prevent square cam textures inheriting this madness. + return aspect > 1.1f && aspect < 1.3f; } void IVideo::DumpAdapters () diff --git a/src/v_video.h b/src/v_video.h index 8d785e43f..26d45d9a0 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -523,8 +523,9 @@ static inline double ActiveRatio (double width, double height) { return ActiveRa int AspectBaseWidth(float aspect); int AspectBaseHeight(float aspect); -int AspectPspriteOffset(float aspect); +double AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); +bool Is54Aspect(float aspect); EXTERN_CVAR(Int, uiscale); From 017d1cee29adf2b2b479cc26dbb8ac5f461f5f0a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 13 Sep 2016 23:26:30 +0200 Subject: [PATCH 18/30] Change canvas rendering to use the aspect ratio of the canvas and generalize 5:4 rendering as AspectTallerThanWide --- src/g_shared/shared_sbar.cpp | 2 +- src/r_main.cpp | 6 +++--- src/r_utility.cpp | 14 +++++++++++--- src/r_utility.h | 2 +- src/v_draw.cpp | 6 +++--- src/v_video.cpp | 25 ++++++++++++++++--------- src/v_video.h | 2 +- 7 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 22171a4bb..f66ec187d 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -300,7 +300,7 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) ST_X = 0; ST_Y = VirticalResolution - RelTop; float aspect = ActiveRatio(SCREENWIDTH, SCREENHEIGHT); - if (!Is54Aspect(aspect)) + if (!AspectTallerThanWide(aspect)) { // Normal resolution ::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution); } diff --git a/src/r_main.cpp b/src/r_main.cpp index 6094f70de..040b57b71 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -318,7 +318,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; - if (Is54Aspect(trueratio)) + if (AspectTallerThanWide(trueratio)) { virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48; } @@ -327,7 +327,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48; } - if (Is54Aspect(WidescreenRatio)) + if (AspectTallerThanWide(WidescreenRatio)) { virtheight = virtheight * AspectMultiplier(WidescreenRatio) / 48; } @@ -948,7 +948,7 @@ void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas, RenderTarget = canvas; bRenderingToCanvas = true; - R_SetWindow (12, width, height, height); + R_SetWindow (12, width, height, height, true); viewwindowx = x; viewwindowy = y; viewactive = true; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 76cf05e9b..ebe36dc9d 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -198,7 +198,7 @@ void R_SetViewSize (int blocks) // //========================================================================== -void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) +void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, bool renderingToCanvas) { float trueratio; @@ -220,7 +220,15 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) freelookviewheight = ((setblocks*fullHeight)/10)&~7; } - WidescreenRatio = ActiveRatio (fullWidth, fullHeight, &trueratio); + if (renderingToCanvas) + { + WidescreenRatio = fullWidth / (float)fullHeight; + trueratio = WidescreenRatio; + } + else + { + WidescreenRatio = ActiveRatio(fullWidth, fullHeight, &trueratio); + } DrawFSHUD = (windowSize == 11); @@ -229,7 +237,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) centery = viewheight/2; centerx = viewwidth/2; - if (Is54Aspect(WidescreenRatio)) + if (AspectTallerThanWide(WidescreenRatio)) { centerxwide = centerx; } diff --git a/src/r_utility.h b/src/r_utility.h index e9fd436e5..09a8b5667 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -95,7 +95,7 @@ void R_ExecuteSetViewSize (void); // Called by M_Responder. void R_SetViewSize (int blocks); -void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight); +void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, bool renderingToCanvas = false); extern void R_FreePastViewers (); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 3075cd92d..4677c4b08 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -874,7 +874,7 @@ void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, double right = x + w; double bottom = y + h; - if (myratio > 1.4f) + if (myratio > 1.334f) { // The target surface is either 16:9 or 16:10, so expand the // specified virtual size to avoid undesired stretching of the // image. Does not handle non-4:3 virtual sizes. I'll worry about @@ -887,7 +887,7 @@ void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, x = x * Width / vwidth; w = right * Width / vwidth - x; } - if (Is54Aspect(myratio)) + if (AspectTallerThanWide(myratio)) { // The target surface is 5:4 y = (y - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5; h = (bottom - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5 - y; @@ -950,7 +950,7 @@ void DCanvas::FillBorder (FTexture *img) return; } int bordtop, bordbottom, bordleft, bordright, bord; - if (Is54Aspect(myratio)) + if (AspectTallerThanWide(myratio)) { // Screen is taller than it is wide bordleft = bordright = 0; bord = Height - Height * AspectMultiplier(myratio) / 48; diff --git a/src/v_video.cpp b/src/v_video.cpp index 710d8b1cf..af190d372 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1362,7 +1362,7 @@ void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int real int cx1, cy1, cx2, cy2; ratio = ActiveRatio(realwidth, realheight); - if (Is54Aspect(ratio)) + if (AspectTallerThanWide(ratio)) { cwidth = realwidth; cheight = realheight * AspectMultiplier(ratio) / 48; @@ -1703,29 +1703,36 @@ int CheckRatio (int width, int height, int *trueratio) int AspectBaseWidth(float aspect) { - return !Is54Aspect(aspect) ? (int)round(240.0f * aspect * 3.0f) : 960; + return (int)round(240.0f * aspect * 3.0f); } int AspectBaseHeight(float aspect) { - return !Is54Aspect(aspect) ? (int)round(200.0f * (320.0f / (240.0f * aspect)) * 3.0f) : 640; + if (!AspectTallerThanWide(aspect)) + return (int)round(200.0f * (320.0f / (AspectBaseWidth(aspect) / 3.0f)) * 3.0f); + else + return (int)round((200.0f * (4.0f / 3.0f)) / aspect * 3.0f); } double AspectPspriteOffset(float aspect) { - return !Is54Aspect(aspect) ? 0.0 : 6.5; + if (!AspectTallerThanWide(aspect)) + return 0.0; + else + return ((4.0 / 3.0) / aspect - 1.0) * 97.5; } int AspectMultiplier(float aspect) { - return !Is54Aspect(aspect) ? (int)round(320.0f / (240.0f * aspect) * 48.0f) : 48 * 15 / 16; + if (!AspectTallerThanWide(aspect)) + return (int)round(320.0f / (AspectBaseWidth(aspect) / 3.0f) * 48.0f); + else + return (int)round(200.0f / (AspectBaseHeight(aspect) / 3.0f) * 48.0f); } -bool Is54Aspect(float aspect) +bool AspectTallerThanWide(float aspect) { - // The 5:4 aspect ratio redefined all the values to mean something else.. - // Limit the range this is active to try prevent square cam textures inheriting this madness. - return aspect > 1.1f && aspect < 1.3f; + return aspect < 1.333f; } void IVideo::DumpAdapters () diff --git a/src/v_video.h b/src/v_video.h index 26d45d9a0..7317c9d1a 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -525,7 +525,7 @@ int AspectBaseWidth(float aspect); int AspectBaseHeight(float aspect); double AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); -bool Is54Aspect(float aspect); +bool AspectTallerThanWide(float aspect); EXTERN_CVAR(Int, uiscale); From f1bca9d20e7d36b3057cc9faee7da213d9cbedd0 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 13 Sep 2016 20:10:06 -0400 Subject: [PATCH 19/30] The old DirectX setup is required to utilize v140_xp. Revert "- removed DirectX setup from CMakeLists for Visual Studio" This reverts commit 954ac8ce5e607e7811a91717e0e1cfe5126d820a. --- src/CMakeLists.txt | 86 ++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bb5f21308..7f1554f44 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -114,59 +114,49 @@ if( WIN32 ) set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib ) set( NASM_NAMES nasmw nasm ) - if( NOT MSVC ) - find_path( D3D_INCLUDE_DIR d3d9.h - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Include ) - if( NOT D3D_INCLUDE_DIR ) - message( SEND_ERROR "Could not find DirectX 9 header files" ) - else() - include_directories( ${D3D_INCLUDE_DIR} ) - endif() - - find_path( XINPUT_INCLUDE_DIR xinput.h - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Include ) - if( NOT XINPUT_INCLUDE_DIR ) - message( WARNING "Could not find xinput.h. XInput will be disabled." ) - add_definitions( -DNO_XINPUT ) - else() - include_directories( ${XINPUT_INCLUDE_DIR} ) - endif() - - find_library( DX_dxguid_LIBRARY dxguid - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) - find_library( DX_dinput8_LIBRARY dinput8 - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) - - set( DX_LIBS_FOUND YES ) - if( NOT DX_dxguid_LIBRARY ) - set( DX_LIBS_FOUND NO ) - endif() - if( NOT DX_dinput8_LIBRARY ) - set( DX_LIBS_FOUND NO ) - endif() - - if( NOT DX_LIBS_FOUND ) - message( FATAL_ERROR "Could not find DirectX 9 libraries" ) - endif() - - set( DX_LIBS - "${DX_dxguid_LIBRARY}" - "${DX_dinput8_LIBRARY}" - ) + find_path( D3D_INCLUDE_DIR d3d9.h + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Include ) + if( NOT D3D_INCLUDE_DIR ) + message( SEND_ERROR "Could not find DirectX 9 header files" ) else() - set( DX_LIBS - dxguid - dinput8 - ) + include_directories( ${D3D_INCLUDE_DIR} ) + endif() + + find_path( XINPUT_INCLUDE_DIR xinput.h + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Include ) + if( NOT XINPUT_INCLUDE_DIR ) + message( WARNING "Could not find xinput.h. XInput will be disabled." ) + add_definitions( -DNO_XINPUT ) + else() + include_directories( ${XINPUT_INCLUDE_DIR} ) endif() - set( ZDOOM_LIBS ${DX_LIBS} + find_library( DX_dxguid_LIBRARY dxguid + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Lib Lib/${XBITS} ) + find_library( DX_dinput8_LIBRARY dinput8 + PATHS ENV DXSDK_DIR + PATH_SUFFIXES Lib Lib/${XBITS} ) + + set( DX_LIBS_FOUND YES ) + if( NOT DX_dxguid_LIBRARY ) + set( DX_LIBS_FOUND NO ) + endif() + if( NOT DX_dinput8_LIBRARY ) + set( DX_LIBS_FOUND NO ) + endif() + + if( NOT DX_LIBS_FOUND ) + message( FATAL_ERROR "Could not find DirectX 9 libraries" ) + endif() + + set( ZDOOM_LIBS wsock32 winmm + "${DX_dxguid_LIBRARY}" + "${DX_dinput8_LIBRARY}" ole32 user32 gdi32 From fd53aefbf27e4ffd2423d027d10f95b3be07dead Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 13 Sep 2016 20:54:06 -0400 Subject: [PATCH 20/30] Added warning if building on Visual Studio 2015 without v140_xp. --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f0bf8293..9d7da1644 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,11 @@ list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ) include( CreateLaunchers ) include( FindPackageHandleStandardArgs ) +# Produce a warning if XP support will be missing. +if( MSVC14 AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" ) + message( WARNING "This project supports Windows XP (including XP x64), but you must set the optional toolset to v140_xp manually to have it in your build! Use -T \"v140_xp\" from the command prompt." ) +endif() + # Support cross compiling option( FORCE_CROSSCOMPILE "Turn on cross compiling." NO ) if( FORCE_CROSSCOMPILE ) From 3b2359959ef9432448c685cc727039e19d2bf26a Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Tue, 13 Sep 2016 23:06:57 -0500 Subject: [PATCH 21/30] Quakes must use their own independent falloffs.This caused discrepencies and sudden drop-outs in stacked quakes otherwise. --- src/g_shared/a_quake.cpp | 10 ++++------ src/g_shared/a_sharedglobal.h | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index aae006ca7..63394e02a 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -291,10 +291,9 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger if (!(quake->m_Flags & QF_WAVE)) { - jiggers.Falloff = MAX(falloff, jiggers.Falloff); - jiggers.RollIntensity = MAX(r, jiggers.RollIntensity) * jiggers.Falloff; + jiggers.RollIntensity = MAX(r, jiggers.RollIntensity) * falloff; - intensity *= jiggers.Falloff; + intensity *= falloff; if (quake->m_Flags & QF_RELATIVE) { jiggers.RelIntensity.X = MAX(intensity.X, jiggers.RelIntensity.X); @@ -310,14 +309,13 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger } else { - jiggers.Falloff = MAX(falloff, jiggers.Falloff); - jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave) * jiggers.Falloff * strength; + jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave) * falloff * strength; intensity.X *= quake->GetModWave(quake->m_WaveSpeed.X); intensity.Y *= quake->GetModWave(quake->m_WaveSpeed.Y); intensity.Z *= quake->GetModWave(quake->m_WaveSpeed.Z); - intensity *= strength * jiggers.Falloff; + intensity *= strength * falloff; // [RH] This only gives effect to the last sine quake. I would // prefer if some way was found to make multiples coexist diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 314061f04..029653bb1 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -153,7 +153,6 @@ struct FQuakeJiggers DVector3 RelIntensity; DVector3 Offset; DVector3 RelOffset; - double Falloff; double RollIntensity, RollWave; }; From 65af26f9629149ec03df5fa3dcccc528aa920c73 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Wed, 14 Sep 2016 12:30:11 +0200 Subject: [PATCH 22/30] The VM now properly aborts on critical errors --- src/zscript/vm.h | 8 ++++++++ src/zscript/vmexec.cpp | 10 +--------- src/zscript/vmframe.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 52b354028..31136bba2 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -156,6 +156,14 @@ enum ATAG_RNG, // pointer to FRandom }; +enum EVMAbortException +{ + X_READ_NIL, + X_WRITE_NIL, + X_TOO_MANY_TRIES, + X_ARRAY_OUT_OF_BOUNDS, +}; + class VMFunction : public DObject { DECLARE_ABSTRACT_CLASS(VMFunction, DObject); diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index 070aeb30a..454f02d03 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -44,7 +44,7 @@ #define ASSERTKA(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstA) #define ASSERTKS(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstS) -#define THROW(x) +#define THROW(x) throw(EVMAbortException(x)) #define CMPJMP(test) \ if ((test) == (a & CMP_CHECK)) { \ @@ -54,14 +54,6 @@ pc += 1; \ } -enum -{ - X_READ_NIL, - X_WRITE_NIL, - X_TOO_MANY_TRIES, - X_ARRAY_OUT_OF_BOUNDS -}; - #define GETADDR(a,o,x) \ if (a == NULL) { THROW(x); } \ ptr = (VM_SBYTE *)a + o diff --git a/src/zscript/vmframe.cpp b/src/zscript/vmframe.cpp index c7d9cb87d..9f8ad7dc0 100644 --- a/src/zscript/vmframe.cpp +++ b/src/zscript/vmframe.cpp @@ -407,6 +407,40 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur } throw; } + catch (EVMAbortException exception) + { + if (allocated) + { + PopFrame(); + } + if (trap != nullptr) + { + *trap = nullptr; + } + + Printf("VM execution aborted: "); + switch (exception) + { + case X_READ_NIL: + Printf("tried to read from address zero."); + break; + + case X_WRITE_NIL: + Printf("tried to write to address zero."); + break; + + case X_TOO_MANY_TRIES: + Printf("too many try-catch blocks."); + break; + + case X_ARRAY_OUT_OF_BOUNDS: + Printf("array access out of bounds."); + break; + } + Printf("\n"); + + return -1; + } catch (...) { if (allocated) From cb17e109f17a36c9f1465568630cc361cf8bac74 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Wed, 14 Sep 2016 12:43:05 +0200 Subject: [PATCH 23/30] Added "division by zero" to the VM-aborting errors --- src/zscript/vm.h | 1 + src/zscript/vmexec.h | 40 ++++++++++++++++++++++++++++++++++++++++ src/zscript/vmframe.cpp | 4 ++++ 3 files changed, 45 insertions(+) diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 31136bba2..0d45ad90a 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -162,6 +162,7 @@ enum EVMAbortException X_WRITE_NIL, X_TOO_MANY_TRIES, X_ARRAY_OUT_OF_BOUNDS, + X_DIVISION_BY_ZERO, }; class VMFunction : public DObject diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index 8232340a0..42a374030 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -786,27 +786,51 @@ begin: OP(DIV_RR): ASSERTD(a); ASSERTD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = reg.d[B] / reg.d[C]; NEXTOP; OP(DIV_RK): ASSERTD(a); ASSERTD(B); ASSERTKD(C); + if (konstd[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = reg.d[B] / konstd[C]; NEXTOP; OP(DIV_KR): ASSERTD(a); ASSERTKD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = konstd[B] / reg.d[C]; NEXTOP; OP(MOD_RR): ASSERTD(a); ASSERTD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = reg.d[B] % reg.d[C]; NEXTOP; OP(MOD_RK): ASSERTD(a); ASSERTD(B); ASSERTKD(C); + if (konstd[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = reg.d[B] % konstd[C]; NEXTOP; OP(MOD_KR): ASSERTD(a); ASSERTKD(B); ASSERTD(C); + if (reg.d[C] == 0) + { + THROW(X_DIVISION_BY_ZERO); + } reg.d[a] = konstd[B] % reg.d[C]; NEXTOP; @@ -981,14 +1005,26 @@ begin: OP(DIVF_RR): ASSERTF(a); ASSERTF(B); ASSERTF(C); + if (reg.f[C] == 0.) + { + THROW(X_DIVISION_BY_ZERO); + } reg.f[a] = reg.f[B] / reg.f[C]; NEXTOP; OP(DIVF_RK): ASSERTF(a); ASSERTF(B); ASSERTKF(C); + if (konstf[C] == 0.) + { + THROW(X_DIVISION_BY_ZERO); + } reg.f[a] = reg.f[B] / konstf[C]; NEXTOP; OP(DIVF_KR): ASSERTF(a); ASSERTKF(B); ASSERTF(C); + if (reg.f[C] == 0.) + { + THROW(X_DIVISION_BY_ZERO); + } reg.f[a] = konstf[B] / reg.f[C]; NEXTOP; @@ -996,6 +1032,10 @@ begin: ASSERTF(a); ASSERTF(B); ASSERTF(C); fb = reg.f[B]; fc = reg.f[C]; Do_MODF: + if (fc == 0.) + { + THROW(X_DIVISION_BY_ZERO); + } reg.f[a] = luai_nummod(fb, fc); NEXTOP; OP(MODF_RK): diff --git a/src/zscript/vmframe.cpp b/src/zscript/vmframe.cpp index 9f8ad7dc0..29da0c5b9 100644 --- a/src/zscript/vmframe.cpp +++ b/src/zscript/vmframe.cpp @@ -436,6 +436,10 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur case X_ARRAY_OUT_OF_BOUNDS: Printf("array access out of bounds."); break; + + case X_DIVISION_BY_ZERO: + Printf("division by zero."); + break; } Printf("\n"); From 48f491cfd12ddc489faf296898f9db050e907767 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 14 Sep 2016 23:38:11 +0200 Subject: [PATCH 24/30] Fix video mode selection bug --- src/menu/videomenu.cpp | 24 ++++++++++++------------ src/v_video.cpp | 4 ++++ src/v_video.h | 4 ++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 1328e2f7a..b1b4d792f 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -95,7 +95,7 @@ CUSTOM_CVAR (Int, menu_screenratios, -1, CVAR_ARCHIVE) } else { - BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits); + BuildModesList (screen->VideoWidth, screen->VideoHeight, DisplayBits); } } @@ -139,7 +139,7 @@ public: DVideoModeMenu() { - SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits); + SetModesMenu (screen->VideoWidth, screen->VideoHeight, DisplayBits); } bool MenuEvent(int mkey, bool fromcontroller) @@ -163,13 +163,13 @@ public: { if (!GetSelectedSize (&NewWidth, &NewHeight)) { - NewWidth = SCREENWIDTH; - NewHeight = SCREENHEIGHT; + NewWidth = screen->VideoWidth; + NewHeight = screen->VideoHeight; } else { - OldWidth = SCREENWIDTH; - OldHeight = SCREENHEIGHT; + OldWidth = screen->VideoWidth; + OldHeight = screen->VideoHeight; OldBits = DisplayBits; NewBits = BitTranslate[DummyDepthCvar]; setmodeneeded = true; @@ -297,11 +297,11 @@ void M_RestoreMode () void M_SetDefaultMode () { // Make current resolution the default - vid_defwidth = SCREENWIDTH; - vid_defheight = SCREENHEIGHT; + vid_defwidth = screen->VideoWidth; + vid_defheight = screen->VideoHeight; vid_defbits = DisplayBits; testingmode = 0; - SetModesMenu (SCREENWIDTH, SCREENHEIGHT, DisplayBits); + SetModesMenu (screen->VideoWidth, screen->VideoHeight, DisplayBits); } @@ -314,7 +314,7 @@ void M_SetDefaultMode () void M_RefreshModesList () { - BuildModesList (SCREENWIDTH, SCREENHEIGHT, DisplayBits); + BuildModesList (screen->VideoWidth, screen->VideoHeight, DisplayBits); } void M_InitVideoModesMenu () @@ -385,8 +385,8 @@ void M_SetVideoMode() { if (!GetSelectedSize (&NewWidth, &NewHeight)) { - NewWidth = SCREENWIDTH; - NewHeight = SCREENHEIGHT; + NewWidth = screen->VideoWidth; + NewHeight = screen->VideoHeight; } else { diff --git a/src/v_video.cpp b/src/v_video.cpp index af190d372..b1f1ced9c 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -850,6 +850,9 @@ DFrameBuffer::DFrameBuffer (int width, int height) { LastMS = LastSec = FrameCount = LastCount = LastTic = 0; Accel2D = false; + + VideoWidth = width; + VideoHeight = height; } //========================================================================== @@ -1352,6 +1355,7 @@ void V_OutputResized (int width, int height) { StatusBar->ScreenSizeChanged(); } + C_NewModeAdjust(); } void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) diff --git a/src/v_video.h b/src/v_video.h index 7317c9d1a..d19a3b06e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -422,6 +422,10 @@ public: virtual bool Is8BitMode() = 0; #endif + // The original size of the framebuffer as selected in the video menu. + int VideoWidth = 0; + int VideoHeight = 0; + protected: void DrawRateStuff (); void CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest); From 0d27996a648a9668650f396b9de544371074f820 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 14 Sep 2016 23:38:50 +0200 Subject: [PATCH 25/30] Replace CheckRatio with AspectTallerThanWide in DrawHUD --- src/g_shared/shared_hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index e40233def..c4d8ec1ed 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -1108,7 +1108,7 @@ void DrawHUD() } else { - if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) == 4) + if (AspectTallerThanWide(WidescreenRatio)) { hudheight = hudwidth * 30 / AspectMultiplier(WidescreenRatio); // BaseRatioSizes is inverted for this mode } From ac70f77e44c17115f908d85275d868ada936e582 Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Thu, 15 Sep 2016 15:09:36 -0400 Subject: [PATCH 26/30] Added the following ccmds: actorlist, actornum, monsternum, itemsnum, countitemsnum Modified the following ccmds: monster, items, countitems All commands with "num" at the end simply print a count of their respective filters, all other listed commands now print a list and a count. --- src/c_cmds.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index d72fc79a2..fa01e1b4b 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -923,10 +923,18 @@ static bool IsActorACountItem(AActor *mo) return mo->IsKindOf(RUNTIME_CLASS(AInventory)) && mo->flags&MF_SPECIAL && mo->flags&MF_COUNTITEM; } -static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const char *FilterName) +// [SP] for all actors +static bool IsActor(AActor *mo) +{ + return true; +} + +// [SP] modified - now allows showing count only, new arg must be passed. Also now still counts regardless, if lists are printed. +static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const char *FilterName, bool countOnly) { AActor *mo; const PClass *FilterClass = NULL; + int counter = 0; if (FilterName != NULL) { @@ -943,10 +951,32 @@ static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const cha { if ((FilterClass == NULL || mo->IsA(FilterClass)) && IsActorType(mo)) { - Printf ("%s at (%f,%f,%f)\n", - mo->GetClass()->TypeName.GetChars(), mo->X(), mo->Y(), mo->Z()); + counter++; + if (!countOnly) + Printf ("%s at (%f,%f,%f)\n", + mo->GetClass()->TypeName.GetChars(), mo->X(), mo->Y(), mo->Z()); } } + Printf("%i match(s) found.\n", counter); +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- +CCMD(actorlist) // [SP] print all actors (this can get quite big?) +{ + if (CheckCheatmode ()) return; + + PrintFilteredActorList(IsActor, argv.argc() > 1 ? argv[1] : NULL, false); +} + +CCMD(actornum) // [SP] count all actors +{ + if (CheckCheatmode ()) return; + + PrintFilteredActorList(IsActor, argv.argc() > 1 ? argv[1] : NULL, true); } //----------------------------------------------------------------------------- @@ -958,7 +988,14 @@ CCMD(monster) { if (CheckCheatmode ()) return; - PrintFilteredActorList(IsActorAMonster, argv.argc() > 1 ? argv[1] : NULL); + PrintFilteredActorList(IsActorAMonster, argv.argc() > 1 ? argv[1] : NULL, false); +} + +CCMD(monsternum) // [SP] count monsters +{ + if (CheckCheatmode ()) return; + + PrintFilteredActorList(IsActorAMonster, argv.argc() > 1 ? argv[1] : NULL, true); } //----------------------------------------------------------------------------- @@ -970,7 +1007,14 @@ CCMD(items) { if (CheckCheatmode ()) return; - PrintFilteredActorList(IsActorAnItem, argv.argc() > 1 ? argv[1] : NULL); + PrintFilteredActorList(IsActorAnItem, argv.argc() > 1 ? argv[1] : NULL, false); +} + +CCMD(itemsnum) // [SP] # of any items +{ + if (CheckCheatmode ()) return; + + PrintFilteredActorList(IsActorAnItem, argv.argc() > 1 ? argv[1] : NULL, true); } //----------------------------------------------------------------------------- @@ -982,7 +1026,14 @@ CCMD(countitems) { if (CheckCheatmode ()) return; - PrintFilteredActorList(IsActorACountItem, argv.argc() > 1 ? argv[1] : NULL); + PrintFilteredActorList(IsActorACountItem, argv.argc() > 1 ? argv[1] : NULL, false); +} + +CCMD(countitemsnum) // [SP] # of counted items +{ + if (CheckCheatmode ()) return; + + PrintFilteredActorList(IsActorACountItem, argv.argc() > 1 ? argv[1] : NULL, true); } //----------------------------------------------------------------------------- From 476b727d5d99afccaf7a73935379816734500157 Mon Sep 17 00:00:00 2001 From: raa-eruanna Date: Fri, 16 Sep 2016 00:47:56 -0400 Subject: [PATCH 27/30] "actorlist" and "actornum" no longer return already-owned inventory objects --- src/c_cmds.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index fa01e1b4b..03a7495e4 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -926,7 +926,10 @@ static bool IsActorACountItem(AActor *mo) // [SP] for all actors static bool IsActor(AActor *mo) { - return true; + if (mo->IsKindOf(RUNTIME_CLASS(AInventory))) + return static_cast(mo)->Owner == NULL; // [SP] Exclude inventory-owned items + else + return true; } // [SP] modified - now allows showing count only, new arg must be passed. Also now still counts regardless, if lists are printed. From 3db7d9ad8459f36aa7c3d80594c6725edae72231 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 Sep 2016 12:22:56 +0200 Subject: [PATCH 28/30] - fixed: AActor::alternative was not declared as a pointer. --- src/p_mobj.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 6d8ce4418..e93b886e8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -140,6 +140,7 @@ IMPLEMENT_POINTY_CLASS (AActor) DECLARE_POINTER (master) DECLARE_POINTER (Poisoner) DECLARE_POINTER (Damage) + DECLARE_POINTER (alternative) END_POINTERS AActor::~AActor () From f1ba19073fce4af02298056b93bd78ff16313822 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 19 Sep 2016 03:36:51 +0200 Subject: [PATCH 29/30] - split Damage into two variables: DamageVal for the old constant and DamageFunc for the DECORATE function. The way this was done was a major headache inducer, requiring reconstruction of the function each time the value was changed and in general made actor damage a major hassle. There was a DECORATE wrapper to mimic the original behavior but this looked quite broken because it completely ignored the different semantics of both damage calculation types. It also made it impossible to determine if damage was a function or a value. This accessor has been reverted to what it should be, only returning the constant, which now is -1 for a damage function. I am sorry if this may break the odd mod out but a quick look over some DECORATE-heavy stuff showed that this was never combined in any of them so that accessing 'damage' in DECORATE code depended on an actual damage function. To get proper damage, a future commit will add a DECORATE function which calls AActor::GetMissileDamage. --- src/actor.h | 23 +++++- src/d_dehacked.cpp | 2 +- src/g_doom/a_bossbrain.cpp | 2 +- src/g_heretic/a_ironlich.cpp | 4 +- src/g_hexen/a_magelightning.cpp | 2 +- src/info.cpp | 2 +- src/p_acs.cpp | 2 +- src/p_map.cpp | 2 +- src/p_mobj.cpp | 115 ++++++--------------------- src/thingdef/olddecorations.cpp | 3 +- src/thingdef/thingdef.cpp | 12 +-- src/thingdef/thingdef_data.cpp | 1 + src/thingdef/thingdef_exp.h | 17 +--- src/thingdef/thingdef_expression.cpp | 74 +---------------- src/thingdef/thingdef_parse.cpp | 16 ++-- src/thingdef/thingdef_properties.cpp | 11 ++- 16 files changed, 81 insertions(+), 207 deletions(-) diff --git a/src/actor.h b/src/actor.h index 522405dd6..d804b0995 100644 --- a/src/actor.h +++ b/src/actor.h @@ -111,6 +111,8 @@ struct FPortalGroupArray; // Any questions? // + + // --- mobj.flags --- enum ActorFlag { @@ -1014,7 +1016,9 @@ public: SDWORD tics; // state tic counter FState *state; - VMFunction *Damage; // For missiles and monster railgun + //VMFunction *Damage; // For missiles and monster railgun + int DamageVal; + VMFunction *DamageFunc; int projectileKickback; ActorFlags flags; ActorFlags2 flags2; // Heretic flags @@ -1201,6 +1205,23 @@ public: FState *GetRaiseState(); void Revive(); + void SetDamage(int dmg) + { + DamageVal = dmg; + DamageFunc = nullptr; + } + + bool IsZeroDamage() const + { + return DamageVal == 0 && DamageFunc == nullptr; + } + + void RestoreDamage() + { + DamageVal = GetDefault()->DamageVal; + DamageFunc = GetDefault()->DamageFunc; + } + FState *FindState (FName label) const { return GetClass()->FindState(1, &label); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 4beb5c25a..dfa4f56f0 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -915,7 +915,7 @@ static int PatchThing (int thingy) } else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) { - info->Damage = CreateDamageFunction(val); + info->SetDamage(val); } else if (linelen == 5) { diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 5d10e0138..e6fd5f16d 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -47,7 +47,7 @@ static void BrainishExplosion (const DVector3 &pos) boom->SetState (state); } boom->effects = 0; - boom->Damage = NULL; // disables collision detection which is not wanted here + boom->SetDamage(0); // disables collision detection which is not wanted here boom->tics -= pr_brainscream() & 7; if (boom->tics < 1) boom->tics = 1; diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index 7f33fb57a..a88748407 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack) fire->target = baseFire->target; fire->Angles.Yaw = baseFire->Angles.Yaw; fire->Vel = baseFire->Vel; - fire->Damage = NULL; + fire->SetDamage(0); fire->health = (i+1) * 2; P_CheckMissileSpawn (fire, self->radius); } @@ -205,7 +205,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow) self->AddZ(9.); if (self->health == 0) { - self->Damage = self->GetDefault()->Damage; + self->RestoreDamage(); self->SetState (self->FindState("NoGrow")); } return 0; diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index b5718f4d7..896384f4e 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -340,7 +340,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap) { mo->SetState (mo->FindState (NAME_Death)); mo->Vel.Z = 40; - mo->Damage = NULL; + mo->SetDamage(0); } return 0; } diff --git a/src/info.cpp b/src/info.cpp index 7198a5de4..6eeca1186 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -344,7 +344,7 @@ size_t PClassActor::PropagateMark() // Mark damage function if (Defaults != NULL) { - GC::Mark(((AActor *)Defaults)->Damage); + GC::Mark(((AActor *)Defaults)->DamageFunc); } // marked += ActorInfo->NumOwnedStates * sizeof(FState); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 67ae37771..ffac7a78f 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3791,7 +3791,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) break; case APROP_Damage: - actor->Damage = CreateDamageFunction(value); + actor->SetDamage(value); break; case APROP_Alpha: diff --git a/src/p_map.cpp b/src/p_map.cpp index 7316e1c96..5cc9bdf72 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1320,7 +1320,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // [RH] What is the point of this check, again? In Hexen, it is unconditional, // but here we only do it if the missile's damage is 0. // MBF bouncer might have a non-0 damage value, but they must not deal damage on impact either. - if ((tm.thing->BounceFlags & BOUNCE_Actors) && (tm.thing->Damage == 0 || !(tm.thing->flags & MF_MISSILE))) + if ((tm.thing->BounceFlags & BOUNCE_Actors) && (tm.thing->IsZeroDamage() || !(tm.thing->flags & MF_MISSILE))) { return (tm.thing->target == thing || !(thing->flags & MF_SOLID)); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e93b886e8..d38901f1e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -139,7 +139,7 @@ IMPLEMENT_POINTY_CLASS (AActor) DECLARE_POINTER (LastHeard) DECLARE_POINTER (master) DECLARE_POINTER (Poisoner) - DECLARE_POINTER (Damage) + DECLARE_POINTER (DamageFunc) DECLARE_POINTER (alternative) END_POINTERS @@ -149,73 +149,6 @@ AActor::~AActor () // Use Destroy() instead. } -//========================================================================== -// -// CalcDamageValue -// -// Given a script function, returns an integer to represent it in a -// savegame. This encoding is compatible with previous incarnations -// where damage was an integer. -// -// 0 : use null function -// 0x40000000 : use default function -// anything else : use function that returns this number -// -//========================================================================== - -static int CalcDamageValue(VMFunction *func) -{ - if (func == NULL) - { - return 0; - } - VMScriptFunction *sfunc = dyn_cast(func); - if (sfunc == NULL) - { - return 0x40000000; - } - VMOP *op = sfunc->Code; - // If the function was created by CreateDamageFunction(), extract - // the value used to create it and return that. Otherwise, return - // indicating to use the default function. - if (op->op == OP_RETI && op->a == 0) - { - return op->i16; - } - if (op->op == OP_RET && op->a == 0 && op->b == (REGT_INT | REGT_KONST)) - { - return sfunc->KonstD[op->c]; - } - return 0x40000000; -} - -//========================================================================== -// -// UncalcDamageValue -// -// Given a damage integer, returns a script function for it. -// -//========================================================================== - -static VMFunction *UncalcDamageValue(int dmg, VMFunction *def) -{ - if (dmg == 0) - { - return NULL; - } - if ((dmg & 0xC0000000) == 0x40000000) - { - return def; - } - // Does the default version return this? If so, use it. Otherwise, - // create a new function. - if (CalcDamageValue(def) == dmg) - { - return def; - } - return CreateDamageFunction(dmg); -} - //========================================================================== // // AActor :: Serialize @@ -263,18 +196,16 @@ void AActor::Serialize(FArchive &arc) << projectilepassheight << Vel << tics - << state; - if (arc.IsStoring()) + << state + << DamageVal; + if (DamageVal == 0x40000000 || DamageVal == -1) { - int dmg; - dmg = CalcDamageValue(Damage); - arc << dmg; + DamageVal = -1; + DamageFunc = GetDefault()->DamageFunc; } else { - int dmg; - arc << dmg; - Damage = UncalcDamageValue(dmg, GetDefault()->Damage); + DamageFunc = nullptr; } P_SerializeTerrain(arc, floorterrain); arc << projectileKickback @@ -2975,8 +2906,21 @@ CCMD(utid) int AActor::GetMissileDamage (int mask, int add) { - if (Damage == NULL) + if (DamageVal >= 0) { + if (mask == 0) + { + return add * DamageVal; + } + else + { + return ((pr_missiledamage() & mask) + add) * DamageVal; + } + } + if (DamageFunc == nullptr) + { + // This should never happen + assert(false && "No damage function found"); return 0; } VMFrameStack stack; @@ -2988,22 +2932,11 @@ int AActor::GetMissileDamage (int mask, int add) results[0].IntAt(&amount); results[1].IntAt(&calculated); - if (stack.Call(Damage, ¶m, 1, results, 2) < 1) + if (stack.Call(DamageFunc, ¶m, 1, results, 2) < 1) { // No results return 0; } - if (calculated) - { - return amount; - } - else if (mask == 0) - { - return add * amount; - } - else - { - return ((pr_missiledamage() & mask) + add) * amount; - } + return amount; } void AActor::Howl () @@ -3695,7 +3628,7 @@ void AActor::Tick () // still have missiles that go straight up and down through actors without // damaging anything. // (for backwards compatibility this must check for lack of damage function, not for zero damage!) - if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && Damage != NULL) + if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage()) { Vel.X = MinVel; } diff --git a/src/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp index 5fa994262..3ea0c4788 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/thingdef/olddecorations.cpp @@ -496,8 +496,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Projectile && sc.Compare ("Damage")) { sc.MustGetNumber (); - FxDamageValue *x = new FxDamageValue(new FxConstant(sc.Number, sc), false); - defaults->Damage = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(x) + 1); + defaults->SetDamage(sc.Number); } else if (def == DEF_Projectile && sc.Compare ("DamageType")) { diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index dfc960627..635637149 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -348,12 +348,12 @@ static void FinishThingdef() continue; } - if (def->Damage != NULL) + if (def->DamageFunc != nullptr) { - FxDamageValue *dmg = (FxDamageValue *)ActorDamageFuncs[(uintptr_t)def->Damage - 1]; + FxDamageValue *dmg = (FxDamageValue *)ActorDamageFuncs[(uintptr_t)def->DamageFunc - 1]; VMScriptFunction *sfunc; sfunc = dmg->GetFunction(); - if (sfunc == NULL) + if (sfunc == nullptr) { FCompileContext ctx(ti); dmg = static_cast(dmg->Resolve(ctx)); @@ -365,15 +365,15 @@ static void FinishThingdef() dmg->Emit(&buildit); sfunc = buildit.MakeFunction(); sfunc->NumArgs = 1; - sfunc->Proto = NULL; ///FIXME: Need a proper prototype here + sfunc->Proto = nullptr; ///FIXME: Need a proper prototype here // Save this function in case this damage value was reused // (which happens quite easily with inheritance). dmg->SetFunction(sfunc); } } - def->Damage = sfunc; + def->DamageFunc = sfunc; - if (dump != NULL && sfunc != NULL) + if (dump != nullptr && sfunc != nullptr) { char label[64]; int labellen = mysnprintf(label, countof(label), "Function %s.Damage", diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 756c56a1a..8248634a3 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -666,4 +666,5 @@ void InitThingdef() symt.AddSymbol(new PField(NAME_Speed, TypeFloat64, VARF_Native, myoffsetof(AActor, Speed))); symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, threshold))); symt.AddSymbol(new PField(NAME_DefThreshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DefThreshold))); + symt.AddSymbol(new PField(NAME_Damage, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DamageVal))); } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 2f06e085e..5fe8f252f 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -854,20 +854,6 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; -//========================================================================== -// -// FxDamage -// -//========================================================================== - -class FxDamage : public FxExpression -{ -public: - FxDamage(const FScriptPosition&); - FxExpression *Resolve(FCompileContext&); - ExpEmit Emit(VMFunctionBuilder *build); -}; - //========================================================================== // // FxArrayElement @@ -1188,12 +1174,11 @@ public: class FxDamageValue : public FxExpression { FxExpression *val; - bool Calculated; VMScriptFunction *MyFunction; public: - FxDamageValue(FxExpression *v, bool calc); + FxDamageValue(FxExpression *v); ~FxDamageValue(); FxExpression *Resolve(FCompileContext&); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 034c304c2..ce603f261 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3218,11 +3218,6 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars()); } } - // the damage property needs special handling - else if (Identifier == NAME_Damage) - { - newex = new FxDamage(ScriptPosition); - } // now check the global identifiers. else if ((sym = ctx.FindGlobal(Identifier)) != NULL) { @@ -3316,65 +3311,6 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) } -//========================================================================== -// -// -// -//========================================================================== - -FxDamage::FxDamage(const FScriptPosition &pos) -: FxExpression(pos) -{ -} - -//========================================================================== -// -// FxDamage :: Resolve -// -//========================================================================== - -FxExpression *FxDamage::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - ValueType = TypeSInt32; - return this; -} - -//========================================================================== -// -// FxDamage :: Emit -// -// Call this actor's damage function, if it has one -// -//========================================================================== - -ExpEmit FxDamage::Emit(VMFunctionBuilder *build) -{ - ExpEmit dmgval(build, REGT_INT); - - // Get damage function - ExpEmit dmgfunc(build, REGT_POINTER); - build->Emit(OP_LO, dmgfunc.RegNum, 0/*self*/, build->GetConstantInt(myoffsetof(AActor, Damage))); - - // If it's non-null... - build->Emit(OP_EQA_K, 1, dmgfunc.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); - size_t nulljump = build->Emit(OP_JMP, 0); - - // ...call it - build->Emit(OP_PARAM, 0, REGT_POINTER, 0/*self*/); - build->Emit(OP_CALL, dmgfunc.RegNum, 1, 1); - build->Emit(OP_RESULT, 0, REGT_INT, dmgval.RegNum); - size_t notnulljump = build->Emit(OP_JMP, 0); - - // Otherwise, use 0 - build->BackpatchToHere(nulljump); - build->EmitLoadInt(dmgval.RegNum, 0); - build->BackpatchToHere(notnulljump); - - return dmgval; -} - - //========================================================================== // // @@ -5225,18 +5161,12 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) // //========================================================================== -FxDamageValue::FxDamageValue(FxExpression *v, bool calc) +FxDamageValue::FxDamageValue(FxExpression *v) : FxExpression(v->ScriptPosition) { val = v; ValueType = TypeVoid; - Calculated = calc; MyFunction = NULL; - - if (!calc) - { - assert(v->isConstant() && "Non-calculated damage must be constant"); - } } FxDamageValue::~FxDamageValue() @@ -5272,7 +5202,7 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build) assert(emitval.RegType == REGT_INT); build->Emit(OP_RET, 0, REGT_INT | (emitval.Konst ? REGT_KONST : 0), emitval.RegNum); } - build->Emit(OP_RETI, 1 | RET_FINAL, Calculated); + build->Emit(OP_RETI, 1 | RET_FINAL, true); return ExpEmit(); } diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index b99f1a384..963165ab1 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -865,19 +865,21 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau if (sc.CheckString ("(")) { - x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true); + conv.i = -1; + params.Push(conv); + x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info))); sc.MustGetStringName(")"); + conv.exp = x; + params.Push(conv); + } else { sc.MustGetNumber(); - if (sc.Number != 0) - { - x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false); - } + conv.i = sc.Number; + params.Push(conv); + conv.exp = nullptr; } - conv.exp = x; - params.Push(conv); } break; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index f6ad511af..52194435b 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -636,7 +636,8 @@ DEFINE_PROPERTY(threshold, I, Actor) //========================================================================== DEFINE_PROPERTY(damage, X, Actor) { - PROP_EXP_PARM(id, 0); + PROP_INT_PARM(dmgval, 0); + PROP_EXP_PARM(id, 1); // Damage can either be a single number, in which case it is subject // to the original damage calculation rules. Or, it can be an expression @@ -646,13 +647,15 @@ DEFINE_PROPERTY(damage, X, Actor) // Store this expression here for now. It will be converted to a function // later once all actors have been processed. - if (id == NULL) + defaults->DamageVal = dmgval; + + if (id == nullptr) { - defaults->Damage = NULL; + defaults->DamageFunc = nullptr; } else { - defaults->Damage = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(id) + 1); + defaults->DamageFunc = (VMFunction *)(uintptr_t)(ActorDamageFuncs.Push(id) + 1); } } From 3eb1af6957541fa8ac021d9aa8aaf8218e8c9d6a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 19 Sep 2016 03:45:22 +0200 Subject: [PATCH 30/30] - added a GetMissileDamage function to DECORATE which can be used to properly retrieve an actor's damage value. The damage property should be considered deprecated inside expressions from now on. --- src/thingdef/thingdef_codeptr.cpp | 32 +++++++++++++++++++++++++++++++ wadsrc/static/actors/actor.txt | 1 + 2 files changed, 33 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 642f132af..21551364b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -231,6 +231,38 @@ DEFINE_ACTION_FUNCTION(AActor, CheckClass) return 0; } +//========================================================================== +// +// CheckClass +// +// NON-ACTION function to calculate missile damage for the given actor +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(AActor, GetMissileDamage) +{ + if (numret > 0) + { + assert(ret != NULL); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(mask); + PARAM_INT(add) + PARAM_INT_OPT(pick_pointer) { pick_pointer = AAPTR_DEFAULT; } + + self = COPY_AAPTR(self, pick_pointer); + if (self == NULL) + { + ret->SetInt(0); + } + else + { + ret->SetInt(self->GetMissileDamage(mask, add)); + } + return 1; + } + return 0; +} + //========================================================================== // // IsPointerEqual diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index b8bbcab14..b8b805219 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -53,6 +53,7 @@ ACTOR Actor native //: Thinker native int CountProximity(class classname, float distance, int flags = 0, int ptr = AAPTR_DEFAULT); native float GetSpriteAngle(int ptr = AAPTR_DEFAULT); native float GetSpriteRotation(int ptr = AAPTR_DEFAULT); + native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); // Action functions // Meh, MBF redundant functions. Only for DeHackEd support.