private void OpenItem_OnClick(object sender, RoutedEventArgs e) { var ofd = new OpenFileDialog() { Filter = "Bundle Files|*.BUN;*.BIN|All Files|*.*", Multiselect = true, RestoreDirectory = true, CheckFileExists = true, CheckPathExists = true }; if (ofd.ShowDialog() == true) { _game = GameDetector.Game.Unknown; var canContinue = true; var fileList = ofd.FileNames.ToList(); Title = $"NFS Viewer v{Assembly.GetExecutingAssembly().GetName().Version}"; foreach (var fileName in fileList.ToList()) { var fullDirectory = Path.GetDirectoryName(fileName); if (fullDirectory == null) { throw new NullReferenceException("fullDirectory == null"); } var parentDirectory = Directory.GetParent(fullDirectory); if (string.Equals("CARS", parentDirectory.Name, StringComparison.CurrentCultureIgnoreCase)) { var texPath = Path.Combine(parentDirectory.FullName, "TEXTURES.BIN"); if (!fileList.Contains(texPath)) { fileList.Add(texPath); } parentDirectory = Directory.GetParent(parentDirectory.FullName); } else if (string.Equals("FRONTEND", parentDirectory.Name, StringComparison.CurrentCultureIgnoreCase)) { parentDirectory = Directory.GetParent(parentDirectory.FullName); } else if (string.Equals("TRACKS", parentDirectory.Name, StringComparison.CurrentCultureIgnoreCase)) { parentDirectory = Directory.GetParent(parentDirectory.FullName); } var detectedGame = GameDetector.DetectGame(parentDirectory.FullName); if (detectedGame != GameDetector.Game.World && detectedGame != GameDetector.Game.MostWanted && detectedGame != GameDetector.Game.Carbon && detectedGame != GameDetector.Game.ProStreet && detectedGame != GameDetector.Game.Underground && detectedGame != GameDetector.Game.Underground2 && detectedGame != GameDetector.Game.Undercover) { MessageUtil.ShowError("Unsupported game!"); canContinue = false; break; } if (_game != GameDetector.Game.Unknown && _game != detectedGame) { MessageUtil.ShowError("Don't mess with me like this"); canContinue = false; break; } _game = detectedGame; } if (!canContinue) { MessageUtil.ShowError("Cannot open files."); return; } Log.PushSimple(LogModel.LogLevel.Info, $"Loading {fileList.Count} file(s) in {_game} mode"); // Data cleanup Containers.Clear(); RenderManager.Reset(); // RenderManager.Instance.Reset(); AssetRegistry.Instance.Reset(); foreach (var file in fileList) { var stopwatch = new Stopwatch(); var cm = new ChunkManager(_game); stopwatch.Start(); cm.Read(file); stopwatch.Stop(); Log.PushSimple(LogModel.LogLevel.Info, $"Loaded [{file}] in {stopwatch.ElapsedMilliseconds}ms"); var resources = cm.Chunks.Where(c => c.Resource != null).Select(c => c.Resource).ToList(); var container = new FileContainer { FileName = Path.GetFileName(file), InnerFiles = new ObservableCollection <FileAssetContainer>(), Assets = new ObservableCollection <FileAssetContainer>(resources.Select(r => { FileAssetContainer fac = new NullAsset(); switch (r) { case TexturePack tpk: fac = new TexturePackAsset { Resource = tpk, SubAssets = new ObservableCollection <FileAssetContainer>() }; foreach (var texture in tpk.Textures.OrderBy(t => t.Name)) { fac.SubAssets.Add(new TextureAsset { Resource = texture, IsSelected = false }); } break; case SolidList solidList: fac = new SolidListAsset { Resource = solidList, SubAssets = new ObservableCollection <FileAssetContainer>() }; foreach (var solidObject in solidList.Objects.OrderBy(o => o.Name)) { fac.SubAssets.Add(new SolidObjectAsset { Resource = solidObject, IsSelected = false }); } break; } return(fac); })) }; Containers.Add(container); } } }
private void OpenMapItem_OnClick(object sender, RoutedEventArgs e) { var openFolder = new OpenFileDialog() { Filter = "Bundle Files|*.BUN;*.BIN|All Files|*.*", RestoreDirectory = true, CheckFileExists = true, CheckPathExists = true }; if (openFolder.ShowDialog() == true) { var fileName = openFolder.FileName; var fullDirectory = new DirectoryInfo(fileName).Parent; if (fullDirectory?.Name.ToLower() != "tracks" && fullDirectory?.Name.ToLower() != "trackshigh") { MessageUtil.ShowError("Looks like you're using the wrong menu command..."); return; } var parentDirectory = fullDirectory.Parent; if (parentDirectory != null) { var game = _game = GameDetector.DetectGame(parentDirectory.FullName); if (game == GameDetector.Game.Unknown) { MessageUtil.ShowError("Cannot determine installed game."); return; } Log.PushSimple(LogModel.LogLevel.Info, $"Loading [{fileName}] in {game} mode"); GameBundleManager gbm; switch (game) { case GameDetector.Game.MostWanted: { gbm = new MostWantedManager(); break; } case GameDetector.Game.Carbon: { gbm = new CarbonManager(); break; } case GameDetector.Game.ProStreet: case GameDetector.Game.ProStreetTest: { gbm = new ProStreetManager(); break; } case GameDetector.Game.Undercover: { gbm = new UndercoverManager(); break; } case GameDetector.Game.World: { gbm = new World15Manager(); break; } default: throw new ArgumentOutOfRangeException(nameof(game), game, "Invalid game!"); } Containers.Clear(); //MainVisual.Children.Clear(); // RenderManager.Instance.Reset(); AssetRegistry.Instance.Reset(); LocationBundle bundle; try { bundle = gbm.ReadLocationBundle(fileName); } catch (Exception) { MessageUtil.ShowError("This is not a map file."); return; } //var bundle = gbm.ReadLocationBundle(fileName); var rootContainer = new FileContainer { FileName = fileName, Assets = new ObservableCollection <FileAssetContainer>() }; BinaryReader masterStream = null; if (game != GameDetector.Game.World) { masterStream = new BinaryReader( File.OpenRead( Path.Combine(fullDirectory.FullName, $"STREAM{bundle.Name}.BUN"))); } if (game == GameDetector.Game.ProStreet && (string.Equals(bundle.Name.ToLower(), "l6r_lodtest") || string.Equals(bundle.Name.ToLower(), "l6r_lighting") || string.Equals(bundle.Name.ToLower(), "l6r_nis") || string.Equals(bundle.Name.ToLower(), "l6r_testtrack"))) { game = GameDetector.Game.ProStreetTest; } var stopwatch = new Stopwatch(); var cm = new ChunkManager(game); stopwatch.Start(); foreach (var section in bundle.Sections.OrderBy(s => s.Number)) { cm.Reset(); var sectionContainer = new SectionContainer { Section = section, SubAssets = new ObservableCollection <FileAssetContainer>() }; // NFS:World loading requires creation of independent file streams if (section is WorldStreamSection wss) { var computedPath = Path.Combine(fullDirectory.FullName, wss.FragmentFileId == 0 ? $"STREAM{bundle.Name}_{wss.Number}.BUN" : $"STREAM{bundle.Name}_0x{wss.FragmentFileId:X8}.BUN"); cm.Read(computedPath); } else { if (masterStream != null) { masterStream.BaseStream.Position = section.Offset; var sectionData = masterStream.ReadBytes((int)section.Size); using (var br = new BinaryReader(new MemoryStream(sectionData))) { cm.Read(br); } } } var resources = cm.Chunks.Where(c => c.Resource != null).Select(c => c.Resource).ToList(); sectionContainer.SubAssets = new ObservableCollection <FileAssetContainer>(resources.Select(r => { FileAssetContainer fac = new NullAsset(); switch (r) { case TexturePack tpk: fac = new TexturePackAsset { Resource = tpk, SubAssets = new ObservableCollection <FileAssetContainer>() }; foreach (var texture in tpk.Textures.OrderBy(t => t.Name)) { fac.SubAssets.Add(new TextureAsset { Resource = texture, IsSelected = false }); } break; case SolidList solidList: fac = new SolidListAsset { Resource = solidList, SubAssets = new ObservableCollection <FileAssetContainer>() }; foreach (var solidObj in solidList.Objects.OrderBy(o => o.Name)) { fac.SubAssets.Add(new SolidObjectAsset { Resource = solidObj, IsSelected = false }); } break; } return(fac); })); rootContainer.Assets.Add(sectionContainer); } stopwatch.Stop(); Log.PushSimple(LogModel.LogLevel.Info, $"Loaded {fileName} [{stopwatch.ElapsedMilliseconds}ms]"); Containers.Add(rootContainer); masterStream?.Dispose(); Title = $"NFS Viewer v{Assembly.GetExecutingAssembly().GetName().Version} - [{fileName} ({game})]"; RenderManager.Reset(); } } }