MeloNX/src/LibRyujinx/LibRyujinx.Device.cs
2024-01-22 22:55:30 +00:00

217 lines
7.1 KiB
C#

using ARMeilleure.Translation;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input.HLE;
using Silk.NET.Vulkan;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace LibRyujinx
{
public static partial class LibRyujinx
{
[UnmanagedCallersOnly(EntryPoint = "device_initialize")]
public static bool InitializeDeviceNative()
{
return InitializeDevice(true, false, SystemLanguage.AmericanEnglish, RegionCode.USA, true, true, true, false, "UTC", false);
}
[UnmanagedCallersOnly(EntryPoint = "device_reloadFilesystem")]
public static void ReloadFileSystem()
{
SwitchDevice?.ReloadFileSystem();
}
public static bool InitializeDevice(bool isHostMapped,
bool useNce,
SystemLanguage systemLanguage,
RegionCode regionCode,
bool enableVsync,
bool enableDockedMode,
bool enablePtc,
bool enableInternetAccess,
string? timeZone,
bool ignoreMissingServices)
{
if (SwitchDevice == null)
{
return false;
}
return SwitchDevice.InitializeContext(isHostMapped,
useNce,
systemLanguage,
regionCode,
enableVsync,
enableDockedMode,
enablePtc,
enableInternetAccess,
timeZone,
ignoreMissingServices);
}
[UnmanagedCallersOnly(EntryPoint = "device_load")]
public static bool LoadApplicationNative(IntPtr pathPtr)
{
if(SwitchDevice?.EmulationContext == null)
{
return false;
}
var path = Marshal.PtrToStringAnsi(pathPtr);
return LoadApplication(path);
}
public static bool LoadApplication(Stream stream, bool isXci)
{
var emulationContext = SwitchDevice.EmulationContext;
return (isXci ? emulationContext?.LoadXci(stream) : emulationContext.LoadNsp(stream)) ?? false;
}
public static bool LoadApplication(string? path)
{
var emulationContext = SwitchDevice.EmulationContext;
if (Directory.Exists(path))
{
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
if (romFsFiles.Length == 0)
{
romFsFiles = Directory.GetFiles(path, "*.romfs");
}
if (romFsFiles.Length > 0)
{
Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
if (!emulationContext.LoadCart(path, romFsFiles[0]))
{
SwitchDevice.DisposeContext();
return false;
}
}
else
{
Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS.");
if (!emulationContext.LoadCart(path))
{
SwitchDevice.DisposeContext();
return false;
}
}
}
else if (File.Exists(path))
{
switch (Path.GetExtension(path).ToLowerInvariant())
{
case ".xci":
Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
if (!emulationContext.LoadXci(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
case ".nca":
Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
if (!emulationContext.LoadNca(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
case ".nsp":
case ".pfs0":
Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
if (!emulationContext.LoadNsp(path))
{
SwitchDevice.DisposeContext();
return false;
}
break;
default:
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
try
{
if (!emulationContext.LoadProgram(path))
{
SwitchDevice.DisposeContext();
return false;
}
}
catch (ArgumentOutOfRangeException)
{
Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");
SwitchDevice.DisposeContext();
return false;
}
break;
}
}
else
{
Logger.Warning?.Print(LogClass.Application, $"Couldn't load '{path}'. Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
SwitchDevice.DisposeContext();
return false;
}
Translator.IsReadyForTranslation.Reset();
return true;
}
public static void SignalEmulationClose()
{
_isStopped = true;
_isActive = false;
debug_break(2);
}
public static void CloseEmulation()
{
if (SwitchDevice == null)
return;
_npadManager?.Dispose();
_npadManager = null;
_touchScreenManager?.Dispose();
_touchScreenManager = null;
SwitchDevice?.InputManager?.Dispose();
SwitchDevice.InputManager = null;
_inputManager = null;
_surfaceEvent?.Set();
if (Renderer != null)
{
_gpuDoneEvent.WaitOne();
_gpuDoneEvent.Dispose();
_gpuDoneEvent = null;
SwitchDevice?.DisposeContext();
Renderer = null;
}
}
}
}