diff --git a/BurnOutSharp.Builders/PlayJ.cs b/BurnOutSharp.Builders/PlayJ.cs index d2a3aca2..c658e148 100644 --- a/BurnOutSharp.Builders/PlayJ.cs +++ b/BurnOutSharp.Builders/PlayJ.cs @@ -132,25 +132,29 @@ namespace BurnOutSharp.Builders // Create a new audio file to fill var audioFile = new AudioFile(); - #region Entry Header + #region Audio Header - // Try to parse the entry header - var entryHeader = ParseEntryHeader(data); - if (entryHeader == null) + // Try to parse the audio header + var audioHeader = ParseAudioHeader(data); + if (audioHeader == null) return null; - // Set the entry header - audioFile.Header = entryHeader; + // Set the audio header + audioFile.Header = audioHeader; #endregion #region Unknown Block 1 + uint unknownOffset1 = (audioHeader.Version == 0x00000000) + ? (audioHeader as AudioHeaderV1).UnknownOffset1 + : (audioHeader as AudioHeaderV2).UnknownOffset1 + 0x54; + // If we have an unknown block 1 offset - if (entryHeader.UnknownOffset1 > 0) + if (unknownOffset1 > 0) { // Get the unknown block 1 offset - long offset = entryHeader.UnknownOffset1 + adjust; + long offset = unknownOffset1 + adjust; if (offset < 0 || offset >= data.Length) return null; @@ -171,15 +175,18 @@ namespace BurnOutSharp.Builders #region V1 Only // If we have a V1 file - if (entryHeader.Version == 0x00000000) + if (audioHeader.Version == 0x00000000) { #region Unknown Value 2 + // Get the V1 unknown offset 2 + uint? unknownOffset2 = (audioHeader as AudioHeaderV1)?.UnknownOffset2; + // If we have an unknown value 2 offset - if (entryHeader.UnknownOffset2 > 0) + if (unknownOffset2 != null && unknownOffset2 > 0) { // Get the unknown value 2 offset - long offset = entryHeader.UnknownOffset2 + adjust; + long offset = unknownOffset2.Value + adjust; if (offset < 0 || offset >= data.Length) return null; @@ -194,11 +201,14 @@ namespace BurnOutSharp.Builders #region Unknown Block 3 + // Get the V1 unknown offset 3 + uint? unknownOffset3 = (audioHeader as AudioHeaderV1)?.UnknownOffset3; + // If we have an unknown block 3 offset - if (entryHeader.UnknownOffset2 > 0) + if (unknownOffset3 != null && unknownOffset3 > 0) { // Get the unknown block 3 offset - long offset = entryHeader.UnknownOffset3 + adjust; + long offset = unknownOffset3.Value + adjust; if (offset < 0 || offset >= data.Length) return null; @@ -222,7 +232,7 @@ namespace BurnOutSharp.Builders #region V2 Only // If we have a V2 file - if (entryHeader.Version == 0x0000000A) + if (audioHeader.Version == 0x0000000A) { #region Data Files Count @@ -271,92 +281,6 @@ namespace BurnOutSharp.Builders return playlistHeader; } - /// - /// Parse a Stream into an entry header - /// - /// Stream to parse - /// Filled entry header on success, null on error - private static EntryHeader ParseEntryHeader(Stream data) - { - // Cache the current offset - long initialOffset = data.Position; - - // TODO: Use marshalling here instead of building - EntryHeader entryHeader = new EntryHeader(); - - entryHeader.Signature = data.ReadUInt32(); - if (entryHeader.Signature != SignatureUInt32) - return null; - - // Only V1 is fully supported - entryHeader.Version = data.ReadUInt32(); - if (entryHeader.Version == 0x00000000) - { - entryHeader.TrackID = data.ReadUInt32(); - entryHeader.UnknownOffset1 = data.ReadUInt32(); - entryHeader.UnknownOffset2 = data.ReadUInt32(); - entryHeader.UnknownOffset3 = data.ReadUInt32(); - entryHeader.Unknown1 = data.ReadUInt32(); - entryHeader.Unknown2 = data.ReadUInt32(); - entryHeader.Year = data.ReadUInt32(); - entryHeader.TrackNumber = data.ReadByteValue(); - entryHeader.Subgenre = (Subgenre)data.ReadByteValue(); - entryHeader.Duration = data.ReadUInt32(); - } - else - { - // Discard the following pieces until we can figure out what they are - _ = data.ReadBytes(0x4C); - - entryHeader.TrackID = data.ReadUInt32(); - entryHeader.Year = data.ReadUInt32(); // Unconfirmed - entryHeader.TrackNumber = data.ReadUInt32(); - - // Discard the following pieces until we can figure out what they are - _ = data.ReadBytes(0x04); - } - - entryHeader.TrackLength = data.ReadUInt16(); - byte[] track = data.ReadBytes(entryHeader.TrackLength); - if (track != null) - entryHeader.Track = Encoding.ASCII.GetString(track); - - entryHeader.ArtistLength = data.ReadUInt16(); - byte[] artist = data.ReadBytes(entryHeader.ArtistLength); - if (artist != null) - entryHeader.Artist = Encoding.ASCII.GetString(artist); - - entryHeader.AlbumLength = data.ReadUInt16(); - byte[] album = data.ReadBytes(entryHeader.AlbumLength); - if (album != null) - entryHeader.Album = Encoding.ASCII.GetString(album); - - entryHeader.WriterLength = data.ReadUInt16(); - byte[] writer = data.ReadBytes(entryHeader.WriterLength); - if (writer != null) - entryHeader.Writer = Encoding.ASCII.GetString(writer); - - entryHeader.PublisherLength = data.ReadUInt16(); - byte[] publisher = data.ReadBytes(entryHeader.PublisherLength); - if (publisher != null) - entryHeader.Publisher = Encoding.ASCII.GetString(publisher); - - entryHeader.LabelLength = data.ReadUInt16(); - byte[] label = data.ReadBytes(entryHeader.LabelLength); - if (label != null) - entryHeader.Label = Encoding.ASCII.GetString(label); - - if (data.Position - initialOffset < entryHeader.UnknownOffset1) - { - entryHeader.CommentsLength = data.ReadUInt16(); - byte[] comments = data.ReadBytes(entryHeader.CommentsLength); - if (comments != null) - entryHeader.Comments = Encoding.ASCII.GetString(comments); - } - - return entryHeader; - } - /// /// Parse a Stream into an audio header /// @@ -422,10 +346,15 @@ namespace BurnOutSharp.Builders v2.Unknown10 = data.ReadUInt32(); v2.Unknown11 = data.ReadUInt32(); v2.Unknown12 = data.ReadUInt32(); + v2.Unknown13 = data.ReadUInt32(); + v2.Unknown14 = data.ReadUInt32(); + v2.Unknown15 = data.ReadUInt32(); + v2.Unknown16 = data.ReadUInt32(); + v2.Unknown17 = data.ReadUInt32(); v2.TrackID = data.ReadUInt32(); v2.Year = data.ReadUInt32(); v2.TrackNumber = data.ReadUInt32(); - v2.Unknown13 = data.ReadUInt32(); + v2.Unknown18 = data.ReadUInt32(); audioHeader = v2; unknownOffset1 = v2.UnknownOffset1 + 0x54; @@ -436,10 +365,6 @@ namespace BurnOutSharp.Builders return null; } - audioHeader.Signature = data.ReadUInt32(); - if (audioHeader.Signature != SignatureUInt32) - return null; - audioHeader.TrackLength = data.ReadUInt16(); byte[] track = data.ReadBytes(audioHeader.TrackLength); if (track != null) diff --git a/BurnOutSharp.Models/PlayJ/AudioFile.cs b/BurnOutSharp.Models/PlayJ/AudioFile.cs index 8d2578aa..af4adde8 100644 --- a/BurnOutSharp.Models/PlayJ/AudioFile.cs +++ b/BurnOutSharp.Models/PlayJ/AudioFile.cs @@ -8,7 +8,7 @@ namespace BurnOutSharp.Models.PlayJ /// /// Header /// - public EntryHeader Header { get; set; } + public AudioHeader Header { get; set; } /// /// Unknown block 1 @@ -18,7 +18,7 @@ namespace BurnOutSharp.Models.PlayJ #region V1 Only /// - /// Value referred to by + /// Value referred to by /// /// Typically 0x00000000 public uint UnknownValue2 { get; set; } diff --git a/BurnOutSharp.Models/PlayJ/AudioHeaderV2.cs b/BurnOutSharp.Models/PlayJ/AudioHeaderV2.cs index 9646158e..ce5b2986 100644 --- a/BurnOutSharp.Models/PlayJ/AudioHeaderV2.cs +++ b/BurnOutSharp.Models/PlayJ/AudioHeaderV2.cs @@ -67,15 +67,40 @@ namespace BurnOutSharp.Models.PlayJ public uint Unknown10; /// - /// Unknown (Always 0x00000000) + /// Unknown /// public uint Unknown11; /// - /// Unknown (Always 0x00000007) + /// Unknown (Always 0x0000005) /// public uint Unknown12; + /// + /// Unknown (Always 0x0000009) + /// + public uint Unknown13; + + /// + /// Unknown + /// + public uint Unknown14; + + /// + /// Unknown + /// + public uint Unknown15; + + /// + /// Unknown (Always 0x0000000) + /// + public uint Unknown16; + + /// + /// Unknown (Always 0x00000007) + /// + public uint Unknown17; + /// /// Download track ID /// @@ -96,6 +121,6 @@ namespace BurnOutSharp.Models.PlayJ /// /// Unknown /// - public uint Unknown13; + public uint Unknown18; } } \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/EntryHeader.cs b/BurnOutSharp.Models/PlayJ/EntryHeader.cs deleted file mode 100644 index c44cdca8..00000000 --- a/BurnOutSharp.Models/PlayJ/EntryHeader.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace BurnOutSharp.Models.PlayJ -{ - /// - /// PlayJ audio header / CDS entry header - /// - /// This is only valid for V1 right now - public sealed class EntryHeader - { - /// - /// Signature (0x4B539DFF) - /// - public uint Signature; - - /// - /// Version - /// - public uint Version; - - /// - /// Download track ID - /// - /// 0xFFFFFFFF if unset - public uint TrackID; - - /// - /// Offset to unknown data block 1 - /// - public uint UnknownOffset1; - - /// - /// Offset to unknown data block 2 - /// - public uint UnknownOffset2; - - /// - /// Offset to unknown data block 3 - /// - public uint UnknownOffset3; - - /// - /// Unknown - /// - /// Always 0x00000001 - public uint Unknown1; - - /// - /// Unknown - /// - /// Typically 0x00000001 in download titles - public uint Unknown2; - - /// - /// Track year - /// - /// 0xFFFFFFFF if unset - public uint Year; - - /// - /// Track number - /// - /// Byte in V1, UInt32 in V2 - public uint TrackNumber; - - /// - /// Subgenre - /// - public Subgenre Subgenre; - - /// - /// Track duration in seconds - /// - public uint Duration; - - /// - /// Length of the track name - /// - public ushort TrackLength; - - /// - /// Track name (not null-terminated) - /// - public string Track; - - /// - /// Length of the artist name - /// - public ushort ArtistLength; - - /// - /// Artist name (not null-terminated) - /// - public string Artist; - - /// - /// Length of the album name - /// - public ushort AlbumLength; - - /// - /// Album name (not null-terminated) - /// - public string Album; - - /// - /// Length of the writer name - /// - public ushort WriterLength; - - /// - /// Writer name (not null-terminated) - /// - public string Writer; - - /// - /// Length of the publisher name - /// - public ushort PublisherLength; - - /// - /// Publisher name (not null-terminated) - /// - public string Publisher; - - /// - /// Length of the label name - /// - public ushort LabelLength; - - /// - /// Label name (not null-terminated) - /// - public string Label; - - /// - /// Length of the comments - /// - /// Optional field only in some samples - public ushort CommentsLength; - - /// - /// Comments (not null-terminated) - /// - /// Optional field only in some samples - public string Comments; - } -} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs b/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs index 5dfc1eb6..34650b39 100644 --- a/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs +++ b/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs @@ -1,7 +1,7 @@ namespace BurnOutSharp.Models.PlayJ { /// - /// Data referred to by + /// Data referred to by or /// public sealed class UnknownBlock1 { diff --git a/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs b/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs index 12f1d2a0..d5e400ed 100644 --- a/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs +++ b/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs @@ -1,7 +1,7 @@ namespace BurnOutSharp.Models.PlayJ { /// - /// Data referred to by + /// Data referred to by /// public sealed class UnknownBlock3 { diff --git a/BurnOutSharp.Wrappers/PlayJAudioFile.cs b/BurnOutSharp.Wrappers/PlayJAudioFile.cs index 8babc0f0..22b95bf8 100644 --- a/BurnOutSharp.Wrappers/PlayJAudioFile.cs +++ b/BurnOutSharp.Wrappers/PlayJAudioFile.cs @@ -8,84 +8,161 @@ namespace BurnOutSharp.Wrappers { #region Pass-Through Properties - #region Entry Header + #region Audio Header - /// + /// public uint Signature => _audioFile.Header.Signature; - /// + /// public uint Version => _audioFile.Header.Version; - /// - public uint TrackID => _audioFile.Header.TrackID; + #region V1 Only - /// - public uint UnknownOffset1 => _audioFile.Header.UnknownOffset1; + /// + public uint? V1_TrackID => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.TrackID; - /// - public uint UnknownOffset2 => _audioFile.Header.UnknownOffset2; + /// + public uint? V1_UnknownOffset1 => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.UnknownOffset1; - /// - public uint UnknownOffset3 => _audioFile.Header.UnknownOffset3; + /// + public uint? V1_UnknownOffset2 => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.UnknownOffset2; - /// - public uint Unknown1 => _audioFile.Header.Unknown1; + /// + public uint? V1_UnknownOffset3 => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.UnknownOffset3; - /// - public uint Unknown2 => _audioFile.Header.Unknown2; + /// + public uint? V1_Unknown1 => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.Unknown1; - /// - public uint Year => _audioFile.Header.Year; + /// + public uint? V1_Unknown2 => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.Unknown2; - /// - public uint TrackNumber => _audioFile.Header.TrackNumber; + /// + public uint? V1_Year => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.Year; - /// - public Models.PlayJ.Subgenre Subgenre => _audioFile.Header.Subgenre; + /// + public uint? V1_TrackNumber => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.TrackNumber; - /// - public uint Duration => _audioFile.Header.Duration; + /// + public Models.PlayJ.Subgenre? V1_Subgenre => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.Subgenre; - /// + /// + public uint? V1_Duration => (_audioFile.Header as Models.PlayJ.AudioHeaderV1)?.Duration; + + #endregion + + #region V2 Only + + /// + public uint? V2_Unknown1 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown1; + + /// + public uint? V2_Unknown2 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown2; + + /// + public uint? V2_Unknown3 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown3; + + /// + public uint? V2_Unknown4 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown4; + + /// + public uint? V2_Unknown5 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown5; + + /// + public uint? V2_Unknown6 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown6; + + /// + public uint? V2_UnknownOffset1 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.UnknownOffset1; + + /// + public uint? V2_Unknown7 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown7; + + /// + public uint? V2_Unknown8 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown8; + + /// + public uint? V2_Unknown9 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown9; + + /// + public uint? V2_UnknownOffset2 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.UnknownOffset2; + + /// + public uint? V2_Unknown10 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown10; + + /// + public uint? V2_Unknown11 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown11; + + /// + public uint? V2_Unknown12 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown12; + + /// + public uint? V2_Unknown13 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown13; + + /// + public uint? V2_Unknown14 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown14; + + /// + public uint? V2_Unknown15 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown15; + + /// + public uint? V2_Unknown16 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown16; + + /// + public uint? V2_Unknown17 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown17; + + /// + public uint? V2_TrackID => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.TrackID; + + /// + public uint? V2_Year => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Year; + + /// + public uint? V2_TrackNumber => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.TrackNumber; + + /// + public uint? V2_Unknown18 => (_audioFile.Header as Models.PlayJ.AudioHeaderV2)?.Unknown18; + + #endregion + + /// public ushort TrackLength => _audioFile.Header.TrackLength; - /// + /// public string Track => _audioFile.Header.Track; - /// + /// public ushort ArtistLength => _audioFile.Header.ArtistLength; - /// + /// public string Artist => _audioFile.Header.Artist; - /// + /// public ushort AlbumLength => _audioFile.Header.AlbumLength; - /// + /// public string Album => _audioFile.Header.Album; - /// + /// public ushort WriterLength => _audioFile.Header.WriterLength; - /// + /// public string Writer => _audioFile.Header.Writer; - /// + /// public ushort PublisherLength => _audioFile.Header.PublisherLength; - /// + /// public string Publisher => _audioFile.Header.Publisher; - /// + /// public ushort LabelLength => _audioFile.Header.LabelLength; - /// + /// public string Label => _audioFile.Header.Label; - /// + /// public ushort CommentsLength => _audioFile.Header.CommentsLength; - /// + /// public string Comments => _audioFile.Header.Comments; #endregion @@ -212,7 +289,7 @@ namespace BurnOutSharp.Wrappers builder.AppendLine("-------------------------"); builder.AppendLine(); - PrintEntryHeader(builder); + PrintAudioHeader(builder); PrintUnknownBlock1(builder); if (Version == 0x00000000) @@ -229,25 +306,58 @@ namespace BurnOutSharp.Wrappers } /// - /// Print entry header information + /// Print audio header information /// /// StringBuilder to append information to - private void PrintEntryHeader(StringBuilder builder) + private void PrintAudioHeader(StringBuilder builder) { - builder.AppendLine(" Entry Header Information:"); + builder.AppendLine(" Audio Header Information:"); builder.AppendLine(" -------------------------"); builder.AppendLine($" Signature: {Signature} (0x{Signature:X})"); builder.AppendLine($" Version: {Version} (0x{Version:X})"); - builder.AppendLine($" Track ID: {TrackID} (0x{TrackID:X})"); - builder.AppendLine($" Unknown offset 1: {UnknownOffset1} (0x{UnknownOffset1:X})"); - builder.AppendLine($" Unknown offset 2: {UnknownOffset2} (0x{UnknownOffset2:X})"); - builder.AppendLine($" Unknown offset 3: {UnknownOffset3} (0x{UnknownOffset3:X})"); - builder.AppendLine($" Unknown 1: {Unknown1} (0x{Unknown1:X})"); - builder.AppendLine($" Unknown 2: {Unknown2} (0x{Unknown2:X})"); - builder.AppendLine($" Year: {Year} (0x{Year:X})"); - builder.AppendLine($" Track number: {TrackNumber} (0x{TrackNumber:X})"); - builder.AppendLine($" Subgenre: {Subgenre} (0x{Subgenre:X})"); - builder.AppendLine($" Duration in seconds: {Duration} (0x{Duration:X})"); + if (Version == 0x00000000) + { + builder.AppendLine($" Track ID: {V1_TrackID} (0x{V1_TrackID:X})"); + builder.AppendLine($" Unknown offset 1: {V1_UnknownOffset1} (0x{V1_UnknownOffset1:X})"); + builder.AppendLine($" Unknown offset 2: {V1_UnknownOffset2} (0x{V1_UnknownOffset2:X})"); + builder.AppendLine($" Unknown offset 3: {V1_UnknownOffset3} (0x{V1_UnknownOffset3:X})"); + builder.AppendLine($" Unknown 1: {V1_Unknown1} (0x{V1_Unknown1:X})"); + builder.AppendLine($" Unknown 2: {V1_Unknown2} (0x{V1_Unknown2:X})"); + builder.AppendLine($" Year: {V1_Year} (0x{V1_Year:X})"); + builder.AppendLine($" Track number: {V1_TrackNumber} (0x{V1_TrackNumber:X})"); + builder.AppendLine($" Subgenre: {V1_Subgenre} (0x{V1_Subgenre:X})"); + builder.AppendLine($" Duration in seconds: {V1_Duration} (0x{V1_Duration:X})"); + } + else if (Version == 0x0000000A) + { + builder.AppendLine($" Unknown 1: {V2_Unknown1} (0x{V2_Unknown1:X})"); + builder.AppendLine($" Unknown 2: {V2_Unknown2} (0x{V2_Unknown2:X})"); + builder.AppendLine($" Unknown 3: {V2_Unknown3} (0x{V2_Unknown3:X})"); + builder.AppendLine($" Unknown 4: {V2_Unknown4} (0x{V2_Unknown4:X})"); + builder.AppendLine($" Unknown 5: {V2_Unknown5} (0x{V2_Unknown5:X})"); + builder.AppendLine($" Unknown 6: {V2_Unknown6} (0x{V2_Unknown6:X})"); + builder.AppendLine($" Unknown Offset 1: {V2_UnknownOffset1} (0x{V2_UnknownOffset1:X})"); + builder.AppendLine($" Unknown 7: {V2_Unknown7} (0x{V2_Unknown7:X})"); + builder.AppendLine($" Unknown 8: {V2_Unknown8} (0x{V2_Unknown8:X})"); + builder.AppendLine($" Unknown 9: {V2_Unknown9} (0x{V2_Unknown9:X})"); + builder.AppendLine($" Unknown Offset 2: {V2_UnknownOffset2} (0x{V2_UnknownOffset2:X})"); + builder.AppendLine($" Unknown 10: {V2_Unknown10} (0x{V2_Unknown10:X})"); + builder.AppendLine($" Unknown 11: {V2_Unknown11} (0x{V2_Unknown11:X})"); + builder.AppendLine($" Unknown 12: {V2_Unknown12} (0x{V2_Unknown12:X})"); + builder.AppendLine($" Unknown 13: {V2_Unknown13} (0x{V2_Unknown13:X})"); + builder.AppendLine($" Unknown 14: {V2_Unknown14} (0x{V2_Unknown14:X})"); + builder.AppendLine($" Unknown 15: {V2_Unknown15} (0x{V2_Unknown15:X})"); + builder.AppendLine($" Unknown 16: {V2_Unknown16} (0x{V2_Unknown16:X})"); + builder.AppendLine($" Unknown 17: {V2_Unknown17} (0x{V2_Unknown17:X})"); + builder.AppendLine($" Track ID: {V2_TrackID} (0x{V2_TrackID:X})"); + builder.AppendLine($" Year: {V2_Year} (0x{V2_Year:X})"); + builder.AppendLine($" Track number: {V2_TrackNumber} (0x{V2_TrackNumber:X})"); + builder.AppendLine($" Unknown 18: {V2_Unknown18} (0x{V2_Unknown18:X})"); + } + else + { + builder.AppendLine($" Unrecognized version, not parsed..."); + } builder.AppendLine($" Track length: {TrackLength} (0x{TrackLength:X})"); builder.AppendLine($" Track: {Track ?? "[NULL]"}"); builder.AppendLine($" Artist length: {ArtistLength} (0x{ArtistLength:X})");