Ryujinx/Ryujinx.Core/OsHle/Horizon.cs

195 lines
5.5 KiB
C#
Raw Normal View History

2018-02-04 15:08:20 -08:00
using ChocolArm64.Memory;
using Ryujinx.Core.Loaders.Executables;
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Utilities;
using System;
2018-02-04 15:08:20 -08:00
using System.Collections.Concurrent;
using System.IO;
namespace Ryujinx.Core.OsHle
2018-02-04 15:08:20 -08:00
{
public class Horizon
2018-02-04 15:08:20 -08:00
{
internal const int HidSize = 0x40000;
internal const int FontSize = 0x50;
internal int HidHandle { get; private set; }
internal int FontHandle { get; private set; }
public long HidOffset { get; private set; }
public long FontOffset { 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;
private HSharedMem HidSharedMem;
2018-02-04 15:08:20 -08:00
private AMemoryAlloc Allocator;
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>();
Allocator = new AMemoryAlloc();
HidOffset = Allocator.Alloc(HidSize);
FontOffset = Allocator.Alloc(FontSize);
HidSharedMem = new HSharedMem(HidOffset);
HidSharedMem.MemoryMapped += HidInit;
HidHandle = Handles.GenerateId(HidSharedMem);
2018-02-04 15:08:20 -08:00
FontHandle = Handles.GenerateId(new HSharedMem(FontOffset));
}
public void LoadCart(string ExeFsDir, string RomFsFile = null)
{
if (RomFsFile != null)
{
Ns.VFs.LoadRomFs(RomFsFile);
}
int ProcessId = IdGen.GenerateId();
Process MainProcess = new Process(Ns, Allocator, ProcessId);
void LoadNso(string FileName)
{
foreach (string File in Directory.GetFiles(ExeFsDir, FileName))
{
if (Path.GetExtension(File) != string.Empty)
{
continue;
}
Logging.Info($"Loading {Path.GetFileNameWithoutExtension(File)}...");
2018-02-04 15:08:20 -08: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.InitializeHeap();
MainProcess.Run();
Processes.TryAdd(ProcessId, MainProcess);
}
public void LoadProgram(string FileName)
2018-02-04 15:08:20 -08:00
{
bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro";
2018-02-04 15:08:20 -08:00
int ProcessId = IdGen.GenerateId();
Process MainProcess = new Process(Ns, Allocator, ProcessId);
using (FileStream Input = new FileStream(FileName, FileMode.Open))
{
MainProcess.LoadProgram(IsNro
? (IExecutable)new Nro(Input)
: (IExecutable)new Nso(Input));
2018-02-04 15:08:20 -08:00
}
MainProcess.SetEmptyArgs();
MainProcess.InitializeHeap();
MainProcess.Run(IsNro);
2018-02-04 15:08:20 -08:00
Processes.TryAdd(ProcessId, MainProcess);
}
public void FinalizeAllProcesses()
2018-02-04 15:08:20 -08:00
{
foreach (Process Process in Processes.Values)
{
Process.StopAllThreads();
Process.Dispose();
2018-02-04 15:08:20 -08:00
}
}
internal bool ExitProcess(int ProcessId)
{
bool Success = Processes.TryRemove(ProcessId, out Process Process);
if (Success)
{
Process.StopAllThreads();
}
if (Processes.Count == 0)
{
Ns.OnFinish(EventArgs.Empty);
}
return Success;
}
2018-02-04 15:08:20 -08:00
internal bool TryGetProcess(int ProcessId, out Process Process)
{
return Processes.TryGetValue(ProcessId, out Process);
2018-02-04 15:08:20 -08: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);
}
private void HidInit(object sender, EventArgs e)
{
HSharedMem SharedMem = (HSharedMem)sender;
if (SharedMem.TryGetLastVirtualPosition(out long Position))
{
Logging.Info($"HID shared memory successfully mapped to {Position:x16}!");
Ns.Hid.Init(Position);
}
}
2018-02-04 15:08:20 -08:00
}
}