diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index f0d376bf52e248bc099e511f0b63f98559488c6e..26e1daf554661a12acab2c53b94ab78dbb65b31e 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -215,7 +215,7 @@ VirtualFile NCA::Decrypt(NCASectionHeader s_header, VirtualFile in, u64 starting
     }
 }
 
-NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
+NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset)
     : file(std::move(file_)),
       bktr_base_romfs(bktr_base_romfs_ ? std::move(bktr_base_romfs_) : nullptr) {
     status = Loader::ResultStatus::Success;
@@ -292,6 +292,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
     is_update = std::find_if(sections.begin(), sections.end(), [](const NCASectionHeader& header) {
                     return header.raw.header.crypto_type == NCASectionCryptoType::BKTR;
                 }) != sections.end();
+    ivfc_offset = 0;
 
     for (std::ptrdiff_t i = 0; i < number_sections; ++i) {
         auto section = sections[i];
@@ -299,8 +300,8 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
         if (section.raw.header.filesystem_type == NCASectionFilesystemType::ROMFS) {
             const size_t base_offset =
                 header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER;
-            const size_t romfs_offset =
-                base_offset + section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
+            ivfc_offset = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
+            const size_t romfs_offset = base_offset + ivfc_offset;
             const size_t romfs_size = section.romfs.ivfc.levels[IVFC_MAX_LEVEL - 1].size;
             auto raw = std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset);
             auto dec = Decrypt(section, raw, romfs_offset);
@@ -414,7 +415,7 @@ NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_)
                     bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
                     relocation_block, relocation_buckets, subsection_block, subsection_buckets,
                     encrypted, encrypted ? key.get() : Core::Crypto::Key128{}, base_offset,
-                    romfs_offset - base_offset, section.raw.section_ctr);
+                    bktr_base_ivfc_offset, section.raw.section_ctr);
 
                 // BKTR applies to entire IVFC, so make an offset version to level 6
 
@@ -511,6 +512,10 @@ VirtualFile NCA::GetBaseFile() const {
     return file;
 }
 
+u64 NCA::GetBaseIVFCOffset() const {
+    return ivfc_offset;
+}
+
 bool NCA::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
     return false;
 }
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index 104226f3a14623f6472b6921b1044dcd0b0cdc9b..00eca52da5107cd4581c41967bab0f79ad71783c 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -79,7 +79,8 @@ bool IsValidNCA(const NCAHeader& header);
 // After construction, use GetStatus to determine if the file is valid and ready to be used.
 class NCA : public ReadOnlyVfsDirectory {
 public:
-    explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr);
+    explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr,
+                 u64 bktr_base_ivfc_offset = 0);
     Loader::ResultStatus GetStatus() const;
 
     std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
@@ -96,6 +97,9 @@ public:
 
     VirtualFile GetBaseFile() const;
 
+    // Returns the base ivfc offset used in BKTR patching.
+    u64 GetBaseIVFCOffset() const;
+
 protected:
     bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 
@@ -112,6 +116,7 @@ private:
     VirtualDir exefs = nullptr;
     VirtualFile file;
     VirtualFile bktr_base_romfs;
+    u64 ivfc_offset;
 
     NCAHeader header{};
     bool has_rights_id{};
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp
index 22fbba5732f720c681b312ced5d303494c0b5cda..e293af45249f53bc0e55b0b2e5d8d016154dfba0 100644
--- a/src/core/file_sys/nca_patch.cpp
+++ b/src/core/file_sys/nca_patch.cpp
@@ -51,7 +51,7 @@ size_t BKTR::Read(u8* data, size_t length, size_t offset) const {
 
     if (!bktr_read) {
         ASSERT_MSG(section_offset > ivfc_offset, "Offset calculation negative.");
-        return base_romfs->Read(data, length, section_offset);
+        return base_romfs->Read(data, length, section_offset - ivfc_offset);
     }
 
     if (!encrypted) {
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp
index fc9cf1eca731ae6965820604e05e07ca0502ea26..33ec62491a3bd0d1a5039fcf98ee44feed713f9c 100644
--- a/src/core/file_sys/romfs_factory.cpp
+++ b/src/core/file_sys/romfs_factory.cpp
@@ -24,14 +24,15 @@ RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) {
     }
 
     updatable = app_loader.IsRomFSUpdatable();
+    ivfc_offset = app_loader.ReadRomFSIVFCOffset();
 }
 
 ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() {
     if (!updatable)
         return MakeResult<VirtualFile>(file);
 
-    const PatchManager patch_manager(Core::CurrentProcess()->process_id);
-    return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file));
+    const PatchManager patch_manager(Core::CurrentProcess()->program_id);
+    return MakeResult<VirtualFile>(patch_manager.PatchRomFS(file, ivfc_offset));
 }
 
 ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) {
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h
index 168db1c465b9634e600fc8e45b26ba4d2f90ee2f..26b8f46cc2565525074ab5a9318d94e12257535b 100644
--- a/src/core/file_sys/romfs_factory.h
+++ b/src/core/file_sys/romfs_factory.h
@@ -37,6 +37,7 @@ public:
 private:
     VirtualFile file;
     bool updatable;
+    u64 ivfc_offset;
 };
 
 } // namespace FileSys
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 225c05127d14a323454d277a29edcc5e6c980fc3..843c4bb912ae3e4d26de0064e872a82c2fd7ee9e 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -214,6 +214,15 @@ public:
         return true;
     }
 
+    /**
+     * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS)
+     * data. Needed for bktr patching.
+     * @return IVFC offset for romfs.
+     */
+    virtual u64 ReadRomFSIVFCOffset() const {
+        return 0;
+    }
+
     /**
      * Get the title of the application
      * @param title Reference to store the application title into
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 6b1c27b47fd2d721c1a519971d4ff3bee241b2e9..6aaffae5951831b0c3e5ad5f4bd7aaf3c280b959 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -71,6 +71,12 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
     return ResultStatus::Success;
 }
 
+u64 AppLoader_NCA::ReadRomFSIVFCOffset() const {
+    if (nca == nullptr)
+        return 0;
+    return nca->GetBaseIVFCOffset();
+}
+
 ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
     if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
         return ResultStatus::ErrorNotInitialized;
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 326f84857971539a5dd8f4e4083fbea87d7b3e5d..10be197c4ba53ffdb4f44a2b39a540dd1d8bfd99 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -37,6 +37,7 @@ public:
     ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
 
     ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
+    u64 ReadRomFSIVFCOffset() const override;
     ResultStatus ReadProgramId(u64& out_program_id) override;
 
 private: