////////////////////////////////////////////////////////////////
//
// CRenderWareSA::ModelInfoTXDLoadTextures
//
// Load textures from a TXD file
//
////////////////////////////////////////////////////////////////
bool CRenderWareSA::ModelInfoTXDLoadTextures ( SReplacementTextures* pReplacementTextures, const SString& strFilename, bool bFilteringEnabled )
{
    // Are we already loaded?
    if ( !pReplacementTextures->textures.empty () )
        return false;

    if ( !g_pCore->GetNetwork ()->CheckFile ( "txd", strFilename ) )
        return false;

    // Try to load it
    RwTexDictionary* pTxd = ReadTXD ( strFilename );
    if ( pTxd )
    {
        // Get the list of textures into our own list
        GetTxdTextures ( pReplacementTextures->textures, pTxd );

        for ( uint i = 0 ; i < pReplacementTextures->textures.size () ; i++ )
        {
            pReplacementTextures->textures[i]->txd = NULL;
            if ( bFilteringEnabled )
                pReplacementTextures->textures[i]->flags = 0x1102;       // Enable filtering (otherwise textures are pixely)
        }

        // Make the txd forget it has any textures and destroy it
        pTxd->textures.root.next = &pTxd->textures.root;
        pTxd->textures.root.prev = &pTxd->textures.root;
        RwTexDictionaryDestroy ( pTxd );
        pTxd = NULL;

        // We succeeded if we got any textures
        return pReplacementTextures->textures.size () > 0;
    }

    return false;
}
/////////////////////////////////////////////////////////////////////////////
//
// CRenderWareSA::RightSizeTxd
//
// Check textures in a txd and shrink if required.
// Returns true if shrunk file was written
//
/////////////////////////////////////////////////////////////////////////////
bool CRenderWareSA::RightSizeTxd( const SString& strInTxdFilename, const SString& strOutTxdFilename, uint uiSizeLimit )
{
    //
    // Read txd from memory
    //
    RwStream* pStream = RwStreamOpen( STREAM_TYPE_FILENAME, STREAM_MODE_READ, *strInTxdFilename );
    if ( pStream == NULL )
        return false;

    // Find our txd chunk 
    if ( RwStreamFindChunk( pStream, 0x16, NULL, NULL ) == false )
    {
        RwStreamClose( pStream, NULL );
        return false;
    }

    // read the txd
    RwTexDictionary* pTxd = RwTexDictionaryGtaStreamRead( pStream );
    RwStreamClose( pStream, NULL );
    if ( !pTxd )
        return false;

    //
    // Process each texture in the txd
    //
    std::vector < RwTexture* > textureList;
    pGame->GetRenderWareSA()->GetTxdTextures( textureList, pTxd );

    bool bChanged = false;
    for ( std::vector < RwTexture* > ::iterator iter = textureList.begin() ; iter != textureList.end() ; iter++ )
    {
        RwTexture* pTexture = *iter;
        RwTexture* pNewRwTexture = RightSizeTexture( pTexture, uiSizeLimit );
        if ( pNewRwTexture && pNewRwTexture != pTexture )
        {
            // Replace texture in txd if changed
            RwTextureDestroy( pTexture );
            RwTexDictionaryAddTexture( pTxd, pNewRwTexture );
            bChanged = true;
        }
        else
        {
            // Keep texture (Reinsert to preserve order for easier debugging)
            RwTexDictionaryRemoveTexture( pTxd, pTexture );
            RwTexDictionaryAddTexture( pTxd, pTexture );
        }
    }


    //
    // Save shrunked txd if changed
    //
    if ( bChanged )
    {
        pStream = RwStreamOpen( STREAM_TYPE_FILENAME, STREAM_MODE_WRITE, *strOutTxdFilename );
        if ( pStream )
        {
            RwTexDictionaryStreamWrite( pTxd, pStream );
            RwStreamClose( pStream, NULL );
            RwTexDictionaryDestroy( pTxd );
            return true;
        }
    }

    RwTexDictionaryDestroy( pTxd );
    return false;
}