mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Hash FS start.
This commit is contained in:
parent
d3ad9d84b6
commit
9679eb72bb
8 changed files with 164 additions and 58 deletions
|
@ -52,6 +52,7 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 offset; ///< Relative to the start of the gamecard header.
|
u64 offset; ///< Relative to the start of the gamecard header.
|
||||||
u64 size; ///< Whole partition size.
|
u64 size; ///< Whole partition size.
|
||||||
|
u64 header_size; ///< Full header size.
|
||||||
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table.
|
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table.
|
||||||
} GameCardHashFileSystemPartitionInfo;
|
} GameCardHashFileSystemPartitionInfo;
|
||||||
|
|
||||||
|
@ -100,8 +101,12 @@ static void gamecardCloseStorageArea(void);
|
||||||
static bool gamecardGetStorageAreasSizes(void);
|
static bool gamecardGetStorageAreasSizes(void);
|
||||||
static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size);
|
static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size);
|
||||||
|
|
||||||
|
static inline GameCardHashFileSystemHeader *gamecardGetHashFileSystemPartitionHeaderByIndex(u32 idx);
|
||||||
|
static inline GameCardHashFileSystemEntry *gamecardGetHashFileSystemEntryByIndex(void *hfs_header, u32 idx);
|
||||||
|
static inline char *gamecardGetHashFileSystemEntryName(void *hfs_header, u32 name_offset);
|
||||||
|
|
||||||
/* Service guard used to generate thread-safe initialize + exit functions. */
|
/* Service guard used to generate thread-safe initialize + exit functions. */
|
||||||
/* I'm using this here even though this actually isn't a service but who cares, it gets the job done. */
|
/* I'm using this here even though this actually isn't a real service but who cares, it gets the job done. */
|
||||||
NX_GENERATE_SERVICE_GUARD(gamecard);
|
NX_GENERATE_SERVICE_GUARD(gamecard);
|
||||||
|
|
||||||
bool gamecardIsReady(void)
|
bool gamecardIsReady(void)
|
||||||
|
@ -217,15 +222,52 @@ bool gamecardGetBundledFirmwareUpdateVersion(u32 *out)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gamecardGetHashFileSystemEntryDataOffsetByName(u32 hfs_partition_idx, const char *name, u64 *out_offset)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
char *entry_name = NULL;
|
||||||
|
size_t name_len = 0;
|
||||||
|
GameCardHashFileSystemHeader *fs_header = NULL;
|
||||||
|
GameCardHashFileSystemEntry *fs_entry = NULL;
|
||||||
|
|
||||||
|
mtx_lock(&g_gameCardSharedDataMutex);
|
||||||
|
|
||||||
|
if (!g_gameCardInserted || !g_gameCardInfoLoaded || !name || !*name || !out_offset)
|
||||||
|
{
|
||||||
|
LOGFILE("Invalid parameters!");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
|
||||||
|
fs_header = gamecardGetHashFileSystemPartitionHeaderByIndex(hfs_partition_idx);
|
||||||
|
if (!fs_header)
|
||||||
|
{
|
||||||
|
LOGFILE("Invalid hash FS partition index! (0x%X)", hfs_partition_idx);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u32 i = 0; i < fs_header->entry_count; i++)
|
||||||
|
{
|
||||||
|
fs_entry = gamecardGetHashFileSystemEntryByIndex(fs_header, i);
|
||||||
|
if (!fs_entry) continue;
|
||||||
|
|
||||||
|
entry_name = gamecardGetHashFileSystemEntryName(fs_header, fs_entry->name_offset);
|
||||||
|
if (!entry_name) continue;
|
||||||
|
|
||||||
|
if (!strncasecmp(entry_name, name, name_len))
|
||||||
|
{
|
||||||
|
*out_offset = (g_gameCardHfsPartitions[hfs_partition_idx].offset + g_gameCardHfsPartitions[hfs_partition_idx].header_size + fs_entry->offset);
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
mtx_unlock(&g_gameCardSharedDataMutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -521,11 +563,10 @@ static void gamecardLoadInfo(void)
|
||||||
/* Read hash FS partitions */
|
/* Read hash FS partitions */
|
||||||
for(u32 i = 0; i < fs_header->entry_count; i++)
|
for(u32 i = 0; i < fs_header->entry_count; i++)
|
||||||
{
|
{
|
||||||
fs_entry = (GameCardHashFileSystemEntry*)(g_gameCardHfsRootHeader + sizeof(GameCardHashFileSystemHeader) + (i * sizeof(GameCardHashFileSystemEntry)));
|
fs_entry = gamecardGetHashFileSystemEntryByIndex(g_gameCardHfsRootHeader, i);
|
||||||
|
if (!fs_entry || !fs_entry->size)
|
||||||
if (!fs_entry->size)
|
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid size for hash FS partition #%u!", i);
|
LOGFILE("Invalid hash FS partition entry!");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,11 +593,12 @@ static void gamecardLoadInfo(void)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the full header size for the current hash FS partition */
|
/* Calculate the full header size for the current hash FS partition and round it to a GAMECARD_MEDIA_UNIT_SIZE bytes boundary */
|
||||||
u64 partition_header_size = (sizeof(GameCardHashFileSystemHeader) + (partition_header.entry_count * sizeof(GameCardHashFileSystemEntry)) + partition_header.name_table_size);
|
g_gameCardHfsPartitions[i].header_size = (sizeof(GameCardHashFileSystemHeader) + (partition_header.entry_count * sizeof(GameCardHashFileSystemEntry)) + partition_header.name_table_size);
|
||||||
|
g_gameCardHfsPartitions[i].header_size = ROUND_UP(g_gameCardHfsPartitions[i].header_size, GAMECARD_MEDIA_UNIT_SIZE);
|
||||||
|
|
||||||
/* Allocate memory for the hash FS partition header */
|
/* Allocate memory for the hash FS partition header */
|
||||||
g_gameCardHfsPartitions[i].header = calloc(partition_header_size, sizeof(u8));
|
g_gameCardHfsPartitions[i].header = calloc(g_gameCardHfsPartitions[i].header_size, sizeof(u8));
|
||||||
if (!g_gameCardHfsPartitions[i].header)
|
if (!g_gameCardHfsPartitions[i].header)
|
||||||
{
|
{
|
||||||
LOGFILE("Unable to allocate memory for the hash FS partition #%u header!", i);
|
LOGFILE("Unable to allocate memory for the hash FS partition #%u header!", i);
|
||||||
|
@ -564,7 +606,7 @@ static void gamecardLoadInfo(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, read the full hash FS partition header */
|
/* Finally, read the full hash FS partition header */
|
||||||
if (!gamecardReadStorageArea(g_gameCardHfsPartitions[i].header, partition_header_size, g_gameCardHfsPartitions[i].offset, false))
|
if (!gamecardReadStorageArea(g_gameCardHfsPartitions[i].header, g_gameCardHfsPartitions[i].header_size, g_gameCardHfsPartitions[i].offset, false))
|
||||||
{
|
{
|
||||||
LOGFILE("Failed to read full hash FS partition #%u header from offset 0x%lX!", i, g_gameCardHfsPartitions[i].offset);
|
LOGFILE("Failed to read full hash FS partition #%u header from offset 0x%lX!", i, g_gameCardHfsPartitions[i].offset);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -862,3 +904,25 @@ static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size)
|
||||||
|
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline GameCardHashFileSystemHeader *gamecardGetHashFileSystemPartitionHeaderByIndex(u32 idx)
|
||||||
|
{
|
||||||
|
if (idx >= ((GameCardHashFileSystemHeader*)g_gameCardHfsRootHeader)->entry_count) return NULL;
|
||||||
|
return (GameCardHashFileSystemHeader*)g_gameCardHfsPartitions[idx].header;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GameCardHashFileSystemEntry *gamecardGetHashFileSystemEntryByIndex(void *hfs_header, u32 idx)
|
||||||
|
{
|
||||||
|
if (!hfs_header || idx >= ((GameCardHashFileSystemHeader*)hfs_header)->entry_count) return NULL;
|
||||||
|
return (GameCardHashFileSystemEntry*)((u8*)hfs_header + sizeof(GameCardHashFileSystemHeader) + (idx * sizeof(GameCardHashFileSystemEntry)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *gamecardGetHashFileSystemEntryName(void *hfs_header, u32 name_offset)
|
||||||
|
{
|
||||||
|
if (!hfs_header) return NULL;
|
||||||
|
|
||||||
|
GameCardHashFileSystemHeader *header = (GameCardHashFileSystemHeader*)hfs_header;
|
||||||
|
if (!header->entry_count || name_offset >= header->name_table_size) return NULL;
|
||||||
|
|
||||||
|
return ((char*)hfs_header + sizeof(GameCardHashFileSystemHeader) + (header->entry_count * sizeof(GameCardHashFileSystemEntry)) + name_offset);
|
||||||
|
}
|
||||||
|
|
|
@ -155,4 +155,6 @@ bool gamecardGetRomCapacity(u64 *out); ///< Not the same as gamecardGetTotalSize
|
||||||
bool gamecardGetCertificate(FsGameCardCertificate *out);
|
bool gamecardGetCertificate(FsGameCardCertificate *out);
|
||||||
bool gamecardGetBundledFirmwareUpdateVersion(u32 *out);
|
bool gamecardGetBundledFirmwareUpdateVersion(u32 *out);
|
||||||
|
|
||||||
|
bool gamecardGetHashFileSystemEntryDataOffsetByName(u32 hfs_partition_idx, const char *name, u64 *out_offset);
|
||||||
|
|
||||||
#endif /* __GAMECARD_H__ */
|
#endif /* __GAMECARD_H__ */
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#define SEGMENT_RODATA BIT(1)
|
#define SEGMENT_RODATA BIT(1)
|
||||||
#define SEGMENT_DATA BIT(2)
|
#define SEGMENT_DATA BIT(2)
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 program_id;
|
u64 program_id;
|
||||||
u8 mask;
|
u8 mask;
|
||||||
|
@ -69,6 +71,8 @@ typedef struct {
|
||||||
u8 key_area_keys[0x20][3][0x10]; ///< Key area encryption keys.
|
u8 key_area_keys[0x20][3][0x10]; ///< Key area encryption keys.
|
||||||
} keysNcaKeyset;
|
} keysNcaKeyset;
|
||||||
|
|
||||||
|
/* Global variables. */
|
||||||
|
|
||||||
static keysNcaKeyset g_ncaKeyset = {0};
|
static keysNcaKeyset g_ncaKeyset = {0};
|
||||||
|
|
||||||
static keysMemoryInfo g_fsRodataMemoryInfo = {
|
static keysMemoryInfo g_fsRodataMemoryInfo = {
|
||||||
|
@ -130,6 +134,8 @@ static keysMemoryInfo g_fsDataMemoryInfo = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Function prototypes. */
|
||||||
|
|
||||||
static bool keysRetrieveDebugHandleFromProcessByProgramId(Handle *out, u64 program_id);
|
static bool keysRetrieveDebugHandleFromProcessByProgramId(Handle *out, u64 program_id);
|
||||||
static bool keysRetrieveProcessMemory(keysMemoryLocation *location);
|
static bool keysRetrieveProcessMemory(keysMemoryLocation *location);
|
||||||
static void keysFreeProcessMemory(keysMemoryLocation *location);
|
static void keysFreeProcessMemory(keysMemoryLocation *location);
|
||||||
|
|
|
@ -65,6 +65,7 @@ int main(int argc, char *argv[])
|
||||||
FsGameCardCertificate cert = {0};
|
FsGameCardCertificate cert = {0};
|
||||||
u64 total_size = 0, trimmed_size = 0;
|
u64 total_size = 0, trimmed_size = 0;
|
||||||
u32 update_version = 0;
|
u32 update_version = 0;
|
||||||
|
u64 nca_offset = 0;
|
||||||
|
|
||||||
if (gamecardGetHeader(&header))
|
if (gamecardGetHeader(&header))
|
||||||
{
|
{
|
||||||
|
@ -167,6 +168,15 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consoleUpdate(NULL);
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
|
if (gamecardGetHashFileSystemEntryDataOffsetByName(2, "7e86768383cfabb30f1b58d2373fed07.nca", &nca_offset)) // Should match 0x1657F5E00
|
||||||
|
{
|
||||||
|
printf("nca_offset: 0x%lX\n", nca_offset);
|
||||||
|
} else {
|
||||||
|
printf("nca_offset failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
SLEEP(3);
|
SLEEP(3);
|
||||||
consoleExit(NULL);
|
consoleExit(NULL);
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 storage_id; ///< NcmStorageId.
|
u8 storage_id; ///< NcmStorageId.
|
||||||
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data.
|
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data.
|
||||||
u64 gc_secure_area_base_offset; ///< Used to read NCA data from a gamecard using a FsStorage instance when storage_id == NcmStorageId_GameCard.
|
u64 gamecard_offset; ///< Used to read NCA data from a gamecard using a FsStorage instance when storage_id == NcmStorageId_GameCard.
|
||||||
NcmContentId id; ///< Also used to read NCA data.
|
NcmContentId id; ///< Also used to read NCA data.
|
||||||
char id_str[0x21];
|
char id_str[0x21];
|
||||||
u8 hash[0x20];
|
u8 hash[0x20];
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool servicesInitialize(void)
|
||||||
rc = g_serviceInfo[i].init_func();
|
rc = g_serviceInfo[i].init_func();
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
utilsConsoleErrorScreen("%s: failed to initialize %s service! (0x%08X)", __func__, g_serviceInfo[i].name, rc);
|
LOGFILE("Failed to initialize %s service! (0x%08X)", g_serviceInfo[i].name, rc);
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,23 @@
|
||||||
|
|
||||||
//#include "freetype_helper.h"
|
//#include "freetype_helper.h"
|
||||||
//#include "lvgl_helper.h"
|
//#include "lvgl_helper.h"
|
||||||
#include "services.h"
|
#include "keys.h"
|
||||||
#include "gamecard.h"
|
#include "gamecard.h"
|
||||||
|
#include "services.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
|
static u8 g_customFirmwareType = UtilsCustomFirmwareType_Unknown;
|
||||||
|
|
||||||
static AppletHookCookie g_systemOverclockCookie = {0};
|
static AppletHookCookie g_systemOverclockCookie = {0};
|
||||||
|
|
||||||
static Mutex g_logfileMutex = 0;
|
static Mutex g_logfileMutex = 0;
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
|
static void _utilsGetCustomFirmwareType(void);
|
||||||
|
|
||||||
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param);
|
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param);
|
||||||
|
|
||||||
u64 utilsHidKeysAllDown(void)
|
u64 utilsHidKeysAllDown(void)
|
||||||
|
@ -71,22 +76,6 @@ void utilsWaitForButtonPress(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void utilsConsoleErrorScreen(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
consoleInit(NULL);
|
|
||||||
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
vprintf(fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
printf("\nPress any button to exit.\n");
|
|
||||||
|
|
||||||
consoleUpdate(NULL);
|
|
||||||
utilsWaitForButtonPress();
|
|
||||||
consoleExit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...)
|
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
mutexLock(&g_logfileMutex);
|
mutexLock(&g_logfileMutex);
|
||||||
|
@ -122,8 +111,19 @@ void utilsOverclockSystem(bool restore)
|
||||||
|
|
||||||
bool utilsInitializeResources(void)
|
bool utilsInitializeResources(void)
|
||||||
{
|
{
|
||||||
/* Initialize all needed services */
|
/* Initialize needed services */
|
||||||
if (!servicesInitialize()) return false;
|
if (!servicesInitialize())
|
||||||
|
{
|
||||||
|
LOGFILE("Failed to initialize needed services!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load NCA keyset */
|
||||||
|
if (!keysLoadNcaKeyset())
|
||||||
|
{
|
||||||
|
LOGFILE("Failed to load NCA keyset!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize FreeType */
|
/* Initialize FreeType */
|
||||||
//if (!freeTypeHelperInitialize()) return false;
|
//if (!freeTypeHelperInitialize()) return false;
|
||||||
|
@ -131,17 +131,20 @@ bool utilsInitializeResources(void)
|
||||||
/* Initialize LVGL */
|
/* Initialize LVGL */
|
||||||
//if (!lvglHelperInitialize()) return false;
|
//if (!lvglHelperInitialize()) return false;
|
||||||
|
|
||||||
|
/* Retrieve custom firmware type */
|
||||||
|
_utilsGetCustomFirmwareType();
|
||||||
|
|
||||||
/* Overclock system */
|
/* Overclock system */
|
||||||
utilsOverclockSystem(false);
|
utilsOverclockSystem(false);
|
||||||
|
|
||||||
/* Setup an applet hook to change the hardware clocks after a system mode change (docked <-> undocked) */
|
/* Setup an applet hook to change the hardware clocks after a system mode change (docked <-> undocked) */
|
||||||
appletHook(&g_systemOverclockCookie, utilsOverclockSystemAppletHook, NULL);
|
appletHook(&g_systemOverclockCookie, utilsOverclockSystemAppletHook, NULL);
|
||||||
|
|
||||||
/* Initialize gamecard */
|
/* Initialize gamecard interface */
|
||||||
Result rc = gamecardInitialize();
|
Result rc = gamecardInitialize();
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
utilsConsoleErrorScreen("gamecard fail\n");
|
LOGFILE("Failed to initialize gamecard interface!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +153,7 @@ bool utilsInitializeResources(void)
|
||||||
|
|
||||||
void utilsCloseResources(void)
|
void utilsCloseResources(void)
|
||||||
{
|
{
|
||||||
/* Deinitialize gamecard */
|
/* Deinitialize gamecard interface */
|
||||||
gamecardExit();
|
gamecardExit();
|
||||||
|
|
||||||
/* Unset our overclock applet hook */
|
/* Unset our overclock applet hook */
|
||||||
|
@ -169,6 +172,31 @@ void utilsCloseResources(void)
|
||||||
servicesClose();
|
servicesClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 utilsGetCustomFirmwareType(void)
|
||||||
|
{
|
||||||
|
return g_customFirmwareType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _utilsGetCustomFirmwareType(void)
|
||||||
|
{
|
||||||
|
bool tx_srv = servicesCheckRunningServiceByName("tx");
|
||||||
|
bool rnx_srv = servicesCheckRunningServiceByName("rnx");
|
||||||
|
|
||||||
|
if (!tx_srv && !rnx_srv)
|
||||||
|
{
|
||||||
|
/* Atmosphere */
|
||||||
|
g_customFirmwareType = UtilsCustomFirmwareType_Atmosphere;
|
||||||
|
} else
|
||||||
|
if (tx_srv && !rnx_srv)
|
||||||
|
{
|
||||||
|
/* SX OS */
|
||||||
|
g_customFirmwareType = UtilsCustomFirmwareType_SXOS;
|
||||||
|
} else {
|
||||||
|
/* ReiNX */
|
||||||
|
g_customFirmwareType = UtilsCustomFirmwareType_ReiNX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param)
|
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param)
|
||||||
{
|
{
|
||||||
(void)param;
|
(void)param;
|
||||||
|
|
|
@ -36,9 +36,10 @@
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UtilsCustomFirmwareType_Atmosphere = 0,
|
UtilsCustomFirmwareType_Unknown = 0,
|
||||||
UtilsCustomFirmwareType_SXOS = 1,
|
UtilsCustomFirmwareType_Atmosphere = 1,
|
||||||
UtilsCustomFirmwareType_ReiNX = 2
|
UtilsCustomFirmwareType_SXOS = 2,
|
||||||
|
UtilsCustomFirmwareType_ReiNX = 3
|
||||||
} UtilsCustomFirmwareType;
|
} UtilsCustomFirmwareType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -56,8 +57,6 @@ u64 utilsHidKeysAllHeld(void);
|
||||||
|
|
||||||
void utilsWaitForButtonPress(void);
|
void utilsWaitForButtonPress(void);
|
||||||
|
|
||||||
void utilsConsoleErrorScreen(const char *fmt, ...);
|
|
||||||
|
|
||||||
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...);
|
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...);
|
||||||
|
|
||||||
void utilsOverclockSystem(bool restore);
|
void utilsOverclockSystem(bool restore);
|
||||||
|
@ -65,6 +64,8 @@ void utilsOverclockSystem(bool restore);
|
||||||
bool utilsInitializeResources(void);
|
bool utilsInitializeResources(void);
|
||||||
void utilsCloseResources(void);
|
void utilsCloseResources(void);
|
||||||
|
|
||||||
|
u8 utilsGetCustomFirmwareType(void); ///< UtilsCustomFirmwareType.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
|
static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
|
||||||
|
@ -72,11 +73,6 @@ static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 utilsGetCustomFirmwareType(void)
|
|
||||||
{
|
|
||||||
return UtilsCustomFirmwareType_Atmosphere;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __UTILS_H__ */
|
#endif /* __UTILS_H__ */
|
||||||
|
|
Loading…
Reference in a new issue