forked from Mirror/Ryujinx
no name: Mii Editor applet support (#2419)
* no name: Mii Editor applet support * addresses gdkchan feedback * Fix comment * Bypass MountCounter of MiiDatabaseManager * Fix GetSettingsPlatformRegion * Disable Applet Menu for unsupported firmwares
This commit is contained in:
parent
fefd4619a5
commit
a79b39b913
27 changed files with 591 additions and 33 deletions
|
@ -37,6 +37,7 @@ namespace Ryujinx.Common.Logging
|
||||||
ServiceLdn,
|
ServiceLdn,
|
||||||
ServiceLdr,
|
ServiceLdr,
|
||||||
ServiceLm,
|
ServiceLm,
|
||||||
|
ServiceMii,
|
||||||
ServiceMm,
|
ServiceMm,
|
||||||
ServiceNfc,
|
ServiceNfc,
|
||||||
ServiceNfp,
|
ServiceNfp,
|
||||||
|
|
|
@ -45,10 +45,11 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public class Horizon : IDisposable
|
public class Horizon : IDisposable
|
||||||
{
|
{
|
||||||
internal const int HidSize = 0x40000;
|
internal const int HidSize = 0x40000;
|
||||||
internal const int FontSize = 0x1100000;
|
internal const int FontSize = 0x1100000;
|
||||||
internal const int IirsSize = 0x8000;
|
internal const int IirsSize = 0x8000;
|
||||||
internal const int TimeSize = 0x1000;
|
internal const int TimeSize = 0x1000;
|
||||||
|
internal const int AppletCaptureBufferSize = 0x384000;
|
||||||
|
|
||||||
internal KernelContext KernelContext { get; }
|
internal KernelContext KernelContext { get; }
|
||||||
|
|
||||||
|
@ -82,6 +83,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
internal KSharedMemory HidSharedMem { get; private set; }
|
internal KSharedMemory HidSharedMem { get; private set; }
|
||||||
internal KSharedMemory FontSharedMem { get; private set; }
|
internal KSharedMemory FontSharedMem { get; private set; }
|
||||||
internal KSharedMemory IirsSharedMem { get; private set; }
|
internal KSharedMemory IirsSharedMem { get; private set; }
|
||||||
|
|
||||||
|
internal KTransferMemory AppletCaptureBufferTransfer { get; private set; }
|
||||||
|
|
||||||
internal SharedFontManager Font { get; private set; }
|
internal SharedFontManager Font { get; private set; }
|
||||||
|
|
||||||
internal AccountManager AccountManager { get; private set; }
|
internal AccountManager AccountManager { get; private set; }
|
||||||
|
@ -129,25 +133,29 @@ namespace Ryujinx.HLE.HOS
|
||||||
// region used that is used is Application, so we can use the other ones for anything.
|
// region used that is used is Application, so we can use the other ones for anything.
|
||||||
KMemoryRegionManager region = KernelContext.MemoryManager.MemoryRegions[(int)MemoryRegion.NvServices];
|
KMemoryRegionManager region = KernelContext.MemoryManager.MemoryRegions[(int)MemoryRegion.NvServices];
|
||||||
|
|
||||||
ulong hidPa = region.Address;
|
ulong hidPa = region.Address;
|
||||||
ulong fontPa = region.Address + HidSize;
|
ulong fontPa = region.Address + HidSize;
|
||||||
ulong iirsPa = region.Address + HidSize + FontSize;
|
ulong iirsPa = region.Address + HidSize + FontSize;
|
||||||
ulong timePa = region.Address + HidSize + FontSize + IirsSize;
|
ulong timePa = region.Address + HidSize + FontSize + IirsSize;
|
||||||
|
ulong appletCaptureBufferPa = region.Address + HidSize + FontSize + IirsSize + TimeSize;
|
||||||
|
|
||||||
KPageList hidPageList = new KPageList();
|
KPageList hidPageList = new KPageList();
|
||||||
KPageList fontPageList = new KPageList();
|
KPageList fontPageList = new KPageList();
|
||||||
KPageList iirsPageList = new KPageList();
|
KPageList iirsPageList = new KPageList();
|
||||||
KPageList timePageList = new KPageList();
|
KPageList timePageList = new KPageList();
|
||||||
|
KPageList appletCaptureBufferPageList = new KPageList();
|
||||||
|
|
||||||
hidPageList.AddRange(hidPa, HidSize / KPageTableBase.PageSize);
|
hidPageList.AddRange(hidPa, HidSize / KPageTableBase.PageSize);
|
||||||
fontPageList.AddRange(fontPa, FontSize / KPageTableBase.PageSize);
|
fontPageList.AddRange(fontPa, FontSize / KPageTableBase.PageSize);
|
||||||
iirsPageList.AddRange(iirsPa, IirsSize / KPageTableBase.PageSize);
|
iirsPageList.AddRange(iirsPa, IirsSize / KPageTableBase.PageSize);
|
||||||
timePageList.AddRange(timePa, TimeSize / KPageTableBase.PageSize);
|
timePageList.AddRange(timePa, TimeSize / KPageTableBase.PageSize);
|
||||||
|
appletCaptureBufferPageList.AddRange(appletCaptureBufferPa, AppletCaptureBufferSize / KPageTableBase.PageSize);
|
||||||
|
|
||||||
var hidStorage = new SharedMemoryStorage(KernelContext, hidPageList);
|
var hidStorage = new SharedMemoryStorage(KernelContext, hidPageList);
|
||||||
var fontStorage = new SharedMemoryStorage(KernelContext, fontPageList);
|
var fontStorage = new SharedMemoryStorage(KernelContext, fontPageList);
|
||||||
var iirsStorage = new SharedMemoryStorage(KernelContext, iirsPageList);
|
var iirsStorage = new SharedMemoryStorage(KernelContext, iirsPageList);
|
||||||
var timeStorage = new SharedMemoryStorage(KernelContext, timePageList);
|
var timeStorage = new SharedMemoryStorage(KernelContext, timePageList);
|
||||||
|
var appletCaptureBufferStorage = new SharedMemoryStorage(KernelContext, appletCaptureBufferPageList);
|
||||||
|
|
||||||
HidStorage = hidStorage;
|
HidStorage = hidStorage;
|
||||||
|
|
||||||
|
@ -159,6 +167,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timeStorage, TimeSize);
|
TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timeStorage, TimeSize);
|
||||||
|
|
||||||
|
AppletCaptureBufferTransfer = new KTransferMemory(KernelContext, appletCaptureBufferStorage);
|
||||||
|
|
||||||
AppletState = new AppletStateMgr(this);
|
AppletState = new AppletStateMgr(this);
|
||||||
|
|
||||||
AppletState.SetFocus(true);
|
AppletState.SetFocus(true);
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
|
||||||
|
{
|
||||||
|
class ILibraryAppletProxy : IpcService
|
||||||
|
{
|
||||||
|
private readonly long _pid;
|
||||||
|
|
||||||
|
public ILibraryAppletProxy(long pid)
|
||||||
|
{
|
||||||
|
_pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(0)]
|
||||||
|
// GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
|
||||||
|
public ResultCode GetCommonStateGetter(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new ICommonStateGetter(context));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(1)]
|
||||||
|
// GetSelfController() -> object<nn::am::service::ISelfController>
|
||||||
|
public ResultCode GetSelfController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new ISelfController(context, _pid));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(2)]
|
||||||
|
// GetWindowController() -> object<nn::am::service::IWindowController>
|
||||||
|
public ResultCode GetWindowController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IWindowController(_pid));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(3)]
|
||||||
|
// GetAudioController() -> object<nn::am::service::IAudioController>
|
||||||
|
public ResultCode GetAudioController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IAudioController());
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(4)]
|
||||||
|
// GetDisplayController() -> object<nn::am::service::IDisplayController>
|
||||||
|
public ResultCode GetDisplayController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IDisplayController(context));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(10)]
|
||||||
|
// GetProcessWindingController() -> object<nn::am::service::IProcessWindingController>
|
||||||
|
public ResultCode GetProcessWindingController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IProcessWindingController());
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(11)]
|
||||||
|
// GetLibraryAppletCreator() -> object<nn::am::service::ILibraryAppletCreator>
|
||||||
|
public ResultCode GetLibraryAppletCreator(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryAppletCreator());
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(20)]
|
||||||
|
// OpenLibraryAppletSelfAccessor() -> object<nn::am::service::ILibraryAppletSelfAccessor>
|
||||||
|
public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryAppletSelfAccessor(context));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(21)]
|
||||||
|
// GetAppletCommonFunctions() -> object<nn::am::service::IAppletCommonFunctions>
|
||||||
|
public ResultCode GetAppletCommonFunctions(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IAppletCommonFunctions());
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(1000)]
|
||||||
|
// GetDebugFunctions() -> object<nn::am::service::IDebugFunctions>
|
||||||
|
public ResultCode GetDebugFunctions(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new IDebugFunctions());
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
|
||||||
// GetSelfController() -> object<nn::am::service::ISelfController>
|
// GetSelfController() -> object<nn::am::service::ISelfController>
|
||||||
public ResultCode GetSelfController(ServiceCtx context)
|
public ResultCode GetSelfController(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISelfController(context.Device.System, _pid));
|
MakeObject(context, new ISelfController(context, _pid));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
|
||||||
// GetDisplayController() -> object<nn::am::service::IDisplayController>
|
// GetDisplayController() -> object<nn::am::service::IDisplayController>
|
||||||
public ResultCode GetDisplayController(ServiceCtx context)
|
public ResultCode GetDisplayController(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new IDisplayController());
|
MakeObject(context, new IDisplayController(context));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
|
||||||
|
{
|
||||||
|
class AppletStandalone
|
||||||
|
{
|
||||||
|
public AppletId AppletId;
|
||||||
|
public LibraryAppletMode LibraryAppletMode;
|
||||||
|
public Queue<byte[]> InputData;
|
||||||
|
|
||||||
|
public AppletStandalone()
|
||||||
|
{
|
||||||
|
InputData = new Queue<byte[]>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
|
||||||
|
{
|
||||||
|
class ILibraryAppletSelfAccessor : IpcService
|
||||||
|
{
|
||||||
|
private AppletStandalone _appletStandalone = new AppletStandalone();
|
||||||
|
|
||||||
|
public ILibraryAppletSelfAccessor(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (context.Device.Application.TitleId == 0x0100000000001009)
|
||||||
|
{
|
||||||
|
// Create MiiEdit data.
|
||||||
|
_appletStandalone = new AppletStandalone()
|
||||||
|
{
|
||||||
|
AppletId = AppletId.MiiEdit,
|
||||||
|
LibraryAppletMode = LibraryAppletMode.AllForeground
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] miiEditInputData = new byte[0x100];
|
||||||
|
miiEditInputData[0] = 0x03; // Hardcoded unknown value.
|
||||||
|
|
||||||
|
_appletStandalone.InputData.Enqueue(miiEditInputData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"{context.Device.Application.TitleId} applet is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(0)]
|
||||||
|
// PopInData() -> object<nn::am::service::IStorage>
|
||||||
|
public ResultCode PopInData(ServiceCtx context)
|
||||||
|
{
|
||||||
|
byte[] appletData = _appletStandalone.InputData.Dequeue();
|
||||||
|
|
||||||
|
if (appletData.Length == 0)
|
||||||
|
{
|
||||||
|
return ResultCode.NotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeObject(context, new IStorage(appletData));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(11)]
|
||||||
|
// GetLibraryAppletInfo() -> nn::am::service::LibraryAppletInfo
|
||||||
|
public ResultCode GetLibraryAppletInfo(ServiceCtx context)
|
||||||
|
{
|
||||||
|
LibraryAppletInfo libraryAppletInfo = new LibraryAppletInfo()
|
||||||
|
{
|
||||||
|
AppletId = _appletStandalone.AppletId,
|
||||||
|
LibraryAppletMode = _appletStandalone.LibraryAppletMode
|
||||||
|
};
|
||||||
|
|
||||||
|
context.ResponseData.WriteStruct(libraryAppletInfo);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(14)]
|
||||||
|
// GetCallerAppletIdentityInfo() -> nn::am::service::AppletIdentityInfo
|
||||||
|
public ResultCode GetCallerAppletIdentityInfo(ServiceCtx context)
|
||||||
|
{
|
||||||
|
AppletIdentifyInfo appletIdentifyInfo = new AppletIdentifyInfo()
|
||||||
|
{
|
||||||
|
AppletId = AppletId.QLaunch,
|
||||||
|
TitleId = 0x0100000000001000
|
||||||
|
};
|
||||||
|
|
||||||
|
context.ResponseData.WriteStruct(appletIdentifyInfo);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Ryujinx.Common;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
|
||||||
|
{
|
||||||
|
class IProcessWindingController : IpcService
|
||||||
|
{
|
||||||
|
public IProcessWindingController() { }
|
||||||
|
|
||||||
|
[CommandHipc(0)]
|
||||||
|
// GetLaunchReason() -> nn::am::service::AppletProcessLaunchReason
|
||||||
|
public ResultCode GetLaunchReason(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// NOTE: Flag is set by using an internal field.
|
||||||
|
AppletProcessLaunchReason appletProcessLaunchReason = new AppletProcessLaunchReason()
|
||||||
|
{
|
||||||
|
Flag = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
context.ResponseData.WriteStruct(appletProcessLaunchReason);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
{
|
||||||
|
class IAppletCommonFunctions : IpcService
|
||||||
|
{
|
||||||
|
public IAppletCommonFunctions() { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Settings.Types;
|
||||||
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
|
@ -241,6 +243,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
return (ResultCode)_apmSystemManagerServer.GetCurrentPerformanceConfiguration(context);
|
return (ResultCode)_apmSystemManagerServer.GetCurrentPerformanceConfiguration(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(300)] // 9.0.0+
|
||||||
|
// GetSettingsPlatformRegion() -> u8
|
||||||
|
public ResultCode GetSettingsPlatformRegion(ServiceCtx context)
|
||||||
|
{
|
||||||
|
PlatformRegion platformRegion = context.Device.System.State.DesiredRegionCode == (uint)RegionCode.China ? PlatformRegion.China : PlatformRegion.Global;
|
||||||
|
|
||||||
|
// FIXME: Call set:sys GetPlatformRegion
|
||||||
|
context.ResponseData.Write((byte)platformRegion);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(900)] // 11.0.0+
|
[CommandHipc(900)] // 11.0.0+
|
||||||
// SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled()
|
// SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled()
|
||||||
public ResultCode SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(ServiceCtx context)
|
public ResultCode SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(ServiceCtx context)
|
||||||
|
|
|
@ -1,7 +1,106 @@
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||||
{
|
{
|
||||||
class IDisplayController : IpcService
|
class IDisplayController : IpcService
|
||||||
{
|
{
|
||||||
public IDisplayController() { }
|
private KTransferMemory _transferMem;
|
||||||
|
private bool _lastApplicationCaptureBufferAcquired;
|
||||||
|
private bool _callerAppletCaptureBufferAcquired;
|
||||||
|
|
||||||
|
public IDisplayController(ServiceCtx context)
|
||||||
|
{
|
||||||
|
_transferMem = context.Device.System.AppletCaptureBufferTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(8)] // 2.0.0+
|
||||||
|
// TakeScreenShotOfOwnLayer(b8, s32)
|
||||||
|
public ResultCode TakeScreenShotOfOwnLayer(ServiceCtx context)
|
||||||
|
{
|
||||||
|
bool unknown1 = context.RequestData.ReadBoolean();
|
||||||
|
int unknown2 = context.RequestData.ReadInt32();
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { unknown1, unknown2 });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(11)]
|
||||||
|
// ReleaseLastApplicationCaptureBuffer()
|
||||||
|
public ResultCode ReleaseLastApplicationCaptureBuffer(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (!_lastApplicationCaptureBufferAcquired)
|
||||||
|
{
|
||||||
|
return ResultCode.BufferNotAcquired;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastApplicationCaptureBufferAcquired = false;
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(15)]
|
||||||
|
// ReleaseCallerAppletCaptureBuffer()
|
||||||
|
public ResultCode ReleaseCallerAppletCaptureBuffer(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (!_callerAppletCaptureBufferAcquired)
|
||||||
|
{
|
||||||
|
return ResultCode.BufferNotAcquired;
|
||||||
|
}
|
||||||
|
|
||||||
|
_callerAppletCaptureBufferAcquired = false;
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(16)]
|
||||||
|
// AcquireLastApplicationCaptureBufferEx() -> (b8, handle<copy>)
|
||||||
|
public ResultCode AcquireLastApplicationCaptureBufferEx(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_lastApplicationCaptureBufferAcquired)
|
||||||
|
{
|
||||||
|
return ResultCode.BufferAlreadyAcquired;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||||
|
|
||||||
|
_lastApplicationCaptureBufferAcquired = true;
|
||||||
|
|
||||||
|
context.ResponseData.Write(_lastApplicationCaptureBufferAcquired);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(18)]
|
||||||
|
// AcquireCallerAppletCaptureBufferEx() -> (b8, handle<copy>)
|
||||||
|
public ResultCode AcquireCallerAppletCaptureBufferEx(ServiceCtx context)
|
||||||
|
{
|
||||||
|
if (_callerAppletCaptureBufferAcquired)
|
||||||
|
{
|
||||||
|
return ResultCode.BufferAlreadyAcquired;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
|
||||||
|
|
||||||
|
_callerAppletCaptureBufferAcquired = true;
|
||||||
|
|
||||||
|
context.ResponseData.Write(_callerAppletCaptureBufferAcquired);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,9 +35,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
private uint _screenShotImageOrientation = 0;
|
private uint _screenShotImageOrientation = 0;
|
||||||
private uint _idleTimeDetectionExtension = 0;
|
private uint _idleTimeDetectionExtension = 0;
|
||||||
|
|
||||||
public ISelfController(Horizon system, long pid)
|
public ISelfController(ServiceCtx context, long pid)
|
||||||
{
|
{
|
||||||
_libraryAppletLaunchableEvent = new KEvent(system.KernelContext);
|
_libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
|
||||||
_pid = pid;
|
_pid = pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(41)] // 4.0.0+
|
||||||
|
// IsSystemBufferSharingEnabled()
|
||||||
|
public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// NOTE: Service checks a private field and return an error if the SystemBufferSharing is disabled.
|
||||||
|
|
||||||
|
return ResultCode.NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(44)] // 10.0.0+
|
[CommandHipc(44)] // 10.0.0+
|
||||||
// CreateManagedDisplaySeparableLayer() -> (u64, u64)
|
// CreateManagedDisplaySeparableLayer() -> (u64, u64)
|
||||||
public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
|
public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
|
||||||
|
|
|
@ -15,5 +15,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(200)]
|
||||||
|
[CommandHipc(201)] // 3.0.0+
|
||||||
|
// OpenLibraryAppletProxy(u64, pid, handle<copy>) -> object<nn::am::service::ILibraryAppletProxy>
|
||||||
|
public ResultCode OpenLibraryAppletProxy(ServiceCtx context)
|
||||||
|
{
|
||||||
|
MakeObject(context, new ILibraryAppletProxy(context.Request.HandleDesc.PId));
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
|
||||||
|
struct AppletIdentifyInfo
|
||||||
|
{
|
||||||
|
public AppletId AppletId;
|
||||||
|
public uint Padding;
|
||||||
|
public ulong TitleId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 0x4)]
|
||||||
|
struct AppletProcessLaunchReason
|
||||||
|
{
|
||||||
|
public byte Flag;
|
||||||
|
public ushort Unknown1;
|
||||||
|
public byte Unknown2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 0x8)]
|
||||||
|
struct LibraryAppletInfo
|
||||||
|
{
|
||||||
|
public AppletId AppletId;
|
||||||
|
public LibraryAppletMode LibraryAppletMode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
enum LibraryAppletMode : uint
|
||||||
|
{
|
||||||
|
AllForeground,
|
||||||
|
PartialForeground,
|
||||||
|
NoUi,
|
||||||
|
PartialForegroundWithIndirectDisplay,
|
||||||
|
AllForegroundInitiallyHidden
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
|
||||||
// GetSelfController() -> object<nn::am::service::ISelfController>
|
// GetSelfController() -> object<nn::am::service::ISelfController>
|
||||||
public ResultCode GetSelfController(ServiceCtx context)
|
public ResultCode GetSelfController(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISelfController(context.Device.System, _pid));
|
MakeObject(context, new ISelfController(context, _pid));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
|
||||||
// GetDisplayController() -> object<nn::am::service::IDisplayController>
|
// GetDisplayController() -> object<nn::am::service::IDisplayController>
|
||||||
public ResultCode GetDisplayController(ServiceCtx context)
|
public ResultCode GetDisplayController(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new IDisplayController());
|
MakeObject(context, new IDisplayController(context));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
ObjectInvalid = (500 << ErrorCodeShift) | ModuleId,
|
ObjectInvalid = (500 << ErrorCodeShift) | ModuleId,
|
||||||
IStorageInUse = (502 << ErrorCodeShift) | ModuleId,
|
IStorageInUse = (502 << ErrorCodeShift) | ModuleId,
|
||||||
OutOfBounds = (503 << ErrorCodeShift) | ModuleId,
|
OutOfBounds = (503 << ErrorCodeShift) | ModuleId,
|
||||||
|
BufferNotAcquired = (504 << ErrorCodeShift) | ModuleId,
|
||||||
|
BufferAlreadyAcquired = (505 << ErrorCodeShift) | ModuleId,
|
||||||
InvalidParameters = (506 << ErrorCodeShift) | ModuleId,
|
InvalidParameters = (506 << ErrorCodeShift) | ModuleId,
|
||||||
OpenedAsWrongType = (511 << ErrorCodeShift) | ModuleId,
|
OpenedAsWrongType = (511 << ErrorCodeShift) | ModuleId,
|
||||||
UnbalancedFatalSection = (512 << ErrorCodeShift) | ModuleId,
|
UnbalancedFatalSection = (512 << ErrorCodeShift) | ModuleId,
|
||||||
|
|
|
@ -499,6 +499,15 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
||||||
return (ResultCode)result.Value;
|
return (ResultCode)result.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(1003)]
|
||||||
|
// DisableAutoSaveDataCreation()
|
||||||
|
public ResultCode DisableAutoSaveDataCreation(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// NOTE: This call does nothing in original service.
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(1004)]
|
[CommandHipc(1004)]
|
||||||
// SetGlobalAccessLogMode(u32 mode)
|
// SetGlobalAccessLogMode(u32 mode)
|
||||||
public ResultCode SetGlobalAccessLogMode(ServiceCtx context)
|
public ResultCode SetGlobalAccessLogMode(ServiceCtx context)
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||||
public static UInt128 GetDeviceId()
|
public static UInt128 GetDeviceId()
|
||||||
{
|
{
|
||||||
// FIXME: call set:sys GetMiiAuthorId
|
// FIXME: call set:sys GetMiiAuthorId
|
||||||
return new UInt128(0, 1);
|
return new UInt128("5279754d69694e780000000000000000"); // RyuMiiNx
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 };
|
public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 };
|
||||||
|
|
|
@ -1,8 +1,41 @@
|
||||||
namespace Ryujinx.HLE.HOS.Services.Mii
|
using Ryujinx.Common.Logging;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Mii
|
||||||
{
|
{
|
||||||
[Service("miiimg")] // 5.0.0+
|
[Service("miiimg")] // 5.0.0+
|
||||||
class IImageDatabaseService : IpcService
|
class IImageDatabaseService : IpcService
|
||||||
{
|
{
|
||||||
|
private uint _imageCount;
|
||||||
|
private bool _isDirty;
|
||||||
|
|
||||||
public IImageDatabaseService(ServiceCtx context) { }
|
public IImageDatabaseService(ServiceCtx context) { }
|
||||||
|
|
||||||
|
[CommandHipc(0)]
|
||||||
|
// Initialize(b8) -> b8
|
||||||
|
public ResultCode Initialize(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// TODO: Service uses MiiImage:/database.dat if true, seems to use hardcoded data if false.
|
||||||
|
bool useHardcodedData = context.RequestData.ReadBoolean();
|
||||||
|
|
||||||
|
_imageCount = 0;
|
||||||
|
_isDirty = false;
|
||||||
|
|
||||||
|
context.ResponseData.Write(_isDirty);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceMii, new { useHardcodedData });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(11)]
|
||||||
|
// GetCount() -> u32
|
||||||
|
public ResultCode GetCount(ServiceCtx context)
|
||||||
|
{
|
||||||
|
context.ResponseData.Write(_imageCount);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceMii);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -101,6 +101,9 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||||
// Ensure we have valid data in the database
|
// Ensure we have valid data in the database
|
||||||
_database.Format();
|
_database.Format();
|
||||||
|
|
||||||
|
// TODO: Unmount is currently not implemented properly at dispose, implement that and decrement MountCounter.
|
||||||
|
MountCounter = 0;
|
||||||
|
|
||||||
MountSave();
|
MountSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,8 +154,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +184,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||||
if (result.IsSuccess())
|
if (result.IsSuccess())
|
||||||
{
|
{
|
||||||
result = _filesystemClient.GetFileSize(out long fileSize, handle);
|
result = _filesystemClient.GetFileSize(out long fileSize, handle);
|
||||||
|
|
||||||
if (result.IsSuccess())
|
if (result.IsSuccess())
|
||||||
{
|
{
|
||||||
if (fileSize == Unsafe.SizeOf<NintendoFigurineDatabase>())
|
if (fileSize == Unsafe.SizeOf<NintendoFigurineDatabase>())
|
||||||
|
|
|
@ -7,6 +7,7 @@ using LibHac.FsSystem.NcaUtils;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using Ryujinx.HLE.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -271,6 +272,20 @@ namespace Ryujinx.HLE.HOS.Services.Settings
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(90)]
|
||||||
|
// GetMiiAuthorId() -> nn::util::Uuid
|
||||||
|
public ResultCode GetMiiAuthorId(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// NOTE: If miiAuthorId is null ResultCode.NullMiiAuthorIdBuffer is returned.
|
||||||
|
// Doesn't occur in our case.
|
||||||
|
|
||||||
|
UInt128 miiAuthorId = Mii.Helper.GetDeviceId();
|
||||||
|
|
||||||
|
miiAuthorId.Write(context.ResponseData);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] GetFirmwareData(Switch device)
|
public byte[] GetFirmwareData(Switch device)
|
||||||
{
|
{
|
||||||
const ulong SystemVersionTitleId = 0x0100000000000809;
|
const ulong SystemVersionTitleId = 0x0100000000000809;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Settings.Types
|
||||||
|
{
|
||||||
|
enum PlatformRegion
|
||||||
|
{
|
||||||
|
Global = 1,
|
||||||
|
China = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,11 +55,11 @@ namespace Ryujinx.HLE.HOS.SystemState
|
||||||
|
|
||||||
DesiredTitleLanguage = language switch
|
DesiredTitleLanguage = language switch
|
||||||
{
|
{
|
||||||
SystemLanguage.Taiwanese or
|
SystemLanguage.Taiwanese => TitleLanguage.Taiwanese,
|
||||||
SystemLanguage.TraditionalChinese => TitleLanguage.Taiwanese,
|
SystemLanguage.TraditionalChinese or
|
||||||
SystemLanguage.Chinese or
|
SystemLanguage.Chinese or
|
||||||
SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese,
|
SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese,
|
||||||
_ => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)),
|
_ => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.Translation.PTC;
|
||||||
using Gtk;
|
using Gtk;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
|
using LibHac.FsSystem.NcaUtils;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using Ryujinx.Audio.Backends.Dummy;
|
using Ryujinx.Audio.Backends.Dummy;
|
||||||
using Ryujinx.Audio.Backends.OpenAL;
|
using Ryujinx.Audio.Backends.OpenAL;
|
||||||
|
@ -87,6 +88,10 @@ namespace Ryujinx.Ui
|
||||||
[GUI] Box _statusBar;
|
[GUI] Box _statusBar;
|
||||||
[GUI] MenuItem _optionMenu;
|
[GUI] MenuItem _optionMenu;
|
||||||
[GUI] MenuItem _manageUserProfiles;
|
[GUI] MenuItem _manageUserProfiles;
|
||||||
|
[GUI] MenuItem _fileMenu;
|
||||||
|
[GUI] MenuItem _loadApplicationFile;
|
||||||
|
[GUI] MenuItem _loadApplicationFolder;
|
||||||
|
[GUI] MenuItem _appletMenu;
|
||||||
[GUI] MenuItem _actionMenu;
|
[GUI] MenuItem _actionMenu;
|
||||||
[GUI] MenuItem _stopEmulation;
|
[GUI] MenuItem _stopEmulation;
|
||||||
[GUI] MenuItem _simulateWakeUpMessage;
|
[GUI] MenuItem _simulateWakeUpMessage;
|
||||||
|
@ -165,6 +170,7 @@ namespace Ryujinx.Ui
|
||||||
_applicationLibrary.ApplicationAdded += Application_Added;
|
_applicationLibrary.ApplicationAdded += Application_Added;
|
||||||
_applicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
|
_applicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
|
||||||
|
|
||||||
|
_fileMenu.StateChanged += FileMenu_StateChanged;
|
||||||
_actionMenu.StateChanged += ActionMenu_StateChanged;
|
_actionMenu.StateChanged += ActionMenu_StateChanged;
|
||||||
_optionMenu.StateChanged += OptionMenu_StateChanged;
|
_optionMenu.StateChanged += OptionMenu_StateChanged;
|
||||||
|
|
||||||
|
@ -575,7 +581,15 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
|
SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
|
||||||
|
|
||||||
bool isDirectory = Directory.Exists(path);
|
bool isDirectory = Directory.Exists(path);
|
||||||
|
bool isFirmwareTitle = false;
|
||||||
|
|
||||||
|
if (path.StartsWith("@SystemContent"))
|
||||||
|
{
|
||||||
|
path = _virtualFileSystem.SwitchPathToSystemPath(path);
|
||||||
|
|
||||||
|
isFirmwareTitle = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError))
|
if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError))
|
||||||
{
|
{
|
||||||
|
@ -636,7 +650,13 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
|
Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
|
||||||
|
|
||||||
if (Directory.Exists(path))
|
if (isFirmwareTitle)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
|
||||||
|
|
||||||
|
_emulationContext.LoadNca(path);
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(path))
|
||||||
{
|
{
|
||||||
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
|
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
|
||||||
|
|
||||||
|
@ -1100,6 +1120,20 @@ namespace Ryujinx.Ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FileMenu_StateChanged(object o, StateChangedArgs args)
|
||||||
|
{
|
||||||
|
_appletMenu.Sensitive = _emulationContext == null && _contentManager.GetCurrentFirmwareVersion() != null && _contentManager.GetCurrentFirmwareVersion().Major > 3;
|
||||||
|
_loadApplicationFile.Sensitive = _emulationContext == null;
|
||||||
|
_loadApplicationFolder.Sensitive = _emulationContext == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Load_Mii_Edit_Applet(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.NandSystem, NcaContentType.Program);
|
||||||
|
|
||||||
|
LoadApplication(contentPath);
|
||||||
|
}
|
||||||
|
|
||||||
private void Open_Ryu_Folder(object sender, EventArgs args)
|
private void Open_Ryu_Folder(object sender, EventArgs args)
|
||||||
{
|
{
|
||||||
OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
|
OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
|
||||||
|
@ -1217,6 +1251,15 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
GtkDialog.CreateInfoDialog(dialogTitle, message);
|
GtkDialog.CreateInfoDialog(dialogTitle, message);
|
||||||
Logger.Info?.Print(LogClass.Application, message);
|
Logger.Info?.Print(LogClass.Application, message);
|
||||||
|
|
||||||
|
// Purge Applet Cache.
|
||||||
|
|
||||||
|
DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
|
||||||
|
|
||||||
|
if (miiEditorCacheFolder.Exists)
|
||||||
|
{
|
||||||
|
miiEditorCacheFolder.Delete(true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="FileMenu">
|
<object class="GtkMenuItem" id="_fileMenu">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">File</property>
|
<property name="label" translatable="yes">File</property>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="LoadApplicationFile">
|
<object class="GtkMenuItem" id="_loadApplicationFile">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible file to load</property>
|
<property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible file to load</property>
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="LoadApplicationFolder">
|
<object class="GtkMenuItem" id="_loadApplicationFolder">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible, unpacked application to load</property>
|
<property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible, unpacked application to load</property>
|
||||||
|
@ -48,6 +48,30 @@
|
||||||
<signal name="activate" handler="Load_Application_Folder" swapped="no"/>
|
<signal name="activate" handler="Load_Application_Folder" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="_appletMenu">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Load Applet</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<child type="submenu">
|
||||||
|
<object class="GtkMenu">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuItem" id="LoadMiiEditApplet">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Open Mii Editor Applet in Standalone mode</property>
|
||||||
|
<property name="label" translatable="yes">Mii Editor</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<signal name="activate" handler="Load_Mii_Edit_Applet" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkSeparatorMenuItem">
|
<object class="GtkSeparatorMenuItem">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
Reference in a new issue