From e523c76cc8652dca4862bed2209cbf56ffbc06c2 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Wed, 8 Mar 2017 16:23:28 -0500
Subject: [PATCH 01/10] Fixed encrypted ROM error messages.

---
 src/core/loader/loader.h |  8 +++++---
 src/core/loader/ncch.cpp | 15 +++++++++++----
 src/core/loader/ncch.h   |  5 +++--
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 1d80766ae..21f73503e 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -100,11 +100,13 @@ public:
      * Loads the system mode that this application needs.
      * This function defaults to 2 (96MB allocated to the application) if it can't read the
      * information.
-     * @returns Optional with the kernel system mode
+     * @param boost::optional<u32> Reference to Boost optional to store system mode.
+     * @ return Result of operation.
      */
-    virtual boost::optional<u32> LoadKernelSystemMode() {
+    virtual ResultStatus LoadKernelSystemMode(boost::optional<u32>& system_mode) {
         // 96MB allocated to the application.
-        return 2;
+        system_mode = 2;
+        return ResultStatus::Success;
     }
 
     /**
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index beeb13ffa..1a20762e4 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -121,12 +121,19 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) {
     return FileType::Error;
 }
 
-boost::optional<u32> AppLoader_NCCH::LoadKernelSystemMode() {
+ResultStatus AppLoader_NCCH::LoadKernelSystemMode(boost::optional<u32>& system_mode) {
     if (!is_loaded) {
-        if (LoadExeFS() != ResultStatus::Success)
-            return boost::none;
+        ResultStatus res = LoadExeFS();
+        if (res != ResultStatus::Success) {
+            // Set the system mode as invalid.
+            system_mode = boost::none;
+            // Return the error code.
+            return res;
+        }
     }
-    return exheader_header.arm11_system_local_caps.system_mode.Value();
+    // Set the system mode as the one from the exheader.
+    system_mode = exheader_header.arm11_system_local_caps.system_mode.Value();
+    return ResultStatus::Success;
 }
 
 ResultStatus AppLoader_NCCH::LoadExec() {
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 4ef95b5c6..269fe4f49 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -179,9 +179,10 @@ public:
 
     /**
      * Loads the Exheader and returns the system mode for this application.
-     * @return Optional with the kernel system mode
+     * @param boost::optional<u32> Reference to Boost optional to store system mode.
+     * @return Result of operation.
      */
-    boost::optional<u32> LoadKernelSystemMode() override;
+    ResultStatus LoadKernelSystemMode(boost::optional<u32>& system_mode) override;
 
     ResultStatus ReadCode(std::vector<u8>& buffer) override;
 

From 1ecb322daa0e2521fe0e179e87889db9aaaf63b0 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Wed, 8 Mar 2017 16:28:30 -0500
Subject: [PATCH 02/10] Added system for handling core errors in citra-qt.

---
 src/citra_qt/bootmanager.cpp        |  6 +-
 src/citra_qt/bootmanager.h          |  3 +
 src/citra_qt/main.cpp               | 86 +++++++++++++++++++++++------
 src/citra_qt/main.h                 |  1 +
 src/core/core.cpp                   | 24 ++++++--
 src/core/core.h                     | 13 +++++
 src/core/hle/service/apt/apt.cpp    |  7 ++-
 src/core/hle/service/err_f.cpp      |  2 +
 src/core/hle/service/fs/fs_user.cpp |  5 ++
 9 files changed, 121 insertions(+), 26 deletions(-)

diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 06b62f44c..16661767f 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -37,7 +37,11 @@ void EmuThread::run() {
             if (!was_active)
                 emit DebugModeLeft();
 
-            Core::System::GetInstance().RunLoop();
+            Core::System::ResultStatus result = Core::System::GetInstance().RunLoop();
+            if (result != Core::System::ResultStatus::Success) {
+                emit ErrorThrown(result);
+                break;
+            }
 
             was_active = running || exec_step;
             if (!was_active && !stop_run)
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 9d39f1af8..c5430a3fa 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -10,6 +10,7 @@
 #include <QGLWidget>
 #include <QThread>
 #include "common/thread.h"
+#include "core/core.h"
 #include "core/frontend/emu_window.h"
 #include "core/frontend/motion_emu.h"
 
@@ -97,6 +98,8 @@ signals:
      * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
      */
     void DebugModeLeft();
+
+    void ErrorThrown(Core::System::ResultStatus);
 };
 
 class GRenderWindow : public QWidget, public EmuWindow {
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index eb2c7d613..e24c48e90 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -301,8 +301,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
 
     if (!gladLoadGL()) {
         QMessageBox::critical(this, tr("Error while starting Citra!"),
-                              tr("Failed to initialize the video core!\n\n"
-                                 "Please ensure that your GPU supports OpenGL 3.3 and that you "
+                              tr("Your GPU may not support OpenGL 3.3, or you do not"
                                  "have the latest graphics driver."));
         return false;
     }
@@ -327,18 +326,17 @@ bool GMainWindow::LoadROM(const QString& filename) {
             break;
 
         case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: {
-            // Build the MessageBox ourselves to have clickable link
-            QMessageBox popup_error;
-            popup_error.setTextFormat(Qt::RichText);
-            popup_error.setWindowTitle(tr("Error while loading ROM!"));
-            popup_error.setText(
+            QMessageBox::critical(
+                this, tr("Error while loading ROM!"),
                 tr("The game that you are trying to load must be decrypted before being used with "
                    "Citra.<br/><br/>"
-                   "For more information on dumping and decrypting games, please see: <a "
-                   "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://"
-                   "citra-emu.org/wiki/Dumping-Game-Cartridges</a>"));
-            popup_error.setIcon(QMessageBox::Critical);
-            popup_error.exec();
+                   "For more information on dumping and decrypting games, please see the following "
+                   "wiki pages: <ul>"
+                   "<li><a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges/'>Dumping Game "
+                   "Cartridges</a></li>"
+                   "<li><a href='https://citra-emu.org/wiki/Dumping-Installed-Titles/'>Dumping "
+                   "Installed Titles</a></li>"
+                   "</ul>"));
             break;
         }
         case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
@@ -346,8 +344,16 @@ bool GMainWindow::LoadROM(const QString& filename) {
                                   tr("The ROM format is not supported."));
             break;
 
+        case Core::System::ResultStatus::ErrorOpenGL:
+            QMessageBox::critical(this, tr("Error while loading OpenGL!"),
+                                  tr("Your GPU may not support OpenGL 3.3, or you do not "
+                                     "have the latest graphics driver."));
+            break;
+
         default:
-            QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!"));
+            QMessageBox::critical(
+                this, tr("Error while loading ROM!"),
+                tr("An unknown error occured. Please see the log for more details."));
             break;
         }
         return false;
@@ -530,6 +536,9 @@ void GMainWindow::OnMenuRecentFile() {
 
 void GMainWindow::OnStartGame() {
     emu_thread->SetRunning(true);
+    qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
+    connect(emu_thread.get(), SIGNAL(ErrorThrown(Core::System::ResultStatus)), this,
+            SLOT(OnCoreError(Core::System::ResultStatus)));
 
     ui.action_Start->setEnabled(false);
     ui.action_Start->setText(tr("Continue"));
@@ -622,14 +631,57 @@ void GMainWindow::UpdateStatusBar() {
     emu_frametime_label->setVisible(true);
 }
 
+void GMainWindow::OnCoreError(Core::System::ResultStatus result) {
+    // Waiting for the dialog to be closed before shutting down causes a segfault, maybe because of
+    // the profiler
+    ShutdownGame();
+    switch (result) {
+    case Core::System::ResultStatus::ErrorSystemFiles:
+        QMessageBox::critical(
+            this, "System Archive Not Found",
+            "Citra was unable to locate the 3DS system archive.<br/><br/>"
+            "The game you are trying to load requires additional files from your 3DS to be dumped "
+            "before playing.<br/><br/>"
+            "For more information on dumping these files, please see the following wiki page: "
+            "<a "
+            "href='https://citra-emu.org/wiki/"
+            "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
+            "Archives and the Shared Fonts from a 3DS Console</a>"
+            ".");
+        break;
+
+    case Core::System::ResultStatus::ErrorSharedFont:
+        QMessageBox::critical(
+            this, "Shared Fonts Not Found",
+            "Citra was unable to locate the 3DS shared fonts.<br/><br/>"
+            "The game you are trying to load requires additional files from your 3DS to be dumped "
+            "before playing.<br/><br/>"
+            "For more information on dumping these files, please see the following wiki page: "
+            "<a "
+            "href='https://citra-emu.org/wiki/"
+            "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
+            "Archives and the Shared Fonts from a 3DS Console</a>"
+            ".");
+        break;
+
+    case Core::System::ResultStatus::ErrorUnknown:
+        QMessageBox::critical(
+            this, "Fatal Error",
+            "Citra has encountered a fatal error, please see the log for more details.");
+        break;
+
+    default:
+        break;
+    }
+}
+
 bool GMainWindow::ConfirmClose() {
     if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
         return true;
 
-    auto answer =
-        QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
-                              QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
-    return answer != QMessageBox::No;
+    return QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
+                                 QMessageBox::Yes | QMessageBox::No,
+                                 QMessageBox::No) != QMessageBox::No;
 }
 
 void GMainWindow::closeEvent(QCloseEvent* event) {
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index cb2e87cbd..1ce0607e2 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -125,6 +125,7 @@ private slots:
     void OnDisplayTitleBars(bool);
     void ToggleWindowMode();
     void OnCreateGraphicsSurfaceViewer();
+    void OnCoreError(Core::System::ResultStatus);
 
 private:
     void UpdateStatusBar();
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 450e7566d..1861bfa9b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -59,7 +59,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
     HW::Update();
     Reschedule();
 
-    return ResultStatus::Success;
+    return GetStatus();
 }
 
 System::ResultStatus System::SingleStep() {
@@ -73,11 +73,21 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
         return ResultStatus::ErrorGetLoader;
     }
+    boost::optional<u32> system_mode = boost::none;
 
-    boost::optional<u32> system_mode{app_loader->LoadKernelSystemMode()};
+    Loader::ResultStatus load_result{app_loader->LoadKernelSystemMode(system_mode)};
     if (!system_mode) {
-        LOG_CRITICAL(Core, "Failed to determine system mode!");
-        return ResultStatus::ErrorSystemMode;
+        LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!", load_result);
+        System::Shutdown();
+
+        switch (load_result) {
+        case Loader::ResultStatus::ErrorEncrypted:
+            return ResultStatus::ErrorLoader_ErrorEncrypted;
+        case Loader::ResultStatus::ErrorInvalidFormat:
+            return ResultStatus::ErrorLoader_ErrorInvalidFormat;
+        default:
+            return ResultStatus::ErrorSystemMode;
+        }
     }
 
     ResultStatus init_result{Init(emu_window, system_mode.get())};
@@ -87,7 +97,7 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         return init_result;
     }
 
-    const Loader::ResultStatus load_result{app_loader->Load()};
+    load_result = app_loader->Load();
     if (Loader::ResultStatus::Success != load_result) {
         LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
         System::Shutdown();
@@ -101,6 +111,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
             return ResultStatus::ErrorLoader;
         }
     }
+    // this->status will be used for errors while actually running the game
+    status = ResultStatus::Success;
     return ResultStatus::Success;
 }
 
@@ -142,7 +154,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
     GDBStub::Init();
 
     if (!VideoCore::Init(emu_window)) {
-        return ResultStatus::ErrorVideoCore;
+        return ResultStatus::ErrorOpenGL;
     }
 
     LOG_DEBUG(Core, "Initialized OK");
diff --git a/src/core/core.h b/src/core/core.h
index 6af772831..0963f273e 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -40,7 +40,11 @@ public:
         ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
         ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an
                                         /// invalid format
+        ErrorSystemFiles,               ///< Error in finding system files
+        ErrorSharedFont,                ///< Error in finding shared font
         ErrorVideoCore,                 ///< Error in the video core
+        ErrorOpenGL,                    ///< Error when initializing OpenGL
+        ErrorUnknown                    ///< Any other error
     };
 
     /**
@@ -105,6 +109,14 @@ public:
     PerfStats perf_stats;
     FrameLimiter frame_limiter;
 
+    ResultStatus GetStatus() {
+        return status;
+    }
+
+    void SetStatus(ResultStatus newStatus) {
+        status = newStatus;
+    }
+
 private:
     /**
      * Initialize the emulated system.
@@ -130,6 +142,7 @@ private:
     std::unique_ptr<Core::TelemetrySession> telemetry_session;
 
     static System s_instance;
+    ResultStatus status;
 };
 
 inline ARM_Interface& CPU() {
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 366d1eacf..a92abb58f 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -5,6 +5,7 @@
 #include "common/common_paths.h"
 #include "common/file_util.h"
 #include "common/logging/log.h"
+#include "core/core.h"
 #include "core/hle/applets/applet.h"
 #include "core/hle/kernel/event.h"
 #include "core/hle/kernel/mutex.h"
@@ -74,6 +75,7 @@ void GetSharedFont(Service::Interface* self) {
         LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
         rb.Push<u32>(-1); // TODO: Find the right error code
         rb.Skip(1 + 2, true);
+        Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSharedFont);
         return;
     }
 
@@ -279,8 +281,9 @@ void CancelParameter(Service::Interface* self) {
     rb.Push(RESULT_SUCCESS); // No error
     rb.Push(true);           // Set to Success
 
-    LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, "
-                             "check_receiver=0x%08X, receiver_appid=0x%08X",
+    LOG_WARNING(Service_APT,
+                "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, "
+                "check_receiver=0x%08X, receiver_appid=0x%08X",
                 check_sender, sender_appid, check_receiver, receiver_appid);
 }
 
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 9da55f328..4f4dc6dc7 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -10,6 +10,7 @@
 #include "common/bit_field.h"
 #include "common/common_types.h"
 #include "common/logging/log.h"
+#include "core/core.h"
 #include "core/hle/result.h"
 #include "core/hle/service/err_f.h"
 
@@ -172,6 +173,7 @@ static void ThrowFatalError(Interface* self) {
     const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
     LOG_CRITICAL(Service_ERR, "Fatal error type: %s",
                  GetErrType(errinfo->errinfo_common.specifier).c_str());
+    Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorUnknown);
 
     // Generic Info
     LogGenericInfo(errinfo->errinfo_common);
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index e53a970d3..5a4437123 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -8,6 +8,7 @@
 #include "common/logging/log.h"
 #include "common/scope_exit.h"
 #include "common/string_util.h"
+#include "core/core.h"
 #include "core/file_sys/errors.h"
 #include "core/hle/kernel/client_session.h"
 #include "core/hle/result.h"
@@ -132,6 +133,10 @@ static void OpenFileDirectly(Service::Interface* self) {
         LOG_ERROR(Service_FS,
                   "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
                   static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
+        if (static_cast<u32>(archive_id) == 0x2345678A) {
+            Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles);
+            return;
+        }
         cmd_buff[1] = archive_handle.Code().raw;
         cmd_buff[3] = 0;
         return;

From 37bec598ea28662462dcaab65d5abd6db8372dbc Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Wed, 8 Mar 2017 20:21:31 -0500
Subject: [PATCH 03/10] Made some changes from review comments: - Made
 LoadKernelSystemMode return a pair consisting of a system mode and a result
 code (Could use review). - Deleted ErrorOpenGL error code in favor of just
 having ErrorVideoCore. - Made dialog messages more clear. - Compared archive
 ID in fs_user.cpp to ArchiveIdCode::NCCH as opposed to hex magic. - Cleaned
 up some other stuff.

---
 src/citra_qt/bootmanager.cpp        |  1 -
 src/citra_qt/main.cpp               | 39 ++++++++++++++++-------------
 src/core/core.cpp                   | 22 +++++++++-------
 src/core/core.h                     |  1 -
 src/core/file_sys/archive_ncch.cpp  |  3 ++-
 src/core/hle/service/fs/archive.cpp |  8 +++---
 src/core/hle/service/fs/fs_user.cpp |  7 +++---
 src/core/loader/loader.h            | 11 ++++----
 src/core/loader/ncch.cpp            | 11 +++-----
 src/core/loader/ncch.h              |  5 ++--
 10 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 16661767f..0fdf0c600 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -40,7 +40,6 @@ void EmuThread::run() {
             Core::System::ResultStatus result = Core::System::GetInstance().RunLoop();
             if (result != Core::System::ResultStatus::Success) {
                 emit ErrorThrown(result);
-                break;
             }
 
             was_active = running || exec_step;
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index e24c48e90..cc38cfc0e 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -300,7 +300,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
     render_window->MakeCurrent();
 
     if (!gladLoadGL()) {
-        QMessageBox::critical(this, tr("Error while starting Citra!"),
+        QMessageBox::critical(this, tr("Error while initializing OpenGL 3.3 Core!"),
                               tr("Your GPU may not support OpenGL 3.3, or you do not"
                                  "have the latest graphics driver."));
         return false;
@@ -329,7 +329,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
             QMessageBox::critical(
                 this, tr("Error while loading ROM!"),
                 tr("The game that you are trying to load must be decrypted before being used with "
-                   "Citra.<br/><br/>"
+                   "Citra. A real 3DS is required.<br/><br/>"
                    "For more information on dumping and decrypting games, please see the following "
                    "wiki pages: <ul>"
                    "<li><a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges/'>Dumping Game "
@@ -344,10 +344,17 @@ bool GMainWindow::LoadROM(const QString& filename) {
                                   tr("The ROM format is not supported."));
             break;
 
-        case Core::System::ResultStatus::ErrorOpenGL:
-            QMessageBox::critical(this, tr("Error while loading OpenGL!"),
-                                  tr("Your GPU may not support OpenGL 3.3, or you do not "
-                                     "have the latest graphics driver."));
+        case Core::System::ResultStatus::ErrorVideoCore:
+            QMessageBox::critical(
+                this, tr("An error occured in the video core."),
+                tr("Citra has encountered an error while running the video core,  please see the "
+                   "log for more details."
+                   "For more information on accessing the log, please see the following page: "
+                   "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
+                   "to "
+                   "Upload the Log File</a>."
+                   "Ensure that you have the latest graphics drivers for your GPU."));
+
             break;
 
         default:
@@ -632,9 +639,6 @@ void GMainWindow::UpdateStatusBar() {
 }
 
 void GMainWindow::OnCoreError(Core::System::ResultStatus result) {
-    // Waiting for the dialog to be closed before shutting down causes a segfault, maybe because of
-    // the profiler
-    ShutdownGame();
     switch (result) {
     case Core::System::ResultStatus::ErrorSystemFiles:
         QMessageBox::critical(
@@ -664,13 +668,13 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result) {
             ".");
         break;
 
-    case Core::System::ResultStatus::ErrorUnknown:
+    default:
         QMessageBox::critical(
             this, "Fatal Error",
-            "Citra has encountered a fatal error, please see the log for more details.");
-        break;
-
-    default:
+            "Citra has encountered a fatal error, please see the log for more details. "
+            "For more information on accessing the log, please see the following page: "
+            "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
+            "Upload the Log File</a>.");
         break;
     }
 }
@@ -679,9 +683,10 @@ bool GMainWindow::ConfirmClose() {
     if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
         return true;
 
-    return QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
-                                 QMessageBox::Yes | QMessageBox::No,
-                                 QMessageBox::No) != QMessageBox::No;
+    auto answer =
+        QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
+                              QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+    return answer != QMessageBox::No;
 }
 
 void GMainWindow::closeEvent(QCloseEvent* event) {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 1861bfa9b..2a9664cb4 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,6 +3,9 @@
 // Refer to the license.txt file included.
 
 #include <memory>
+#include <utility>
+
+#include <boost/optional.hpp>
 
 #include "audio_core/audio_core.h"
 #include "common/logging/log.h"
@@ -26,6 +29,7 @@ namespace Core {
 /*static*/ System System::s_instance;
 
 System::ResultStatus System::RunLoop(int tight_loop) {
+    this->status = ResultStatus::Success;
     if (!cpu_core) {
         return ResultStatus::ErrorNotInitialized;
     }
@@ -73,14 +77,14 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
         return ResultStatus::ErrorGetLoader;
     }
