diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index d607d985ee..7804913faf 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -13,6 +13,36 @@
 
 namespace Service::LDR {
 
+namespace ErrCodes {
+enum {
+    InvalidNRO = 52,
+    InvalidNRR = 53,
+    MissingNRRHash = 54,
+    MaximumNRO = 55,
+    MaximumNRR = 56,
+    AlreadyLoaded = 57,
+    InvalidAlignment = 81,
+    InvalidSize = 82,
+    InvalidNROAddress = 84,
+    InvalidNRRAddress = 85,
+    NotInitialized = 87,
+};
+}
+
+constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO);
+constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR);
+constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash);
+constexpr ResultCode ERROR_MAXIMUM_NRO(ErrorModule::Loader, ErrCodes::MaximumNRO);
+constexpr ResultCode ERROR_MAXIMUM_NRR(ErrorModule::Loader, ErrCodes::MaximumNRR);
+constexpr ResultCode ERROR_ALREADY_LOADED(ErrorModule::Loader, ErrCodes::AlreadyLoaded);
+constexpr ResultCode ERROR_INVALID_ALIGNMENT(ErrorModule::Loader, ErrCodes::InvalidAlignment);
+constexpr ResultCode ERROR_INVALID_SIZE(ErrorModule::Loader, ErrCodes::InvalidSize);
+constexpr ResultCode ERROR_INVALID_NRO_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNROAddress);
+constexpr ResultCode ERROR_INVALID_NRR_ADDRESS(ErrorModule::Loader, ErrCodes::InvalidNRRAddress);
+constexpr ResultCode ERROR_NOT_INITIALIZED(ErrorModule::Loader, ErrCodes::NotInitialized);
+
+constexpr u64 MAXIMUM_LOADED_RO = 0x40;
+
 class DebugMonitor final : public ServiceFramework<DebugMonitor> {
 public:
     explicit DebugMonitor() : ServiceFramework{"ldr:dmnt"} {
@@ -75,6 +105,88 @@ public:
     }
 
     void LoadNrr(Kernel::HLERequestContext& ctx) {
+        IPC::RequestParser rp{ctx};
+        rp.Skip(2, false);
+        const VAddr nrr_addr{rp.Pop<VAddr>()};
+        const u64 nrr_size{rp.Pop<u64>()};
+
+        if (!initialized) {
+            LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_NOT_INITIALIZED);
+            return;
+        }
+
+        if (nro.size() >= MAXIMUM_LOADED_RO) {
+            LOG_ERROR(Service_LDR, "Loading new NRR would exceed the maximum number of loaded NRRs "
+                                   "(0x40)! Failing...");
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_MAXIMUM_NRR);
+            return;
+        }
+
+        // NRR Address does not fall on 0x1000 byte boundary
+        if ((nrr_addr & 0xFFF) != 0) {
+            LOG_ERROR(Service_LDR, "NRR Address has invalid alignment (actual {:016X})!", nrr_addr);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_INVALID_ALIGNMENT);
+            return;
+        }
+
+        // NRR Size is zero or causes overflow
+        if (nrr_addr + nrr_size <= nrr_addr || nrr_size == 0 || (nrr_size & 0xFFF) != 0) {
+            LOG_ERROR(Service_LDR, "NRR Size is invalid! (nrr_address={:016X}, nrr_size={:016X})",
+                      nrr_addr, nrr_size);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_INVALID_SIZE);
+            return;
+        }
+        // Read NRR data from memory
+        std::vector<u8> nrr_data(nrr_size);
+        Memory::ReadBlock(nrr_addr, nrr_data.data(), nrr_size);
+        NRRHeader header;
+        std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
+
+        if (header.magic != Common::MakeMagic('N', 'R', 'R', '0')) {
+            LOG_ERROR(Service_LDR, "NRR did not have magic 'NRR0' (actual {:08X})!", header.magic);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_INVALID_NRR);
+            return;
+        }
+
+        if (header.size != nrr_size) {
+            LOG_ERROR(Service_LDR,
+                      "NRR header reported size did not match LoadNrr parameter size! "
+                      "(header_size={:016X}, loadnrr_size={:016X})",
+                      header.size, nrr_size);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_INVALID_SIZE);
+            return;
+        }
+
+        if (Core::CurrentProcess()->GetTitleID() != header.title_id) {
+            LOG_ERROR(Service_LDR,
+                      "Attempting to load NRR with title ID other than current process. (actual "
+                      "{:016X})!",
+                      header.title_id);
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(ERROR_INVALID_NRR);
+            return;
+        }
+
+        std::vector<SHA256Hash> hashes;
+        for (std::size_t i = header.hash_offset;
+             i < (header.hash_offset + (header.hash_count << 5)); i += 8) {
+            hashes.emplace_back();
+            std::memcpy(hashes.back().data(), nrr_data.data() + i, sizeof(SHA256Hash));
+        }
+
+        nrr.insert_or_assign(nrr_addr, std::move(hashes));
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(RESULT_SUCCESS);
+    }
+
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
         LOG_WARNING(Service_LDR, "(STUBBED) called");