From ca59d71e7d2a9f4516327675aba02ebfb30ede48 Mon Sep 17 00:00:00 2001 From: Deterous <138427222+Deterous@users.noreply.github.com> Date: Fri, 20 Dec 2024 00:23:50 +0900 Subject: [PATCH] Print PS4/PS5 app.pkg info (#785) * Print PS4/PS5 app.pkg info * namespace * Use a filestream * Use appPkgHeaderDeserializer obj * null check --- CHANGELIST.md | 1 + MPF.Frontend/Tools/PhysicalTool.cs | 111 ++++++++++++++++++++++ MPF.Frontend/Tools/SubmissionGenerator.cs | 2 + 3 files changed, 114 insertions(+) diff --git a/CHANGELIST.md b/CHANGELIST.md index c967b8ed..ff910c28 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -90,6 +90,7 @@ - (EXPERIMENTAL) Skip log line queue - Fully remove processing queue code - Introduce maximum log length +- Print PS4/PS5 app.pkg info ### 3.2.4 (2024-11-24) diff --git a/MPF.Frontend/Tools/PhysicalTool.cs b/MPF.Frontend/Tools/PhysicalTool.cs index a83dff3a..fd642fc2 100644 --- a/MPF.Frontend/Tools/PhysicalTool.cs +++ b/MPF.Frontend/Tools/PhysicalTool.cs @@ -452,6 +452,61 @@ namespace MPF.Frontend.Tools } } + /// + /// Get the app.pkg info from a PlayStation 4 disc, if possible + /// + /// Drive to extract information from + /// PKG info if possible, null on error + public static string? GetPlayStation4PkgInfo(Drive? drive) + { + // If there's no drive path, we can't do this part + if (string.IsNullOrEmpty(drive?.Name)) + return null; + + // If the folder no longer exists, we can't do this part + if (!Directory.Exists(drive!.Name)) + return null; + + // Try parse the app.pkg (multiple if they exist) + try + { + string? pkgInfo = ""; + + string[] appDirs = Directory.GetDirectories(Path.Combine(drive.Name, "app"), "?????????", SearchOption.TopDirectoryOnly); + + foreach (string dir in appDirs) + { + string appPkgPath = Path.Combine(dir, "app.pkg"); + if (!File.Exists(appPkgPath)) + continue; + + // Read the app.pkg header + using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read); + var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader(); + var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream); + + if (appPkgHeader != null) + { + byte[] date = BitConverter.GetBytes(appPkgHeader.VersionDate); + if (BitConverter.IsLittleEndian) + Array.Reverse(date); + + pkgInfo = $"app.pkg ID: {appPkgHeader.ContentID}" + Environment.NewLine + $"app.pkg Date: {date[0]:X2}{date[1]:X2}-{date[2]:X2}-{date[3]:X2}"; + } + } + + if (pkgInfo == "") + return null; + else + return pkgInfo; + } + catch + { + // We don't care what the error was + return null; + } + } + /// /// Get the internal serial from a PlayStation 5 disc, if possible /// @@ -550,6 +605,62 @@ namespace MPF.Frontend.Tools } } + /// + /// Get the app.pkg info from a PlayStation 5 disc, if possible + /// + /// Drive to extract information from + /// PKG info if possible, null on error + public static string? GetPlayStation5PkgInfo(Drive? drive) + { + // If there's no drive path, we can't do this part + if (string.IsNullOrEmpty(drive?.Name)) + return null; + + // If the folder no longer exists, we can't do this part + if (!Directory.Exists(drive!.Name)) + return null; + + // Try parse the app_sc.pkg (multiple if they exist) + try + { + string? pkgInfo = ""; + + string[] appDirs = Directory.GetDirectories(Path.Combine(drive.Name, "app"), "?????????", SearchOption.TopDirectoryOnly); + + foreach (string dir in appDirs) + { + string appPkgPath = Path.Combine(dir, "app_sc.pkg"); + if (!File.Exists(appPkgPath)) + continue; + + // Read the app_sc.pkg header + using var fileStream = new FileStream(appPkgPath, FileMode.Open, FileAccess.Read); + var appPkgHeaderDeserializer = new SabreTools.Serialization.Deserializers.AppPkgHeader(); + var appPkgHeader = appPkgHeaderDeserializer.Deserialize(fileStream); + + if (appPkgHeader != null) + { + byte[] date = BitConverter.GetBytes(appPkgHeader.VersionDate); + if (BitConverter.IsLittleEndian) + Array.Reverse(date); + + string pkgDate = $"{date[0]:X2}{date[1]:X2}-{date[2]:X2}-{date[3]:X2}"; + pkgInfo = $"app_sc.pkg ID: {appPkgHeader.ContentID}" + Environment.NewLine + $"app_sc.pkg Date: {pkgDate}"; + } + } + + if (pkgInfo == "") + return null; + else + return pkgInfo; + } + catch + { + // We don't care what the error was + return null; + } + } + #endregion #region Xbox diff --git a/MPF.Frontend/Tools/SubmissionGenerator.cs b/MPF.Frontend/Tools/SubmissionGenerator.cs index 27ecc9d1..7b7ea7b1 100644 --- a/MPF.Frontend/Tools/SubmissionGenerator.cs +++ b/MPF.Frontend/Tools/SubmissionGenerator.cs @@ -921,11 +921,13 @@ namespace MPF.Frontend.Tools case RedumpSystem.SonyPlayStation4: SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStation4Serial); SetVersionIfNotExists(info, drive, PhysicalTool.GetPlayStation4Version); + SetContentFieldIfNotExists(info, SiteCode.Games, drive, PhysicalTool.GetPlayStation4PkgInfo); break; case RedumpSystem.SonyPlayStation5: SetCommentFieldIfNotExists(info, SiteCode.InternalSerialName, drive, PhysicalTool.GetPlayStation5Serial); SetVersionIfNotExists(info, drive, PhysicalTool.GetPlayStation5Version); + SetContentFieldIfNotExists(info, SiteCode.Games, drive, PhysicalTool.GetPlayStation5PkgInfo); break; case RedumpSystem.TomyKissSite: