Exemple #1
0
//////////////////////////////////////////////////////////
//
// NvOptimusDetect
//
// Try detecting optimus via NvAPI
//
//////////////////////////////////////////////////////////
bool NvOptimusDetect( void )
{
    if( NvAPI_Initialize() != NVAPI_OK )
    {
		return false;
    }

    // Get and log driver info
	NvAPI_ShortString szDesc = "-";
    NvU32 uiDriverVersion = -1;
	NvAPI_ShortString szBuildBranchString = "-";

    NvAPI_GetInterfaceVersionString( szDesc );
    NvAPI_SYS_GetDriverAndBranchVersion( &uiDriverVersion, szBuildBranchString );
    WriteDebugEventAndReport( 7460, SString( "NvAPI - InterfaceVersion:'%s' DriverVersion:%d.%d Branch:'%s'", szDesc, uiDriverVersion / 100, uiDriverVersion % 100, szBuildBranchString ) );
    
    // Get all the Physical GPU Handles
    NvPhysicalGpuHandle nvGPUHandle[NVAPI_MAX_PHYSICAL_GPUS] = {0};
    NvU32 uiGpuCount = 0;
    if( NvAPI_EnumPhysicalGPUs( nvGPUHandle, &uiGpuCount ) != NVAPI_OK )
    {
        return false;
    }

    bool bFoundOptimus = false;
    for( NvU32 i = 0; i < uiGpuCount; i++ )
    {
        NV_SYSTEM_TYPE SystemType = (NV_SYSTEM_TYPE)-1;     // 1-Laptop 2-Desktop
        NV_GPU_TYPE GpuType = (NV_GPU_TYPE)-1;              // 1-Integrated 2-Discrete
        NvAPI_ShortString szName = "-";

        NvAPI_GPU_GetSystemType( nvGPUHandle[i], &SystemType );
        NvAPI_GPU_GetGPUType( nvGPUHandle[i], &GpuType );
        NvAPI_GPU_GetFullName( nvGPUHandle[i], szName );
        SString strStatus( "NvAPI - GPU %d/%d - SystemType:%d GpuType:%d (%s)", i, uiGpuCount, SystemType, GpuType, szName );

        if ( SystemType == NV_SYSTEM_TYPE_LAPTOP && GpuType == NV_SYSTEM_TYPE_DGPU )
        {
            bFoundOptimus = true;
            strStatus += " FoundOptimus";
        }
        WriteDebugEventAndReport( 7461, strStatus );
    }

    return bFoundOptimus;
}
//////////////////////////////////////////////////////////
//
// ShouldUseExeCopy
//
// Returns true if patches should be applied to exe copy
//
//////////////////////////////////////////////////////////
bool ShouldUseExeCopy( void )
{
    SString strUseCopyReason;
    if ( GetApplicationSettingInt( "nvhacks", "optimus" ) )
        strUseCopyReason = GetApplicationSettingInt( "nvhacks", "optimus-rename-exe" ) == 0 ? "" : "optimus-rename-exe";
    else
        strUseCopyReason = GetApplicationSettingInt( "driver-overrides-disabled" ) == 0 ? "" : "driver-overrides-disabled";

    if ( GetPatchRequirementAltModules() )
        strUseCopyReason += " AltModules";

    if ( RequiresAltTabFix() )
        strUseCopyReason += " AltTabFix";

    // Log reason for using proxy_sa
    static SString strUseCopyReasonPrevious;
    if ( strUseCopyReasonPrevious != strUseCopyReason )
    {
        WriteDebugEventAndReport( 3500, SString( "Using proxy_sa because: %s", *strUseCopyReason ) );
        strUseCopyReasonPrevious = strUseCopyReason;
    }
    return !strUseCopyReason.empty();
}
EPatchResult UpdatePatchStatusAltModules( const SString& strGTAEXEPath, EPatchMode mode )
{
    // List of names to check/change
    SSearchInfo searchList[] = {
                    { 0x4a0000, 0x3000, "vorbisfile.dll", "vvof.dll", 0, },
                    { 0x4a0000, 0x3000, "eax.dll",        "vea.dll",  0, },
                    { 0xD96000, 0x7000, "vorbisfile.dll", "vvof.dll", 0, },
                    { 0xD96000, 0x7000, "eax.dll",        "vea.dll",  0, },
                };

    uint uiNumOldNames = 0;
    uint uiNumNewNames = 0;

    FILE* fh = fopen ( strGTAEXEPath, "rb" );
    if ( fh )
    {
        for ( uint i = 0 ; i < NUMELMS( searchList ) ; i++ )
        {
            SSearchInfo& item = searchList[i];
            if ( !fseek ( fh, item.uiOffsetStart, SEEK_SET ) )
            {
                std::vector < char > buffer;
                buffer.resize( item.uiSearchSize );
                if ( fread ( &buffer[0], item.uiSearchSize, 1, fh ) == 1 )
                {
                    std::vector < char >::iterator it;
                    it = std::search( buffer.begin(), buffer.end(), item.szOldName, item.szOldName + strlen( item.szOldName ), SearchPredicate );
                    if ( it != buffer.end() )
                    {
                        uiNumOldNames++;
                    }
                    else
                    {
                        it = std::search( buffer.begin(), buffer.end(), item.szNewName, item.szNewName + strlen( item.szNewName ), SearchPredicate );
                        if ( it != buffer.end() )
                        {
                            uiNumNewNames++;
                        }
                    }

                    if ( it != buffer.end() )
                    {
                        char* p0 = &buffer[0];
                        char* p1 = &(*it);
                        item.uiFileOffset = item.uiOffsetStart + (uint)p1 - (uint)p0;
                    }
                }
            }
        }
        fclose ( fh );
    }

    // Return status if just checking
    if ( mode == PATCH_CHECK )
    {
        if ( uiNumNewNames > 0 )
            return PATCH_CHECK_RESULT_ON;
        return PATCH_CHECK_RESULT_OFF;
    }

    if ( uiNumOldNames + uiNumNewNames != 4 )
    {
        WriteDebugEventAndReport( 9804, SString ( "UpdatePatchStatusAltModules: Can't find module names (%d,%d)", uiNumOldNames, uiNumNewNames ) );
    }

    if ( ( mode == PATCH_SET_ON && uiNumOldNames > 0 )
      || ( mode == PATCH_SET_OFF && uiNumNewNames > 0 ) )
    {
        // Change needed!

        // Can't do this to gta_sa.exe 4 sure
        assert( !strGTAEXEPath.EndsWithI( "gta_sa.exe" ) );

        SetFileAttributes ( strGTAEXEPath, FILE_ATTRIBUTE_NORMAL );
        FILE* fh = fopen ( strGTAEXEPath, "r+b" );
        if ( !fh )
        {
            return PATCH_SET_RESULT_REQ_ADMIN;
        }

        for ( uint i = 0 ; i < NUMELMS( searchList ) ; i++ )
        {
            SSearchInfo& item = searchList[i];
            const char* szName = ( mode == PATCH_SET_ON ) ? item.szNewName : item.szOldName;

            if ( item.uiFileOffset )
            {
                if ( !fseek ( fh, item.uiFileOffset, SEEK_SET ) )
                {
                    fwrite( szName, strlen( szName ) + 1, 1, fh );                         
                }
            }
        }
        fclose ( fh );

        if ( mode == PATCH_SET_ON )
            WriteDebugEvent( SString ( "UpdatePatchStatusAltModules: Now using alt modules (%d,%d)", uiNumOldNames, uiNumNewNames ) );
    }

    return PATCH_SET_RESULT_OK;
}
EPatchResult UpdatePatchStatusNvightmare( const SString& strGTAEXEPath, EPatchMode mode )
{
    char bIsEUVersion = false;
    bool bHasExportTable = true;
    uint uiExportValue = 0;
    bool bUnknownBytes = false;
    FILE* fh = fopen( strGTAEXEPath, "rb" );
    bool bFileError = ( fh == NULL );
    if( !bFileError )
    {
        // Determine version
        bFileError |= ( fseek( fh, EU_VERSION_BYTE, SEEK_SET ) != 0 );
        bFileError |= ( fread( &bIsEUVersion, 1, 1, fh ) != 1 );

        // Determine patched status
        for ( uint i = 0 ; i < NUMELMS( datumList ) ; i++ )
        {
            const SDataumRow& row = datumList[ i ];
            uint uiFileOffset = bIsEUVersion ? row.uiFileOffsetEU : row.uiFileOffsetUS;

            bFileError |= ( fseek( fh, uiFileOffset, SEEK_SET ) != 0 );

            std::vector < char > buffer( row.uiDataSize );
            bFileError |=  ( fread( &buffer[0], row.uiDataSize, 1, fh ) != 1 );

            if ( memcmp( &buffer[0], row.pOldData, row.uiDataSize ) == 0 )
                bHasExportTable = false;
            else
            if ( memcmp( &buffer[0], row.pNewData, row.uiDataSize ) != 0 )
                bUnknownBytes = true;
        }
        // Determine export value
        {
            uint uiFileOffset = bIsEUVersion ? valueItem.uiFileOffsetEU : valueItem.uiFileOffsetUS;
            bFileError |= ( fseek( fh, uiFileOffset, SEEK_SET ) != 0 );
            bFileError |= ( fread( &uiExportValue, sizeof( uiExportValue ), 1, fh ) != 1 );
        }
        fclose ( fh );
    }

    // Return status if just checking
    if ( mode == PATCH_CHECK )
    {
        if ( bHasExportTable && uiExportValue == 1 )
            return PATCH_CHECK_RESULT_ON;
        return PATCH_CHECK_RESULT_OFF;
    }

    if ( bFileError )
        WriteDebugEventAndReport( 9801, "Nvightmare patch: Can not apply due to unknown file error" );
    else
    if ( bUnknownBytes )
        WriteDebugEventAndReport( 9802, "Nvightmare patch: Can not apply due to unknown file bytes" );
    else
    {
        // Determine if change required
        bool bReqExportTable = ( mode == PATCH_SET_ON );
        uint uiReqExportValue = 1;
        if ( bReqExportTable == bHasExportTable && uiReqExportValue == uiExportValue )
        {
            if ( bReqExportTable )
                WriteDebugEvent( SString( "Nvightmare patch:  Already applied ExportValue of %d", uiReqExportValue ) );
        }
        else
        {
            // Change needed!
            SetFileAttributes( strGTAEXEPath, FILE_ATTRIBUTE_NORMAL );
            FILE* fh = fopen( strGTAEXEPath, "r+b" );
            if ( !fh )
            {
                return PATCH_SET_RESULT_REQ_ADMIN;
            }

            bool bFileError = false;
            // Write patches
            if ( bReqExportTable != bHasExportTable )
            {
                WriteDebugEvent( SString( "Nvightmare patch: Changing HasExportTable to %d", bReqExportTable ) );
                for ( uint i = 0 ; i < NUMELMS( datumList ) ; i++ )
                {
                    const SDataumRow& row = datumList[ i ];
                    uint uiFileOffset = bIsEUVersion ? row.uiFileOffsetEU : row.uiFileOffsetUS;

                    bFileError |= ( fseek( fh, uiFileOffset, SEEK_SET ) != 0 );
                    if ( bReqExportTable )
                        bFileError |= ( fwrite( row.pNewData, row.uiDataSize, 1, fh ) != 1 );
                    else
                        bFileError |= ( fwrite( row.pOldData, row.uiDataSize, 1, fh ) != 1 );
                }
            }
            // Write value
            if ( uiReqExportValue != uiExportValue )
            {
                WriteDebugEvent( SString( "Nvightmare patch: Changing ExportValue to %d", uiReqExportValue ) );
                uint uiFileOffset = bIsEUVersion ? valueItem.uiFileOffsetEU : valueItem.uiFileOffsetUS;
                bFileError |= ( fseek( fh, uiFileOffset, SEEK_SET ) != 0 );
                bFileError |= ( fwrite( &uiReqExportValue, sizeof( uiReqExportValue ), 1, fh ) != 1 );
            }

            fclose ( fh );
            if ( bFileError )
                WriteDebugEventAndReport( 9803, "Nvightmare patch: File update completed with file errors" );
            else
                WriteDebugEvent( "Nvightmare patch: File update completed" );
        }
    }
    return PATCH_SET_RESULT_OK;
}