mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Many small changes (sorry, I need to push these).
* Use forward declarations for type definitions wherever suitable (e.g. NcaContext, BucketTreeContext). * Replace references to "DumpDestination" with "OutputStorage". * Replace references to "append key area" with "prepend key area". * Update LZ4 to v1.9.4. * Update Material Icons font to 2022-08-01. * RootView: change USB-related icons, reflect how many UMS devices are currently connected to the console, provide a way for child views to retrieve the populated UMS devices vector. * Tasks: implement GetUmsDevices(). * Update borealis. * Update libusbhsfs. * Begin implementation of a DumpOptionsFrame class to display configurable options before starting a new dump process. * bktr: rename bktrIsValidSubstorage() to bktrIsValidSubStorage(), use bktrIsValidSubStorage() in bktrInitializeCompressedStorageContext(), fixed a bug in bktrReadCompressedStorage() where Sparse substorages wouldn't be allowed. * GamecardTab: push a DumpOptionsFrame object onto the view stack if the XCI option is clicked.
This commit is contained in:
parent
3cbdb5dc65
commit
7bb708e394
32 changed files with 1085 additions and 343 deletions
|
@ -161,14 +161,17 @@ typedef enum {
|
||||||
BucketTreeSubStorageType_Count = 5 ///< Total values supported by this enum.
|
BucketTreeSubStorageType_Count = 5 ///< Total values supported by this enum.
|
||||||
} BucketTreeSubStorageType;
|
} BucketTreeSubStorageType;
|
||||||
|
|
||||||
|
// Forward declaration for BucketTreeSubStorage.
|
||||||
|
typedef struct _BucketTreeContext BucketTreeContext;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 index; ///< Substorage index.
|
u8 index; ///< Substorage index.
|
||||||
NcaFsSectionContext *nca_fs_ctx; ///< NCA FS section context. Used to perform operations on the target NCA.
|
NcaFsSectionContext *nca_fs_ctx; ///< NCA FS section context. Used to perform operations on the target NCA.
|
||||||
u8 type; ///< BucketTreeSubStorageType.
|
u8 type; ///< BucketTreeSubStorageType.
|
||||||
void *bktr_ctx; ///< BucketTreeContext related to this storage. Only used if type > BucketTreeSubStorageType_Regular.
|
BucketTreeContext *bktr_ctx; ///< BucketTreeContext related to this storage. Only used if type > BucketTreeSubStorageType_Regular.
|
||||||
} BucketTreeSubStorage;
|
} BucketTreeSubStorage;
|
||||||
|
|
||||||
typedef struct {
|
struct _BucketTreeContext {
|
||||||
NcaFsSectionContext *nca_fs_ctx; ///< NCA FS section context. Used to perform operations on the target NCA.
|
NcaFsSectionContext *nca_fs_ctx; ///< NCA FS section context. Used to perform operations on the target NCA.
|
||||||
u8 storage_type; ///< BucketTreeStorageType.
|
u8 storage_type; ///< BucketTreeStorageType.
|
||||||
BucketTreeTable *storage_table; ///< Pointer to the dynamically allocated Bucket Tree Table for this storage.
|
BucketTreeTable *storage_table; ///< Pointer to the dynamically allocated Bucket Tree Table for this storage.
|
||||||
|
@ -181,7 +184,7 @@ typedef struct {
|
||||||
u64 start_offset; ///< Virtual storage start offset.
|
u64 start_offset; ///< Virtual storage start offset.
|
||||||
u64 end_offset; ///< Virtual storage end offset.
|
u64 end_offset; ///< Virtual storage end offset.
|
||||||
BucketTreeSubStorage substorages[BKTR_MAX_SUBSTORAGE_COUNT]; ///< Substorages required for this BucketTree storage. May be set after initializing this context.
|
BucketTreeSubStorage substorages[BKTR_MAX_SUBSTORAGE_COUNT]; ///< Substorages required for this BucketTree storage. May be set after initializing this context.
|
||||||
} BucketTreeContext;
|
};
|
||||||
|
|
||||||
/// Initializes a Bucket Tree context using the provided NCA FS section context and a storage type.
|
/// Initializes a Bucket Tree context using the provided NCA FS section context and a storage type.
|
||||||
/// 'storage_type' may only be BucketTreeStorageType_Indirect, BucketTreeStorageType_AesCtrEx or BucketTreeStorageType_Sparse.
|
/// 'storage_type' may only be BucketTreeStorageType_Indirect, BucketTreeStorageType_AesCtrEx or BucketTreeStorageType_Sparse.
|
||||||
|
@ -231,11 +234,11 @@ NX_INLINE bool bktrIsBlockWithinStorageRange(BucketTreeContext *ctx, u64 size, u
|
||||||
return (bktrIsValidContext(ctx) && size > 0 && ctx->start_offset <= offset && size <= (ctx->end_offset - offset));
|
return (bktrIsValidContext(ctx) && size > 0 && ctx->start_offset <= offset && size <= (ctx->end_offset - offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
NX_INLINE bool bktrIsValidSubstorage(BucketTreeSubStorage *substorage)
|
NX_INLINE bool bktrIsValidSubStorage(BucketTreeSubStorage *substorage)
|
||||||
{
|
{
|
||||||
return (substorage && substorage->index < BKTR_MAX_SUBSTORAGE_COUNT && substorage->nca_fs_ctx && substorage->type < BucketTreeSubStorageType_Count && \
|
return (substorage && substorage->index < BKTR_MAX_SUBSTORAGE_COUNT && substorage->nca_fs_ctx && substorage->type < BucketTreeSubStorageType_Count && \
|
||||||
((substorage->type == BucketTreeSubStorageType_Regular && substorage->index == 0 && !substorage->bktr_ctx) || \
|
((substorage->type == BucketTreeSubStorageType_Regular && substorage->index == 0 && !substorage->bktr_ctx) || \
|
||||||
(substorage->type > BucketTreeSubStorageType_Regular && substorage->bktr_ctx)));
|
(substorage->type > BucketTreeSubStorageType_Regular && substorage->bktr_ctx && substorage->bktr_ctx->nca_fs_ctx == substorage->nca_fs_ctx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -31,10 +31,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ConfigDumpDestination_SdCard = 0,
|
ConfigOutputStorage_SdCard = 0,
|
||||||
ConfigDumpDestination_UsbHost = 1,
|
ConfigOutputStorage_UsbHost = 1,
|
||||||
ConfigDumpDestination_Count = 2
|
ConfigOutputStorage_Count = 2
|
||||||
} ConfigDumpDestination;
|
} ConfigOutputStorage;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ConfigChecksumLookupMethod_None = 0,
|
ConfigChecksumLookupMethod_None = 0,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* LZ4 - Fast LZ compression algorithm
|
* LZ4 - Fast LZ compression algorithm
|
||||||
* Header File
|
* Header File
|
||||||
* Copyright (C) 2011-present, Yann Collet.
|
* Copyright (C) 2011-2020, Yann Collet.
|
||||||
|
|
||||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
@ -97,36 +97,77 @@ extern "C" {
|
||||||
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_FREESTANDING :
|
||||||
|
* When this macro is set to 1, it enables "freestanding mode" that is
|
||||||
|
* suitable for typical freestanding environment which doesn't support
|
||||||
|
* standard C library.
|
||||||
|
*
|
||||||
|
* - LZ4_FREESTANDING is a compile-time switch.
|
||||||
|
* - It requires the following macros to be defined:
|
||||||
|
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
|
||||||
|
* - It only enables LZ4/HC functions which don't use heap.
|
||||||
|
* All LZ4F_* functions are not supported.
|
||||||
|
* - See tests/freestanding.c to check its basic setup.
|
||||||
|
*/
|
||||||
|
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
|
||||||
|
# define LZ4_HEAPMODE 0
|
||||||
|
# define LZ4HC_HEAPMODE 0
|
||||||
|
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
|
||||||
|
# if !defined(LZ4_memcpy)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
|
||||||
|
# endif
|
||||||
|
# if !defined(LZ4_memset)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
|
||||||
|
# endif
|
||||||
|
# if !defined(LZ4_memmove)
|
||||||
|
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
|
||||||
|
# endif
|
||||||
|
#elif ! defined(LZ4_FREESTANDING)
|
||||||
|
# define LZ4_FREESTANDING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*------ Version ------*/
|
/*------ Version ------*/
|
||||||
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||||
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
||||||
#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
|
#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */
|
||||||
|
|
||||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||||
|
|
||||||
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||||
#define LZ4_QUOTE(str) #str
|
#define LZ4_QUOTE(str) #str
|
||||||
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||||
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
|
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
|
||||||
|
|
||||||
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
|
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
|
||||||
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */
|
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Tuning parameter
|
* Tuning parameter
|
||||||
**************************************/
|
**************************************/
|
||||||
|
#define LZ4_MEMORY_USAGE_MIN 10
|
||||||
|
#define LZ4_MEMORY_USAGE_DEFAULT 14
|
||||||
|
#define LZ4_MEMORY_USAGE_MAX 20
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* LZ4_MEMORY_USAGE :
|
* LZ4_MEMORY_USAGE :
|
||||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
|
||||||
* Increasing memory usage improves compression ratio.
|
* Increasing memory usage improves compression ratio, at the cost of speed.
|
||||||
* Reduced memory usage may improve speed, thanks to better cache locality.
|
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
|
||||||
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||||
*/
|
*/
|
||||||
#ifndef LZ4_MEMORY_USAGE
|
#ifndef LZ4_MEMORY_USAGE
|
||||||
# define LZ4_MEMORY_USAGE 14
|
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too small !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too large !"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Simple Functions
|
* Simple Functions
|
||||||
|
@ -270,8 +311,25 @@ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcS
|
||||||
***********************************************/
|
***********************************************/
|
||||||
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Note about RC_INVOKED
|
||||||
|
|
||||||
|
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
|
||||||
|
|
||||||
|
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
|
||||||
|
and reports warning "RC4011: identifier truncated".
|
||||||
|
|
||||||
|
- To eliminate the warning, we surround long preprocessor symbol with
|
||||||
|
"#if !defined(RC_INVOKED) ... #endif" block that means
|
||||||
|
"skip this block when rc.exe is trying to read it".
|
||||||
|
*/
|
||||||
|
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
||||||
|
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
||||||
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||||
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||||
|
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! LZ4_resetStream_fast() : v1.9.0+
|
/*! LZ4_resetStream_fast() : v1.9.0+
|
||||||
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
||||||
|
@ -355,8 +413,12 @@ typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
|
||||||
* creation / destruction of streaming decompression tracking context.
|
* creation / destruction of streaming decompression tracking context.
|
||||||
* A tracking context can be re-used multiple times.
|
* A tracking context can be re-used multiple times.
|
||||||
*/
|
*/
|
||||||
|
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
||||||
|
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
||||||
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||||
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||||
|
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! LZ4_setStreamDecode() :
|
/*! LZ4_setStreamDecode() :
|
||||||
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
||||||
|
@ -406,7 +468,10 @@ LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
|
||||||
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
||||||
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
|
||||||
|
const char* src, char* dst,
|
||||||
|
int srcSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
/*! LZ4_decompress_*_usingDict() :
|
/*! LZ4_decompress_*_usingDict() :
|
||||||
|
@ -417,7 +482,16 @@ LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecod
|
||||||
* Performance tip : Decompression speed can be substantially increased
|
* Performance tip : Decompression speed can be substantially increased
|
||||||
* when dst == dictStart + dictSize.
|
* when dst == dictStart + dictSize.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_usingDict(const char* src, char* dst,
|
||||||
|
int srcSize, int dstCapacity,
|
||||||
|
const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
LZ4LIB_API int
|
||||||
|
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
|
||||||
|
int compressedSize,
|
||||||
|
int targetOutputSize, int maxOutputSize,
|
||||||
|
const char* dictStart, int dictSize);
|
||||||
|
|
||||||
#endif /* LZ4_H_2983827168210 */
|
#endif /* LZ4_H_2983827168210 */
|
||||||
|
|
||||||
|
@ -496,13 +570,15 @@ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const c
|
||||||
* stream (and source buffer) must remain in-place / accessible / unchanged
|
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||||
* through the completion of the first compression call on the stream.
|
* through the completion of the first compression call on the stream.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
|
LZ4LIB_STATIC_API void
|
||||||
|
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
|
||||||
|
const LZ4_stream_t* dictionaryStream);
|
||||||
|
|
||||||
|
|
||||||
/*! In-place compression and decompression
|
/*! In-place compression and decompression
|
||||||
*
|
*
|
||||||
* It's possible to have input and output sharing the same buffer,
|
* It's possible to have input and output sharing the same buffer,
|
||||||
* for highly contrained memory environments.
|
* for highly constrained memory environments.
|
||||||
* In both cases, it requires input to lay at the end of the buffer,
|
* In both cases, it requires input to lay at the end of the buffer,
|
||||||
* and decompression to start at beginning of the buffer.
|
* and decompression to start at beginning of the buffer.
|
||||||
* Buffer size must feature some margin, hence be larger than final size.
|
* Buffer size must feature some margin, hence be larger than final size.
|
||||||
|
@ -592,38 +668,26 @@ LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const
|
||||||
typedef unsigned int LZ4_u32;
|
typedef unsigned int LZ4_u32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_stream_t :
|
||||||
|
* Never ever use below internal definitions directly !
|
||||||
|
* These definitions are not API/ABI safe, and may change in future versions.
|
||||||
|
* If you need static allocation, declare or allocate an LZ4_stream_t object.
|
||||||
|
**/
|
||||||
|
|
||||||
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||||
struct LZ4_stream_t_internal {
|
struct LZ4_stream_t_internal {
|
||||||
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
|
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
|
||||||
LZ4_u32 currentOffset;
|
|
||||||
LZ4_u32 tableType;
|
|
||||||
const LZ4_byte* dictionary;
|
const LZ4_byte* dictionary;
|
||||||
const LZ4_stream_t_internal* dictCtx;
|
const LZ4_stream_t_internal* dictCtx;
|
||||||
|
LZ4_u32 currentOffset;
|
||||||
|
LZ4_u32 tableType;
|
||||||
LZ4_u32 dictSize;
|
LZ4_u32 dictSize;
|
||||||
|
/* Implicit padding to ensure structure is aligned */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
|
||||||
const LZ4_byte* externalDict;
|
|
||||||
size_t extDictSize;
|
|
||||||
const LZ4_byte* prefixEnd;
|
|
||||||
size_t prefixSize;
|
|
||||||
} LZ4_streamDecode_t_internal;
|
|
||||||
|
|
||||||
|
|
||||||
/*! LZ4_stream_t :
|
|
||||||
* Do not use below internal definitions directly !
|
|
||||||
* Declare or allocate an LZ4_stream_t instead.
|
|
||||||
* LZ4_stream_t can also be created using LZ4_createStream(), which is recommended.
|
|
||||||
* The structure definition can be convenient for static allocation
|
|
||||||
* (on stack, or as part of larger structure).
|
|
||||||
* Init this structure with LZ4_initStream() before first use.
|
|
||||||
* note : only use this definition in association with static linking !
|
|
||||||
* this definition is not API/ABI safe, and may change in future versions.
|
|
||||||
*/
|
|
||||||
#define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */
|
|
||||||
#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
|
|
||||||
union LZ4_stream_u {
|
union LZ4_stream_u {
|
||||||
void* table[LZ4_STREAMSIZE_VOIDP];
|
char minStateSize[LZ4_STREAM_MINSIZE];
|
||||||
LZ4_stream_t_internal internal_donotuse;
|
LZ4_stream_t_internal internal_donotuse;
|
||||||
}; /* previously typedef'd to LZ4_stream_t */
|
}; /* previously typedef'd to LZ4_stream_t */
|
||||||
|
|
||||||
|
@ -641,21 +705,25 @@ union LZ4_stream_u {
|
||||||
* In which case, the function will @return NULL.
|
* In which case, the function will @return NULL.
|
||||||
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
||||||
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
||||||
*/
|
**/
|
||||||
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
/*! LZ4_streamDecode_t :
|
/*! LZ4_streamDecode_t :
|
||||||
* information structure to track an LZ4 stream during decompression.
|
* Never ever use below internal definitions directly !
|
||||||
* init this structure using LZ4_setStreamDecode() before first use.
|
* These definitions are not API/ABI safe, and may change in future versions.
|
||||||
* note : only use in association with static linking !
|
* If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
|
||||||
* this definition is not API/ABI safe,
|
**/
|
||||||
* and may change in a future version !
|
typedef struct {
|
||||||
*/
|
const LZ4_byte* externalDict;
|
||||||
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ )
|
const LZ4_byte* prefixEnd;
|
||||||
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
size_t extDictSize;
|
||||||
|
size_t prefixSize;
|
||||||
|
} LZ4_streamDecode_t_internal;
|
||||||
|
|
||||||
|
#define LZ4_STREAMDECODE_MINSIZE 32
|
||||||
union LZ4_streamDecode_u {
|
union LZ4_streamDecode_u {
|
||||||
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
char minStateSize[LZ4_STREAMDECODE_MINSIZE];
|
||||||
LZ4_streamDecode_t_internal internal_donotuse;
|
LZ4_streamDecode_t_internal internal_donotuse;
|
||||||
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||||
|
|
||||||
|
|
|
@ -358,11 +358,14 @@ typedef enum {
|
||||||
NcaFsSectionType_Invalid = 4
|
NcaFsSectionType_Invalid = 4
|
||||||
} NcaFsSectionType;
|
} NcaFsSectionType;
|
||||||
|
|
||||||
|
// Forward declaration for NcaFsSectionContext.
|
||||||
|
typedef struct _NcaContext NcaContext;
|
||||||
|
|
||||||
/// Unlike NCA contexts, we don't need to keep a hash for the NCA FS section header in NCA FS section contexts.
|
/// Unlike NCA contexts, we don't need to keep a hash for the NCA FS section header in NCA FS section contexts.
|
||||||
/// This is because the functions that modify the NCA FS section header also update the NCA FS section header hash stored in the NCA header.
|
/// This is because the functions that modify the NCA FS section header also update the NCA FS section header hash stored in the NCA header.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool enabled; ///< Set to true if this NCA FS section has passed all validation checks and can be safely used.
|
bool enabled; ///< Set to true if this NCA FS section has passed all validation checks and can be safely used.
|
||||||
void *nca_ctx; ///< NcaContext. Used to perform NCA reads.
|
NcaContext *nca_ctx; ///< NcaContext. Used to perform NCA reads.
|
||||||
NcaFsHeader header; ///< Plaintext NCA FS section header.
|
NcaFsHeader header; ///< Plaintext NCA FS section header.
|
||||||
NcaFsHeader encrypted_header; ///< Encrypted NCA FS section header. If the plaintext NCA FS section header is modified, this will hold an encrypted copy of it.
|
NcaFsHeader encrypted_header; ///< Encrypted NCA FS section header. If the plaintext NCA FS section header is modified, this will hold an encrypted copy of it.
|
||||||
///< Otherwise, this holds the unmodified, encrypted NCA FS section header.
|
///< Otherwise, this holds the unmodified, encrypted NCA FS section header.
|
||||||
|
@ -418,7 +421,7 @@ typedef struct {
|
||||||
|
|
||||||
NXDT_ASSERT(NcaDecryptedKeyArea, NCA_KEY_AREA_USED_SIZE);
|
NXDT_ASSERT(NcaDecryptedKeyArea, NCA_KEY_AREA_USED_SIZE);
|
||||||
|
|
||||||
typedef struct {
|
struct _NcaContext {
|
||||||
u8 storage_id; ///< NcmStorageId.
|
u8 storage_id; ///< NcmStorageId.
|
||||||
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data from eMMC/SD.
|
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data from eMMC/SD.
|
||||||
u64 gamecard_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.
|
||||||
|
@ -448,7 +451,7 @@ typedef struct {
|
||||||
void *content_type_ctx; ///< Pointer to a content type context (e.g. ContentMetaContext, ProgramInfoContext, NacpContext, LegalInfoContext). Set to NULL if unused.
|
void *content_type_ctx; ///< Pointer to a content type context (e.g. ContentMetaContext, ProgramInfoContext, NacpContext, LegalInfoContext). Set to NULL if unused.
|
||||||
bool content_type_ctx_patch; ///< Set to true if a NCA patch generated by the content type context is needed and hasn't been completely written yet.
|
bool content_type_ctx_patch; ///< Set to true if a NCA patch generated by the content type context is needed and hasn't been completely written yet.
|
||||||
u32 content_type_ctx_data_idx; ///< Start index for the data generated by the content type context. Used while creating NSPs.
|
u32 content_type_ctx_data_idx; ///< Start index for the data generated by the content type context. Used while creating NSPs.
|
||||||
} NcaContext;
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool written; ///< Set to true if this patch has already been written.
|
bool written; ///< Set to true if this patch has already been written.
|
||||||
|
@ -478,7 +481,7 @@ void ncaFreeCryptoBuffer(void);
|
||||||
/// Initializes a NCA context.
|
/// Initializes a NCA context.
|
||||||
/// If 'storage_id' == NcmStorageId_GameCard, the 'hfs_partition_type' argument must be a valid GameCardHashFileSystemPartitionType value.
|
/// If 'storage_id' == NcmStorageId_GameCard, the 'hfs_partition_type' argument must be a valid GameCardHashFileSystemPartitionType value.
|
||||||
/// If the NCA holds a populated Rights ID field, ticket data will need to be retrieved.
|
/// If the NCA holds a populated Rights ID field, ticket data will need to be retrieved.
|
||||||
/// If the 'tik' argument points to a valid Ticket element, it will either be updated (if it's empty) or be used to read ticket data that has already been retrieved.
|
/// If the 'tik' argument points to a valid Ticket element, it will either be updated (if it's empty) or used to read ticket data that has already been retrieved.
|
||||||
/// If the 'tik' argument is NULL, the function will just retrieve the necessary ticket data on its own.
|
/// If the 'tik' argument is NULL, the function will just retrieve the necessary ticket data on its own.
|
||||||
/// If ticket data can't be retrieved, the context will still be initialized, but anything that involves working with encrypted NCA FS section blocks won't be possible (e.g. ncaReadFsSection()).
|
/// If ticket data can't be retrieved, the context will still be initialized, but anything that involves working with encrypted NCA FS section blocks won't be possible (e.g. ncaReadFsSection()).
|
||||||
bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, const NcmContentInfo *content_info, u32 title_version, Ticket *tik);
|
bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type, const NcmContentInfo *content_info, u32 title_version, Ticket *tik);
|
||||||
|
|
|
@ -157,7 +157,7 @@ NX_INLINE void pfsWriteEntryPatchToMemoryBuffer(PartitionFileSystemContext *ctx,
|
||||||
{
|
{
|
||||||
if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->nca_fs_ctx != ctx->storage_ctx.nca_fs_ctx || \
|
if (!ctx || !ncaStorageIsValidContext(&(ctx->storage_ctx)) || ctx->nca_fs_ctx != ctx->storage_ctx.nca_fs_ctx || \
|
||||||
ctx->storage_ctx.base_storage_type != NcaStorageBaseStorageType_Regular) return;
|
ctx->storage_ctx.base_storage_type != NcaStorageBaseStorageType_Regular) return;
|
||||||
ncaWriteHierarchicalSha256PatchToMemoryBuffer((NcaContext*)ctx->nca_fs_ctx->nca_ctx, patch, buf, buf_size, buf_offset);
|
ncaWriteHierarchicalSha256PatchToMemoryBuffer(ctx->nca_fs_ctx->nca_ctx, patch, buf, buf_size, buf_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
NX_INLINE void pfsFreeEntryPatch(NcaHierarchicalSha256Patch *patch)
|
NX_INLINE void pfsFreeEntryPatch(NcaHierarchicalSha256Patch *patch)
|
||||||
|
|
|
@ -281,7 +281,7 @@ NX_INLINE void romfsWriteFileEntryPatchToMemoryBuffer(RomFileSystemContext *ctx,
|
||||||
(!patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs) || \
|
(!patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs) || \
|
||||||
(patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)) return;
|
(patch->use_old_format_patch && ctx->default_storage_ctx->nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)) return;
|
||||||
|
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->default_storage_ctx->nca_fs_ctx->nca_ctx;
|
NcaContext *nca_ctx = ctx->default_storage_ctx->nca_fs_ctx->nca_ctx;
|
||||||
|
|
||||||
if (patch->use_old_format_patch)
|
if (patch->use_old_format_patch)
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,7 +121,8 @@
|
||||||
#define GITHUB_API_RELEASE_URL GITHUB_API_URL "/repos/" GITHUB_REPOSITORY "/releases/latest"
|
#define GITHUB_API_RELEASE_URL GITHUB_API_URL "/repos/" GITHUB_REPOSITORY "/releases/latest"
|
||||||
|
|
||||||
#define NSWDB_XML_URL "http://nswdb.com/xml.php"
|
#define NSWDB_XML_URL "http://nswdb.com/xml.php"
|
||||||
#define NSWDB_XML_PATH APP_BASE_PATH "NSWreleases.xml"
|
#define NSWDB_XML_NAME "NSWreleases.xml"
|
||||||
|
#define NSWDB_XML_PATH APP_BASE_PATH NSWDB_XML_NAME
|
||||||
|
|
||||||
#define BOREALIS_URL "https://github.com/natinusala/borealis"
|
#define BOREALIS_URL "https://github.com/natinusala/borealis"
|
||||||
#define LIBUSBHSFS_URL "https://github.com/DarkMatterCore/libusbhsfs"
|
#define LIBUSBHSFS_URL "https://github.com/DarkMatterCore/libusbhsfs"
|
||||||
|
|
340
include/dump_options_frame.hpp
Normal file
340
include/dump_options_frame.hpp
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
* dump_options_frame.hpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2022, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __DUMP_OPTIONS_FRAME_HPP__
|
||||||
|
#define __DUMP_OPTIONS_FRAME_HPP__
|
||||||
|
|
||||||
|
#include <borealis.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace brls::i18n::literals;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
class DumpOptionsFrame: public brls::ThumbnailFrame
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
RootView *root_view = nullptr;
|
||||||
|
nxdt::tasks::UmsEvent::Subscription ums_task_sub;
|
||||||
|
|
||||||
|
char *raw_filename = NULL;
|
||||||
|
const char *extension = NULL;
|
||||||
|
|
||||||
|
brls::List *list = nullptr;
|
||||||
|
brls::InputListItem *filename_input = nullptr;
|
||||||
|
brls::SelectListItem *output_storage = nullptr;
|
||||||
|
brls::ToggleListItem *prepend_key_area = nullptr;
|
||||||
|
brls::ToggleListItem *keep_certificate = nullptr;
|
||||||
|
brls::ToggleListItem *trim_dump = nullptr;
|
||||||
|
brls::ToggleListItem *calculate_checksum = nullptr;
|
||||||
|
brls::SelectListItem *checksum_lookup_method = nullptr;
|
||||||
|
|
||||||
|
std::string RegenerateFileName(void)
|
||||||
|
{
|
||||||
|
if (!this->raw_filename) return "dummy";
|
||||||
|
|
||||||
|
char *raw_filename_dup = strdup(this->raw_filename);
|
||||||
|
if (!raw_filename_dup) return "dummy";
|
||||||
|
|
||||||
|
u8 selected = static_cast<u8>(this->output_storage ? this->output_storage->getSelectedValue() : configGetInteger("output_storage"));
|
||||||
|
utilsReplaceIllegalCharacters(raw_filename_dup, selected == ConfigOutputStorage_SdCard);
|
||||||
|
|
||||||
|
std::string output = std::string(raw_filename_dup);
|
||||||
|
free(raw_filename_dup);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateRawFileName(void)
|
||||||
|
{
|
||||||
|
if (raw_filename) free(this->raw_filename);
|
||||||
|
this->raw_filename = strdup(this->filename_input->getValue().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateStorages(const nxdt::tasks::UmsDeviceVector* ums_devices)
|
||||||
|
{
|
||||||
|
if (!this->output_storage) return;
|
||||||
|
|
||||||
|
std::vector<std::string> *storages = this->output_storage->getValues();
|
||||||
|
storages->clear();
|
||||||
|
|
||||||
|
storages->push_back("dump_options/output_storage/value_00"_i18n);
|
||||||
|
storages->push_back("dump_options/output_storage/value_01"_i18n);
|
||||||
|
|
||||||
|
for(const UsbHsFsDevice& cur_ums_device : *ums_devices)
|
||||||
|
{
|
||||||
|
std::string device_str = (std::string(cur_ums_device.name) + ", ");
|
||||||
|
if (cur_ums_device.product_name[0]) device_str += (std::string(cur_ums_device.product_name) + ", ");
|
||||||
|
device_str += fmt::format("LUN {}, FS #{}, {}", cur_ums_device.lun, cur_ums_device.fs_idx, LIBUSBHSFS_FS_TYPE_STR(cur_ums_device.fs_type));
|
||||||
|
storages->push_back(brls::i18n::getStr("dump_options/output_storage/value_02"_i18n, device_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->output_storage->getSelectedValue() > ConfigOutputStorage_UsbHost)
|
||||||
|
{
|
||||||
|
/* Set the SD card as the current output storage. */
|
||||||
|
this->output_storage->setSelectedValue(ConfigOutputStorage_SdCard);
|
||||||
|
|
||||||
|
/* Regenerate filename. */
|
||||||
|
this->output_storage->getValueSelectedEvent()->fire(ConfigOutputStorage_SdCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool onCancel(void) override
|
||||||
|
{
|
||||||
|
/* Pop view. */
|
||||||
|
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
DumpOptionsFrame(RootView *root_view, std::string title, brls::Image *icon, char *raw_filename, const char *extension) : brls::ThumbnailFrame(), root_view(root_view), raw_filename(raw_filename), extension(extension)
|
||||||
|
{
|
||||||
|
/* Set UI properties. */
|
||||||
|
this->setTitle(title);
|
||||||
|
this->setIcon(icon);
|
||||||
|
|
||||||
|
this->list = new brls::List();
|
||||||
|
this->list->setSpacing(this->list->getSpacing() / 2);
|
||||||
|
this->list->setMarginBottom(20);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->filename_input = new brls::InputListItem("dump_options/filename/label"_i18n, this->RegenerateFileName(), "", "dump_options/filename/description"_i18n, 255);
|
||||||
|
|
||||||
|
this->filename_input->getClickEvent()->subscribe([this](brls::View *view) {
|
||||||
|
this->UpdateRawFileName();
|
||||||
|
this->filename_input->setValue(this->RegenerateFileName());
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->filename_input);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->output_storage = new brls::SelectListItem("dump_options/output_storage/label"_i18n, {
|
||||||
|
"dump_options/output_storage/value_00"_i18n,
|
||||||
|
"dump_options/output_storage/value_01"_i18n
|
||||||
|
}, configGetInteger("output_storage"),
|
||||||
|
brls::i18n::getStr("dump_options/output_storage/description"_i18n, GITHUB_REPOSITORY_URL));
|
||||||
|
|
||||||
|
/* Subscribe to SelectListItem's value selected event. */
|
||||||
|
this->output_storage->getValueSelectedEvent()->subscribe([this](int selected) {
|
||||||
|
/* Make sure the current value isn't out of bounds. */
|
||||||
|
if (selected < ConfigOutputStorage_SdCard || selected >= static_cast<int>(this->root_view->GetUmsDevices()->size() + ConfigOutputStorage_Count)) return;
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
if (selected == ConfigOutputStorage_SdCard || selected == ConfigOutputStorage_UsbHost) configSetInteger("output_storage", selected);
|
||||||
|
|
||||||
|
/* Update output filename. */
|
||||||
|
this->filename_input->setValue(this->RegenerateFileName());
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Update output storages vector. */
|
||||||
|
this->UpdateStorages(this->root_view->GetUmsDevices());
|
||||||
|
|
||||||
|
this->list->addView(this->output_storage);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Subscribe to the UMS device event. */
|
||||||
|
this->ums_task_sub = this->root_view->RegisterUmsTaskListener([this](const nxdt::tasks::UmsDeviceVector* ums_devices) {
|
||||||
|
/* Update output storages vector. */
|
||||||
|
this->UpdateStorages(ums_devices);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->prepend_key_area = new brls::ToggleListItem("dump_options/prepend_key_area/label"_i18n, configGetBoolean("gamecard/prepend_key_area"), \
|
||||||
|
"dump_options/prepend_key_area/description"_i18n, "generic/value_enabled"_i18n, \
|
||||||
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->prepend_key_area->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/prepend_key_area", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Prepend Key Area setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->prepend_key_area);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->keep_certificate = new brls::ToggleListItem("dump_options/keep_certificate/label"_i18n, configGetBoolean("gamecard/keep_certificate"), \
|
||||||
|
"dump_options/keep_certificate/description"_i18n, "generic/value_enabled"_i18n, \
|
||||||
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->keep_certificate->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/keep_certificate", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Keep certificate setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->keep_certificate);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->trim_dump = new brls::ToggleListItem("dump_options/trim_dump/label"_i18n, configGetBoolean("gamecard/trim_dump"), \
|
||||||
|
"dump_options/trim_dump/description"_i18n, "generic/value_enabled"_i18n, \
|
||||||
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->trim_dump->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/trim_dump", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Trim dump setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->trim_dump);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->calculate_checksum = new brls::ToggleListItem("dump_options/calculate_checksum/label"_i18n, configGetBoolean("gamecard/calculate_checksum"), \
|
||||||
|
"dump_options/calculate_checksum/description"_i18n, "generic/value_enabled"_i18n, \
|
||||||
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->calculate_checksum->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/calculate_checksum", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Calculate checksum setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->calculate_checksum);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->checksum_lookup_method = new brls::SelectListItem("dump_options/checksum_lookup_method/label"_i18n, {
|
||||||
|
"dump_options/checksum_lookup_method/value_00"_i18n,
|
||||||
|
"NSWDB",
|
||||||
|
"No-Intro"
|
||||||
|
}, configGetInteger("gamecard/checksum_lookup_method"),
|
||||||
|
brls::i18n::getStr("dump_options/checksum_lookup_method/description"_i18n,
|
||||||
|
"dump_options/calculate_checksum/label"_i18n, "NSWDB", NSWDB_XML_NAME, "No-Intro"));
|
||||||
|
|
||||||
|
/* Subscribe to SelectListItem's value selected event. */
|
||||||
|
this->checksum_lookup_method->getValueSelectedEvent()->subscribe([this](int selected) {
|
||||||
|
/* Make sure the current value isn't out of bounds. */
|
||||||
|
if (selected < ConfigChecksumLookupMethod_None || selected >= ConfigChecksumLookupMethod_Count) return;
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetInteger("gamecard/checksum_lookup_method", selected);
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->checksum_lookup_method);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
brls::Button *button = this->getSidebar()->getButton();
|
||||||
|
button->setLabel("dump_options/start_dump"_i18n);
|
||||||
|
button->getClickEvent()->subscribe([](brls::View *view) {
|
||||||
|
brls::Application::notify("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this->setContentView(this->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
~DumpOptionsFrame(void)
|
||||||
|
{
|
||||||
|
/* Unregister task listener. */
|
||||||
|
this->root_view->UnregisterUmsTaskListener(this->ums_task_sub);
|
||||||
|
|
||||||
|
if (this->raw_filename) free(this->raw_filename);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __DUMP_OPTIONS_FRAME_HPP__ */
|
|
@ -41,7 +41,8 @@ namespace nxdt::views
|
||||||
brls::Label *time_lbl = nullptr;
|
brls::Label *time_lbl = nullptr;
|
||||||
brls::Label *battery_icon = nullptr, *battery_percentage = nullptr;
|
brls::Label *battery_icon = nullptr, *battery_percentage = nullptr;
|
||||||
brls::Label *connection_icon = nullptr, *connection_status_lbl = nullptr;
|
brls::Label *connection_icon = nullptr, *connection_status_lbl = nullptr;
|
||||||
brls::Label *usb_icon = nullptr, *usb_host_speed_lbl = nullptr;
|
brls::Label *usb_icon = nullptr, *ums_counter_lbl = nullptr;
|
||||||
|
brls::Label *cable_icon = nullptr, *usb_host_speed_lbl = nullptr;
|
||||||
|
|
||||||
nxdt::tasks::StatusInfoTask *status_info_task = nullptr;
|
nxdt::tasks::StatusInfoTask *status_info_task = nullptr;
|
||||||
nxdt::tasks::GameCardTask *gc_status_task = nullptr;
|
nxdt::tasks::GameCardTask *gc_status_task = nullptr;
|
||||||
|
@ -50,6 +51,7 @@ namespace nxdt::views
|
||||||
nxdt::tasks::UsbHostTask *usb_host_task = nullptr;
|
nxdt::tasks::UsbHostTask *usb_host_task = nullptr;
|
||||||
|
|
||||||
nxdt::tasks::StatusInfoEvent::Subscription status_info_task_sub;
|
nxdt::tasks::StatusInfoEvent::Subscription status_info_task_sub;
|
||||||
|
nxdt::tasks::UmsEvent::Subscription ums_task_sub;
|
||||||
nxdt::tasks::UsbHostEvent::Subscription usb_host_task_sub;
|
nxdt::tasks::UsbHostEvent::Subscription usb_host_task_sub;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -75,6 +77,11 @@ namespace nxdt::views
|
||||||
return this->title_task->GetApplicationMetadata(is_system);
|
return this->title_task->GetApplicationMetadata(is_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE const nxdt::tasks::UmsDeviceVector* GetUmsDevices(void)
|
||||||
|
{
|
||||||
|
return this->ums_task->GetUmsDevices();
|
||||||
|
}
|
||||||
|
|
||||||
EVENT_SUBSCRIPTION(StatusInfoTask, StatusInfoEvent, status_info_task);
|
EVENT_SUBSCRIPTION(StatusInfoTask, StatusInfoEvent, status_info_task);
|
||||||
EVENT_SUBSCRIPTION(GameCardTask, GameCardStatusEvent, gc_status_task);
|
EVENT_SUBSCRIPTION(GameCardTask, GameCardStatusEvent, gc_status_task);
|
||||||
EVENT_SUBSCRIPTION(TitleTask, TitleEvent, title_task);
|
EVENT_SUBSCRIPTION(TitleTask, TitleEvent, title_task);
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace nxdt::tasks
|
||||||
TitleTask(void);
|
TitleTask(void);
|
||||||
~TitleTask(void);
|
~TitleTask(void);
|
||||||
|
|
||||||
/* Intentionally left here to let system titles views retrieve metadata. */
|
/* Intentionally left here to let views retrieve title metadata. */
|
||||||
const TitleApplicationMetadataVector* GetApplicationMetadata(bool is_system);
|
const TitleApplicationMetadataVector* GetApplicationMetadata(bool is_system);
|
||||||
|
|
||||||
EVENT_SUBSCRIPTION(TitleEvent, title_event);
|
EVENT_SUBSCRIPTION(TitleEvent, title_event);
|
||||||
|
@ -143,6 +143,9 @@ namespace nxdt::tasks
|
||||||
UmsTask(void);
|
UmsTask(void);
|
||||||
~UmsTask(void);
|
~UmsTask(void);
|
||||||
|
|
||||||
|
/* Intentionally left here to let views retrieve UMS device info. */
|
||||||
|
const UmsDeviceVector* GetUmsDevices(void);
|
||||||
|
|
||||||
EVENT_SUBSCRIPTION(UmsEvent, ums_event);
|
EVENT_SUBSCRIPTION(UmsEvent, ums_event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 642c599c33f8632c42b0931aaa7676293576a191
|
Subproject commit f9f4aa9637f84aa89025d68a8ec15e5ff34d1537
|
|
@ -1 +1 @@
|
||||||
Subproject commit 315c98ecd631656b0e5839ca5e6fc293908d06f8
|
Subproject commit c1f63a931df0c6d07f8f2c91ef6352657acbdb2d
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"overclock": true,
|
"overclock": true,
|
||||||
"naming_convention": 0,
|
"naming_convention": 0,
|
||||||
"dump_destination": 0,
|
"output_storage": 0,
|
||||||
"gamecard": {
|
"gamecard": {
|
||||||
"append_key_area": false,
|
"prepend_key_area": false,
|
||||||
"keep_certificate": false,
|
"keep_certificate": false,
|
||||||
"trim_dump": false,
|
"trim_dump": false,
|
||||||
"calculate_checksum": true,
|
"calculate_checksum": true,
|
||||||
|
|
42
romfs/i18n/en-US/dump_options.json
Normal file
42
romfs/i18n/en-US/dump_options.json
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"filename": {
|
||||||
|
"label": "Filename",
|
||||||
|
"description": "Filename used for the output dump.\nIllegal filesystem characters will be automatically replaced with underscores (\"_\"). If the inserted SD card is used as the output storage, only ASCII characters will be kept — this is a limitation on Nintendo's FS driver.\nThe file extension cannot be modified, and it is excluded on purpose."
|
||||||
|
},
|
||||||
|
|
||||||
|
"output_storage": {
|
||||||
|
"label": "Output storage",
|
||||||
|
"description": "Storage where the dumped data will be written to. Changing it will automatically update the output filename to better suit the output filesystem limitations.\nUsing a connected USB host requires a libusb-based driver, as well as the Python host script. For more information, please visit \"{}\".",
|
||||||
|
"value_00": "SD card",
|
||||||
|
"value_01": "USB host",
|
||||||
|
"value_02": "USB Mass Storage ({})"
|
||||||
|
},
|
||||||
|
|
||||||
|
"prepend_key_area": {
|
||||||
|
"label": "Prepend KeyArea data",
|
||||||
|
"description": "Prepends the full, 4 KiB long KeyArea block to the output XCI dump, which includes the InitialData area. XCI dumps with KeyArea data are also known as \"Full XCIs\". Disabled by default."
|
||||||
|
},
|
||||||
|
|
||||||
|
"keep_certificate": {
|
||||||
|
"label": "Keep certificate",
|
||||||
|
"description": "Preserves the gamecard certificate in the output XCI dump, which is used to unequivocally identify each individual gamecard. Disabled by default."
|
||||||
|
},
|
||||||
|
|
||||||
|
"trim_dump": {
|
||||||
|
"label": "Trim dump",
|
||||||
|
"description": "Trims the output XCI dump by removing padding data beyond the end of the last HFS partition. Disabled by default."
|
||||||
|
},
|
||||||
|
|
||||||
|
"calculate_checksum": {
|
||||||
|
"label": "Calculate checksum",
|
||||||
|
"description": "Calculates one or more CRC32 checksums over the dumped data, depending on the selected configuration. Checksums are useful to verify data integrity. Enabled by default."
|
||||||
|
},
|
||||||
|
|
||||||
|
"checksum_lookup_method": {
|
||||||
|
"label": "Checksum lookup method",
|
||||||
|
"description": "If \"{0}\" is enabled, this option determines which lookup method is used to validate the calculated CRC32 checksum at the end of the dump process.\nIf \"{1}\" is selected, the calculated checksum will be looked up in \"{2}\", which must have been previously downloaded.\nIf \"{3}\" is selected, the calculated checksum will be looked up using an Internet connection and a public HTTP endpoint.",
|
||||||
|
"value_00": "None"
|
||||||
|
},
|
||||||
|
|
||||||
|
"start_dump": "Start dump"
|
||||||
|
}
|
|
@ -15,5 +15,8 @@
|
||||||
"unknown_exception": "unknown",
|
"unknown_exception": "unknown",
|
||||||
|
|
||||||
"libnx_abort": "Fatal error triggered in libnx!\nError code: 0x{:08X}.",
|
"libnx_abort": "Fatal error triggered in libnx!\nError code: 0x{:08X}.",
|
||||||
"exception_triggered": "Fatal exception triggered!\nReason: {} (0x{:X})."
|
"exception_triggered": "Fatal exception triggered!\nReason: {} (0x{:X}).",
|
||||||
|
|
||||||
|
"value_enabled": "Yes",
|
||||||
|
"value_disabled": "No"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
"overclock": {
|
"overclock": {
|
||||||
"label": "Overclock",
|
"label": "Overclock",
|
||||||
"description": "Overclocks both CPU and MEM to 1785 MHz and 1600 MHz, respectively, in order to speed up dump operations. This is considered a relatively safe action.\n\nIf the application is running under title override mode, and sys-clk is active, and a clock profile has been created for the overridden title, this setting has no effect at all.",
|
"description": "Overclocks both CPU and MEM to 1785 MHz and 1600 MHz, respectively, in order to speed up dump operations. This is considered a relatively safe action.\n\nIf the application is running under title override mode, and sys-clk is active, and a clock profile has been created for the overridden title, this setting has no effect at all."
|
||||||
"value_enabled": "Yes",
|
|
||||||
"value_disabled": "No"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"naming_convention": {
|
"naming_convention": {
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
"not_connected": "Not connected",
|
"not_connected": "Not connected",
|
||||||
|
|
||||||
|
"ums_counter": "{} UMS device(s)",
|
||||||
|
|
||||||
|
"usb_host_speed": "USB {}.0 host",
|
||||||
|
"usb_host_not_connected": "No USB host connected",
|
||||||
|
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"gamecard": "Gamecard",
|
"gamecard": "Gamecard",
|
||||||
"user_titles": "User titles",
|
"user_titles": "User titles",
|
||||||
|
|
Binary file not shown.
|
@ -137,10 +137,9 @@ static bool bktrVisitorMovePrevious(BucketTreeVisitor *visitor);
|
||||||
|
|
||||||
bool bktrInitializeContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, u8 storage_type)
|
bool bktrInitializeContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, u8 storage_type)
|
||||||
{
|
{
|
||||||
NcaContext *nca_ctx = NULL;
|
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || !nca_fs_ctx->nca_ctx || \
|
||||||
|
(nca_fs_ctx->nca_ctx->rights_id_available && !nca_fs_ctx->nca_ctx->titlekey_retrieved) || storage_type == BucketTreeStorageType_Compressed || \
|
||||||
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || !(nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx) || \
|
storage_type >= BucketTreeStorageType_Count)
|
||||||
(nca_ctx->rights_id_available && !nca_ctx->titlekey_retrieved) || storage_type == BucketTreeStorageType_Compressed || storage_type >= BucketTreeStorageType_Count)
|
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -166,20 +165,17 @@ bool bktrInitializeContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_c
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) LOG_MSG_ERROR("Failed to initialize Bucket Tree %s storage for FS section #%u in \"%s\".", bktrGetStorageTypeName(storage_type), nca_fs_ctx->section_idx, \
|
if (!success) LOG_MSG_ERROR("Failed to initialize Bucket Tree %s storage for FS section #%u in \"%s\".", bktrGetStorageTypeName(storage_type), nca_fs_ctx->section_idx, \
|
||||||
nca_ctx->content_id_str);
|
nca_fs_ctx->nca_ctx->content_id_str);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSubStorage *substorage)
|
bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSubStorage *substorage)
|
||||||
{
|
{
|
||||||
NcaFsSectionContext *nca_fs_ctx = NULL;
|
if (!out || !bktrIsValidSubStorage(substorage) || substorage->index != 0 || !substorage->nca_fs_ctx->enabled || !substorage->nca_fs_ctx->has_compression_layer || \
|
||||||
NcaContext *nca_ctx = NULL;
|
substorage->nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || !substorage->nca_fs_ctx->nca_ctx || \
|
||||||
|
(substorage->nca_fs_ctx->nca_ctx->rights_id_available && !substorage->nca_fs_ctx->nca_ctx->titlekey_retrieved) || \
|
||||||
if (!out || !substorage || substorage->index != 0 || !(nca_fs_ctx = substorage->nca_fs_ctx) || !nca_fs_ctx->enabled || !nca_fs_ctx->has_compression_layer || \
|
substorage->type == BucketTreeSubStorageType_AesCtrEx || substorage->type == BucketTreeSubStorageType_Compressed || substorage->type >= BucketTreeSubStorageType_Count)
|
||||||
nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || !(nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx) || (nca_ctx->rights_id_available && !nca_ctx->titlekey_retrieved) || \
|
|
||||||
substorage->type == BucketTreeSubStorageType_AesCtrEx || substorage->type == BucketTreeSubStorageType_Compressed || substorage->type >= BucketTreeSubStorageType_Count || \
|
|
||||||
(substorage->type == BucketTreeSubStorageType_Regular && substorage->bktr_ctx) || (substorage->type != BucketTreeSubStorageType_Regular && !substorage->bktr_ctx))
|
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -188,6 +184,7 @@ bool bktrInitializeCompressedStorageContext(BucketTreeContext *out, BucketTreeSu
|
||||||
/* Free output context beforehand. */
|
/* Free output context beforehand. */
|
||||||
bktrFreeContext(out);
|
bktrFreeContext(out);
|
||||||
|
|
||||||
|
NcaFsSectionContext *nca_fs_ctx = substorage->nca_fs_ctx;
|
||||||
NcaBucketInfo *compressed_bucket = &(nca_fs_ctx->header.compression_info.bucket);
|
NcaBucketInfo *compressed_bucket = &(nca_fs_ctx->header.compression_info.bucket);
|
||||||
BucketTreeTable *compressed_table = NULL;
|
BucketTreeTable *compressed_table = NULL;
|
||||||
u64 node_storage_size = 0, entry_storage_size = 0;
|
u64 node_storage_size = 0, entry_storage_size = 0;
|
||||||
|
@ -253,10 +250,8 @@ end:
|
||||||
|
|
||||||
bool bktrSetRegularSubStorage(BucketTreeContext *ctx, NcaFsSectionContext *nca_fs_ctx)
|
bool bktrSetRegularSubStorage(BucketTreeContext *ctx, NcaFsSectionContext *nca_fs_ctx)
|
||||||
{
|
{
|
||||||
NcaContext *nca_ctx = NULL;
|
|
||||||
|
|
||||||
if (!bktrIsValidContext(ctx) || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || \
|
if (!bktrIsValidContext(ctx) || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->section_type >= NcaFsSectionType_Invalid || \
|
||||||
!(nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx) || (nca_ctx->rights_id_available && !nca_ctx->titlekey_retrieved) || \
|
!nca_fs_ctx->nca_ctx || (nca_fs_ctx->nca_ctx->rights_id_available && !nca_fs_ctx->nca_ctx->titlekey_retrieved) || \
|
||||||
ctx->storage_type == BucketTreeStorageType_Compressed || ctx->storage_type >= BucketTreeStorageType_Count || \
|
ctx->storage_type == BucketTreeStorageType_Compressed || ctx->storage_type >= BucketTreeStorageType_Count || \
|
||||||
(ctx->storage_type == BucketTreeStorageType_Indirect && ctx->nca_fs_ctx == nca_fs_ctx) || \
|
(ctx->storage_type == BucketTreeStorageType_Indirect && ctx->nca_fs_ctx == nca_fs_ctx) || \
|
||||||
((ctx->storage_type == BucketTreeStorageType_AesCtrEx || ctx->storage_type == BucketTreeStorageType_Sparse) && ctx->nca_fs_ctx != nca_fs_ctx))
|
((ctx->storage_type == BucketTreeStorageType_AesCtrEx || ctx->storage_type == BucketTreeStorageType_Sparse) && ctx->nca_fs_ctx != nca_fs_ctx))
|
||||||
|
@ -364,7 +359,7 @@ bool bktrIsBlockWithinIndirectStorageRange(BucketTreeContext *ctx, u64 offset, u
|
||||||
/* Check if we're dealing with a Compressed storage. */
|
/* Check if we're dealing with a Compressed storage. */
|
||||||
if (ctx->storage_type == BucketTreeStorageType_Compressed)
|
if (ctx->storage_type == BucketTreeStorageType_Compressed)
|
||||||
{
|
{
|
||||||
BucketTreeContext *indirect_storage = (BucketTreeContext*)ctx->substorages[0].bktr_ctx;
|
BucketTreeContext *indirect_storage = ctx->substorages[0].bktr_ctx;
|
||||||
const u64 compressed_storage_base_offset = ctx->nca_fs_ctx->hash_region.size;
|
const u64 compressed_storage_base_offset = ctx->nca_fs_ctx->hash_region.size;
|
||||||
BucketTreeCompressedStorageEntry *start_entry = NULL, *end_entry = NULL;
|
BucketTreeCompressedStorageEntry *start_entry = NULL, *end_entry = NULL;
|
||||||
|
|
||||||
|
@ -509,7 +504,7 @@ static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NcaContext *nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx;
|
NcaContext *nca_ctx = nca_fs_ctx->nca_ctx;
|
||||||
NcaBucketInfo *indirect_bucket = (is_sparse ? &(nca_fs_ctx->header.sparse_info.bucket) : &(nca_fs_ctx->header.patch_info.indirect_bucket));
|
NcaBucketInfo *indirect_bucket = (is_sparse ? &(nca_fs_ctx->header.sparse_info.bucket) : &(nca_fs_ctx->header.patch_info.indirect_bucket));
|
||||||
BucketTreeTable *indirect_table = NULL;
|
BucketTreeTable *indirect_table = NULL;
|
||||||
u64 node_storage_size = 0, entry_storage_size = 0;
|
u64 node_storage_size = 0, entry_storage_size = 0;
|
||||||
|
@ -532,7 +527,7 @@ static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSe
|
||||||
|
|
||||||
/* Read indirect storage table data. */
|
/* Read indirect storage table data. */
|
||||||
if ((!is_sparse && !ncaReadFsSection(nca_fs_ctx, indirect_table, indirect_bucket->size, indirect_bucket->offset)) || \
|
if ((!is_sparse && !ncaReadFsSection(nca_fs_ctx, indirect_table, indirect_bucket->size, indirect_bucket->offset)) || \
|
||||||
(is_sparse && !ncaReadContentFile((NcaContext*)nca_fs_ctx->nca_ctx, indirect_table, indirect_bucket->size, nca_fs_ctx->sparse_table_offset)))
|
(is_sparse && !ncaReadContentFile(nca_ctx, indirect_table, indirect_bucket->size, nca_fs_ctx->sparse_table_offset)))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Failed to read Indirect Storage Table data! (%s).", is_sparse ? "sparse" : "patch");
|
LOG_MSG_ERROR("Failed to read Indirect Storage Table data! (%s).", is_sparse ? "sparse" : "patch");
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -595,10 +590,10 @@ static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 r
|
||||||
{
|
{
|
||||||
BucketTreeContext *ctx = visitor->bktr_ctx;
|
BucketTreeContext *ctx = visitor->bktr_ctx;
|
||||||
bool is_sparse = (ctx->storage_type == BucketTreeStorageType_Sparse);
|
bool is_sparse = (ctx->storage_type == BucketTreeStorageType_Sparse);
|
||||||
bool missing_original_storage = !bktrIsValidSubstorage(&(ctx->substorages[0]));
|
bool missing_original_storage = !bktrIsValidSubStorage(&(ctx->substorages[0]));
|
||||||
|
|
||||||
if (!out || (is_sparse && (missing_original_storage || ctx->substorages[0].type != BucketTreeSubStorageType_Regular)) || \
|
if (!out || (is_sparse && (missing_original_storage || ctx->substorages[0].type != BucketTreeSubStorageType_Regular)) || \
|
||||||
(!is_sparse && (!bktrIsValidSubstorage(&(ctx->substorages[1])) || ctx->substorages[1].type != BucketTreeSubStorageType_AesCtrEx || \
|
(!is_sparse && (!bktrIsValidSubStorage(&(ctx->substorages[1])) || ctx->substorages[1].type != BucketTreeSubStorageType_AesCtrEx || \
|
||||||
(!missing_original_storage && (ctx->substorages[0].type == BucketTreeSubStorageType_Indirect || ctx->substorages[0].type == BucketTreeSubStorageType_AesCtrEx || \
|
(!missing_original_storage && (ctx->substorages[0].type == BucketTreeSubStorageType_Indirect || ctx->substorages[0].type == BucketTreeSubStorageType_AesCtrEx || \
|
||||||
ctx->substorages[0].type >= BucketTreeSubStorageType_Count)))) || (offset + read_size) > ctx->end_offset)
|
ctx->substorages[0].type >= BucketTreeSubStorageType_Count)))) || (offset + read_size) > ctx->end_offset)
|
||||||
{
|
{
|
||||||
|
@ -771,7 +766,7 @@ static bool bktrReadAesCtrExStorage(BucketTreeVisitor *visitor, void *out, u64 r
|
||||||
{
|
{
|
||||||
BucketTreeContext *ctx = visitor->bktr_ctx;
|
BucketTreeContext *ctx = visitor->bktr_ctx;
|
||||||
|
|
||||||
if (!out || !bktrIsValidSubstorage(&(ctx->substorages[0])) || ctx->substorages[0].type != BucketTreeSubStorageType_Regular || (offset + read_size) > ctx->end_offset)
|
if (!out || !bktrIsValidSubStorage(&(ctx->substorages[0])) || ctx->substorages[0].type != BucketTreeSubStorageType_Regular || (offset + read_size) > ctx->end_offset)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -856,7 +851,8 @@ static bool bktrReadCompressedStorage(BucketTreeVisitor *visitor, void *out, u64
|
||||||
NcaFsSectionContext *nca_fs_ctx = ctx->nca_fs_ctx;
|
NcaFsSectionContext *nca_fs_ctx = ctx->nca_fs_ctx;
|
||||||
u64 compressed_storage_base_offset = nca_fs_ctx->hash_region.size;
|
u64 compressed_storage_base_offset = nca_fs_ctx->hash_region.size;
|
||||||
|
|
||||||
if (!out || !bktrIsValidSubstorage(&(ctx->substorages[0])) || ctx->substorages[0].type >= BucketTreeSubStorageType_AesCtrEx || (offset + read_size) > ctx->end_offset)
|
if (!out || !bktrIsValidSubStorage(&(ctx->substorages[0])) || ctx->substorages[0].type == BucketTreeSubStorageType_AesCtrEx || \
|
||||||
|
ctx->substorages[0].type == BucketTreeSubStorageType_Compressed || ctx->substorages[0].type >= BucketTreeSubStorageType_Count || (offset + read_size) > ctx->end_offset)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1016,7 +1012,7 @@ end:
|
||||||
|
|
||||||
static bool bktrReadSubStorage(BucketTreeSubStorage *substorage, BucketTreeSubStorageReadParams *params)
|
static bool bktrReadSubStorage(BucketTreeSubStorage *substorage, BucketTreeSubStorageReadParams *params)
|
||||||
{
|
{
|
||||||
if (!bktrIsValidSubstorage(substorage) || !params || !params->buffer || !params->size)
|
if (!bktrIsValidSubStorage(substorage) || !params || !params->buffer || !params->size)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1041,8 +1037,7 @@ static bool bktrReadSubStorage(BucketTreeSubStorage *substorage, BucketTreeSubSt
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Perform a read on the target BucketTree storage. */
|
/* Perform a read on the target BucketTree storage. */
|
||||||
BucketTreeContext *ctx = (BucketTreeContext*)substorage->bktr_ctx;
|
success = bktrReadStorage(substorage->bktr_ctx, params->buffer, params->size, params->offset);
|
||||||
success = bktrReadStorage(ctx, params->buffer, params->size, params->offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) LOG_MSG_ERROR("Failed to read 0x%lX-byte long chunk from offset 0x%lX!", params->size, params->offset);
|
if (!success) LOG_MSG_ERROR("Failed to read 0x%lX-byte long chunk from offset 0x%lX!", params->size, params->offset);
|
||||||
|
|
|
@ -169,7 +169,7 @@ static void configFreeConfigJson(void)
|
||||||
|
|
||||||
static bool configValidateJsonRootObject(const struct json_object *obj)
|
static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
{
|
{
|
||||||
bool ret = false, overclock_found = false, naming_convention_found = false, dump_destination_found = false, gamecard_found = false;
|
bool ret = false, overclock_found = false, naming_convention_found = false, output_storage_found = false, gamecard_found = false;
|
||||||
bool nsp_found = false, ticket_found = false, nca_fs_found = false;
|
bool nsp_found = false, ticket_found = false, nca_fs_found = false;
|
||||||
|
|
||||||
if (!jsonValidateObject(obj)) goto end;
|
if (!jsonValidateObject(obj)) goto end;
|
||||||
|
@ -178,7 +178,7 @@ static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
{
|
{
|
||||||
CONFIG_VALIDATE_FIELD(Boolean, overclock);
|
CONFIG_VALIDATE_FIELD(Boolean, overclock);
|
||||||
CONFIG_VALIDATE_FIELD(Integer, naming_convention, TitleNamingConvention_Full, TitleNamingConvention_Count - 1);
|
CONFIG_VALIDATE_FIELD(Integer, naming_convention, TitleNamingConvention_Full, TitleNamingConvention_Count - 1);
|
||||||
CONFIG_VALIDATE_FIELD(Integer, dump_destination, ConfigDumpDestination_SdCard, ConfigDumpDestination_Count - 1);
|
CONFIG_VALIDATE_FIELD(Integer, output_storage, ConfigOutputStorage_SdCard, ConfigOutputStorage_Count - 1);
|
||||||
CONFIG_VALIDATE_OBJECT(GameCard, gamecard);
|
CONFIG_VALIDATE_OBJECT(GameCard, gamecard);
|
||||||
CONFIG_VALIDATE_OBJECT(Nsp, nsp);
|
CONFIG_VALIDATE_OBJECT(Nsp, nsp);
|
||||||
CONFIG_VALIDATE_OBJECT(Ticket, ticket);
|
CONFIG_VALIDATE_OBJECT(Ticket, ticket);
|
||||||
|
@ -186,7 +186,7 @@ static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (overclock_found && naming_convention_found && dump_destination_found && gamecard_found && nsp_found && ticket_found && nca_fs_found);
|
ret = (overclock_found && naming_convention_found && output_storage_found && gamecard_found && nsp_found && ticket_found && nca_fs_found);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -194,13 +194,13 @@ end:
|
||||||
|
|
||||||
static bool configValidateJsonGameCardObject(const struct json_object *obj)
|
static bool configValidateJsonGameCardObject(const struct json_object *obj)
|
||||||
{
|
{
|
||||||
bool ret = false, append_key_area_found = false, keep_certificate_found = false, trim_dump_found = false, calculate_checksum_found = false, checksum_lookup_method_found = false;
|
bool ret = false, prepend_key_area_found = false, keep_certificate_found = false, trim_dump_found = false, calculate_checksum_found = false, checksum_lookup_method_found = false;
|
||||||
|
|
||||||
if (!jsonValidateObject(obj)) goto end;
|
if (!jsonValidateObject(obj)) goto end;
|
||||||
|
|
||||||
json_object_object_foreach(obj, key, val)
|
json_object_object_foreach(obj, key, val)
|
||||||
{
|
{
|
||||||
CONFIG_VALIDATE_FIELD(Boolean, append_key_area);
|
CONFIG_VALIDATE_FIELD(Boolean, prepend_key_area);
|
||||||
CONFIG_VALIDATE_FIELD(Boolean, keep_certificate);
|
CONFIG_VALIDATE_FIELD(Boolean, keep_certificate);
|
||||||
CONFIG_VALIDATE_FIELD(Boolean, trim_dump);
|
CONFIG_VALIDATE_FIELD(Boolean, trim_dump);
|
||||||
CONFIG_VALIDATE_FIELD(Boolean, calculate_checksum);
|
CONFIG_VALIDATE_FIELD(Boolean, calculate_checksum);
|
||||||
|
@ -208,7 +208,7 @@ static bool configValidateJsonGameCardObject(const struct json_object *obj)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (append_key_area_found && keep_certificate_found && trim_dump_found && calculate_checksum_found && checksum_lookup_method_found);
|
ret = (prepend_key_area_found && keep_certificate_found && trim_dump_found && calculate_checksum_found && checksum_lookup_method_found);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -273,8 +273,9 @@ bool ncaGenerateHierarchicalSha256Patch(NcaFsSectionContext *ctx, const void *da
|
||||||
|
|
||||||
void ncaWriteHierarchicalSha256PatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset)
|
void ncaWriteHierarchicalSha256PatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalSha256Patch *patch, void *buf, u64 buf_size, u64 buf_offset)
|
||||||
{
|
{
|
||||||
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || memcmp(patch->content_id.c, ctx->content_id.c, 0x10) != 0 || \
|
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \
|
||||||
!patch->hash_region_count || patch->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
|
memcmp(patch->content_id.c, ctx->content_id.c, sizeof(NcmContentId)) != 0 || !patch->hash_region_count || \
|
||||||
|
patch->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
|
||||||
|
|
||||||
patch->written = true;
|
patch->written = true;
|
||||||
|
|
||||||
|
@ -297,8 +298,8 @@ bool ncaGenerateHierarchicalIntegrityPatch(NcaFsSectionContext *ctx, const void
|
||||||
|
|
||||||
void ncaWriteHierarchicalIntegrityPatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalIntegrityPatch *patch, void *buf, u64 buf_size, u64 buf_offset)
|
void ncaWriteHierarchicalIntegrityPatchToMemoryBuffer(NcaContext *ctx, NcaHierarchicalIntegrityPatch *patch, void *buf, u64 buf_size, u64 buf_offset)
|
||||||
{
|
{
|
||||||
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || memcmp(patch->content_id.c, ctx->content_id.c, 0x10) != 0 || \
|
if (!ctx || !*(ctx->content_id_str) || ctx->content_size < NCA_FULL_HEADER_LENGTH || !patch || patch->written || \
|
||||||
!buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
|
memcmp(patch->content_id.c, ctx->content_id.c, sizeof(NcmContentId)) != 0 || !buf || !buf_size || (buf_offset + buf_size) > ctx->content_size) return;
|
||||||
|
|
||||||
patch->written = true;
|
patch->written = true;
|
||||||
|
|
||||||
|
@ -458,13 +459,12 @@ void ncaUpdateContentIdAndHash(NcaContext *ctx, u8 hash[SHA256_HASH_SIZE])
|
||||||
|
|
||||||
const char *ncaGetFsSectionTypeName(NcaFsSectionContext *ctx)
|
const char *ncaGetFsSectionTypeName(NcaFsSectionContext *ctx)
|
||||||
{
|
{
|
||||||
NcaContext *nca_ctx = NULL;
|
|
||||||
const char *str = "Invalid";
|
const char *str = "Invalid";
|
||||||
bool is_exefs = false;
|
bool is_exefs = false;
|
||||||
|
|
||||||
if (!ctx || !(nca_ctx = (NcaContext*)ctx->nca_ctx)) return str;
|
if (!ctx || !ctx->nca_ctx) return str;
|
||||||
|
|
||||||
is_exefs = (nca_ctx->content_type == NcmContentType_Program && ctx->section_idx == 0);
|
is_exefs = (ctx->nca_ctx->content_type == NcmContentType_Program && ctx->section_idx == 0);
|
||||||
|
|
||||||
switch(ctx->section_type)
|
switch(ctx->section_type)
|
||||||
{
|
{
|
||||||
|
@ -1019,7 +1019,7 @@ end:
|
||||||
static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
{
|
{
|
||||||
#if LOG_LEVEL <= LOG_LEVEL_WARNING
|
#if LOG_LEVEL <= LOG_LEVEL_WARNING
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
const char *content_id_str = ctx->nca_ctx->content_id_str;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool success = false, valid = true;
|
bool success = false, valid = true;
|
||||||
|
@ -1038,7 +1038,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
if (!hash_data->hash_block_size || !hash_data->hash_region_count || hash_data->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT)
|
if (!hash_data->hash_block_size || !hash_data->hash_region_count || hash_data->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT)
|
||||||
{
|
{
|
||||||
LOG_DATA_WARNING(hash_data, sizeof(NcaHierarchicalSha256Data), "Invalid HierarchicalSha256 data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
LOG_DATA_WARNING(hash_data, sizeof(NcaHierarchicalSha256Data), "Invalid HierarchicalSha256 data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
||||||
ctx->section_idx, nca_ctx->content_id_str);
|
ctx->section_idx, content_id_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,7 +1050,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
((i < (hash_data->hash_region_count - 1) || !ctx->has_sparse_layer) && (hash_region->offset + hash_region->size) > ctx->section_size))
|
((i < (hash_data->hash_region_count - 1) || !ctx->has_sparse_layer) && (hash_region->offset + hash_region->size) > ctx->section_size))
|
||||||
{
|
{
|
||||||
LOG_MSG_WARNING("HierarchicalSha256 region #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
LOG_MSG_WARNING("HierarchicalSha256 region #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
||||||
i, ctx->section_idx, nca_ctx->content_id_str);
|
i, ctx->section_idx, content_id_str);
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1070,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
hash_data->info_level_hash.max_level_count != NCA_IVFC_MAX_LEVEL_COUNT)
|
hash_data->info_level_hash.max_level_count != NCA_IVFC_MAX_LEVEL_COUNT)
|
||||||
{
|
{
|
||||||
LOG_DATA_WARNING(hash_data, sizeof(NcaIntegrityMetaInfo), "Invalid HierarchicalIntegrity data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
LOG_DATA_WARNING(hash_data, sizeof(NcaIntegrityMetaInfo), "Invalid HierarchicalIntegrity data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
||||||
ctx->section_idx, nca_ctx->content_id_str);
|
ctx->section_idx, content_id_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1082,7 +1082,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
(!ctx->has_sparse_layer && ctx->section_type != NcaFsSectionType_PatchRomFs)) && (lvl_info->offset + lvl_info->size) > ctx->section_size))
|
(!ctx->has_sparse_layer && ctx->section_type != NcaFsSectionType_PatchRomFs)) && (lvl_info->offset + lvl_info->size) > ctx->section_size))
|
||||||
{
|
{
|
||||||
LOG_MSG_WARNING("HierarchicalIntegrity level #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
LOG_MSG_WARNING("HierarchicalIntegrity level #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
||||||
i, ctx->section_idx, nca_ctx->content_id_str);
|
i, ctx->section_idx, content_id_str);
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1095,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_MSG_WARNING("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", ctx->section_idx, nca_ctx->content_id_str, ctx->hash_type);
|
LOG_MSG_WARNING("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", ctx->section_idx, content_id_str, ctx->hash_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1115,7 +1115,7 @@ static bool _ncaReadFsSection(NcaFsSectionContext *ctx, void *out, u64 read_size
|
||||||
size_t crypt_res = 0;
|
size_t crypt_res = 0;
|
||||||
u64 sector_num = 0;
|
u64 sector_num = 0;
|
||||||
|
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
NcaContext *nca_ctx = ctx->nca_ctx;
|
||||||
u64 content_offset = (ctx->section_offset + offset);
|
u64 content_offset = (ctx->section_offset + offset);
|
||||||
|
|
||||||
u64 sparse_virtual_offset = ((ctx->has_sparse_layer && ctx->cur_sparse_virtual_offset) ? (ctx->section_offset + ctx->cur_sparse_virtual_offset) : 0);
|
u64 sparse_virtual_offset = ((ctx->has_sparse_layer && ctx->cur_sparse_virtual_offset) ? (ctx->section_offset + ctx->cur_sparse_virtual_offset) : 0);
|
||||||
|
@ -1299,7 +1299,7 @@ static bool _ncaReadAesCtrExStorage(NcaFsSectionContext *ctx, void *out, u64 rea
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
NcaContext *nca_ctx = ctx->nca_ctx;
|
||||||
u64 content_offset = (ctx->section_offset + offset);
|
u64 content_offset = (ctx->section_offset + offset);
|
||||||
|
|
||||||
u64 block_start_offset = 0, block_end_offset = 0, block_size = 0;
|
u64 block_start_offset = 0, block_end_offset = 0, block_size = 0;
|
||||||
|
@ -1394,7 +1394,7 @@ static bool ncaGenerateHashDataPatch(NcaFsSectionContext *ctx, const void *data,
|
||||||
|
|
||||||
bool use_sha3 = false, success = false;
|
bool use_sha3 = false, success = false;
|
||||||
|
|
||||||
if (!ctx || !ctx->enabled || ctx->has_sparse_layer || ctx->has_compression_layer || !(nca_ctx = (NcaContext*)ctx->nca_ctx) || \
|
if (!ctx || !ctx->enabled || ctx->has_sparse_layer || ctx->has_compression_layer || !(nca_ctx = ctx->nca_ctx) || \
|
||||||
(!is_integrity_patch && ((ctx->hash_type != NcaHashType_HierarchicalSha256 && ctx->hash_type != NcaHashType_HierarchicalSha3256) || \
|
(!is_integrity_patch && ((ctx->hash_type != NcaHashType_HierarchicalSha256 && ctx->hash_type != NcaHashType_HierarchicalSha3256) || \
|
||||||
!ctx->header.hash_data.hierarchical_sha256_data.hash_block_size || !(layer_count = ctx->header.hash_data.hierarchical_sha256_data.hash_region_count) || \
|
!ctx->header.hash_data.hierarchical_sha256_data.hash_block_size || !(layer_count = ctx->header.hash_data.hierarchical_sha256_data.hash_region_count) || \
|
||||||
layer_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !(last_layer_size = ctx->header.hash_data.hierarchical_sha256_data.hash_region[layer_count - 1].size))) || \
|
layer_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT || !(last_layer_size = ctx->header.hash_data.hierarchical_sha256_data.hash_region[layer_count - 1].size))) || \
|
||||||
|
@ -1656,7 +1656,7 @@ static void *ncaGenerateEncryptedFsSectionBlock(NcaFsSectionContext *ctx, const
|
||||||
size_t crypt_res = 0;
|
size_t crypt_res = 0;
|
||||||
u64 sector_num = 0;
|
u64 sector_num = 0;
|
||||||
|
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
NcaContext *nca_ctx = ctx->nca_ctx;
|
||||||
u64 content_offset = (ctx->section_offset + data_offset);
|
u64 content_offset = (ctx->section_offset + data_offset);
|
||||||
|
|
||||||
u64 block_start_offset = 0, block_end_offset = 0, block_size = 0;
|
u64 block_start_offset = 0, block_end_offset = 0, block_size = 0;
|
||||||
|
|
|
@ -95,7 +95,7 @@ bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStora
|
||||||
NcaContext *patch_nca_ctx = NULL, *base_nca_ctx = NULL;
|
NcaContext *patch_nca_ctx = NULL, *base_nca_ctx = NULL;
|
||||||
|
|
||||||
if (!ncaStorageIsValidContext(patch_ctx) || !ncaStorageIsValidContext(base_ctx) || patch_ctx->nca_fs_ctx == base_ctx->nca_fs_ctx || \
|
if (!ncaStorageIsValidContext(patch_ctx) || !ncaStorageIsValidContext(base_ctx) || patch_ctx->nca_fs_ctx == base_ctx->nca_fs_ctx || \
|
||||||
!(patch_nca_ctx = (NcaContext*)patch_ctx->nca_fs_ctx->nca_ctx) || !(base_nca_ctx = (NcaContext*)base_ctx->nca_fs_ctx->nca_ctx) || \
|
!(patch_nca_ctx = patch_ctx->nca_fs_ctx->nca_ctx) || !(base_nca_ctx = base_ctx->nca_fs_ctx->nca_ctx) || \
|
||||||
patch_ctx->nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || base_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
|
patch_ctx->nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || base_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
|
||||||
patch_nca_ctx->header.program_id != base_nca_ctx->header.program_id || patch_nca_ctx->header.content_type != base_nca_ctx->header.content_type || \
|
patch_nca_ctx->header.program_id != base_nca_ctx->header.program_id || patch_nca_ctx->header.content_type != base_nca_ctx->header.content_type || \
|
||||||
patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version < base_nca_ctx->title_version || \
|
patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version < base_nca_ctx->title_version || \
|
||||||
|
|
|
@ -30,7 +30,7 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
|
||||||
bool success = false, dump_meta_header = false, dump_acid_header = false, dump_aci_header = false;
|
bool success = false, dump_meta_header = false, dump_acid_header = false, dump_aci_header = false;
|
||||||
PartitionFileSystemEntry *pfs_entry = NULL;
|
PartitionFileSystemEntry *pfs_entry = NULL;
|
||||||
|
|
||||||
if (!out || !pfs_ctx || !ncaStorageIsValidContext(&(pfs_ctx->storage_ctx)) || !(nca_ctx = (NcaContext*)pfs_ctx->nca_fs_ctx->nca_ctx) || \
|
if (!out || !pfs_ctx || !ncaStorageIsValidContext(&(pfs_ctx->storage_ctx)) || !(nca_ctx = pfs_ctx->nca_fs_ctx->nca_ctx) || \
|
||||||
nca_ctx->content_type != NcmContentType_Program || !pfs_ctx->offset || !pfs_ctx->size || !pfs_ctx->is_exefs || \
|
nca_ctx->content_type != NcmContentType_Program || !pfs_ctx->offset || !pfs_ctx->size || !pfs_ctx->is_exefs || \
|
||||||
pfs_ctx->header_size <= sizeof(PartitionFileSystemHeader) || !pfs_ctx->header)
|
pfs_ctx->header_size <= sizeof(PartitionFileSystemHeader) || !pfs_ctx->header)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,12 +31,11 @@ static bool nsoGetSectionFromRodataSegment(NsoContext *nso_ctx, u8 *rodata_buf,
|
||||||
|
|
||||||
bool nsoInitializeContext(NsoContext *out, PartitionFileSystemContext *pfs_ctx, PartitionFileSystemEntry *pfs_entry)
|
bool nsoInitializeContext(NsoContext *out, PartitionFileSystemContext *pfs_ctx, PartitionFileSystemEntry *pfs_entry)
|
||||||
{
|
{
|
||||||
NcaContext *nca_ctx = NULL;
|
|
||||||
u8 *rodata_buf = NULL;
|
u8 *rodata_buf = NULL;
|
||||||
bool success = false, dump_nso_header = false;
|
bool success = false, dump_nso_header = false;
|
||||||
|
|
||||||
if (!out || !pfs_ctx || !ncaStorageIsValidContext(&(pfs_ctx->storage_ctx)) || !(nca_ctx = (NcaContext*)pfs_ctx->nca_fs_ctx->nca_ctx) || \
|
if (!out || !pfs_ctx || !ncaStorageIsValidContext(&(pfs_ctx->storage_ctx)) || !pfs_ctx->nca_fs_ctx->nca_ctx || \
|
||||||
nca_ctx->content_type != NcmContentType_Program || !pfs_ctx->offset || !pfs_ctx->size || !pfs_ctx->is_exefs || \
|
pfs_ctx->nca_fs_ctx->nca_ctx->content_type != NcmContentType_Program || !pfs_ctx->offset || !pfs_ctx->size || !pfs_ctx->is_exefs || \
|
||||||
pfs_ctx->header_size <= sizeof(PartitionFileSystemHeader) || !pfs_ctx->header || !pfs_entry)
|
pfs_ctx->header_size <= sizeof(PartitionFileSystemHeader) || !pfs_ctx->header || !pfs_entry)
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx)
|
bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx)
|
||||||
{
|
{
|
||||||
NcaContext *nca_ctx = NULL;
|
|
||||||
u32 magic = 0;
|
u32 magic = 0;
|
||||||
|
|
||||||
PartitionFileSystemHeader pfs_header = {0};
|
PartitionFileSystemHeader pfs_header = {0};
|
||||||
|
@ -36,8 +35,8 @@ bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *
|
||||||
bool success = false, dump_fs_header = false;
|
bool success = false, dump_fs_header = false;
|
||||||
|
|
||||||
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->has_sparse_layer || nca_fs_ctx->section_type != NcaFsSectionType_PartitionFs || \
|
if (!out || !nca_fs_ctx || !nca_fs_ctx->enabled || nca_fs_ctx->has_sparse_layer || nca_fs_ctx->section_type != NcaFsSectionType_PartitionFs || \
|
||||||
(nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256 && nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha3256) || !(nca_ctx = (NcaContext*)nca_fs_ctx->nca_ctx) || \
|
(nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256 && nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha3256) || !nca_fs_ctx->nca_ctx || \
|
||||||
(nca_ctx->rights_id_available && !nca_ctx->titlekey_retrieved))
|
(nca_fs_ctx->nca_ctx->rights_id_available && !nca_fs_ctx->nca_ctx->titlekey_retrieved))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,12 +38,12 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
|
||||||
base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)));
|
base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)));
|
||||||
|
|
||||||
if (!out || !base_nca_fs_ctx || (!patch_nca_fs_ctx && (missing_base_romfs || base_nca_fs_ctx->has_sparse_layer)) || \
|
if (!out || !base_nca_fs_ctx || (!patch_nca_fs_ctx && (missing_base_romfs || base_nca_fs_ctx->has_sparse_layer)) || \
|
||||||
(!missing_base_romfs && (!(base_nca_ctx = (NcaContext*)base_nca_fs_ctx->nca_ctx) || (base_nca_ctx->format_version == NcaVersion_Nca0 && \
|
(!missing_base_romfs && (!(base_nca_ctx = base_nca_fs_ctx->nca_ctx) || (base_nca_ctx->format_version == NcaVersion_Nca0 && \
|
||||||
(base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs || base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256)) || \
|
(base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs || base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256)) || \
|
||||||
(base_nca_ctx->format_version != NcaVersion_Nca0 && (base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
|
(base_nca_ctx->format_version != NcaVersion_Nca0 && (base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \
|
||||||
(base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegrity && base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegritySha3))) || \
|
(base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegrity && base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegritySha3))) || \
|
||||||
(base_nca_ctx->rights_id_available && !base_nca_ctx->titlekey_retrieved))) || (patch_nca_fs_ctx && (!patch_nca_fs_ctx->enabled || \
|
(base_nca_ctx->rights_id_available && !base_nca_ctx->titlekey_retrieved))) || (patch_nca_fs_ctx && (!patch_nca_fs_ctx->enabled || \
|
||||||
!(patch_nca_ctx = (NcaContext*)patch_nca_fs_ctx->nca_ctx) || (!missing_base_romfs && patch_nca_ctx->format_version != base_nca_ctx->format_version) || \
|
!(patch_nca_ctx = patch_nca_fs_ctx->nca_ctx) || (!missing_base_romfs && patch_nca_ctx->format_version != base_nca_ctx->format_version) || \
|
||||||
patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || (patch_nca_ctx->rights_id_available && !patch_nca_ctx->titlekey_retrieved))))
|
patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || (patch_nca_ctx->rights_id_available && !patch_nca_ctx->titlekey_retrieved))))
|
||||||
{
|
{
|
||||||
LOG_MSG_ERROR("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <nxdt_utils.h>
|
#include <nxdt_utils.h>
|
||||||
#include <gamecard_tab.hpp>
|
#include <gamecard_tab.hpp>
|
||||||
#include <titles_tab.hpp>
|
#include <titles_tab.hpp>
|
||||||
|
#include <dump_options_frame.hpp>
|
||||||
|
|
||||||
namespace i18n = brls::i18n; /* For getStr(). */
|
namespace i18n = brls::i18n; /* For getStr(). */
|
||||||
using namespace i18n::literals; /* For _i18n. */
|
using namespace i18n::literals; /* For _i18n. */
|
||||||
|
@ -34,7 +35,7 @@ namespace nxdt::views
|
||||||
this->list->setSpacing(this->list->getSpacing() / 2);
|
this->list->setSpacing(this->list->getSpacing() / 2);
|
||||||
this->list->setMarginBottom(20);
|
this->list->setMarginBottom(20);
|
||||||
|
|
||||||
/* Subscribe to gamecard status event. */
|
/* Subscribe to the gamecard status event. */
|
||||||
this->gc_status_task_sub = this->root_view->RegisterGameCardTaskListener([this](GameCardStatus gc_status) {
|
this->gc_status_task_sub = this->root_view->RegisterGameCardTaskListener([this](GameCardStatus gc_status) {
|
||||||
/* Process gamecard status. */
|
/* Process gamecard status. */
|
||||||
this->ProcessGameCardStatus(gc_status);
|
this->ProcessGameCardStatus(gc_status);
|
||||||
|
@ -179,9 +180,16 @@ namespace nxdt::views
|
||||||
|
|
||||||
brls::ListItem *dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
|
brls::ListItem *dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
|
||||||
|
|
||||||
/*dump_card_image->getClickEvent()->subscribe([](brls::View *view) {
|
dump_card_image->getClickEvent()->subscribe([this](brls::View *view) {
|
||||||
|
char *raw_filename = titleGenerateGameCardFileName(configGetInteger("naming_convention"), TitleFileNameIllegalCharReplaceType_None);
|
||||||
|
if (!raw_filename) return;
|
||||||
|
|
||||||
});*/
|
brls::Image *icon = new brls::Image();
|
||||||
|
icon->setImage(BOREALIS_ASSET("icon/" APP_TITLE ".jpg"));
|
||||||
|
icon->setScaleType(brls::ImageScaleType::SCALE);
|
||||||
|
|
||||||
|
brls::Application::pushView(new DumpOptionsFrame(this->root_view, "gamecard_tab/list/dump_card_image/label"_i18n, icon, raw_filename, ".xci"), brls::ViewAnimation::SLIDE_LEFT);
|
||||||
|
});
|
||||||
|
|
||||||
this->list->addView(dump_card_image);
|
this->list->addView(dump_card_image);
|
||||||
|
|
||||||
|
|
|
@ -395,8 +395,8 @@ namespace nxdt::views
|
||||||
|
|
||||||
/* Overclock. */
|
/* Overclock. */
|
||||||
brls::ToggleListItem *overclock = new brls::ToggleListItem("options_tab/overclock/label"_i18n, configGetBoolean("overclock"), \
|
brls::ToggleListItem *overclock = new brls::ToggleListItem("options_tab/overclock/label"_i18n, configGetBoolean("overclock"), \
|
||||||
"options_tab/overclock/description"_i18n, "options_tab/overclock/value_enabled"_i18n, \
|
"options_tab/overclock/description"_i18n, "generic/value_enabled"_i18n, \
|
||||||
"options_tab/overclock/value_disabled"_i18n);
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
overclock->getClickEvent()->subscribe([](brls::View* view) {
|
overclock->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
/* Get current value. */
|
/* Get current value. */
|
||||||
|
|
|
@ -81,7 +81,18 @@ namespace nxdt::views
|
||||||
this->usb_icon->setVerticalAlign(NVG_ALIGN_TOP);
|
this->usb_icon->setVerticalAlign(NVG_ALIGN_TOP);
|
||||||
this->usb_icon->setParent(this);
|
this->usb_icon->setParent(this);
|
||||||
|
|
||||||
this->usb_host_speed_lbl = new brls::Label(brls::LabelStyle::SMALL, "root_view/not_connected"_i18n);
|
this->ums_counter_lbl = new brls::Label(brls::LabelStyle::SMALL, i18n::getStr("root_view/ums_counter"_i18n, usbHsFsGetPhysicalDeviceCount()));
|
||||||
|
this->ums_counter_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT);
|
||||||
|
this->ums_counter_lbl->setVerticalAlign(NVG_ALIGN_TOP);
|
||||||
|
this->ums_counter_lbl->setParent(this);
|
||||||
|
|
||||||
|
this->cable_icon = new brls::Label(brls::LabelStyle::SMALL, "\uEFE6");
|
||||||
|
this->cable_icon->setFont(material);
|
||||||
|
this->cable_icon->setHorizontalAlign(NVG_ALIGN_RIGHT);
|
||||||
|
this->cable_icon->setVerticalAlign(NVG_ALIGN_TOP);
|
||||||
|
this->cable_icon->setParent(this);
|
||||||
|
|
||||||
|
this->usb_host_speed_lbl = new brls::Label(brls::LabelStyle::SMALL, "root_view/usb_host_not_connected"_i18n);
|
||||||
this->usb_host_speed_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT);
|
this->usb_host_speed_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT);
|
||||||
this->usb_host_speed_lbl->setVerticalAlign(NVG_ALIGN_TOP);
|
this->usb_host_speed_lbl->setVerticalAlign(NVG_ALIGN_TOP);
|
||||||
this->usb_host_speed_lbl->setParent(this);
|
this->usb_host_speed_lbl->setParent(this);
|
||||||
|
@ -128,8 +139,13 @@ namespace nxdt::views
|
||||||
this->time_lbl->setText(this->GetFormattedDateString(status_info_data->timeinfo));
|
this->time_lbl->setText(this->GetFormattedDateString(status_info_data->timeinfo));
|
||||||
|
|
||||||
/* Update battery labels. */
|
/* Update battery labels. */
|
||||||
this->battery_icon->setText(charger_type != PsmChargerType_Unconnected ? "\uE1A3" : (charge_percentage <= 15 ? "\uE19C" : "\uE1A4"));
|
this->battery_icon->setText(charger_type != PsmChargerType_Unconnected ? "\uE1A3" : (charge_percentage >= 100 ? "\uE1A4" : (charge_percentage >= 83 ? "\uEBD2" : \
|
||||||
this->battery_icon->setColor(charger_type != PsmChargerType_Unconnected ? nvgRGB(0, 255, 0) : (charge_percentage <= 15 ? nvgRGB(255, 0, 0) : brls::Application::getTheme()->textColor));
|
(charge_percentage >= 67 ? "\uEBD4" : (charge_percentage >= 50 ? "\uEBE2" : \
|
||||||
|
(charge_percentage >= 33 ? "\uEBDD" : (charge_percentage >= 17 ? "\uEBE0" : \
|
||||||
|
(charge_percentage > 0 ? "\uEBD9" : "\uEBDC"))))))));
|
||||||
|
|
||||||
|
this->battery_icon->setColor(charger_type != PsmChargerType_Unconnected ? nvgRGB(0, 255, 0) : (charge_percentage <= 15 ? nvgRGB(255, 0, 0) : \
|
||||||
|
brls::Application::getTheme()->textColor));
|
||||||
|
|
||||||
this->battery_percentage->setText(fmt::format("{}%", charge_percentage));
|
this->battery_percentage->setText(fmt::format("{}%", charge_percentage));
|
||||||
|
|
||||||
|
@ -138,19 +154,24 @@ namespace nxdt::views
|
||||||
this->connection_status_lbl->setText(ip_addr ? std::string(ip_addr) : "root_view/not_connected"_i18n);
|
this->connection_status_lbl->setText(ip_addr ? std::string(ip_addr) : "root_view/not_connected"_i18n);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Subscribe to UMS event. */
|
||||||
|
this->ums_task_sub = this->ums_task->RegisterListener([this](const nxdt::tasks::UmsDeviceVector* ums_devices) {
|
||||||
|
/* Update UMS counter label. */
|
||||||
|
this->ums_counter_lbl->setText(i18n::getStr("root_view/ums_counter"_i18n, usbHsFsGetPhysicalDeviceCount()));
|
||||||
|
});
|
||||||
|
|
||||||
/* Subscribe to USB host event. */
|
/* Subscribe to USB host event. */
|
||||||
this->usb_host_task_sub = this->usb_host_task->RegisterListener([this](UsbHostSpeed usb_host_speed) {
|
this->usb_host_task_sub = this->usb_host_task->RegisterListener([this](UsbHostSpeed usb_host_speed) {
|
||||||
/* Update USB host speed label. */
|
/* Update USB host speed label. */
|
||||||
this->usb_host_speed_lbl->setText(usb_host_speed ? fmt::format("USB {}.0", usb_host_speed) : "root_view/not_connected"_i18n);
|
this->usb_host_speed_lbl->setText(usb_host_speed ? i18n::getStr("root_view/usb_host_speed"_i18n, usb_host_speed) : "root_view/usb_host_not_connected"_i18n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RootView::~RootView(void)
|
RootView::~RootView(void)
|
||||||
{
|
{
|
||||||
/* Unregister USB host task listener. */
|
/* Unregister task listeners. */
|
||||||
this->usb_host_task->UnregisterListener(this->usb_host_task_sub);
|
this->usb_host_task->UnregisterListener(this->usb_host_task_sub);
|
||||||
|
this->ums_task->UnregisterListener(this->ums_task_sub);
|
||||||
/* Unregister status info task listener. */
|
|
||||||
this->status_info_task->UnregisterListener(this->status_info_task_sub);
|
this->status_info_task->UnregisterListener(this->status_info_task_sub);
|
||||||
|
|
||||||
/* Stop background tasks. */
|
/* Stop background tasks. */
|
||||||
|
@ -168,6 +189,8 @@ namespace nxdt::views
|
||||||
delete this->connection_icon;
|
delete this->connection_icon;
|
||||||
delete this->connection_status_lbl;
|
delete this->connection_status_lbl;
|
||||||
delete this->usb_icon;
|
delete this->usb_icon;
|
||||||
|
delete this->ums_counter_lbl;
|
||||||
|
delete this->cable_icon;
|
||||||
delete this->usb_host_speed_lbl;
|
delete this->usb_host_speed_lbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,12 +235,15 @@ namespace nxdt::views
|
||||||
this->connection_status_lbl->frame(ctx);
|
this->connection_status_lbl->frame(ctx);
|
||||||
|
|
||||||
this->usb_icon->frame(ctx);
|
this->usb_icon->frame(ctx);
|
||||||
|
this->ums_counter_lbl->frame(ctx);
|
||||||
|
|
||||||
|
this->cable_icon->frame(ctx);
|
||||||
this->usb_host_speed_lbl->frame(ctx);
|
this->usb_host_speed_lbl->frame(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootView::layout(NVGcontext* vg, brls::Style* style, brls::FontStash* stash)
|
void RootView::layout(NVGcontext* vg, brls::Style* style, brls::FontStash* stash)
|
||||||
{
|
{
|
||||||
int x_pos = 0, y_pos = 0;
|
int x_orig = 0, x_pos = 0, y_pos = 0;
|
||||||
|
|
||||||
brls::AppletFrame::layout(vg, style, stash);
|
brls::AppletFrame::layout(vg, style, stash);
|
||||||
|
|
||||||
|
@ -232,7 +258,7 @@ namespace nxdt::views
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Time label. */
|
/* Time label. */
|
||||||
x_pos = (this->x + this->width - style->AppletFrame.separatorSpacing - style->AppletFrame.footerTextSpacing);
|
x_orig = x_pos = (this->x + this->width - style->AppletFrame.separatorSpacing - style->AppletFrame.footerTextSpacing);
|
||||||
y_pos = this->y + style->AppletFrame.imageTopPadding;
|
y_pos = this->y + style->AppletFrame.imageTopPadding;
|
||||||
|
|
||||||
this->time_lbl->setBoundaries(x_pos, y_pos, 0, 0);
|
this->time_lbl->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
|
@ -259,8 +285,8 @@ namespace nxdt::views
|
||||||
this->battery_icon->setBoundaries(x_pos, y_pos, 0, 0);
|
this->battery_icon->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
this->battery_icon->invalidate();
|
this->battery_icon->invalidate();
|
||||||
|
|
||||||
/* USB host speed labels. */
|
/* UMS device counter and USB host speed labels. */
|
||||||
x_pos = (this->x + this->width - style->AppletFrame.separatorSpacing - style->AppletFrame.footerTextSpacing);
|
x_pos = x_orig;
|
||||||
y_pos += (this->connection_status_lbl->getTextHeight() + 5);
|
y_pos += (this->connection_status_lbl->getTextHeight() + 5);
|
||||||
|
|
||||||
this->usb_host_speed_lbl->setBoundaries(x_pos, y_pos, 0, 0);
|
this->usb_host_speed_lbl->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
|
@ -268,6 +294,16 @@ namespace nxdt::views
|
||||||
|
|
||||||
x_pos -= (5 + this->usb_host_speed_lbl->getTextWidth());
|
x_pos -= (5 + this->usb_host_speed_lbl->getTextWidth());
|
||||||
|
|
||||||
|
this->cable_icon->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
|
this->cable_icon->invalidate();
|
||||||
|
|
||||||
|
x_pos -= (10 + this->cable_icon->getTextWidth());
|
||||||
|
|
||||||
|
this->ums_counter_lbl->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
|
this->ums_counter_lbl->invalidate();
|
||||||
|
|
||||||
|
x_pos -= (5 + this->ums_counter_lbl->getTextWidth());
|
||||||
|
|
||||||
this->usb_icon->setBoundaries(x_pos, y_pos, 0, 0);
|
this->usb_icon->setBoundaries(x_pos, y_pos, 0, 0);
|
||||||
this->usb_icon->invalidate();
|
this->usb_icon->invalidate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,11 @@ namespace nxdt::tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UmsDeviceVector* UmsTask::GetUmsDevices(void)
|
||||||
|
{
|
||||||
|
return &(this->ums_devices);
|
||||||
|
}
|
||||||
|
|
||||||
void UmsTask::PopulateUmsDeviceVector(void)
|
void UmsTask::PopulateUmsDeviceVector(void)
|
||||||
{
|
{
|
||||||
UsbHsFsDevice *ums_devices = NULL;
|
UsbHsFsDevice *ums_devices = NULL;
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace nxdt::views
|
||||||
if (!app_metadata_count) return;
|
if (!app_metadata_count) return;
|
||||||
|
|
||||||
/* Populate list. */
|
/* Populate list. */
|
||||||
for(TitleApplicationMetadata *cur_app_metadata : *app_metadata)
|
for(const TitleApplicationMetadata *cur_app_metadata : *app_metadata)
|
||||||
{
|
{
|
||||||
/* Create list item. */
|
/* Create list item. */
|
||||||
TitlesTabItem *title = new TitlesTabItem(cur_app_metadata, this->is_system);
|
TitlesTabItem *title = new TitlesTabItem(cur_app_metadata, this->is_system);
|
||||||
|
|
Loading…
Reference in a new issue