public bool LoadNSRIndexHeader(BinaryReader binaryReader, ref NSR.NSR nsrFile) { // binaryReader is to a filename.*.nsr.index stream char[] nsrIndex = binaryReader.ReadChars(4); nsrFile.IndexHeader.Version = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Unk0 = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Unk1 = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Count = binaryReader.ReadUInt32(); nsrFile.IndexHeader.IndexOffset = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Offsets = new uint[nsrFile.IndexHeader.Count]; for (int i = 0; i < nsrFile.IndexHeader.Count; i++) { nsrFile.IndexHeader.Offsets[i] = binaryReader.ReadUInt32(); } // TODO: Provide option to update DescriptionHeader.HeaderLength to include IndexHeader length // This would ultimately merge the standalone index file into the base nsr file. if (false) { nsrFile.DescriptionHeader.HeaderLength += nsrFile.IndexHeader.IndexOffset + (nsrFile.IndexHeader.Count * 4); } return(true); }
private void Ghost_Info_Load(object sender, EventArgs e) { Visible = true; Refresh(); DateTime startBenchmark = DateTime.Now; // Cache all the keyframes for future reference, but only actually display based on the visible cache list _cachedKeyframeList.AddRange(_tempNSRFile.KeyframeHeaders); _cachedVisibleKeyframeList.AddRange(_tempNSRFile.KeyframeHeaders); _tempNSRFile = null; KeyframesListBox.VirtualMode = true; KeyframesListBox.VirtualListSize = _cachedVisibleKeyframeList.Count; foreach (NSR.KeyframeHeader keyframeHeader in _cachedKeyframeList) { if (!_loadedKeyframeTypes.Contains(keyframeHeader.KeyframeType)) { _loadedKeyframeTypes.Add(keyframeHeader.KeyframeType); } } FillFilterSuggestions(); DateTime endBenchmark = DateTime.Now; double benchmark = endBenchmark.Subtract(startBenchmark).TotalSeconds; // Warn when it has taken more than 10 seconds to load ghosts, application should not be frozen for longer than that if (benchmark > 10.0) { MessageBox.Show("GHOSTS took " + benchmark.ToString("N2") + " seconds to load."); } _loadingPacifier.Visible = false; }
public bool LoadNSR(BinaryReader binaryReader, ref NSR.NSR nsrFile) { LoadNSRPreview(binaryReader, ref nsrFile); nsrFile.RawSize = binaryReader.BaseStream.Length; try { // ghosts - keyframe while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) { NSR.KeyframeHeader keyframeHeader = new NSR.KeyframeHeader { RawPosition = binaryReader.BaseStream.Position, KeyframeOrder0 = binaryReader.ReadUInt16(), KeyframeOrder1 = binaryReader.ReadUInt16(), Length = binaryReader.ReadUInt16(), Unk0 = binaryReader.ReadUInt16(), Id = binaryReader.ReadBytes(8), DataType = binaryReader.ReadByte(), Unk1 = binaryReader.ReadByte(), DataCount = binaryReader.ReadByte(), }; keyframeHeader.Data = new byte[keyframeHeader.Length - 11]; keyframeHeader.Data = binaryReader.ReadBytes(keyframeHeader.Length - 11); keyframeHeader.KeyframeType = NSR.KeyframeHeader.MapKeyframeTypes(keyframeHeader.Id[0]); keyframeHeader.KeyframePosition = nsrFile.KeyframeHeaders.Count; nsrFile.KeyframeHeaders.Add(keyframeHeader); } // ghosts - keyframe } catch (EndOfStreamException exception) { string message = ""; message += "Error reading GHOSTs. Would you like to attempt to still view successfully parsed ones?" + Environment.NewLine; message += Environment.NewLine + "---- GHOST ERROR ----" + Environment.NewLine + exception.Message + Environment.NewLine; message += exception.StackTrace + Environment.NewLine; if (MessageBox.Show(message, "Error readings Ghosts", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes) { // TODO: Perform specific ghost safe-load error handling if needed // Currently returning what we have is good enough } else { return(false); } } return(true); }
public void SetInfo(string fileName, ref NSR.NSR nsrFile) { _loadingPacifier.Visible = true; Refresh(); KeyframesListBox.Items.Clear(); _cachedKeyframeList = new List <NSR.KeyframeHeader>(); _cachedVisibleKeyframeList = new List <NSR.KeyframeHeader>(); GhostInfoGroupBox.Text = fileName; RawSizeValLabel.Text = ((nsrFile.RawSize / 1024f) / 1024f).ToString("N2") + " MB"; KeyframesValLabel.Text = nsrFile.KeyframeHeaders.Count.ToString("N0"); _tempNSRFile = nsrFile; }
private void ViewGhostsBtn_Click(object sender, EventArgs e) { if (ReplayFileListBox.SelectedIndex <= -1) { return; } // Display data collected from matrix_fury::RequestGhosts // Full Load NSR byte[] compressedFile = File.ReadAllBytes(ReplayFileListBox.SelectedItem.ToString()); // loads compressed size into memory byte[] decompressedBytes = ReplayFileListBox.SelectedItem.ToString().EndsWith(".nsr_raw") ? compressedFile : Decompress(compressedFile); // loads raw size 2x into memory // Done using compressed data now compressedFile = null; using (MemoryStream decompressedStream = new MemoryStream(decompressedBytes)) using (BinaryReader decompressedReader = new BinaryReader(decompressedStream, Encoding.UTF8)) { NSR.NSR nsrFile = new NSR.NSR(); if (LoadNSR(decompressedReader, ref nsrFile) == false) // loads raw size 2x into memory { MessageBox.Show("Error loading Network Stream Replay.", "Network Stream Replay Viewer", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // begin decompressed cleanup, they aren't going to be used again and are storing a lot of memory decompressedReader.Dispose(); decompressedStream.Dispose(); decompressedBytes = null; GhostInfo ghostInfo = new GhostInfo(); ghostInfo.SetInfo(ReplayFileListBox.SelectedItem.ToString(), ref nsrFile); ghostInfo.ShowDialog(); // release NSR resources nsrFile = null; } } //MessageBox.Show(Ghosts, "Ghosts", MessageBoxButtons.OK, MessageBoxIcon.Information); // This doesn't happen often so should be safe to force now GC.Collect(2); }
private void ReplayFileListBox_SelectedIndexChanged(object sender, EventArgs e) { ResetLabelText(); if (ReplayFileListBox.SelectedIndex <= -1) { return; } using (FileStream compressedStreamPreview = new FileStream(ReplayFileListBox.SelectedItem.ToString(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { compressedStreamPreview.Position = compressedStreamPreview.Length - 4; byte[] lengthBytes = new byte[4]; compressedStreamPreview.Read(lengthBytes, 0, 4); compressedStreamPreview.Position = 0; using (GZipStream decompressedStream = new GZipStream(compressedStreamPreview, CompressionMode.Decompress)) using (BinaryReader b = (ReplayFileListBox.SelectedItem.ToString().EndsWith(".nsr_raw") ? new BinaryReader(compressedStreamPreview, Encoding.UTF8) : new BinaryReader(decompressedStream, Encoding.UTF8))) { NSR.NSR nsrFile = new NSR.NSR(); if (!LoadNSRPreview(b, ref nsrFile)) { MessageBox.Show("Error loading Network Stream Replay.", "Network Stream Replay Viewer", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } long rawLength = BitConverter.ToUInt32(lengthBytes, 0); long compressedLength = compressedStreamPreview.Length; // Set label text ProtocolVersionValLabel.Text = nsrFile.DescriptionHeader.ProtocolVersion.ToString(); ZoneValLabel.Text = nsrFile.MetaHeader.Zone.ToString(); DescriptionValLabel.Text = nsrFile.MetaHeader.Description; DateValLabel.Text = nsrFile.MetaHeader.RecordingTime; CharacterGUIDValLabel.Text = nsrFile.MetaHeader.CharacterGuid.ToString(); UserValLabel.Text = nsrFile.MetaHeader.CharacterName; FirefallVersionValLabel.Text = nsrFile.MetaHeader.FirefallVersion; Date2ValLabel.Text = nsrFile.MetaHeader.GameTime; FileSizeValLabel.Text = $"{compressedLength.ToString("N0")} bytes | {((rawLength / 1024f) / 1024f).ToString("N2")} MB RAW"; } } }
public bool LoadNSRPreview(BinaryReader binaryReader, ref NSR.NSR nsrFile) { // matrix_fury::RequestGhosts->Headers // description header try { char[] nsrDescription = binaryReader.ReadChars(4); } catch (InvalidDataException ex) { // file is either corrupt or not a valid NSR file return(false); } nsrFile.DescriptionHeader.Version = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.HeaderLength = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.MetaLength = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.DescriptionLength = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.OffsetData = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.Unk0 = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.ProtocolVersion = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.MicrosecondEpoch = binaryReader.ReadUInt64(); // utc nsrFile.DescriptionHeader.Unk1 = binaryReader.ReadUInt32(); nsrFile.DescriptionHeader.Unk2 = binaryReader.ReadUInt32(); // description header // index header // if the header_length is 48 bytes then the file is large and the index header is now split into filename*.nsr.index if (nsrFile.DescriptionHeader.HeaderLength != 48) { char[] nsrIndex = binaryReader.ReadChars(4); nsrFile.IndexHeader.Version = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Unk0 = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Unk1 = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Count = binaryReader.ReadUInt32(); nsrFile.IndexHeader.IndexOffset = binaryReader.ReadUInt32(); nsrFile.IndexHeader.Offsets = new uint[nsrFile.IndexHeader.Count]; for (int i = 0; i < nsrFile.IndexHeader.Count; i++) { nsrFile.IndexHeader.Offsets[i] = binaryReader.ReadUInt32(); } } // index header // meta header nsrFile.MetaHeader.Version = binaryReader.ReadUInt32(); nsrFile.MetaHeader.ZoneId = binaryReader.ReadUInt32(); nsrFile.MetaHeader.Description = ReadToNull(ref binaryReader); nsrFile.MetaHeader.RecordingTime = ReadToNull(ref binaryReader); nsrFile.MetaHeader.Position = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); nsrFile.MetaHeader.Rotation = new Vector4(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); nsrFile.MetaHeader.CharacterGuid = binaryReader.ReadUInt64(); nsrFile.MetaHeader.CharacterName = ReadToNull(ref binaryReader); nsrFile.MetaHeader.Unk3 = binaryReader.ReadBytes(18); nsrFile.MetaHeader.FirefallVersion = ReadToNull(ref binaryReader); nsrFile.MetaHeader.MicrosecondEpoch = binaryReader.ReadUInt64(); nsrFile.MetaHeader.MonthRecording = binaryReader.ReadUInt32(); nsrFile.MetaHeader.DayRecording = binaryReader.ReadUInt32(); nsrFile.MetaHeader.YearRecording = binaryReader.ReadUInt32(); nsrFile.MetaHeader.YearLore = binaryReader.ReadUInt32(); nsrFile.MetaHeader.SolarTime = binaryReader.ReadSingle(); // utc nsrFile.MetaHeader.GameTime = ReadToNull(ref binaryReader); nsrFile.MetaHeader.Padding = binaryReader.ReadBytes(128 - (nsrFile.MetaHeader.GameTime.Length + 1)); nsrFile.MetaHeader.Unk4 = binaryReader.ReadBytes(31); // meta header return(true); }
private void SearchBtn_Click(object sender, EventArgs e) { Viewer owningForm = (Viewer)Owner; if (ClearCurrentSearchCheckBox.Checked) { owningForm.LoadNSRDirectory(owningForm.GetNSRDirectory()); } CheckSearchField(); CheckSearchType(); ListBox.ObjectCollection fileList = owningForm.GetReplayFileListBoxItems(); string searchString = SearchStringTextBox.Text; List <string> resultsList = new List <string>(); string errorMessage = ""; foreach (string file in fileList) { using (FileStream compressedStreamPreview = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (GZipStream decompressedStream = new GZipStream(compressedStreamPreview, CompressionMode.Decompress)) using (BinaryReader binaryReader = new BinaryReader(decompressedStream, Encoding.UTF8)) { NSR.NSR nsrFile = new NSR.NSR(); if (owningForm.LoadNSRPreview(binaryReader, ref nsrFile) == false) { if (errorMessage == "") { errorMessage = "The following file(s) were unable to be read:" + Environment.NewLine; } errorMessage += file + Environment.NewLine; } else { switch (_searchField) { case 0: if (_searchType == 0) { if (nsrFile.DescriptionHeader.ProtocolVersion.ToString().IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.DescriptionHeader.ProtocolVersion.ToString().Equals(searchString)) { resultsList.Add(file); } } break; case 1: if (_searchType == 0) { if (nsrFile.MetaHeader.ZoneId.ToString().IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.ZoneId.ToString().Equals(searchString)) { resultsList.Add(file); } } break; case 2: if (_searchType == 0) { if (nsrFile.MetaHeader.Zone.ToString().IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.Zone.ToString().Equals(searchString)) { resultsList.Add(file); } } break; case 3: if (_searchType == 0) { if (nsrFile.MetaHeader.Description.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.Description.Equals(searchString)) { resultsList.Add(file); } } break; case 4: if (_searchType == 0) { if (nsrFile.MetaHeader.RecordingTime.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.RecordingTime.Equals(searchString)) { resultsList.Add(file); } } break; case 5: if (_searchType == 0) { if (nsrFile.MetaHeader.CharacterGuid.ToString().IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.CharacterGuid.ToString().Equals(searchString)) { resultsList.Add(file); } } break; case 6: if (_searchType == 0) { if (nsrFile.MetaHeader.CharacterName.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.CharacterName.Equals(searchString)) { resultsList.Add(file); } } break; case 7: if (_searchType == 0) { if (nsrFile.MetaHeader.FirefallVersion.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.FirefallVersion.Equals(searchString)) { resultsList.Add(file); } } break; case 8: if (_searchType == 0) { if (nsrFile.MetaHeader.GameTime.IndexOf(searchString, 0, StringComparison.CurrentCultureIgnoreCase) > -1) { resultsList.Add(file); } } else { if (nsrFile.MetaHeader.GameTime.Equals(searchString)) { resultsList.Add(file); } } break; default: break; } } } } if (errorMessage != "") { MessageBox.Show(errorMessage); } if (resultsList.Count > 0) { owningForm.ApplyFilteredReplayFileListItems(resultsList); MessageBox.Show("Search Complete." + Environment.NewLine + resultsList.Count + " Matches Found."); } else { MessageBox.Show("No matches found. Search filter will not be applied."); } Close(); }