Add EmulatedGameCardFsCreator

This commit is contained in:
Alex Barney 2019-10-08 20:39:07 -05:00
parent f4aaa3b453
commit 089b5b4f63
8 changed files with 116 additions and 6 deletions

View file

@ -1,4 +1,5 @@
using System;
using LibHac.Common;
using LibHac.FsService;
namespace LibHac.Fs
@ -13,6 +14,22 @@ namespace LibHac.Fs
return fsProxy.OpenGameCardStorage(out storage, handle, partitionType);
}
public static Result MountGameCardPartition(this FileSystemClient fs, U8Span mountName, GameCardHandle handle,
GameCardPartition partitionId)
{
Result rc = MountHelpers.CheckMountNameAcceptingReservedMountName(mountName);
if (rc.IsFailure()) return rc;
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
rc = fsProxy.OpenGameCardFileSystem(out IFileSystem cardFs, handle, partitionId);
if (rc.IsFailure()) return rc;
var mountNameGenerator = new GameCardCommonMountNameGenerator(handle, partitionId);
return fs.Register(mountName, cardFs, mountNameGenerator);
}
public static Result GetGameCardHandle(this FileSystemClient fs, out GameCardHandle handle)
{
handle = default;
@ -57,6 +74,40 @@ namespace LibHac.Fs
{
return (long)page << 9;
}
private class GameCardCommonMountNameGenerator : ICommonMountNameGenerator
{
private GameCardHandle Handle { get; }
private GameCardPartition PartitionId { get; }
public GameCardCommonMountNameGenerator(GameCardHandle handle, GameCardPartition partitionId)
{
Handle = handle;
PartitionId = partitionId;
}
public Result Generate(Span<byte> nameBuffer)
{
char letter = GetPartitionMountLetter(PartitionId);
string mountName = $"@Gc{letter}{Handle.Value:x8}";
new U8Span(mountName).Value.CopyTo(nameBuffer);
return Result.Success;
}
private static char GetPartitionMountLetter(GameCardPartition partition)
{
switch (partition)
{
case GameCardPartition.Update: return 'U';
case GameCardPartition.Normal: return 'N';
case GameCardPartition.Secure: return 'S';
default:
throw new ArgumentOutOfRangeException(nameof(partition), partition, null);
}
}
}
}
public enum GameCardSize

View file

@ -0,0 +1,34 @@
using LibHac.Fs;
namespace LibHac.FsService.Creators
{
public class EmulatedGameCardFsCreator : IGameCardFileSystemCreator
{
// ReSharper disable once UnusedAutoPropertyAccessor.Local
private EmulatedGameCardStorageCreator StorageCreator { get; }
private EmulatedGameCard GameCard { get; }
public EmulatedGameCardFsCreator(EmulatedGameCardStorageCreator storageCreator, EmulatedGameCard gameCard)
{
StorageCreator = storageCreator;
GameCard = gameCard;
}
public Result Create(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionType)
{
// Use the old xci code temporarily
fileSystem = default;
Result rc = GameCard.GetXci(out Xci xci, handle);
if (rc.IsFailure()) return rc;
if (!xci.HasPartition((XciPartitionType)partitionType))
{
return ResultFs.PartitionNotFound.Log();
}
fileSystem = xci.OpenPartition((XciPartitionType)partitionType);
return Result.Success;
}
}
}

View file

@ -3,7 +3,7 @@ using LibHac.Fs;
namespace LibHac.FsService.Creators
{
class EmulatedGameCardStorageCreator : IGameCardStorageCreator
public class EmulatedGameCardStorageCreator : IGameCardStorageCreator
{
private EmulatedGameCard GameCard { get; }

View file

@ -35,6 +35,8 @@ namespace LibHac.FsService.Creators
string path = Path ?? DefaultPath;
// Todo: Add ProxyFileSystem?
return Util.CreateSubFileSystem(out fileSystem, RootFileSystem, path, true);
}

View file

@ -14,9 +14,12 @@ namespace LibHac.FsService
var creators = new FileSystemCreators();
var gameCard = new EmulatedGameCard(keyset);
var gcStorageCreator = new EmulatedGameCardStorageCreator(gameCard);
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(keyset);
creators.GameCardStorageCreator = new EmulatedGameCardStorageCreator(gameCard);
creators.GameCardStorageCreator = gcStorageCreator;
creators.GameCardFileSystemCreator = new EmulatedGameCardFsCreator(gcStorageCreator, gameCard);
creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keyset);
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(rootFileSystem);
creators.SdFileSystemCreator = new EmulatedSdFileSystemCreator(rootFileSystem);

View file

@ -1,6 +1,5 @@
using System;
using LibHac.Fs;
using LibHac.FsSystem;
namespace LibHac.FsService
{
@ -9,6 +8,7 @@ namespace LibHac.FsService
private IStorage CardImageStorage { get; set; }
private int Handle { get; set; }
private XciHeader CardHeader { get; set; }
private Xci CardImage { get; set; }
private Keyset Keyset { get; set; }
public EmulatedGameCard() { }
@ -38,7 +38,8 @@ namespace LibHac.FsService
CardImageStorage = cardImageStorage;
CardHeader = new XciHeader(Keyset, cardImageStorage.AsStream());
CardImage = new Xci(Keyset, cardImageStorage);
CardHeader = CardImage.Header;
}
public void RemoveGameCard()
@ -49,7 +50,17 @@ namespace LibHac.FsService
Handle++;
}
}
internal Result GetXci(out Xci xci, GameCardHandle handle)
{
xci = default;
if (IsGameCardHandleInvalid(handle)) return ResultFs.InvalidGameCardHandleOnRead.Log();
if (!IsGameCardInserted()) return ResultFs.GameCardNotInserted.Log();
xci = CardImage;
return Result.Success;
}
public Result Read(GameCardHandle handle, long offset, Span<byte> destination)
{
if (IsGameCardHandleInvalid(handle)) return ResultFs.InvalidGameCardHandleOnRead.Log();

View file

@ -423,9 +423,12 @@ namespace LibHac.FsService
return FsProxyCore.OpenCustomStorageFileSystem(out fileSystem, storageId);
}
public Result OpenGameCardFileSystem(out IFileSystem fileSystem, GameCardHandle handle, GameCardPartition partitionId)
public Result OpenGameCardFileSystem(out IFileSystem fileSystem, GameCardHandle handle,
GameCardPartition partitionId)
{
throw new NotImplementedException();
// Missing permission check and FileSystemInterfaceAdapter
return FsProxyCore.OpenGameCardFileSystem(out fileSystem, handle, partitionId);
}
public Result QuerySaveDataTotalSize(out long totalSize, long dataSize, long journalSize)

View file

@ -149,6 +149,12 @@ namespace LibHac.FsService
}
}
public Result OpenGameCardFileSystem(out IFileSystem fileSystem, GameCardHandle handle,
GameCardPartition partitionId)
{
return FsCreators.GameCardFileSystemCreator.Create(out fileSystem, handle, partitionId);
}
public Result RegisterExternalKey(ref RightsId rightsId, ref AccessKey externalKey)
{
return ExternalKeys.Add(rightsId, externalKey);