-    boost::optional<u32> system_mode = boost::none;
+    std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode =
+        app_loader->LoadKernelSystemMode();
 
-    Loader::ResultStatus load_result{app_loader->LoadKernelSystemMode(system_mode)};
-    if (!system_mode) {
-        LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!", load_result);
+    if (system_mode.second != Loader::ResultStatus::Success) {
+        LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!", system_mode.second);
         System::Shutdown();
 
-        switch (load_result) {
+        switch (system_mode.second) {
         case Loader::ResultStatus::ErrorEncrypted:
             return ResultStatus::ErrorLoader_ErrorEncrypted;
         case Loader::ResultStatus::ErrorInvalidFormat:
@@ -90,15 +94,15 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         }
     }
 
-    ResultStatus init_result{Init(emu_window, system_mode.get())};
+    ResultStatus init_result{Init(emu_window, system_mode.first.get())};
     if (init_result != ResultStatus::Success) {
         LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result);
         System::Shutdown();
         return init_result;
     }
 
-    load_result = app_loader->Load();
-    if (Loader::ResultStatus::Success != load_result) {
+    Loader::ResultStatus load_result = app_loader->Load();
+    if (load_result != Loader::ResultStatus::Success) {
         LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
         System::Shutdown();
 
@@ -154,7 +158,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
     GDBStub::Init();
 
     if (!VideoCore::Init(emu_window)) {
-        return ResultStatus::ErrorOpenGL;
+        return ResultStatus::ErrorVideoCore;
     }
 
     LOG_DEBUG(Core, "Initialized OK");
diff --git a/src/core/core.h b/src/core/core.h
index 0963f273e..a7b4f8d62 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -43,7 +43,6 @@ public:
         ErrorSystemFiles,               ///< Error in finding system files
         ErrorSharedFont,                ///< Error in finding shared font
         ErrorVideoCore,                 ///< Error in the video core
-        ErrorOpenGL,                    ///< Error when initializing OpenGL
         ErrorUnknown                    ///< Any other error
     };
 
diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index 89455e39c..bf4e0916b 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -37,7 +37,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path&
     auto file = std::make_shared<FileUtil::IOFile>(file_path, "rb");
 
     if (!file->IsOpen()) {
-        return ResultCode(-1); // TODO(Subv): Find the right error code
+        return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
+                          ErrorLevel::Status);
     }
     auto size = file->GetSize();
 
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 632712f2c..6d1a49d92 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -257,11 +257,9 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
     LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code);
 
     auto itr = id_code_map.find(id_code);
