diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
index e1b9a61bc1..36a275e291 100644
--- a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
+++ b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs
@@ -82,9 +82,6 @@ namespace Ryujinx.Graphics.Gpu
             }
         }
 
-        private int _currMacroPosition;
-        private int _currMacroBindIndex;
-
         private ShadowRamControl _shadowCtrl;
 
         private CachedMacro[] _macros;
diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs
index f6ab5ba99a..bc7016bda2 100644
--- a/Ryujinx.HLE/HOS/ApplicationLoader.cs
+++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs
@@ -415,13 +415,13 @@ namespace Ryujinx.HLE.HOS
 
             bool isNro = Path.GetExtension(filePath).ToLower() == ".nro";
 
-            IExecutable nro;
+            IExecutable executable;
 
             if (isNro)
             {
                 FileStream input = new FileStream(filePath, FileMode.Open);
                 NroExecutable obj = new NroExecutable(input);
-                nro = obj;
+                executable = obj;
 
                 // homebrew NRO can actually have some data after the actual NRO
                 if (input.Length > obj.FileSize)
@@ -493,7 +493,7 @@ namespace Ryujinx.HLE.HOS
             }
             else
             {
-                nro = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read));
+                executable = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read));
             }
 
             _contentManager.LoadEntries(_device);
@@ -502,7 +502,7 @@ namespace Ryujinx.HLE.HOS
             TitleId = metaData.Aci0.TitleId;
             TitleIs64Bit = metaData.Is64Bit;
 
-            ProgramLoader.LoadNsos(_device.System.KernelContext, metaData, executables: nro);
+            ProgramLoader.LoadNsos(_device.System.KernelContext, metaData, executables: executable);
         }
 
         private Npdm GetDefaultNpdm()
diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs
index 1158925ab7..cf5b15bac4 100644
--- a/Ryujinx.HLE/HOS/ProgramLoader.cs
+++ b/Ryujinx.HLE/HOS/ProgramLoader.cs
@@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS
 
             int codePagesCount = codeSize / KMemoryManager.PageSize;
 
-            ulong codeBaseAddress = (kip.Header.Flags & 0x10) != 0 ? 0x8000000UL : 0x200000UL;
+            ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL;
 
             ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset;
 
@@ -45,27 +45,27 @@ namespace Ryujinx.HLE.HOS
                 mmuFlags |= 0x20;
             }
 
-            if ((kip.Header.Flags & 0x10) != 0)
+            if (kip.Is64BitAddressSpace)
             {
                 mmuFlags |= (int)AddressSpaceType.Addr39Bits << 1;
             }
 
-            if ((kip.Header.Flags & 0x08) != 0)
+            if (kip.Is64Bit)
             {
                 mmuFlags |= 1;
             }
 
             ProcessCreationInfo creationInfo = new ProcessCreationInfo(
-                kip.Header.Name,
-                kip.Header.ProcessCategory,
-                kip.Header.TitleId,
+                kip.Name,
+                kip.Version,
+                kip.ProgramId,
                 codeAddress,
                 codePagesCount,
                 mmuFlags,
                 0,
                 0);
 
-            MemoryRegion memoryRegion = (kip.Header.Flags & 0x20) != 0
+            MemoryRegion memoryRegion = kip.UsesSecureMemory
                 ? MemoryRegion.Service
                 : MemoryRegion.Application;
 
@@ -105,9 +105,9 @@ namespace Ryujinx.HLE.HOS
                 return false;
             }
 
-            process.DefaultCpuCore = kip.Header.DefaultCore;
+            process.DefaultCpuCore = kip.IdealCoreId;
 
-            result = process.Start(kip.Header.MainThreadPriority, (ulong)kip.Header.Sections[1].Attribute);
+            result = process.Start(kip.Priority, (ulong)kip.StackSize);
 
             if (result != KernelResult.Success)
             {
diff --git a/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs b/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs
index 8bbf26b26b..d94030fab4 100644
--- a/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs
+++ b/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs
@@ -9,9 +9,9 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth
     [Service("btdrv")]
     class IBluetoothDriver : IpcService
     {
-#pragma warning disable CS0169
+#pragma warning disable CS0414
         private string _unknownLowEnergy;
-#pragma warning restore CS0169
+#pragma warning restore CS0414
 
         public IBluetoothDriver(ServiceCtx context) { }
 
diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs
index 246c92bdef..3bdf15a1af 100644
--- a/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs
+++ b/Ryujinx.HLE/HOS/Services/Sockets/Nsd/Manager/FqdnResolver.cs
@@ -32,7 +32,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd.Manager
                     return ResultCode.Success;
                 }
 
+#pragma warning disable CS0162
                 return ResultCode.NullOutputObject;
+#pragma warning restore CS0162
             }
         }
 
diff --git a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
index 9f04cf4e43..0f1309c028 100644
--- a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
+++ b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs
@@ -1,35 +1,76 @@
-using LibHac;
 using LibHac.Fs;
