diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp
new file mode 100644
index 000000000..5583e7a0b
--- /dev/null
+++ b/stratosphere/fatal/source/fatal_config.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include "fatal_types.hpp"
+#include "fatal_config.hpp"
+
+static FatalConfig g_fatal_config;
+
+static IEvent *g_fatal_settings_event = nullptr;
+
+FatalConfig *GetFatalConfig() {
+ return &g_fatal_config;
+}
+
+static void UpdateLanguageCode() {
+ setGetLanguageCode(&GetFatalConfig()->language_code);
+}
+
+IEvent *GetFatalSettingsEvent() {
+ if (g_fatal_settings_event == nullptr) {
+ Event evt;
+ if (R_FAILED(setsysBindFatalDirtyFlagEvent(&evt))) {
+ std::abort();
+ }
+ g_fatal_settings_event = LoadReadOnlySystemEvent(evt.revent, [](u64 timeout) {
+ u64 flags_0, flags_1;
+ if (R_SUCCEEDED(setsysGetFatalDirtyFlags(&flags_0, &flags_1)) && (flags_0 & 1)) {
+ UpdateLanguageCode();
+ }
+ return 0;
+ }, true);
+ }
+
+ return g_fatal_settings_event;
+}
+
+void InitializeFatalConfig() {
+ FatalConfig *config = GetFatalConfig();
+
+ memset(config, 0, sizeof(*config));
+ setsysGetSerialNumber(config->serial_number);
+ setsysGetFirmwareVersion(&config->firmware_version);
+ UpdateLanguageCode();
+
+ setsysGetSettingsItemValue("fatal", "transition_to_fatal", &config->transition_to_fatal, sizeof(config->transition_to_fatal));
+ setsysGetSettingsItemValue("fatal", "show_extra_info", &config->show_extra_info, sizeof(config->show_extra_info));
+ setsysGetSettingsItemValue("fatal", "quest_reboot_interval_second", &config->quest_reboot_interval_second, sizeof(config->quest_reboot_interval_second));
+
+ setsysGetFlag(SetSysFlag_Quest, &config->quest_flag);
+}
diff --git a/stratosphere/fatal/source/fatal_config.hpp b/stratosphere/fatal/source/fatal_config.hpp
new file mode 100644
index 000000000..105534bfc
--- /dev/null
+++ b/stratosphere/fatal/source/fatal_config.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+struct FatalConfig {
+ char serial_number[0x18];
+ SetSysFirmwareVersion firmware_version;
+ u64 language_code;
+ u64 quest_reboot_interval_second;
+ bool transition_to_fatal;
+ bool show_extra_info;
+ bool quest_flag;
+};
+
+IEvent *GetFatalSettingsEvent();
+FatalConfig *GetFatalConfig();
+
+void InitializeFatalConfig();
\ No newline at end of file
diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp
index 31cb4a798..62324f6f1 100644
--- a/stratosphere/fatal/source/fatal_main.cpp
+++ b/stratosphere/fatal/source/fatal_main.cpp
@@ -26,6 +26,7 @@
#include "fatal_types.hpp"
#include "fatal_private.hpp"
#include "fatal_user.hpp"
+#include "fatal_config.hpp"
extern "C" {
extern u32 __start__;
@@ -65,6 +66,11 @@ void __appInit(void) {
std::abort();
}
+ rc = setInitialize();
+ if (R_FAILED(rc)) {
+ std::abort();
+ }
+
rc = setsysInitialize();
if (R_FAILED(rc)) {
std::abort();
@@ -118,13 +124,15 @@ void __appExit(void) {
i2cExit();
pminfoExit();
setsysExit();
+ setExit();
smExit();
}
int main(int argc, char **argv)
{
- /* TODO: Load settings from set:sys. */
-
+ /* Load settings from set:sys. */
+ InitializeFatalConfig();
+
/* TODO: Load shared font. */
/* TODO: Check whether we should throw fatal due to repair process... */
@@ -135,6 +143,7 @@ int main(int argc, char **argv)
/* TODO: Create services. */
server_manager->AddWaitable(new ServiceServer("fatal:p", 4));
server_manager->AddWaitable(new ServiceServer("fatal:u", 4));
+ server_manager->AddWaitable(GetFatalSettingsEvent());
/* Loop forever, servicing our services. */
server_manager->Process();
diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp
index 88e934f53..a804d6ff5 100644
--- a/stratosphere/fatal/source/fatal_task_power.cpp
+++ b/stratosphere/fatal/source/fatal_task_power.cpp
@@ -16,6 +16,7 @@
#include
#include "fatal_task_power.hpp"
+#include "fatal_config.hpp"
bool PowerControlTask::TryShutdown() {
/* Set a timeout of 30 seconds. */
@@ -91,12 +92,16 @@ void PowerButtonObserveTask::WaitForPowerButton() {
/* Wait up to a second for error report generation to finish. */
eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL));
- /* TODO: Force a reboot after some time if kiosk unit. */
+ /* Force a reboot after some time if kiosk unit. */
+ const FatalConfig *config = GetFatalConfig();
+ TimeoutHelper reboot_helper(config->quest_reboot_interval_second * 1000000000UL);
BpcSleepButtonState state;
while (true) {
+
+
Result rc = bpcGetSleepButtonState(&state);
- if (R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) {
+ if ((R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) {
bpcRebootSystem();
return;
}
diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp
index a28be3fa3..5dcf40b04 100644
--- a/stratosphere/fatal/source/fatal_task_screen.cpp
+++ b/stratosphere/fatal/source/fatal_task_screen.cpp
@@ -16,6 +16,7 @@
#include
#include "fatal_task_screen.hpp"
+#include "fatal_config.hpp"
Result ShowFatalTask::ShowFatal() {
Result rc = 0;
diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp
index b21aefc29..f5405267c 100644
--- a/stratosphere/fatal/source/fatal_user.cpp
+++ b/stratosphere/fatal/source/fatal_user.cpp
@@ -18,6 +18,7 @@
#include "fatal_user.hpp"
#include "fatal_event_manager.hpp"
#include "fatal_task.hpp"
+#include "fatal_config.hpp"
static bool g_thrown = false;
@@ -37,6 +38,9 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp
ctx.error_code = error;
ctx.cpu_ctx = *cpu_ctx;
+ /* Get config. */
+ const FatalConfig *config = GetFatalConfig();
+
/* Get title id. On failure, it'll be zero. */
u64 title_id = 0;
pminfoGetTitleId(&title_id, pid);
@@ -63,7 +67,13 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp
}
/* Run tasks. */
- RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event);
+ if (config->transition_to_fatal) {
+ RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event);
+ } else {
+ /* If flag is not set, don't show the fatal screen. */
+ return 0;
+ }
+
}
break;
default: