summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2017-06-02 22:24:29 -0400
committerGravatar GitHub2017-06-02 22:24:29 -0400
commit81449f025a190cd9f931d73cf959ddbfebff497a (patch)
tree24a15888dd6ebc515a09eaf00623fa23e2d4665d /src
parentMerge pull request #2722 from wwylele/cam-ipc-helper (diff)
parentAddressed Bunnei's review comments, and made some other tweaks: (diff)
downloadyuzu-81449f025a190cd9f931d73cf959ddbfebff497a.tar.gz
yuzu-81449f025a190cd9f931d73cf959ddbfebff497a.tar.xz
yuzu-81449f025a190cd9f931d73cf959ddbfebff497a.zip
Merge pull request #2611 from TheKoopaKingdom/missing-file-dialogs
Display QMessageBox Dialogs For Errors
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/bootmanager.cpp5
-rw-r--r--src/citra_qt/bootmanager.h3
-rw-r--r--src/citra_qt/main.cpp123
-rw-r--r--src/citra_qt/main.h3
-rw-r--r--src/core/core.cpp29
-rw-r--r--src/core/core.h17
-rw-r--r--src/core/file_sys/archive_ncch.cpp39
-rw-r--r--src/core/hle/service/apt/apt.cpp2
-rw-r--r--src/core/hle/service/err_f.cpp2
-rw-r--r--src/core/hle/service/fs/archive.cpp4
-rw-r--r--src/core/hle/service/fs/fs_user.cpp3
-rw-r--r--src/core/loader/loader.h7
-rw-r--r--src/core/loader/ncch.cpp12
-rw-r--r--src/core/loader/ncch.h4
14 files changed, 212 insertions, 41 deletions
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 06b62f44c..a8a4aed8b 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -37,7 +37,10 @@ void EmuThread::run() {
37 if (!was_active) 37 if (!was_active)
38 emit DebugModeLeft(); 38 emit DebugModeLeft();
39 39
40 Core::System::GetInstance().RunLoop(); 40 Core::System::ResultStatus result = Core::System::GetInstance().RunLoop();
41 if (result != Core::System::ResultStatus::Success) {
42 emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails());
43 }
41 44
42 was_active = running || exec_step; 45 was_active = running || exec_step;
43 if (!was_active && !stop_run) 46 if (!was_active && !stop_run)
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 9d39f1af8..4b3a3b3cc 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -10,6 +10,7 @@
10#include <QGLWidget> 10#include <QGLWidget>
11#include <QThread> 11#include <QThread>
12#include "common/thread.h" 12#include "common/thread.h"
13#include "core/core.h"
13#include "core/frontend/emu_window.h" 14#include "core/frontend/emu_window.h"
14#include "core/frontend/motion_emu.h" 15#include "core/frontend/motion_emu.h"
15 16
@@ -97,6 +98,8 @@ signals:
97 * Qt::BlockingQueuedConnection (additionally block source thread until slot returns) 98 * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
98 */ 99 */
99 void DebugModeLeft(); 100 void DebugModeLeft();
101
102 void ErrorThrown(Core::System::ResultStatus, std::string);
100}; 103};
101 104
102class GRenderWindow : public QWidget, public EmuWindow { 105class GRenderWindow : public QWidget, public EmuWindow {
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index eb2c7d613..4f5b2ddab 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -93,6 +93,14 @@ void GMainWindow::InitializeWidgets() {
93 ui.horizontalLayout->addWidget(game_list); 93 ui.horizontalLayout->addWidget(game_list);
94 94
95 // Create status bar 95 // Create status bar
96 message_label = new QLabel();
97 // Configured separately for left alignment
98 message_label->setVisible(false);
99 message_label->setFrameStyle(QFrame::NoFrame);
100 message_label->setContentsMargins(4, 0, 4, 0);
101 message_label->setAlignment(Qt::AlignLeft);
102 statusBar()->addPermanentWidget(message_label, 1);
103
96 emu_speed_label = new QLabel(); 104 emu_speed_label = new QLabel();
97 emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% " 105 emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% "
98 "indicate emulation is running faster or slower than a 3DS.")); 106 "indicate emulation is running faster or slower than a 3DS."));
@@ -108,7 +116,7 @@ void GMainWindow::InitializeWidgets() {
108 label->setVisible(false); 116 label->setVisible(false);
109 label->setFrameStyle(QFrame::NoFrame); 117 label->setFrameStyle(QFrame::NoFrame);
110 label->setContentsMargins(4, 0, 4, 0); 118 label->setContentsMargins(4, 0, 4, 0);
111 statusBar()->addPermanentWidget(label); 119 statusBar()->addPermanentWidget(label, 0);
112 } 120 }
113 statusBar()->setVisible(true); 121 statusBar()->setVisible(true);
114 setStyleSheet("QStatusBar::item{border: none;}"); 122 setStyleSheet("QStatusBar::item{border: none;}");
@@ -300,9 +308,8 @@ bool GMainWindow::LoadROM(const QString& filename) {
300 render_window->MakeCurrent(); 308 render_window->MakeCurrent();
301 309
302 if (!gladLoadGL()) { 310 if (!gladLoadGL()) {
303 QMessageBox::critical(this, tr("Error while starting Citra!"), 311 QMessageBox::critical(this, tr("Error while initializing OpenGL 3.3 Core!"),
304 tr("Failed to initialize the video core!\n\n" 312 tr("Your GPU may not support OpenGL 3.3, or you do not"
305 "Please ensure that your GPU supports OpenGL 3.3 and that you "
306 "have the latest graphics driver.")); 313 "have the latest graphics driver."));
307 return false; 314 return false;
308 } 315 }
@@ -327,18 +334,17 @@ bool GMainWindow::LoadROM(const QString& filename) {
327 break; 334 break;
328 335
329 case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: { 336 case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: {
330 // Build the MessageBox ourselves to have clickable link 337 QMessageBox::critical(
331 QMessageBox popup_error; 338 this, tr("Error while loading ROM!"),
332 popup_error.setTextFormat(Qt::RichText);
333 popup_error.setWindowTitle(tr("Error while loading ROM!"));
334 popup_error.setText(
335 tr("The game that you are trying to load must be decrypted before being used with " 339 tr("The game that you are trying to load must be decrypted before being used with "
336 "Citra.<br/><br/>" 340 "Citra. A real 3DS is required.<br/><br/>"
337 "For more information on dumping and decrypting games, please see: <a " 341 "For more information on dumping and decrypting games, please see the following "
338 "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://" 342 "wiki pages: <ul>"
339 "citra-emu.org/wiki/Dumping-Game-Cartridges</a>")); 343 "<li><a href='https://citra-emu.org/wiki/dumping-game-cartridges/'>Dumping Game "
340 popup_error.setIcon(QMessageBox::Critical); 344 "Cartridges</a></li>"
341 popup_error.exec(); 345 "<li><a href='https://citra-emu.org/wiki/dumping-installed-titles/'>Dumping "
346 "Installed Titles</a></li>"
347 "</ul>"));
342 break; 348 break;
343 } 349 }
344 case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat: 350 case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat:
@@ -346,8 +352,23 @@ bool GMainWindow::LoadROM(const QString& filename) {
346 tr("The ROM format is not supported.")); 352 tr("The ROM format is not supported."));
347 break; 353 break;
348 354
355 case Core::System::ResultStatus::ErrorVideoCore:
356 QMessageBox::critical(
357 this, tr("An error occured in the video core."),
358 tr("Citra has encountered an error while running the video core, please see the "
359 "log for more details."
360 "For more information on accessing the log, please see the following page: "
361 "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
362 "to "
363 "Upload the Log File</a>."
364 "Ensure that you have the latest graphics drivers for your GPU."));
365
366 break;
367
349 default: 368 default:
350 QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!")); 369 QMessageBox::critical(
370 this, tr("Error while loading ROM!"),
371 tr("An unknown error occured. Please see the log for more details."));
351 break; 372 break;
352 } 373 }
353 return false; 374 return false;
@@ -424,6 +445,7 @@ void GMainWindow::ShutdownGame() {
424 445
425 // Disable status bar updates 446 // Disable status bar updates
426 status_bar_update_timer.stop(); 447 status_bar_update_timer.stop();
448 message_label->setVisible(false);
427 emu_speed_label->setVisible(false); 449 emu_speed_label->setVisible(false);
428 game_fps_label->setVisible(false); 450 game_fps_label->setVisible(false);
429 emu_frametime_label->setVisible(false); 451 emu_frametime_label->setVisible(false);
@@ -530,6 +552,10 @@ void GMainWindow::OnMenuRecentFile() {
530 552
531void GMainWindow::OnStartGame() { 553void GMainWindow::OnStartGame() {
532 emu_thread->SetRunning(true); 554 emu_thread->SetRunning(true);
555 qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
556 qRegisterMetaType<std::string>("std::string");
557 connect(emu_thread.get(), SIGNAL(ErrorThrown(Core::System::ResultStatus, std::string)), this,
558 SLOT(OnCoreError(Core::System::ResultStatus, std::string)));
533 559
534 ui.action_Start->setEnabled(false); 560 ui.action_Start->setEnabled(false);
535 ui.action_Start->setText(tr("Continue")); 561 ui.action_Start->setText(tr("Continue"));
@@ -622,11 +648,74 @@ void GMainWindow::UpdateStatusBar() {
622 emu_frametime_label->setVisible(true); 648 emu_frametime_label->setVisible(true);
623} 649}
624 650
651void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
652 QMessageBox::StandardButton answer;
653 QString status_message;
654 const QString common_message =
655 tr("The game you are trying to load requires additional files from your 3DS to be dumped "
656 "before playing.<br/><br/>For more information on dumping these files, please see the "
657 "following wiki page: <a "
658 "href='https://citra-emu.org/wiki/"
659 "dumping-system-archives-and-the-shared-fonts-from-a-3ds-console/'>Dumping System "
660 "Archives and the Shared Fonts from a 3DS Console</a>.<br/><br/>Would you like to quit "
661 "back to the game list? Continuing emulation may result in crashes, corrupted save "
662 "data, or other bugs.");
663 switch (result) {
664 case Core::System::ResultStatus::ErrorSystemFiles: {
665 QString message = "Citra was unable to locate a 3DS system archive";
666 if (!details.empty()) {
667 message.append(tr(": %1. ").arg(details.c_str()));
668 } else {
669 message.append(". ");
670 }
671 message.append(common_message);
672
673 answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
674 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
675 status_message = "System Archive Missing";
676 break;
677 }
678
679 case Core::System::ResultStatus::ErrorSharedFont: {
680 QString message = tr("Citra was unable to locate the 3DS shared fonts. ");
681 message.append(common_message);
682 answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
683 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
684 status_message = "Shared Font Missing";
685 break;
686 }
687
688 default:
689 answer = QMessageBox::question(
690 this, tr("Fatal Error"),
691 tr("Citra has encountered a fatal error, please see the log for more details. "
692 "For more information on accessing the log, please see the following page: "
693 "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How to "
694 "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game list? "
695 "Continuing emulation may result in crashes, corrupted save data, or other bugs."),
696 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
697 status_message = "Fatal Error encountered";
698 break;
699 }
700
701 if (answer == QMessageBox::Yes) {
702 if (emu_thread) {
703 ShutdownGame();
704 }
705 } else {
706 // Only show the message if the game is still running.
707 if (emu_thread) {
708 message_label->setText(status_message);
709 message_label->setVisible(true);
710 }
711 }
712}
713
625bool GMainWindow::ConfirmClose() { 714bool GMainWindow::ConfirmClose() {
626 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) 715 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
627 return true; 716 return true;
628 717
629 auto answer = 718 QMessageBox::StandardButton answer =
630 QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"), 719 QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
631 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 720 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
632 return answer != QMessageBox::No; 721 return answer != QMessageBox::No;
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index cb2e87cbd..952a50974 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -8,6 +8,7 @@
8#include <memory> 8#include <memory>
9#include <QMainWindow> 9#include <QMainWindow>
10#include <QTimer> 10#include <QTimer>
11#include "core/core.h"
11#include "ui_main.h" 12#include "ui_main.h"
12 13
13class Config; 14class Config;
@@ -125,6 +126,7 @@ private slots:
125 void OnDisplayTitleBars(bool); 126 void OnDisplayTitleBars(bool);
126 void ToggleWindowMode(); 127 void ToggleWindowMode();
127 void OnCreateGraphicsSurfaceViewer(); 128 void OnCreateGraphicsSurfaceViewer();
129 void OnCoreError(Core::System::ResultStatus, std::string);
128 130
129private: 131private:
130 void UpdateStatusBar(); 132 void UpdateStatusBar();
@@ -135,6 +137,7 @@ private:
135 GameList* game_list; 137 GameList* game_list;
136 138
137 // Status bar elements 139 // Status bar elements
140 QLabel* message_label = nullptr;
138 QLabel* emu_speed_label = nullptr; 141 QLabel* emu_speed_label = nullptr;
139 QLabel* game_fps_label = nullptr; 142 QLabel* game_fps_label = nullptr;
140 QLabel* emu_frametime_label = nullptr; 143 QLabel* emu_frametime_label = nullptr;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 450e7566d..5429bcb26 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6 6#include <utility>
7#include "audio_core/audio_core.h" 7#include "audio_core/audio_core.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
@@ -26,6 +26,7 @@ namespace Core {
26/*static*/ System System::s_instance; 26/*static*/ System System::s_instance;
27 27
28System::ResultStatus System::RunLoop(int tight_loop) { 28System::ResultStatus System::RunLoop(int tight_loop) {
29 status = ResultStatus::Success;
29 if (!cpu_core) { 30 if (!cpu_core) {
30 return ResultStatus::ErrorNotInitialized; 31 return ResultStatus::ErrorNotInitialized;
31 } 32 }
@@ -59,7 +60,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
59 HW::Update(); 60 HW::Update();
60 Reschedule(); 61 Reschedule();
61 62
62 return ResultStatus::Success; 63 return status;
63} 64}
64 65
65System::ResultStatus System::SingleStep() { 66System::ResultStatus System::SingleStep() {
@@ -73,14 +74,25 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
73 LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str()); 74 LOG_CRITICAL(Core, "Failed to obtain loader for %s!", filepath.c_str());
74 return ResultStatus::ErrorGetLoader; 75 return ResultStatus::ErrorGetLoader;
75 } 76 }
77 std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode =
78 app_loader->LoadKernelSystemMode();
79
80 if (system_mode.second != Loader::ResultStatus::Success) {
81 LOG_CRITICAL(Core, "Failed to determine system mode (Error %i)!",
82 static_cast<int>(system_mode.second));
83 System::Shutdown();
76 84
77 boost::optional<u32> system_mode{app_loader->LoadKernelSystemMode()}; 85 switch (system_mode.second) {
78 if (!system_mode) { 86 case Loader::ResultStatus::ErrorEncrypted:
79 LOG_CRITICAL(Core, "Failed to determine system mode!"); 87 return ResultStatus::ErrorLoader_ErrorEncrypted;
80 return ResultStatus::ErrorSystemMode; 88 case Loader::ResultStatus::ErrorInvalidFormat:
89 return ResultStatus::ErrorLoader_ErrorInvalidFormat;
90 default:
91 return ResultStatus::ErrorSystemMode;
92 }
81 } 93 }
82 94
83 ResultStatus init_result{Init(emu_window, system_mode.get())}; 95 ResultStatus init_result{Init(emu_window, system_mode.first.get())};
84 if (init_result != ResultStatus::Success) { 96 if (init_result != ResultStatus::Success) {
85 LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result); 97 LOG_CRITICAL(Core, "Failed to initialize system (Error %i)!", init_result);
86 System::Shutdown(); 98 System::Shutdown();
@@ -101,7 +113,8 @@ System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& file
101 return ResultStatus::ErrorLoader; 113 return ResultStatus::ErrorLoader;
102 } 114 }
103 } 115 }
104 return ResultStatus::Success; 116 status = ResultStatus::Success;
117 return status;
105} 118}
106 119
107void System::PrepareReschedule() { 120void System::PrepareReschedule() {
diff --git a/src/core/core.h b/src/core/core.h
index 6af772831..4e3b6b409 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -40,7 +40,10 @@ public:
40 ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption 40 ErrorLoader_ErrorEncrypted, ///< Error loading the specified application due to encryption
41 ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an 41 ErrorLoader_ErrorInvalidFormat, ///< Error loading the specified application due to an
42 /// invalid format 42 /// invalid format
43 ErrorSystemFiles, ///< Error in finding system files
44 ErrorSharedFont, ///< Error in finding shared font
43 ErrorVideoCore, ///< Error in the video core 45 ErrorVideoCore, ///< Error in the video core
46 ErrorUnknown ///< Any other error
44 }; 47 };
45 48
46 /** 49 /**
@@ -105,6 +108,17 @@ public:
105 PerfStats perf_stats; 108 PerfStats perf_stats;
106 FrameLimiter frame_limiter; 109 FrameLimiter frame_limiter;
107 110
111 void SetStatus(ResultStatus new_status, const char* details = nullptr) {
112 status = new_status;
113 if (details) {
114 status_details = details;
115 }
116 }
117
118 const std::string& GetStatusDetails() const {
119 return status_details;
120 }
121
108private: 122private:
109 /** 123 /**
110 * Initialize the emulated system. 124 * Initialize the emulated system.
@@ -130,6 +144,9 @@ private:
130 std::unique_ptr<Core::TelemetrySession> telemetry_session; 144 std::unique_ptr<Core::TelemetrySession> telemetry_session;
131 145
132 static System s_instance; 146 static System s_instance;
147
148 ResultStatus status = ResultStatus::Success;
149 std::string status_details = "";
133}; 150};
134 151
135inline ARM_Interface& CPU() { 152inline ARM_Interface& CPU() {
diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp
index 89455e39c..6d9007731 100644
--- a/src/core/file_sys/archive_ncch.cpp
+++ b/src/core/file_sys/archive_ncch.cpp
@@ -9,7 +9,9 @@
9#include "common/file_util.h" 9#include "common/file_util.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/string_util.h" 11#include "common/string_util.h"
12#include "core/core.h"
12#include "core/file_sys/archive_ncch.h" 13#include "core/file_sys/archive_ncch.h"
14#include "core/file_sys/errors.h"
13#include "core/file_sys/ivfc_archive.h" 15#include "core/file_sys/ivfc_archive.h"
14#include "core/hle/service/fs/archive.h" 16#include "core/hle/service/fs/archive.h"
15 17
@@ -33,11 +35,44 @@ ArchiveFactory_NCCH::ArchiveFactory_NCCH(const std::string& nand_directory)
33ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path) { 35ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path) {
34 auto vec = path.AsBinary(); 36 auto vec = path.AsBinary();
35 const u32* data = reinterpret_cast<u32*>(vec.data()); 37 const u32* data = reinterpret_cast<u32*>(vec.data());
36 std::string file_path = GetNCCHPath(mount_point, data[1], data[0]); 38 u32 high = data[1];
39 u32 low = data[0];
40 std::string file_path = GetNCCHPath(mount_point, high, low);
37 auto file = std::make_shared<FileUtil::IOFile>(file_path, "rb"); 41 auto file = std::make_shared<FileUtil::IOFile>(file_path, "rb");
38 42
39 if (!file->IsOpen()) { 43 if (!file->IsOpen()) {
40 return ResultCode(-1); // TODO(Subv): Find the right error code 44 // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list).
45 constexpr u32 shared_data_archive = 0x0004009B;
46 constexpr u32 system_data_archive = 0x000400DB;
47
48 // Low Title IDs.
49 constexpr u32 mii_data = 0x00010202;
50 constexpr u32 region_manifest = 0x00010402;
51 constexpr u32 ng_word_list = 0x00010302;
52
53 LOG_DEBUG(Service_FS, "Full Path: %s. Category: 0x%X. Path: 0x%X.", path.DebugStr().c_str(),
54 high, low);
55
56 if (high == shared_data_archive) {
57 if (low == mii_data) {
58 LOG_ERROR(Service_FS, "Failed to get a handle for shared data archive: Mii data. ");
59 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
60 "Mii data");
61 } else if (low == region_manifest) {
62 LOG_ERROR(Service_FS,
63 "Failed to get a handle for shared data archive: region manifest.");
64 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
65 "Region manifest");
66 }
67 } else if (high == system_data_archive) {
68 if (low == ng_word_list) {
69 LOG_ERROR(Service_FS,
70 "Failed to get a handle for system data archive: NG bad word list.");
71 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles,
72 "NG bad word list");
73 }
74 }
75 return ERROR_NOT_FOUND;
41 } 76 }
42 auto size = file->GetSize(); 77 auto size = file->GetSize();
43 78
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 366d1eacf..4c587e3c8 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -5,6 +5,7 @@
5#include "common/common_paths.h" 5#include "common/common_paths.h"
6#include "common/file_util.h" 6#include "common/file_util.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h"
8#include "core/hle/applets/applet.h" 9#include "core/hle/applets/applet.h"
9#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
@@ -74,6 +75,7 @@ void GetSharedFont(Service::Interface* self) {
74 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); 75 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
75 rb.Push<u32>(-1); // TODO: Find the right error code 76 rb.Push<u32>(-1); // TODO: Find the right error code
76 rb.Skip(1 + 2, true); 77 rb.Skip(1 + 2, true);
78 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSharedFont);
77 return; 79 return;
78 } 80 }
79 81
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 @@
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "core/core.h"
13#include "core/hle/result.h" 14#include "core/hle/result.h"
14#include "core/hle/service/err_f.h" 15#include "core/hle/service/err_f.h"
15 16
@@ -172,6 +173,7 @@ static void ThrowFatalError(Interface* self) {
172 const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]); 173 const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
173 LOG_CRITICAL(Service_ERR, "Fatal error type: %s", 174 LOG_CRITICAL(Service_ERR, "Fatal error type: %s",
174 GetErrType(errinfo->errinfo_common.specifier).c_str()); 175 GetErrType(errinfo->errinfo_common.specifier).c_str());
176 Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorUnknown);
175 177
176 // Generic Info 178 // Generic Info
177 LogGenericInfo(errinfo->errinfo_common); 179 LogGenericInfo(errinfo->errinfo_common);
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 632712f2c..21929e966 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -258,9 +258,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
258 258
259 auto itr = id_code_map.find(id_code); 259 auto itr = id_code_map.find(id_code);
260 if (itr == id_code_map.end()) { 260 if (itr == id_code_map.end()) {
261 // TODO: Verify error against hardware 261 return FileSys::ERROR_NOT_FOUND;
262 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound,
263 ErrorLevel::Permanent);
264 } 262 }
265 263
266 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); 264 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 e53a970d3..c1825e9c8 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -8,6 +8,7 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/scope_exit.h" 9#include "common/scope_exit.h"
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "core/core.h"
11#include "core/file_sys/errors.h" 12#include "core/file_sys/errors.h"
12#include "core/hle/kernel/client_session.h" 13#include "core/hle/kernel/client_session.h"
13#include "core/hle/result.h" 14#include "core/hle/result.h"
@@ -130,7 +131,7 @@ static void OpenFileDirectly(Service::Interface* self) {
130 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); 131 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
131 if (archive_handle.Failed()) { 132 if (archive_handle.Failed()) {
132 LOG_ERROR(Service_FS, 133 LOG_ERROR(Service_FS,
133 "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 134 "Failed to get a handle for archive archive_id=0x%08X archive_path=%s",
134 static_cast<u32>(archive_id), archive_path.DebugStr().c_str()); 135 static_cast<u32>(archive_id), archive_path.DebugStr().c_str());
135 cmd_buff[1] = archive_handle.Code().raw; 136 cmd_buff[1] = archive_handle.Code().raw;
136 cmd_buff[3] = 0; 137 cmd_buff[3] = 0;
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 1d80766ae..48bbf687d 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -8,6 +8,7 @@
8#include <initializer_list> 8#include <initializer_list>
9#include <memory> 9#include <memory>
10#include <string> 10#include <string>
11#include <utility>
11#include <vector> 12#include <vector>
12#include <boost/optional.hpp> 13#include <boost/optional.hpp>
13#include "common/common_types.h" 14#include "common/common_types.h"
@@ -100,11 +101,11 @@ public:
100 * Loads the system mode that this application needs. 101 * Loads the system mode that this application needs.
101 * This function defaults to 2 (96MB allocated to the application) if it can't read the 102 * This function defaults to 2 (96MB allocated to the application) if it can't read the
102 * information. 103 * information.
103 * @returns Optional with the kernel system mode 104 * @returns A pair with the optional system mode, and and the status.
104 */ 105 */
105 virtual boost::optional<u32> LoadKernelSystemMode() { 106 virtual std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() {
106 // 96MB allocated to the application. 107 // 96MB allocated to the application.
107 return 2; 108 return std::make_pair(2, ResultStatus::Success);
108 } 109 }
109 110
110 /** 111 /**
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index beeb13ffa..ffc019560 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -121,12 +121,16 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) {
121 return FileType::Error; 121 return FileType::Error;
122} 122}
123 123
124boost::optional<u32> AppLoader_NCCH::LoadKernelSystemMode() { 124std::pair<boost::optional<u32>, ResultStatus> AppLoader_NCCH::LoadKernelSystemMode() {
125 if (!is_loaded) { 125 if (!is_loaded) {
126 if (LoadExeFS() != ResultStatus::Success) 126 ResultStatus res = LoadExeFS();
127 return boost::none; 127 if (res != ResultStatus::Success) {
128 return std::make_pair(boost::none, res);
129 }
128 } 130 }
129 return exheader_header.arm11_system_local_caps.system_mode.Value(); 131 // Set the system mode as the one from the exheader.
132 return std::make_pair(exheader_header.arm11_system_local_caps.system_mode.Value(),
133 ResultStatus::Success);
130} 134}
131 135
132ResultStatus AppLoader_NCCH::LoadExec() { 136ResultStatus AppLoader_NCCH::LoadExec() {
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 4ef95b5c6..0ebd47fd5 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -179,9 +179,9 @@ public:
179 179
180 /** 180 /**
181 * Loads the Exheader and returns the system mode for this application. 181 * Loads the Exheader and returns the system mode for this application.
182 * @return Optional with the kernel system mode 182 * @returns A pair with the optional system mode, and and the status.
183 */ 183 */
184 boost::optional<u32> LoadKernelSystemMode() override; 184 std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() override;
185 185
186 ResultStatus ReadCode(std::vector<u8>& buffer) override; 186 ResultStatus ReadCode(std::vector<u8>& buffer) override;
187 187