From 7f9430f7aee9e7ef11d1bd86a2b98ae239c5be06 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Sun, 5 Aug 2018 18:27:05 -0400
Subject: loader: Make AppLoader_NCA rely on directory loading code

Eliminates duplicate code shared between their Load methods, after all the only difference is how the romfs is handled.
---
 src/core/loader/deconstructed_rom_directory.cpp | 11 ++++++-
 src/core/loader/deconstructed_rom_directory.h   |  4 +++
 src/core/loader/nca.cpp                         | 44 +++++--------------------
 src/core/loader/nca.h                           |  2 ++
 4 files changed, 24 insertions(+), 37 deletions(-)

(limited to 'src')

diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index b0277a8750..076927dff3 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -20,6 +20,10 @@ namespace Loader {
 AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file)
     : AppLoader(std::move(file)) {}
 
+AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
+    FileSys::VirtualDir directory)
+    : AppLoader(directory->GetFile("main")), dir(std::move(directory)) {}
+
 FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
     if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
         return FileType::DeconstructedRomDirectory;
@@ -34,7 +38,12 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
         return ResultStatus::ErrorAlreadyLoaded;
     }
 
-    const FileSys::VirtualDir dir = file->GetContainingDirectory();
+    if (dir == nullptr) {
+        if (file == nullptr)
+            return ResultStatus::ErrorInvalidFormat;
+        const FileSys::VirtualDir dir = file->GetContainingDirectory();
+    }
+
     const FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
     if (npdm == nullptr)
         return ResultStatus::ErrorInvalidFormat;
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 7319ba6ea1..7d54335633 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -22,6 +22,9 @@ class AppLoader_DeconstructedRomDirectory final : public AppLoader {
 public:
     explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file);
 
+    // Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
+    explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory);
+
     /**
      * Returns the type of the file
      * @param file std::shared_ptr<VfsFile> open file
@@ -40,6 +43,7 @@ public:
 private:
     FileSys::ProgramMetadata metadata;
     FileSys::VirtualFile romfs;
+    FileSys::VirtualDir dir;
 };
 
 } // namespace Loader
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index a1f8235d12..dbc67c0b52 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -22,7 +22,8 @@
 
 namespace Loader {
 
-AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
+AppLoader_NCA::AppLoader_NCA(FileSys::VirtualFile file_)
+    : AppLoader(std::move(file_)), nca(std::make_unique<FileSys::NCA>(file)) {}
 
 FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
     FileSys::NCA nca(file);
@@ -39,8 +40,7 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
         return ResultStatus::ErrorAlreadyLoaded;
     }
 
-    nca = std::make_unique<FileSys::NCA>(file);
-    ResultStatus result = nca->GetStatus();
+    const auto result = nca->GetStatus();
     if (result != ResultStatus::Success) {
         return result;
     }
@@ -48,44 +48,16 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
     if (nca->GetType() != FileSys::NCAContentType::Program)
         return ResultStatus::ErrorInvalidFormat;
 
-    auto exefs = nca->GetExeFS();
+    const auto exefs = nca->GetExeFS();
 
     if (exefs == nullptr)
         return ResultStatus::ErrorInvalidFormat;
 
-    result = metadata.Load(exefs->GetFile("main.npdm"));
-    if (result != ResultStatus::Success) {
-        return result;
-    }
-    metadata.Print();
-
-    const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
-    if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) {
-        return ResultStatus::ErrorUnsupportedArch;
-    }
-
-    VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
-    for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
-                               "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
-        const VAddr load_addr = next_load_addr;
-
-        next_load_addr = AppLoader_NSO::LoadModule(exefs->GetFile(module), load_addr);
-        if (next_load_addr) {
-            LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
-            // Register module with GDBStub
-            GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
-        } else {
-            next_load_addr = load_addr;
-        }
-    }
+    directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs);
 
-    process->program_id = metadata.GetTitleID();
-    process->svc_access_mask.set();
-    process->address_mappings = default_address_mappings;
-    process->resource_limit =
-        Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
-    process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
-                 metadata.GetMainThreadStackSize());
+    const auto load_result = directory_loader->Load(process);
+    if (load_result != ResultStatus::Success)
+        return load_result;
 
     if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0)
         Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index e14d618b36..0fd2d04175 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -10,6 +10,7 @@
 #include "core/file_sys/program_metadata.h"
 #include "core/hle/kernel/object.h"
 #include "core/loader/loader.h"
+#include "deconstructed_rom_directory.h"
 
 namespace Loader {
 
@@ -41,6 +42,7 @@ private:
     FileSys::ProgramMetadata metadata;
 
     std::unique_ptr<FileSys::NCA> nca;
+    std::unique_ptr<AppLoader_DeconstructedRomDirectory> directory_loader;
 };
 
 } // namespace Loader
-- 
cgit v1.2.3-70-g09d2