-using System.IO;
+using LibHac.Loader;
 
 namespace Ryujinx.HLE.Loaders.Executables
 {
-    class KipExecutable : Kip, IExecutable
+    class KipExecutable : IExecutable
     {
         public byte[] Text { get; }
         public byte[] Ro { get; }
         public byte[] Data { get; }
 
-        public int TextOffset => Header.Sections[0].OutOffset;
-        public int RoOffset => Header.Sections[1].OutOffset;
-        public int DataOffset => Header.Sections[2].OutOffset;
-        public int BssOffset => Header.Sections[3].OutOffset;
-        public int BssSize => Header.Sections[3].DecompressedSize;
+        public int TextOffset { get; }
+        public int RoOffset { get; }
+        public int DataOffset { get; }
+        public int BssOffset { get; }
+        public int BssSize { get; }
 
         public int[] Capabilities { get; }
+        public bool UsesSecureMemory { get; }
+        public bool Is64BitAddressSpace { get; }
+        public bool Is64Bit { get; }
+        public ulong ProgramId { get; }
+        public byte Priority { get; }
+        public int StackSize { get; }
+        public byte IdealCoreId { get; }
+        public int Version { get; }
+        public string Name { get; }
 
-        public KipExecutable(IStorage inStorage) : base(inStorage)
+        public KipExecutable(IStorage inStorage)
         {
+            KipReader reader = new KipReader();
+
+            reader.Initialize(inStorage).ThrowIfFailure();
+
+            TextOffset = reader.Segments[0].MemoryOffset;
+            RoOffset = reader.Segments[1].MemoryOffset;
+            DataOffset = reader.Segments[2].MemoryOffset;
+            BssOffset = reader.Segments[3].MemoryOffset;
+            BssSize = reader.Segments[3].Size;
+
+            StackSize = reader.StackSize;
+
+            UsesSecureMemory = reader.UsesSecureMemory;
+            Is64BitAddressSpace = reader.Is64BitAddressSpace;
+            Is64Bit = reader.Is64Bit;
+
+            ProgramId = reader.ProgramId;
+            Priority = reader.Priority;
+            IdealCoreId = reader.IdealCoreId;
+            Version = reader.Version;
+            Name = reader.Name.ToString();
+
             Capabilities = new int[32];
 
             for (int index = 0; index < Capabilities.Length; index++)
             {
-                Capabilities[index] = System.BitConverter.ToInt32(Header.Capabilities, index * 4);
+                Capabilities[index] = (int)reader.Capabilities[index];
             }
 
-            Text = DecompressSection(0);
-            Ro = DecompressSection(1);
-            Data = DecompressSection(2);
+            Text = DecompressSection(reader, KipReader.SegmentType.Text);
+            Ro = DecompressSection(reader, KipReader.SegmentType.Ro);
+            Data = DecompressSection(reader, KipReader.SegmentType.Data);
+        }
+
+        private static byte[] DecompressSection(KipReader reader, KipReader.SegmentType segmentType)
+        {
+            reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure();
+
+            byte[] result = new byte[uncompressedSize];
+
+            reader.ReadSegment(segmentType, result).ThrowIfFailure();
+
+            return result;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs b/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs
index 6050432d0e..bbe2c87fe2 100644
--- a/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs
+++ b/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs
@@ -1,28 +1,47 @@
-using LibHac;
 using LibHac.Fs;
-using System;
-using System.IO;
+using LibHac.FsSystem;
+using LibHac.Loader;
 
 namespace Ryujinx.HLE.Loaders.Executables
 {
-    class NsoExecutable : Nso, IExecutable
+    class NsoExecutable : IExecutable
     {
         public byte[] Text { get; }
         public byte[] Ro { get; }
         public byte[] Data { get; }
 
-        public int TextOffset => (int)Sections[0].MemoryOffset;
-        public int RoOffset => (int)Sections[1].MemoryOffset;
-        public int DataOffset => (int)Sections[2].MemoryOffset;
+        public int TextOffset { get; }
+        public int RoOffset { get; }
+        public int DataOffset { get; }
         public int BssOffset => DataOffset + Data.Length;
 
-        public new int BssSize => (int)base.BssSize;
+        public int BssSize { get; }
 
-        public NsoExecutable(IStorage inStorage) : base(inStorage)
+        public NsoExecutable(IStorage inStorage)
         {
-            Text = Sections[0].DecompressSection();
-            Ro = Sections[1].DecompressSection();
-            Data =  Sections[2].DecompressSection();
+            NsoReader reader = new NsoReader();
+
+            reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure();
+
+            TextOffset = (int)reader.Header.Segments[0].MemoryOffset;
+            RoOffset = (int)reader.Header.Segments[1].MemoryOffset;
+            DataOffset = (int)reader.Header.Segments[2].MemoryOffset;
+            BssSize = (int)reader.Header.BssSize;
+
+            Text = DecompressSection(reader, NsoReader.SegmentType.Text);
+            Ro = DecompressSection(reader, NsoReader.SegmentType.Ro);
+            Data = DecompressSection(reader, NsoReader.SegmentType.Data);
+        }
+
+        private static byte[] DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType)
+        {
+            reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure();
+
+            byte[] result = new byte[uncompressedSize];
+
+            reader.ReadSegment(segmentType, result).ThrowIfFailure();
+
+            return result;
         }
     }
 }
\ No newline at end of file