61 lines
3.2 KiB
C#
61 lines
3.2 KiB
C#
namespace Ludarium.Application;
|
|
|
|
/// <summary>
|
|
/// Selects the one unique read-only GameCube or Wii image a Dolphin session may launch.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Dolphin serves two platforms from one mount, so a runtime path always names its platform
|
|
/// directory. Everything else — path safety, prefix rebasing, capability vocabulary — is shared with
|
|
/// every other native player.
|
|
/// </remarks>
|
|
public static class DolphinLaunchPolicy
|
|
{
|
|
public static NativeRemotePlayer Player => NativeRemotePlayerRegistry.Dolphin;
|
|
|
|
public static IReadOnlyList<string> SupportedPlatforms => Player.Platforms;
|
|
|
|
/// <summary>A disc image below this size is a stub, a companion file or a partial download.</summary>
|
|
private const long MinimumImageBytes = 1024 * 1024;
|
|
|
|
public static NativeRemotePlayCapability EvaluateCapability(Guid gameId, string? platform, bool runtimeReady,
|
|
IReadOnlyList<NativeLaunchCandidate> candidates, DateTimeOffset? checkedAt = null,
|
|
bool vaultBacked = false)
|
|
{
|
|
var now = checkedAt ?? DateTimeOffset.UtcNow;
|
|
if (!Player.Owns(platform))
|
|
return Unavailable(NativeRemotePlayState.UnsupportedPlatform,
|
|
"Only GameCube and Wii games can use the isolated Dolphin player.");
|
|
if (!runtimeReady)
|
|
return Unavailable(NativeRemotePlayState.RuntimeUnavailable,
|
|
"The isolated Dolphin runtime or exact-title controller is not available.");
|
|
if (candidates.Count == 0)
|
|
return Unavailable(NativeRemotePlayState.MissingGame,
|
|
"No linked Dolphin-compatible disc image was found for this game.");
|
|
if (!candidates.Any(candidate => candidate.SourceReadOnly))
|
|
return Unavailable(NativeRemotePlayState.SourceNotReadOnly,
|
|
"The linked source is not mounted read-only, so playback is blocked.");
|
|
if (SelectGame(candidates) is null)
|
|
return Unavailable(NativeRemotePlayState.AmbiguousMapping,
|
|
"Ludarium could not identify one unique read-only Dolphin-compatible image for this game.");
|
|
return NativeRemotePlayPolicy.Available(Player, gameId,
|
|
"The exact linked game is ready in the isolated Dolphin player.", now, platform, vaultBacked);
|
|
|
|
NativeRemotePlayCapability Unavailable(NativeRemotePlayState state, string message) =>
|
|
NativeRemotePlayPolicy.Unavailable(Player, gameId, state, message, now, platform);
|
|
}
|
|
|
|
public static NativeLaunchCandidate? SelectGame(IReadOnlyList<NativeLaunchCandidate> candidates)
|
|
{
|
|
var eligible = candidates.Where(candidate => candidate.SourceReadOnly &&
|
|
candidate.Size > MinimumImageBytes && Player.AcceptsExtension(candidate.RelativePath) &&
|
|
NativeRemotePlayPolicy.IsSafeRelativePath(candidate.RelativePath)).ToArray();
|
|
return eligible.Length == 1 ? eligible[0] : null;
|
|
}
|
|
|
|
public static string ToRuntimePath(string platform, string relativePath, string catalogPrefix)
|
|
{
|
|
if (!Player.Owns(platform)) throw new InvalidOperationException("Unsupported Dolphin platform.");
|
|
return NativeRemotePlayPolicy.ToRuntimePath(relativePath, catalogPrefix, Player.Extensions, platform);
|
|
}
|
|
}
|