From 98e8b7c562aff57526fe8eef3ffd7fc6fb02e844 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 3 Nov 2024 21:46:04 -0500 Subject: [PATCH] Fix: DSurface lost (#109) Switching screen mode (from or to full screen) with FA2 open and loaded with map, when you get back, the program haulted and killed immediately. This PR fix the device lost issue, and get the right surface . --- MissionEditor/IsoView.cpp | 239 ++++++++++++++++- MissionEditor/IsoView.h | 4 +- MissionEditor/Loading.cpp | 245 ++---------------- MissionEditorPackLib/MissionEditorPackLib.cpp | 2 + MissionEditorPackLib/MissionEditorPackLib.h | 2 + 5 files changed, 266 insertions(+), 226 deletions(-) diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp index 5aacc66..01899a6 100644 --- a/MissionEditor/IsoView.cpp +++ b/MissionEditor/IsoView.cpp @@ -201,6 +201,218 @@ CIsoView::~CIsoView() bNoThreadDraw = TRUE; } +BOOL CIsoView::RecreateSurfaces() +{ + last_succeeded_operation = 7; + + errstream << "\n\nDirectDrawCreate() will be called now\n"; + errstream.flush(); + + CIsoView& isoView = *this; + if (DirectDrawCreate(NULL, &isoView.dd_1, NULL) != DD_OK) { + errstream << "DirectDrawCreate() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("DirectDraw could not be initialized! Quitting..."); + exit(-1); + + return FALSE; + } + + errstream << "DirectDrawCreate() successful\n\n"; + errstream.flush(); + + errstream << "Now querying the DirectX 7 or 6 interface\n"; + errstream.flush(); + + if (isoView.dd_1->QueryInterface(IID_IDirectDraw7, (void**)&isoView.dd) != DD_OK) { + errstream << "QueryInterface() failed -> Using DirectX 6.0\n"; + errstream.flush(); + //ShowWindow(SW_HIDE); + //MessageBox("You don´t have DirectX 6.0 but an older version. Quitting..."); + //exit(-1); + + //return FALSE; + + if (isoView.dd_1->QueryInterface(IID_IDirectDraw4, (void**)&isoView.dd) != DD_OK) { + MessageBox("You need at least DirectX 6.0 to run this program", "Error"); + exit(-1); + return FALSE; + } + } + + errstream << "QueryInterface() successful\n\nNow setting cooperative level\n"; + errstream.flush(); + + if (isoView.dd->SetCooperativeLevel(isoView.m_hWnd, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK) { + errstream << "SetCooperativeLevel() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Cooperative Level could not be set! Quitting..."); + isoView.dd->Release(); + isoView.dd = NULL; + exit(-2); + + return FALSE; + } + + errstream << "SetCooperativeLevel() successful\n\nCreating primary surface\n"; + errstream.flush(); + + DDSURFACEDESC2 ddsd; + + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + ddsd.dwFlags = DDSD_CAPS; + + + + int res = 0; + int trycount = 0; + do { + res = isoView.dd->CreateSurface(&ddsd, &isoView.lpds, NULL); + errstream << "Return code: " << res << endl; + errstream.flush(); + + //if(res!=DD_OK && (res!=DDERR_PRIMARYSURFACEALREADYEXISTS || trycount>100)) + if (res != DD_OK && trycount >= 300) { + + errstream << "CreateSurface() failed\n"; + + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Primary surface could not be initialized! Quitting..."); + isoView.dd->Release(); + isoView.dd = NULL; + exit(-3); + + return FALSE; + } + trycount++; + if (res != DD_OK) { + Sleep(50); + } + + + } while (res != DD_OK); + +#ifdef NOSURFACES + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize = sizeof(DDPIXELFORMAT); + + isoView.lpds->GetPixelFormat(&pf); + + if (!pf.dwBBitMask || !pf.dwRBitMask || !pf.dwGBitMask) { + ShowWindow(SW_HIDE); + MessageBox("You must not use a palette color mode like 8 bit in order to run FinalSun/FinalAlert 2. Please check readme.txt", "Error", MB_OK); + + isoView.lpds->Release(); + isoView.lpds = NULL; + isoView.dd->Release(); + isoView.dd = NULL; + exit(-3); + return FALSE; + } + bpp = (pf.dwRGBBitCount + 7) / 8; +#endif + + + errstream << "CreateSurface() successful\n\nCreating backbuffer surface\n"; + errstream.flush(); + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + isoView.lpds->GetSurfaceDesc(&ddsd); + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + + + if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBack, NULL) != DD_OK) { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Backbuffer surface could not be initialized! Quitting..."); + isoView.lpds->Release(); + isoView.lpds = NULL; + isoView.dd->Release(); + isoView.dd = NULL; + exit(-4); + + return FALSE; + } + if (theApp.m_Options.bHighResUI && isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBackHighRes, NULL) != DD_OK) { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Highres Backbuffer surface could not be initialized! Quitting..."); + isoView.lpdsBack->Release(); + isoView.lpdsBack = NULL; + isoView.lpds->Release(); + isoView.lpds = NULL; + isoView.dd->Release(); + isoView.dd = NULL; + exit(-4); + + return FALSE; + } + if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsTemp, NULL) != DD_OK) { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Tempbuffer surface could not be initialized! Quitting..."); + isoView.lpdsBack->Release(); + isoView.lpdsBack = NULL; + if (isoView.lpdsBackHighRes) + isoView.lpdsBackHighRes->Release(); + isoView.lpdsBackHighRes = nullptr; + isoView.lpds->Release(); + isoView.lpds = NULL; + isoView.dd->Release(); + isoView.dd = NULL; + exit(-4); + + return FALSE; + } + + errstream << "CreateSurface() successful\n\nNow creating clipper\n"; + errstream.flush(); + + LPDIRECTDRAWCLIPPER ddc; + if (isoView.dd->CreateClipper(0, &ddc, NULL) != DD_OK) { + errstream << "CreateClipper() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Clipper could not be created! Quitting..."); + isoView.lpdsTemp->Release(); + isoView.lpdsTemp = NULL; + isoView.lpdsBack->Release(); + isoView.lpdsBack = NULL; + if (isoView.lpdsBackHighRes) + isoView.lpdsBackHighRes->Release(); + isoView.lpdsBackHighRes = nullptr; + isoView.lpds->Release(); + isoView.lpds = NULL; + isoView.dd->Release(); + isoView.dd = NULL; + exit(-6); + } + + errstream << "CreateClipper() successful\n\n"; + errstream.flush(); + + isoView.lpds->SetClipper(ddc); + + ddc->SetHWnd(0, isoView.m_hWnd); + + return TRUE; +} + BEGIN_MESSAGE_MAP(CIsoView, CView) //{{AFX_MSG_MAP(CIsoView) @@ -6044,11 +6256,8 @@ void CIsoView::DrawMap() } -void CIsoView::RenderUIOverlay() +std::tuple CIsoView::getDDDesc(bool recreated) { - if (!m_textDefault) - updateFontScaled(); - LPDIRECTDRAWSURFACE4 dds = lpdsBack; bool useHighRes = false; if (m_viewScale != Vec2(1.0f, 1.0f) && lpdsBackHighRes) { @@ -6063,7 +6272,27 @@ void CIsoView::RenderUIOverlay() dds->GetSurfaceDesc(&ddsd); - dds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + auto const lockRet = dds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + + if (lockRet == DDERR_SURFACELOST && !recreated) { + ReInitializeDDraw(); + return getDDDesc(true); + } + + ASSERT(lockRet == S_OK); + ASSERT(ddsd.lpSurface != nullptr); + + return { ddsd, dds, useHighRes }; +} + +void CIsoView::RenderUIOverlay() +{ + if (!m_textDefault) { + updateFontScaled(); + } + + auto const [ddsd, dds, useHighRes] = getDDDesc(false); + LineDrawer d(ddsd.lpSurface, bpp, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch); int lr, lt, ll, lb; diff --git a/MissionEditor/IsoView.h b/MissionEditor/IsoView.h index b250cf0..80e051b 100644 --- a/MissionEditor/IsoView.h +++ b/MissionEditor/IsoView.h @@ -101,6 +101,8 @@ public: CIsoView(); virtual ~CIsoView(); + BOOL RecreateSurfaces(); + // overwriteables //{{AFX_VIRTUAL(CIsoView) public: @@ -119,7 +121,7 @@ protected: virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif - + std::tuple getDDDesc(bool recreated); // generated message maps //{{AFX_MSG(CIsoView) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 8c94902..6c13504 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -3539,214 +3539,7 @@ void CLoading::CalcPicCount() BOOL CLoading::InitDirectDraw() { - last_succeeded_operation = 7; - - errstream << "\n\nDirectDrawCreate() will be called now\n"; - errstream.flush(); - - CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; - if (DirectDrawCreate(NULL, &v.dd_1, NULL) != DD_OK) { - errstream << "DirectDrawCreate() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("DirectDraw could not be initialized! Quitting..."); - exit(-1); - - return FALSE; - } - - errstream << "DirectDrawCreate() successful\n\n"; - errstream.flush(); - - errstream << "Now querying the DirectX 7 or 6 interface\n"; - errstream.flush(); - - if (v.dd_1->QueryInterface(IID_IDirectDraw7, (void**)&v.dd) != DD_OK) { - errstream << "QueryInterface() failed -> Using DirectX 6.0\n"; - errstream.flush(); - //ShowWindow(SW_HIDE); - //MessageBox("You don´t have DirectX 6.0 but an older version. Quitting..."); - //exit(-1); - - //return FALSE; - - if (v.dd_1->QueryInterface(IID_IDirectDraw4, (void**)&v.dd) != DD_OK) { - MessageBox("You need at least DirectX 6.0 to run this program", "Error"); - exit(-1); - return FALSE; - } - } - - errstream << "QueryInterface() successful\n\nNow setting cooperative level\n"; - errstream.flush(); - - if (v.dd->SetCooperativeLevel(v.m_hWnd, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK) { - errstream << "SetCooperativeLevel() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Cooperative Level could not be set! Quitting..."); - v.dd->Release(); - v.dd = NULL; - exit(-2); - - return FALSE; - } - - errstream << "SetCooperativeLevel() successful\n\nCreating primary surface\n"; - errstream.flush(); - - DDSURFACEDESC2 ddsd; - - - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - ddsd.dwFlags = DDSD_CAPS; - - - - int res = 0; - int trycount = 0; - do { - res = v.dd->CreateSurface(&ddsd, &v.lpds, NULL); - errstream << "Return code: " << res << endl; - errstream.flush(); - - //if(res!=DD_OK && (res!=DDERR_PRIMARYSURFACEALREADYEXISTS || trycount>100)) - if (res != DD_OK && trycount >= 300) { - - errstream << "CreateSurface() failed\n"; - - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Primary surface could not be initialized! Quitting..."); - v.dd->Release(); - v.dd = NULL; - exit(-3); - - return FALSE; - } - trycount++; - if (res != DD_OK) { - Sleep(50); - } - - - } while (res != DD_OK); - -#ifdef NOSURFACES - DDPIXELFORMAT pf; - memset(&pf, 0, sizeof(DDPIXELFORMAT)); - pf.dwSize = sizeof(DDPIXELFORMAT); - - v.lpds->GetPixelFormat(&pf); - - if (!pf.dwBBitMask || !pf.dwRBitMask || !pf.dwGBitMask) { - ShowWindow(SW_HIDE); - MessageBox("You must not use a palette color mode like 8 bit in order to run FinalSun/FinalAlert 2. Please check readme.txt", "Error", MB_OK); - - v.lpds->Release(); - v.lpds = NULL; - v.dd->Release(); - v.dd = NULL; - exit(-3); - return FALSE; - } - bpp = (pf.dwRGBBitCount + 7) / 8; -#endif - - - errstream << "CreateSurface() successful\n\nCreating backbuffer surface\n"; - errstream.flush(); - - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - v.lpds->GetSurfaceDesc(&ddsd); - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - - - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - - - if (v.dd->CreateSurface(&ddsd, &v.lpdsBack, NULL) != DD_OK) { - errstream << "CreateSurface() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Backbuffer surface could not be initialized! Quitting..."); - v.lpds->Release(); - v.lpds = NULL; - v.dd->Release(); - v.dd = NULL; - exit(-4); - - return FALSE; - } - if (theApp.m_Options.bHighResUI && v.dd->CreateSurface(&ddsd, &v.lpdsBackHighRes, NULL) != DD_OK) { - errstream << "CreateSurface() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Highres Backbuffer surface could not be initialized! Quitting..."); - v.lpdsBack->Release(); - v.lpdsBack = NULL; - v.lpds->Release(); - v.lpds = NULL; - v.dd->Release(); - v.dd = NULL; - exit(-4); - - return FALSE; - } - if (v.dd->CreateSurface(&ddsd, &v.lpdsTemp, NULL) != DD_OK) { - errstream << "CreateSurface() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Tempbuffer surface could not be initialized! Quitting..."); - v.lpdsBack->Release(); - v.lpdsBack = NULL; - if (v.lpdsBackHighRes) - v.lpdsBackHighRes->Release(); - v.lpdsBackHighRes = nullptr; - v.lpds->Release(); - v.lpds = NULL; - v.dd->Release(); - v.dd = NULL; - exit(-4); - - return FALSE; - } - - errstream << "CreateSurface() successful\n\nNow creating clipper\n"; - errstream.flush(); - - LPDIRECTDRAWCLIPPER ddc; - if (v.dd->CreateClipper(0, &ddc, NULL) != DD_OK) { - errstream << "CreateClipper() failed\n"; - errstream.flush(); - ShowWindow(SW_HIDE); - MessageBox("Clipper could not be created! Quitting..."); - v.lpdsTemp->Release(); - v.lpdsTemp = NULL; - v.lpdsBack->Release(); - v.lpdsBack = NULL; - if (v.lpdsBackHighRes) - v.lpdsBackHighRes->Release(); - v.lpdsBackHighRes = nullptr; - v.lpds->Release(); - v.lpds = NULL; - v.dd->Release(); - v.dd = NULL; - exit(-6); - } - - errstream << "CreateClipper() successful\n\n"; - errstream.flush(); - - v.lpds->SetClipper(ddc); - - ddc->SetHWnd(0, v.m_hWnd); - - return TRUE; + return ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RecreateSurfaces(); } void CLoading::OnPaint() @@ -3919,18 +3712,30 @@ void CLoading::FreeAll() try { CFinalSunDlg* dlg = ((CFinalSunDlg*)theApp.m_pMainWnd); - if (dlg->m_view.m_isoview->lpds != NULL) dlg->m_view.m_isoview->lpds->Release(); - dlg->m_view.m_isoview->lpds = NULL; - if (dlg->m_view.m_isoview->lpdsBack != NULL) dlg->m_view.m_isoview->lpdsBack->Release(); - dlg->m_view.m_isoview->lpdsBack = NULL; - if (dlg->m_view.m_isoview->lpdsBackHighRes != NULL) dlg->m_view.m_isoview->lpdsBackHighRes->Release(); - dlg->m_view.m_isoview->lpdsBackHighRes = NULL; - if (dlg->m_view.m_isoview->lpdsTemp != NULL) dlg->m_view.m_isoview->lpdsTemp->Release(); - dlg->m_view.m_isoview->lpdsTemp = NULL; - if (dlg->m_view.m_isoview->dd != NULL) dlg->m_view.m_isoview->dd->Release(); - dlg->m_view.m_isoview->dd = NULL; - if (dlg->m_view.m_isoview->dd_1 != NULL) dlg->m_view.m_isoview->dd_1->Release(); - dlg->m_view.m_isoview->dd_1 = NULL; + if (dlg->m_view.m_isoview->lpds != NULL) { + dlg->m_view.m_isoview->lpds->Release(); + dlg->m_view.m_isoview->lpds = NULL; + } + if (dlg->m_view.m_isoview->lpdsBack != NULL) { + dlg->m_view.m_isoview->lpdsBack->Release(); + dlg->m_view.m_isoview->lpdsBack = NULL; + } + if (dlg->m_view.m_isoview->lpdsBackHighRes != NULL) { + dlg->m_view.m_isoview->lpdsBackHighRes->Release(); + dlg->m_view.m_isoview->lpdsBackHighRes = NULL; + } + if (dlg->m_view.m_isoview->lpdsTemp != NULL) { + dlg->m_view.m_isoview->lpdsTemp->Release(); + dlg->m_view.m_isoview->lpdsTemp = NULL; + } + if (dlg->m_view.m_isoview->dd != NULL) { + dlg->m_view.m_isoview->dd->Release(); + dlg->m_view.m_isoview->dd = NULL; + } + if (dlg->m_view.m_isoview->dd_1 != NULL) { + dlg->m_view.m_isoview->dd_1->Release(); + dlg->m_view.m_isoview->dd_1 = NULL; + } } catch (...) { errstream << "Exception while freeing DirectDraw" << endl; } diff --git a/MissionEditorPackLib/MissionEditorPackLib.cpp b/MissionEditorPackLib/MissionEditorPackLib.cpp index 7065ea8..bb46786 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.cpp +++ b/MissionEditorPackLib/MissionEditorPackLib.cpp @@ -1635,6 +1635,7 @@ namespace FSunPackLib VoxelNormalTable emptyNormalTable; +#if defined(XCC_VXL_DRAW) BOOL LoadVXLImageInSurface(const VoxelNormalTables& normalTables, Vec3f lightDirection, IDirectDraw4* pdd, int iStart, int iCount, const Vec3f rotation, const Vec3f postHVAOffset, LPDIRECTDRAWSURFACE4* pdds, HTSPALETTE hPalette, int* lpXCenter, int* lpYCenter, int ZAdjust, int* lpXCenterZMax, int* lpYCenterZMax, int i3dCenterX, int i3dCenterY) { if (hPalette == NULL || hPalette > dwPalCount) return NULL; @@ -1850,6 +1851,7 @@ namespace FSunPackLib //pal.close(); return TRUE; } +#endif BOOL LoadVXLImage( const VoxelNormalTables& normalTables, diff --git a/MissionEditorPackLib/MissionEditorPackLib.h b/MissionEditorPackLib/MissionEditorPackLib.h index c80b533..3a1b2be 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.h +++ b/MissionEditorPackLib/MissionEditorPackLib.h @@ -228,7 +228,9 @@ namespace FSunPackLib BOOL GetVXLSectionInfo(int section, VoxelNormalClass& normalClass); +#if defined(XCC_VXL_DRAW) BOOL LoadVXLImageInSurface(const VoxelNormalTables& normalTables, Vec3f lightDirection, IDirectDraw4* pdd, int iStart, int iCount, Vec3f rotation, Vec3f modelOffset, LPDIRECTDRAWSURFACE4* pdds, HTSPALETTE hPalette, int* lpXCenter = NULL, int* lpYCenter = NULL, int ZAdjust = 0, int* lpXCenterZMax = NULL, int* lpYCenterZMax = NULL, int i3dCenterX = -1, int i3dCenterY = -1); +#endif // modelOffset is applied before VXL/HVA translates and scales and before model-to-world rotation BOOL LoadVXLImage(const VoxelNormalTables& normalTables,