Compare commits

..

33 Commits

Author SHA1 Message Date
5cb085b00c daybreak: Add firmware compatibility gate and German UI
Block unsupported firmware updates via a dedicated dialog using
Exosphere's maximum supported HOS version, and translate the Daybreak
interface to German.
2026-05-17 12:59:14 +02:00
hexkyz
2c7e2bfaae Merge pull request #2800 from masagrator/patch-1
fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs
2026-04-25 19:55:43 +01:00
MasaGratoR
e655fd4b01 fs.mitm: Add "Until Then" as another game which needs stolen heap for layeredfs 2026-04-24 22:30:25 +02:00
hexkyz
022000f668 docs: add changelog for 1.11.1
this was missing from the usual enum recognition changes
synchronization will happen at a future release instead
2026-04-07 22:53:21 +01:00
hexkyz
d04c20a049 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "82f1553c4"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "82f1553c4"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-04-07 17:24:31 +01:00
hexkyz
252f8685b4 Merge pull request #2786 from alula/alula
ams: add enum recognition for 22.1.0
2026-04-07 17:22:46 +01:00
Alula
020ed307b1 ams: add enum recognition for 22.1.0 2026-04-07 03:22:37 +02:00
hexkyz
d9e1d799ab git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "3726bfd65"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "3726bfd65"
git-subrepo:
  version:  "0.4.9"
  origin:   "???"
  commit:   "???"
2026-04-05 20:34:44 +01:00
ndeadly
80bd459516 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "8e9c9ab16"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "8e9c9ab16"
git-subrepo:
  version:  "0.4.9"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5e0f401"
2026-04-04 16:44:08 +02:00
hexkyz
931e3c37fd docs: add changelog for 1.11.0 2026-04-03 23:34:13 +01:00
hexkyz
4b4db91341 pgl: no need to initialize lr services when already using our own 2026-04-03 23:32:15 +01:00
hexkyz
e3fc339fe5 Merge pull request #2766 from alula/erpt-crash-fix
erpt: Fix rare aborts caused by ResultInvalidPowerState
2026-04-03 23:09:55 +01:00
Alula
a051c3c723 erpt: document unknown 0x20000 flag 2026-04-04 00:06:49 +02:00
Alula
9a1ea02c8c erpt: Add some missed 20.0.0+ FsInfo changes 2026-04-04 00:06:49 +02:00
hexkyz
bae1ad22ec Merge pull request #2768 from masagrator/patch-1
Update services in PGL to match 21.0.0
2026-04-03 22:33:28 +01:00
hexkyz
cd1503a9ca emummc: fix offsets
22.0.0 now boots under emummc
2026-04-03 22:31:19 +01:00
Alula
72e3b0dd34 erpt: Fix rare aborts caused by ResultInvalidPowerState 2026-04-03 22:55:09 +02:00
MasaGratoR
ac120cf84b Match 21.0.0 FW 2026-04-03 22:23:08 +02:00
MasaGratoR
97ffad2ab6 Update service access to match 21.0.0 2026-04-03 22:22:15 +02:00
hexkyz
c8d68a3a8a Merge pull request #2763 from masagrator/patch-1
Fix off by 1 bug + allocation error + missing initialize in PGL
2026-04-03 19:27:56 +01:00
hexkyz
8987d642d1 Merge pull request #2748 from CTCaer/auto_dram_cfg
[Feature] Auto dram cfg & Auto memory mode
2026-04-03 19:27:38 +01:00
hexkyz
7ffb1da2ac Merge pull request #2734 from ndeadly/r_discard
libvapours: add R_DISCARD macro
2026-04-03 19:27:19 +01:00
hexkyz
5c426bf90d loader: remove unused file 2026-04-03 19:09:28 +01:00
MasaGratoR
31ca20f3b7 Add missing libstratosphere lr::Initialize() 2026-04-02 21:09:15 +02:00
MasaGratoR
174da786e4 Override new and delete operators 2026-04-02 20:45:30 +02:00
MasaGratoR
4a8f7628c2 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:44:08 +02:00
MasaGratoR
9d16ee6a74 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:41:25 +02:00
MasaGratoR
3b9ee08c69 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:33:27 +02:00
MasaGratoR
2694f31eb3 Update pgl_srv_shell_host_utils.cpp 2026-04-01 20:31:47 +02:00
MasaGratoR
f3f1fa46ed Fix off by 1 bug 2026-04-01 20:17:52 +02:00
CTCaer
5dd9816e3c exosphere: allow memory mode to be used on retail 2026-03-19 16:35:36 +02:00
CTCaer
5a5d9b206b exosphere: automatically adjust dram id if needed
Checks if programmed memory size matches the one from fused dram id.
If not, adjust it properly so PCV can do proper training and not crash.
2026-03-19 16:32:12 +02:00
ndeadly
f8a5a6c015 libvapours: add R_DISCARD macro 2026-02-23 01:09:11 +01:00
26 changed files with 368 additions and 128 deletions

View File

@@ -15,6 +15,13 @@
# Desc: Controls whether userland has access to the PMU registers. # Desc: Controls whether userland has access to the PMU registers.
# NOTE: It is unknown what effects this has on official code. # NOTE: It is unknown what effects this has on official code.
# Key: enable_mem_mode, default: 0.
# Desc: Controls whether boot config memory mode is taken into account
# for retail units. This does not affect development units.
# NOTE: On retail units max ram size is capped to 4GB.
# Enabling this will use the boot config memory mode parameter,
# which by default is auto and size gets set based on physical size.
# Key: blank_prodinfo_sysmmc, default: 0. # Key: blank_prodinfo_sysmmc, default: 0.
# Desc: Controls whether PRODINFO should be blanked in sysmmc. # Desc: Controls whether PRODINFO should be blanked in sysmmc.
# This will cause the system to see dummied out keys and # This will cause the system to see dummied out keys and
@@ -51,6 +58,7 @@ debugmode=1
debugmode_user=0 debugmode_user=0
disable_user_exception_handlers=0 disable_user_exception_handlers=0
enable_user_pmu_access=0 enable_user_pmu_access=0
enable_mem_mode=0
blank_prodinfo_sysmmc=0 blank_prodinfo_sysmmc=0
blank_prodinfo_emummc=0 blank_prodinfo_emummc=0
allow_writing_to_cal_sysmmc=0 allow_writing_to_cal_sysmmc=0

View File

@@ -1,4 +1,25 @@
# Changelog # Changelog
## 1.11.1
+ Basic support was added for 22.1.0.
+ General system stability improvements to enhance the user's experience.
## 1.11.0
+ Support was added for 22.0.0.
+ Special thanks to @alula for handling a large chunk of the necessary kernel, loader and erpt changes.
+ The console should boot and atmosphère should be fully functional.
+ **Please note**: A change in how applications/applets' lifespan is managed broke the homebrew ecosystem.
+ All applications and applets are expected to perform a clean exit by calling the relevant IPC commands.
+ Homebrew compiled with libnx and hbmenu itself explicitly avoid exiting so it can keep using the same process.
+ Properly fixing this would require a re-design of how homebrew is launched and terminated.
+ As a temporary solution, patches to the `am` sysmodule are now included which allow restoring the previous behavior and regain homebrew compatibility without any further changes.
+ Nonetheless, please report any issues you may face when testing homebrew to ensure no edge cases have been missed.
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `loader` was updated to reflect the latest official behavior.
+ `erpt` was updated to reflect the latest official behavior.
+ `pgl` was updated to fix a few issues.
+ Support was added for memory modes above 4GB (thanks @CTCaer).
+ A build time option to configure Joy-Con rails as UART for debugging was added (thanks @alula).
+ General system stability improvements to enhance the user's experience.
## 1.10.2 ## 1.10.2
+ Basic support was added for 21.2.0. + Basic support was added for 21.2.0.
+ General system stability improvements to enhance the user's experience. + General system stability improvements to enhance the user's experience.

