using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; using OpenSage.FileFormats.Big; using Pfim; namespace AnotherReplayReader { internal sealed class MinimapReader { public static readonly IReadOnlyDictionary FormatMapper = new Dictionary { { ImageFormat.Rgb24, PixelFormats.Bgr24 }, { ImageFormat.Rgba32, PixelFormats.Bgr32 }, { ImageFormat.Rgb8, PixelFormats.Gray8 }, { ImageFormat.R5g5b5a1, PixelFormats.Bgr555 }, { ImageFormat.R5g5b5, PixelFormats.Bgr555 }, { ImageFormat.R5g6b5, PixelFormats.Bgr565 }, }; private readonly BigMinimapCache _cache; private readonly string _ra3InstallPath; private readonly string _mapFolderPath; private readonly string _modFolderPath; public MinimapReader(BigMinimapCache cache, string ra3InstallPath, string mapFolderPath, string modFolderPath) { _cache = cache; _ra3InstallPath = ra3InstallPath; _mapFolderPath = mapFolderPath; _modFolderPath = modFolderPath; } public BitmapSource TryReadTarga(string path, Mod mod, double dpiX = 96.0, double dpiY = 96.0) { using (var targa = TryGetTarga(path, mod)) { if(targa == null) { return null; } try { return BitmapSource.Create(targa.Width, targa.Height, dpiX, dpiY, FormatMapper[targa.Format], null, targa.Data, targa.Stride); } catch (Exception exception) { Debug.Instance.DebugMessage += $"Exception creating BitmapSource from minimap:\r\n {exception}\r\n"; return null; } } } private Targa TryGetTarga(string path, Mod mod) { var tga = null as Targa; const string customMapPrefix = "data/maps/internal/"; if (Directory.Exists(_mapFolderPath) && path.StartsWith(customMapPrefix)) { var minimapPath = Path.Combine(_mapFolderPath, path.Substring(customMapPrefix.Length)); if(File.Exists(minimapPath)) { return Targa.Create(File.ReadAllBytes(minimapPath), new PfimConfig()); } } // now, normalize paths path = path.Replace('/', '\\'); if(!mod.IsRA3) { try { var modSkudefPaths = Enumerable.Empty(); foreach (var subFolder in Directory.EnumerateDirectories(_modFolderPath)) { modSkudefPaths = modSkudefPaths.Concat(Directory.EnumerateFiles(subFolder, $"{mod.ModName}_{mod.ModVersion}.SkuDef")); } foreach (var modSkudefPath in modSkudefPaths) { var modBigPaths = BigMinimapCache.ParseSkudefs(new[] { modSkudefPath }); foreach (var modBigPath in modBigPaths) { using (var modBig = new BigArchive(modBigPath)) { var entry = modBig.GetEntry(path); if (entry != null) { return Targa.Create(entry.Open(), new PfimConfig()); } } } } } catch (Exception exception) { Debug.Instance.DebugMessage += $"Exception when reading minimap from Skudef big:\r\n {exception}\r\n"; } } if (_cache != null && _cache.TryGetBigByEntryPath(path, out var big)) { using (big) { return Targa.Create(big.GetEntry(path).Open(), new PfimConfig()); } } if (Directory.Exists(_ra3InstallPath)) { var minimapPath = Path.Combine(_mapFolderPath, path); if (File.Exists(minimapPath)) { return Targa.Create(File.ReadAllBytes(minimapPath), new PfimConfig()); } } return null; } } }