/*========================================================= RwStreamCreateIsoTranslated (MTA extension) Arguments: file - MTA stream handle Purpose: Transforms the MTA stream handle into a RenderWare stream. The MTA stream handle should not be reused after passing to this function. Returns NULL if the operation failed or the MTA stream handle is NULL. =========================================================*/ RwStream* RwStreamCreateIsoTranslated( CFile *file ) { if ( !file ) return NULL; RwStreamTypeData data; data.callbackClose = RwTranslatedIsoStreamClose; data.callbackRead = RwTranslatedStreamRead; data.callbackWrite = RwTranslatedStreamWrite; data.callbackSeek = RwTranslatedStreamSeek; data.ptr_callback = file; return RwStreamOpen( STREAM_TYPE_CALLBACK, STREAM_MODE_NULL, &data ); }
///////////////////////////////////////////////////////////////////////////// // // 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; }
///////////////////////////////////////////////////////////////////////////// // // CRenderWareSA::RightSizeTexture // // Check texture and shrink if required. // Returns new texture if did shrink // ///////////////////////////////////////////////////////////////////////////// RwTexture* CRenderWareSA::RightSizeTexture( RwTexture* pTexture, uint uiSizeLimit ) { // Validate RwRaster* pRaster = pTexture->raster; if ( !pRaster ) return NULL; RwD3D9Raster* pD3DRaster = (RwD3D9Raster*)( &pRaster->renderResource ); if ( !pD3DRaster->texture || !pD3DRaster->lockedSurface || !pD3DRaster->lockedRect.pBits ) return NULL; // Get texture info uint uiWidth = pRaster->width; uint uiHeight = pRaster->height; D3DFORMAT d3dFormat = pD3DRaster->format; bool bHasAlpha = pD3DRaster->alpha != 0; bool bIsCubeTexture = ( pD3DRaster->cubeTextureFlags & 0x01 ) != 0; bool bHasMipMaps = ( pRaster->numLevels > 1 ); bool bIsCompressed = ( pD3DRaster->textureFlags & 0x10 ) != 0; // Check we can do this if ( bIsCubeTexture || !bIsCompressed ) return NULL; // Only process DXT formats if ( d3dFormat != D3DFMT_DXT1 && d3dFormat != D3DFMT_DXT3 && d3dFormat != D3DFMT_DXT5 ) return NULL; // Change size uint uiReqWidth = Min( uiSizeLimit, uiWidth ); uint uiReqHeight = Min( uiSizeLimit, uiHeight ); if ( uiReqWidth == uiWidth && uiReqHeight == uiHeight ) return NULL; // Lock mip level 0 if required D3DLOCKED_RECT lockedRect = pD3DRaster->lockedRect; bool bNeedOwnLock = ( pD3DRaster->lockedLevel != 0 ) || !pD3DRaster->lockedSurface; if ( bNeedOwnLock ) if ( FAILED( pD3DRaster->texture->LockRect( 0, &lockedRect, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY ) ) ) return NULL; // Try resize CBuffer newPixelBuffer; bool bDidResize = g_pCore->GetGraphics()->ResizeTextureData( lockedRect.pBits, lockedRect.Pitch, uiWidth, uiHeight, d3dFormat, uiReqWidth, uiReqHeight, newPixelBuffer ); if ( bNeedOwnLock ) pD3DRaster->texture->UnlockRect( 0 ); if ( !bDidResize ) return NULL; // Make new RwTexture from pixels NativeTexturePC_Header header; memset( &header, 0, sizeof( header ) ); header.TextureFormat.platformId = 9; header.TextureFormat.filterMode = pTexture->flags & 0xff; header.TextureFormat.uAddressing = ( pTexture->flags & 0xf00 ) >> 8; header.TextureFormat.vAddressing = ( pTexture->flags & 0xf000 ) >> 12; memcpy( header.TextureFormat.name, pTexture->name, 32 ); memcpy( header.TextureFormat.maskName, pTexture->mask, 32 ); header.RasterFormat.rasterFormat = ( pRaster->format & 0x0f ) << 8; // ( dxt1 = 0x00000100 or 0x00000200 / dxt3 = 0x00000300 ) | 0x00008000 mipmaps? header.RasterFormat.d3dFormat = pD3DRaster->format; header.RasterFormat.width = uiReqWidth; header.RasterFormat.height = uiReqHeight; header.RasterFormat.depth = pRaster->depth; header.RasterFormat.numLevels = 1; header.RasterFormat.rasterType = pRaster->type; // dxt1 = 4 / dxt3 = 4 header.RasterFormat.alpha = bHasAlpha; header.RasterFormat.cubeTexture = bIsCubeTexture; header.RasterFormat.autoMipMaps = false; header.RasterFormat.compressed = bIsCompressed; // Create stream containing new texture data CBuffer nativeData; CBufferWriteStream stream( nativeData ); stream.Write( 1 ); stream.Write( 0 ); // Size ignored stream.Write( 0x1803FFFF ); stream.WriteBytes( &header, sizeof( header ) ); stream.Write( newPixelBuffer.GetSize() ); stream.WriteBytes( newPixelBuffer.GetData(), newPixelBuffer.GetSize() ); RwBuffer buffer; buffer.ptr = (void*)nativeData.GetData(); buffer.size = nativeData.GetSize(); RwStream * rwStream = RwStreamOpen( STREAM_TYPE_BUFFER, STREAM_MODE_READ, &buffer ); if ( !rwStream ) return NULL; // Read new texture RwTexture* pNewRwTexture = NULL; rwD3D9NativeTextureRead( rwStream, &pNewRwTexture ); RwStreamClose( rwStream, NULL ); return pNewRwTexture; }