diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp index beaac74..ebdc857 100644 --- a/MissionEditor/IsoView.cpp +++ b/MissionEditor/IsoView.cpp @@ -201,6 +201,14 @@ CIsoView::~CIsoView() bNoThreadDraw = TRUE; } +template +void releaseIfExists(TDD& surf) +{ + if (auto const pdd = std::exchange(surf, nullptr)) { + pdd->Release(); + } +} + BOOL CIsoView::RecreateSurfaces() { last_succeeded_operation = 7; @@ -209,6 +217,9 @@ BOOL CIsoView::RecreateSurfaces() errstream.flush(); CIsoView& isoView = *this; + + releaseIfExists(isoView.dd_1); + if (DirectDrawCreate(NULL, &isoView.dd_1, NULL) != DD_OK) { errstream << "DirectDrawCreate() failed\n"; errstream.flush(); @@ -225,6 +236,8 @@ BOOL CIsoView::RecreateSurfaces() errstream << "Now querying the DirectX 7 or 6 interface\n"; errstream.flush(); + releaseIfExists(isoView.dd); + if (isoView.dd_1->QueryInterface(IID_IDirectDraw7, (void**)&isoView.dd) != DD_OK) { errstream << "QueryInterface() failed -> Using DirectX 6.0\n"; errstream.flush(); @@ -267,7 +280,7 @@ BOOL CIsoView::RecreateSurfaces() ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; ddsd.dwFlags = DDSD_CAPS; - + releaseIfExists(isoView.lpds); int res = 0; int trycount = 0; @@ -332,7 +345,7 @@ BOOL CIsoView::RecreateSurfaces() ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - + releaseIfExists(isoView.lpdsBack); if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBack, NULL) != DD_OK) { errstream << "CreateSurface() failed\n"; errstream.flush(); @@ -346,6 +359,7 @@ BOOL CIsoView::RecreateSurfaces() return FALSE; } + releaseIfExists(isoView.lpdsBackHighRes); if (theApp.m_Options.bHighResUI && isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBackHighRes, NULL) != DD_OK) { errstream << "CreateSurface() failed\n"; errstream.flush(); @@ -361,6 +375,7 @@ BOOL CIsoView::RecreateSurfaces() return FALSE; } + releaseIfExists(isoView.lpdsTemp); if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsTemp, NULL) != DD_OK) { errstream << "CreateSurface() failed\n"; errstream.flush(); @@ -3541,7 +3556,10 @@ void CIsoView::ReInitializeDDraw() dlg.ShowWindow(SW_SHOW); dlg.UpdateWindow(); - dd->RestoreAllSurfaces(); + auto const hr = dd->RestoreAllSurfaces(); + if (FAILED(hr)) { + errstream << "could not restore surfaces, got hr: " << hr << std::endl; + } updateFontScaled(); diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index afe0b36..b907716 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -731,52 +731,69 @@ void CLoading::InitPics(CProgressCtrl* prog) try { auto pPic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_SCROLLCURSOR)).Detach(); // This is really dangerous to store a dangling ComPtr - pics["SCROLLCURSOR"].pic = pPic; + auto& scrollCursorSlot = pics["SCROLLCURSOR"]; + auto pOldPic = std::exchange(scrollCursorSlot.pic, pPic); + if (pOldPic) { + reinterpret_cast(pOldPic)->Release(); + } if (!pPic) { throw new BitmapNotFound(); } - FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pPic, -1); + FSunPackLib::SetColorKey(pPic, -1); ::memset(&desc, 0, sizeof(DDSURFACEDESC2)); desc.dwSize = sizeof(DDSURFACEDESC2); desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; - ((LPDIRECTDRAWSURFACE4)pPic)->GetSurfaceDesc(&desc); - pics["SCROLLCURSOR"].wHeight = desc.dwHeight; - pics["SCROLLCURSOR"].wWidth = desc.dwWidth; - pics["SCROLLCURSOR"].bType = PICDATA_TYPE_BMP; + pPic->GetSurfaceDesc(&desc); + scrollCursorSlot.wHeight = desc.dwHeight; + scrollCursorSlot.wWidth = desc.dwWidth; + scrollCursorSlot.bType = PICDATA_TYPE_BMP; } catch (const BitmapNotFound&) { + errstream << "scroll cursor BMP image not found" << std::endl; } try { - pics["CELLTAG"].pic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_CELLTAG)).Detach(); - FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic, CLR_INVALID); + auto pPic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_CELLTAG)).Detach(); + auto& cellTagSlot = pics["CELLTAG"]; + auto pOldPic = std::exchange(cellTagSlot.pic, pPic); + if (pOldPic) { + reinterpret_cast(pOldPic)->Release(); + } + FSunPackLib::SetColorKey(pPic, CLR_INVALID); ::memset(&desc, 0, sizeof(DDSURFACEDESC2)); desc.dwSize = sizeof(DDSURFACEDESC2); desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; - ((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic)->GetSurfaceDesc(&desc); - pics["CELLTAG"].wHeight = desc.dwHeight; - pics["CELLTAG"].wWidth = desc.dwWidth; + pPic->GetSurfaceDesc(&desc); + cellTagSlot.wHeight = desc.dwHeight; + cellTagSlot.wWidth = desc.dwWidth; #ifdef RA2_MODE - pics["CELLTAG"].x = -1; - pics["CELLTAG"].y = 0; + cellTagSlot.x = -1; + cellTagSlot.y = 0; #else - pics["CELLTAG"].x = -1; - pics["CELLTAG"].y = -1; + cellTagSlot.x = -1; + cellTagSlot.y = -1; #endif - pics["CELLTAG"].bType = PICDATA_TYPE_BMP; + cellTagSlot.bType = PICDATA_TYPE_BMP; } catch (const BitmapNotFound&) { + errstream << "cell tag BMP image not found" << std::endl; } try { - pics["FLAG"].pic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_FLAG)).Detach(); - FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic, -1); + auto pPic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_FLAG)).Detach(); + auto& flagSlot = pics["FLAG"]; + auto pOldPic = std::exchange(flagSlot.pic, pPic); + if (pOldPic) { + reinterpret_cast(pOldPic)->Release(); + } + FSunPackLib::SetColorKey(pPic, -1); ::memset(&desc, 0, sizeof(DDSURFACEDESC2)); desc.dwSize = sizeof(DDSURFACEDESC2); desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; - ((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic)->GetSurfaceDesc(&desc); - pics["FLAG"].wHeight = desc.dwHeight; - pics["FLAG"].wWidth = desc.dwWidth; - pics["FLAG"].bType = PICDATA_TYPE_BMP; + pPic->GetSurfaceDesc(&desc); + flagSlot.wHeight = desc.dwHeight; + flagSlot.wWidth = desc.dwWidth; + flagSlot.bType = PICDATA_TYPE_BMP; } catch (const BitmapNotFound&) { + errstream << "flag BMP image not found" << std::endl; } @@ -792,12 +809,17 @@ void CLoading::InitPics(CProgressCtrl* prog) ddsd.dwHeight = f_y; LPDIRECTDRAWSURFACE4 srf = NULL; + //auto ddptr = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd->CreateSurface(&ddsd, &srf, 0); - pics["HTILE"].pic = srf; - pics["HTILE"].wHeight = ddsd.dwHeight; - pics["HTILE"].wWidth = ddsd.dwWidth; - pics["HTILE"].bType = PICDATA_TYPE_BMP; + auto& htileSlot = pics["HTILE"]; + auto const pOldHtSurf = reinterpret_cast(std::exchange(htileSlot.pic, srf)); + if (pOldHtSurf) { + pOldHtSurf->Release(); + } + htileSlot.wHeight = ddsd.dwHeight; + htileSlot.wWidth = ddsd.dwWidth; + htileSlot.bType = PICDATA_TYPE_BMP; HDC hDC; srf->GetDC(&hDC); @@ -834,7 +856,6 @@ void CLoading::InitPics(CProgressCtrl* prog) // new: Prepare building terrain information: for (auto const& [seq, id] : rules.GetSection("BuildingTypes")) { PrepareUnitGraphic(id); - } ms.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatusEx(&ms); @@ -4149,69 +4170,65 @@ void CLoading::PrepareUnitGraphic(const CString& lpUnittype) const auto& artSection = art[image]; // is it a shp graphic? - if (!artSection.GetBool("Voxel")) { - try { - auto shp = FindUnitShp(image, cur_theat, artSection); - if (!shp) { - return; - } - - filename = shp->filename; - hPalette = shp->palette; - - auto limited_to_theater = artSection.GetBool("TerrainPalette") ? shp->mixfile_theater : TheaterChar::None; - - if (filename == "tibtre01.tem" || filename == "tibtre02.tem" || filename == "tibtre03.tem" || filename == "veinhole.tem") { - hPalette = m_palettes.m_hPalUnitTemp; - } - - if (shp->mixfile > 0) { - - BOOL bSuccess = FSunPackLib::SetCurrentSHP(filename, shp->mixfile); - if (!bSuccess) { - filename = image + ".sno"; - if (cur_theat == 'T' || cur_theat == 'U') hPalette = m_palettes.m_hPalIsoTemp; - HMIXFILE hShpMix = FindFileInMix(filename); - bSuccess = FSunPackLib::SetCurrentSHP(filename, hShpMix); - - if (!bSuccess) { - return; - } - } - - if (bSuccess) { - - - char ic[50]; - int i = 0; - itoa(i, ic, 10); - - // just fill in a stub entry - Final* will automatically retry loading once the graphic really must be loaded - PICDATA p; - p.pic = NULL; - p.x = 0; - p.y = 0; - p.wHeight = 0; - p.wWidth = 0; - p.wMaxWidth = 0; - p.wMaxHeight = 0; - p.bType = PICDATA_TYPE_SHP; - p.bTerrain = limited_to_theater; - - - pics[image + ic] = p; - - - } - - } - - } catch (...) { - errstream << " exception " << endl; - errstream.flush(); + if (artSection.GetBool("Voxel")) { + return; + } + try { + auto shp = FindUnitShp(image, cur_theat, artSection); + if (!shp) { + return; } + filename = shp->filename; + hPalette = shp->palette; + auto limited_to_theater = artSection.GetBool("TerrainPalette") ? shp->mixfile_theater : TheaterChar::None; + + if (filename == "tibtre01.tem" || filename == "tibtre02.tem" || filename == "tibtre03.tem" || filename == "veinhole.tem") { + hPalette = m_palettes.m_hPalUnitTemp; + } + + if (shp->mixfile == NULL) { + return; + } + + BOOL bSuccess = FSunPackLib::SetCurrentSHP(filename, shp->mixfile); + if (!bSuccess) { + filename = image + ".sno"; + if (cur_theat == 'T' || cur_theat == 'U') hPalette = m_palettes.m_hPalIsoTemp; + HMIXFILE hShpMix = FindFileInMix(filename); + bSuccess = FSunPackLib::SetCurrentSHP(filename, hShpMix); + + if (!bSuccess) { + return; + } + } + + if (bSuccess) { + char ic[50]; + int i = 0; + itoa(i, ic, 10); + + // just fill in a stub entry - Final* will automatically retry loading once the graphic really must be loaded + PICDATA p; + p.pic = NULL; + p.x = 0; + p.y = 0; + p.wHeight = 0; + p.wWidth = 0; + p.wMaxWidth = 0; + p.wMaxHeight = 0; + p.bType = PICDATA_TYPE_SHP; + p.bTerrain = limited_to_theater; + + auto const oldPicData = std::exchange(pics[image + ic], p); + if (oldPicData.pic) { + delete oldPicData.pic; + } + } + } + catch (...) { + errstream << " exception " << endl; + errstream.flush(); } - } \ No newline at end of file