From cb3c666f6432d8c80a8e7e9215ab8ed172fea709 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 14 Jan 2023 21:43:59 -0800 Subject: [PATCH] Add PlayJ models --- BurnOutSharp.Models/PlayJ/AudioFile.cs | 29 ++++ BurnOutSharp.Models/PlayJ/Constants.cs | 9 ++ BurnOutSharp.Models/PlayJ/EntryHeader.cs | 170 ++++++++++++++++++++ BurnOutSharp.Models/PlayJ/Enums.cs | 122 ++++++++++++++ BurnOutSharp.Models/PlayJ/Playlist.cs | 18 +++ BurnOutSharp.Models/PlayJ/PlaylistHeader.cs | 18 +++ BurnOutSharp.Models/PlayJ/UnknownBlock1.cs | 18 +++ BurnOutSharp.Models/PlayJ/UnknownBlock3.cs | 13 ++ BurnOutSharp/FileType/PLJ.cs | 78 --------- 9 files changed, 397 insertions(+), 78 deletions(-) create mode 100644 BurnOutSharp.Models/PlayJ/AudioFile.cs create mode 100644 BurnOutSharp.Models/PlayJ/Constants.cs create mode 100644 BurnOutSharp.Models/PlayJ/EntryHeader.cs create mode 100644 BurnOutSharp.Models/PlayJ/Enums.cs create mode 100644 BurnOutSharp.Models/PlayJ/Playlist.cs create mode 100644 BurnOutSharp.Models/PlayJ/PlaylistHeader.cs create mode 100644 BurnOutSharp.Models/PlayJ/UnknownBlock1.cs create mode 100644 BurnOutSharp.Models/PlayJ/UnknownBlock3.cs diff --git a/BurnOutSharp.Models/PlayJ/AudioFile.cs b/BurnOutSharp.Models/PlayJ/AudioFile.cs new file mode 100644 index 00000000..04716a05 --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/AudioFile.cs @@ -0,0 +1,29 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + /// PlayJ audio file / CDS entry + /// + public sealed class AudioFile + { + /// + /// Header + /// + public EntryHeader Header { get; set; } + + /// + /// Unknown block 1 + /// + public UnknownBlock1 UnknownBlock1 { get; set; } + + /// + /// Value referred to by + /// + /// Typically 0x00000000 + public uint UnknownValue2 { get; set; } + + /// + /// Unknown block 3 + /// + public UnknownBlock3 UnknownBlock3 { get; set; } + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/Constants.cs b/BurnOutSharp.Models/PlayJ/Constants.cs new file mode 100644 index 00000000..71a8562e --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/Constants.cs @@ -0,0 +1,9 @@ +namespace BurnOutSharp.Models.PlayJ +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = new byte[] { 0xFF, 0x9D, 0x53, 0x4B }; + + public const uint SignatureUInt32 = 0x4B539DFF; + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/EntryHeader.cs b/BurnOutSharp.Models/PlayJ/EntryHeader.cs new file mode 100644 index 00000000..3fd1fbe2 --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/EntryHeader.cs @@ -0,0 +1,170 @@ +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 + /// + public byte 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; + + #region V2 Notes + + // Header Layout (V2) [WIP] + // ------------------------------------------------------------------------------ + // 0x00 Signature UInt32 + // 0x04 Version UInt32 [0x0000000A] + // 0x08 UNKNOWN byte[36] + // 0x2A Track Length UInt16 + // 0x2C Track String + // 0x2C+TL Artist Length UInt16 + // 0x2E+TL Artist String + // 0x2E+TL+TAL Album Length UInt16 + // 0x30+TL+TAL Album String + // 0x30+TL+TAL+AL Writer Length UInt16 + // 0x32+TL+TAL+AL Writer String + // 0x32+TL+TAL+AL+WL Publisher Length UInt16 + // 0x34+TL+TAL+AL+WL Publisher String + // 0x34+TL+TAL+AL+WL+PL Label Length UInt16 + // 0x36+TL+TAL+AL+WL+PL Label String + + // In the third block: + // lady.plj has 0x00000002 and references "ad006376_5.dat" after + + #endregion + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/Enums.cs b/BurnOutSharp.Models/PlayJ/Enums.cs new file mode 100644 index 00000000..af016511 --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/Enums.cs @@ -0,0 +1,122 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + public enum Genre + { + /// + /// Blues/Folk/Country + /// + BluesFolkCountry = 1, + + /// + /// Jazz + /// + Jazz = 5, + + /// + /// Reggae + /// + Reggae = 10, + + /// + /// Classical + /// + Classical = 12, + + /// + /// Electronic + /// + Electronic = 13, + + /// + /// Pop/Rock + /// + PopRock = 15, + + /// + /// World + /// + World = 16, + + /// + /// Urban + /// + Urban = 17, + + /// + /// Latin + /// + Latin = 18, + + /// + /// Soundtrack/Other + /// + SoundtrackOther = 20, + + /// + /// New Age + /// + NewAge = 21, + + /// + /// Spiritual + /// + Spiritual = 22, + + /// + /// Sway & Tech + /// + SwayAndTech = 23, + + /// + /// Jam Bands + /// + JamBands = 24, + + /// + /// Comedy + /// + Comedy = 25, + + /// + /// Brazilian + /// + Brazilian = 26, + } + + // TODO: Fill out the remaining subgenres from the wayback machine + /// + /// Every subgenre is uniquely associated with a genre + public enum Subgenre : byte + { + /// + /// Blues/Folk/Country > Blues (Modern/Electric) + /// + BluesModernElectric = 2, + + /// + /// Blues/Folk/Country > Blues (Modern/Acoustic) + /// + BluesModernAcoustic = 3, + + /// + /// Blues/Folk/Country > Blues (Traditional) + /// + BluesTraditional = 4, + + /// + /// Blues/Folk/Country > Folk (Traditional) + /// + FolkTraditional = 5, + + /// + /// Blues/Folk/Country > Folk (Contemporary) + /// + FolkContemporary = 6, + + /// + /// Blues/Folk/Country > Folk (Jazz) + /// + FolkJazz = 7, + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/Playlist.cs b/BurnOutSharp.Models/PlayJ/Playlist.cs new file mode 100644 index 00000000..57557003 --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/Playlist.cs @@ -0,0 +1,18 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + /// PlayJ playlist file + /// + public sealed class Playlist + { + /// + /// Playlist header + /// + public PlaylistHeader PlaylistHeader { get; set; } + + /// + /// Entry headers + /// + public EntryHeader[] EntryHeaders { get; set; } + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/PlaylistHeader.cs b/BurnOutSharp.Models/PlayJ/PlaylistHeader.cs new file mode 100644 index 00000000..eb70e87d --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/PlaylistHeader.cs @@ -0,0 +1,18 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + /// PlayJ playlist header + /// + public sealed class PlaylistHeader + { + /// + /// Number of tracks contained within the playlist + /// + public uint TrackCount; + + /// + /// 52 bytes of unknown data + /// + public byte[] Data; + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs b/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs new file mode 100644 index 00000000..c7b7a9ec --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/UnknownBlock1.cs @@ -0,0 +1,18 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + /// Data referred to by + /// + public sealed class UnknownBlock1 + { + /// + /// Length of the following data block + /// + public ushort Length; + + /// + /// Unknown data + /// + public byte[] Data; + } +} \ No newline at end of file diff --git a/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs b/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs new file mode 100644 index 00000000..1cf366ab --- /dev/null +++ b/BurnOutSharp.Models/PlayJ/UnknownBlock3.cs @@ -0,0 +1,13 @@ +namespace BurnOutSharp.Models.PlayJ +{ + /// + /// Data referred to by + /// + public sealed class UnknownBlock3 + { + /// + /// Unknown data + /// + public byte[] Data; + } +} \ No newline at end of file diff --git a/BurnOutSharp/FileType/PLJ.cs b/BurnOutSharp/FileType/PLJ.cs index 3e5dcb83..9c60c491 100644 --- a/BurnOutSharp/FileType/PLJ.cs +++ b/BurnOutSharp/FileType/PLJ.cs @@ -37,84 +37,6 @@ namespace BurnOutSharp.FileType AppendToDictionary(protections, file, "PlayJ Audio File"); return protections; } - - // Header Layout (V1) - // ------------------------------------------------------------------------------ - // 0x00 Signature UInt32 - // 0x04 Version UInt32 [0x00000000] - // 0x08 Track ID UInt32 [Always 0xFFFFFFFF in CD titles] - // 0x0C Unknown Offset 1 UInt32 - // 0x10 Unknown Offset 2 UInt32 - // 0x14 Unknown Offset 3 UInt32 - // 0x18 Unknown (Initial play count?) UInt32 [Always 0x00000001] - // 0x1C Unknown (Play count?) UInt32 [Always 0x00000001 in download titles] - // 0x20 Year UInt32 [0xFFFFFFFF if unset] - // 0x24 Track Number Byte - // 0x25 Subgenre Byte - // 0x26 Duration in Seconds UInt32 - // 0x2A Track Length UInt16 - // 0x2C Track String - // 0x2C+TL Artist Length UInt16 - // 0x2E+TL Artist String - // 0x2E+TL+TAL Album Length UInt16 - // 0x30+TL+TAL Album String - // 0x30+TL+TAL+AL Writer Length UInt16 - // 0x32+TL+TAL+AL Writer String - // 0x32+TL+TAL+AL+WL Publisher Length UInt16 - // 0x34+TL+TAL+AL+WL Publisher String - // 0x34+TL+TAL+AL+WL+PL Label Length UInt16 - // 0x36+TL+TAL+AL+WL+PL Label String - // - // The following samples also have a "Comments" section after the label, same format - // - golden_empire.plj - // - i_want_to_take_you_higher.plj - // - // Unknown Offset 1 - // ------------------------------------------------------------------------------ - // UO1 Unknown Block 1 Length UInt32 - // UO1+2 Unknown Block 1 byte[UB1L] - // - // Unknown Offset 2 - // ------------------------------------------------------------------------------ - // UO2 Unknown Value UInt32 - // Most of the samples have 0x00000000 - // nature_soundscape_v.plj has 0x00C88028 - // - // Unknown Offset 3 - // ------------------------------------------------------------------------------ - // UO3 Unknown Data byte[??] - // - - // Header Layout (V2) [WIP] - // ------------------------------------------------------------------------------ - // 0x00 Signature UInt32 - // 0x04 Version UInt32 [0x0000000A] - // 0x08 UNKNOWN byte[36] - // 0x2A Track Length UInt16 - // 0x2C Track String - // 0x2C+TL Artist Length UInt16 - // 0x2E+TL Artist String - // 0x2E+TL+TAL Album Length UInt16 - // 0x30+TL+TAL Album String - // 0x30+TL+TAL+AL Writer Length UInt16 - // 0x32+TL+TAL+AL Writer String - // 0x32+TL+TAL+AL+WL Publisher Length UInt16 - // 0x34+TL+TAL+AL+WL Publisher String - // 0x34+TL+TAL+AL+WL+PL Label Length UInt16 - // 0x36+TL+TAL+AL+WL+PL Label String - - // In the third block: - // lady.plj has 0x00000002 and references "ad006376_5.dat" after - - // Known Subgenre IDs (http://playj.com/static/subgenre_XX.html) - // ----------------------------------------------- - // 2 - Blues/Folk/Country > Blues (Modern/Electric) - // 3 - Blues/Folk/Country > Blues (Modern/Acoustic) - // 4 - Blues/Folk/Country > Blues (Traditional) - // 5 - Blues/Folk/Country > Folk (Traditional) - // 6 - Blues/Folk/Country > Folk (Contemporary) - // 7 - Blues/Folk/Country > Folk (Jazz) - // TODO: When converting to enum, fill in the rest } catch (Exception ex) {