///////////////////////////////////////////////////////////// // // CProxyDirect3DIndexBuffer::Lock // // For stats // ///////////////////////////////////////////////////////////// HRESULT CProxyDirect3DIndexBuffer::Lock(UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) { m_stats.iLockedCount++; *ppbData = NULL; HRESULT hr = m_pOriginal->Lock(OffsetToLock, SizeToLock, ppbData, Flags); if (FAILED(hr)) { SString strMessage("Lock IndexBuffer fail: hr:%x Length:%x Usage:%x Format:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x", hr, m_iMemUsed, m_dwUsage, m_format, m_pool, OffsetToLock, SizeToLock, Flags); WriteDebugEvent(strMessage); AddReportLog(8625, strMessage); CCore::GetSingleton().LogEvent(625, "Lock IndexBuffer", "", strMessage); } else if (*ppbData == NULL) { SString strMessage("Lock IndexBuffer result NULL: hr:%x Length:%x Usage:%x Format:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x", hr, m_iMemUsed, m_dwUsage, m_format, m_pool, OffsetToLock, SizeToLock, Flags); WriteDebugEvent(strMessage); AddReportLog(8626, strMessage); CCore::GetSingleton().LogEvent(626, "Lock IndexBuffer NULL", "", strMessage); } return hr; }
///////////////////////////////////////////////////////////// // // CProxyDirect3DVertexBuffer::Lock // // If lock is writable, tell manager that range content will change // ///////////////////////////////////////////////////////////// HRESULT CProxyDirect3DVertexBuffer::Lock ( UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags ) { m_stats.iLockedCount++; if ( ( Flags & D3DLOCK_READONLY ) == 0 ) { CAdditionalVertexStreamManager::GetSingleton ()->OnVertexBufferRangeInvalidated ( m_pOriginal, OffsetToLock, SizeToLock ); CVertexStreamBoundingBoxManager::GetSingleton ()->OnVertexBufferRangeInvalidated ( m_pOriginal, OffsetToLock, SizeToLock ); } *ppbData = NULL; HRESULT hr = m_pOriginal->Lock ( OffsetToLock, SizeToLock, ppbData, Flags ); if( FAILED( hr ) ) { SString strMessage( "Lock VertexBuffer fail: hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x" , hr, m_iMemUsed, m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags ); WriteDebugEvent( strMessage ); AddReportLog( 8620, strMessage ); CCore::GetSingleton ().LogEvent ( 620, "Lock VertexBuffer", "", strMessage ); } else if ( *ppbData == NULL ) { SString strMessage( "Lock VertexBuffer result NULL: hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x" , hr, m_iMemUsed, m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags ); WriteDebugEvent( strMessage ); AddReportLog( 8621, strMessage ); CCore::GetSingleton ().LogEvent ( 621, "Lock VertexBuffer NULL", "", strMessage ); } return hr; }
//////////////////////////////////////////////////// // // CNewsBrowser::LoadLayoutAndImages // // // //////////////////////////////////////////////////// CGUIWindow* CNewsBrowser::LoadLayoutAndImages(CGUIElement* pParent, const SNewsItem& newsItem) { CGUI* pManager = g_pCore->GetGUI(); // Make sure we have the layout filename if (newsItem.strLayoutFilename.empty()) { AddReportLog(3302, SString("CNewsBrowser::LoadLayout: Problem loading %s", *newsItem.strContentFullDir)); return NULL; } // Load any imagesets for (uint i = 0; i < newsItem.imagesetFilenameList.size(); i++) { if (!pManager->LoadImageset(newsItem.imagesetFilenameList[i])) { AddReportLog( 3303, SString("CNewsBrowser::LoadLayout: Problem with LoadImageset [%s] %s", *newsItem.strContentFullDir, *newsItem.imagesetFilenameList[i])); return NULL; } } // Load layout CGUIWindow* pWindow = pManager->LoadLayout(pParent, newsItem.strLayoutFilename); if (!pWindow) { AddReportLog(3304, SString("CNewsBrowser::LoadLayout: Problem with LoadLayout [%s] %s", *newsItem.strContentFullDir, *newsItem.strLayoutFilename)); return NULL; } return pWindow; }
////////////////////////////////////////////////////////// // // CInstallManager::_InstallNewsItems // // // ////////////////////////////////////////////////////////// SString CInstallManager::_InstallNewsItems ( void ) { // Get install news queue CArgMap queue; queue.SetFromString ( GetApplicationSetting ( "news-install" ) ); SetApplicationSetting ( "news-install", "" ); std::vector < SString > keyList; queue.GetKeys ( keyList ); for ( uint i = 0 ; i < keyList.size () ; i++ ) { // Install each file SString strDate = keyList[i]; SString strFileLocation = queue.Get ( strDate ); // Save cwd SString strSavedDir = GetSystemCurrentDirectory (); // Calc and make target dir SString strTargetDir = PathJoin ( GetMTADataPath (), "news", strDate ); MkDir ( strTargetDir ); // Extract into target dir SetCurrentDirectory ( strTargetDir ); // Try to extract the files if ( !ExtractFiles ( strFileLocation ) ) { // If extract failed and update file is an exe, try to run it if ( ExtractExtension ( strFileLocation ).CompareI ( "exe" ) ) ShellExecuteBlocking ( "open", strFileLocation, "-s" ); } // Restore cwd SetCurrentDirectory ( strSavedDir ); // Check result if ( FileExists ( PathJoin ( strTargetDir, "files.xml" ) ) ) { SetApplicationSettingInt ( "news-updated", 1 ); AddReportLog ( 2051, SString ( "InstallNewsItems ok for '%s'", *strDate ) ); } else { AddReportLog ( 4048, SString ( "InstallNewsItems failed with '%s' '%s' '%s'", *strDate, *strFileLocation, *strTargetDir ) ); } } return "ok"; }
///////////////////////////////////////////////////////////// // // CDirect3DEvents9::CreateTexture // // // ///////////////////////////////////////////////////////////// HRESULT CDirect3DEvents9::CreateTexture ( IDirect3DDevice9 *pDevice, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle ) { HRESULT hr; for ( uint i = 0 ; i < 2 ; i++ ) { hr = pDevice->CreateTexture ( Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle ); if( SUCCEEDED( hr ) ) break; if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 ) { SString strMessage( "CreateTexture fail: hr:%x W:%x H:%x L:%x Usage:%x Format:%x Pool:%x", hr, Width, Height, Levels, Usage, Format, Pool ); WriteDebugEvent( strMessage ); AddReportLog( 8612, strMessage ); CCore::GetSingleton ().LogEvent ( 612, "CreateTexture", "", strMessage ); return hr; } pDevice->EvictManagedResources (); } // Create proxy so we can track when it's finished with *ppTexture = new CProxyDirect3DTexture ( pDevice, *ppTexture, Width, Height, Levels, Usage, Format, Pool ); return hr; }
///////////////////////////////////////////////////////////// // // CDirect3DEvents9::CreateIndexBuffer // // // ///////////////////////////////////////////////////////////// HRESULT CDirect3DEvents9::CreateIndexBuffer ( IDirect3DDevice9 *pDevice, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle ) { HRESULT hr; for ( uint i = 0 ; i < 2 ; i++ ) { hr = pDevice->CreateIndexBuffer ( Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle ); if( SUCCEEDED( hr ) ) break; if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 ) { SString strMessage( "CreateIndexBuffer fail: hr:%x Length:%x Usage:%x Format:%x Pool:%x", hr, Length, Usage, Format, Pool ); WriteDebugEvent( strMessage ); AddReportLog( 8611, strMessage ); CCore::GetSingleton ().LogEvent ( 611, "CreateIndexBuffer", "", strMessage ); return hr; } pDevice->EvictManagedResources (); } // Create proxy so we can track when it's finished with *ppIndexBuffer = new CProxyDirect3DIndexBuffer ( pDevice, *ppIndexBuffer, Length, Usage, Format, Pool ); return hr; }
///////////////////////////////////////////////////////////// // // CDirect3DEvents9::CreateVertexBuffer // // Creates a proxy object for the new vertex buffer // ///////////////////////////////////////////////////////////// HRESULT CDirect3DEvents9::CreateVertexBuffer ( IDirect3DDevice9 *pDevice, UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle ) { HRESULT hr; // We may have to look at the contents to generate normals (Not needed for dynamic buffers) if ( ( Usage & D3DUSAGE_DYNAMIC ) == 0 ) Usage &= -1 - D3DUSAGE_WRITEONLY; for ( uint i = 0 ; i < 2 ; i++ ) { hr = pDevice->CreateVertexBuffer ( Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle ); if( SUCCEEDED( hr ) ) break; if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 ) { SString strMessage( "CreateVertexBuffer fail: hr:%x Length:%x Usage:%x FVF:%x Pool:%x", hr, Length, Usage, FVF, Pool ); WriteDebugEvent( strMessage ); AddReportLog( 8610, strMessage ); CCore::GetSingleton ().LogEvent ( 610, "CreateVertexBuffer", "", strMessage ); return hr; } pDevice->EvictManagedResources (); } // Create proxy *ppVertexBuffer = new CProxyDirect3DVertexBuffer ( pDevice, *ppVertexBuffer, Length, Usage, FVF, Pool ); return hr; }
////////////////////////////////////////////////////////////// // // Check if any clumps have become unused outside of the cache // ////////////////////////////////////////////////////////////// uint GetNumCached ( void ) { uint uiNumCached = 0; for ( std::vector < SSavedClumpInfo >::iterator iter = savedClumpList.begin () ; iter != savedClumpList.end () ; ++iter ) { SSavedClumpInfo& info = *iter; RpGeometry* pGeometry = ( ( RpAtomic* ) ( ( info.pClump->atomics.root.next ) - 0x8 ) )->geometry; #ifdef CLOTHES_REF_TEST if ( pGeometry->refs < 21 ) { AddReportLog( 7521, SString ( "Clothes geometry refs below expected value: %d", pGeometry->refs ) ); pGeometry->refs = 21; } if ( pGeometry->refs == 21 ) #else if ( pGeometry->refs == 1 ) #endif { uiNumCached++; if ( !info.bUnused ) { info.timeUnused = CTickCount::Now (); info.bUnused = true; } } else info.bUnused = false; } m_Stats.uiNumTotal = savedClumpList.size (); m_Stats.uiNumUnused = uiNumCached; return uiNumCached; }
////////////////////////////////////////////////////////// // // CInstallManager::GetLauncherPathFilename // // Get path to launch exe // ////////////////////////////////////////////////////////// SString CInstallManager::GetLauncherPathFilename ( void ) { SString strLocation = m_pSequencer->GetVariable ( INSTALL_LOCATION ); SString strResult = PathJoin ( strLocation == "far" ? GetSystemCurrentDirectory () : GetMTASAPath (), MTA_EXE_NAME ); AddReportLog ( 1062, SString ( "GetLauncherPathFilename %s", *strResult ) ); return strResult; }
////////////////////////////////////////////////////////// // // CInstallManager::RestoreSequencerFromSnapshot // // Set current sequencer position from a string // ////////////////////////////////////////////////////////// void CInstallManager::RestoreSequencerFromSnapshot ( const SString& strText ) { AddReportLog ( 1061, SString ( "CInstallManager::RestoreSequencerState %s", *strText ) ); std::vector < SString > parts; strText.Split ( " ", parts ); int iFirstArg = 0; if ( parts.size () > 0 && parts[0].Contains ( "=" ) ) { // Upgrade variables if ( parts[0].Contains ( INSTALL_STAGE ) && !parts[0].Contains ( "_pc_label" ) ) parts[0] = parts[0].Replace ( INSTALL_STAGE, "_pc_label" ); m_pSequencer->RestoreStateFromString ( parts[0] ); iFirstArg++; } // Add any extra command line args if ( m_pSequencer->GetVariableInt ( "_argc" ) == 0 ) { m_pSequencer->SetVariable ( "_argc", parts.size () - iFirstArg ); for ( uint i = iFirstArg ; i < parts.size () ; i++ ) { m_pSequencer->SetVariable ( SString ( "_arg_%d", i - iFirstArg ), parts[i] ); } } // Ignore LastResult m_pSequencer->SetVariable ( "LastResult", "ok" ); }
//////////////////////////////////////////////// // // CreateDeviceSecondCallCheck // // Check for, and handle subsequent calls to create device // Know to occur with RTSSHooks.dll (EVGA Precision X on screen display) // //////////////////////////////////////////////// bool CreateDeviceSecondCallCheck(HRESULT& hOutResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) { static uint uiCreateCount = 0; // Also check for invalid size if (pPresentationParameters->BackBufferWidth == 0) { WriteDebugEvent(SString(" Passing through call #%d to CreateDevice because size is invalid", uiCreateCount)); return true; } // Also check for calls from other threads if (!IsMainThread()) { SString strMessage(" Passing through call #%d to CreateDevice because not main thread", uiCreateCount); WriteDebugEvent(strMessage); AddReportLog(8627, strMessage); return true; } if (++uiCreateCount == 1) return false; WriteDebugEvent(SString(" Passing through call #%d to CreateDevice", uiCreateCount)); hOutResult = pDirect3D->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); return true; }
/////////////////////////////////////////////////////////////// // // CCrashDumpWriter::UpdateCounters // // Static function. Called every so often, you know // /////////////////////////////////////////////////////////////// void CCrashDumpWriter::UpdateCounters( void ) { if ( ms_uiInvalidParameterCount > ms_uiInvalidParameterCountLogged && ms_uiInvalidParameterCountLogged < 10 ) { AddReportLog( 9206, SString( "InvalidParameterCount changed from %d to %d", ms_uiInvalidParameterCountLogged, ms_uiInvalidParameterCount ) ); ms_uiInvalidParameterCountLogged = ms_uiInvalidParameterCount; } }
////////////////////////////////////////////////////////// // // CheckOnRestartCommand // // Changes current directory if required // ////////////////////////////////////////////////////////// SString CheckOnRestartCommand ( void ) { const SString strMTASAPath = GetMTASAPath (); SetCurrentDirectory ( strMTASAPath ); SetDllDirectory( strMTASAPath ); SString strOperation, strFile, strParameters, strDirectory, strShowCmd; if ( GetOnRestartCommand ( strOperation, strFile, strParameters, strDirectory, strShowCmd ) ) { if ( strOperation == "files" || strOperation == "silent" ) { // // Update // // Make temp path name and go there SString strArchivePath, strArchiveName; strFile.Split ( "\\", &strArchivePath, &strArchiveName, -1 ); SString strTempPath = MakeUniquePath ( strArchivePath + "\\_" + strArchiveName + "_tmp_" ); if ( !MkDir ( strTempPath ) ) return "FileError1"; if ( !SetCurrentDirectory ( strTempPath ) ) return "FileError2"; // Start progress bar if ( !strParameters.Contains( "hideprogress" ) ) StartPseudoProgress( g_hInstance, "MTA: San Andreas", _("Extracting files...") ); // Try to extract the files if ( !ExtractFiles ( strFile ) ) { // If extract failed and update file is an exe, try to run it if ( ExtractExtension ( strFile ).CompareI ( "exe" ) ) ShellExecuteBlocking ( "open", strFile, "-s" ); } // Stop progress bar StopPseudoProgress(); // If a new "Multi Theft Auto.exe" exists, let that complete the install if ( FileExists ( MTA_EXE_NAME_RELEASE ) ) return "install from far " + strOperation + " " + strParameters; // Otherwise use the current exe to install return "install from near " + strOperation + " " + strParameters; } else { AddReportLog ( 5052, SString ( "CheckOnRestartCommand: Unknown restart command %s", strOperation.c_str () ) ); } } return "no update"; }
/////////////////////////////////////////////////////////////// // // CGameEntityXRefManagerImpl::OnGameEntityDestruct // // Called when GTA is destroying a game entity // /////////////////////////////////////////////////////////////// void CGameEntityXRefManagerImpl::OnGameEntityDestruct ( CEntitySAInterface* pEntitySAInterface ) { if ( MapContains ( m_InterfaceToClientMap, pEntitySAInterface ) ) { BYTE* pInterface = (BYTE*)pEntitySAInterface; DWORD InterfaceVtbl = *(DWORD*)pInterface; ushort InterfaceModelId = *(ushort*)(pInterface + 34); CClientEntity* pClientEntity = MapFindRef ( m_InterfaceToClientMap, pEntitySAInterface ); bool bClientEntityValid = MapContains ( m_ValidClientEntityMap, pClientEntity ); SString strClientEntityInfo; if ( bClientEntityValid ) { CEntity* pGameEntity = NULL; if ( CClientPed* pPed = DynamicCast < CClientPed > ( pClientEntity ) ) pGameEntity = pPed->GetGameEntity (); if ( CClientVehicle* pVehicle = DynamicCast < CClientVehicle > ( pClientEntity ) ) pGameEntity = pVehicle->GetGameEntity (); if ( CClientObject* pObject = DynamicCast < CClientObject > ( pClientEntity ) ) pGameEntity = pObject->GetGameEntity (); if ( CClientProjectile* pProjectile = DynamicCast < CClientProjectile > ( pClientEntity ) ) pGameEntity = pProjectile->GetGameEntity (); if ( CClientPickup* pPickup = DynamicCast < CClientPickup > ( pClientEntity ) ) pGameEntity = pPickup->GetGameObject (); CEntity* pMappedGameEntity = MapFindRef ( m_ClientToGameMap, pClientEntity ); CClientEntity* pMappedClientEntity = MapFindRef ( m_GameToClientMap, pGameEntity ); strClientEntityInfo = SString ( "%s Id:%x GameEntity:%08x MappedGameEntity:%08x MappedClientEntity:%08x" , pClientEntity->GetClassName () , pClientEntity->GetID () , (int)pGameEntity , (int)pMappedGameEntity , (int)pMappedClientEntity ); } SString strMessage ( "EntitySAInterface:%08x Vtbl:%08x ModelId:%d ClientEntity:%08x [%s]" , (int)pEntitySAInterface , InterfaceVtbl , InterfaceModelId , (int)pClientEntity , *strClientEntityInfo ); g_pCore->LogEvent ( 8542, "XRefManager", "GameEntity Mismatch", strMessage ); AddReportLog ( 8542, strMessage ); dassert ( 0 ); } }
////////////////////////////////////////////////////////// // // CInstallManager::_ChangeFromAdmin // // Save the state of the sequencer and exit back to the user process // ////////////////////////////////////////////////////////// SString CInstallManager::_ChangeFromAdmin ( void ) { if ( IsUserAdmin () && IsBlockingUserProcess () ) { SendStringToUserProcess ( GetSequencerSnapshot () ); AddReportLog ( 1003, SString ( "CInstallManager::_ChangeToAdmin - exit(0) %s", "" ) ); ClearIsBlockingUserProcess (); ExitProcess ( 0 ); } return "fail"; }
////////////////////////////////////////////////////////// // // HandleResetSettings // // // ////////////////////////////////////////////////////////// void HandleResetSettings ( void ) { if ( CheckAndShowFileOpenFailureMessage () ) return; CheckAndShowMissingFileMessage(); SString strSaveFilePath = PathJoin ( GetSystemPersonalPath(), "GTA San Andreas User Files" ); SString strSettingsFilename = PathJoin ( strSaveFilePath, "gta_sa.set" ); SString strSettingsFilenameBak = PathJoin ( strSaveFilePath, "gta_sa_old.set" ); if ( FileExists ( strSettingsFilename ) ) { int iResponse = MessageBoxUTF8 ( NULL, _("There seems to be a problem launching MTA:SA.\nResetting GTA settings can sometimes fix this problem.\n\nDo you want to reset GTA settings now?"), "MTA: San Andreas"+_E("CL08"), MB_YESNO | MB_ICONQUESTION | MB_TOPMOST ); if ( iResponse == IDYES ) { FileDelete ( strSettingsFilenameBak ); FileRename ( strSettingsFilename, strSettingsFilenameBak ); FileDelete ( strSettingsFilename ); if ( !FileExists ( strSettingsFilename ) ) { AddReportLog ( 4053, "Deleted gta_sa.set" ); MessageBoxUTF8 ( NULL, _("GTA settings have been reset.\n\nPress OK to continue."), "MTA: San Andreas", MB_OK | MB_ICONINFORMATION | MB_TOPMOST ); } else { AddReportLog ( 5054, SString ( "Delete gta_sa.set failed with '%s'", *strSettingsFilename ) ); MessageBoxUTF8 ( NULL, SString ( _("File could not be deleted: '%s'"), *strSettingsFilename ), "Error"+_E("CL09"), MB_OK | MB_ICONWARNING | MB_TOPMOST ); } } } else { // No settings to delete, or can't find them int iResponse = MessageBoxUTF8 ( NULL, _("Are you having problems running MTA:SA?.\n\nDo you want to see some online help?"), "MTA: San Andreas", MB_YESNO | MB_ICONQUESTION | MB_TOPMOST ); if ( iResponse == IDYES ) { BrowseToSolution ( "crashing-before-gtalaunch", TERMINATE_PROCESS ); } } }
int WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, PVOID pvNothing) { CFilePathTranslator FileTranslator; std::string WorkingDirectory; if ( dwReason == DLL_PROCESS_ATTACH ) { WriteDebugEvent( SString( "DLL_PROCESS_ATTACH %08x", pvNothing ) ); if ( IsGTAProcess() ) { WriteDebugEvent( SString( "ModuleFileName: %s", *GetLaunchPathFilename() ) ); AddUtf8FileHooks(); // Set low frag heap for XP ULONG heapInfo = 2 ; HeapSetInformation( GetProcessHeap(), HeapCompatibilityInformation, &heapInfo, sizeof( heapInfo ) ); FileTranslator.GetGTARootDirectory ( WorkingDirectory ); SetCurrentDirectory ( WorkingDirectory.c_str ( ) ); // For dll searches, this call replaces the current directory entry and turns off 'SafeDllSearchMode' // Meaning it will search the supplied path before the system and windows directory. // http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx SetDllDirectory( CalcMTASAPath ( "MTA" ) ); g_pCore = new CCore; FileTranslator.GetGTARootDirectory ( WorkingDirectory ); SetCurrentDirectory ( WorkingDirectory.c_str ( ) ); } } else if (dwReason == DLL_PROCESS_DETACH) { WriteDebugEvent( SString( "DLL_PROCESS_DETACH %08x", pvNothing ) ); if ( IsGTAProcess () ) { RemoveUtf8FileHooks(); AddReportLog( 7102, "Core - PROCESS_DETACH" ); // For now, TerminateProcess if any destruction is attempted (or we'll crash) TerminateProcess ( GetCurrentProcess (), 0 ); if ( g_pCore ) { delete g_pCore; g_pCore = NULL; } } } return TRUE; }
//////////////////////////////////////////////////////////////// // // CRenderWareSA::OnDestroyTexInfo // // // //////////////////////////////////////////////////////////////// void CRenderWareSA::OnDestroyTexInfo ( STexInfo* pTexInfo ) { // Remove from lookup maps SString strUniqueKey ( "%d_%s", pTexInfo->usTxdId, *pTexInfo->strTextureName ); if ( !MapContains ( m_UniqueTexInfoMap, strUniqueKey ) ) AddReportLog ( 5133, SString ( "OnDestroyTexInfo missing %s", *strUniqueKey ) ); MapRemove ( m_UniqueTexInfoMap, strUniqueKey ); // This assert fails when using engine txd replace functions - TODO find out why //assert ( MapContains ( m_D3DDataTexInfoMap, pTexInfo->pD3DData ) ); MapRemove ( m_D3DDataTexInfoMap, pTexInfo->pD3DData ); }
void CCrashDumpWriter::RunErrorTool ( CExceptionInformation* pExceptionInformation ) { // MTA Error Reporter is now integrated into the launcher // Only do once static bool bDoneReport = false; if ( bDoneReport ) return; bDoneReport = false; // Log the basic exception information SString strMessage ( "Crash 0x%08X 0x%08X %s" " EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X" " EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X" " CS=%04X DS=%04X SS=%04X ES=%04X" " FS=%04X GS=%04X", pExceptionInformation->GetCode (), pExceptionInformation->GetAddressModuleOffset (), pExceptionInformation->GetModulePathName (), pExceptionInformation->GetEAX (), pExceptionInformation->GetEBX (), pExceptionInformation->GetECX (), pExceptionInformation->GetEDX (), pExceptionInformation->GetESI (), pExceptionInformation->GetEDI (), pExceptionInformation->GetEBP (), pExceptionInformation->GetESP (), pExceptionInformation->GetEIP (), pExceptionInformation->GetEFlags (), pExceptionInformation->GetCS (), pExceptionInformation->GetDS (), pExceptionInformation->GetSS (), pExceptionInformation->GetES (), pExceptionInformation->GetFS (), pExceptionInformation->GetGS () ); AddReportLog ( 3120, strMessage ); // Try relaunch with crashed flag SString strMTASAPath = GetMTASABaseDir (); SetCurrentDirectory ( strMTASAPath ); SetDllDirectory( strMTASAPath ); #ifdef MTA_DEBUG #define MTA_EXE_NAME "Multi Theft Auto_d.exe" #else #define MTA_EXE_NAME "Multi Theft Auto.exe" #endif SString strFile = strMTASAPath + "\\" + MTA_EXE_NAME; ShellExecute( NULL, "open", strFile, "install_stage=crashed", NULL, SW_SHOWNORMAL ); }
////////////////////////////////////////////////////////// // // CInstallManager::Continue // // Process next step // ////////////////////////////////////////////////////////// SString CInstallManager::Continue ( void ) { // Initial report line DWORD dwProcessId = GetCurrentProcessId(); SString GotPathFrom = ( m_pSequencer->GetVariable ( INSTALL_LOCATION ) == "far" ) ? "registry" : "module location"; AddReportLog ( 1041, SString ( "* Launch * pid:%d '%s' MTASAPath set from %s '%s'", dwProcessId, GetMTASAModuleFileName ().c_str (), GotPathFrom.c_str (), GetMTASAPath ().c_str () ) ); // Run sequencer for ( int i = 0 ; !m_pSequencer->AtEnd () && i < 1000 ; i++ ) m_pSequencer->ProcessNextLine (); // Remove unwanted files CleanDownloadCache (); // Extract command line launch args SString strCommandLineOut; for ( int i = 0 ; i < m_pSequencer->GetVariableInt ( "_argc" ) ; i++ ) strCommandLineOut += m_pSequencer->GetVariable ( SString ( "_arg_%d", i ) ) + " "; AddReportLog ( 1060, SString ( "CInstallManager::Continue - return %s", *strCommandLineOut ) ); return *strCommandLineOut.TrimEnd ( " " ); }
////////////////////////////////////////////////////////// // // CInstallManager::_InstallFiles // // // ////////////////////////////////////////////////////////// SString CInstallManager::_InstallFiles ( void ) { WatchDogReset (); // Install new files if ( !InstallFiles ( m_pSequencer->GetVariable ( SILENT_OPT ) != "no" ) ) { if ( !IsUserAdmin () ) AddReportLog ( 3048, SString ( "_InstallFiles: Install - trying as admin %s", "" ) ); else AddReportLog ( 5049, SString ( "_InstallFiles: Couldn't install files %s", "" ) ); m_strAdminReason = _("Install updated MTA:SA files"); return "fail"; } else { UpdateMTAVersionApplicationSetting (); AddReportLog ( 2050, SString ( "_InstallFiles: ok %s", "" ) ); return "ok"; } }
////////////////////////////////////////////////////////// // // HandleNotUsedMainMenu // // Called when a problem occured before the main menu was used by user // If fullscreen, then maybe change fullscreen mode // ////////////////////////////////////////////////////////// void HandleNotUsedMainMenu ( void ) { AddReportLog( 9310, "Loader - HandleNotUsedMainMenu" ); { // Slighty hacky way of checking in-game settings SString strCoreConfigFilename = CalcMTASAPath( PathJoin( "mta", "config", "coreconfig.xml" ) ); SString strCoreConfig; FileLoad( strCoreConfigFilename, strCoreConfig ); SString strWindowed = strCoreConfig.SplitRight( "<display_windowed>" ).Left( 1 ); SString strFullscreenStyle = strCoreConfig.SplitRight( "<display_fullscreen_style>" ).Left( 1 ); if ( strFullscreenStyle == "1" ) { AddReportLog( 9315, "Loader - HandleNotUsedMainMenu - Already Borderless window" ); } else if ( !strWindowed.empty() && !strFullscreenStyle.empty()) { if ( strWindowed == "0" && strFullscreenStyle == "0" ) // 0=FULLSCREEN_STANDARD { // Inform user SString strMessage = _("Are you having problems running MTA:SA?.\n\nDo you want to change the following setting?"); strMessage += "\n" + _("Fullscreen mode:") + " -> " + _("Borderless window"); HideSplash(); int iResponse = MessageBoxUTF8 ( NULL, strMessage, "MTA: San Andreas", MB_YESNO | MB_ICONQUESTION | MB_TOPMOST ); if ( iResponse == IDYES ) { // Very hacky way of changing in-game settings strCoreConfig = strCoreConfig.Replace( "<display_fullscreen_style>0", "<display_fullscreen_style>1" ); FileSave( strCoreConfigFilename, strCoreConfig ); AddReportLog( 9311, "Loader - HandleNotUsedMainMenu - User change to Borderless window" ); } else AddReportLog( 9313, "Loader - HandleNotUsedMainMenu - User said no" ); } else AddReportLog( 9314, "Loader - HandleNotUsedMainMenu - Mode not fullscreen standard" ); } else { // If no valid settings file yet, do the change without asking strCoreConfig = "<mainconfig><settings><display_fullscreen_style>1</display_fullscreen_style></settings></mainconfig>"; FileSave( strCoreConfigFilename, strCoreConfig ); AddReportLog( 9312, "Loader - HandleNotUsedMainMenu - Set Borderless window" ); } } // Check if Evolve is active for ( auto processId : MyEnumProcesses( true ) ) { SString strFilename = ExtractFilename( GetProcessPathFilename( processId ) ); if ( strFilename.BeginsWithI( "Evolve" ) ) { SString strMessage = _("Are you having problems running MTA:SA?.\n\nTry disabling the following products for GTA and MTA:"); strMessage += "\n\nEvolve"; DisplayErrorMessageBox ( strMessage, _E("CL43"), "not-used-menu-evolve" ); break; } } }
/////////////////////////////////////////////////////////////// // // CResourceFileDownloadManager::DoPulse // // Downloading initial resource files // /////////////////////////////////////////////////////////////// void CResourceFileDownloadManager::DoPulse() { if (!g_pNet->IsConnected()) return; if (!IsTransferringInitialFiles()) return; // Pulse the http downloads uint uiDownloadSizeTotal = 0; for (auto serverInfo : m_HttpServerList) { CNetHTTPDownloadManagerInterface* pHTTP = g_pNet->GetHTTPDownloadManager(serverInfo.downloadChannel); pHTTP->ProcessQueuedFiles(); uiDownloadSizeTotal += pHTTP->GetDownloadSizeNow(); } // Handle fatal error if (!m_strLastHTTPError.empty()) { // Throw the error and disconnect g_pCore->GetConsole()->Printf(_("Download error: %s"), *m_strLastHTTPError); AddReportLog(7106, SString("Game - HTTPError (%s)", *m_strLastHTTPError)); g_pCore->GetModManager()->RequestUnload(); g_pCore->ShowMessageBox(_("Error") + _E("CD20"), *m_strLastHTTPError, MB_BUTTON_OK | MB_ICON_ERROR); // HTTP Error m_bIsTransferingFiles = false; return; } // Update progress box GetTransferBox()->SetInfo(uiDownloadSizeTotal); GetTransferBox()->DoPulse(); // Check if completed downloading current group if (m_ActiveFileDownloadList.empty()) { // Hide progress box if all groups done if (m_PendingFileDownloadList.empty()) { m_bIsTransferingFiles = false; GetTransferBox()->Hide(); } // Load our newly ready resources g_pClientGame->GetResourceManager()->OnDownloadGroupFinished(); UpdatePendingDownloads(); } }
//////////////////////////////////////////////////////////////// // // CRenderWareSA::CreateTexInfo // // // //////////////////////////////////////////////////////////////// STexInfo* CRenderWareSA::CreateTexInfo ( ushort usTxdId, const SString& strTextureName, CD3DDUMMY* pD3DData ) { // Create texinfo m_TexInfoList.push_back ( STexInfo ( usTxdId, strTextureName, pD3DData ) ); STexInfo* pTexInfo = &m_TexInfoList.back (); // Add to lookup maps SString strUniqueKey ( "%d_%s", pTexInfo->usTxdId, *pTexInfo->strTextureName ); if ( MapContains ( m_UniqueTexInfoMap, strUniqueKey ) ) AddReportLog ( 5132, SString ( "CreateTexInfo duplicate %s", *strUniqueKey ) ); MapSet ( m_UniqueTexInfoMap, strUniqueKey, pTexInfo ); // This assert fails when using engine txd replace functions - TODO find out why //assert ( !MapContains ( m_D3DDataTexInfoMap, pTexInfo->pD3DData ) ); MapSet ( m_D3DDataTexInfoMap, pTexInfo->pD3DData, pTexInfo ); return pTexInfo; }
// // Direct players to info about trouble // void SharedUtil::BrowseToSolution ( const SString& strType, bool bAskQuestion, bool bTerminateProcess, bool bDoOnExit, const SString& strMessageBoxMessage ) { AddReportLog ( 3200, SString ( "Trouble %s", *strType ) ); // Put args into a string and save in the registry CArgMap argMap; argMap.Set ( "type", strType.SplitLeft ( ";" ) ); argMap.Set ( "bAskQuestion", bAskQuestion ); argMap.Set ( "message", strMessageBoxMessage ); SetApplicationSetting ( "pending-browse-to-solution", argMap.ToString () ); // Do it now if required if ( !bDoOnExit ) ProcessPendingBrowseToSolution (); // Exit if required if ( bTerminateProcess ) TerminateProcess ( GetCurrentProcess (), 1 ); }
////////////////////////////////////////////////////////// // // CInstallManager::_CheckOnRestartCommand // // // ////////////////////////////////////////////////////////// SString CInstallManager::_CheckOnRestartCommand ( void ) { // Check for pending update const SString strResult = CheckOnRestartCommand (); if ( strResult.Contains ( "install" ) ) { // New settings for install m_pSequencer->SetVariable ( INSTALL_LOCATION, strResult.Contains ( "far" ) ? "far" : "near" ); m_pSequencer->SetVariable ( SILENT_OPT, strResult.Contains ( "silent" ) ? "yes" : "no" ); return "ok"; } else if ( !strResult.Contains ( "no update" ) ) { AddReportLog ( 4047, SString ( "_CheckOnRestartCommand: CheckOnRestartCommand returned %s", strResult.c_str () ) ); } return "no_action"; }
// // What to do on next restart // bool SharedUtil::GetOnRestartCommand ( SString& strOperation, SString& strFile, SString& strParameters, SString& strDirectory, SString& strShowCmd ) { SString strOnRestartCommand = GetRegistryValue ( "", "OnRestartCommand" ); SetOnRestartCommand ( "" ); std::vector < SString > vecParts; strOnRestartCommand.Split ( "\t", vecParts ); if ( vecParts.size () > 5 && vecParts[0].length () ) { SString strVersion ( "%d.%d.%d-%d.%05d", MTASA_VERSION_MAJOR, MTASA_VERSION_MINOR, MTASA_VERSION_MAINTENANCE, MTASA_VERSION_TYPE, MTASA_VERSION_BUILD ); if ( vecParts[5] == strVersion ) { strOperation = vecParts[0]; strFile = vecParts[1]; strParameters = vecParts[2]; strDirectory = vecParts[3]; strShowCmd = vecParts[4]; return true; } AddReportLog( 4000, SString ( "OnRestartCommand disregarded due to version change %s -> %s", vecParts[5].c_str (), strVersion.c_str () ) ); } return false; }
/////////////////////////////////////////////////////////////// // // WinMain // // // /////////////////////////////////////////////////////////////// int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // Load the loader.dll and continue the load #ifdef MTA_DEBUG SString strLoaderDllFilename = "loader_d.dll"; #else SString strLoaderDllFilename = "loader.dll"; #endif SString strMTASAPath = PathJoin ( GetLaunchPath (), "mta" ); SString strLoaderDllPathFilename = PathJoin ( strMTASAPath, strLoaderDllFilename ); // Load loader dll HMODULE hModule = LoadLibrary ( strLoaderDllPathFilename ); int iReturnCode = 0; if ( hModule ) { // Find and call DoWinMain typedef int (*PFNDOWINMAIN) ( HINSTANCE, HINSTANCE, LPSTR, int ); PFNDOWINMAIN pfnDoWinMain = static_cast < PFNDOWINMAIN > ( static_cast < PVOID > ( GetProcAddress ( hModule, "DoWinMain" ) ) ); if ( pfnDoWinMain ) iReturnCode = pfnDoWinMain ( hInstance, hPrevInstance, lpCmdLine, nCmdShow ); FreeLibrary ( hModule ); } else { SString strError = GetSystemErrorMessage ( GetLastError () ); SString strMessage ( "Failed to load: '%s'\n\n%s", *strLoaderDllPathFilename, *strError ); AddReportLog ( 5711, strMessage ); BrowseToSolution ( "loader-dll-missing", true, false, false, strMessage ); iReturnCode = 1; } return iReturnCode; }
///////////////////////////////////////////////////////////// // // CDirect3DEvents9::CreateVertexDeclaration // // Creates a proxy object for the new vertex declaration // ///////////////////////////////////////////////////////////// HRESULT CDirect3DEvents9::CreateVertexDeclaration ( IDirect3DDevice9 *pDevice, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl ) { HRESULT hr; hr = pDevice->CreateVertexDeclaration ( pVertexElements, ppDecl ); if ( FAILED(hr) ) { SString strStatus; // Make a string with decl info for ( uint i = 0 ; i < MAXD3DDECLLENGTH ; i++ ) { const D3DVERTEXELEMENT9& element = pVertexElements[ i ]; if ( element.Stream == 0xFF ) break; strStatus += SString( "[%d,%d,%d,%d,%d,%d]" ,element.Stream ,element.Offset ,element.Type ,element.Method ,element.Usage ,element.UsageIndex ); } SString strMessage( "CreateVertexDecl fail: hr:%x %s", hr, *strStatus ); WriteDebugEvent( strMessage ); AddReportLog( 8613, strMessage ); CCore::GetSingleton ().LogEvent ( 613, "CreateVertexDecl", "", strMessage ); return hr; } // Create proxy *ppDecl = new CProxyDirect3DVertexDeclaration ( pDevice, *ppDecl, pVertexElements ); return hr; }
void CCrashDumpWriter::DumpMiniDump ( _EXCEPTION_POINTERS* pException, CExceptionInformation* pExceptionInformation ) { WriteDebugEvent ( "CCrashDumpWriter::DumpMiniDump" ); // Try to load the DLL in our directory HMODULE hDll = NULL; char szDbgHelpPath [MAX_PATH]; if ( GetModuleFileNameA ( NULL, szDbgHelpPath, MAX_PATH ) ) { char* pSlash = _tcsrchr ( szDbgHelpPath, '\\' ); if ( pSlash ) { _tcscpy ( pSlash + 1, "DBGHELP.DLL" ); hDll = LoadLibrary ( szDbgHelpPath ); } } // If we couldn't load the one in our dir, load any version available if ( !hDll ) { hDll = LoadLibrary( "DBGHELP.DLL" ); } if ( !hDll ) AddReportLog( 9201, "CCrashDumpWriter::DumpMiniDump - Could not load DBGHELP.DLL" ); // We could load a dll? if ( hDll ) { // Grab the MiniDumpWriteDump proc address MINIDUMPWRITEDUMP pDump = reinterpret_cast < MINIDUMPWRITEDUMP > ( GetProcAddress( hDll, "MiniDumpWriteDump" ) ); if ( !pDump ) AddReportLog( 9202, "CCrashDumpWriter::DumpMiniDump - Could not find MiniDumpWriteDump" ); if ( pDump ) { // Create the file HANDLE hFile = CreateFile ( CalcMTASAPath ( "mta\\core.dmp" ), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) AddReportLog( 9203, SString( "CCrashDumpWriter::DumpMiniDump - Could not create '%s'", *CalcMTASAPath ( "mta\\core.dmp" ) ) ); if ( hFile != INVALID_HANDLE_VALUE ) { // Create an exception information struct _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = GetCurrentThreadId (); ExInfo.ExceptionPointers = pException; ExInfo.ClientPointers = FALSE; // Write the dump BOOL bResult = pDump ( GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)( MiniDumpNormal | MiniDumpWithIndirectlyReferencedMemory ), &ExInfo, NULL, NULL ); if ( !bResult ) AddReportLog( 9204, SString( "CCrashDumpWriter::DumpMiniDump - MiniDumpWriteDump failed (%08x)", GetLastError() ) ); else WriteDebugEvent ( "CCrashDumpWriter::DumpMiniDump - MiniDumpWriteDump succeeded" ); // Close the dumpfile CloseHandle ( hFile ); // Grab the current time // Ask windows for the system time. SYSTEMTIME SystemTime; GetLocalTime ( &SystemTime ); // Create the dump directory CreateDirectory ( CalcMTASAPath ( "mta\\dumps" ), 0 ); CreateDirectory ( CalcMTASAPath ( "mta\\dumps\\private" ), 0 ); SString strModuleName = pExceptionInformation->GetModuleBaseName (); strModuleName = strModuleName.ReplaceI ( ".dll", "" ).Replace ( ".exe", "" ).Replace ( "_", "" ).Replace ( ".", "" ).Replace ( "-", "" ); if ( strModuleName.length () == 0 ) strModuleName = "unknown"; SString strMTAVersionFull = SString ( "%s.%s", MTA_DM_BUILDTAG_LONG, *GetApplicationSetting ( "mta-version-ext" ).SplitRight ( ".", NULL, -2 ) ); SString strSerialPart = GetApplicationSetting ( "serial" ).substr ( 0, 5 ); uint uiServerIP = GetApplicationSettingInt ( "last-server-ip" ); uint uiServerPort = GetApplicationSettingInt ( "last-server-port" ); int uiServerTime = GetApplicationSettingInt ( "last-server-time" ); int uiServerDuration = _time32 ( NULL ) - uiServerTime; uiServerDuration = Clamp ( 0, uiServerDuration + 1, 0xfff ); // Get path to mta dir SString strPathCode; { std::vector < SString > parts; PathConform ( CalcMTASAPath ( "" ) ).Split ( PATH_SEPERATOR, parts ); for ( uint i = 0 ; i < parts.size () ; i++ ) { if ( parts[i].CompareI ( "Program Files" ) ) strPathCode += "Pr"; else if ( parts[i].CompareI ( "Program Files (x86)" ) ) strPathCode += "Px"; else if ( parts[i].CompareI ( "MTA San Andreas" ) ) strPathCode += "Mt"; else if ( parts[i].BeginsWithI ( "MTA San Andreas" ) ) strPathCode += "Mb"; else strPathCode += parts[i].Left ( 1 ).ToUpper (); } } // Ensure filename parts match up with EDumpFileNameParts SString strFilename ( "mta\\dumps\\private\\client_%s_%s_%08x_%x_%s_%08X_%04X_%03X_%s_%04d%02d%02d_%02d%02d.dmp", strMTAVersionFull.c_str (), strModuleName.c_str (), pExceptionInformation->GetAddressModuleOffset (), pExceptionInformation->GetCode () & 0xffff, strPathCode.c_str (), uiServerIP, uiServerPort, uiServerDuration, strSerialPart.c_str (), SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute ); SString strPathFilename = CalcMTASAPath ( strFilename ); // Copy the file CopyFile ( CalcMTASAPath ( "mta\\core.dmp" ), strPathFilename, false ); // For the dump uploader SetApplicationSetting ( "diagnostics", "last-dump-extra", "none" ); SetApplicationSetting ( "diagnostics", "last-dump-save", strPathFilename ); // Try to append pool sizes info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-pools" ); CBuffer poolInfo; GetPoolInfo ( poolInfo ); AppendToDumpFile ( strPathFilename, poolInfo, 'POLs', 'POLe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-pools" ); // Try to append d3d state info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-d3d" ); CBuffer d3dInfo; GetD3DInfo ( d3dInfo ); AppendToDumpFile ( strPathFilename, d3dInfo, 'D3Ds', 'D3De' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-d3d" ); // Try to append crash averted stats to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-crash-averted" ); CBuffer crashAvertedStats; GetCrashAvertedStats ( crashAvertedStats ); AppendToDumpFile ( strPathFilename, crashAvertedStats, 'CASs', 'CASe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-crash-averted" ); // Try to append log info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-log" ); CBuffer logInfo; GetLogInfo ( logInfo ); AppendToDumpFile ( strPathFilename, logInfo, 'LOGs', 'LOGe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-log" ); // Try to append dx info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-misc" ); CBuffer dxInfo; GetDxInfo ( dxInfo ); AppendToDumpFile ( strPathFilename, dxInfo, 'DXIs', 'DXIe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-misc" ); // Try to append misc info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-misc" ); CBuffer miscInfo; GetMiscInfo ( miscInfo ); AppendToDumpFile ( strPathFilename, miscInfo, 'MSCs', 'MSCe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-misc" ); // Try to append memory info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-mem" ); CBuffer memInfo; GetMemoryInfo ( memInfo ); AppendToDumpFile ( strPathFilename, memInfo, 'MEMs', 'MEMe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-mem" ); // Try to logfile.txt to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-logfile" ); CBuffer logfileContent; logfileContent.LoadFromFile( CalcMTASAPath( PathJoin( "mta", "logs", "logfile.txt" ) ) ); AppendToDumpFile ( strPathFilename, logfileContent, 'LOGs', 'LOGe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-logfile" ); // Try to report.log to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-report" ); CBuffer reportLogContent; reportLogContent.LoadFromFile( PathJoin( GetMTADataPath(), "report.log" ) ); AppendToDumpFile ( strPathFilename, reportLogContent, 'REPs', 'REPe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-report" ); } } // Free the DLL again FreeLibrary ( hDll ); } // Auto-fixes // Check if crash was in volumetric shadow code if ( ms_uiInCrashZone == 1 || ms_uiInCrashZone == 2 ) { CVARS_SET( "volumetric_shadows", false ); CCore::GetSingleton().SaveConfig(); AddReportLog( 9205, "Disabled volumetric shadows" ); } CNet* pNet = CCore::GetSingleton().GetNetwork(); if ( pNet ) pNet->PostCrash(); }