-    if (itr == id_code_map.end()) {
-        // TODO: Verify error against hardware
-        return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound,
-                          ErrorLevel::Permanent);
-    }
+    if (itr == id_code_map.end())
+        return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
+                          ErrorLevel::Status);
 
     CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
 
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 5a4437123..0538ffc9c 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -133,12 +133,11 @@ static void OpenFileDirectly(Service::Interface* self) {
         LOG_ERROR(Service_FS,
                   "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
                   static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
-        if (static_cast<u32>(archive_id) == 0x2345678A) {
-            Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles);
-            return;
-        }
         cmd_buff[1] = archive_handle.Code().raw;
         cmd_buff[3] = 0;
+        if (static_cast<FS::ArchiveIdCode>(archive_id) == ArchiveIdCode::NCCH) {
+            Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles);
+        }
         return;
     }
     SCOPE_EXIT({ CloseArchive(*archive_handle); });
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 21f73503e..0a2d4a10e 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -8,8 +8,11 @@
 #include <initializer_list>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
+
 #include <boost/optional.hpp>
+
 #include "common/common_types.h"
 #include "common/file_util.h"
 
@@ -100,13 +103,11 @@ public:
      * Loads the system mode that this application needs.
      * This function defaults to 2 (96MB allocated to the application) if it can't read the
      * information.
-     * @param boost::optional<u32> Reference to Boost optional to store system mode.
-     * @ return Result of operation.
+     * @return A pair with the system mode (If found) and the result.
      */
-    virtual ResultStatus LoadKernelSystemMode(boost::optional<u32>& system_mode) {
+    virtual std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() {
         // 96MB allocated to the application.
-        system_mode = 2;
-        return ResultStatus::Success;
+        return std::make_pair(2, ResultStatus::Success);
     }
 
     /**
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 1a20762e4..ffc019560 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -121,19 +121,16 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) {
     return FileType::Error;
 }
 
-ResultStatus AppLoader_NCCH::LoadKernelSystemMode(boost::optional<u32>& system_mode) {
+std::pair<boost::optional<u32>, ResultStatus> AppLoader_NCCH::LoadKernelSystemMode() {
     if (!is_loaded) {
         ResultStatus res = LoadExeFS();
         if (res != ResultStatus::Success) {
-            // Set the system mode as invalid.
-            system_mode = boost::none;
-            // Return the error code.
-            return res;
+            return std::make_pair(boost::none, res);
         }
     }
     // Set the system mode as the one from the exheader.
-    system_mode = exheader_header.arm11_system_local_caps.system_mode.Value();
-    return ResultStatus::Success;
+    return std::make_pair(exheader_header.arm11_system_local_caps.system_mode.Value(),
+                          ResultStatus::Success);
 }
 
 ResultStatus AppLoader_NCCH::LoadExec() {
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 269fe4f49..712d496a4 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -179,10 +179,9 @@ public:
 
     /**
      * Loads the Exheader and returns the system mode for this application.
-     * @param boost::optional<u32> Reference to Boost optional to store system mode.
-     * @return Result of operation.
+     * @return A pair with the system mode (If found) and the result.
      */
-    ResultStatus LoadKernelSystemMode(boost::optional<u32>& system_mode) override;
+    std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() override;
 
     ResultStatus ReadCode(std::vector<u8>& buffer) override;
 

From b6bab59000cbcdb34aed3f8633c5aae391db6dcb Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Thu, 13 Apr 2017 01:10:19 -0400
Subject: [PATCH 04/10] Added message to status bar to show core errors ignored
 by the user.

---
 src/citra_qt/main.cpp | 11 ++++++++++-
 src/citra_qt/main.h   |  1 +
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index cc38cfc0e..6121d4728 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -93,6 +93,14 @@ void GMainWindow::InitializeWidgets() {
     ui.horizontalLayout->addWidget(game_list);
 
     // Create status bar
+    message_label = new QLabel();
+    // Configured separately for left alignment
+    message_label->setVisible(false);
+    message_label->setFrameStyle(QFrame::NoFrame);
+    message_label->setContentsMargins(4, 0, 4, 0);
+    message_label->setAlignment(Qt::AlignLeft);
+    statusBar()->addPermanentWidget(message_label, 1);
+
     emu_speed_label = new QLabel();
     emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% "
                                    "indicate emulation is running faster or slower than a 3DS."));
@@ -108,7 +116,7 @@ void GMainWindow::InitializeWidgets() {
         label->setVisible(false);
         label->setFrameStyle(QFrame::NoFrame);
         label->setContentsMargins(4, 0, 4, 0);
-        statusBar()->addPermanentWidget(label);
+        statusBar()->addPermanentWidget(label, 0);
     }
     statusBar()->setVisible(true);
     setStyleSheet("QStatusBar::item{border: none;}");