6
emummc/.gitrepo vendored
View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/m4xw/emummc remote = https://github.com/m4xw/emummc
branch = develop branch = develop
commit = 8ab963b0b1c24b68de8e0c98c62c7822a9765bf3 commit = 3726bfd659600cdafd138277054568a3edba60a6
parent = 1e88f37892555da4c38ca6c95f43c56cc6bb87e6 parent = 80bd459516e813fc6f10268ca31dd72a053a4ef3
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.9

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260 #define FS_OFFSET_2200_CLKRST_SET_MIN_V_CLK_RATE 0x1CF260
// Misc funcs // Misc funcs
#define FS_OFFSET_2200_LOCK_MUTEX 0x1CF260 #define FS_OFFSET_2200_LOCK_MUTEX 0x1A4EF0
#define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40 #define FS_OFFSET_2200_UNLOCK_MUTEX 0x1A4F40
#define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0 #define FS_OFFSET_2200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1AC0B0

View File

@@ -31,7 +31,7 @@
#define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450 #define FS_OFFSET_2200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1DA450
// Misc funcs // Misc funcs
#define FS_OFFSET_2200_EXFAT_LOCK_MUTEX 0x1DA450 #define FS_OFFSET_2200_EXFAT_LOCK_MUTEX 0x1B00E0
#define FS_OFFSET_2200_EXFAT_UNLOCK_MUTEX 0x1B0130 #define FS_OFFSET_2200_EXFAT_UNLOCK_MUTEX 0x1B0130
#define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0 #define FS_OFFSET_2200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1B72A0

View File

@@ -132,10 +132,13 @@ namespace ams::secmon::smc {
} }
u32 GetMemoryMode() { u32 GetMemoryMode() {
/* Unless development function is enabled, we're 4 GB. */ /* Unless development function or forced boot config memory size is enabled, we're 4 GB. */
u32 memory_mode = pkg1::MemoryMode_4GB; u32 memory_mode = pkg1::MemoryMode_4GB;
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { const auto &bcd = GetBootConfig().data;
const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
memory_mode = GetMemoryMode(bcd.GetMemoryMode()); memory_mode = GetMemoryMode(bcd.GetMemoryMode());
} }
@@ -146,17 +149,19 @@ namespace ams::secmon::smc {
pkg1::MemorySize memory_size = pkg1::MemorySize_4GB; pkg1::MemorySize memory_size = pkg1::MemorySize_4GB;
util::BitPack32 value = {}; util::BitPack32 value = {};
if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { const auto &bcd = GetBootConfig().data;
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode())); const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */
if (bcd.IsDevelopmentFunctionEnabled()) {
value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1()); value.Set<KernelConfiguration::Flags1>(bcd.GetKernelFlags1());
value.Set<KernelConfiguration::Flags0>(bcd.GetKernelFlags0()); value.Set<KernelConfiguration::Flags0>(bcd.GetKernelFlags0());
} }
value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size); if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) {
memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode()));
}
/* Exosphere extensions. */ value.Set<KernelConfiguration::PhysicalMemorySize>(memory_size);
const auto &sc = GetSecmonConfiguration();
if (!sc.DisableUserModeExceptionHandlers()) { if (!sc.DisableUserModeExceptionHandlers()) {
value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true); value.Set<KernelConfiguration::EnableUserExceptionHandlers>(true);
@@ -169,6 +174,27 @@ namespace ams::secmon::smc {
return value.value; return value.value;
} }
fuse::DramId GetDramIdAdjusted() {
const auto dram_id = fuse::GetDramId();
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count);
const auto fuse_mem_size = DramIdToMemorySize[dram_id];
const auto phys_mem_size = GetPhysicalMemorySize();
AMS_ABORT_UNLESS(fuse_mem_size <= phys_mem_size);
if (fuse_mem_size == phys_mem_size) {
return dram_id;
}
/* Adjust Dram ID to match density/ranks. */
if (GetSocType() == fuse::SocType_Erista) {
return fuse::DramId_IcosaSamsung6GB;
} else { /* fuse::SocType_Mariko */
return fuse::DramId_IowaSamsung1y8GBX;
}
}
constinit u64 g_payload_address = 0; constinit u64 g_payload_address = 0;
constinit bool g_set_true_target_firmware = false; constinit bool g_set_true_target_firmware = false;
@@ -178,7 +204,7 @@ namespace ams::secmon::smc {
args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled(); args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled();
break; break;
case ConfigItem::DramId: case ConfigItem::DramId:
args.r[1] = fuse::GetDramId(); args.r[1] = GetDramIdAdjusted(); /* Nintendo: fuse::GetDramId() */
break; break;
case ConfigItem::SecurityEngineInterruptNumber: case ConfigItem::SecurityEngineInterruptNumber:
args.r[1] = SecurityEngineUserInterruptId; args.r[1] = SecurityEngineUserInterruptId;
@@ -471,9 +497,18 @@ namespace ams::secmon::smc {
/* For exosphere's usage. */ /* For exosphere's usage. */
pkg1::MemorySize GetPhysicalMemorySize() { pkg1::MemorySize GetPhysicalMemorySize() {
const auto dram_id = fuse::GetDramId(); const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count); const u32 mem_size = reg::Read(MC + MC_EMEM_CFG) & 0x3FFF;
return DramIdToMemorySize[dram_id];
switch (mem_size >> 10) {
case 4:
default:
return pkg1::MemorySize_4GB;
case 6:
return pkg1::MemorySize_6GB;
case 8:
return pkg1::MemorySize_8GB;
}
} }
} }

View File

@@ -545,6 +545,12 @@ namespace ams::nxboot {
} else { } else {
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess; storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess;
} }
} else if (std::strcmp(entry.key, "enable_mem_mode") == 0) {
if (entry.value[0] == '1') {
storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
} else {
storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled;
}
} else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) { } else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) {
if (!emummc_enabled) { if (!emummc_enabled) {
if (entry.value[0] == '1') { if (entry.value[0] == '1') {

View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master branch = master
commit = 9a8703e710760be8c88147d15414a1c581711625 commit = 82f1553c4c7e68364f7e630b1c68f2aee8681dee
parent = eb34f9789c62745d87f37e76761b14d946bac300 parent = 252f8685b493d0dfd428e9439b0296109776b935
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.9

View File

@@ -30,6 +30,7 @@ namespace ams::secmon {
SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5), SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5),
SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6), SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6),
SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7), SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7),
SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled = (1u << 8),
SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel, SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel,
}; };
@@ -103,6 +104,7 @@ namespace ams::secmon {
constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; } constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; }
constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; } constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; }
constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; } constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; }
constexpr bool IsBootConfigMemoryModeEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled) != 0; }
constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); } constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); }
}; };

View File

@@ -111,6 +111,7 @@ namespace ams::erpt {
struct CreateReportOptionFlag { struct CreateReportOptionFlag {
using SubmitFsInfo = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<0>; using SubmitFsInfo = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<0>;
using Unknown0x20000 = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>::Flag<17>; /* TODO: What is this, it's checked in Reporter::CreateReport or below */
}; };
using CreateReportOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>; using CreateReportOptionFlagSet = util::BitFlagSet<BITSIZEOF(u32), CreateReportOptionFlag>;

View File

@@ -52,7 +52,8 @@ namespace ams::fs {
struct GameCardErrorReportInfo { struct GameCardErrorReportInfo {
u16 game_card_crc_error_num; u16 game_card_crc_error_num;
u16 reserved1; u8 last_deactivate_reason;
u8 reserved1;
u16 asic_crc_error_num; u16 asic_crc_error_num;
u16 reserved2; u16 reserved2;
u16 refresh_num; u16 refresh_num;
@@ -73,7 +74,8 @@ namespace ams::fs {
u32 awaken_count; u32 awaken_count;
u32 read_count_from_insert; u32 read_count_from_insert;
u32 read_count_from_awaken; u32 read_count_from_awaken;
u8 reserved5[8]; u32 last_deactivate_reason_result;
u32 reserved5;
}; };
static_assert(util::is_pod<GameCardErrorReportInfo>::value); static_assert(util::is_pod<GameCardErrorReportInfo>::value);
static_assert(sizeof(GameCardErrorReportInfo) == 0x40); static_assert(sizeof(GameCardErrorReportInfo) == 0x40);

View File

@@ -101,6 +101,7 @@ namespace ams::hos {
Version_21_1_0 = ::ams::TargetFirmware_21_1_0, Version_21_1_0 = ::ams::TargetFirmware_21_1_0,
Version_21_2_0 = ::ams::TargetFirmware_21_2_0, Version_21_2_0 = ::ams::TargetFirmware_21_2_0,
Version_22_0_0 = ::ams::TargetFirmware_22_0_0, Version_22_0_0 = ::ams::TargetFirmware_22_0_0,
Version_22_1_0 = ::ams::TargetFirmware_22_1_0,
Version_Current = ::ams::TargetFirmware_Current, Version_Current = ::ams::TargetFirmware_Current,

View File

@@ -19,5 +19,6 @@
namespace ams::erpt::srv { namespace ams::erpt::srv {
Result SubmitFsInfo(); Result SubmitFsInfo();
void ClearFsInfo();
} }

View File

@@ -363,6 +363,8 @@ namespace ams::erpt::srv {
R_ABORT_UNLESS(record->Add(FieldId_GameCardReadCountFromAwaken, ei.read_count_from_awaken)); R_ABORT_UNLESS(record->Add(FieldId_GameCardReadCountFromAwaken, ei.read_count_from_awaken));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageAddress, ei.last_read_error_page_address)); R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageAddress, ei.last_read_error_page_address));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageCount, ei.last_read_error_page_count)); R_ABORT_UNLESS(record->Add(FieldId_GameCardLastReadErrorPageCount, ei.last_read_error_page_count));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastDeactivateReasonResult, ei.last_deactivate_reason_result));
R_ABORT_UNLESS(record->Add(FieldId_GameCardLastDeactivateReason, ei.last_deactivate_reason));
/* Submit the record. */ /* Submit the record. */
R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record))); R_ABORT_UNLESS(Context::SubmitContextRecord(std::move(record)));
@@ -496,4 +498,27 @@ namespace ams::erpt::srv {
R_SUCCEED(); R_SUCCEED();
} }
void ClearFsInfo() {
Context::ClearContext(CategoryId_NANDTypeInfo);
Context::ClearContext(CategoryId_NANDSpeedModeInfo);
Context::ClearContext(CategoryId_NANDExtendedCsd);
Context::ClearContext(CategoryId_NANDPatrolInfo);
Context::ClearContext(CategoryId_NANDErrorInfo);
Context::ClearContext(CategoryId_NANDDriverLog);
Context::ClearContext(CategoryId_MicroSDTypeInfo);
Context::ClearContext(CategoryId_MicroSDSpeedModeInfo);
Context::ClearContext(CategoryId_SdCardSizeSpec);
Context::ClearContext(CategoryId_SdCardActivationInfo);
Context::ClearContext(CategoryId_SdCardErrorInfo);
Context::ClearContext(CategoryId_SdCardDriverLog);
Context::ClearContext(CategoryId_GameCardCIDInfo);
Context::ClearContext(CategoryId_GameCardErrorInfo);
Context::ClearContext(CategoryId_GameCardDetailedErrorInfo);
Context::ClearContext(CategoryId_GameCardLogInfo);
Context::ClearContext(CategoryId_FsProxyErrorInfo);
Context::ClearContext(CategoryId_FsProxyErrorInfo2);
Context::ClearContext(CategoryId_FsProxyErrorInfo3);
Context::ClearContext(CategoryId_FsMemoryInfo);
}
} }

View File

@@ -423,7 +423,11 @@ namespace ams::erpt::srv {
auto report = std::make_unique<Report>(record.get(), redirect_new_reports); auto report = std::make_unique<Report>(record.get(), redirect_new_reports);
R_UNLESS(report != nullptr, erpt::ResultOutOfMemory()); R_UNLESS(report != nullptr, erpt::ResultOutOfMemory());
auto report_guard = SCOPE_GUARD { const auto delete_res = report->Delete(); R_ASSERT(delete_res); AMS_UNUSED(delete_res); }; auto report_guard = SCOPE_GUARD {
const auto delete_res = report->Delete();
R_ASSERT(delete_res);
AMS_UNUSED(delete_res);
};
R_TRY(Context::WriteContextsToReport(report.get())); R_TRY(Context::WriteContextsToReport(report.get()));
R_TRY(report->GetSize(std::addressof(record->m_info.report_size))); R_TRY(report->GetSize(std::addressof(record->m_info.report_size)));
@@ -434,7 +438,7 @@ namespace ams::erpt::srv {
} else { } else {
/* If we are redirecting new reports, we don't want to store the report in the journal. */ /* If we are redirecting new reports, we don't want to store the report in the journal. */
/* We should take this opportunity to delete any attachments associated with the report. */ /* We should take this opportunity to delete any attachments associated with the report. */
R_ABORT_UNLESS(JournalForAttachments::DeleteAttachments(report_id)); R_TRY(JournalForAttachments::DeleteAttachments(report_id));
} }
R_TRY(Journal::Commit()); R_TRY(Journal::Commit());
@@ -489,6 +493,20 @@ namespace ams::erpt::srv {
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfo)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfo));
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoAuto)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoAuto));
static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoDefaults)); static_cast<void>(Context::ClearContext(CategoryId_ErrorInfoDefaults));
#if defined(ATMOSPHERE_OS_HORIZON)
/* TODO: What else is missing? */
if (hos::GetVersion() >= hos::Version_17_0_0 && flags.Test<CreateReportOptionFlag::SubmitFsInfo>()) {
ClearFsInfo();
}
/* if (erpt::ResultInvalidPowerState::Includes(...)) {
* Nintendo ignores this and sends "power_state_violation" play report if this error happens.
* } else {
* Nintendo sends "write_failure" play report if any other error happens.
* }
*/
#endif
}; };
/* Get the context entry pointer. */ /* Get the context entry pointer. */

View File

@@ -75,15 +75,15 @@ namespace ams::pgl::srv {
NON_COPYABLE(HostPackageReader); NON_COPYABLE(HostPackageReader);
NON_MOVEABLE(HostPackageReader); NON_MOVEABLE(HostPackageReader);
private: private:
char m_content_path[fs::EntryNameLengthMax] = {}; char m_content_path[fs::EntryNameLengthMax] = {};
ExtensionType m_extension_type = ExtensionType::None; ExtensionType m_extension_type = ExtensionType::None;
char m_mount_name[fs::MountNameLengthMax] = {}; char m_mount_name[fs::MountNameLengthMax + 1] = {};
bool m_is_mounted = false; bool m_is_mounted = false;
ncm::AutoBuffer m_content_meta_buffer; ncm::AutoBuffer m_content_meta_buffer;
ncm::ProgramId m_program_id = ncm::InvalidProgramId; ncm::ProgramId m_program_id = ncm::InvalidProgramId;
u32 m_program_version = 0; u32 m_program_version = 0;
ncm::ContentMetaType m_content_meta_type = static_cast<ncm::ContentMetaType>(0); ncm::ContentMetaType m_content_meta_type = static_cast<ncm::ContentMetaType>(0);
u8 m_program_index = 0; u8 m_program_index = 0;
public: public:
HostPackageReader() : m_content_meta_buffer() { /* ... */ } HostPackageReader() : m_content_meta_buffer() { /* ... */ }
~HostPackageReader() { ~HostPackageReader() {

View File

@@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 11 #define ATMOSPHERE_RELEASE_VERSION_MINOR 11
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0

View File

@@ -99,8 +99,9 @@
#define ATMOSPHERE_TARGET_FIRMWARE_21_1_0 ATMOSPHERE_TARGET_FIRMWARE(21, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_21_1_0 ATMOSPHERE_TARGET_FIRMWARE(21, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_21_2_0 ATMOSPHERE_TARGET_FIRMWARE(21, 2, 0) #define ATMOSPHERE_TARGET_FIRMWARE_21_2_0 ATMOSPHERE_TARGET_FIRMWARE(21, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_22_1_0 ATMOSPHERE_TARGET_FIRMWARE(22, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_0_0 #define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_1_0
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@@ -192,6 +193,7 @@ namespace ams {
TargetFirmware_21_1_0 = ATMOSPHERE_TARGET_FIRMWARE_21_1_0, TargetFirmware_21_1_0 = ATMOSPHERE_TARGET_FIRMWARE_21_1_0,
TargetFirmware_21_2_0 = ATMOSPHERE_TARGET_FIRMWARE_21_2_0, TargetFirmware_21_2_0 = ATMOSPHERE_TARGET_FIRMWARE_21_2_0,
TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0, TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0,
TargetFirmware_22_1_0 = ATMOSPHERE_TARGET_FIRMWARE_22_1_0,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,

View File

@@ -452,6 +452,9 @@ namespace ams::result::impl {
} \ } \
} }
/// Explicitly discards the result returned by an expression.
#define R_DISCARD(res_expr) (static_cast<void>(res_expr))
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_IS_STRATOSPHERE) && !defined(AMS_ENABLE_DETAILED_ASSERTIONS) && !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING) #if defined(ATMOSPHERE_BOARD_NINTENDO_NX) && defined(ATMOSPHERE_IS_STRATOSPHERE) && !defined(AMS_ENABLE_DETAILED_ASSERTIONS) && !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING)
#define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false) #define AMS_CALL_ON_RESULT_ASSERTION_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)
#define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false) #define AMS_CALL_ON_RESULT_ABORT_IMPL(cond, val) do { ::ams::diag::impl::FatalErrorByResultForNx(val); AMS_INFINITE_LOOP(); AMS_ASSUME(false); } while (false)

View File

@@ -36,6 +36,11 @@ namespace ams::mitm::fs {
}; };
constexpr const ApplicationWithDynamicHeapInfo ApplicationsWithDynamicHeap[] = { constexpr const ApplicationWithDynamicHeapInfo ApplicationsWithDynamicHeap[] = {
/* Until Then. */
/* Requirement ~34 MB. */
/* No particular heap sensitivity. */
{ 0x010019C023004000, 16_MB, 0_MB },
/* Trails in the Sky 1st Chapter. */ /* Trails in the Sky 1st Chapter. */
/* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */ /* Requirement ? MB. 16 MB stolen heap fixes a crash, though. */
/* Unknown heap sensitivity. */ /* Unknown heap sensitivity. */

View File

@@ -1,18 +0,0 @@
/*
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*/
#define AMS_ZSTD_IMPLEMENTATION
#include <stratosphere/util/util_zbic_for_loader.hpp>

View File

@@ -15,7 +15,7 @@
"filesystem_access": { "filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF" "permissions": "0xFFFFFFFFFFFFFFFF"
}, },
"service_access": ["erpt:c", "fatal:u", "fsp-srv", "ldr:shel", "lm", "lr", "pm:shell", "set", "set:sys"], "service_access": ["fatal:u", "fsp-srv", "ldr:shel", "lr", "pm:shell", "set:sys"],
"service_host": ["pgl"], "service_host": ["pgl"],
"kernel_capabilities": [{ "kernel_capabilities": [{
"type": "kernel_flags", "type": "kernel_flags",

View File

@@ -31,12 +31,13 @@ namespace ams {
fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate); fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate);
fs::SetEnabledAutoAbort(false); fs::SetEnabledAutoAbort(false);
/* Initialize lr. */
lr::Initialize();
/* Initialize other services we need. */ /* Initialize other services we need. */
R_ABORT_UNLESS(setInitialize());
R_ABORT_UNLESS(setsysInitialize()); R_ABORT_UNLESS(setsysInitialize());
R_ABORT_UNLESS(pmshellInitialize()); R_ABORT_UNLESS(pmshellInitialize());
R_ABORT_UNLESS(ldrShellInitialize()); R_ABORT_UNLESS(ldrShellInitialize());
R_ABORT_UNLESS(lrInitialize());
/* Verify that we can sanely execute. */ /* Verify that we can sanely execute. */
ams::CheckApiVersion(); ams::CheckApiVersion();
@@ -58,3 +59,36 @@ namespace ams {
} }
} }
/* Override operator new. */
void *operator new(size_t size) {
return ams::pgl::srv::Allocate(size);
}
void *operator new(size_t size, const std::nothrow_t &) {
return ams::pgl::srv::Allocate(size);
}
void operator delete(void *p) {
return ams::pgl::srv::Deallocate(p, 0);
}
void operator delete(void *p, size_t size) {
return ams::pgl::srv::Deallocate(p, size);
}
void *operator new[](size_t size) {
return ams::pgl::srv::Allocate(size);
}
void *operator new[](size_t size, const std::nothrow_t &) {
return ams::pgl::srv::Allocate(size);
}
void operator delete[](void *p) {
return ams::pgl::srv::Deallocate(p, 0);
}
void operator delete[](void *p, size_t size) {
return ams::pgl::srv::Deallocate(p, size);
}

View File

@@ -141,8 +141,31 @@ namespace dbk {
return rc; return rc;
} }
u32 EncodeVersion(u32 major, u32 minor, u32 micro, u32 relstep = 0) { u32 EncodeVersion(u32 major, u32 minor, u32 micro) {
return ((major & 0xFF) << 24) | ((minor & 0xFF) << 16) | ((micro & 0xFF) << 8) | ((relstep & 0xFF) << 8); return ((major & 0xFF) << 24) | ((minor & 0xFF) << 16) | ((micro & 0xFF) << 8);
}
u32 NcmVersionToHosVersion(u32 ncm_version) {
const u32 major = (ncm_version >> 26) & 0x1f;
const u32 minor = (ncm_version >> 20) & 0x1f;
const u32 micro = (ncm_version >> 16) & 0xf;
return EncodeVersion(major, minor, micro);
}
bool IsHosVersionSupported(u32 hos_version) {
return hos_version <= g_supported_version;
}
std::shared_ptr<Menu> CreateUpdateMenuAfterPathSelection(std::shared_ptr<Menu> prev_menu) {
AmsSuUpdateInformation update_info = {};
if (R_SUCCEEDED(amssuGetUpdateInformation(&update_info, g_update_path))) {
const u32 update_hos_version = NcmVersionToHosVersion(update_info.version);
if (!IsHosVersionSupported(update_hos_version)) {
return std::make_shared<FirmwareNotSupportedMenu>(prev_menu, update_info.version, g_supported_version);
}
}
return std::make_shared<ValidateUpdateMenu>(prev_menu);
} }
} }
@@ -347,7 +370,7 @@ namespace dbk {
/* Copy result text if there is a result. */ /* Copy result text if there is a result. */
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
snprintf(m_result_text, sizeof(m_result_text), "Result: 0x%08x", rc); snprintf(m_result_text, sizeof(m_result_text), "Ergebnis: 0x%08x", rc);
} }
} }
@@ -375,7 +398,7 @@ namespace dbk {
const float button_width = WindowWidth - HorizontalInset * 2.0f; const float button_width = WindowWidth - HorizontalInset * 2.0f;
/* Add buttons. */ /* Add buttons. */
this->AddButton(ExitButtonId, "Exit", x + HorizontalInset, button_y, button_width, ButtonHeight); this->AddButton(ExitButtonId, "Beenden", x + HorizontalInset, button_y, button_width, ButtonHeight);
this->SetButtonSelected(ExitButtonId, true); this->SetButtonSelected(ExitButtonId, true);
} }
@@ -412,8 +435,8 @@ namespace dbk {
const float button_y = y + TitleGap + SubTextHeight + VerticalGap * 2.0f + (R_FAILED(m_rc) ? SubTextHeight : 0.0f); const float button_y = y + TitleGap + SubTextHeight + VerticalGap * 2.0f + (R_FAILED(m_rc) ? SubTextHeight : 0.0f);
const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap; const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap;
this->AddButton(BackButtonId, "Back", x + HorizontalInset, button_y, button_width, ButtonHeight); this->AddButton(BackButtonId, "Zurück", x + HorizontalInset, button_y, button_width, ButtonHeight);
this->AddButton(ContinueButtonId, "Continue", x + HorizontalInset + button_width + ButtonHorizontalGap, button_y, button_width, ButtonHeight); this->AddButton(ContinueButtonId, "Weiter", x + HorizontalInset + button_width + ButtonHorizontalGap, button_y, button_width, ButtonHeight);
this->SetButtonSelected(ContinueButtonId, true); this->SetButtonSelected(ContinueButtonId, true);
} }
@@ -446,12 +469,75 @@ namespace dbk {
} }
} }
namespace {
struct FirmwareNotSupportedSubtext {
char value[0x100];
FirmwareNotSupportedSubtext(u32 update_ncm_version, u32 max_supported_hos_version) {
snprintf(this->value, sizeof(this->value),
"Maximal unterstützte Firmware ist %u.%u.%u.\n"
"Aktualisiere Atmosphere, bevor du diese Firmware installierst.",
(max_supported_hos_version >> 24) & 0xff, (max_supported_hos_version >> 16) & 0xff, (max_supported_hos_version >> 8) & 0xff);
}
operator const char *() const {
return this->value;
}
};
}
FirmwareNotSupportedMenu::FirmwareNotSupportedMenu(std::shared_ptr<Menu> prev_menu, u32 update_ncm_version, u32 max_supported_hos_version)
: AlertMenu(prev_menu, "Nicht unterstützte Firmware-Version", FirmwareNotSupportedSubtext(update_ncm_version, max_supported_hos_version), 0) {
const float window_height = WindowHeight + SubTextAreaHeight;
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
const float button_y = y + TitleGap + SubTextAreaHeight + VerticalGap * 2.0f;
const float button_width = WindowWidth - HorizontalInset * 2.0f;
this->AddButton(BackButtonId, "Zurück", x + HorizontalInset, button_y, button_width, ButtonHeight);
this->SetButtonSelected(BackButtonId, true);
}
void FirmwareNotSupportedMenu::Draw(NVGcontext *vg, u64 ns) {
const float window_height = WindowHeight + SubTextAreaHeight;
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - window_height / 2.0f;
DrawWindow(vg, m_text, x, y, WindowWidth, window_height);
DrawTextBlock(vg, m_subtext, x + HorizontalInset, y + TitleGap, WindowWidth - HorizontalInset * 2.0f, SubTextAreaHeight);
this->DrawButtons(vg, ns);
}
void FirmwareNotSupportedMenu::Update(u64 ns) {
u64 k_down = padGetButtonsDown(&g_pad);
if (k_down & HidNpadButton_B) {
ReturnToPreviousMenu();
return;
}
if (const Button *activated_button = this->GetActivatedButton(); activated_button != nullptr) {
if (activated_button->id == BackButtonId) {
ReturnToPreviousMenu();
return;
}
}
this->UpdateButtons();
if (const Button *selected_button = this->GetSelectedButton(); k_down && selected_button == nullptr) {
this->SetButtonSelected(BackButtonId, true);
}
}
MainMenu::MainMenu() : Menu(nullptr) { MainMenu::MainMenu() : Menu(nullptr) {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
this->AddButton(InstallButtonId, "Install", x + HorizontalInset, y + TitleGap, WindowWidth - HorizontalInset * 2, ButtonHeight); this->AddButton(InstallButtonId, "Installieren", x + HorizontalInset, y + TitleGap, WindowWidth - HorizontalInset * 2, ButtonHeight);
this->AddButton(ExitButtonId, "Exit", x + HorizontalInset, y + TitleGap + ButtonHeight + VerticalGap, WindowWidth - HorizontalInset * 2, ButtonHeight); this->AddButton(ExitButtonId, "Beenden", x + HorizontalInset, y + TitleGap + ButtonHeight + VerticalGap, WindowWidth - HorizontalInset * 2, ButtonHeight);
this->SetButtonSelected(InstallButtonId, true); this->SetButtonSelected(InstallButtonId, true);
} }
@@ -475,24 +561,24 @@ namespace dbk {
u64 is_emummc; u64 is_emummc;
if (R_FAILED(rc = splGetConfig(SplConfigItem_HardwareType, &hardware_type))) { if (R_FAILED(rc = splGetConfig(SplConfigItem_HardwareType, &hardware_type))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to get hardware type.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Ein Fehler ist aufgetreten", "Hardwaretyp konnte nicht ermittelt werden.", rc));
return; return;
} }
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereHasRcmBugPatch), &has_rcm_bug_patch))) { if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereHasRcmBugPatch), &has_rcm_bug_patch))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to check RCM bug status.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Ein Fehler ist aufgetreten", "RCM-Bug-Status konnte nicht geprüft werden.", rc));
return; return;
} }
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereEmummcType), &is_emummc))) { if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereEmummcType), &is_emummc))) {
ChangeMenu(std::make_shared<ErrorMenu>("An error has occurred", "Failed to check emuMMC status.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Ein Fehler ist aufgetreten", "emuMMC-Status konnte nicht geprüft werden.", rc));
return; return;
} }
/* Warn if we're working with a patched unit. */ /* Warn if we're working with a patched unit. */
const bool is_erista = hardware_type == 0 || hardware_type == 1; const bool is_erista = hardware_type == 0 || hardware_type == 1;
if (is_erista && has_rcm_bug_patch && !is_emummc) { if (is_erista && has_rcm_bug_patch && !is_emummc) {
ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, file_menu, "Warning: Patched unit detected", "You may burn fuses or render your switch inoperable.")); ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, file_menu, "Warnung: Gepatchte Konsole erkannt", "Sicherungen können durchgebrannt werden oder die Konsole unbrauchbar gemacht werden."));
} else { } else {
ChangeMenu(file_menu); ChangeMenu(file_menu);
} }
@@ -688,7 +774,7 @@ namespace dbk {
snprintf(g_update_path, sizeof(g_update_path), "%s", current_path); snprintf(g_update_path, sizeof(g_update_path), "%s", current_path);
/* Change the menu. */ /* Change the menu. */
ChangeMenu(std::make_shared<ValidateUpdateMenu>(g_current_menu)); ChangeMenu(CreateUpdateMenuAfterPathSelection(g_current_menu));
} else { } else {
ChangeMenu(std::make_shared<FileMenu>(g_current_menu, current_path)); ChangeMenu(std::make_shared<FileMenu>(g_current_menu, current_path));
} }
@@ -739,7 +825,7 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
DrawWindow(vg, "Select an update directory", x, y, WindowWidth, WindowHeight); DrawWindow(vg, "Update-Ordner auswählen", x, y, WindowWidth, WindowHeight);
DrawTextBackground(vg, x + TextBackgroundOffset, y + TitleGap, WindowWidth - TextBackgroundOffset * 2.0f, (FileRowHeight + FileRowGap) * MaxFileRows + FileRowGap); DrawTextBackground(vg, x + TextBackgroundOffset, y + TitleGap, WindowWidth - TextBackgroundOffset * 2.0f, (FileRowHeight + FileRowGap) * MaxFileRows + FileRowGap);
nvgSave(vg); nvgSave(vg);
@@ -765,8 +851,8 @@ namespace dbk {
const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap; const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap;
/* Add buttons. */ /* Add buttons. */
this->AddButton(BackButtonId, "Back", x + HorizontalInset, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight); this->AddButton(BackButtonId, "Zurück", x + HorizontalInset, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight);
this->AddButton(ContinueButtonId, "Continue", x + HorizontalInset + button_width + ButtonHorizontalGap, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight); this->AddButton(ContinueButtonId, "Weiter", x + HorizontalInset + button_width + ButtonHorizontalGap, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight);
this->SetButtonEnabled(BackButtonId, false); this->SetButtonEnabled(BackButtonId, false);
this->SetButtonEnabled(ContinueButtonId, false); this->SetButtonEnabled(ContinueButtonId, false);
@@ -776,32 +862,33 @@ namespace dbk {
this->SetButtonSelected(BackButtonId, true); this->SetButtonSelected(BackButtonId, true);
} else { } else {
/* Log this early so it is printed out before validation causes stalling. */ /* Log this early so it is printed out before validation causes stalling. */
this->LogText("Validating update, this may take a moment...\n"); this->LogText("Update wird geprüft, bitte warten...\n");
} }
} }
Result ValidateUpdateMenu::GetUpdateInformation() { Result ValidateUpdateMenu::GetUpdateInformation() {
Result rc = 0; Result rc = 0;
this->LogText("Directory %s\n", g_update_path); this->LogText("Verzeichnis %s\n", g_update_path);
/* Attempt to get the update information. */ /* Attempt to get the update information. */
if (R_FAILED(rc = amssuGetUpdateInformation(&m_update_info, g_update_path))) { if (R_FAILED(rc = amssuGetUpdateInformation(&m_update_info, g_update_path))) {
if (rc == 0x1a405) { if (rc == 0x1a405) {
this->LogText("No update found in folder.\nEnsure your ncas are named correctly!\nResult: 0x%08x\n", rc); this->LogText("Kein Update im Ordner gefunden.\nStelle sicher, dass die NCAs korrekt benannt sind!\nErgebnis: 0x%08x\n", rc);
} else { } else {
this->LogText("Failed to get update information.\nResult: 0x%08x\n", rc); this->LogText("Update-Informationen konnten nicht abgerufen werden.\nErgebnis: 0x%08x\n", rc);
} }
return rc; return rc;
} }
/* Print update information. */ /* Print update information. */
this->LogText("- Version: %d.%d.%d\n", (m_update_info.version >> 26) & 0x1f, (m_update_info.version >> 20) & 0x1f, (m_update_info.version >> 16) & 0xf); this->LogText("- Version: %d.%d.%d\n", (m_update_info.version >> 26) & 0x1f, (m_update_info.version >> 20) & 0x1f, (m_update_info.version >> 16) & 0xf);
this->LogText("- Von Atmosphere max. unterstützt: %d.%d.%d\n", (g_supported_version >> 24) & 0xff, (g_supported_version >> 16) & 0xff, (g_supported_version >> 8) & 0xff);
if (m_update_info.exfat_supported) { if (m_update_info.exfat_supported) {
this->LogText("- exFAT: Supported\n"); this->LogText("- exFAT: Unterstützt\n");
} else { } else {
this->LogText("- exFAT: Unsupported\n"); this->LogText("- exFAT: Nicht unterstützt\n");
} }
this->LogText("- Firmware variations: %d\n", m_update_info.num_firmware_variations); this->LogText("- Firmware-Varianten: %d\n", m_update_info.num_firmware_variations);
/* Mark as having obtained update info. */ /* Mark as having obtained update info. */
m_has_info = true; m_has_info = true;
@@ -813,21 +900,21 @@ namespace dbk {
/* Validate the update. */ /* Validate the update. */
if (R_FAILED(rc = amssuValidateUpdate(&m_validation_info, g_update_path))) { if (R_FAILED(rc = amssuValidateUpdate(&m_validation_info, g_update_path))) {
this->LogText("Failed to validate update.\nResult: 0x%08x\n", rc); this->LogText("Update konnte nicht validiert werden.\nErgebnis: 0x%08x\n", rc);
return; return;
} }
/* Check the result. */ /* Check the result. */
if (R_SUCCEEDED(m_validation_info.result)) { if (R_SUCCEEDED(m_validation_info.result)) {
this->LogText("Update is valid!\n"); this->LogText("Update ist gültig!\n");
if (R_FAILED(m_validation_info.exfat_result)) { if (R_FAILED(m_validation_info.exfat_result)) {
const u32 version = m_validation_info.invalid_key.version; const u32 version = m_validation_info.invalid_key.version;
this->LogText("exFAT Validation failed with result: 0x%08x\n", m_validation_info.exfat_result); this->LogText("exFAT-Validierung fehlgeschlagen, Ergebnis: 0x%08x\n", m_validation_info.exfat_result);
this->LogText("Missing content:\n- Program id: %016lx\n- Version: %d.%d.%d\n", m_validation_info.invalid_key.id, (version >> 26) & 0x1f, (version >> 20) & 0x1f, (version >> 16) & 0xf); this->LogText("Fehlender Inhalt:\n- Programm-ID: %016lx\n- Version: %d.%d.%d\n", m_validation_info.invalid_key.id, (version >> 26) & 0x1f, (version >> 20) & 0x1f, (version >> 16) & 0xf);
/* Log the missing content id. */ /* Log the missing content id. */
this->LogText("- Content id: "); this->LogText("- Inhalts-ID: ");
for (size_t i = 0; i < sizeof(NcmContentId); i++) { for (size_t i = 0; i < sizeof(NcmContentId); i++) {
this->LogText("%02x", m_validation_info.invalid_content_id.c[i]); this->LogText("%02x", m_validation_info.invalid_content_id.c[i]);
} }
@@ -841,11 +928,11 @@ namespace dbk {
} else { } else {
/* Log the missing content info. */ /* Log the missing content info. */
const u32 version = m_validation_info.invalid_key.version; const u32 version = m_validation_info.invalid_key.version;
this->LogText("Validation failed with result: 0x%08x\n", m_validation_info.result); this->LogText("Validierung fehlgeschlagen, Ergebnis: 0x%08x\n", m_validation_info.result);
this->LogText("Missing content:\n- Program id: %016lx\n- Version: %d.%d.%d\n", m_validation_info.invalid_key.id, (version >> 26) & 0x1f, (version >> 20) & 0x1f, (version >> 16) & 0xf); this->LogText("Fehlender Inhalt:\n- Programm-ID: %016lx\n- Version: %d.%d.%d\n", m_validation_info.invalid_key.id, (version >> 26) & 0x1f, (version >> 20) & 0x1f, (version >> 16) & 0xf);
/* Log the missing content id. */ /* Log the missing content id. */
this->LogText("- Content id: "); this->LogText("- Inhalts-ID: ");
for (size_t i = 0; i < sizeof(NcmContentId); i++) { for (size_t i = 0; i < sizeof(NcmContentId); i++) {
this->LogText("%02x", m_validation_info.invalid_content_id.c[i]); this->LogText("%02x", m_validation_info.invalid_content_id.c[i]);
} }
@@ -897,13 +984,7 @@ namespace dbk {
/* Warn the user if they're updating with exFAT supposed to be supported but not present/corrupted. */ /* Warn the user if they're updating with exFAT supposed to be supported but not present/corrupted. */
if (m_update_info.exfat_supported && R_FAILED(m_validation_info.exfat_result)) { if (m_update_info.exfat_supported && R_FAILED(m_validation_info.exfat_result)) {
next_menu = std::make_shared<WarningMenu>(g_current_menu, next_menu, "Warning: exFAT firmware is missing or corrupt", "Are you sure you want to proceed?"); next_menu = std::make_shared<WarningMenu>(g_current_menu, next_menu, "Warnung: exFAT-Firmware fehlt oder ist beschädigt", "Möchtest du wirklich fortfahren?");
}
/* Warn the user if they're updating to a version higher than supported. */
const u32 version = m_validation_info.invalid_key.version;
if (EncodeVersion((version >> 26) & 0x1f, (version >> 20) & 0x1f, (version >> 16) & 0xf) > g_supported_version) {
next_menu = std::make_shared<WarningMenu>(g_current_menu, next_menu, "Warning: firmware is too new and not known to be supported", "Are you sure you want to proceed?");
} }
/* Change to the next menu. */ /* Change to the next menu. */
@@ -919,7 +1000,7 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
DrawWindow(vg, "Update information", x, y, WindowWidth, WindowHeight); DrawWindow(vg, "Update-Informationen", x, y, WindowWidth, WindowHeight);
DrawTextBackground(vg, x + HorizontalInset, y + TitleGap, WindowWidth - HorizontalInset * 2.0f, TextAreaHeight); DrawTextBackground(vg, x + HorizontalInset, y + TitleGap, WindowWidth - HorizontalInset * 2.0f, TextAreaHeight);
DrawTextBlock(vg, m_log_buffer, x + HorizontalInset + TextHorizontalInset, y + TitleGap + TextVerticalInset, WindowWidth - (HorizontalInset + TextHorizontalInset) * 2.0f, TextAreaHeight - TextVerticalInset * 2.0f); DrawTextBlock(vg, m_log_buffer, x + HorizontalInset + TextHorizontalInset, y + TitleGap + TextVerticalInset, WindowWidth - (HorizontalInset + TextHorizontalInset) * 2.0f, TextAreaHeight - TextVerticalInset * 2.0f);
@@ -933,8 +1014,8 @@ namespace dbk {
const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap; const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap;
/* Add buttons. */ /* Add buttons. */
this->AddButton(ResetToFactorySettingsButtonId, "Reset to factory settings", x + HorizontalInset, y + TitleGap, button_width, ButtonHeight); this->AddButton(ResetToFactorySettingsButtonId, "Werkseinstellungen", x + HorizontalInset, y + TitleGap, button_width, ButtonHeight);
this->AddButton(PreserveSettingsButtonId, "Preserve settings", x + HorizontalInset + button_width + ButtonHorizontalGap, y + TitleGap, button_width, ButtonHeight); this->AddButton(PreserveSettingsButtonId, "Einstellungen behalten", x + HorizontalInset + button_width + ButtonHorizontalGap, y + TitleGap, button_width, ButtonHeight);
this->SetButtonSelected(PreserveSettingsButtonId, true); this->SetButtonSelected(PreserveSettingsButtonId, true);
} }
@@ -963,11 +1044,11 @@ namespace dbk {
if (g_exfat_supported) { if (g_exfat_supported) {
next_menu = std::make_shared<ChooseExfatMenu>(g_current_menu); next_menu = std::make_shared<ChooseExfatMenu>(g_current_menu);
} else { } else {
next_menu = std::make_shared<WarningMenu>(g_current_menu, std::make_shared<InstallUpdateMenu>(g_current_menu), "Ready to begin update installation", "Are you sure you want to proceed?"); next_menu = std::make_shared<WarningMenu>(g_current_menu, std::make_shared<InstallUpdateMenu>(g_current_menu), "Bereit zur Update-Installation", "Möchtest du wirklich fortfahren?");
} }
if (g_reset_to_factory) { if (g_reset_to_factory) {
ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, next_menu, "Warning: Factory reset selected", "Saves and installed games will be permanently deleted.")); ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, next_menu, "Warnung: Werkseinstellungen ausgewählt", "Spielstände und installierte Spiele werden dauerhaft gelöscht."));
} else { } else {
ChangeMenu(next_menu); ChangeMenu(next_menu);
} }
@@ -985,7 +1066,7 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
DrawWindow(vg, "Select settings mode", x, y, WindowWidth, WindowHeight); DrawWindow(vg, "Einstellungsmodus wählen", x, y, WindowWidth, WindowHeight);
this->DrawButtons(vg, ns); this->DrawButtons(vg, ns);
} }
@@ -1029,7 +1110,7 @@ namespace dbk {
break; break;
} }
ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, std::make_shared<InstallUpdateMenu>(g_current_menu), "Ready to begin update installation", "Are you sure you want to proceed?")); ChangeMenu(std::make_shared<WarningMenu>(g_current_menu, std::make_shared<InstallUpdateMenu>(g_current_menu), "Bereit zur Update-Installation", "Möchtest du wirklich fortfahren?"));
} }
this->UpdateButtons(); this->UpdateButtons();
@@ -1044,7 +1125,7 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
DrawWindow(vg, "Select driver variant", x, y, WindowWidth, WindowHeight); DrawWindow(vg, "Treibervariante wählen", x, y, WindowWidth, WindowHeight);
this->DrawButtons(vg, ns); this->DrawButtons(vg, ns);
} }
@@ -1054,8 +1135,8 @@ namespace dbk {
const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap; const float button_width = (WindowWidth - HorizontalInset * 2.0f) / 2.0f - ButtonHorizontalGap;
/* Add buttons. */ /* Add buttons. */
this->AddButton(ShutdownButtonId, "Shutdown", x + HorizontalInset, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight); this->AddButton(ShutdownButtonId, "Ausschalten", x + HorizontalInset, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight);
this->AddButton(RebootButtonId, "Reboot", x + HorizontalInset + button_width + ButtonHorizontalGap, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight); this->AddButton(RebootButtonId, "Neustart", x + HorizontalInset + button_width + ButtonHorizontalGap, y + WindowHeight - BottomInset - ButtonHeight, button_width, ButtonHeight);
this->SetButtonEnabled(ShutdownButtonId, false); this->SetButtonEnabled(ShutdownButtonId, false);
this->SetButtonEnabled(RebootButtonId, false); this->SetButtonEnabled(RebootButtonId, false);
@@ -1075,34 +1156,34 @@ namespace dbk {
if (m_install_state == InstallState::NeedsSetup) { if (m_install_state == InstallState::NeedsSetup) {
/* Setup the update. */ /* Setup the update. */
if (R_FAILED(rc = amssuSetupUpdate(nullptr, UpdateTaskBufferSize, g_update_path, g_use_exfat))) { if (R_FAILED(rc = amssuSetupUpdate(nullptr, UpdateTaskBufferSize, g_update_path, g_use_exfat))) {
this->LogText("Failed to setup update.\nResult: 0x%08x\n", rc); this->LogText("Update-Einrichtung fehlgeschlagen.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
/* Log setup completion. */ /* Log setup completion. */
this->LogText("Update setup complete.\n"); this->LogText("Update-Einrichtung abgeschlossen.\n");
m_install_state = InstallState::NeedsPrepare; m_install_state = InstallState::NeedsPrepare;
} else if (m_install_state == InstallState::NeedsPrepare) { } else if (m_install_state == InstallState::NeedsPrepare) {
/* Request update preparation. */ /* Request update preparation. */
if (R_FAILED(rc = amssuRequestPrepareUpdate(&m_prepare_result))) { if (R_FAILED(rc = amssuRequestPrepareUpdate(&m_prepare_result))) {
this->LogText("Failed to request update preparation.\nResult: 0x%08x\n", rc); this->LogText("Update-Vorbereitung konnte nicht angefordert werden.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
/* Log awaiting prepare. */ /* Log awaiting prepare. */
this->LogText("Preparing update...\n"); this->LogText("Update wird vorbereitet...\n");
m_install_state = InstallState::AwaitingPrepare; m_install_state = InstallState::AwaitingPrepare;
} else if (m_install_state == InstallState::AwaitingPrepare) { } else if (m_install_state == InstallState::AwaitingPrepare) {
/* Check if preparation has a result. */ /* Check if preparation has a result. */
if (R_FAILED(rc = asyncResultWait(&m_prepare_result, 0)) && rc != 0xea01) { if (R_FAILED(rc = asyncResultWait(&m_prepare_result, 0)) && rc != 0xea01) {
this->LogText("Failed to check update preparation result.\nResult: 0x%08x\n", rc); this->LogText("Ergebnis der Update-Vorbereitung konnte nicht geprüft werden.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} else if (R_SUCCEEDED(rc)) { } else if (R_SUCCEEDED(rc)) {
if (R_FAILED(rc = asyncResultGet(&m_prepare_result))) { if (R_FAILED(rc = asyncResultGet(&m_prepare_result))) {
this->LogText("Failed to prepare update.\nResult: 0x%08x\n", rc); this->LogText("Update konnte nicht vorbereitet werden.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
@@ -1111,14 +1192,14 @@ namespace dbk {
/* Check if the update has been prepared. */ /* Check if the update has been prepared. */
bool prepared; bool prepared;
if (R_FAILED(rc = amssuHasPreparedUpdate(&prepared))) { if (R_FAILED(rc = amssuHasPreparedUpdate(&prepared))) {
this->LogText("Failed to check if update has been prepared.\nResult: 0x%08x\n", rc); this->LogText("Prüfung, ob das Update vorbereitet wurde, fehlgeschlagen.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
/* Mark for application if preparation complete. */ /* Mark for application if preparation complete. */
if (prepared) { if (prepared) {
this->LogText("Update preparation complete.\nApplying update...\n"); this->LogText("Update-Vorbereitung abgeschlossen.\nUpdate wird angewendet...\n");
m_install_state = InstallState::NeedsApply; m_install_state = InstallState::NeedsApply;
return rc; return rc;
} }
@@ -1126,7 +1207,7 @@ namespace dbk {
/* Check update progress. */ /* Check update progress. */
NsSystemUpdateProgress update_progress = {}; NsSystemUpdateProgress update_progress = {};
if (R_FAILED(rc = amssuGetPrepareUpdateProgress(&update_progress))) { if (R_FAILED(rc = amssuGetPrepareUpdateProgress(&update_progress))) {
this->LogText("Failed to check update progress.\nResult: 0x%08x\n", rc); this->LogText("Update-Fortschritt konnte nicht geprüft werden.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
@@ -1140,28 +1221,28 @@ namespace dbk {
} else if (m_install_state == InstallState::NeedsApply) { } else if (m_install_state == InstallState::NeedsApply) {
/* Apply the prepared update. */ /* Apply the prepared update. */
if (R_FAILED(rc = amssuApplyPreparedUpdate())) { if (R_FAILED(rc = amssuApplyPreparedUpdate())) {
this->LogText("Failed to apply update.\nResult: 0x%08x\n", rc); this->LogText("Update konnte nicht angewendet werden.\nErgebnis: 0x%08x\n", rc);
} else { } else {
/* Log success. */ /* Log success. */
this->LogText("Update applied successfully.\n"); this->LogText("Update erfolgreich angewendet.\n");
if (g_reset_to_factory) { if (g_reset_to_factory) {
if (R_FAILED(rc = nsResetToFactorySettingsForRefurbishment())) { if (R_FAILED(rc = nsResetToFactorySettingsForRefurbishment())) {
/* Fallback on ResetToFactorySettings. */ /* Fallback on ResetToFactorySettings. */
if (rc == MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer)) { if (rc == MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer)) {
if (R_FAILED(rc = nsResetToFactorySettings())) { if (R_FAILED(rc = nsResetToFactorySettings())) {
this->LogText("Failed to reset to factory settings.\nResult: 0x%08x\n", rc); this->LogText("Zurücksetzen auf Werkseinstellungen fehlgeschlagen.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
} else { } else {
this->LogText("Failed to reset to factory settings for refurbishment.\nResult: 0x%08x\n", rc); this->LogText("Zurücksetzen für Aufbereitung fehlgeschlagen.\nErgebnis: 0x%08x\n", rc);
this->MarkForReboot(); this->MarkForReboot();
return rc; return rc;
} }
} }
this->LogText("Successfully reset to factory settings.\n", rc); this->LogText("Erfolgreich auf Werkseinstellungen zurückgesetzt.\n", rc);
} }
} }
@@ -1201,7 +1282,7 @@ namespace dbk {
const float x = g_screen_width / 2.0f - WindowWidth / 2.0f; const float x = g_screen_width / 2.0f - WindowWidth / 2.0f;
const float y = g_screen_height / 2.0f - WindowHeight / 2.0f; const float y = g_screen_height / 2.0f - WindowHeight / 2.0f;
DrawWindow(vg, "Installing update", x, y, WindowWidth, WindowHeight); DrawWindow(vg, "Update wird installiert", x, y, WindowWidth, WindowHeight);
DrawProgressText(vg, x + HorizontalInset, y + TitleGap, m_progress_percent); DrawProgressText(vg, x + HorizontalInset, y + TitleGap, m_progress_percent);
DrawProgressBar(vg, x + HorizontalInset, y + TitleGap + ProgressTextHeight, WindowWidth - HorizontalInset * 2.0f, ProgressBarHeight, m_progress_percent); DrawProgressBar(vg, x + HorizontalInset, y + TitleGap + ProgressTextHeight, WindowWidth - HorizontalInset * 2.0f, ProgressBarHeight, m_progress_percent);
DrawTextBackground(vg, x + HorizontalInset, y + TitleGap + ProgressTextHeight + ProgressBarHeight + VerticalGap, WindowWidth - HorizontalInset * 2.0f, TextAreaHeight); DrawTextBackground(vg, x + HorizontalInset, y + TitleGap + ProgressTextHeight + ProgressBarHeight + VerticalGap, WindowWidth - HorizontalInset * 2.0f, TextAreaHeight);
@@ -1211,7 +1292,7 @@ namespace dbk {
/* We have drawn now, allow setup to occur. */ /* We have drawn now, allow setup to occur. */
if (m_install_state == InstallState::NeedsDraw) { if (m_install_state == InstallState::NeedsDraw) {
this->LogText("Beginning update setup...\n"); this->LogText("Update-Einrichtung wird gestartet...\n");
m_install_state = InstallState::NeedsSetup; m_install_state = InstallState::NeedsSetup;
} }
} }
@@ -1236,7 +1317,7 @@ namespace dbk {
/* Attempt to get the exosphere version. */ /* Attempt to get the exosphere version. */
u64 version; u64 version;
if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereApiVersionConfigItem), &version))) { if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereApiVersionConfigItem), &version))) {
ChangeMenu(std::make_shared<ErrorMenu>("Atmosphere not found", "Daybreak requires Atmosphere to be installed.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Atmosphere nicht gefunden", "Daybreak benötigt eine installierte Atmosphere-Umgebung.", rc));
return false; return false;
} }
@@ -1247,20 +1328,22 @@ namespace dbk {
/* Validate the exosphere version. */ /* Validate the exosphere version. */
const bool ams_supports_sysupdate_api = EncodeVersion(version_major, version_minor, version_micro) >= EncodeVersion(0, 14, 0); const bool ams_supports_sysupdate_api = EncodeVersion(version_major, version_minor, version_micro) >= EncodeVersion(0, 14, 0);
if (!ams_supports_sysupdate_api) { if (!ams_supports_sysupdate_api) {
ChangeMenu(std::make_shared<ErrorMenu>("Outdated Atmosphere version", "Daybreak requires Atmosphere 0.14.0 or later.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Veraltete Atmosphere-Version", "Daybreak benötigt Atmosphere 0.14.0 oder neuer.", rc));
return false; return false;
} }
/* Ensure DayBreak is ran as a NRO. */ /* Ensure DayBreak is ran as a NRO. */
if (envIsNso()) { if (envIsNso()) {
ChangeMenu(std::make_shared<ErrorMenu>("Unsupported Environment", "Please launch Daybreak via the Homebrew menu.", rc)); ChangeMenu(std::make_shared<ErrorMenu>("Nicht unterstützte Umgebung", "Bitte starte Daybreak über das Homebrew-Menü.", rc));
return false; return false;
} }
/* Attempt to get the supported version. */ /* Get the maximum HOS version supported by this Atmosphere build (hos::Version_Max). */
if (R_SUCCEEDED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereSupportedHosVersion), &version))) { if (R_FAILED(rc = splGetConfig(static_cast<SplConfigItem>(ExosphereSupportedHosVersion), &version))) {
g_supported_version = static_cast<u32>(version); ChangeMenu(std::make_shared<ErrorMenu>("Atmosphere nicht gefunden", "Maximal unterstützte Firmware-Version konnte nicht ermittelt werden.", rc));
return false;
} }
g_supported_version = static_cast<u32>(version);
/* Initialize ams:su. */ /* Initialize ams:su. */
if (R_FAILED(rc = amssuInitialize())) { if (R_FAILED(rc = amssuInitialize())) {
@@ -1280,7 +1363,7 @@ namespace dbk {
strncpy(g_update_path, update_path, sizeof(g_update_path)-1); strncpy(g_update_path, update_path, sizeof(g_update_path)-1);
/* Change the menu. */ /* Change the menu. */
ChangeMenu(std::make_shared<ValidateUpdateMenu>(g_current_menu)); ChangeMenu(CreateUpdateMenuAfterPathSelection(g_current_menu));
return true; return true;
} }

View File

@@ -120,6 +120,17 @@ namespace dbk {
virtual void Update(u64 ns) override; virtual void Update(u64 ns) override;
}; };
class FirmwareNotSupportedMenu : public AlertMenu {
private:
static constexpr u32 BackButtonId = 0;
static constexpr float SubTextAreaHeight = 72.0f;
public:
FirmwareNotSupportedMenu(std::shared_ptr<Menu> prev_menu, u32 update_ncm_version, u32 max_supported_hos_version);
virtual void Update(u64 ns) override;
virtual void Draw(NVGcontext *vg, u64 ns) override;
};
class MainMenu : public Menu { class MainMenu : public Menu {
private: private:
static constexpr u32 InstallButtonId = 0; static constexpr u32 InstallButtonId = 0;

View File

@@ -148,7 +148,7 @@ namespace dbk {
void DrawProgressText(NVGcontext *vg, float x, float y, float progress) { void DrawProgressText(NVGcontext *vg, float x, float y, float progress) {
char progress_text[32] = {}; char progress_text[32] = {};
snprintf(progress_text, sizeof(progress_text)-1, "%d%% complete", static_cast<int>(progress * 100.0f)); snprintf(progress_text, sizeof(progress_text)-1, "%d%% abgeschlossen", static_cast<int>(progress * 100.0f));
nvgFontSize(vg, 24.0f); nvgFontSize(vg, 24.0f);
nvgFontFace(vg, SwitchStandardFont); nvgFontFace(vg, SwitchStandardFont);