mirror of
https://github.com/SabreTools/MPF.git
synced 2026-04-05 22:01:16 +00:00
Parse and process Steam AppIDs and DepotIDs (#961)
* Recreate PR * Implement first round of fixes.
This commit is contained in:
committed by
GitHub
parent
29601f130a
commit
f819632a40
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
@@ -157,6 +158,255 @@ namespace MPF.Frontend.Tools
|
||||
|
||||
#endregion
|
||||
|
||||
#region Computer
|
||||
|
||||
/// <summary>
|
||||
/// Get info for discs containing Steam2 (sis/sim/sid) depots
|
||||
/// </summary>
|
||||
/// <param name="drive">Drive to extract information from</param>
|
||||
/// <returns>Steam2 information on success, null otherwise</returns>
|
||||
public static string? GetSteamSimSidInfo(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, we can't get any sis files
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get any information
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
string steamInfo = string.Empty;
|
||||
var steamDepotIdList = new List<long>();
|
||||
|
||||
// ? needed due to note in https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.getfiles
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var options = new EnumerationOptions
|
||||
{
|
||||
MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true
|
||||
};
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", options);
|
||||
#else
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", SearchOption.AllDirectories);
|
||||
#endif
|
||||
|
||||
foreach (string sis in sisPaths)
|
||||
{
|
||||
if (!File.Exists(sis))
|
||||
continue;
|
||||
|
||||
long sisSize = new FileInfo(sis).Length;
|
||||
|
||||
// Arbitrary filesize cap, a disc would need over 100x the normal amount of depots to go over this.
|
||||
if (sisSize > 10000)
|
||||
continue;
|
||||
|
||||
// Read the sku sis file
|
||||
using var fileStream = new FileStream(sis, FileMode.Open, FileAccess.Read);
|
||||
var skuSisDeserializer = new SabreTools.Serialization.Readers.SkuSis();
|
||||
var skuSis = skuSisDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (skuSis?.Sku is not null)
|
||||
{
|
||||
var sku = skuSis.Sku;
|
||||
|
||||
// Skips csm/csd sku sis files
|
||||
if (sku.Manifests is not null)
|
||||
continue;
|
||||
|
||||
// There should always be depots.
|
||||
if (sku.Depots is null)
|
||||
continue;
|
||||
|
||||
steamDepotIdList.AddRange([.. sku.Depots.Values]);
|
||||
}
|
||||
}
|
||||
|
||||
long[] sortedArray = [.. steamDepotIdList.Distinct()];
|
||||
Array.Sort(sortedArray);
|
||||
|
||||
steamInfo = string.Join("\n", Array.ConvertAll(sortedArray, l => l.ToString()));
|
||||
|
||||
if (string.IsNullOrEmpty(steamInfo))
|
||||
return null;
|
||||
|
||||
return steamInfo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get info for discs containing Steam3 (sis/csm/csd) depots
|
||||
/// </summary>
|
||||
/// <param name="drive">Drive to extract information from</param>
|
||||
/// <returns>Steam Csm/Csd information on success, null otherwise</returns>
|
||||
public static string? GetSteamCsmCsdInfo(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, we can't get exe name
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get any information
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
string steamInfo = string.Empty;
|
||||
var steamDepotIdDict = new SortedDictionary<long, long>();
|
||||
|
||||
// ? needed due to note in https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.getfiles
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var options = new EnumerationOptions
|
||||
{
|
||||
MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true
|
||||
};
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", options);
|
||||
#else
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", SearchOption.AllDirectories);
|
||||
#endif
|
||||
|
||||
foreach (string sis in sisPaths)
|
||||
{
|
||||
if (!File.Exists(sis))
|
||||
continue;
|
||||
|
||||
long sisSize = new FileInfo(sis).Length;
|
||||
|
||||
// Arbitrary filesize cap, a disc would need over 100x the normal amount of depots to go over this.
|
||||
if (sisSize > 10000)
|
||||
continue;
|
||||
|
||||
// Read the sku sis file
|
||||
using var fileStream = new FileStream(sis, FileMode.Open, FileAccess.Read);
|
||||
var skuSisDeserializer = new SabreTools.Serialization.Readers.SkuSis();
|
||||
var skuSis = skuSisDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (skuSis?.Sku is not null)
|
||||
{
|
||||
var sku = skuSis.Sku;
|
||||
|
||||
if (sku is null)
|
||||
continue;
|
||||
|
||||
// Skips steam2 sku sis files. Steam3 csm/csd sis files always have manifests.
|
||||
if (sku.Manifests is not null)
|
||||
{
|
||||
foreach (var depot in sku.Manifests)
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
steamDepotIdDict.Add(depot.Key, depot.Value); // Always fine in practice.
|
||||
#else
|
||||
steamDepotIdDict.TryAdd(depot.Key,
|
||||
depot.Value); // Mainly here to allow easier bulk testing.
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var depot in steamDepotIdDict)
|
||||
{
|
||||
steamInfo += $"{depot.Key} ({depot.Value})\n";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(steamInfo))
|
||||
return null;
|
||||
|
||||
return steamInfo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get info for discs containing Steam2 (sis/sim/sid) depots
|
||||
/// </summary>
|
||||
/// <param name="drive">Drive to extract information from</param>
|
||||
/// <returns>Steam2 information on success, null otherwise</returns>
|
||||
public static string? GetSteamAppInfo(Drive? drive)
|
||||
{
|
||||
// If there's no drive path, we can't get exe name
|
||||
if (string.IsNullOrEmpty(drive?.Name))
|
||||
return null;
|
||||
|
||||
// If the folder no longer exists, we can't get any information
|
||||
if (!Directory.Exists(drive!.Name))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
string steamInfo = string.Empty;
|
||||
var steamAppIdList = new List<long>();
|
||||
|
||||
// ? needed due to note in note in https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.getfiles
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var options = new EnumerationOptions
|
||||
{
|
||||
MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = true
|
||||
};
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", options);
|
||||
#else
|
||||
string[] sisPaths = Directory.GetFiles(drive.Name, "?*.sis", SearchOption.AllDirectories);
|
||||
#endif
|
||||
|
||||
// Looping needed in case i.e. this is a coverdisc with multiple steam game installers on it.
|
||||
foreach (string sis in sisPaths)
|
||||
{
|
||||
if (!File.Exists(sis))
|
||||
continue;
|
||||
|
||||
string filename = Path.GetFileName(sis);
|
||||
|
||||
// Arbitrary filesize cap, a disc would need over 100x the normal amount of depots to go over this.
|
||||
long sisSize = new FileInfo(sis).Length;
|
||||
if (sisSize > 10000)
|
||||
continue;
|
||||
|
||||
// Read the sku sis file
|
||||
using var fileStream = new FileStream(sis, FileMode.Open, FileAccess.Read);
|
||||
var skuSisDeserializer = new SabreTools.Serialization.Readers.SkuSis();
|
||||
var skuSis = skuSisDeserializer.Deserialize(fileStream);
|
||||
|
||||
if (skuSis?.Sku is not null)
|
||||
{
|
||||
var sku = skuSis.Sku;
|
||||
|
||||
// There should always be apps
|
||||
if (sku.Apps is null)
|
||||
continue;
|
||||
|
||||
steamAppIdList.AddRange([.. sku.Apps.Values]);
|
||||
}
|
||||
}
|
||||
|
||||
long[] sortedArray = [.. steamAppIdList.Distinct()];
|
||||
Array.Sort(sortedArray);
|
||||
|
||||
steamInfo = string.Join(", ", Array.ConvertAll(sortedArray, l => l.ToString()));
|
||||
|
||||
if (string.IsNullOrEmpty(steamInfo))
|
||||
return null;
|
||||
|
||||
return steamInfo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb the exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PlayStation
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -851,6 +851,16 @@ namespace MPF.Frontend.Tools
|
||||
info.CommonDiscInfo.Category ??= DiscCategory.Multimedia;
|
||||
break;
|
||||
|
||||
case RedumpSystem.IBMPCcompatible:
|
||||
case RedumpSystem.AppleMacintosh:
|
||||
info.CommonDiscInfo.CommentsSpecialFields[SiteCode.SteamAppID] =
|
||||
PhysicalTool.GetSteamAppInfo(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.ContentsSpecialFields[SiteCode.SteamSimSidDepotID] =
|
||||
PhysicalTool.GetSteamSimSidInfo(drive) ?? string.Empty;
|
||||
info.CommonDiscInfo.ContentsSpecialFields[SiteCode.SteamCsmCsdDepotID] =
|
||||
PhysicalTool.GetSteamCsmCsdInfo(drive) ?? string.Empty;
|
||||
break;
|
||||
|
||||
case RedumpSystem.IncredibleTechnologiesEagle:
|
||||
info.CommonDiscInfo.EXEDateBuildDate ??= addPlaceholders ? RequiredValue : string.Empty;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user