mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-27 05:04:10 -04:00
Loader: Button override + first-class HBL support
This commit is contained in:
parent
d8391078c8
commit
6afbcd12d9
11 changed files with 692 additions and 35 deletions
|
@ -19,8 +19,10 @@
|
|||
#include <cstdio>
|
||||
#include "ldr_npdm.hpp"
|
||||
#include "ldr_registration.hpp"
|
||||
#include "ldr_content_management.hpp"
|
||||
|
||||
static NpdmUtils::NpdmCache g_npdm_cache = {0};
|
||||
static NpdmUtils::NpdmCache g_original_npdm_cache = {0};
|
||||
static char g_npdm_path[FS_MAX_PATH] = {0};
|
||||
|
||||
Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) {
|
||||
|
@ -31,6 +33,12 @@ Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
FILE *NpdmUtils::OpenNpdmFromHBL() {
|
||||
std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0);
|
||||
snprintf(g_npdm_path, FS_MAX_PATH, "hbl:/main.npdm");
|
||||
return fopen(g_npdm_path, "rb");
|
||||
}
|
||||
|
||||
FILE *NpdmUtils::OpenNpdmFromExeFS() {
|
||||
std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0);
|
||||
snprintf(g_npdm_path, FS_MAX_PATH, "code:/main.npdm");
|
||||
|
@ -45,20 +53,23 @@ FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) {
|
|||
|
||||
|
||||
FILE *NpdmUtils::OpenNpdm(u64 title_id) {
|
||||
FILE *f_out = OpenNpdmFromSdCard(title_id);
|
||||
if (f_out != NULL) {
|
||||
return f_out;
|
||||
if (ContentManagement::ShouldOverrideContents()) {
|
||||
if (ContentManagement::ShouldReplaceWithHBL(title_id)) {
|
||||
return OpenNpdmFromHBL();
|
||||
}
|
||||
FILE *f_out = OpenNpdmFromSdCard(title_id);
|
||||
if (f_out != NULL) {
|
||||
return f_out;
|
||||
}
|
||||
}
|
||||
return OpenNpdmFromExeFS();
|
||||
}
|
||||
|
||||
Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
||||
Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) {
|
||||
Result rc;
|
||||
|
||||
g_npdm_cache.info = (const NpdmUtils::NpdmInfo){0};
|
||||
|
||||
FILE *f_npdm = OpenNpdm(tid);
|
||||
|
||||
cache->info = (const NpdmUtils::NpdmInfo){0};
|
||||
|
||||
rc = 0x202;
|
||||
if (f_npdm == NULL) {
|
||||
/* For generic "Couldn't open the file" error, just say the file doesn't exist. */
|
||||
|
@ -70,7 +81,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
fseek(f_npdm, 0, SEEK_SET);
|
||||
|
||||
rc = 0x609;
|
||||
if ((npdm_size > sizeof(g_npdm_cache.buffer)) || (fread(g_npdm_cache.buffer, 1, npdm_size, f_npdm) != npdm_size)) {
|
||||
if ((npdm_size > sizeof(cache->buffer)) || (fread(cache->buffer, 1, npdm_size, f_npdm) != npdm_size)) {
|
||||
fclose(f_npdm);
|
||||
return rc;
|
||||
}
|
||||
|
@ -83,8 +94,8 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
}
|
||||
|
||||
/* For ease of access... */
|
||||
g_npdm_cache.info.header = (NpdmUtils::NpdmHeader *)(g_npdm_cache.buffer);
|
||||
NpdmInfo *info = &g_npdm_cache.info;
|
||||
cache->info.header = (NpdmUtils::NpdmHeader *)(cache->buffer);
|
||||
NpdmInfo *info = &cache->info;
|
||||
|
||||
if (info->header->magic != MAGIC_META) {
|
||||
return rc;
|
||||
|
@ -98,7 +109,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
info->aci0 = (NpdmAci0 *)(g_npdm_cache.buffer + info->header->aci0_offset);
|
||||
info->aci0 = (NpdmAci0 *)(cache->buffer + info->header->aci0_offset);
|
||||
|
||||
if (info->aci0->magic != MAGIC_ACI0) {
|
||||
return rc;
|
||||
|
@ -126,7 +137,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
info->acid = (NpdmAcid *)(g_npdm_cache.buffer + info->header->acid_offset);
|
||||
info->acid = (NpdmAcid *)(cache->buffer + info->header->acid_offset);
|
||||
|
||||
if (info->acid->magic != MAGIC_ACID) {
|
||||
return rc;
|
||||
|
@ -152,7 +163,48 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
|
||||
info->acid_kac = (void *)((uintptr_t)info->acid + info->acid->kac_offset);
|
||||
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
||||
Result rc;
|
||||
|
||||
rc = LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache);
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
NpdmInfo *info = &g_npdm_cache.info;
|
||||
/* Override the ACID/ACI0 title ID, in order to facilitate HBL takeover of any title. */
|
||||
info->acid->title_id_range_min = tid;
|
||||
info->acid->title_id_range_max = tid;
|
||||
info->aci0->title_id = tid;
|
||||
|
||||
if (ContentManagement::ShouldOverrideContents() && ContentManagement::ShouldReplaceWithHBL(tid)
|
||||
&& R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) {
|
||||
NpdmInfo *original_info = &g_original_npdm_cache.info;
|
||||
/* Fix pool partition. */
|
||||
if (kernelAbove500()) {
|
||||
info->acid->flags = (info->acid->flags & 0xFFFFFFF9) | (original_info->acid->flags & 0x00000006);
|
||||
}
|
||||
/* Fix application type. */
|
||||
const u32 original_application_type = GetApplicationType((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7;
|
||||
u32 *caps = (u32 *)info->aci0_kac;
|
||||
for (unsigned int i = 0; i < info->aci0->kac_size/sizeof(u32); i++) {
|
||||
if ((caps[i] & 0x3FFF) == 0x1FFF) {
|
||||
caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14);
|
||||
}
|
||||
}
|
||||
caps = (u32 *)info->acid_kac;
|
||||
for (unsigned int i = 0; i < info->acid->kac_size/sizeof(u32); i++) {
|
||||
if ((caps[i] & 0x3FFF) == 0x1FFF) {
|
||||
caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We validated! */
|
||||
info->title_id = tid;
|
||||
*out = *info;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue