bcat:u: Implement EnumerateDeliveryCacheDirectory (#768)

* bcat:u: Implement EnumerateDeliveryCacheDirectory

Basic implementation `EnumerateDeliveryCacheDirectory` call to `IDeliveryCacheStorageService` according to RE.  (close #622)
I've added some comments in the whole service for when we'll implement a real bcat implementation.
For now, all games who use it isn't playable because of GPU.

* Use Array instead of List

* Add ApplicationLaunchPropertyHelper

* Fix helper

* Fix helper 2

* Fix ApplicationLaunchProperty Default

* Fix ApplicationLaunchProperty 2

* Fix folder
This commit is contained in:
Ac_K 2019-09-10 11:55:28 +02:00 committed by Thomas Guillemard
parent 1ff89d6482
commit 0e93a51030
8 changed files with 125 additions and 33 deletions

View File

@ -1,6 +1,6 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Arp; using Ryujinx.HLE.HOS.Services.Glue;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
using System; using System;
@ -173,26 +173,14 @@ namespace Ryujinx.HLE.HOS.Services.Acc
/* /*
if (nn::arp::detail::IReader::GetApplicationLaunchProperty() == 0xCC9D) // InvalidProcessId if (nn::arp::detail::IReader::GetApplicationLaunchProperty() == 0xCC9D) // InvalidProcessId
{ {
_applicationLaunchProperty = new ApplicationLaunchProperty _applicationLaunchProperty = ApplicationLaunchProperty.Default;
{
TitleId = 0x00;
Version = 0x00;
BaseGameStorageId = 0x03;
UpdateGameStorageId = 0x00;
}
return ResultCode.InvalidArgument; return ResultCode.InvalidArgument;
} }
else else
*/ */
{ {
_applicationLaunchProperty = new ApplicationLaunchProperty _applicationLaunchProperty = ApplicationLaunchProperty.GetByPid(context);
{
TitleId = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleID), 0),
Version = 0x00,
BaseGameStorageId = (byte)StorageId.NandSystem,
UpdateGameStorageId = (byte)StorageId.None
};
} }
Logger.PrintStub(LogClass.ServiceAcc, new { unknown }); Logger.PrintStub(LogClass.ServiceAcc, new { unknown });

View File

@ -1,5 +1,5 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Arp; using Ryujinx.HLE.HOS.Services.Glue;
using Ryujinx.HLE.Utilities; using Ryujinx.HLE.Utilities;
namespace Ryujinx.HLE.HOS.Services.Acc namespace Ryujinx.HLE.HOS.Services.Acc

View File

@ -1,11 +0,0 @@
namespace Ryujinx.HLE.HOS.Services.Arp
{
class ApplicationLaunchProperty
{
public long TitleId;
public int Version;
public byte BaseGameStorageId;
public byte UpdateGameStorageId;
public short Padding;
}
}

View File

@ -1,7 +1,9 @@
using Ryujinx.HLE.HOS.Services.Glue;
namespace Ryujinx.HLE.HOS.Services.Bcat namespace Ryujinx.HLE.HOS.Services.Bcat
{ {
class IBcatService : IpcService class IBcatService : IpcService
{ {
public IBcatService() { } public IBcatService(ApplicationLaunchProperty applicationLaunchProperty) { }
} }
} }

View File

@ -1,7 +1,47 @@
using Ryujinx.HLE.HOS.Services.Glue;
using System;
using System.Text;
namespace Ryujinx.HLE.HOS.Services.Bcat namespace Ryujinx.HLE.HOS.Services.Bcat
{ {
class IDeliveryCacheStorageService : IpcService class IDeliveryCacheStorageService : IpcService
{ {
public IDeliveryCacheStorageService() { } private const int DeliveryCacheDirectoriesLimit = 100;
private const int DeliveryCacheDirectoryNameLength = 32;
private string[] _deliveryCacheDirectories = new string[0];
public IDeliveryCacheStorageService(ServiceCtx context, ApplicationLaunchProperty applicationLaunchProperty)
{
// TODO: Read directories.meta file from the save data (loaded in IServiceCreator) in _deliveryCacheDirectories.
}
[Command(10)]
// EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>)
public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context)
{
long outputPosition = context.Request.ReceiveBuff[0].Position;
long outputSize = context.Request.ReceiveBuff[0].Size;
for (int index = 0; index < _deliveryCacheDirectories.Length; index++)
{
if (index == DeliveryCacheDirectoriesLimit - 1)
{
break;
}
byte[] directoryNameBuffer = Encoding.ASCII.GetBytes(_deliveryCacheDirectories[index]);
Array.Resize(ref directoryNameBuffer, DeliveryCacheDirectoryNameLength);
directoryNameBuffer[DeliveryCacheDirectoryNameLength - 1] = 0x00;
context.Memory.WriteBytes(outputPosition + index * DeliveryCacheDirectoryNameLength, directoryNameBuffer);
}
context.ResponseData.Write(_deliveryCacheDirectories.Length);
return ResultCode.Success;
}
} }
} }

View File

@ -1,3 +1,5 @@
using Ryujinx.HLE.HOS.Services.Glue;
namespace Ryujinx.HLE.HOS.Services.Bcat namespace Ryujinx.HLE.HOS.Services.Bcat
{ {
[Service("bcat:a")] [Service("bcat:a")]
@ -12,9 +14,16 @@ namespace Ryujinx.HLE.HOS.Services.Bcat
// CreateBcatService(u64, pid) -> object<nn::bcat::detail::ipc::IBcatService> // CreateBcatService(u64, pid) -> object<nn::bcat::detail::ipc::IBcatService>
public ResultCode CreateBcatService(ServiceCtx context) public ResultCode CreateBcatService(ServiceCtx context)
{ {
long id = context.RequestData.ReadInt64(); // TODO: Call arp:r GetApplicationLaunchProperty with the pid to get the TitleId.
// Add an instance of nn::bcat::detail::service::core::PassphraseManager.
// Add an instance of nn::bcat::detail::service::ServiceMemoryManager.
// Add an instance of nn::bcat::detail::service::core::TaskManager who load "bcat-sys:/" system save data and open "dc/task.bin".
// If the file don't exist, create a new one (size of 0x800) and write 2 empty struct with a size of 0x400.
MakeObject(context, new IBcatService()); MakeObject(context, new IBcatService(ApplicationLaunchProperty.GetByPid(context)));
// NOTE: If the IBcatService is null this error is returned, Doesn't occur in our case.
// return ResultCode.NullObject;
return ResultCode.Success; return ResultCode.Success;
} }
@ -23,9 +32,16 @@ namespace Ryujinx.HLE.HOS.Services.Bcat
// CreateDeliveryCacheStorageService(u64, pid) -> object<nn::bcat::detail::ipc::IDeliveryCacheStorageService> // CreateDeliveryCacheStorageService(u64, pid) -> object<nn::bcat::detail::ipc::IDeliveryCacheStorageService>
public ResultCode CreateDeliveryCacheStorageService(ServiceCtx context) public ResultCode CreateDeliveryCacheStorageService(ServiceCtx context)
{ {
long id = context.RequestData.ReadInt64(); // TODO: Call arp:r GetApplicationLaunchProperty with the pid to get the TitleId.
// Add an instance of nn::bcat::detail::service::core::ApplicationStorageManager who load "bcat-dc-X:/" system save data,
// return ResultCode.NullSaveData if failed.
// Where X depend of the ApplicationLaunchProperty stored in an array (range 0-3).
// Add an instance of nn::bcat::detail::service::ServiceMemoryManager.
MakeObject(context, new IDeliveryCacheStorageService()); MakeObject(context, new IDeliveryCacheStorageService(context, ApplicationLaunchProperty.GetByPid(context)));
// NOTE: If the IDeliveryCacheStorageService is null this error is returned, Doesn't occur in our case.
// return ResultCode.NullObject;
return ResultCode.Success; return ResultCode.Success;
} }

View File

@ -0,0 +1,14 @@
namespace Ryujinx.HLE.HOS.Services.Bcat
{
enum ResultCode
{
ModuleId = 122,
ErrorCodeShift = 9,
Success = 0,
NullArgument = (2 << ErrorCodeShift) | ModuleId,
NullSaveData = (31 << ErrorCodeShift) | ModuleId,
NullObject = (91 << ErrorCodeShift) | ModuleId
}
}

View File

@ -0,0 +1,43 @@
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.Utilities;
using System;
namespace Ryujinx.HLE.HOS.Services.Glue
{
class ApplicationLaunchProperty
{
public long TitleId;
public int Version;
public byte BaseGameStorageId;
public byte UpdateGameStorageId;
public short Padding;
public static ApplicationLaunchProperty Default
{
get
{
return new ApplicationLaunchProperty
{
TitleId = 0x00,
Version = 0x00,
BaseGameStorageId = (byte)StorageId.NandSystem,
UpdateGameStorageId = (byte)StorageId.None
};
}
}
public static ApplicationLaunchProperty GetByPid(ServiceCtx context)
{
// TODO: Handle ApplicationLaunchProperty as array when pid will be supported and return the right item.
// For now we can hardcode values, and fix it after GetApplicationLaunchProperty is implemented.
return new ApplicationLaunchProperty
{
TitleId = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleID), 0),
Version = 0x00,
BaseGameStorageId = (byte)StorageId.NandSystem,
UpdateGameStorageId = (byte)StorageId.None
};
}
}
}