2018-02-20 21:09:23 +01:00
|
|
|
using Ryujinx.Core.Loaders.Executables;
|
|
|
|
using Ryujinx.Core.OsHle.Handles;
|
|
|
|
using Ryujinx.Core.OsHle.Utilities;
|
|
|
|
using System;
|
2018-02-05 00:08:20 +01:00
|
|
|
using System.Collections.Concurrent;
|
|
|
|
using System.IO;
|
|
|
|
|
2018-02-20 21:09:23 +01:00
|
|
|
namespace Ryujinx.Core.OsHle
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-02-20 21:09:23 +01:00
|
|
|
public class Horizon
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
internal const int HidSize = 0x40000;
|
|
|
|
internal const int FontSize = 0x50;
|
|
|
|
|
|
|
|
internal int HidHandle { get; private set; }
|
|
|
|
internal int FontHandle { get; private set; }
|
|
|
|
|
|
|
|
internal IdPool IdGen { get; private set; }
|
|
|
|
internal IdPool NvMapIds { get; private set; }
|
|
|
|
|
|
|
|
internal IdPoolWithObj Handles { get; private set; }
|
|
|
|
internal IdPoolWithObj Fds { get; private set; }
|
|
|
|
internal IdPoolWithObj Displays { get; private set; }
|
|
|
|
|
|
|
|
public ConcurrentDictionary<long, Mutex> Mutexes { get; private set; }
|
|
|
|
public ConcurrentDictionary<long, CondVar> CondVars { get; private set; }
|
|
|
|
|
|
|
|
private ConcurrentDictionary<int, Process> Processes;
|
|
|
|
|
2018-03-05 06:09:52 +01:00
|
|
|
internal HSharedMem HidSharedMem;
|
2018-02-17 22:36:08 +01:00
|
|
|
|
2018-02-05 00:08:20 +01:00
|
|
|
private Switch Ns;
|
|
|
|
|
|
|
|
public Horizon(Switch Ns)
|
|
|
|
{
|
|
|
|
this.Ns = Ns;
|
|
|
|
|
|
|
|
IdGen = new IdPool();
|
|
|
|
NvMapIds = new IdPool();
|
|
|
|
|
|
|
|
Handles = new IdPoolWithObj();
|
|
|
|
Fds = new IdPoolWithObj();
|
|
|
|
Displays = new IdPoolWithObj();
|
|
|
|
|
|
|
|
Mutexes = new ConcurrentDictionary<long, Mutex>();
|
|
|
|
CondVars = new ConcurrentDictionary<long, CondVar>();
|
|
|
|
|
|
|
|
Processes = new ConcurrentDictionary<int, Process>();
|
|
|
|
|
2018-02-28 00:45:07 +01:00
|
|
|
HidSharedMem = new HSharedMem();
|
2018-02-17 22:36:08 +01:00
|
|
|
|
|
|
|
HidHandle = Handles.GenerateId(HidSharedMem);
|
|
|
|
|
2018-02-28 00:45:07 +01:00
|
|
|
FontHandle = Handles.GenerateId(new HSharedMem());
|
2018-03-11 00:39:16 +01:00
|
|
|
|
|
|
|
HidSharedMem.AddVirtualPosition(0);
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void LoadCart(string ExeFsDir, string RomFsFile = null)
|
|
|
|
{
|
|
|
|
if (RomFsFile != null)
|
|
|
|
{
|
|
|
|
Ns.VFs.LoadRomFs(RomFsFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ProcessId = IdGen.GenerateId();
|
|
|
|
|
2018-02-28 00:45:07 +01:00
|
|
|
Process MainProcess = new Process(Ns, ProcessId);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
|
|
|
void LoadNso(string FileName)
|
|
|
|
{
|
|
|
|
foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
|
|
|
|
{
|
|
|
|
if (Path.GetExtension(File) != string.Empty)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-02-18 00:54:19 +01:00
|
|
|
Logging.Info($"Loading {Path.GetFileNameWithoutExtension(File)}...");
|
2018-02-17 22:06:11 +01:00
|
|
|
|
2018-02-05 00:08:20 +01:00
|
|
|
using (FileStream Input = new FileStream(File, FileMode.Open))
|
|
|
|
{
|
|
|
|
Nso Program = new Nso(Input);
|
|
|
|
|
|
|
|
MainProcess.LoadProgram(Program);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LoadNso("rtld");
|
|
|
|
|
|
|
|
MainProcess.SetEmptyArgs();
|
|
|
|
|
|
|
|
LoadNso("main");
|
|
|
|
LoadNso("subsdk*");
|
|
|
|
LoadNso("sdk");
|
|
|
|
|
|
|
|
MainProcess.Run();
|
|
|
|
|
|
|
|
Processes.TryAdd(ProcessId, MainProcess);
|
|
|
|
}
|
|
|
|
|
2018-02-17 22:36:08 +01:00
|
|
|
public void LoadProgram(string FileName)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-02-24 01:59:38 +01:00
|
|
|
bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro";
|
|
|
|
|
2018-02-05 00:08:20 +01:00
|
|
|
int ProcessId = IdGen.GenerateId();
|
|
|
|
|
2018-02-28 00:45:07 +01:00
|
|
|
Process MainProcess = new Process(Ns, ProcessId);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
|
|
|
using (FileStream Input = new FileStream(FileName, FileMode.Open))
|
|
|
|
{
|
2018-02-24 01:59:38 +01:00
|
|
|
MainProcess.LoadProgram(IsNro
|
|
|
|
? (IExecutable)new Nro(Input)
|
|
|
|
: (IExecutable)new Nso(Input));
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MainProcess.SetEmptyArgs();
|
2018-02-24 01:59:38 +01:00
|
|
|
MainProcess.Run(IsNro);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
|
|
|
Processes.TryAdd(ProcessId, MainProcess);
|
|
|
|
}
|
|
|
|
|
2018-02-14 03:43:08 +01:00
|
|
|
public void FinalizeAllProcesses()
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
foreach (Process Process in Processes.Values)
|
|
|
|
{
|
|
|
|
Process.StopAllThreads();
|
2018-02-14 03:43:08 +01:00
|
|
|
Process.Dispose();
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-17 22:36:08 +01:00
|
|
|
internal bool ExitProcess(int ProcessId)
|
|
|
|
{
|
|
|
|
bool Success = Processes.TryRemove(ProcessId, out Process Process);
|
|
|
|
|
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
Process.StopAllThreads();
|
2018-02-15 13:16:16 +01:00
|
|
|
}
|
|
|
|
|
2018-02-17 22:36:08 +01:00
|
|
|
if (Processes.Count == 0)
|
|
|
|
{
|
2018-02-15 13:16:16 +01:00
|
|
|
Ns.OnFinish(EventArgs.Empty);
|
|
|
|
}
|
2018-02-17 22:36:08 +01:00
|
|
|
|
2018-02-15 13:16:16 +01:00
|
|
|
return Success;
|
|
|
|
}
|
2018-02-17 22:36:08 +01:00
|
|
|
|
2018-02-05 00:08:20 +01:00
|
|
|
internal bool TryGetProcess(int ProcessId, out Process Process)
|
|
|
|
{
|
2018-02-20 11:54:00 +01:00
|
|
|
return Processes.TryGetValue(ProcessId, out Process);
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void CloseHandle(int Handle)
|
|
|
|
{
|
|
|
|
object HndData = Handles.GetData<object>(Handle);
|
|
|
|
|
|
|
|
if (HndData is HTransferMem TransferMem)
|
|
|
|
{
|
|
|
|
TransferMem.Memory.Manager.Reprotect(
|
|
|
|
TransferMem.Position,
|
|
|
|
TransferMem.Size,
|
|
|
|
TransferMem.Perm);
|
|
|
|
}
|
|
|
|
|
|
|
|
Handles.Delete(Handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|