aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/OsHle/Horizon.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Core/OsHle/Horizon.cs')
-rw-r--r--Ryujinx.Core/OsHle/Horizon.cs197
1 files changed, 197 insertions, 0 deletions
diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs
new file mode 100644
index 00000000..e2d38d52
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Horizon.cs
@@ -0,0 +1,197 @@
+using ChocolArm64.Memory;
+using Ryujinx.Core.Loaders.Executables;
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Utilities;
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+
+namespace Ryujinx.Core.OsHle
+{
+ public class Horizon
+ {
+ 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;
+
+ 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);
+
+ 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)}...");
+
+ 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)
+ {
+ int ProcessId = IdGen.GenerateId();
+
+ Process MainProcess = new Process(Ns, Allocator, ProcessId);
+
+ using (FileStream Input = new FileStream(FileName, FileMode.Open))
+ {
+ if (Path.GetExtension(FileName).ToLower() == ".nro")
+ {
+ MainProcess.LoadProgram(new Nro(Input));
+ }
+ else
+ {
+ MainProcess.LoadProgram(new Nso(Input));
+ }
+ }
+
+ MainProcess.SetEmptyArgs();
+ MainProcess.InitializeHeap();
+ MainProcess.Run();
+
+ Processes.TryAdd(ProcessId, MainProcess);
+ }
+
+ public void FinalizeAllProcesses()
+ {
+ foreach (Process Process in Processes.Values)
+ {
+ Process.StopAllThreads();
+ Process.Dispose();
+ }
+ }
+
+ 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;
+ }
+
+ internal bool TryGetProcess(int ProcessId, out Process Process)
+ {
+ return Processes.TryGetValue(ProcessId, out Process);
+ }
+
+ 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);
+ }
+ }
+ }
+} \ No newline at end of file