@@ -437,6 +445,7 @@ void GMainWindow::ShutdownGame() {
 
     // Disable status bar updates
     status_bar_update_timer.stop();
+    message_label->setVisible(false);
     emu_speed_label->setVisible(false);
     game_fps_label->setVisible(false);
     emu_frametime_label->setVisible(false);
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 1ce0607e2..3ecbc001e 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -136,6 +136,7 @@ private:
     GameList* game_list;
 
     // Status bar elements
+    QLabel* message_label = nullptr;
     QLabel* emu_speed_label = nullptr;
     QLabel* game_fps_label = nullptr;
     QLabel* emu_frametime_label = nullptr;

From 0409bdfea5ea046e3d040ab494b8a0764fd35424 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Thu, 13 Apr 2017 01:15:23 -0400
Subject: [PATCH 05/10] Optimized messages that were repetitive and added
 ability for core errors to specify more details optionally.

---
 src/citra_qt/bootmanager.cpp |  2 +-
 src/citra_qt/bootmanager.h   |  2 +-
 src/citra_qt/main.cpp        | 88 ++++++++++++++++++++++--------------
 src/citra_qt/main.h          |  2 +-
 src/core/core.h              | 17 ++++++-
 5 files changed, 71 insertions(+), 40 deletions(-)

diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 0fdf0c600..a8a4aed8b 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -39,7 +39,7 @@ void EmuThread::run() {
 
             Core::System::ResultStatus result = Core::System::GetInstance().RunLoop();
             if (result != Core::System::ResultStatus::Success) {
-                emit ErrorThrown(result);
+                emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails());
             }
 
             was_active = running || exec_step;
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index c5430a3fa..b12b37132 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -99,7 +99,7 @@ signals:
      */
     void DebugModeLeft();
 
-    void ErrorThrown(Core::System::ResultStatus);
+    void ErrorThrown(Core::System::ResultStatus, boost::optional<std::string>);
 };
 
 class GRenderWindow : public QWidget, public EmuWindow {
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 6121d4728..1688e55cd 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -553,8 +553,10 @@ void GMainWindow::OnMenuRecentFile() {
 void GMainWindow::OnStartGame() {
     emu_thread->SetRunning(true);
     qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
-    connect(emu_thread.get(), SIGNAL(ErrorThrown(Core::System::ResultStatus)), this,
-            SLOT(OnCoreError(Core::System::ResultStatus)));
+    qRegisterMetaType<boost::optional<std::string>>("boost::optional<std::string>");
+    connect(emu_thread.get(),
+            SIGNAL(ErrorThrown(Core::System::ResultStatus, boost::optional<std::string>)), this,
+            SLOT(OnCoreError(Core::System::ResultStatus, boost::optional<std::string>)));
 
     ui.action_Start->setEnabled(false);
     ui.action_Start->setText(tr("Continue"));
@@ -647,52 +649,68 @@ void GMainWindow::UpdateStatusBar() {
     emu_frametime_label->setVisible(true);
 }
 
-void GMainWindow::OnCoreError(Core::System::ResultStatus result) {
+void GMainWindow::OnCoreError(Core::System::ResultStatus result,
+                              boost::optional<std::string> details) {
+    QMessageBox::StandardButton answer;
+    QString status_message;
+    const QString common_message =
+        tr("The game you are trying to load requires additional files from your 3DS to be dumped "
+           "before playing.<br/><br/>For more information on dumping these files, please see the "
+           "following wiki page: <a "
+           "href='https://citra-emu.org/wiki/"
+           "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
+           "Archives and the Shared Fonts from a 3DS Console</a>.<br/><br/>Would you like to quit "
+           "back to the game list?");
     switch (result) {
-    case Core::System::ResultStatus::ErrorSystemFiles:
-        QMessageBox::critical(
-            this, "System Archive Not Found",
-            "Citra was unable to locate the 3DS system archive.<br/><br/>"
-            "The game you are trying to load requires additional files from your 3DS to be dumped "
-            "before playing.<br/><br/>"
-            "For more information on dumping these files, please see the following wiki page: "
-            "<a "
-            "href='https://citra-emu.org/wiki/"
-            "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
-            "Archives and the Shared Fonts from a 3DS Console</a>"
-            ".");
-        break;
+    case Core::System::ResultStatus::ErrorSystemFiles: {
+        QString message = "Citra was unable to locate a 3DS system archive";
+        if (details)
+            message.append(tr(": %1. ").arg(details.get().c_str()));
+        else
+            message.append(". ");
+        message.append(common_message);
 
-    case Core::System::ResultStatus::ErrorSharedFont:
-        QMessageBox::critical(
-            this, "Shared Fonts Not Found",
-            "Citra was unable to locate the 3DS shared fonts.<br/><br/>"
-            "The game you are trying to load requires additional files from your 3DS to be dumped "
-            "before playing.<br/><br/>"
-            "For more information on dumping these files, please see the following wiki page: "
-            "<a "
-            "href='https://citra-emu.org/wiki/"
-            "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
-            "Archives and the Shared Fonts from a 3DS Console</a>"
-            ".");
+        answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
+                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+        status_message = "System Archive Missing";
         break;
+    }
+
+    case Core::System::ResultStatus::ErrorSharedFont: {
+        QString message = tr("Citra was unable to locate the 3DS shared fonts. ");
+        message.append(common_message);
+        answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
+                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+        status_message = "Shared Font Missing";
+        break;
+    }
 
     default:
-        QMessageBox::critical(
-            this, "Fatal Error",
-            "Citra has encountered a fatal error, please see the log for more details. "
-            "For more information on accessing the log, please see the following page: "
-            "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
-            "Upload the Log File</a>.");
+        answer = QMessageBox::question(
+            this, tr("Fatal Error"),
+            tr("Citra has encountered a fatal error, please see the log for more details. "
+               "For more information on accessing the log, please see the following page: "
+               "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
+               "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game list?"),
+            QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+        status_message = "Fatal Error encountered.";
         break;
     }
+
+    if (answer == QMessageBox::Yes) {
+        if (emu_thread != nullptr)
+            ShutdownGame();
+    } else {
+        message_label->setText(status_message);
+        message_label->setVisible(true);
+    }
 }
 
 bool GMainWindow::ConfirmClose() {
     if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
         return true;
 
-    auto answer =
+    QMessageBox::StandardButton answer =
         QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
                               QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
     return answer != QMessageBox::No;
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 3ecbc001e..eb2b055f6 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -125,7 +125,7 @@ private slots:
     void OnDisplayTitleBars(bool);
     void ToggleWindowMode();
     void OnCreateGraphicsSurfaceViewer();
-    void OnCoreError(Core::System::ResultStatus);
+    void OnCoreError(Core::System::ResultStatus, boost::optional<std::string>);
 
 private:
     void UpdateStatusBar();
diff --git a/src/core/core.h b/src/core/core.h
index a7b4f8d62..bc363ed97 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -6,6 +6,9 @@
 
 #include <memory>
 #include <string>
+
+#include <boost/optional.hpp>
+
 #include "common/common_types.h"
 #include "core/memory.h"
 #include "core/perf_stats.h"
@@ -112,8 +115,16 @@ public:
         return status;
     }
 
-    void SetStatus(ResultStatus newStatus) {
-        status = newStatus;
+    void SetStatus(ResultStatus new_status, std::string details = std::string()) {
+        status = new_status;
+        if (details == std::string())
+            status_details = boost::none;
+        else
+            status_details = details;
+    }
+
+    boost::optional<std::string> GetStatusDetails() {
+        return status_details;
     }
 
 private:
@@ -141,7 +152,9 @@ private:
     std::unique_ptr<Core::TelemetrySession> telemetry_session;
 
     static System s_instance;
+
     ResultStatus status;
+    boost::optional<std::string> status_details;
 };
 
 inline ARM_Interface& CPU() {

From a8aef599e02e336f9ecb8d5cfc50aa856ea0a1c7 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Thu, 13 Apr 2017 01:18:54 -0400
Subject: [PATCH 06/10] Created a whitelist of system archives to prevent false
 positives creating dialogs.

---
 src/citra_qt/bootmanager.h          |  2 +-
 src/citra_qt/main.cpp               | 16 ++++-----
 src/citra_qt/main.h                 |  3 +-
 src/core/core.cpp                   |  6 ++--
 src/core/core.h                     | 12 ++-----
 src/core/hle/service/apt/apt.cpp    |  5 ++-
 src/core/hle/service/fs/fs_user.cpp | 55 ++++++++++++++++++++++++++---
 src/core/loader/loader.h            |  4 +--
 src/core/loader/ncch.h              |  2 +-
 9 files changed, 70 insertions(+), 35 deletions(-)

diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index b12b37132..4b3a3b3cc 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -99,7 +99,7 @@ signals:
      */
     void DebugModeLeft();
 
-    void ErrorThrown(Core::System::ResultStatus, boost::optional<std::string>);
+    void ErrorThrown(Core::System::ResultStatus, std::string);
 };
 
 class GRenderWindow : public QWidget, public EmuWindow {
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 1688e55cd..e3b296188 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -553,10 +553,9 @@ void GMainWindow::OnMenuRecentFile() {
 void GMainWindow::OnStartGame() {
     emu_thread->SetRunning(true);
     qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
-    qRegisterMetaType<boost::optional<std::string>>("boost::optional<std::string>");
-    connect(emu_thread.get(),
-            SIGNAL(ErrorThrown(Core::System::ResultStatus, boost::optional<std::string>)), this,
-            SLOT(OnCoreError(Core::System::ResultStatus, boost::optional<std::string>)));
+    qRegisterMetaType<std::string>("std::string");
+    connect(emu_thread.get(), SIGNAL(ErrorThrown(Core::System::ResultStatus, std::string)), this,
+            SLOT(OnCoreError(Core::System::ResultStatus, std::string)));
 
     ui.action_Start->setEnabled(false);
     ui.action_Start->setText(tr("Continue"));
@@ -649,8 +648,7 @@ void GMainWindow::UpdateStatusBar() {
     emu_frametime_label->setVisible(true);
 }
 
-void GMainWindow::OnCoreError(Core::System::ResultStatus result,
-                              boost::optional<std::string> details) {
+void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
     QMessageBox::StandardButton answer;
     QString status_message;
     const QString common_message =
@@ -664,8 +662,8 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result,
     switch (result) {
     case Core::System::ResultStatus::ErrorSystemFiles: {
         QString message = "Citra was unable to locate a 3DS system archive";
-        if (details)
-            message.append(tr(": %1. ").arg(details.get().c_str()));
+        if (details != std::string())
+            message.append(tr(": %1. ").arg(details.c_str()));
         else
             message.append(". ");
         message.append(common_message);
@@ -693,7 +691,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result,
                "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
                "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game list?"),
             QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
-        status_message = "Fatal Error encountered.";
+        status_message = "Fatal Error encountered";
         break;
     }
 
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index eb2b055f6..952a50974 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <QMainWindow>
 #include <QTimer>
+#include "core/core.h"
 #include "ui_main.h"
 
 class Config;
@@ -125,7 +126,7 @@ private slots:
     void OnDisplayTitleBars(bool);
     void ToggleWindowMode();
     void OnCreateGraphicsSurfaceViewer();
-    void OnCoreError(Core::System::ResultStatus, boost::optional<std::string>);
+    void OnCoreError(Core::System::ResultStatus, std::string);
 
 private:
     void UpdateStatusBar();
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 2a9664cb4..2456d8aa2 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -4,9 +4,6 @@
 
 #include <memory>
 #include <utility>
-
-#include <boost/optional.hpp>
-
 #include "audio_core/audio_core.h"
 #include "common/logging/log.h"
 #include "core/arm/arm_interface.h"
@@ -81,7 +78,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         app_loader->LoadKernelSystemMode();
 
     if (system_mode.second != Loader::ResultStatus::Success) {
-        LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!", system_mode.second);
+        LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!",
+                     static_cast<int>(system_mode.second));
         System::Shutdown();
 
         switch (system_mode.second) {
diff --git a/src/core/core.h b/src/core/core.h
index bc363ed97..6e555f954 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -6,9 +6,6 @@
 
 #include <memory>
 #include <string>
-
-#include <boost/optional.hpp>
-
 #include "common/common_types.h"
 #include "core/memory.h"
 #include "core/perf_stats.h"
@@ -117,13 +114,10 @@ public:
 
     void SetStatus(ResultStatus new_status, std::string details = std::string()) {
         status = new_status;
-        if (details == std::string())
-            status_details = boost::none;
-        else
-            status_details = details;
+        status_details = details;
     }
 
-    boost::optional<std::string> GetStatusDetails() {
+    std::string GetStatusDetails() {
         return status_details;
     }
 
@@ -154,7 +148,7 @@ private:
     static System s_instance;
 
     ResultStatus status;
-    boost::optional<std::string> status_details;
+    std::string status_details;
 };
 
 inline ARM_Interface& CPU() {
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index a92abb58f..4c587e3c8 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -281,9 +281,8 @@ void CancelParameter(Service::Interface* self) {
     rb.Push(RESULT_SUCCESS); // No error
     rb.Push(true);           // Set to Success
 
-    LOG_WARNING(Service_APT,
-                "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, "
-                "check_receiver=0x%08X, receiver_appid=0x%08X",
+    LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, "
+                             "check_receiver=0x%08X, receiver_appid=0x%08X",
                 check_sender, sender_appid, check_receiver, receiver_appid);
 }
 
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 0538ffc9c..c65d46238 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -130,14 +130,61 @@ static void OpenFileDirectly(Service::Interface* self) {
 
     ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
     if (archive_handle.Failed()) {
-        LOG_ERROR(Service_FS,
-                  "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
-                  static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
         cmd_buff[1] = archive_handle.Code().raw;
         cmd_buff[3] = 0;
+
         if (static_cast<FS::ArchiveIdCode>(archive_id) == ArchiveIdCode::NCCH) {
-            Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles);
+            // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list).
+            // (Note: The values there are big endian, these must be little endian.)
+            const std::vector<u8> shared_data_archive = {0x9B, 0x00, 0x04, 0x00};
+            const std::vector<u8> system_data_archive = {0xDB, 0x00, 0x04, 0x00};
+
+            // Low Title IDs.
+            const std::vector<u8> mii_data = {0x02, 0x02, 0x01, 0x00};
+            const std::vector<u8> region_manifest = {0x02, 0x04, 0x01, 0x00};
+            const std::vector<u8> ng_word_list = {0x02, 0x03, 0x01, 0x00};
+
+            // Make a copy of the binary path because reusing AsBinary() for creating category
+            // results in bad_alloc being thrown.
+            std::vector<u8> binary_archive_path = archive_path.AsBinary();
+            std::vector<u8> category(binary_archive_path.begin() + 4,
+                                     binary_archive_path.begin() + 8);
+            std::vector<u8> path(binary_archive_path.begin(), binary_archive_path.begin() + 4);
+
+            if (category == shared_data_archive) {
+                if (path == mii_data) {
+                    LOG_ERROR(Service_FS,
+                              "Failed to get a handle for shared data archive: Mii data. "
+                              "Archive ID=0x%08X Archive Path=%s",
+                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
+                    Core::System::GetInstance().SetStatus(
+                        Core::System::ResultStatus::ErrorSystemFiles, "Mii data");
+                    return;
+                } else if (path == region_manifest) {
+                    LOG_ERROR(Service_FS,
+                              "Failed to get a handle for shared data archive: region manifest. "
+                              "Archive ID=0x%08X Archive Path=%s",
+                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
+                    Core::System::GetInstance().SetStatus(
+                        Core::System::ResultStatus::ErrorSystemFiles, "Region manifest");
+                    return;
+                }
+            } else if (category == system_data_archive) {
+                if (path == ng_word_list) {
+                    LOG_ERROR(Service_FS,
+                              "Failed to get a handle for system data archive: NG bad word list. "
+                              "Archive ID=0x%08X Archive Path=%s",
+                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
+                    Core::System::GetInstance().SetStatus(
+                        Core::System::ResultStatus::ErrorSystemFiles, "NG bad word list");
+                    return;
+                }
+            }
         }
+
+        LOG_ERROR(Service_FS,
+                  "Failed to get a handle for archive archive_id=0x%08X archive_path=%s",
+                  static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
         return;
     }
     SCOPE_EXIT({ CloseArchive(*archive_handle); });
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 0a2d4a10e..adb3ffdcf 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -10,9 +10,7 @@
 #include <string>
 #include <utility>
 #include <vector>
-
 #include <boost/optional.hpp>
-
 #include "common/common_types.h"
 #include "common/file_util.h"
 
@@ -103,7 +101,7 @@ public:
      * Loads the system mode that this application needs.
      * This function defaults to 2 (96MB allocated to the application) if it can't read the
      * information.
-     * @return A pair with the system mode (If found) and the result.
+     * @returns a pair of Optional with the kernel system mode and ResultStatus.
      */
     virtual std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() {
         // 96MB allocated to the application.
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 712d496a4..507da7550 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -179,7 +179,7 @@ public:
 
     /**
      * Loads the Exheader and returns the system mode for this application.
-     * @return A pair with the system mode (If found) and the result.
+     * @returns a pair of Optional with the kernel system mode and ResultStatus
      */
     std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() override;
 

From cea19fd659496bcdf09a12b163ce490c1fa71ff7 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Tue, 23 May 2017 19:46:30 -0400
Subject: [PATCH 07/10] Moved whitelist checks from FS_User to the Archive_NCCH
 handler.

---
 src/core/file_sys/archive_ncch.cpp  | 36 ++++++++++++++++++-
 src/core/hle/service/fs/fs_user.cpp | 54 ++---------------------------
 2 files changed, 37 insertions(+), 53 deletions(-)

diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index bf4e0916b..84950f871 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -9,6 +9,7 @@
 #include "common/file_util.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
+#include "core/core.h"
 #include "core/file_sys/archive_ncch.h"
 #include "core/file_sys/ivfc_archive.h"
 #include "core/hle/service/fs/archive.h"
@@ -33,10 +34,43 @@ ArchiveFactory_NCCH::ArchiveFactory_NCCH(const std::string& nand_directory)
 ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path) {
     auto vec = path.AsBinary();
     const u32* data = reinterpret_cast<u32*>(vec.data());
-    std::string file_path = GetNCCHPath(mount_point, data[1], data[0]);
+    u32 high = data[1];
+    u32 low = data[0];
+    std::string file_path = GetNCCHPath(mount_point, high, low);
     auto file = std::make_shared<FileUtil::IOFile>(file_path, "rb");
 
     if (!file->IsOpen()) {
+        // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list).
+        const u32 shared_data_archive = 0x0004009B;
+        const u32 system_data_archive = 0x000400DB;
+
+        // Low Title IDs.
+        const u32 mii_data = 0x00010202;
+        const u32 region_manifest = 0x00010402;
+        const u32 ng_word_list = 0x00010302;
+
+        LOG_DEBUG(Service_FS, "Full Path: %s. Category: 0x%X. Path: 0x%X.", path.DebugStr().c_str(),
+                  high, low);
+
+        if (high == shared_data_archive) {
+            if (low == mii_data) {
+                LOG_ERROR(Service_FS, "Failed to get a handle for shared data archive: Mii data. ");
+                Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
+                                                      "Mii data");
+            } else if (low == region_manifest) {
+                LOG_ERROR(Service_FS,
+                          "Failed to get a handle for shared data archive: region manifes");
+                Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
+                                                      "Region manifest");
+            }
+        } else if (high == system_data_archive) {
+            if (low == ng_word_list) {
+                LOG_ERROR(Service_FS,
+                          "Failed to get a handle for system data archive: NG bad word list.");
+                Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
+                                                      "NG bad word list");
+            }
+        }
         return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
                           ErrorLevel::Status);
     }
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index c65d46238..c1825e9c8 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -130,61 +130,11 @@ static void OpenFileDirectly(Service::Interface* self) {
 
     ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
     if (archive_handle.Failed()) {
-        cmd_buff[1] = archive_handle.Code().raw;
-        cmd_buff[3] = 0;
-
-        if (static_cast<FS::ArchiveIdCode>(archive_id) == ArchiveIdCode::NCCH) {
-            // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list).
-            // (Note: The values there are big endian, these must be little endian.)
-            const std::vector<u8> shared_data_archive = {0x9B, 0x00, 0x04, 0x00};
-            const std::vector<u8> system_data_archive = {0xDB, 0x00, 0x04, 0x00};
-
-            // Low Title IDs.
-            const std::vector<u8> mii_data = {0x02, 0x02, 0x01, 0x00};
-            const std::vector<u8> region_manifest = {0x02, 0x04, 0x01, 0x00};
-            const std::vector<u8> ng_word_list = {0x02, 0x03, 0x01, 0x00};
-
-            // Make a copy of the binary path because reusing AsBinary() for creating category
-            // results in bad_alloc being thrown.
-            std::vector<u8> binary_archive_path = archive_path.AsBinary();
-            std::vector<u8> category(binary_archive_path.begin() + 4,
-                                     binary_archive_path.begin() + 8);
-            std::vector<u8> path(binary_archive_path.begin(), binary_archive_path.begin() + 4);
-
-            if (category == shared_data_archive) {
-                if (path == mii_data) {
-                    LOG_ERROR(Service_FS,
-                              "Failed to get a handle for shared data archive: Mii data. "
-                              "Archive ID=0x%08X Archive Path=%s",
-                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
-                    Core::System::GetInstance().SetStatus(
-                        Core::System::ResultStatus::ErrorSystemFiles, "Mii data");
-                    return;
-                } else if (path == region_manifest) {
-                    LOG_ERROR(Service_FS,
-                              "Failed to get a handle for shared data archive: region manifest. "
-                              "Archive ID=0x%08X Archive Path=%s",
-                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
-                    Core::System::GetInstance().SetStatus(
-                        Core::System::ResultStatus::ErrorSystemFiles, "Region manifest");
-                    return;
-                }
-            } else if (category == system_data_archive) {
-                if (path == ng_word_list) {
-                    LOG_ERROR(Service_FS,
-                              "Failed to get a handle for system data archive: NG bad word list. "
-                              "Archive ID=0x%08X Archive Path=%s",
-                              static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
-                    Core::System::GetInstance().SetStatus(
-                        Core::System::ResultStatus::ErrorSystemFiles, "NG bad word list");
-                    return;
-                }
-            }
-        }
-
         LOG_ERROR(Service_FS,
                   "Failed to get a handle for archive archive_id=0x%08X archive_path=%s",
                   static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
+        cmd_buff[1] = archive_handle.Code().raw;
+        cmd_buff[3] = 0;
         return;
     }
     SCOPE_EXIT({ CloseArchive(*archive_handle); });

From 59de38b96525d1230df07de3d6cda422421fd883 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Wed, 24 May 2017 19:51:31 -0400
Subject: [PATCH 08/10] Switched to the ERROR_NOT_FOUND constant from errors.h.

---
 src/core/file_sys/archive_ncch.cpp  | 4 ++--
 src/core/hle/service/fs/archive.cpp | 3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index 84950f871..ad59c053e 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -11,6 +11,7 @@
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/file_sys/archive_ncch.h"
+#include "core/file_sys/errors.h"
 #include "core/file_sys/ivfc_archive.h"
 #include "core/hle/service/fs/archive.h"
 
@@ -71,8 +72,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path&
                                                       "NG bad word list");
             }
         }
-        return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
-                          ErrorLevel::Status);
+        return ERROR_NOT_FOUND;
     }
     auto size = file->GetSize();
 
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 6d1a49d92..40d52f54b 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -258,8 +258,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
 
     auto itr = id_code_map.find(id_code);
     if (itr == id_code_map.end())
-        return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
-                          ErrorLevel::Status);
+        return FileSys::ERROR_NOT_FOUND;
 
     CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
 

From ff04320c9716b78b7a6047e3c699a0ea4c5431b3 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Thu, 25 May 2017 16:49:46 -0400
Subject: [PATCH 09/10] Fixed wiki URLs.

---
 src/citra_qt/main.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index e3b296188..c899e075f 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -340,9 +340,9 @@ bool GMainWindow::LoadROM(const QString& filename) {
                    "Citra. A real 3DS is required.<br/><br/>"
                    "For more information on dumping and decrypting games, please see the following "
                    "wiki pages: <ul>"
-                   "<li><a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges/'>Dumping Game "
+                   "<li><a href='https://citra-emu.org/wiki/dumping-game-cartridges/'>Dumping Game "
                    "Cartridges</a></li>"
-                   "<li><a href='https://citra-emu.org/wiki/Dumping-Installed-Titles/'>Dumping "
+                   "<li><a href='https://citra-emu.org/wiki/dumping-installed-titles/'>Dumping "
                    "Installed Titles</a></li>"
                    "</ul>"));
             break;
@@ -355,7 +355,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
         case Core::System::ResultStatus::ErrorVideoCore:
             QMessageBox::critical(
                 this, tr("An error occured in the video core."),
-                tr("Citra has encountered an error while running the video core,  please see the "
+                tr("Citra has encountered an error while running the video core, please see the "
                    "log for more details."
                    "For more information on accessing the log, please see the following page: "
                    "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
@@ -656,9 +656,10 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
            "before playing.<br/><br/>For more information on dumping these files, please see the "
            "following wiki page: <a "
            "href='https://citra-emu.org/wiki/"
-           "Dumping-System-Archives-and-the-Shared-Fonts-from-a-3DS-Console/'>Dumping System "
+           "dumping-system-archives-and-the-shared-fonts-from-a-3ds-console/'>Dumping System "
            "Archives and the Shared Fonts from a 3DS Console</a>.<br/><br/>Would you like to quit "
-           "back to the game list?");
+           "back to the game list? Continuing emulation may result in crashes, corrupted save "
+           "data, or other bugs.");
     switch (result) {
     case Core::System::ResultStatus::ErrorSystemFiles: {
         QString message = "Citra was unable to locate a 3DS system archive";
@@ -689,7 +690,8 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
             tr("Citra has encountered a fatal error, please see the log for more details. "
                "For more information on accessing the log, please see the following page: "
                "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
-               "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game list?"),
+               "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game list? "
+               "Continuing emulation may result in crashes, corrupted save data, or other bugs."),
             QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
         status_message = "Fatal Error encountered";
         break;

From f008b22e3b2baa7720ea65c320fe49929a53bad7 Mon Sep 17 00:00:00 2001
From: TheKoopaKingdom <thekoopakingdom@gmail.com>
Date: Fri, 2 Jun 2017 17:03:38 -0400
Subject: [PATCH 10/10] Addressed Bunnei's review comments, and made some other
 tweaks:  - Deleted GetStatus() because it wasn't used anywhere outside of
 Core::System.  - Fixed design flaw where the message bar status could be set
 despite the game being stopped.

---
 src/citra_qt/main.cpp               | 15 ++++++++++-----
 src/core/core.cpp                   | 11 +++++------
 src/core/core.h                     | 16 +++++++---------
 src/core/file_sys/archive_ncch.cpp  | 12 ++++++------
 src/core/hle/service/fs/archive.cpp |  3 ++-
 src/core/loader/loader.h            |  2 +-
 src/core/loader/ncch.h              |  2 +-
 7 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index c899e075f..4f5b2ddab 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -663,10 +663,11 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
     switch (result) {
     case Core::System::ResultStatus::ErrorSystemFiles: {
         QString message = "Citra was unable to locate a 3DS system archive";
-        if (details != std::string())
+        if (!details.empty()) {
             message.append(tr(": %1. ").arg(details.c_str()));
-        else
+        } else {
             message.append(". ");
+        }
         message.append(common_message);
 
         answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
@@ -698,11 +699,15 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
     }
 
     if (answer == QMessageBox::Yes) {
-        if (emu_thread != nullptr)
+        if (emu_thread) {
             ShutdownGame();
+        }
     } else {
-        message_label->setText(status_message);
-        message_label->setVisible(true);
+        // Only show the message if the game is still running.
+        if (emu_thread) {
+            message_label->setText(status_message);
+            message_label->setVisible(true);
+        }
     }
 }
 
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 2456d8aa2..5429bcb26 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -26,7 +26,7 @@ namespace Core {
 /*static*/ System System::s_instance;
 
 System::ResultStatus System::RunLoop(int tight_loop) {
-    this->status = ResultStatus::Success;
+    status = ResultStatus::Success;
     if (!cpu_core) {
         return ResultStatus::ErrorNotInitialized;
     }
@@ -60,7 +60,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
     HW::Update();
     Reschedule();
 
-    return GetStatus();
+    return status;
 }
 
 System::ResultStatus System::SingleStep() {
@@ -99,8 +99,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
         return init_result;
     }
 
-    Loader::ResultStatus load_result = app_loader->Load();
-    if (load_result != Loader::ResultStatus::Success) {
+    const Loader::ResultStatus load_result{app_loader->Load()};
+    if (Loader::ResultStatus::Success != load_result) {
         LOG_CRITICAL(Core, "Failed to load ROM (Error %i)!", load_result);
         System::Shutdown();
 
@@ -113,9 +113,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
             return ResultStatus::ErrorLoader;
         }
     }
-    // this->status will be used for errors while actually running the game
     status = ResultStatus::Success;
-    return ResultStatus::Success;
+    return status;
 }
 
 void System::PrepareReschedule() {
diff --git a/src/core/core.h b/src/core/core.h
index 6e555f954..4e3b6b409 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -108,16 +108,14 @@ public:
     PerfStats perf_stats;
     FrameLimiter frame_limiter;
 
-    ResultStatus GetStatus() {
-        return status;
-    }
-
-    void SetStatus(ResultStatus new_status, std::string details = std::string()) {
+    void SetStatus(ResultStatus new_status, const char* details = nullptr) {
         status = new_status;
-        status_details = details;
+        if (details) {
+            status_details = details;
+        }
     }
 
-    std::string GetStatusDetails() {
+    const std::string& GetStatusDetails() const {
         return status_details;
     }
 
@@ -147,8 +145,8 @@ private:
 
     static System s_instance;
 
-    ResultStatus status;
-    std::string status_details;
+    ResultStatus status = ResultStatus::Success;
+    std::string status_details = "";
 };
 
 inline ARM_Interface& CPU() {
diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index ad59c053e..6d9007731 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -42,13 +42,13 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path&
 
     if (!file->IsOpen()) {
         // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list).
-        const u32 shared_data_archive = 0x0004009B;
-        const u32 system_data_archive = 0x000400DB;
+        constexpr u32 shared_data_archive = 0x0004009B;
+        constexpr u32 system_data_archive = 0x000400DB;
 
         // Low Title IDs.
-        const u32 mii_data = 0x00010202;
-        const u32 region_manifest = 0x00010402;
-        const u32 ng_word_list = 0x00010302;
+        constexpr u32 mii_data = 0x00010202;
+        constexpr u32 region_manifest = 0x00010402;
+        constexpr u32 ng_word_list = 0x00010302;
 
         LOG_DEBUG(Service_FS, "Full Path: %s. Category: 0x%X. Path: 0x%X.", path.DebugStr().c_str(),
                   high, low);
@@ -60,7 +60,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path&
                                                       "Mii data");
             } else if (low == region_manifest) {
                 LOG_ERROR(Service_FS,
-                          "Failed to get a handle for shared data archive: region manifes");
+                          "Failed to get a handle for shared data archive: region manifest.");
                 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
                                                       "Region manifest");
             }
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 40d52f54b..21929e966 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -257,8 +257,9 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
     LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code);
 
     auto itr = id_code_map.find(id_code);
-    if (itr == id_code_map.end())
+    if (itr == id_code_map.end()) {
         return FileSys::ERROR_NOT_FOUND;
+    }
 
     CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
 
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index adb3ffdcf..48bbf687d 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -101,7 +101,7 @@ public:
      * Loads the system mode that this application needs.
      * This function defaults to 2 (96MB allocated to the application) if it can't read the
      * information.
-     * @returns a pair of Optional with the kernel system mode and ResultStatus.
+     * @returns A pair with the optional system mode, and and the status.
      */
     virtual std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() {
         // 96MB allocated to the application.
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 507da7550..0ebd47fd5 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -179,7 +179,7 @@ public:
 
     /**
      * Loads the Exheader and returns the system mode for this application.
-     * @returns a pair of Optional with the kernel system mode and ResultStatus
+     * @returns A pair with the optional system mode, and and the status.
      */
     std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() override;