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: