From f14107662b4ae204f46ce68d5f2df9d9ff252a78 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Mon, 21 Jun 2021 20:30:46 -0400 Subject: [PATCH] Added BFSAR interface. --- include/core/bfsar.h | 44 ++++++++++ include/defines.h | 1 + source/core/bfsar.c | 202 +++++++++++++++++++++++++++++++++++++++++++ source/core/bfttf.c | 2 +- 4 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 include/core/bfsar.h create mode 100644 source/core/bfsar.c diff --git a/include/core/bfsar.h b/include/core/bfsar.h new file mode 100644 index 0000000..5c53181 --- /dev/null +++ b/include/core/bfsar.h @@ -0,0 +1,44 @@ +/* + * bfsar.h + * + * Copyright (c) 2020-2021, DarkMatterCore . + * + * This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool). + * + * nxdumptool is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nxdumptool is distributed in the hope that 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 + +#ifndef __BFSAR_H__ +#define __BFSAR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/// Initializes the BFSAR interface. +bool bfsarInitialize(void); + +/// Closes the BFSAR interface. +void bfsarExit(void); + +/// Returns a pointer to the BFSAR file path. +const char *bfsarGetFilePath(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BFSAR_H__ */ diff --git a/include/defines.h b/include/defines.h index c54a5be..3965e58 100644 --- a/include/defines.h +++ b/include/defines.h @@ -61,6 +61,7 @@ #define SPL_SYSMODULE_TID (u64)0x0100000000000028 #define ES_SYSMODULE_TID (u64)0x0100000000000033 #define SYSTEM_UPDATE_TID (u64)0x0100000000000816 +#define QLAUNCH_TID (u64)0x0100000000001000 #define FAT32_FILESIZE_LIMIT (u64)0xFFFFFFFF /* 4 GiB - 1 (4294967295 bytes). */ diff --git a/source/core/bfsar.c b/source/core/bfsar.c new file mode 100644 index 0000000..8823e97 --- /dev/null +++ b/source/core/bfsar.c @@ -0,0 +1,202 @@ +/* + * bfsar.c + * + * Copyright (c) 2020-2021, DarkMatterCore . + * + * This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool). + * + * nxdumptool is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * nxdumptool is distributed in the hope that 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 "nxdt_utils.h" +#include "bfsar.h" +#include "romfs.h" +#include "title.h" + +#define BFSAR_FILENAME "qlaunch.bfsar" +#define BFSAR_ROMFS_PATH "/sound/" BFSAR_FILENAME + +/* Global variables. */ + +static Mutex g_bfsarMutex = 0; +static bool g_bfsarInterfaceInit = false; + +static char g_bfsarPath[FS_MAX_PATH] = {0}; + +bool bfsarInitialize(void) +{ + bool use_root = true; + const char *launch_path = utilsGetLaunchPath(); + char *ptr1 = NULL, *ptr2 = NULL; + + TitleInfo *title_info = NULL; + + NcaContext *nca_ctx = NULL; + + RomFileSystemContext romfs_ctx = {0}; + RomFileSystemFileEntry *romfs_file_entry = NULL; + + FILE *bfsar_file = NULL; + u8 *bfsar_data = NULL; + size_t bfsar_size = 0, wr = 0; + + bool ret = false; + + SCOPED_LOCK(&g_bfsarMutex) + { + ret = g_bfsarInterfaceInit; + if (ret) break; + + /* Generate BFSAR file path. */ + if (launch_path) + { + ptr1 = strchr(launch_path, '/'); + ptr2 = strrchr(launch_path, '/'); + + if (ptr1 && ptr2 && ptr1 != ptr2) + { + /* Create BFSAR file in the current working directory. */ + snprintf(g_bfsarPath, sizeof(g_bfsarPath), "%.*s" BFSAR_FILENAME, (int)((ptr2 - ptr1) + 1), ptr1); + use_root = false; + } + } + + /* Create BFSAR file in the SD card root directory. */ + if (use_root) sprintf(g_bfsarPath, "/" BFSAR_FILENAME); + + /* Check if the BFSAR file is already available and not empty. */ + bfsar_file = fopen(g_bfsarPath, "rb"); + if (bfsar_file) + { + fseek(bfsar_file, 0, SEEK_END); + bfsar_size = ftell(bfsar_file); + if (bfsar_size) + { + ret = g_bfsarInterfaceInit = true; + break; + } + } + + /* Get title info. */ + if (!(title_info = titleGetInfoFromStorageByTitleId(NcmStorageId_BuiltInSystem, QLAUNCH_TID))) + { + LOG_MSG("Failed to get title info for qlaunch!"); + break; + } + + /* Allocate memory for a temporary NCA context. */ + nca_ctx = calloc(1, sizeof(NcaContext)); + if (!nca_ctx) + { + LOG_MSG("Failed to allocate memory for temporary NCA context!"); + break; + } + + /* Initialize NCA context. */ + if (!ncaInitializeContext(nca_ctx, NcmStorageId_BuiltInSystem, 0, titleGetContentInfoByTypeAndIdOffset(title_info, NcmContentType_Data, 0), NULL)) + { + LOG_MSG("Failed to initialize qlaunch Data NCA context!"); + break; + } + + /* Initialize RomFS context. */ + if (!romfsInitializeContext(&romfs_ctx, &(nca_ctx->fs_ctx[0]))) + { + LOG_MSG("Failed to initialize RomFS context for qlaunch Data NCA!"); + break; + } + + /* Get RomFS file entry. */ + if (!(romfs_file_entry = romfsGetFileEntryByPath(&romfs_ctx, BFSAR_ROMFS_PATH))) + { + LOG_MSG("Failed to retrieve RomFS file entry for \"" BFSAR_ROMFS_PATH "\"!"); + break; + } + + /* Check file size. */ + bfsar_size = romfs_file_entry->size; + if (!bfsar_size) + { + LOG_MSG("File size for qlaunch's \"" BFSAR_ROMFS_PATH "\" is zero!"); + break; + } + + /* Allocate memory for BFSAR data. */ + if (!(bfsar_data = malloc(bfsar_size))) + { + LOG_MSG("Failed to allocate 0x%lX bytes for qlaunch's \"" BFSAR_ROMFS_PATH "\"!", bfsar_size); + break; + } + + /* Read BFSAR data. */ + if (!romfsReadFileEntryData(&romfs_ctx, romfs_file_entry, bfsar_data, bfsar_size, 0)) + { + LOG_MSG("Failed to read 0x%lX bytes long \"" BFSAR_ROMFS_PATH "\" from qlaunch!", bfsar_size); + break; + } + + /* Create BFSAR file. */ + bfsar_file = fopen(g_bfsarPath, "wb"); + if (!bfsar_file) + { + LOG_MSG("Failed to open \"%s\" for writing!", g_bfsarPath); + break; + } + + /* Write BFSAR data. */ + wr = fwrite(bfsar_data, 1, bfsar_size, bfsar_file); + if (wr != bfsar_size) + { + LOG_MSG("Failed to write 0x%lX bytes block to \"%s\"!", bfsar_size, g_bfsarPath); + break; + } + + /* Update flags. */ + ret = g_bfsarInterfaceInit = true; + } + + if (bfsar_file) fclose(bfsar_file); + + if (bfsar_data) free(bfsar_data); + + romfsFreeContext(&romfs_ctx); + + if (nca_ctx) free(nca_ctx); + + titleFreeTitleInfo(&title_info); + + return ret; +} + +void bfsarExit(void) +{ + SCOPED_LOCK(&g_bfsarMutex) + { + /* Clear BFSAR file path. */ + *g_bfsarPath = '\0'; + g_bfttfInterfaceInit = false; + } +} + +const char *bfsarGetFilePath(void) +{ + const char *ret = NULL; + + SCOPED_TRY_LOCK(&g_bfsarMutex) + { + if (g_bfttfInterfaceInit) ret = (const char*)g_bfsarPath; + } + + return ret; +} diff --git a/source/core/bfttf.c b/source/core/bfttf.c index 398d95b..7fc4f79 100644 --- a/source/core/bfttf.c +++ b/source/core/bfttf.c @@ -213,7 +213,7 @@ bool bfttfGetFontByType(BfttfFontData *font_data, u8 font_type) bool ret = false; - SCOPED_LOCK(&g_bfttfMutex) + SCOPED_TRY_LOCK(&g_bfttfMutex) { BfttfFontInfo *font_info = &(g_fontInfo[font_type]); if (font_info->size <= 8 || !font_info->data)