2018-06-21 07:42:46 +01:00
# include <stdarg.h>
# include <stddef.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/stat.h>
2019-06-05 23:44:18 +01:00
# include <math.h>
2018-06-21 07:42:46 +01:00
# include <switch.h>
2019-04-21 17:27:33 +01:00
# include <ft2build.h>
# include FT_FREETYPE_H
2019-06-05 23:44:18 +01:00
# include <turbojpeg.h>
2018-06-21 07:42:46 +01:00
# include "dumper.h"
2019-06-05 23:44:18 +01:00
# include "fs_ext.h"
2018-06-21 07:42:46 +01:00
# include "ui.h"
# include "util.h"
2019-06-09 02:36:21 +01:00
# include "keys.h"
2018-06-21 07:42:46 +01:00
2019-04-21 17:27:33 +01:00
/* Extern variables */
2019-10-17 21:15:35 +01:00
extern dumpOptions dumpCfg ;
2019-11-06 18:22:40 +00:00
extern bool keysFileAvailable ;
2019-04-23 06:14:57 +01:00
extern AppletType programAppletType ;
2019-12-11 08:56:58 +00:00
extern gamecard_ctx_t gameCardInfo ;
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
extern u32 titleAppCount , titlePatchCount , titleAddOnCount ;
extern u32 sdCardTitleAppCount , sdCardTitlePatchCount , sdCardTitleAddOnCount ;
extern u32 emmcTitleAppCount , emmcTitlePatchCount , emmcTitleAddOnCount ;
2018-06-21 07:42:46 +01:00
2019-12-11 08:56:58 +00:00
extern base_app_ctx_t * baseAppEntries ;
extern patch_addon_ctx_t * patchEntries , * addOnEntries ;
2018-06-21 07:42:46 +01:00
2019-04-21 17:27:33 +01:00
extern char * filenames [ FILENAME_MAX_CNT ] ;
extern int filenamesCount ;
2019-06-05 23:44:18 +01:00
extern char curRomFsPath [ NAME_BUF_LEN ] ;
extern romfs_browser_entry * romFsBrowserEntries ;
2019-12-11 08:56:58 +00:00
extern browser_entry_size_info * hfs0ExeFsEntriesSizes ;
2019-09-15 03:45:27 +01:00
2019-06-09 02:36:21 +01:00
extern orphan_patch_addon_entry * orphanEntries ;
2019-10-17 21:15:35 +01:00
extern char strbuf [ NAME_BUF_LEN ] ;
2019-05-01 21:24:13 +01:00
2019-12-11 08:56:58 +00:00
extern char cfwDirStr [ 32 ] ;
2019-04-21 17:27:33 +01:00
/* Statically allocated variables */
2019-09-15 03:45:27 +01:00
static PlFontData sharedFonts [ PlSharedFontType_Total ] ;
2019-04-21 17:27:33 +01:00
static FT_Library library ;
2019-09-15 03:45:27 +01:00
static FT_Face sharedFontsFaces [ PlSharedFontType_Total ] ;
2019-04-21 17:27:33 +01:00
static Framebuffer fb ;
static u32 * framebuf = NULL ;
static u32 framebuf_width = 0 ;
2019-10-17 21:15:35 +01:00
static const u8 bgColors [ 3 ] = { BG_COLOR_RGB } ;
static const u8 hlBgColors [ 3 ] = { HIGHLIGHT_BG_COLOR_RGB } ;
2019-04-21 17:27:33 +01:00
int cursor = 0 ;
int scroll = 0 ;
int breaks = 0 ;
int font_height = 0 ;
2019-12-11 08:56:58 +00:00
int titleListCursor = 0 , titleListScroll = 0 ;
int orphanListCursor = 0 , orphanListScroll = 0 ;
int browserCursor = 0 , browserScroll = 0 ;
2019-06-20 04:56:14 +01:00
2019-06-09 02:36:21 +01:00
curMenuType menuType ;
static bool orphanMode = false ;
2019-06-20 04:56:14 +01:00
static char titleSelectorStr [ NAME_BUF_LEN ] = { ' \0 ' } ;
2019-09-15 03:45:27 +01:00
static char exeFsAndRomFsSelectorStr [ NAME_BUF_LEN ] = { ' \0 ' } ;
2019-06-28 21:13:54 +01:00
static char dumpedContentInfoStr [ NAME_BUF_LEN ] = { ' \0 ' } ;
2019-06-20 04:56:14 +01:00
2019-06-05 23:44:18 +01:00
static u32 selectedAppInfoIndex = 0 ;
static u32 selectedAppIndex ;
static u32 selectedPatchIndex ;
static u32 selectedAddOnIndex ;
2019-04-23 06:14:57 +01:00
static u32 selectedPartitionIndex ;
static u32 selectedFileIndex ;
2019-06-05 23:44:18 +01:00
static nspDumpType selectedNspDumpType ;
2019-06-28 21:13:54 +01:00
2019-09-15 03:45:27 +01:00
static bool exeFsUpdateFlag = false ;
static selectedRomFsType curRomFsType = ROMFS_TYPE_APP ;
2019-04-23 06:14:57 +01:00
2019-11-06 18:22:40 +00:00
static selectedTicketType curTikType = TICKET_TYPE_APP ;
static bool updatePerformed = false ;
2019-10-17 21:15:35 +01:00
bool highlight = false ;
2019-06-28 21:13:54 +01:00
2018-06-21 07:42:46 +01:00
static char statusMessage [ 2048 ] = { ' \0 ' } ;
static int statusMessageFadeout = 0 ;
2019-12-11 08:56:58 +00:00
extern u64 freeSpace ;
extern char freeSpaceStr [ 32 ] ;
2018-06-21 07:42:46 +01:00
static UIState uiState ;
2019-12-11 08:56:58 +00:00
static bool fb_init = false , romfs_init = false , ft_lib_init = false , ft_faces_init [ PlSharedFontType_Total ] ;
2019-06-09 02:36:21 +01:00
static const char * dirNormalIconPath = " romfs:/browser/dir_normal.jpg " ;
2019-06-05 23:44:18 +01:00
static u8 * dirNormalIconBuf = NULL ;
2019-06-09 02:36:21 +01:00
static const char * dirHighlightIconPath = " romfs:/browser/dir_highlight.jpg " ;
2019-06-05 23:44:18 +01:00
static u8 * dirHighlightIconBuf = NULL ;
2019-06-09 02:36:21 +01:00
static const char * fileNormalIconPath = " romfs:/browser/file_normal.jpg " ;
2019-10-17 21:15:35 +01:00
static u8 * fileNormalIconBuf = NULL ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
static const char * fileHighlightIconPath = " romfs:/browser/file_highlight.jpg " ;
2019-06-05 23:44:18 +01:00
static u8 * fileHighlightIconBuf = NULL ;
2019-10-17 21:15:35 +01:00
static const char * enabledNormalIconPath = " romfs:/browser/enabled_normal.jpg " ;
u8 * enabledNormalIconBuf = NULL ;
static const char * enabledHighlightIconPath = " romfs:/browser/enabled_highlight.jpg " ;
u8 * enabledHighlightIconBuf = NULL ;
static const char * disabledNormalIconPath = " romfs:/browser/disabled_normal.jpg " ;
u8 * disabledNormalIconBuf = NULL ;
static const char * disabledHighlightIconPath = " romfs:/browser/disabled_highlight.jpg " ;
u8 * disabledHighlightIconBuf = NULL ;
2019-12-11 08:56:58 +00:00
static const char * appHeadline = " NXDumpTool v " APP_VERSION " . Built on " __DATE__ " - " __TIME__ " . \n Made by DarkMatterCore. \n \n " ;
2019-06-09 02:36:21 +01:00
static const char * appControlsCommon = " [ " NINTENDO_FONT_DPAD " / " NINTENDO_FONT_LSTICK " / " NINTENDO_FONT_RSTICK " ] Move | [ " NINTENDO_FONT_A " ] Select | [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_PLUS " ] Exit " ;
2019-11-06 18:22:40 +00:00
static const char * appControlsGameCardMultiApp = " [ " NINTENDO_FONT_DPAD " / " NINTENDO_FONT_LSTICK " / " NINTENDO_FONT_RSTICK " ] Move | [ " NINTENDO_FONT_A " ] Select | [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_L " / " NINTENDO_FONT_R " / " NINTENDO_FONT_ZL " / " NINTENDO_FONT_ZR " ] Show info from another base application | [ " NINTENDO_FONT_PLUS " ] Exit " ;
2019-06-09 02:36:21 +01:00
static const char * appControlsNoContent = " [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_PLUS " ] Exit " ;
2019-06-28 21:13:54 +01:00
static const char * appControlsSdCardEmmcFull = " [ " NINTENDO_FONT_DPAD " / " NINTENDO_FONT_LSTICK " / " NINTENDO_FONT_RSTICK " ] Move | [ " NINTENDO_FONT_A " ] Select | [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_X " ] Batch mode | [ " NINTENDO_FONT_Y " ] Dump installed content with missing base application | [ " NINTENDO_FONT_PLUS " ] Exit " ;
static const char * appControlsSdCardEmmcNoApp = " [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_X " ] Batch mode | [ " NINTENDO_FONT_Y " ] Dump installed content with missing base application | [ " NINTENDO_FONT_PLUS " ] Exit " ;
static const char * appControlsRomFs = " [ " NINTENDO_FONT_DPAD " / " NINTENDO_FONT_LSTICK " / " NINTENDO_FONT_RSTICK " ] Move | [ " NINTENDO_FONT_A " ] Select | [ " NINTENDO_FONT_B " ] Back | [ " NINTENDO_FONT_Y " ] Dump current directory | [ " NINTENDO_FONT_PLUS " ] Exit " ;
2018-06-21 07:42:46 +01:00
2019-12-11 08:56:58 +00:00
static const char * mainMenuItems [ ] = { " Dump gamecard content " , " Dump installed SD card / eMMC content " , " Update options " } ;
static const char * gameCardMenuItems [ ] = { " NX Card Image (XCI) dump " , " Nintendo Submission Package (NSP) dump " , " HFS0 options " , " ExeFS options " , " RomFS options " , " Dump gamecard certificate " } ;
static const char * xciDumpMenuItems [ ] = { " Start XCI dump process " , " Split output dump (FAT32 support): " , " Create directory with archive bit set: " , " Keep certificate: " , " Trim output dump: " , " CRC32 checksum calculation + dump verification: " , " Dump verification method: " , " Output naming scheme: " } ;
2019-06-09 02:36:21 +01:00
static const char * nspDumpGameCardMenuItems [ ] = { " Dump base application NSP " , " Dump bundled update NSP " , " Dump bundled DLC NSP " } ;
static const char * nspDumpSdCardEmmcMenuItems [ ] = { " Dump base application NSP " , " Dump installed update NSP " , " Dump installed DLC NSP " } ;
2019-12-11 08:56:58 +00:00
static const char * nspAppDumpMenuItems [ ] = { " Start NSP dump process " , " Split output dump (FAT32 support): " , " Verify dump using No-Intro database: " , " Remove console specific data: " , " Generate ticket-less dump: " , " Change NPDM RSA key/sig in Program NCA: " , " Base application to dump: " , " Output naming scheme: " } ;
static const char * nspPatchDumpMenuItems [ ] = { " Start NSP dump process " , " Split output dump (FAT32 support): " , " Verify dump using No-Intro database: " , " Remove console specific data: " , " Generate ticket-less dump: " , " Change NPDM RSA key/sig in Program NCA: " , " Dump delta fragments: " , " Update to dump: " , " Output naming scheme: " } ;
static const char * nspAddOnDumpMenuItems [ ] = { " Start NSP dump process " , " Split output dump (FAT32 support): " , " Verify dump using No-Intro database: " , " Remove console specific data: " , " Generate ticket-less dump: " , " DLC to dump: " , " Output naming scheme: " } ;
2019-06-05 23:44:18 +01:00
static const char * hfs0MenuItems [ ] = { " Raw HFS0 partition dump " , " HFS0 partition data dump " , " Browse HFS0 partitions " } ;
static const char * hfs0PartitionDumpType1MenuItems [ ] = { " Dump HFS0 partition 0 (Update) " , " Dump HFS0 partition 1 (Normal) " , " Dump HFS0 partition 2 (Secure) " } ;
static const char * hfs0PartitionDumpType2MenuItems [ ] = { " Dump HFS0 partition 0 (Update) " , " Dump HFS0 partition 1 (Logo) " , " Dump HFS0 partition 2 (Normal) " , " Dump HFS0 partition 3 (Secure) " } ;
static const char * hfs0BrowserType1MenuItems [ ] = { " Browse HFS0 partition 0 (Update) " , " Browse HFS0 partition 1 (Normal) " , " Browse HFS0 partition 2 (Secure) " } ;
static const char * hfs0BrowserType2MenuItems [ ] = { " Browse HFS0 partition 0 (Update) " , " Browse HFS0 partition 1 (Logo) " , " Browse HFS0 partition 2 (Normal) " , " Browse HFS0 partition 3 (Secure) " } ;
2019-12-11 08:56:58 +00:00
static const char * exeFsMenuItems [ ] = { " ExeFS section data dump " , " Browse ExeFS section " , " Split files bigger than 4 GiB (FAT32 support): " , " Save data to CFW directory (LayeredFS): " , " Use update: " } ;
2019-06-28 21:13:54 +01:00
static const char * exeFsSectionDumpMenuItems [ ] = { " Start ExeFS data dump process " , " Base application to dump: " , " Use update: " } ;
static const char * exeFsSectionBrowserMenuItems [ ] = { " Browse ExeFS section " , " Base application to browse: " , " Use update: " } ;
2019-12-11 08:56:58 +00:00
static const char * romFsMenuItems [ ] = { " RomFS section data dump " , " Browse RomFS section " , " Split files bigger than 4 GiB (FAT32 support): " , " Save data to CFW directory (LayeredFS): " , " Use update/DLC: " } ;
2019-09-15 03:45:27 +01:00
static const char * romFsSectionDumpMenuItems [ ] = { " Start RomFS data dump process " , " Base application to dump: " , " Use update/DLC: " } ;
static const char * romFsSectionBrowserMenuItems [ ] = { " Browse RomFS section " , " Base application to browse: " , " Use update/DLC: " } ;
2019-11-06 18:22:40 +00:00
static const char * sdCardEmmcMenuItems [ ] = { " Nintendo Submission Package (NSP) dump " , " ExeFS options " , " RomFS options " , " Ticket options " } ;
2019-12-11 08:56:58 +00:00
static const char * batchModeMenuItems [ ] = { " Start batch dump process " , " Dump base applications: " , " Dump updates: " , " Dump DLCs: " , " Split output dumps (FAT32 support): " , " Remove console specific data: " , " Generate ticket-less dumps: " , " Change NPDM RSA key/sig in Program NCA: " , " Dump delta fragments from updates: " , " Skip already dumped titles: " , " Remember dumped titles: " , " Halt dump process on errors: " , " Output naming scheme: " , " Source storage: " } ;
2019-11-06 18:22:40 +00:00
static const char * ticketMenuItems [ ] = { " Start ticket dump " , " Remove console specific data: " , " Use ticket from title: " } ;
2019-06-05 23:44:18 +01:00
static const char * updateMenuItems [ ] = { " Update NSWDB.COM XML database " , " Update application " } ;
2018-06-21 07:42:46 +01:00
2019-12-11 08:56:58 +00:00
static const char * xciChecksumLookupMethods [ ] = { " NSWDB.COM XML database (offline) " , " No-Intro database lookup (online) " } ;
static const char * xciNamingSchemes [ ] = { " TitleName v[TitleVersion] ([TitleID]) " , " TitleName [[TitleID]][v[TitleVersion]] " } ;
static const char * nspNamingSchemes [ ] = { " TitleName v[TitleVersion] ([TitleID]) ([TitleType]) " , " TitleName [[TitleID]][v[TitleVersion]][[TitleType]] " } ;
2018-06-21 07:42:46 +01:00
void uiFill ( int x , int y , int width , int height , u8 r , u8 g , u8 b )
{
2019-04-21 17:27:33 +01:00
/* Perform validity checks */
2019-10-17 21:15:35 +01:00
if ( width < = 0 | | height < = 0 | | ( x + width ) < 0 | | ( y + height ) < 0 | | x > = FB_WIDTH | | y > = FB_HEIGHT ) return ;
2019-04-21 17:27:33 +01:00
2018-06-21 07:42:46 +01:00
if ( x < 0 )
{
width + = x ;
x = 0 ;
}
if ( y < 0 )
{
height + = y ;
y = 0 ;
}
2019-06-05 23:44:18 +01:00
2019-04-21 17:27:33 +01:00
if ( ( x + width ) > = FB_WIDTH ) width = ( FB_WIDTH - x ) ;
2019-06-05 23:44:18 +01:00
2019-04-21 17:27:33 +01:00
if ( ( y + height ) > = FB_HEIGHT ) height = ( FB_HEIGHT - y ) ;
if ( framebuf = = NULL )
{
/* Begin new frame */
u32 stride ;
framebuf = ( u32 * ) framebufferBegin ( & fb , & stride ) ;
framebuf_width = ( stride / sizeof ( u32 ) ) ;
}
u32 lx , ly ;
u32 framex , framey ;
for ( ly = 0 ; ly < height ; ly + + )
{
for ( lx = 0 ; lx < width ; lx + + )
{
framex = ( x + lx ) ;
framey = ( y + ly ) ;
framebuf [ ( framey * framebuf_width ) + framex ] = RGBA8_MAXALPHA ( r , g , b ) ;
}
}
2018-06-21 07:42:46 +01:00
}
2019-06-05 23:44:18 +01:00
void uiDrawIcon ( const u8 * icon , int width , int height , int x , int y )
{
/* Perform validity checks */
if ( ! icon | | ! width | | ! height | | ( x + width ) < 0 | | ( y + height ) < 0 | | x > = FB_WIDTH | | y > = FB_HEIGHT ) return ;
if ( x < 0 )
{
width + = x ;
x = 0 ;
}
if ( y < 0 )
{
height + = y ;
y = 0 ;
}
if ( ( x + width ) > = FB_WIDTH ) width = ( FB_WIDTH - x ) ;
if ( ( y + height ) > = FB_HEIGHT ) height = ( FB_HEIGHT - y ) ;
if ( framebuf = = NULL )
{
/* Begin new frame */
u32 stride ;
framebuf = ( u32 * ) framebufferBegin ( & fb , & stride ) ;
framebuf_width = ( stride / sizeof ( u32 ) ) ;
}
u32 lx , ly ;
u32 framex , framey ;
u32 pos = 0 ;
for ( ly = 0 ; ly < height ; ly + + )
{
for ( lx = 0 ; lx < width ; lx + + )
{
framex = ( x + lx ) ;
framey = ( y + ly ) ;
pos = ( ( ( ly * width ) + lx ) * 3 ) ;
framebuf [ ( framey * framebuf_width ) + framex ] = RGBA8_MAXALPHA ( icon [ pos ] , icon [ pos + 1 ] , icon [ pos + 2 ] ) ;
}
}
}
bool uiLoadJpgFromMem ( u8 * rawJpg , size_t rawJpgSize , int expectedWidth , int expectedHeight , int desiredWidth , int desiredHeight , u8 * * outBuf )
{
if ( ! rawJpg | | ! rawJpgSize | | ! expectedWidth | | ! expectedHeight | | ! desiredWidth | | ! desiredHeight | | ! outBuf )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: invalid parameters to process JPG image buffer! " , __func__ ) ;
2019-06-05 23:44:18 +01:00
return false ;
}
int ret , w , h , samp ;
tjhandle _jpegDecompressor = NULL ;
bool success = false ;
bool foundScalingFactor = false ;
int i , numScalingFactors = 0 , pitch ;
tjscalingfactor * scalingFactors = NULL ;
u8 * jpgScaledBuf = NULL ;
_jpegDecompressor = tjInitDecompress ( ) ;
2019-12-11 08:56:58 +00:00
if ( ! _jpegDecompressor )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: tjInitDecompress failed! " , __func__ ) ;
return success ;
}
ret = tjDecompressHeader2 ( _jpegDecompressor , rawJpg , rawJpgSize , & w , & h , & samp ) ;
if ( ret = = - 1 )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: tjDecompressHeader2 failed! (%d) " , __func__ , ret ) ;
goto out ;
}
if ( w ! = expectedWidth | | h ! = expectedHeight )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: invalid image width/height! " , __func__ ) ;
goto out ;
}
scalingFactors = tjGetScalingFactors ( & numScalingFactors ) ;
if ( ! scalingFactors )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: unable to retrieve scaling factors! " , __func__ ) ;
goto out ;
}
for ( i = 0 ; i < numScalingFactors ; i + + )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( TJSCALED ( expectedWidth , scalingFactors [ i ] ) = = desiredWidth & & TJSCALED ( expectedHeight , scalingFactors [ i ] ) = = desiredHeight )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
foundScalingFactor = true ;
break ;
2019-06-05 23:44:18 +01:00
}
}
2019-12-11 08:56:58 +00:00
if ( ! foundScalingFactor )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: unable to find a valid scaling factor! " , __func__ ) ;
goto out ;
}
pitch = TJPAD ( desiredWidth * tjPixelSize [ TJPF_RGB ] ) ;
jpgScaledBuf = malloc ( pitch * desiredHeight ) ;
if ( ! jpgScaledBuf )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: unable to allocate memory for the scaled RGB image output! " , __func__ ) ;
goto out ;
}
ret = tjDecompress2 ( _jpegDecompressor , rawJpg , rawJpgSize , jpgScaledBuf , desiredWidth , 0 , desiredHeight , TJPF_RGB , TJFLAG_ACCURATEDCT ) ;
if ( ret = = - 1 )
{
free ( jpgScaledBuf ) ;
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: tjDecompress2 failed! (%d) " , __func__ , ret ) ;
goto out ;
}
* outBuf = jpgScaledBuf ;
success = true ;
out :
tjDestroy ( _jpegDecompressor ) ;
2019-06-05 23:44:18 +01:00
return success ;
}
bool uiLoadJpgFromFile ( const char * filename , int expectedWidth , int expectedHeight , int desiredWidth , int desiredHeight , u8 * * outBuf )
{
if ( ! filename | | ! desiredWidth | | ! desiredHeight | | ! outBuf )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: invalid parameters to process JPG image file! " , __func__ ) ;
2019-06-05 23:44:18 +01:00
return false ;
}
u8 * buf = NULL ;
FILE * fp = NULL ;
size_t filesize = 0 , read = 0 ;
fp = fopen ( filename , " rb " ) ;
if ( ! fp )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: failed to open file \" %s \" ! " , __func__ , filename ) ;
2019-06-05 23:44:18 +01:00
return false ;
}
fseek ( fp , 0 , SEEK_END ) ;
filesize = ftell ( fp ) ;
rewind ( fp ) ;
if ( ! filesize )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: file \" %s \" is empty! " , __func__ , filename ) ;
2019-06-05 23:44:18 +01:00
fclose ( fp ) ;
return false ;
}
buf = malloc ( filesize ) ;
if ( ! buf )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: error allocating memory for image \" %s \" ! " , __func__ , filename ) ;
2019-06-05 23:44:18 +01:00
fclose ( fp ) ;
return false ;
}
read = fread ( buf , 1 , filesize , fp ) ;
fclose ( fp ) ;
if ( read ! = filesize )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s: error reading image \" %s \" ! " , __func__ , filename ) ;
2019-06-05 23:44:18 +01:00
free ( buf ) ;
return false ;
}
bool ret = uiLoadJpgFromMem ( buf , filesize , expectedWidth , expectedHeight , desiredWidth , desiredHeight , outBuf ) ;
free ( buf ) ;
return ret ;
}
2019-04-21 17:27:33 +01:00
void uiDrawChar ( FT_Bitmap * bitmap , int x , int y , u8 r , u8 g , u8 b )
2018-06-21 07:42:46 +01:00
{
2019-04-21 17:27:33 +01:00
if ( framebuf = = NULL ) return ;
2019-10-17 21:15:35 +01:00
u32 framex , framey , framebuf_offset ;
2019-04-21 17:27:33 +01:00
u32 tmpx , tmpy ;
u8 * imageptr = bitmap - > buffer ;
u8 src_val ;
float opacity ;
2019-10-17 21:15:35 +01:00
u8 fontR , fontG , fontB ;
2019-04-21 17:27:33 +01:00
if ( bitmap - > pixel_mode ! = FT_PIXEL_MODE_GRAY ) return ;
for ( tmpy = 0 ; tmpy < bitmap - > rows ; tmpy + + )
{
for ( tmpx = 0 ; tmpx < bitmap - > width ; tmpx + + )
{
framex = ( x + tmpx ) ;
framey = ( y + tmpy ) ;
if ( framex > = FB_WIDTH | | framey > = FB_HEIGHT ) continue ;
2019-10-17 21:15:35 +01:00
framebuf_offset = ( ( framey * framebuf_width ) + framex ) ;
2019-04-21 17:27:33 +01:00
src_val = imageptr [ tmpx ] ;
if ( ! src_val )
{
/* Render background color */
2019-10-17 21:15:35 +01:00
framebuf [ framebuf_offset ] = ( highlight ? RGBA8_MAXALPHA ( hlBgColors [ 0 ] , hlBgColors [ 1 ] , hlBgColors [ 2 ] ) : RGBA8_MAXALPHA ( bgColors [ 0 ] , bgColors [ 1 ] , bgColors [ 2 ] ) ) ;
2019-04-21 17:27:33 +01:00
} else {
/* Calculate alpha (opacity) */
opacity = ( src_val / 255.0 ) ;
2019-10-17 21:15:35 +01:00
fontR = ( r * opacity + ( 1 - opacity ) * ( highlight ? hlBgColors [ 0 ] : bgColors [ 0 ] ) ) ;
fontG = ( g * opacity + ( 1 - opacity ) * ( highlight ? hlBgColors [ 1 ] : bgColors [ 1 ] ) ) ;
fontB = ( b * opacity + ( 1 - opacity ) * ( highlight ? hlBgColors [ 2 ] : bgColors [ 2 ] ) ) ;
2019-04-21 17:27:33 +01:00
2019-10-17 21:15:35 +01:00
framebuf [ framebuf_offset ] = RGBA8_MAXALPHA ( fontR , fontG , fontB ) ;
2019-04-21 17:27:33 +01:00
}
}
imageptr + = bitmap - > pitch ;
}
}
2018-06-21 07:42:46 +01:00
2019-10-17 21:15:35 +01:00
void uiDrawString ( int x , int y , u8 r , u8 g , u8 b , const char * fmt , . . . )
2019-05-01 21:24:13 +01:00
{
2019-10-17 21:15:35 +01:00
if ( ! fmt | | ! * fmt ) return ;
2019-05-01 21:24:13 +01:00
2019-10-17 21:15:35 +01:00
char string [ NAME_BUF_LEN ] = { ' \0 ' } ;
2019-05-01 21:24:13 +01:00
2019-10-17 21:15:35 +01:00
va_list args ;
va_start ( args , fmt ) ;
2019-12-11 08:56:58 +00:00
vsnprintf ( string , MAX_CHARACTERS ( string ) , fmt , args ) ;
2019-10-17 21:15:35 +01:00
va_end ( args ) ;
2019-06-05 23:44:18 +01:00
u32 tmpx = ( x < = 8 ? 8 : ( x + 8 ) ) ;
u32 tmpy = ( font_height + ( y < = 8 ? 8 : ( y + 8 ) ) ) ;
2019-09-15 03:45:27 +01:00
2019-04-21 17:27:33 +01:00
FT_Error ret = 0 ;
2019-09-15 03:45:27 +01:00
FT_UInt glyph_index = 0 ;
2019-04-21 17:27:33 +01:00
2019-09-15 03:45:27 +01:00
u32 i , j ;
2019-04-21 17:27:33 +01:00
u32 str_size = strlen ( string ) ;
2019-06-05 23:44:18 +01:00
u32 tmpchar ;
2019-04-21 17:27:33 +01:00
ssize_t unitcount = 0 ;
if ( framebuf = = NULL )
{
/* Begin new frame */
u32 stride ;
framebuf = ( u32 * ) framebufferBegin ( & fb , & stride ) ;
framebuf_width = ( stride / sizeof ( u32 ) ) ;
}
for ( i = 0 ; i < str_size ; )
{
2019-09-15 03:45:27 +01:00
unitcount = decode_utf8 ( & tmpchar , ( const u8 * ) & string [ i ] ) ;
if ( unitcount < = 0 ) break ;
i + = unitcount ;
2019-04-21 17:27:33 +01:00
2019-09-15 03:45:27 +01:00
if ( tmpchar = = ' \n ' )
2019-04-21 17:27:33 +01:00
{
2019-09-15 03:45:27 +01:00
tmpx = 8 ;
2019-10-17 21:15:35 +01:00
tmpy + = LINE_HEIGHT ;
2019-09-15 03:45:27 +01:00
breaks + + ;
continue ;
} else
if ( tmpchar = = ' \t ' )
{
tmpx + = ( font_height * TAB_WIDTH ) ;
continue ;
} else
if ( tmpchar = = ' \r ' )
{
continue ;
2019-04-21 17:27:33 +01:00
}
2019-09-15 03:45:27 +01:00
for ( j = 0 ; j < PlSharedFontType_Total ; j + + )
2019-05-01 21:24:13 +01:00
{
2019-09-15 03:45:27 +01:00
glyph_index = FT_Get_Char_Index ( sharedFontsFaces [ j ] , tmpchar ) ;
if ( glyph_index ) break ;
2019-05-01 21:24:13 +01:00
}
2019-09-15 03:45:27 +01:00
if ( ! glyph_index & & j = = PlSharedFontType_Total ) j = 0 ;
ret = FT_Load_Glyph ( sharedFontsFaces [ j ] , glyph_index , FT_LOAD_DEFAULT ) ;
if ( ret = = 0 ) ret = FT_Render_Glyph ( sharedFontsFaces [ j ] - > glyph , FT_RENDER_MODE_NORMAL ) ;
if ( ret ) break ;
if ( ( tmpx + ( sharedFontsFaces [ j ] - > glyph - > advance . x > > 6 ) ) > = ( FB_WIDTH - 8 ) )
{
tmpx = 8 ;
2019-10-17 21:15:35 +01:00
tmpy + = LINE_HEIGHT ;
2019-09-15 03:45:27 +01:00
breaks + + ;
}
uiDrawChar ( & ( sharedFontsFaces [ j ] - > glyph - > bitmap ) , tmpx + sharedFontsFaces [ j ] - > glyph - > bitmap_left , tmpy - sharedFontsFaces [ j ] - > glyph - > bitmap_top , r , g , b ) ;
tmpx + = ( sharedFontsFaces [ j ] - > glyph - > advance . x > > 6 ) ;
tmpy + = ( sharedFontsFaces [ j ] - > glyph - > advance . y > > 6 ) ;
2019-04-21 17:27:33 +01:00
}
2018-06-21 07:42:46 +01:00
}
2019-10-17 21:15:35 +01:00
u32 uiGetStrWidth ( const char * fmt , . . . )
2019-06-09 02:36:21 +01:00
{
2019-10-17 21:15:35 +01:00
if ( ! fmt | | ! * fmt ) return 0 ;
char string [ NAME_BUF_LEN ] = { ' \0 ' } ;
va_list args ;
va_start ( args , fmt ) ;
2019-12-11 08:56:58 +00:00
vsnprintf ( string , MAX_CHARACTERS ( string ) , fmt , args ) ;
2019-10-17 21:15:35 +01:00
va_end ( args ) ;
2019-06-09 02:36:21 +01:00
FT_Error ret = 0 ;
2019-09-15 03:45:27 +01:00
FT_UInt glyph_index = 0 ;
2019-06-09 02:36:21 +01:00
2019-09-15 03:45:27 +01:00
u32 i , j ;
2019-06-09 02:36:21 +01:00
u32 str_size = strlen ( string ) ;
u32 tmpchar ;
ssize_t unitcount = 0 ;
u32 width = 0 ;
for ( i = 0 ; i < str_size ; )
{
2019-09-15 03:45:27 +01:00
unitcount = decode_utf8 ( & tmpchar , ( const u8 * ) & string [ i ] ) ;
if ( unitcount < = 0 ) break ;
i + = unitcount ;
2019-06-09 02:36:21 +01:00
2019-09-15 03:45:27 +01:00
if ( tmpchar = = ' \n ' | | tmpchar = = ' \r ' )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
continue ;
} else
if ( tmpchar = = ' \t ' )
{
width + = ( font_height * TAB_WIDTH ) ;
continue ;
2019-06-09 02:36:21 +01:00
}
2019-09-15 03:45:27 +01:00
for ( j = 0 ; j < PlSharedFontType_Total ; j + + )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
glyph_index = FT_Get_Char_Index ( sharedFontsFaces [ j ] , tmpchar ) ;
if ( glyph_index ) break ;
2019-06-09 02:36:21 +01:00
}
2019-09-15 03:45:27 +01:00
if ( ! glyph_index & & j = = PlSharedFontType_Total ) j = 0 ;
ret = FT_Load_Glyph ( sharedFontsFaces [ j ] , glyph_index , FT_LOAD_DEFAULT ) ;
if ( ret = = 0 ) ret = FT_Render_Glyph ( sharedFontsFaces [ j ] - > glyph , FT_RENDER_MODE_NORMAL ) ;
if ( ret ) break ;
width + = ( sharedFontsFaces [ j ] - > glyph - > advance . x > > 6 ) ;
2019-06-09 02:36:21 +01:00
}
return width ;
}
2019-04-21 17:27:33 +01:00
void uiRefreshDisplay ( )
2018-06-21 07:42:46 +01:00
{
2019-04-21 17:27:33 +01:00
if ( framebuf ! = NULL )
{
framebufferEnd ( & fb ) ;
framebuf = NULL ;
framebuf_width = 0 ;
}
2018-06-21 07:42:46 +01:00
}
2019-04-21 17:27:33 +01:00
void uiStatusMsg ( const char * fmt , . . . )
2018-06-21 07:42:46 +01:00
{
2019-12-11 08:56:58 +00:00
statusMessageFadeout = 2500 ;
2019-10-17 21:15:35 +01:00
va_list args ;
va_start ( args , fmt ) ;
2019-12-11 08:56:58 +00:00
vsnprintf ( statusMessage , MAX_CHARACTERS ( statusMessage ) , fmt , args ) ;
2019-10-17 21:15:35 +01:00
va_end ( args ) ;
2018-06-21 07:42:46 +01:00
}
2018-06-22 01:46:17 +01:00
void uiUpdateStatusMsg ( )
{
if ( ! strlen ( statusMessage ) | | ! statusMessageFadeout ) return ;
2019-10-17 21:15:35 +01:00
uiFill ( 0 , FB_HEIGHT - ( font_height + STRING_Y_POS ( 1 ) ) , FB_WIDTH , font_height + STRING_Y_POS ( 1 ) , BG_COLOR_RGB ) ;
if ( ( statusMessageFadeout - 4 ) > bgColors [ 0 ] )
2019-04-21 17:27:33 +01:00
{
int fadeout = ( statusMessageFadeout > 255 ? 255 : statusMessageFadeout ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , FB_HEIGHT - ( font_height + STRING_Y_POS ( 1 ) ) , fadeout , fadeout , fadeout , statusMessage ) ;
2019-04-21 17:27:33 +01:00
statusMessageFadeout - = 4 ;
} else {
statusMessageFadeout = 0 ;
}
2018-06-22 01:46:17 +01:00
}
2019-12-11 08:56:58 +00:00
void uiClearStatusMsg ( )
{
statusMessageFadeout = 0 ;
statusMessage [ 0 ] = ' \0 ' ;
}
2019-05-01 21:24:13 +01:00
void uiPleaseWait ( u8 wait )
2018-06-22 01:46:17 +01:00
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Please wait... " ) ;
2019-04-21 17:27:33 +01:00
uiRefreshDisplay ( ) ;
2019-05-01 21:24:13 +01:00
if ( wait ) delay ( wait ) ;
2018-06-22 01:46:17 +01:00
}
2019-04-21 17:27:33 +01:00
void uiClearScreen ( )
2018-06-21 07:42:46 +01:00
{
2019-10-17 21:15:35 +01:00
uiFill ( 0 , 0 , FB_WIDTH , FB_HEIGHT , BG_COLOR_RGB ) ;
2018-06-21 07:42:46 +01:00
}
2019-04-21 17:27:33 +01:00
void uiPrintHeadline ( )
2018-06-21 07:42:46 +01:00
{
2019-05-01 21:24:13 +01:00
breaks = 0 ;
2019-04-21 17:27:33 +01:00
uiClearScreen ( ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_DEFAULT_POS , FONT_COLOR_RGB , appHeadline ) ;
2018-06-21 07:42:46 +01:00
}
2019-10-17 21:15:35 +01:00
void uiPrintOption ( int x , int y , int endPosition , bool leftArrow , bool rightArrow , int r , int g , int b , const char * fmt , . . . )
2019-06-20 04:56:14 +01:00
{
2019-10-17 21:15:35 +01:00
if ( x < 8 | | x > = OPTIONS_X_END_POS | | y < 8 | | y > = ( FB_HEIGHT - 8 - font_height ) | | endPosition < OPTIONS_X_END_POS | | endPosition > = ( FB_WIDTH - 8 ) | | ! fmt | | ! * fmt ) return ;
2019-06-20 04:56:14 +01:00
int xpos = x ;
2019-10-17 21:15:35 +01:00
char option [ NAME_BUF_LEN ] = { ' \0 ' } ;
va_list args ;
va_start ( args , fmt ) ;
2019-12-11 08:56:58 +00:00
vsnprintf ( option , MAX_CHARACTERS ( option ) , fmt , args ) ;
2019-10-17 21:15:35 +01:00
va_end ( args ) ;
2019-06-20 04:56:14 +01:00
u32 optionStrWidth = uiGetStrWidth ( option ) ;
2019-10-17 21:15:35 +01:00
if ( leftArrow ) uiDrawString ( xpos , y , FONT_COLOR_RGB , " < " ) ;
2019-06-20 04:56:14 +01:00
xpos + = uiGetStrWidth ( " < " ) ;
2019-06-28 21:13:54 +01:00
xpos + = ( ( ( endPosition - xpos ) / 2 ) - ( optionStrWidth / 2 ) ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( xpos , y , r , g , b , option ) ;
2019-06-28 21:13:54 +01:00
if ( rightArrow )
{
xpos = endPosition ;
2019-10-17 21:15:35 +01:00
uiDrawString ( xpos , y , FONT_COLOR_RGB , " > " ) ;
2019-06-28 21:13:54 +01:00
}
}
void uiTruncateOptionStr ( char * str , int x , int y , int endPosition )
{
if ( ! str | | ! strlen ( str ) | | x < 8 | | x > = OPTIONS_X_END_POS | | y < 8 | | y > = ( FB_HEIGHT - 8 - font_height ) | | endPosition < OPTIONS_X_END_POS | | endPosition > = ( FB_WIDTH - 8 ) ) return ;
int xpos = x ;
char * option = str ;
u32 optionStrWidth = uiGetStrWidth ( option ) ;
2019-06-20 04:56:14 +01:00
// Check if we're dealing with a long title selector string
2019-06-28 21:13:54 +01:00
if ( optionStrWidth > = ( endPosition - xpos - ( font_height * 2 ) ) )
2019-06-20 04:56:14 +01:00
{
while ( optionStrWidth > = ( endPosition - xpos - ( font_height * 2 ) ) )
{
option + + ;
optionStrWidth = uiGetStrWidth ( option ) ;
}
option [ 0 ] = option [ 1 ] = option [ 2 ] = ' . ' ;
2019-06-28 21:13:54 +01:00
memmove ( str , option , strlen ( option ) ) ;
2019-06-20 04:56:14 +01:00
2019-06-28 21:13:54 +01:00
str [ strlen ( option ) ] = ' \0 ' ;
2019-06-20 04:56:14 +01:00
}
}
2019-12-11 08:56:58 +00:00
bool uiInit ( )
2018-06-21 07:42:46 +01:00
{
2019-12-11 08:56:58 +00:00
Result result = 0 ;
2019-04-21 17:27:33 +01:00
FT_Error ret = 0 ;
2019-09-15 03:45:27 +01:00
u32 i ;
2019-12-11 08:56:58 +00:00
bool success = false ;
char tmp [ 256 ] = { ' \0 ' } ;
2019-06-05 23:44:18 +01:00
/* Set initial UI state */
uiState = stateMainMenu ;
2019-06-09 02:36:21 +01:00
menuType = MENUTYPE_MAIN ;
2019-06-05 23:44:18 +01:00
cursor = 0 ;
scroll = 0 ;
2019-12-11 08:56:58 +00:00
/* Clear FreeType init flags */
memset ( ft_faces_init , 0 , PlSharedFontType_Total ) ;
2019-06-05 23:44:18 +01:00
2019-09-15 03:45:27 +01:00
/* Retrieve shared fonts */
for ( i = 0 ; i < PlSharedFontType_Total ; i + + )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
result = plGetSharedFontByType ( & sharedFonts [ i ] , i ) ;
if ( R_FAILED ( result ) ) break ;
2019-06-05 23:44:18 +01:00
}
2019-04-21 17:27:33 +01:00
2019-12-11 08:56:58 +00:00
if ( R_FAILED ( result ) )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
consoleErrorScreen ( " %s: plGetSharedFontByType() failed to retrieve shared font #%u! (0x%08X) " , __func__ , i , result ) ;
2019-06-05 23:44:18 +01:00
goto out ;
2019-04-21 17:27:33 +01:00
}
/* Initialize FreeType */
ret = FT_Init_FreeType ( & library ) ;
if ( ret )
{
2019-12-11 08:56:58 +00:00
consoleErrorScreen ( " %s: FT_Init_FreeType() failed! (%d) " , __func__ , ret ) ;
2019-06-05 23:44:18 +01:00
goto out ;
2019-04-21 17:27:33 +01:00
}
2019-06-05 23:44:18 +01:00
ft_lib_init = true ;
2019-09-15 03:45:27 +01:00
/* Create memory faces for the shared fonts */
for ( i = 0 ; i < PlSharedFontType_Total ; i + + )
2019-04-21 17:27:33 +01:00
{
2019-09-15 03:45:27 +01:00
ret = FT_New_Memory_Face ( library , sharedFonts [ i ] . address , sharedFonts [ i ] . size , 0 , & sharedFontsFaces [ i ] ) ;
if ( ret ) break ;
ft_faces_init [ i ] = true ;
2019-04-21 17:27:33 +01:00
}
if ( ret )
{
2019-12-11 08:56:58 +00:00
consoleErrorScreen ( " %s: FT_New_Memory_Face() failed to create memory face for shared font #%u! (%d) " , __func__ , i , ret ) ;
2019-06-05 23:44:18 +01:00
goto out ;
2019-04-21 17:27:33 +01:00
}
2019-09-15 03:45:27 +01:00
/* Set character size for all shared fonts */
for ( i = 0 ; i < PlSharedFontType_Total ; i + + )
2019-06-05 23:44:18 +01:00
{
2019-09-15 03:45:27 +01:00
ret = FT_Set_Char_Size ( sharedFontsFaces [ i ] , 0 , CHAR_PT_SIZE * 64 , SCREEN_DPI_CNT , SCREEN_DPI_CNT ) ;
if ( ret ) break ;
2019-06-05 23:44:18 +01:00
}
2019-04-21 17:27:33 +01:00
2019-06-05 23:44:18 +01:00
if ( ret )
{
2019-12-11 08:56:58 +00:00
consoleErrorScreen ( " %s: FT_Set_Char_Size() failed to set character size for shared font #%u! (%d) " , __func__ , i , ret ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
2019-09-15 03:45:27 +01:00
/* Store font height */
font_height = ( sharedFontsFaces [ 0 ] - > size - > metrics . height / 64 ) ;
2019-04-21 17:27:33 +01:00
2019-06-05 23:44:18 +01:00
/* Mount Application's RomFS */
2019-12-11 08:56:58 +00:00
result = romfsInit ( ) ;
if ( R_FAILED ( result ) )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
consoleErrorScreen ( " %s: romfsInit() failed! (0x%08X) " , __func__ , result ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
romfs_init = true ;
if ( ! uiLoadJpgFromFile ( dirNormalIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & dirNormalIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load directory icon (normal)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( dirHighlightIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & dirHighlightIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load directory icon (highlighted)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( fileNormalIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & fileNormalIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load file icon (normal)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( fileHighlightIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & fileHighlightIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load file icon (highlighted)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-06-05 23:44:18 +01:00
goto out ;
}
2019-10-17 21:15:35 +01:00
if ( ! uiLoadJpgFromFile ( enabledNormalIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & enabledNormalIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load enabled icon (normal)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-10-17 21:15:35 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( enabledHighlightIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & enabledHighlightIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load enabled icon (highlighted)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-10-17 21:15:35 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( disabledNormalIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & disabledNormalIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load disabled icon (normal)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-10-17 21:15:35 +01:00
goto out ;
}
if ( ! uiLoadJpgFromFile ( disabledHighlightIconPath , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , & disabledHighlightIconBuf ) )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " \n %s: failed to load disabled icon (highlighted)! " , __func__ ) ;
strcat ( strbuf , tmp ) ;
consoleErrorScreen ( strbuf ) ;
2019-10-17 21:15:35 +01:00
goto out ;
}
2019-06-05 23:44:18 +01:00
/* Unmount Application's RomFS */
romfsExit ( ) ;
romfs_init = false ;
/* Create framebuffer */
framebufferCreate ( & fb , nwindowGetDefault ( ) , FB_WIDTH , FB_HEIGHT , PIXEL_FORMAT_RGBA_8888 , 2 ) ;
framebufferMakeLinear ( & fb ) ;
2019-12-11 08:56:58 +00:00
fb_init = true ;
2019-04-23 06:14:57 +01:00
2019-04-21 17:27:33 +01:00
/* Clear screen */
uiClearScreen ( ) ;
2019-06-05 23:44:18 +01:00
/* Set output status */
2019-12-11 08:56:58 +00:00
success = true ;
2019-06-05 23:44:18 +01:00
out :
2019-12-11 08:56:58 +00:00
return success ;
2018-06-21 07:42:46 +01:00
}
2019-04-21 17:27:33 +01:00
void uiDeinit ( )
2018-06-21 07:42:46 +01:00
{
2019-04-21 17:27:33 +01:00
/* Free framebuffer object */
2019-12-11 08:56:58 +00:00
if ( fb_init ) framebufferClose ( & fb ) ;
2019-04-21 17:27:33 +01:00
2019-10-17 21:15:35 +01:00
/* Free enabled/disabled icons (batch mode summary list) */
2019-12-11 08:56:58 +00:00
if ( disabledHighlightIconBuf ) free ( disabledHighlightIconBuf ) ;
if ( disabledNormalIconBuf ) free ( disabledNormalIconBuf ) ;
if ( enabledHighlightIconBuf ) free ( enabledHighlightIconBuf ) ;
if ( enabledNormalIconBuf ) free ( enabledNormalIconBuf ) ;
2019-10-17 21:15:35 +01:00
2019-06-05 23:44:18 +01:00
/* Free directory/file icons */
2019-12-11 08:56:58 +00:00
if ( fileHighlightIconBuf ) free ( fileHighlightIconBuf ) ;
if ( fileNormalIconBuf ) free ( fileNormalIconBuf ) ;
if ( dirHighlightIconBuf ) free ( dirHighlightIconBuf ) ;
if ( dirNormalIconBuf ) free ( dirNormalIconBuf ) ;
2019-09-15 03:45:27 +01:00
2019-12-11 08:56:58 +00:00
/* Unmount Application's RomFS */
if ( romfs_init ) romfsExit ( ) ;
2019-06-05 23:44:18 +01:00
2019-04-21 17:27:33 +01:00
/* Free FreeType resources */
2019-12-11 08:56:58 +00:00
for ( u32 i = 0 ; i < PlSharedFontType_Total ; i + + )
{
if ( ft_faces_init [ i ] ) FT_Done_Face ( sharedFontsFaces [ i ] ) ;
}
2019-04-21 17:27:33 +01:00
2019-12-11 08:56:58 +00:00
if ( ft_lib_init ) FT_Done_FreeType ( library ) ;
2018-06-21 07:42:46 +01:00
}
2019-04-21 17:27:33 +01:00
void uiSetState ( UIState state )
2018-06-22 01:46:17 +01:00
{
2019-06-20 04:56:14 +01:00
if ( uiState = = stateSdCardEmmcMenu )
{
if ( state ! = stateMainMenu )
{
// Store current cursor/scroll values
titleListCursor = cursor ;
titleListScroll = scroll ;
} else {
// Reset title list cursor/scroll values
titleListCursor = 0 ;
titleListScroll = 0 ;
}
} else
if ( uiState = = stateSdCardEmmcOrphanPatchAddOnMenu )
{
if ( state ! = stateSdCardEmmcMenu )
{
// Store current cursor/scroll values
orphanListCursor = cursor ;
orphanListScroll = scroll ;
} else {
// Reset orphan list cursor/scroll values
orphanListCursor = 0 ;
orphanListScroll = 0 ;
}
2019-12-11 08:56:58 +00:00
} else
if ( uiState = = stateHfs0Browser | | uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsSectionBrowser )
{
if ( ( uiState = = stateHfs0Browser & & state ! = stateHfs0BrowserMenu ) | | ( uiState = = stateExeFsSectionBrowser & & state ! = stateExeFsSectionBrowserMenu & & state ! = stateExeFsMenu ) | | ( uiState = = stateRomFsSectionBrowser & & state ! = stateRomFsSectionBrowserMenu & & state ! = stateRomFsMenu & & state ! = stateRomFsSectionBrowserChangeDir ) )
{
// Store current cursor/scroll values
browserCursor = cursor ;
browserScroll = scroll ;
} else {
// Reset browser cursor/scroll values
browserCursor = 0 ;
browserScroll = 0 ;
}
2019-06-20 04:56:14 +01:00
}
2019-04-21 17:27:33 +01:00
uiState = state ;
2019-06-20 04:56:14 +01:00
if ( state = = stateSdCardEmmcMenu )
{
// Override cursor/scroll values
cursor = titleListCursor ;
scroll = titleListScroll ;
} else
if ( state = = stateSdCardEmmcOrphanPatchAddOnMenu )
{
// Override cursor/scroll values
cursor = orphanListCursor ;
scroll = orphanListScroll ;
2019-12-11 08:56:58 +00:00
} else
if ( uiState = = stateHfs0Browser | | uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsSectionBrowser )
{
// Override cursor/scroll values
cursor = browserCursor ;
scroll = browserScroll ;
2019-06-20 04:56:14 +01:00
} else {
cursor = 0 ;
scroll = 0 ;
}
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2018-06-22 01:46:17 +01:00
}
2019-04-21 17:27:33 +01:00
UIState uiGetState ( )
2018-06-21 07:42:46 +01:00
{
2019-04-21 17:27:33 +01:00
return uiState ;
2018-06-21 07:42:46 +01:00
}
2019-04-21 17:27:33 +01:00
UIResult uiProcess ( )
2018-06-21 07:42:46 +01:00
{
2019-04-21 17:27:33 +01:00
UIResult res = resultNone ;
int i , j ;
const char * * menu = NULL ;
int menuItemsCount = 0 ;
2019-12-11 08:56:58 +00:00
u64 keysDown = 0 , keysHeld = 0 ;
2019-04-21 17:27:33 +01:00
2019-06-05 23:44:18 +01:00
int scrollAmount = 0 ;
2019-06-20 04:56:14 +01:00
bool scrollWithKeysDown = false ;
2019-06-05 23:44:18 +01:00
u32 patch , addon , xpos , ypos , startYPos ;
2019-10-17 21:15:35 +01:00
int maxElements = ( uiState = = stateSdCardEmmcMenu ? SDCARD_MAX_ELEMENTS : ( uiState = = stateSdCardEmmcOrphanPatchAddOnMenu ? ORPHAN_MAX_ELEMENTS : ( uiState = = stateHfs0Browser ? HFS0_MAX_ELEMENTS : ( ( uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsSectionBrowser ) ? ROMFS_MAX_ELEMENTS : ( uiState = = stateSdCardEmmcBatchModeMenu ? BATCH_MAX_ELEMENTS : COMMON_MAX_ELEMENTS ) ) ) ) ) ;
2019-06-20 04:56:14 +01:00
const char * upwardsArrow = UPWARDS_ARROW ;
const char * downwardsArrow = DOWNWARDS_ARROW ;
2019-06-28 21:13:54 +01:00
bool forcedXciDump = false ;
2019-04-21 17:27:33 +01:00
uiPrintHeadline ( ) ;
2019-06-09 02:36:21 +01:00
loadTitleInfo ( ) ;
2019-04-21 17:27:33 +01:00
2019-11-06 18:22:40 +00:00
if ( uiState = = stateMainMenu | | uiState = = stateGameCardMenu | | uiState = = stateXciDumpMenu | | uiState = = stateNspDumpMenu | | uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu | | uiState = = stateHfs0Menu | | uiState = = stateRawHfs0PartitionDumpMenu | | uiState = = stateHfs0PartitionDataDumpMenu | | uiState = = stateHfs0BrowserMenu | | uiState = = stateHfs0Browser | | uiState = = stateExeFsMenu | | uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu | | uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsMenu | | uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu | | uiState = = stateRomFsSectionBrowser | | uiState = = stateSdCardEmmcMenu | | uiState = = stateSdCardEmmcTitleMenu | | uiState = = stateSdCardEmmcOrphanPatchAddOnMenu | | uiState = = stateSdCardEmmcBatchModeMenu | | uiState = = stateTicketMenu | | uiState = = stateUpdateMenu )
2019-04-21 17:27:33 +01:00
{
2019-06-09 02:36:21 +01:00
switch ( menuType )
{
case MENUTYPE_MAIN :
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsCommon ) ;
2019-06-09 02:36:21 +01:00
break ;
case MENUTYPE_GAMECARD :
2019-06-28 21:13:54 +01:00
if ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) > 1 )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsRomFs ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , ( ! gameCardInfo . isInserted ? appControlsNoContent : ( titleAppCount > 1 ? appControlsGameCardMultiApp : appControlsCommon ) ) ) ;
2019-06-28 21:13:54 +01:00
}
2019-06-09 02:36:21 +01:00
break ;
case MENUTYPE_SDCARD_EMMC :
2019-09-15 03:45:27 +01:00
if ( uiState = = stateSdCardEmmcBatchModeMenu )
2019-06-09 02:36:21 +01:00
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsCommon ) ;
2019-06-09 02:36:21 +01:00
} else {
2019-09-15 03:45:27 +01:00
if ( ! orphanMode )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
if ( titleAppCount )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcMenu & & ( calculateOrphanPatchOrAddOnCount ( false ) | | calculateOrphanPatchOrAddOnCount ( true ) ) )
2019-09-15 03:45:27 +01:00
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsSdCardEmmcFull ) ;
2019-11-06 18:22:40 +00:00
breaks + = 2 ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Hint: installed updates/DLCs for gamecard titles can be found in the orphan title list (press the " NINTENDO_FONT_Y " button). " ) ;
2019-09-15 03:45:27 +01:00
} else
if ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) > 1 )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsRomFs ) ;
2019-09-15 03:45:27 +01:00
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsCommon ) ;
2019-09-15 03:45:27 +01:00
}
2019-06-09 02:36:21 +01:00
} else {
2019-09-15 03:45:27 +01:00
if ( titlePatchCount | | titleAddOnCount )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsSdCardEmmcNoApp ) ;
2019-09-15 03:45:27 +01:00
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsNoContent ) ;
2019-09-15 03:45:27 +01:00
}
2019-06-09 02:36:21 +01:00
}
} else {
2019-09-15 03:45:27 +01:00
if ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) > 1 )
2019-06-09 02:36:21 +01:00
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsRomFs ) ;
2019-06-09 02:36:21 +01:00
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , appControlsCommon ) ;
2019-06-09 02:36:21 +01:00
}
}
}
break ;
default :
break ;
}
2019-04-21 17:27:33 +01:00
2019-06-09 02:36:21 +01:00
breaks + = 2 ;
2019-12-11 08:56:58 +00:00
}
if ( uiState ! = stateSdCardEmmcBatchDump )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Free SD card space: %s (%lu bytes). " , freeSpaceStr , freeSpace ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-06-05 23:44:18 +01:00
}
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( ! gameCardInfo . isInserted | | ! gameCardInfo . rootHfs0Header | | ( gameCardInfo . hfs0PartitionCnt ! = GAMECARD_TYPE1_PARTITION_CNT & & gameCardInfo . hfs0PartitionCnt ! = GAMECARD_TYPE2_PARTITION_CNT ) | | ! titleAppCount | | ! baseAppEntries )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
if ( gameCardInfo . isInserted )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
if ( gameCardInfo . rootHfs0Header )
2019-05-01 21:24:13 +01:00
{
2019-12-11 08:56:58 +00:00
if ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT | | gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE2_PARTITION_CNT )
2019-05-01 21:24:13 +01:00
{
2019-06-28 21:13:54 +01:00
forcedXciDump = true ;
2019-12-11 08:56:58 +00:00
if ( titleAppCount )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " Error: unable to retrieve title entries from the inserted gamecard! " ) ;
2019-06-05 23:44:18 +01:00
2019-12-11 08:56:58 +00:00
if ( strlen ( gameCardInfo . updateVersionStr ) )
2019-06-09 02:36:21 +01:00
{
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Bundled FW Update: %s " , gameCardInfo . updateVersionStr ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " In order to be able to dump data from this gamecard, make sure your console is at least on this FW version. " ) ;
2019-06-09 02:36:21 +01:00
}
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " Error: gamecard application count is zero! " ) ;
2019-06-05 23:44:18 +01:00
}
} else {
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " Error: unknown root HFS0 header partition count! (%u) " , gameCardInfo . hfs0PartitionCnt ) ;
2019-06-05 23:44:18 +01:00
}
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " Error: unable to get root HFS0 header data! " ) ;
2019-06-05 23:44:18 +01:00
}
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " Gamecard is not inserted! " ) ;
2019-06-05 23:44:18 +01:00
}
2019-06-09 02:36:21 +01:00
2019-11-06 18:22:40 +00:00
breaks + = 2 ;
2019-12-11 08:56:58 +00:00
if ( gameCardInfo . isInserted )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( forcedXciDump )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Press " NINTENDO_FONT_Y " to dump the gamecard to \" gamecard.xci \" . " ) ;
} else {
if ( ! gameCardInfo . rootHfs0Header ) uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Are you using \" nogc \" spoofing in your CFW? If so, please consider this option disables all gamecard I/O. " ) ;
}
2019-06-28 21:13:54 +01:00
}
2019-06-09 02:36:21 +01:00
uiUpdateStatusMsg ( ) ;
uiRefreshDisplay ( ) ;
res = resultShowGameCardMenu ;
hidScanInput ( ) ;
keysDown = hidKeysDown ( CONTROLLER_P1_AUTO ) ;
// Exit
if ( keysDown & KEY_PLUS ) res = resultExit ;
// Back
if ( keysDown & KEY_B )
{
res = resultShowMainMenu ;
menuType = MENUTYPE_MAIN ;
}
2019-06-28 21:13:54 +01:00
// Forced XCI dump
if ( ( keysDown & KEY_Y ) & & forcedXciDump )
{
uiPrintHeadline ( ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 0 ] ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
uiRefreshDisplay ( ) ;
// Set default options
2019-10-17 21:15:35 +01:00
xciOptions xciDumpCfg ;
2019-12-11 08:56:58 +00:00
memset ( & xciDumpCfg , 0 , sizeof ( xciOptions ) ) ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
xciDumpCfg . isFat32 = true ;
xciDumpCfg . keepCert = true ;
2019-12-11 08:56:58 +00:00
dumpNXCardImage ( & xciDumpCfg ) ;
2019-06-28 21:13:54 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-28 21:13:54 +01:00
}
2019-06-09 02:36:21 +01:00
return res ;
2019-06-05 23:44:18 +01:00
}
2019-06-09 02:36:21 +01:00
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
2019-06-05 23:44:18 +01:00
{
2019-09-15 03:45:27 +01:00
if ( ! titleAppCount & & ! orphanMode )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( titlePatchCount | | titleAddOnCount )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " No base applications available in the SD card / eMMC storage! " ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-11-06 18:22:40 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Use the " NINTENDO_FONT_Y " button to dump installed content with missing base applications! " ) ;
2019-06-09 02:36:21 +01:00
} else {
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_ERROR_RGB , " No titles available in the SD card / eMMC storage! " ) ;
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
uiUpdateStatusMsg ( ) ;
uiRefreshDisplay ( ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
res = resultShowSdCardEmmcMenu ;
hidScanInput ( ) ;
keysDown = hidKeysDown ( CONTROLLER_P1_AUTO ) ;
// Exit
if ( keysDown & KEY_PLUS ) res = resultExit ;
// Back
if ( keysDown & KEY_B )
{
res = resultShowMainMenu ;
menuType = MENUTYPE_MAIN ;
}
// Dump installed content with missing base application
if ( ( titlePatchCount | | titleAddOnCount ) & & ( keysDown & KEY_Y ) )
{
res = resultShowSdCardEmmcOrphanPatchAddOnMenu ;
orphanMode = true ;
}
return res ;
}
}
2019-11-06 18:22:40 +00:00
if ( uiState = = stateMainMenu | | uiState = = stateGameCardMenu | | uiState = = stateXciDumpMenu | | uiState = = stateNspDumpMenu | | uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu | | uiState = = stateHfs0Menu | | uiState = = stateRawHfs0PartitionDumpMenu | | uiState = = stateHfs0PartitionDataDumpMenu | | uiState = = stateHfs0BrowserMenu | | uiState = = stateHfs0Browser | | uiState = = stateExeFsMenu | | uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu | | uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsMenu | | uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu | | uiState = = stateRomFsSectionBrowser | | uiState = = stateSdCardEmmcMenu | | uiState = = stateSdCardEmmcTitleMenu | | uiState = = stateSdCardEmmcOrphanPatchAddOnMenu | | uiState = = stateSdCardEmmcBatchModeMenu | | uiState = = stateTicketMenu | | uiState = = stateUpdateMenu )
2019-06-09 02:36:21 +01:00
{
2019-06-28 21:13:54 +01:00
if ( ( menuType = = MENUTYPE_GAMECARD & & uiState ! = stateHfs0Browser & & uiState ! = stateExeFsSectionBrowser & & uiState ! = stateRomFsSectionBrowser ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & uiState ! = stateSdCardEmmcMenu & & uiState ! = stateSdCardEmmcBatchModeMenu & & uiState ! = stateExeFsSectionBrowser & & uiState ! = stateRomFsSectionBrowser ) )
2019-06-09 02:36:21 +01:00
{
2019-06-05 23:44:18 +01:00
/* Print application info */
2019-10-17 21:15:35 +01:00
xpos = STRING_X_POS ;
ypos = STRING_Y_POS ( breaks ) ;
2019-06-05 23:44:18 +01:00
startYPos = ypos ;
/* Draw icon */
2019-12-11 08:56:58 +00:00
if ( baseAppEntries [ selectedAppInfoIndex ] . icon ! = NULL )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawIcon ( baseAppEntries [ selectedAppInfoIndex ] . icon , NACP_ICON_DOWNSCALED , NACP_ICON_DOWNSCALED , xpos , ypos + 8 ) ;
2019-06-05 23:44:18 +01:00
xpos + = ( NACP_ICON_DOWNSCALED + 8 ) ;
ypos + = 8 ;
}
2019-12-11 08:56:58 +00:00
if ( strlen ( baseAppEntries [ selectedAppInfoIndex ] . name ) )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( xpos , ypos , FONT_COLOR_SUCCESS_RGB , " Name: %s " , baseAppEntries [ selectedAppInfoIndex ] . name ) ;
2019-10-17 21:15:35 +01:00
ypos + = LINE_HEIGHT ;
2019-06-05 23:44:18 +01:00
}
2019-12-11 08:56:58 +00:00
if ( strlen ( baseAppEntries [ selectedAppInfoIndex ] . author ) )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( xpos , ypos , FONT_COLOR_SUCCESS_RGB , " Publisher: %s " , baseAppEntries [ selectedAppInfoIndex ] . author ) ;
2019-10-17 21:15:35 +01:00
ypos + = LINE_HEIGHT ;
2019-06-05 23:44:18 +01:00
}
2019-12-11 08:56:58 +00:00
uiDrawString ( xpos , ypos , FONT_COLOR_SUCCESS_RGB , " Title ID: %016lX " , baseAppEntries [ selectedAppInfoIndex ] . titleId ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
if ( titlePatchCount > 0 )
2019-06-05 23:44:18 +01:00
{
u32 patchCnt = 0 ;
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s update(s): v " , ( menuType = = MENUTYPE_GAMECARD ? " Bundled " : " Installed " ) ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
for ( patch = 0 ; patch < titlePatchCount ; patch + + )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( checkIfPatchOrAddOnBelongsToBaseApplication ( patch , selectedAppInfoIndex , false ) & & ( ( menuType = = MENUTYPE_GAMECARD & & baseAppEntries [ selectedAppInfoIndex ] . storageId = = patchEntries [ patch ] . storageId ) | | menuType = = MENUTYPE_SDCARD_EMMC ) )
2019-06-05 23:44:18 +01:00
{
if ( patchCnt > 0 ) strcat ( strbuf , " , v " ) ;
2019-12-11 08:56:58 +00:00
strcat ( strbuf , patchEntries [ patch ] . versionStr ) ;
2019-06-05 23:44:18 +01:00
patchCnt + + ;
}
}
2019-10-17 21:15:35 +01:00
if ( patchCnt > 0 ) uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , ypos , FONT_COLOR_SUCCESS_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
}
2019-10-17 21:15:35 +01:00
ypos + = LINE_HEIGHT ;
2019-06-05 23:44:18 +01:00
2019-12-11 08:56:58 +00:00
uiDrawString ( xpos , ypos , FONT_COLOR_SUCCESS_RGB , " Version: %s " , baseAppEntries [ selectedAppInfoIndex ] . versionStr ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
if ( titleAddOnCount > 0 )
2019-06-05 23:44:18 +01:00
{
u32 addOnCnt = 0 ;
2019-06-09 02:36:21 +01:00
for ( addon = 0 ; addon < titleAddOnCount ; addon + + )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( checkIfPatchOrAddOnBelongsToBaseApplication ( addon , selectedAppInfoIndex , true ) & & ( ( menuType = = MENUTYPE_GAMECARD & & baseAppEntries [ selectedAppInfoIndex ] . storageId = = addOnEntries [ addon ] . storageId ) | | menuType = = MENUTYPE_SDCARD_EMMC ) ) addOnCnt + + ;
2019-05-01 21:24:13 +01:00
}
2019-04-21 17:27:33 +01:00
2019-12-11 08:56:58 +00:00
if ( addOnCnt > 0 ) uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , ypos , FONT_COLOR_SUCCESS_RGB , " %s DLC(s): %u " , ( menuType = = MENUTYPE_GAMECARD ? " Bundled " : " Installed " ) , addOnCnt ) ;
2019-06-05 23:44:18 +01:00
}
2019-12-11 08:56:58 +00:00
ypos + = LINE_HEIGHT ;
2019-06-05 23:44:18 +01:00
ypos + = 8 ;
if ( xpos > 8 & & ( ypos - NACP_ICON_DOWNSCALED ) < startYPos ) ypos + = ( NACP_ICON_DOWNSCALED - ( ypos - startYPos ) ) ;
2019-10-17 21:15:35 +01:00
ypos + = LINE_HEIGHT ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
breaks + = ( int ) round ( ( double ) ( ypos - startYPos ) / ( double ) LINE_HEIGHT ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Capacity: %s | Used space: %s " , gameCardInfo . sizeStr , gameCardInfo . trimmedSizeStr ) ;
2019-06-09 02:36:21 +01:00
2019-12-11 08:56:58 +00:00
if ( titleAppCount > 1 )
{
if ( baseAppEntries [ selectedAppInfoIndex ] . contentSize )
{
uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Base application count: %u | Base application displayed: %u | Content size: %s " , titleAppCount , selectedAppInfoIndex + 1 , baseAppEntries [ selectedAppInfoIndex ] . contentSizeStr ) ;
} else {
uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Base application count: %u | Base application displayed: %u " , titleAppCount , selectedAppInfoIndex + 1 ) ;
}
} else {
if ( baseAppEntries [ selectedAppInfoIndex ] . contentSize ) uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Content size: %s " , baseAppEntries [ selectedAppInfoIndex ] . contentSizeStr ) ;
}
2019-06-09 02:36:21 +01:00
2019-04-21 17:27:33 +01:00
breaks + + ;
2019-06-09 02:36:21 +01:00
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Partition count: %u (%s) " , gameCardInfo . hfs0PartitionCnt , GAMECARD_TYPE ( gameCardInfo . hfs0PartitionCnt ) ) ;
2019-06-09 02:36:21 +01:00
2019-12-11 08:56:58 +00:00
if ( strlen ( gameCardInfo . updateVersionStr ) ) uiDrawString ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Bundled FW update: %s " , gameCardInfo . updateVersionStr ) ;
2019-06-09 02:36:21 +01:00
2019-06-28 21:13:54 +01:00
breaks + + ;
2019-06-09 02:36:21 +01:00
2019-06-28 21:13:54 +01:00
if ( titleAppCount > 1 & & ( titlePatchCount > 0 | | titleAddOnCount > 0 ) )
2019-06-09 02:36:21 +01:00
{
2019-10-17 21:15:35 +01:00
if ( titlePatchCount > 0 ) uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Total bundled update(s): %u " , titlePatchCount ) ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
if ( titleAddOnCount > 0 ) uiDrawString ( ( titlePatchCount > 0 ? ( ( FB_WIDTH / 2 ) - ( FB_WIDTH / 8 ) ) : 8 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Total bundled DLC(s): %u " , titleAddOnCount ) ;
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
breaks + + ;
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
if ( baseAppEntries [ selectedAppInfoIndex ] . contentSize )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Content size: %s " , baseAppEntries [ selectedAppInfoIndex ] . contentSizeStr ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
}
2019-06-28 21:13:54 +01:00
}
if ( ! strlen ( dumpedContentInfoStr ) )
2019-06-20 04:56:14 +01:00
{
2019-06-28 21:13:54 +01:00
// Look for dumped content in the SD card
char * dumpName = NULL ;
char dumpPath [ NAME_BUF_LEN ] = { ' \0 ' } , tmpStr [ 64 ] = { ' \0 ' } ;
bool dumpedXci = false , dumpedXciCertificate = false , dumpedBase = false , dumpedBaseConsoleData = false ;
u32 patchCnt = 0 , addOnCnt = 0 ;
u32 patchCntConsoleData = 0 , addOnCntConsoleData = 0 ;
2019-12-11 08:56:58 +00:00
snprintf ( dumpedContentInfoStr , MAX_CHARACTERS ( dumpedContentInfoStr ) , " Content already dumped: " ) ;
2019-06-28 21:13:54 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
for ( i = 0 ; i < 2 ; i + + )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
dumpName = generateGameCardDumpName ( i = = 1 ) ;
if ( ! dumpName ) continue ;
// First check if a full XCI dump is available
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.xci " , XCI_DUMP_PATH , dumpName ) ;
2019-06-28 21:13:54 +01:00
if ( ! ( dumpedXci = checkIfFileExists ( dumpPath ) ) )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
// Check if a split XCI dump is available
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.xc0 " , XCI_DUMP_PATH , dumpName ) ;
2019-06-28 21:13:54 +01:00
dumpedXci = checkIfFileExists ( dumpPath ) ;
2019-06-20 04:56:14 +01:00
}
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
free ( dumpName ) ;
dumpName = NULL ;
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
if ( dumpedXci )
{
dumpedXciCertificate = checkIfDumpedXciContainsCertificate ( dumpPath ) ;
break ;
}
2019-06-20 04:56:14 +01:00
}
2019-06-28 21:13:54 +01:00
}
// Now search for dumped NSPs
// Look for a dumped base application
2019-12-11 08:56:58 +00:00
for ( i = 0 ; i < 2 ; i + + )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
dumpName = generateNSPDumpName ( DUMP_APP_NSP , selectedAppInfoIndex , ( i = = 1 ) ) ;
if ( ! dumpName ) continue ;
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.nsp " , NSP_DUMP_PATH , dumpName ) ;
2019-06-20 04:56:14 +01:00
2019-06-28 21:13:54 +01:00
free ( dumpName ) ;
dumpName = NULL ;
if ( checkIfFileExists ( dumpPath ) )
{
dumpedBase = true ;
dumpedBaseConsoleData = checkIfDumpedNspContainsConsoleData ( dumpPath ) ;
2019-12-11 08:56:58 +00:00
break ;
2019-06-28 21:13:54 +01:00
}
}
// Look for dumped updates
2019-12-11 08:56:58 +00:00
for ( patch = 0 ; patch < titlePatchCount ; patch + + )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( ! checkIfPatchOrAddOnBelongsToBaseApplication ( patch , selectedAppInfoIndex , false ) ) continue ;
for ( i = 0 ; i < 2 ; i + + )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
dumpName = generateNSPDumpName ( DUMP_PATCH_NSP , patch , ( i = = 1 ) ) ;
if ( ! dumpName ) continue ;
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.nsp " , NSP_DUMP_PATH , dumpName ) ;
free ( dumpName ) ;
dumpName = NULL ;
if ( checkIfFileExists ( dumpPath ) )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
patchCnt + + ;
if ( checkIfDumpedNspContainsConsoleData ( dumpPath ) ) patchCntConsoleData + + ;
break ;
2019-06-20 04:56:14 +01:00
}
}
2019-06-28 21:13:54 +01:00
}
// Look for dumped DLCs
2019-12-11 08:56:58 +00:00
for ( addon = 0 ; addon < titleAddOnCount ; addon + + )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( ! checkIfPatchOrAddOnBelongsToBaseApplication ( addon , selectedAppInfoIndex , true ) ) continue ;
for ( i = 0 ; i < 2 ; i + + )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
dumpName = generateNSPDumpName ( DUMP_ADDON_NSP , addon , ( i = = 1 ) ) ;
if ( ! dumpName ) continue ;
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.nsp " , NSP_DUMP_PATH , dumpName ) ;
free ( dumpName ) ;
dumpName = NULL ;
if ( checkIfFileExists ( dumpPath ) )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
addOnCnt + + ;
if ( checkIfDumpedNspContainsConsoleData ( dumpPath ) ) addOnCntConsoleData + + ;
break ;
2019-06-20 04:56:14 +01:00
}
}
2019-06-28 21:13:54 +01:00
}
if ( ! dumpedXci & & ! dumpedBase & & ! patchCnt & & ! addOnCnt )
{
strcat ( dumpedContentInfoStr , " NONE " ) ;
} else {
if ( dumpedXci )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " XCI (%s cert) " , ( dumpedXciCertificate ? " with " : " without " ) ) ;
strcat ( dumpedContentInfoStr , tmpStr ) ;
2019-06-28 21:13:54 +01:00
}
if ( dumpedBase )
{
if ( dumpedXci ) strcat ( dumpedContentInfoStr , " , " ) ;
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " BASE (%s console data) " , ( dumpedBaseConsoleData ? " with " : " without " ) ) ;
strcat ( dumpedContentInfoStr , tmpStr ) ;
2019-06-28 21:13:54 +01:00
}
if ( patchCnt )
{
2019-12-11 08:56:58 +00:00
if ( dumpedXci | | dumpedBase ) strcat ( dumpedContentInfoStr , " , " ) ;
2019-06-28 21:13:54 +01:00
if ( patchCntConsoleData )
2019-06-20 04:56:14 +01:00
{
2019-06-28 21:13:54 +01:00
if ( patchCntConsoleData = = patchCnt )
2019-06-20 04:56:14 +01:00
{
if ( patchCnt > 1 )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u UPD (all with console data) " , patchCnt ) ;
2019-06-20 04:56:14 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " UPD (with console data) " ) ;
2019-06-20 04:56:14 +01:00
}
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u UPD (%u with console data) " , patchCnt , patchCntConsoleData ) ;
2019-06-28 21:13:54 +01:00
}
} else {
if ( patchCnt > 1 )
{
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u UPD (all without console data) " , patchCnt ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " UPD (without console data) " ) ;
2019-06-20 04:56:14 +01:00
}
}
2019-06-28 21:13:54 +01:00
strcat ( dumpedContentInfoStr , tmpStr ) ;
}
if ( addOnCnt )
{
2019-12-11 08:56:58 +00:00
if ( dumpedXci | | dumpedBase | | patchCnt ) strcat ( dumpedContentInfoStr , " , " ) ;
2019-06-28 21:13:54 +01:00
if ( addOnCntConsoleData )
2019-06-20 04:56:14 +01:00
{
2019-06-28 21:13:54 +01:00
if ( addOnCntConsoleData = = addOnCnt )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u DLC (%s console data) " , addOnCnt , ( addOnCnt > 1 ? " all with " : " with " ) ) ;
2019-06-20 04:56:14 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u DLC (%u with console data) " , addOnCnt , addOnCntConsoleData ) ;
2019-06-20 04:56:14 +01:00
}
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( tmpStr , MAX_CHARACTERS ( tmpStr ) , " %u DLC (%s console data) " , addOnCnt , ( addOnCnt > 1 ? " all without " : " without " ) ) ;
2019-06-20 04:56:14 +01:00
}
2019-06-28 21:13:54 +01:00
strcat ( dumpedContentInfoStr , tmpStr ) ;
2019-06-20 04:56:14 +01:00
}
}
2019-06-05 23:44:18 +01:00
}
2019-06-20 04:56:14 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , dumpedContentInfoStr ) ;
2019-06-20 04:56:14 +01:00
breaks + = 2 ;
2019-06-09 02:36:21 +01:00
} else
2019-12-11 08:56:58 +00:00
if ( menuType = = MENUTYPE_SDCARD_EMMC & & orphanMode & & ( uiState = = stateSdCardEmmcTitleMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu | | uiState = = stateExeFsMenu | | uiState = = stateRomFsMenu | | uiState = = stateTicketMenu ) )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
if ( strlen ( orphanEntries [ orphanListCursor ] . name ) )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Parent base application: %s " , orphanEntries [ orphanListCursor ] . name ) ;
breaks + + ;
}
2019-12-11 08:56:58 +00:00
patch_addon_ctx_t * ptr = ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? & ( patchEntries [ selectedPatchIndex ] ) : & ( addOnEntries [ selectedAddOnIndex ] ) ) ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Title ID: %016lX " , ptr - > titleId ) ;
2019-06-05 23:44:18 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Version: %s " , ptr - > versionStr ) ;
2019-06-20 04:56:14 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
if ( ptr - > contentSize )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , " Content size: %s " , ptr - > contentSizeStr ) ;
breaks + + ;
}
2019-06-28 21:13:54 +01:00
if ( ! strlen ( dumpedContentInfoStr ) )
2019-06-20 04:56:14 +01:00
{
// Look for dumped content in the SD card
char * dumpName = NULL ;
char dumpPath [ NAME_BUF_LEN ] = { ' \0 ' } ;
2019-12-11 08:56:58 +00:00
bool dumpedOrphan = false ;
nspDumpType orphanDumpType = ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? DUMP_PATCH_NSP : DUMP_ADDON_NSP ) ;
u32 orphanIndex = ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
2019-06-20 04:56:14 +01:00
2019-12-11 08:56:58 +00:00
snprintf ( dumpedContentInfoStr , MAX_CHARACTERS ( dumpedContentInfoStr ) , " Title already dumped: " ) ;
2019-06-20 04:56:14 +01:00
2019-12-11 08:56:58 +00:00
for ( i = 0 ; i < 2 ; i + + )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
dumpName = generateNSPDumpName ( orphanDumpType , orphanIndex , ( i = = 1 ) ) ;
if ( ! dumpName ) continue ;
snprintf ( dumpPath , MAX_CHARACTERS ( dumpPath ) , " %s%s.nsp " , NSP_DUMP_PATH , dumpName ) ;
2019-06-20 04:56:14 +01:00
free ( dumpName ) ;
dumpName = NULL ;
2019-12-11 08:56:58 +00:00
dumpedOrphan = checkIfFileExists ( dumpPath ) ;
if ( dumpedOrphan )
2019-06-20 04:56:14 +01:00
{
2019-06-28 21:13:54 +01:00
strcat ( dumpedContentInfoStr , " Yes " ) ;
2019-06-20 04:56:14 +01:00
if ( checkIfDumpedNspContainsConsoleData ( dumpPath ) )
{
2019-06-28 21:13:54 +01:00
strcat ( dumpedContentInfoStr , " (with console data) " ) ;
2019-06-20 04:56:14 +01:00
} else {
2019-06-28 21:13:54 +01:00
strcat ( dumpedContentInfoStr , " (without console data) " ) ;
2019-06-20 04:56:14 +01:00
}
2019-12-11 08:56:58 +00:00
break ;
2019-06-20 04:56:14 +01:00
}
}
2019-12-11 08:56:58 +00:00
if ( ! dumpedOrphan ) strcat ( dumpedContentInfoStr , " No " ) ;
2019-06-20 04:56:14 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_SUCCESS_RGB , dumpedContentInfoStr ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
2019-06-20 04:56:14 +01:00
} else {
2019-06-28 21:13:54 +01:00
dumpedContentInfoStr [ 0 ] = ' \0 ' ;
2019-06-05 23:44:18 +01:00
}
switch ( uiState )
{
case stateMainMenu :
menu = mainMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( mainMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Main menu " ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateGameCardMenu :
menu = gameCardMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( gameCardMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , mainMenuItems [ 0 ] ) ;
2019-06-09 02:36:21 +01:00
2019-06-05 23:44:18 +01:00
break ;
case stateXciDumpMenu :
menu = xciDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( xciDumpMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 0 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateNspDumpMenu :
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
{
menu = nspDumpGameCardMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( nspDumpGameCardMenuItems ) ;
2019-06-09 02:36:21 +01:00
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
menu = nspDumpSdCardEmmcMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( nspDumpSdCardEmmcMenuItems ) ;
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 1 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateNspAppDumpMenu :
menu = nspAppDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( nspAppDumpMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , nspDumpGameCardMenuItems [ 0 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateNspPatchDumpMenu :
menu = nspPatchDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( nspPatchDumpMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( menuType = = MENUTYPE_GAMECARD ? nspDumpGameCardMenuItems [ 1 ] : nspDumpSdCardEmmcMenuItems [ 1 ] ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateNspAddOnDumpMenu :
menu = nspAddOnDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( nspAddOnDumpMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( menuType = = MENUTYPE_GAMECARD ? nspDumpGameCardMenuItems [ 2 ] : nspDumpSdCardEmmcMenuItems [ 2 ] ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateHfs0Menu :
menu = hfs0MenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( hfs0MenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 2 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateRawHfs0PartitionDumpMenu :
case stateHfs0PartitionDataDumpMenu :
2019-12-11 08:56:58 +00:00
menu = ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0PartitionDumpType1MenuItems : hfs0PartitionDumpType2MenuItems ) ;
menuItemsCount = ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? MAX_ELEMENTS ( hfs0PartitionDumpType1MenuItems ) : MAX_ELEMENTS ( hfs0PartitionDumpType2MenuItems ) ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( uiState = = stateRawHfs0PartitionDumpMenu ? hfs0MenuItems [ 0 ] : hfs0MenuItems [ 1 ] ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateHfs0BrowserMenu :
2019-12-11 08:56:58 +00:00
menu = ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0BrowserType1MenuItems : hfs0BrowserType2MenuItems ) ;
menuItemsCount = ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? MAX_ELEMENTS ( hfs0BrowserType1MenuItems ) : MAX_ELEMENTS ( hfs0BrowserType2MenuItems ) ) ;
2019-04-21 17:27:33 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , hfs0MenuItems [ 2 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateHfs0Browser :
menu = ( const char * * ) filenames ;
menuItemsCount = filenamesCount ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0BrowserType1MenuItems [ selectedPartitionIndex ] : hfs0BrowserType2MenuItems [ selectedPartitionIndex ] ) ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Entry count: %d | Current entry: %d " , menuItemsCount , cursor + 1 ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateExeFsMenu :
menu = exeFsMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( exeFsMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 3 ] ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateExeFsSectionDataDumpMenu :
menu = exeFsSectionDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( exeFsSectionDumpMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , exeFsMenuItems [ 0 ] ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateExeFsSectionBrowserMenu :
menu = exeFsSectionBrowserMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( exeFsSectionBrowserMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , exeFsMenuItems [ 1 ] ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateExeFsSectionBrowser :
menu = ( const char * * ) filenames ;
menuItemsCount = filenamesCount ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , exeFsMenuItems [ 1 ] ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , exeFsMenuItems [ 2 ] , ( dumpCfg . exeFsDumpCfg . isFat32 ? " Yes " : " No " ) , exeFsMenuItems [ 3 ] , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
if ( ! exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , exeFsSectionBrowserMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-09 02:36:21 +01:00
breaks + = 2 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Entry count: %d | Current entry: %d " , menuItemsCount , cursor + 1 ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateRomFsMenu :
menu = romFsMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( romFsMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 4 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateRomFsSectionDataDumpMenu :
menu = romFsSectionDumpMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( romFsSectionDumpMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 0 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateRomFsSectionBrowserMenu :
menu = romFsSectionBrowserMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( romFsSectionBrowserMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 1 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateRomFsSectionBrowser :
menu = ( const char * * ) filenames ;
menuItemsCount = filenamesCount ;
2019-11-06 18:22:40 +00:00
// Skip the parent directory entry ("..") in the RomFS browser if we're currently at the root directory
if ( menu & & menuItemsCount & & strlen ( curRomFsPath ) < = 1 )
{
menu + + ;
menuItemsCount - - ;
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 1 ] ) ;
2019-04-21 17:27:33 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , romFsSectionBrowserMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Path: romfs:%s " , curRomFsPath ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
2019-04-21 17:27:33 +01:00
2019-11-06 18:22:40 +00:00
if ( strlen ( curRomFsPath ) < = 1 | | ( strlen ( curRomFsPath ) > 1 & & cursor > 0 ) )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " Entry count: %d | Current entry: %d " , filenamesCount - 1 , ( strlen ( curRomFsPath ) < = 1 ? ( cursor + 1 ) : cursor ) ) ;
2019-06-05 23:44:18 +01:00
} else {
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " Entry count: %d " , filenamesCount - 1 ) ;
2019-04-21 17:27:33 +01:00
}
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
2019-06-09 02:36:21 +01:00
break ;
case stateSdCardEmmcMenu :
2019-12-11 08:56:58 +00:00
generateSdCardEmmcTitleList ( ) ;
menu = ( const char * * ) filenames ;
menuItemsCount = filenamesCount ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , mainMenuItems [ 1 ] ) ;
2019-06-09 02:36:21 +01:00
if ( menuItemsCount )
{
breaks + = 2 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Title count: %d | Current title: %d " , menuItemsCount , cursor + 1 ) ;
2019-06-09 02:36:21 +01:00
}
2019-06-20 04:56:14 +01:00
breaks + + ;
2019-06-09 02:36:21 +01:00
break ;
case stateSdCardEmmcTitleMenu :
menu = sdCardEmmcMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( sdCardEmmcMenuItems ) ;
2019-06-09 02:36:21 +01:00
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( ! orphanMode ? mainMenuItems [ 1 ] : ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? " Dump orphan update content " : " Dump orphan DLC content " ) ) ) ;
2019-06-09 02:36:21 +01:00
break ;
case stateSdCardEmmcOrphanPatchAddOnMenu :
2019-12-11 08:56:58 +00:00
// Generate orphan content list
// If orphanEntries == NULL or if orphanEntriesCnt == 0, both variables will be regenerated
// Otherwise, this will only fill filenameBuffer
generateOrphanPatchOrAddOnList ( ) ;
2019-06-09 02:36:21 +01:00
menu = ( const char * * ) filenames ;
menuItemsCount = filenamesCount ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Dump installed content with missing base application " ) ;
2019-06-09 02:36:21 +01:00
if ( menuItemsCount )
{
breaks + = 2 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " Title count: %d | Current title: %d " , menuItemsCount , cursor + 1 ) ;
2019-06-09 02:36:21 +01:00
}
2019-06-28 21:13:54 +01:00
break ;
case stateSdCardEmmcBatchModeMenu :
menu = batchModeMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( batchModeMenuItems ) ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Batch mode " ) ;
2019-06-28 21:13:54 +01:00
2019-11-06 18:22:40 +00:00
break ;
case stateTicketMenu :
menu = ticketMenuItems ;
menuItemsCount = MAX_ELEMENTS ( ticketMenuItems ) ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , sdCardEmmcMenuItems [ 3 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
case stateUpdateMenu :
menu = updateMenuItems ;
2019-10-17 21:15:35 +01:00
menuItemsCount = MAX_ELEMENTS ( updateMenuItems ) ;
2019-06-05 23:44:18 +01:00
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , mainMenuItems [ 2 ] ) ;
2019-06-05 23:44:18 +01:00
break ;
default :
break ;
}
if ( menu & & menuItemsCount )
{
2019-06-20 04:56:14 +01:00
breaks + + ;
2019-11-06 18:22:40 +00:00
if ( scroll > 0 )
2019-06-20 04:56:14 +01:00
{
u32 arrowWidth = uiGetStrWidth ( upwardsArrow ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( ( FB_WIDTH / 2 ) - ( arrowWidth / 2 ) , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , upwardsArrow ) ;
2019-06-20 04:56:14 +01:00
}
breaks + + ;
2019-06-05 23:44:18 +01:00
j = 0 ;
highlight = false ;
for ( i = scroll ; i < menuItemsCount ; i + + , j + + )
{
2019-06-20 04:56:14 +01:00
if ( j > = maxElements ) break ;
2019-06-05 23:44:18 +01:00
// Avoid printing the "Create directory with archive bit set" option if "Split output dump" is disabled
2019-10-17 21:15:35 +01:00
if ( uiState = = stateXciDumpMenu & & i = = 2 & & ! dumpCfg . xciDumpCfg . isFat32 )
2019-06-05 23:44:18 +01:00
{
j - - ;
continue ;
}
2019-12-11 08:56:58 +00:00
// Avoid printing the "Dump verification method" option if "CRC32 checksum calculation + dump verification" is disabled
if ( uiState = = stateXciDumpMenu & & i = = 6 & & ! dumpCfg . xciDumpCfg . calcCrc )
{
j - - ;
continue ;
}
2019-11-06 18:22:40 +00:00
// Avoid printing the "Dump bundled update NSP" / "Dump installed update NSP" option in the NSP dump menu if we're dealing with a gamecard and it doesn't include any bundled updates, or if we're dealing with a SD/eMMC title without installed updates
// Also avoid printing the "Dump bundled DLC NSP" / "Dump installed DLC NSP" option in the NSP dump menu if we're dealing with a gamecard and it doesn't include any bundled DLCs, or if we're dealing with a SD/eMMC title without installed DLCs
if ( uiState = = stateNspDumpMenu & & ( ( i = = 1 & & ( ! titlePatchCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) ) ) | | ( i = = 2 & & ( ! titleAddOnCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) ) ) )
2019-04-21 17:27:33 +01:00
{
2019-11-06 18:22:40 +00:00
j - - ;
continue ;
2019-04-21 17:27:33 +01:00
}
2019-12-11 08:56:58 +00:00
// Avoid printing the "Verify dump using No-Intro database" option in the NSP dump menus if we're dealing with a gamecard title
// Also, avoid printing the "Remove console specific data" option in the NSP dump menus if we're dealing with a gamecard title
2019-06-20 04:56:14 +01:00
// Also, avoid printing the "Generate ticket-less dump" option in the NSP dump menus if we're dealing with a gamecard Application/AddOn title
2019-12-11 08:56:58 +00:00
if ( menuType = = MENUTYPE_GAMECARD & & ( ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & ( i = = 2 | | i = = 3 ) ) | | ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & i = = 4 ) ) )
{
j - - ;
continue ;
}
// Avoid printing the "Dump delta fragments" option in the update NSP dump menu if we're dealing with a gamecard update
if ( menuType = = MENUTYPE_GAMECARD & & uiState = = stateNspPatchDumpMenu & & i = = 6 )
2019-06-09 02:36:21 +01:00
{
j - - ;
continue ;
}
// Avoid printing the "Generate ticket-less dump" option in the NSP dump menus if we're dealing with a SD/eMMC title and the "Remove console specific data" option is disabled
2019-10-17 21:15:35 +01:00
if ( menuType = = MENUTYPE_SDCARD_EMMC & & ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & i = = 4 & & ! dumpCfg . nspDumpCfg . removeConsoleData )
2019-06-09 02:36:21 +01:00
{
j - - ;
continue ;
}
2019-06-28 21:13:54 +01:00
// Avoid printing the "Dump base applications", "Dump updates" and/or "Dump DLCs" options in the batch mode menu if we're dealing with a storage source that doesn't hold any title belonging to the current category
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & ( ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & ( ( ! titleAppCount & & i = = 1 ) | | ( ! titlePatchCount & & i = = 2 ) | | ( ! titleAddOnCount & & i = = 3 ) ) ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD & & ( ( ! sdCardTitleAppCount & & i = = 1 ) | | ( ! sdCardTitlePatchCount & & i = = 2 ) | | ( ! sdCardTitleAddOnCount & & i = = 3 ) ) ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC & & ( ( ! emmcTitleAppCount & & i = = 1 ) | | ( ! emmcTitlePatchCount & & i = = 2 ) | | ( ! emmcTitleAddOnCount & & i = = 3 ) ) ) ) )
2019-06-28 21:13:54 +01:00
{
j - - ;
continue ;
}
// Avoid printing the "Generate ticket-less dumps" option in the batch mode menu if the "Remove console specific data" option is disabled
2019-10-17 21:15:35 +01:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & i = = 6 & & ! dumpCfg . batchDumpCfg . removeConsoleData )
2019-06-28 21:13:54 +01:00
{
j - - ;
continue ;
}
2019-12-11 08:56:58 +00:00
// Avoid printing the "Dump delta fragments from updates" option in the batch mode menu if the "Dump updates" option is disabled
if ( uiState = = stateSdCardEmmcBatchModeMenu & & i = = 8 & & ! dumpCfg . batchDumpCfg . dumpPatchTitles )
{
j - - ;
continue ;
}
2019-06-28 21:13:54 +01:00
// Avoid printing the "Source storage" option in the batch mode menu if we only have titles available in a single source storage device
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & i = = 13 & & ( ( ! sdCardTitleAppCount & & ! sdCardTitlePatchCount & & ! sdCardTitleAddOnCount ) | | ( ! emmcTitleAppCount & & ! emmcTitlePatchCount & & ! emmcTitleAddOnCount ) ) )
2019-06-28 21:13:54 +01:00
{
j - - ;
continue ;
}
2019-09-15 03:45:27 +01:00
// Avoid printing the "Use update" option in the ExeFS menu if we're dealing with a gamecard and either its base application count is greater than 1 or it has no available patches
2019-12-11 08:56:58 +00:00
// Also avoid printing it if we're dealing with a SD/eMMC title and it has no available patches, or if we're dealing with an orphan Patch
if ( uiState = = stateExeFsMenu & & i = = 4 & & ( ( menuType = = MENUTYPE_GAMECARD & & ( titleAppCount > 1 | | ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ( ( ! orphanMode & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) | | orphanMode ) ) ) )
2019-09-15 03:45:27 +01:00
{
j - - ;
continue ;
}
// Avoid printing the "Use update" option in the ExeFS data dump and browser menus if we're not dealing with a gamecard, if the base application count is equal to or less than 1, or if the selected base application has no available patches
if ( ( uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu ) & & i = = 2 & & ( menuType ! = MENUTYPE_GAMECARD | | titleAppCount < = 1 | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) ) )
2019-06-28 21:13:54 +01:00
{
j - - ;
continue ;
}
2019-09-15 03:45:27 +01:00
// Avoid printing the "Use update/DLC" option in the RomFS menu if we're dealing with a gamecard and either its base application count is greater than 1 or it has no available patches/DLCs
// Also avoid printing it if we're dealing with a SD/eMMC title and it has no available patches/DLCs (or if its an orphan title)
2019-12-11 08:56:58 +00:00
if ( uiState = = stateRomFsMenu & & i = = 4 & & ( ( menuType = = MENUTYPE_GAMECARD & & ( titleAppCount > 1 | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , true ) ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ( orphanMode | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) ) ) )
2019-09-15 03:45:27 +01:00
{
j - - ;
continue ;
}
// Avoid printing the "Use update/DLC" option in the RomFS data dump and browser menus if we're not dealing with a gamecard, if the base application count is equal to or less than 1, or if the selected base application has no available patches/DLCs
if ( ( uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu ) & & i = = 2 & & ( menuType ! = MENUTYPE_GAMECARD | | titleAppCount < = 1 | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) ) )
2019-06-28 21:13:54 +01:00
{
j - - ;
continue ;
}
2019-12-11 08:56:58 +00:00
// Avoid printing the "RomFS options" element in the SD card / eMMC title menu if we're dealing with an orphan Patch
// Also avoid printing the "ExeFS options" element in the SD card / eMMC title menu if we're dealing with an orphan DLC
if ( uiState = = stateSdCardEmmcTitleMenu & & orphanMode & & ( ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH & & i = = 2 ) | | ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_ADDON & & i = = 1 ) ) )
2019-06-05 23:44:18 +01:00
{
j - - ;
continue ;
}
2019-11-06 18:22:40 +00:00
// Avoid printing the "Use ticket from title" element in the Ticket menu if we're dealing with an orphan title
if ( uiState = = stateTicketMenu & & orphanMode & & i = = 2 )
2019-09-15 03:45:27 +01:00
{
j - - ;
continue ;
}
2019-10-17 21:15:35 +01:00
xpos = STRING_X_POS ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( uiState = = stateSdCardEmmcMenu ? ( j * ( NACP_ICON_DOWNSCALED + 12 ) ) : ( j * ( font_height + 12 ) ) ) + 6 ) ;
2019-06-05 23:44:18 +01:00
if ( i = = cursor )
{
highlight = true ;
2019-10-17 21:15:35 +01:00
uiFill ( 0 , ( ypos + 8 ) - 6 , FB_WIDTH , ( uiState = = stateSdCardEmmcMenu ? ( NACP_ICON_DOWNSCALED + 12 ) : ( font_height + 12 ) ) , HIGHLIGHT_BG_COLOR_RGB ) ;
2019-06-05 23:44:18 +01:00
}
2019-06-09 02:36:21 +01:00
if ( uiState = = stateSdCardEmmcMenu )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( baseAppEntries [ i ] . icon ! = NULL )
2019-06-09 02:36:21 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawIcon ( baseAppEntries [ i ] . icon , NACP_ICON_DOWNSCALED , NACP_ICON_DOWNSCALED , xpos , ypos + 8 ) ;
2019-06-09 02:36:21 +01:00
xpos + = ( NACP_ICON_DOWNSCALED + 8 ) ;
}
ypos + = ( ( NACP_ICON_DOWNSCALED / 2 ) - ( font_height / 2 ) ) ;
} else
if ( uiState = = stateHfs0Browser | | uiState = = stateExeFsSectionBrowser | | uiState = = stateRomFsSectionBrowser )
{
2019-12-11 08:56:58 +00:00
u8 * icon = NULL ;
if ( uiState = = stateRomFsSectionBrowser )
{
u32 idx = ( strlen ( curRomFsPath ) < = 1 ? ( i + 1 ) : i ) ; // Adjust index if we're at the root directory
icon = ( highlight ? ( romFsBrowserEntries [ idx ] . type = = ROMFS_ENTRY_DIR ? dirHighlightIconBuf : fileHighlightIconBuf ) : ( romFsBrowserEntries [ idx ] . type = = ROMFS_ENTRY_DIR ? dirNormalIconBuf : fileNormalIconBuf ) ) ;
} else {
icon = ( highlight ? fileHighlightIconBuf : fileNormalIconBuf ) ;
}
2019-06-09 02:36:21 +01:00
uiDrawIcon ( icon , BROWSER_ICON_DIMENSION , BROWSER_ICON_DIMENSION , xpos , ypos + 8 ) ;
2019-06-05 23:44:18 +01:00
xpos + = ( BROWSER_ICON_DIMENSION + 8 ) ;
}
2019-04-21 17:27:33 +01:00
2019-10-17 21:15:35 +01:00
if ( highlight )
{
uiDrawString ( xpos , ypos , HIGHLIGHT_FONT_COLOR_RGB , menu [ i ] ) ;
2019-12-11 08:56:58 +00:00
u32 idx = ( ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) < = 1 ) ? ( i + 1 ) : i ) ; // Adjust index if we're at the root directory
if ( uiState = = stateHfs0Browser | | uiState = = stateExeFsSectionBrowser )
{
uiDrawString ( FB_WIDTH - ( font_height * 7 ) , ypos , HIGHLIGHT_FONT_COLOR_RGB , " (%s) " , hfs0ExeFsEntriesSizes [ idx ] . sizeStr ) ;
} else
if ( uiState = = stateRomFsSectionBrowser & & romFsBrowserEntries [ idx ] . type = = ROMFS_ENTRY_FILE )
{
uiDrawString ( FB_WIDTH - ( font_height * 7 ) , ypos , HIGHLIGHT_FONT_COLOR_RGB , " (%s) " , romFsBrowserEntries [ idx ] . sizeInfo . sizeStr ) ;
}
2019-10-17 21:15:35 +01:00
} else {
uiDrawString ( xpos , ypos , FONT_COLOR_RGB , menu [ i ] ) ;
2019-12-11 08:56:58 +00:00
u32 idx = ( ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) < = 1 ) ? ( i + 1 ) : i ) ; // Adjust index if we're at the root directory
if ( uiState = = stateHfs0Browser | | uiState = = stateExeFsSectionBrowser )
{
uiDrawString ( FB_WIDTH - ( font_height * 7 ) , ypos , FONT_COLOR_RGB , " (%s) " , hfs0ExeFsEntriesSizes [ idx ] . sizeStr ) ;
} else
if ( uiState = = stateRomFsSectionBrowser & & romFsBrowserEntries [ idx ] . type = = ROMFS_ENTRY_FILE )
{
uiDrawString ( FB_WIDTH - ( font_height * 7 ) , ypos , FONT_COLOR_RGB , " (%s) " , romFsBrowserEntries [ idx ] . sizeInfo . sizeStr ) ;
}
2019-10-17 21:15:35 +01:00
}
2019-06-09 02:36:21 +01:00
2019-06-20 04:56:14 +01:00
xpos = OPTIONS_X_START_POS ;
2019-06-09 02:36:21 +01:00
2019-06-20 04:56:14 +01:00
bool leftArrowCondition = false ;
bool rightArrowCondition = false ;
2019-04-21 17:27:33 +01:00
2019-06-05 23:44:18 +01:00
// Print XCI dump menu settings values
if ( uiState = = stateXciDumpMenu & & i > 0 )
2019-04-21 17:27:33 +01:00
{
2019-06-05 23:44:18 +01:00
switch ( i )
2019-04-21 17:27:33 +01:00
{
2019-06-05 23:44:18 +01:00
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . xciDumpCfg . isFat32 , ! dumpCfg . xciDumpCfg . isFat32 , ( dumpCfg . xciDumpCfg . isFat32 ? 0 : 255 ) , ( dumpCfg . xciDumpCfg . isFat32 ? 255 : 0 ) , 0 , ( dumpCfg . xciDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case 2 : // Create directory with archive bit set
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . xciDumpCfg . setXciArchiveBit , ! dumpCfg . xciDumpCfg . setXciArchiveBit , ( dumpCfg . xciDumpCfg . setXciArchiveBit ? 0 : 255 ) , ( dumpCfg . xciDumpCfg . setXciArchiveBit ? 255 : 0 ) , 0 , ( dumpCfg . xciDumpCfg . setXciArchiveBit ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
2019-09-15 03:45:27 +01:00
case 3 : // Keep certificate
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . xciDumpCfg . keepCert , ! dumpCfg . xciDumpCfg . keepCert , ( dumpCfg . xciDumpCfg . keepCert ? 0 : 255 ) , ( dumpCfg . xciDumpCfg . keepCert ? 255 : 0 ) , 0 , ( dumpCfg . xciDumpCfg . keepCert ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case 4 : // Trim output dump
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . xciDumpCfg . trimDump , ! dumpCfg . xciDumpCfg . trimDump , ( dumpCfg . xciDumpCfg . trimDump ? 0 : 255 ) , ( dumpCfg . xciDumpCfg . trimDump ? 255 : 0 ) , 0 , ( dumpCfg . xciDumpCfg . trimDump ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
case 5 : // CRC32 checksum calculation + dump verification
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . xciDumpCfg . calcCrc , ! dumpCfg . xciDumpCfg . calcCrc , ( dumpCfg . xciDumpCfg . calcCrc ? 0 : 255 ) , ( dumpCfg . xciDumpCfg . calcCrc ? 255 : 0 ) , 0 , ( dumpCfg . xciDumpCfg . calcCrc ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Dump verification method
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , dumpCfg . xciDumpCfg . useNoIntroLookup , ! dumpCfg . xciDumpCfg . useNoIntroLookup , FONT_COLOR_RGB , ( dumpCfg . xciDumpCfg . useNoIntroLookup ? xciChecksumLookupMethods [ 1 ] : xciChecksumLookupMethods [ 0 ] ) ) ;
break ;
case 7 : // Output naming scheme
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , dumpCfg . xciDumpCfg . useBrackets , ! dumpCfg . xciDumpCfg . useBrackets , FONT_COLOR_RGB , ( dumpCfg . xciDumpCfg . useBrackets ? xciNamingSchemes [ 1 ] : xciNamingSchemes [ 0 ] ) ) ;
break ;
2019-06-05 23:44:18 +01:00
default :
break ;
}
}
// Print NSP dump menus settings values
if ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & i > 0 )
{
switch ( i )
{
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . isFat32 , ! dumpCfg . nspDumpCfg . isFat32 , ( dumpCfg . nspDumpCfg . isFat32 ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . isFat32 ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 2 : // Verify dump using No-Intro database
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . useNoIntroLookup , ! dumpCfg . nspDumpCfg . useNoIntroLookup , ( dumpCfg . nspDumpCfg . useNoIntroLookup ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . useNoIntroLookup ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . useNoIntroLookup ? " Yes " : " No " ) ) ;
2019-06-09 02:36:21 +01:00
break ;
case 3 : // Remove console specific data
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . removeConsoleData , ! dumpCfg . nspDumpCfg . removeConsoleData , ( dumpCfg . nspDumpCfg . removeConsoleData ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . removeConsoleData ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
2019-06-09 02:36:21 +01:00
break ;
case 4 : // Generate ticket-less dump
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . tiklessDump , ! dumpCfg . nspDumpCfg . tiklessDump , ( dumpCfg . nspDumpCfg . tiklessDump ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . tiklessDump ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . tiklessDump ? " Yes " : " No " ) ) ;
2019-06-05 23:44:18 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 5 : // Change NPDM RSA key/sig in Program NCA || DLC to dump
if ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu )
{
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . npdmAcidRsaPatch , ! dumpCfg . nspDumpCfg . npdmAcidRsaPatch , ( dumpCfg . nspDumpCfg . npdmAcidRsaPatch ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . npdmAcidRsaPatch ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . npdmAcidRsaPatch ? " Yes " : " No " ) ) ;
} else
if ( uiState = = stateNspAddOnDumpMenu )
{
if ( ! strlen ( titleSelectorStr ) )
{
// Find a matching application to print its name and Title ID
// Otherwise, just print the Title ID
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , ( menuType = = MENUTYPE_GAMECARD ) , NULL , titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) ) ;
if ( addOnEntries [ selectedAddOnIndex ] . contentSize )
{
strcat ( titleSelectorStr , " ( " ) ;
strcat ( titleSelectorStr , addOnEntries [ selectedAddOnIndex ] . contentSizeStr ) ;
strcat ( titleSelectorStr , " ) " ) ;
}
2019-11-06 18:22:40 +00:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = ( ( menuType = = MENUTYPE_GAMECARD & & titleAddOnCount > 0 & & selectedAddOnIndex > 0 ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppInfoIndex , true ) ! = selectedAddOnIndex ) ) ;
rightArrowCondition = ( ( menuType = = MENUTYPE_GAMECARD & & titleAddOnCount > 0 & & selectedAddOnIndex < ( titleAddOnCount - 1 ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppInfoIndex , true ) ! = selectedAddOnIndex ) ) ;
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , titleSelectorStr ) ;
}
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Application to dump || Dump delta fragments || Output naming scheme (DLC)
2019-06-05 23:44:18 +01:00
if ( uiState = = stateNspAppDumpMenu )
2019-05-01 21:24:13 +01:00
{
2019-06-20 04:56:14 +01:00
if ( ! strlen ( titleSelectorStr ) )
{
// Print application name
2019-12-11 08:56:58 +00:00
snprintf ( titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) , " %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
if ( baseAppEntries [ selectedAppIndex ] . contentSize )
{
strcat ( titleSelectorStr , " ( " ) ;
strcat ( titleSelectorStr , baseAppEntries [ selectedAppIndex ] . contentSizeStr ) ;
strcat ( titleSelectorStr , " ) " ) ;
}
2019-06-28 21:13:54 +01:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
2019-06-20 04:56:14 +01:00
}
leftArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex > 0 ) ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex < ( titleAppCount - 1 ) ) ;
2019-06-05 23:44:18 +01:00
} else
if ( uiState = = stateNspPatchDumpMenu )
2019-12-11 08:56:58 +00:00
{
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . nspDumpCfg . dumpDeltaFragments , ! dumpCfg . nspDumpCfg . dumpDeltaFragments , ( dumpCfg . nspDumpCfg . dumpDeltaFragments ? 0 : 255 ) , ( dumpCfg . nspDumpCfg . dumpDeltaFragments ? 255 : 0 ) , 0 , ( dumpCfg . nspDumpCfg . dumpDeltaFragments ? " Yes " : " No " ) ) ;
} else
if ( uiState = = stateNspAddOnDumpMenu )
{
leftArrowCondition = dumpCfg . nspDumpCfg . useBrackets ;
rightArrowCondition = ! dumpCfg . nspDumpCfg . useBrackets ;
}
if ( uiState ! = stateNspPatchDumpMenu ) uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , ( uiState = = stateNspAddOnDumpMenu ? ( dumpCfg . nspDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) : titleSelectorStr ) ) ;
break ;
case 7 : // Output naming scheme (base application) || Update to dump
if ( uiState = = stateNspAppDumpMenu )
{
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , dumpCfg . nspDumpCfg . useBrackets , ! dumpCfg . nspDumpCfg . useBrackets , FONT_COLOR_RGB , ( dumpCfg . nspDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) ) ;
} else
if ( uiState = = stateNspPatchDumpMenu )
2019-06-05 23:44:18 +01:00
{
2019-06-20 04:56:14 +01:00
if ( ! strlen ( titleSelectorStr ) )
{
// Find a matching application to print its name
// Otherwise, just print the Title ID
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , ( menuType = = MENUTYPE_GAMECARD ) , NULL , titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) ) ;
if ( patchEntries [ selectedPatchIndex ] . contentSize )
{
strcat ( titleSelectorStr , " ( " ) ;
strcat ( titleSelectorStr , patchEntries [ selectedPatchIndex ] . contentSizeStr ) ;
strcat ( titleSelectorStr , " ) " ) ;
}
2019-06-28 21:13:54 +01:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
2019-06-20 04:56:14 +01:00
}
leftArrowCondition = ( ( menuType = = MENUTYPE_GAMECARD & & titlePatchCount > 0 & & selectedPatchIndex > 0 ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppInfoIndex , false ) ! = selectedPatchIndex ) ) ;
rightArrowCondition = ( ( menuType = = MENUTYPE_GAMECARD & & titlePatchCount > 0 & & selectedPatchIndex < ( titlePatchCount - 1 ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppInfoIndex , false ) ! = selectedPatchIndex ) ) ;
2019-12-11 08:56:58 +00:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , titleSelectorStr ) ;
2019-05-01 21:24:13 +01:00
}
2019-12-11 08:56:58 +00:00
break ;
case 8 : // Output naming scheme (update)
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , dumpCfg . nspDumpCfg . useBrackets , ! dumpCfg . nspDumpCfg . useBrackets , FONT_COLOR_RGB , ( dumpCfg . nspDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) ) ;
2019-06-05 23:44:18 +01:00
break ;
default :
break ;
}
if ( i = = 2 )
{
2019-12-11 08:56:58 +00:00
if ( dumpCfg . nspDumpCfg . useNoIntroLookup )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( FB_WIDTH / 2 , ypos , FONT_COLOR_RGB , " This requires a working Internet connection! " ) ;
2019-06-05 23:44:18 +01:00
} else {
2019-10-17 21:15:35 +01:00
if ( highlight )
{
uiFill ( FB_WIDTH / 2 , ( ypos + 8 ) - 6 , FB_WIDTH / 2 , font_height + 12 , HIGHLIGHT_BG_COLOR_RGB ) ;
} else {
uiFill ( FB_WIDTH / 2 , ( ypos + 8 ) - 6 , FB_WIDTH / 2 , font_height + 12 , BG_COLOR_RGB ) ;
}
2019-05-01 21:24:13 +01:00
}
2019-04-21 17:27:33 +01:00
}
}
2019-06-05 23:44:18 +01:00
2019-06-28 21:13:54 +01:00
// Print settings values for the batch mode menu
if ( uiState = = stateSdCardEmmcBatchModeMenu & & i > 0 )
2019-06-05 23:44:18 +01:00
{
switch ( i )
{
2019-06-28 21:13:54 +01:00
case 1 : // Dump base applications
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . dumpAppTitles , ! dumpCfg . batchDumpCfg . dumpAppTitles , ( dumpCfg . batchDumpCfg . dumpAppTitles ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . dumpAppTitles ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . dumpAppTitles ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
case 2 : // Dump updates
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . dumpPatchTitles , ! dumpCfg . batchDumpCfg . dumpPatchTitles , ( dumpCfg . batchDumpCfg . dumpPatchTitles ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . dumpPatchTitles ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . dumpPatchTitles ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
case 3 : // Dump DLCs
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . dumpAddOnTitles , ! dumpCfg . batchDumpCfg . dumpAddOnTitles , ( dumpCfg . batchDumpCfg . dumpAddOnTitles ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . dumpAddOnTitles ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . dumpAddOnTitles ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
case 4 : // Split output dumps (FAT32 support)
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . isFat32 , ! dumpCfg . batchDumpCfg . isFat32 , ( dumpCfg . batchDumpCfg . isFat32 ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . isFat32 ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
case 5 : // Remove console specific data
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . removeConsoleData , ! dumpCfg . batchDumpCfg . removeConsoleData , ( dumpCfg . batchDumpCfg . removeConsoleData ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . removeConsoleData ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
case 6 : // Generate ticket-less dumps
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . tiklessDump , ! dumpCfg . batchDumpCfg . tiklessDump , ( dumpCfg . batchDumpCfg . tiklessDump ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . tiklessDump ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . tiklessDump ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 7 : // Change NPDM RSA key/sig in Program NCA
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . npdmAcidRsaPatch , ! dumpCfg . batchDumpCfg . npdmAcidRsaPatch , ( dumpCfg . batchDumpCfg . npdmAcidRsaPatch ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . npdmAcidRsaPatch ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . npdmAcidRsaPatch ? " Yes " : " No " ) ) ;
break ;
2019-12-11 08:56:58 +00:00
case 8 : // Dump delta fragments from updates
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . dumpDeltaFragments , ! dumpCfg . batchDumpCfg . dumpDeltaFragments , ( dumpCfg . batchDumpCfg . dumpDeltaFragments ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . dumpDeltaFragments ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . dumpDeltaFragments ? " Yes " : " No " ) ) ;
break ;
case 9 : // Skip dumped titles
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . skipDumpedTitles , ! dumpCfg . batchDumpCfg . skipDumpedTitles , ( dumpCfg . batchDumpCfg . skipDumpedTitles ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . skipDumpedTitles ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . skipDumpedTitles ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 10 : // Remember dumped titles
2019-11-06 18:22:40 +00:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . rememberDumpedTitles , ! dumpCfg . batchDumpCfg . rememberDumpedTitles , ( dumpCfg . batchDumpCfg . rememberDumpedTitles ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . rememberDumpedTitles ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . rememberDumpedTitles ? " Yes " : " No " ) ) ;
break ;
2019-12-11 08:56:58 +00:00
case 11 : // Halt dump process on errors
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . batchDumpCfg . haltOnErrors , ! dumpCfg . batchDumpCfg . haltOnErrors , ( dumpCfg . batchDumpCfg . haltOnErrors ? 0 : 255 ) , ( dumpCfg . batchDumpCfg . haltOnErrors ? 255 : 0 ) , 0 , ( dumpCfg . batchDumpCfg . haltOnErrors ? " Yes " : " No " ) ) ;
break ;
case 12 : // Output naming scheme
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , dumpCfg . batchDumpCfg . useBrackets , ! dumpCfg . batchDumpCfg . useBrackets , FONT_COLOR_RGB , ( dumpCfg . batchDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) ) ;
break ;
case 13 : // Source storage
2019-10-17 21:15:35 +01:00
leftArrowCondition = ( dumpCfg . batchDumpCfg . batchModeSrc ! = BATCH_SOURCE_ALL ) ;
rightArrowCondition = ( dumpCfg . batchDumpCfg . batchModeSrc ! = BATCH_SOURCE_EMMC ) ;
2019-06-20 04:56:14 +01:00
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL ? " All (SD card + eMMC) " : ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD ? " SD card " : " eMMC " ) ) ) ;
2019-06-28 21:13:54 +01:00
2019-06-05 23:44:18 +01:00
break ;
default :
break ;
}
}
2019-09-15 03:45:27 +01:00
// Print settings values for ExeFS menu
if ( uiState = = stateExeFsMenu & & i > 1 )
2019-06-28 21:13:54 +01:00
{
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
switch ( i )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . exeFsDumpCfg . isFat32 , ! dumpCfg . exeFsDumpCfg . isFat32 , ( dumpCfg . exeFsDumpCfg . isFat32 ? 0 : 255 ) , ( dumpCfg . exeFsDumpCfg . isFat32 ? 255 : 0 ) , 0 , ( dumpCfg . exeFsDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . exeFsDumpCfg . useLayeredFSDir , ! dumpCfg . exeFsDumpCfg . useLayeredFSDir , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? 0 : 255 ) , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? 255 : 0 ) , 0 , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
break ;
case 4 : // Use update
2019-09-15 03:45:27 +01:00
if ( exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
if ( ! strlen ( exeFsAndRomFsSelectorStr ) )
2019-06-28 21:13:54 +01:00
{
// Find a matching application to print its name
// Otherwise, just print the Title ID
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-06-28 21:13:54 +01:00
// Concatenate patch source storage
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-06-28 21:13:54 +01:00
2019-09-15 03:45:27 +01:00
uiTruncateOptionStr ( exeFsAndRomFsSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
2019-06-28 21:13:54 +01:00
}
leftArrowCondition = true ;
rightArrowCondition = ( ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 ) | | menuType = = MENUTYPE_SDCARD_EMMC ) & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , appIndex , false ) ! = selectedPatchIndex ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , exeFsAndRomFsSelectorStr ) ;
2019-06-28 21:13:54 +01:00
} else {
leftArrowCondition = false ;
rightArrowCondition = ( ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 ) | | menuType = = MENUTYPE_SDCARD_EMMC ) & & checkIfBaseApplicationHasPatchOrAddOn ( appIndex , false ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_ERROR_RGB , " No " ) ;
2019-06-28 21:13:54 +01:00
}
break ;
default :
break ;
}
}
2019-09-15 03:45:27 +01:00
// Print settings values for ExeFS submenus
if ( ( uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu ) & & i > 0 )
2019-06-28 21:13:54 +01:00
{
switch ( i )
{
case 1 : // Bundled application to dump/browse
if ( ! strlen ( titleSelectorStr ) )
{
// Print application name
2019-12-11 08:56:58 +00:00
snprintf ( titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) , " %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-06-28 21:13:54 +01:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex > 0 ) ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex < ( titleAppCount - 1 ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , titleSelectorStr ) ;
2019-06-28 21:13:54 +01:00
break ;
case 2 : // Use update
2019-09-15 03:45:27 +01:00
if ( exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
if ( ! strlen ( exeFsAndRomFsSelectorStr ) )
2019-06-28 21:13:54 +01:00
{
// Find a matching application to print its name
// Otherwise, just print the Title ID
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , ( menuType = = MENUTYPE_GAMECARD ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-06-28 21:13:54 +01:00
// Concatenate patch source storage
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-06-28 21:13:54 +01:00
2019-09-15 03:45:27 +01:00
uiTruncateOptionStr ( exeFsAndRomFsSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
2019-06-28 21:13:54 +01:00
}
leftArrowCondition = true ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppIndex , false ) ! = selectedPatchIndex ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , exeFsAndRomFsSelectorStr ) ;
2019-06-28 21:13:54 +01:00
} else {
leftArrowCondition = false ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_ERROR_RGB , " No " ) ;
2019-06-28 21:13:54 +01:00
}
break ;
default :
break ;
}
}
2019-09-15 03:45:27 +01:00
// Print settings values for RomFS menu
if ( uiState = = stateRomFsMenu & & i > 1 )
{
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
switch ( i )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . romFsDumpCfg . isFat32 , ! dumpCfg . romFsDumpCfg . isFat32 , ( dumpCfg . romFsDumpCfg . isFat32 ? 0 : 255 ) , ( dumpCfg . romFsDumpCfg . isFat32 ? 255 : 0 ) , 0 , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . romFsDumpCfg . useLayeredFSDir , ! dumpCfg . romFsDumpCfg . useLayeredFSDir , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? 0 : 255 ) , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? 255 : 0 ) , 0 , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
break ;
case 4 : // Use update/DLC
2019-09-15 03:45:27 +01:00
if ( curRomFsType ! = ROMFS_TYPE_APP )
{
if ( ! strlen ( exeFsAndRomFsSelectorStr ) )
{
// Find a matching application to print its name. Otherwise, just print the Title ID
// Concatenate title type
// Concatenate source storage
switch ( curRomFsType )
{
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-09-15 03:45:27 +01:00
strcat ( exeFsAndRomFsSelectorStr , " (UPD) " ) ;
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-09-15 03:45:27 +01:00
strcat ( exeFsAndRomFsSelectorStr , " (DLC) " ) ;
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( addOnEntries [ selectedAddOnIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( addOnEntries [ selectedAddOnIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-09-15 03:45:27 +01:00
break ;
default :
break ;
}
uiTruncateOptionStr ( exeFsAndRomFsSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = true ;
rightArrowCondition = ( ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 ) | | menuType = = MENUTYPE_SDCARD_EMMC ) & & ( ( curRomFsType = = ROMFS_TYPE_PATCH & & ( retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , appIndex , false ) ! = selectedPatchIndex | | checkIfBaseApplicationHasPatchOrAddOn ( appIndex , true ) ) ) | | ( curRomFsType = = ROMFS_TYPE_ADDON & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , appIndex , true ) ! = selectedAddOnIndex ) ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , exeFsAndRomFsSelectorStr ) ;
2019-09-15 03:45:27 +01:00
} else {
leftArrowCondition = false ;
rightArrowCondition = ( ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 ) | | menuType = = MENUTYPE_SDCARD_EMMC ) & & ( checkIfBaseApplicationHasPatchOrAddOn ( appIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( appIndex , true ) ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_ERROR_RGB , " No " ) ;
2019-09-15 03:45:27 +01:00
}
break ;
default :
break ;
}
}
// Print settings values for RomFS submenus
if ( ( uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu ) & & i > 0 )
{
switch ( i )
{
case 1 : // Bundled application to dump/browse
if ( ! strlen ( titleSelectorStr ) )
{
// Print application name
2019-12-11 08:56:58 +00:00
snprintf ( titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) , " %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex > 0 ) ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & selectedAppIndex < ( titleAppCount - 1 ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , titleSelectorStr ) ;
2019-09-15 03:45:27 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 2 : // Use update/DLC
2019-09-15 03:45:27 +01:00
if ( curRomFsType ! = ROMFS_TYPE_APP )
{
if ( ! strlen ( exeFsAndRomFsSelectorStr ) )
{
// Find a matching application to print its name. Otherwise, just print the Title ID
// Concatenate title type
// Concatenate source storage
switch ( curRomFsType )
{
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , ( menuType = = MENUTYPE_GAMECARD ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-09-15 03:45:27 +01:00
strcat ( exeFsAndRomFsSelectorStr , " (UPD) " ) ;
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( patchEntries [ selectedPatchIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , ( menuType = = MENUTYPE_GAMECARD ) , NULL , exeFsAndRomFsSelectorStr , MAX_CHARACTERS ( exeFsAndRomFsSelectorStr ) ) ;
2019-09-15 03:45:27 +01:00
strcat ( exeFsAndRomFsSelectorStr , " (DLC) " ) ;
2019-12-11 08:56:58 +00:00
strcat ( exeFsAndRomFsSelectorStr , ( addOnEntries [ selectedAddOnIndex ] . storageId = = NcmStorageId_GameCard ? " (gamecard) " : ( addOnEntries [ selectedAddOnIndex ] . storageId = = NcmStorageId_SdCard ? " (SD card) " : " (eMMC) " ) ) ) ;
2019-09-15 03:45:27 +01:00
break ;
default :
break ;
}
uiTruncateOptionStr ( exeFsAndRomFsSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = true ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & ( ( curRomFsType = = ROMFS_TYPE_PATCH & & ( retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppIndex , false ) ! = selectedPatchIndex | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) ) | | ( curRomFsType = = ROMFS_TYPE_ADDON & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppIndex , true ) ! = selectedAddOnIndex ) ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , exeFsAndRomFsSelectorStr ) ;
2019-09-15 03:45:27 +01:00
} else {
leftArrowCondition = false ;
rightArrowCondition = ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) ) ;
2019-10-17 21:15:35 +01:00
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_ERROR_RGB , " No " ) ;
2019-09-15 03:45:27 +01:00
}
break ;
default :
break ;
}
}
2019-11-06 18:22:40 +00:00
// Print settings values for the Ticket menu
if ( uiState = = stateTicketMenu & & i > 0 )
{
switch ( i )
{
case 1 : // Remove console specific data
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS , dumpCfg . tikDumpCfg . removeConsoleData , ! dumpCfg . tikDumpCfg . removeConsoleData , ( dumpCfg . tikDumpCfg . removeConsoleData ? 0 : 255 ) , ( dumpCfg . tikDumpCfg . removeConsoleData ? 255 : 0 ) , 0 , ( dumpCfg . tikDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
break ;
case 2 : // Use ticket from title
if ( curTikType ! = TICKET_TYPE_APP )
{
if ( ! strlen ( titleSelectorStr ) )
{
// Print update/DLC TID
switch ( curTikType )
{
case TICKET_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , false , NULL , titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) ) ;
2019-11-06 18:22:40 +00:00
strcat ( titleSelectorStr , " (UPD) " ) ;
break ;
case TICKET_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , false , NULL , titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) ) ;
2019-11-06 18:22:40 +00:00
strcat ( titleSelectorStr , " (DLC) " ) ;
break ;
default :
break ;
}
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = true ;
rightArrowCondition = ( ( curTikType = = TICKET_TYPE_PATCH & & ( retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppInfoIndex , false ) ! = selectedPatchIndex | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) | | ( curTikType = = TICKET_TYPE_ADDON & & retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppInfoIndex , true ) ! = selectedAddOnIndex ) ) ;
} else {
if ( ! strlen ( titleSelectorStr ) )
{
// Print application TID
2019-12-11 08:56:58 +00:00
snprintf ( titleSelectorStr , MAX_CHARACTERS ( titleSelectorStr ) , " %016lX v%s (BASE) " , baseAppEntries [ selectedAppInfoIndex ] . titleId , baseAppEntries [ selectedAppInfoIndex ] . versionStr ) ;
2019-11-06 18:22:40 +00:00
uiTruncateOptionStr ( titleSelectorStr , xpos , ypos , OPTIONS_X_END_POS_NSP ) ;
}
leftArrowCondition = false ;
rightArrowCondition = ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ;
}
uiPrintOption ( xpos , ypos , OPTIONS_X_END_POS_NSP , leftArrowCondition , rightArrowCondition , FONT_COLOR_RGB , titleSelectorStr ) ;
break ;
default :
break ;
}
}
2019-06-28 21:13:54 +01:00
if ( i = = cursor ) highlight = false ;
}
if ( ( scroll + maxElements ) < menuItemsCount )
{
2019-10-17 21:15:35 +01:00
ypos = ( ( breaks * LINE_HEIGHT ) + ( uiState = = stateSdCardEmmcMenu ? ( j * ( NACP_ICON_DOWNSCALED + 12 ) ) : ( j * ( font_height + 12 ) ) ) ) ;
2019-06-28 21:13:54 +01:00
u32 arrowWidth = uiGetStrWidth ( downwardsArrow ) ;
2019-10-17 21:15:35 +01:00
uiDrawString ( ( FB_WIDTH / 2 ) - ( arrowWidth / 2 ) , ypos , FONT_COLOR_RGB , downwardsArrow ) ;
2019-06-28 21:13:54 +01:00
}
2019-09-15 03:45:27 +01:00
2019-12-11 08:56:58 +00:00
if ( uiState = = stateMainMenu )
2019-11-06 18:22:40 +00:00
{
j + + ;
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
2019-12-11 08:56:58 +00:00
// Print warning about missing Lockpick_RCM keys file
if ( ! keysFileAvailable )
{
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " Warning: missing keys file at \" %s \" . " , KEYS_FILE_PATH ) ;
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " This file is needed to deal with the encryption schemes used by Nintendo Switch content files. " ) ;
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " SD/eMMC operations will be entirely disabled, along with NSP/ExeFS/RomFS related operations. " ) ;
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " Please run Lockpick_RCM to generate this file. More info at: https://github.com/shchmue/Lockpick_RCM " ) ;
}
// Print warning about running the application under applet mode
if ( programAppletType ! = AppletType_Application & & programAppletType ! = AppletType_SystemApplication )
{
if ( ! keysFileAvailable ) j + = 2 ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " Warning: running under applet mode. " ) ;
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " It seems you used an applet (Album, Settings, etc.) to run the application. This mode greatly limits the amount of usable RAM. " ) ;
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_ERROR_RGB , " If you ever get any memory allocation errors, please consider running the application through title override (hold R while launching a game). " ) ;
}
}
// Print information about the "Change NPDM RSA key/sig in Program NCA" option
if ( ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu ) & & cursor = = 5 ) | | ( uiState = = stateSdCardEmmcBatchModeMenu & & cursor = = 7 ) )
{
2019-11-06 18:22:40 +00:00
j + + ;
2019-12-11 08:56:58 +00:00
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
2019-11-06 18:22:40 +00:00
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " Replaces the public RSA key in the NPDM ACID section and the NPDM RSA signature in the Program NCA (only if it needs other modifications). " ) ;
2019-11-06 18:22:40 +00:00
j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " Disabling this will make the output NSP require ACID patches to work under any CFW, but will also make the Program NCA verifiable by PC tools. " ) ;
}
// Print information about the "Dump delta fragments" option
if ( ( uiState = = stateNspPatchDumpMenu & & cursor = = 6 ) | | ( uiState = = stateSdCardEmmcBatchModeMenu & & cursor = = 8 ) )
{
2019-11-06 18:22:40 +00:00
j + + ;
2019-12-11 08:56:58 +00:00
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
2019-11-06 18:22:40 +00:00
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " Dumps delta fragments for the selected update(s), if available. These are commonly excluded - they serve no real purpose in output dumps. " ) ;
2019-11-06 18:22:40 +00:00
}
2019-12-11 08:56:58 +00:00
// Print information about the "Split files bigger than 4 GiB (FAT32 support)" option
if ( ( uiState = = stateExeFsMenu | | uiState = = stateRomFsMenu ) & & cursor = = 2 )
2019-11-06 18:22:40 +00:00
{
j + + ;
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " If FAT32 support is enabled, files bigger than 4 GiB will be split and stored in a subdirectory with the archive bit set (like NSPs). " ) ;
}
// Print information about the "Save data to CFW directory (LayeredFS)" option
if ( ( uiState = = stateExeFsMenu | | uiState = = stateRomFsMenu ) & & cursor = = 3 )
{
2019-11-06 18:22:40 +00:00
j + + ;
2019-12-11 08:56:58 +00:00
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
2019-11-06 18:22:40 +00:00
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " Enabling this option will save output data to \" %s[TitleID]/%s/ \" (LayeredFS directory structure). " , strchr ( cfwDirStr , ' / ' ) , ( uiState = = stateExeFsMenu ? " exefs " : " romfs " ) ) ;
2019-11-06 18:22:40 +00:00
}
2019-09-15 03:45:27 +01:00
// Print hint about dumping RomFS content from DLCs
2019-12-11 08:56:58 +00:00
if ( ( uiState = = stateRomFsMenu & & cursor = = 4 & & ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount < = 1 & & checkIfBaseApplicationHasPatchOrAddOn ( 0 , true ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) ) | | ( ( uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu ) & & cursor = = 2 & & ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) ) )
2019-09-15 03:45:27 +01:00
{
j + + ;
if ( ( scroll + maxElements ) < menuItemsCount ) j + + ;
2019-10-17 21:15:35 +01:00
ypos = ( ( breaks * LINE_HEIGHT ) + ( j * ( font_height + 12 ) ) ) ;
2019-11-06 18:22:40 +00:00
uiDrawString ( STRING_X_POS , ypos , FONT_COLOR_RGB , " Hint: choosing a DLC will only access RomFS data from it, unlike updates (which share their RomFS data with its base application). " ) ;
2019-09-15 03:45:27 +01:00
}
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
breaks + = 2 ;
if ( uiState = = stateRomFsSectionBrowser )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " No entries available in the selected directory! Press " NINTENDO_FONT_B " to go back. " ) ;
} else
2019-06-28 21:13:54 +01:00
if ( uiState = = stateSdCardEmmcOrphanPatchAddOnMenu )
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_RGB , " No orphan updates/DLCs available in the SD card / eMMC storage! " ) ;
2019-06-28 21:13:54 +01:00
}
}
2019-12-11 08:56:58 +00:00
bool curGcStatus = gameCardInfo . isInserted ;
2019-10-17 21:15:35 +01:00
while ( true )
{
uiUpdateStatusMsg ( ) ;
uiRefreshDisplay ( ) ;
hidScanInput ( ) ;
keysDown = hidKeysDown ( CONTROLLER_P1_AUTO ) ;
keysHeld = hidKeysHeld ( CONTROLLER_P1_AUTO ) ;
2019-12-11 08:56:58 +00:00
if ( ( keysDown & & ! ( keysDown & KEY_TOUCH ) ) | | ( keysHeld & & ! ( keysHeld & KEY_TOUCH ) ) | | ( menuType = = MENUTYPE_GAMECARD & & gameCardInfo . isInserted ! = curGcStatus ) ) break ;
2019-10-17 21:15:35 +01:00
}
2019-04-21 17:27:33 +01:00
// Exit
2019-04-23 06:14:57 +01:00
if ( keysDown & KEY_PLUS ) res = resultExit ;
2019-04-21 17:27:33 +01:00
// Process key inputs only if the UI state hasn't been changed
if ( res = = resultNone )
{
2019-06-05 23:44:18 +01:00
// Process base application info change
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & uiState ! = stateHfs0Browser & & uiState ! = stateExeFsSectionBrowser & & uiState ! = stateRomFsSectionBrowser )
2019-06-05 23:44:18 +01:00
{
if ( ( keysDown & KEY_L ) | | ( keysDown & KEY_ZL ) )
{
if ( selectedAppInfoIndex > 0 )
{
selectedAppInfoIndex - - ;
2019-06-28 21:13:54 +01:00
dumpedContentInfoStr [ 0 ] = ' \0 ' ;
2019-06-05 23:44:18 +01:00
}
}
if ( ( keysDown & KEY_R ) | | ( keysDown & KEY_ZR ) )
{
2019-06-28 21:13:54 +01:00
if ( ( selectedAppInfoIndex + 1 ) < titleAppCount )
{
selectedAppInfoIndex + + ;
dumpedContentInfoStr [ 0 ] = ' \0 ' ;
}
2019-06-05 23:44:18 +01:00
}
}
2019-04-21 17:27:33 +01:00
if ( uiState = = stateXciDumpMenu )
{
// Select
2019-04-23 06:14:57 +01:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 ) res = resultDumpXci ;
2019-04-21 17:27:33 +01:00
// Back
2019-06-09 02:36:21 +01:00
if ( keysDown & KEY_B ) res = resultShowGameCardMenu ;
2019-04-21 17:27:33 +01:00
// Change option to false
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . isFat32 = dumpCfg . xciDumpCfg . setXciArchiveBit = false ;
2019-06-05 23:44:18 +01:00
break ;
case 2 : // Create directory with archive bit set
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . setXciArchiveBit = false ;
2019-04-21 17:27:33 +01:00
break ;
2019-09-15 03:45:27 +01:00
case 3 : // Keep certificate
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . keepCert = false ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
case 4 : // Trim output dump
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . trimDump = false ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
case 5 : // CRC32 checksum calculation + dump verification
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . calcCrc = false ;
2019-04-21 17:27:33 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Dump verification method
dumpCfg . xciDumpCfg . useNoIntroLookup = false ;
break ;
case 7 : // Output naming scheme
dumpCfg . xciDumpCfg . useBrackets = false ;
break ;
2019-04-21 17:27:33 +01:00
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-04-21 17:27:33 +01:00
}
// Change option to true
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . isFat32 = true ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
case 2 : // Create directory with archive bit set
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . setXciArchiveBit = true ;
2019-06-05 23:44:18 +01:00
break ;
2019-09-15 03:45:27 +01:00
case 3 : // Keep certificate
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . keepCert = true ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
case 4 : // Trim output dump
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . trimDump = true ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
case 5 : // CRC32 checksum calculation + dump verification
2019-10-17 21:15:35 +01:00
dumpCfg . xciDumpCfg . calcCrc = true ;
2019-04-21 17:27:33 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Dump verification method
dumpCfg . xciDumpCfg . useNoIntroLookup = true ;
break ;
case 7 : // Output naming scheme
dumpCfg . xciDumpCfg . useBrackets = true ;
break ;
2019-04-21 17:27:33 +01:00
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-04-21 17:27:33 +01:00
}
// Go up
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
2019-04-21 17:27:33 +01:00
2019-05-01 21:24:13 +01:00
// Go down
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
2019-05-01 21:24:13 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu )
2019-05-01 21:24:13 +01:00
{
// Select
2019-06-05 23:44:18 +01:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 )
{
selectedNspDumpType = ( uiState = = stateNspAppDumpMenu ? DUMP_APP_NSP : ( uiState = = stateNspPatchDumpMenu ? DUMP_PATCH_NSP : DUMP_ADDON_NSP ) ) ;
res = resultDumpNsp ;
}
2019-05-01 21:24:13 +01:00
// Back
2019-06-05 23:44:18 +01:00
if ( keysDown & KEY_B )
{
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( uiState = = stateNspAppDumpMenu & & ! titlePatchCount & & ! titleAddOnCount )
{
res = resultShowGameCardMenu ;
} else {
res = resultShowNspDumpMenu ;
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
if ( ! orphanMode )
{
if ( uiState = = stateNspAppDumpMenu & & ( ! titlePatchCount | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) & & ( ! titleAddOnCount | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) )
{
res = resultShowSdCardEmmcTitleMenu ;
} else {
res = resultShowNspDumpMenu ;
}
} else {
2019-11-06 18:22:40 +00:00
res = resultShowSdCardEmmcTitleMenu ;
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
}
}
2019-05-01 21:24:13 +01:00
// Change option to false
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . isFat32 = false ;
2019-05-01 21:24:13 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 2 : // Verify dump using No-Intro database
dumpCfg . nspDumpCfg . useNoIntroLookup = false ;
2019-05-01 21:24:13 +01:00
break ;
2019-06-09 02:36:21 +01:00
case 3 : // Remove console specific data
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . removeConsoleData = dumpCfg . nspDumpCfg . tiklessDump = false ;
2019-06-09 02:36:21 +01:00
break ;
case 4 : // Generate ticket-less dump
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . tiklessDump = false ;
2019-06-09 02:36:21 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 5 : // Change NPDM RSA key/sig in Program NCA || DLC to dump
if ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu )
2019-05-01 21:24:13 +01:00
{
2019-11-06 18:22:40 +00:00
dumpCfg . nspDumpCfg . npdmAcidRsaPatch = false ;
2019-06-05 23:44:18 +01:00
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateNspAddOnDumpMenu )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( selectedAddOnIndex > 0 )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedAddOnIndex - - ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
if ( ! orphanMode )
{
2019-11-06 18:22:40 +00:00
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppInfoIndex , true ) ;
if ( newIndex ! = selectedAddOnIndex )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedAddOnIndex = newIndex ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
}
2019-06-05 23:44:18 +01:00
}
2019-11-06 18:22:40 +00:00
}
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Application to dump || Dump delta fragments || Output naming scheme (DLC)
2019-11-06 18:22:40 +00:00
if ( uiState = = stateNspAppDumpMenu )
{
if ( menuType = = MENUTYPE_GAMECARD )
{
if ( selectedAppIndex > 0 )
{
selectedAppIndex - - ;
titleSelectorStr [ 0 ] = ' \0 ' ;
}
}
2019-06-05 23:44:18 +01:00
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateNspPatchDumpMenu )
2019-12-11 08:56:58 +00:00
{
dumpCfg . nspDumpCfg . dumpDeltaFragments = false ;
} else
if ( uiState = = stateNspAddOnDumpMenu )
{
dumpCfg . nspDumpCfg . useBrackets = false ;
}
break ;
case 7 : // Output naming scheme (base application) || Update to dump
if ( uiState = = stateNspAppDumpMenu )
{
dumpCfg . nspDumpCfg . useBrackets = false ;
} else
if ( uiState = = stateNspPatchDumpMenu )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( selectedPatchIndex > 0 )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedPatchIndex - - ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
if ( ! orphanMode )
{
2019-11-06 18:22:40 +00:00
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppInfoIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedPatchIndex = newIndex ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
}
2019-06-05 23:44:18 +01:00
}
2019-05-01 21:24:13 +01:00
}
break ;
2019-12-11 08:56:58 +00:00
case 8 : // Output naming scheme (update)
dumpCfg . nspDumpCfg . useBrackets = false ;
break ;
2019-05-01 21:24:13 +01:00
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-05-01 21:24:13 +01:00
}
// Change option to true
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
case 1 : // Split output dump (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . isFat32 = true ;
2019-05-01 21:24:13 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 2 : // Verify dump using No-Intro database
dumpCfg . nspDumpCfg . useNoIntroLookup = true ;
2019-05-01 21:24:13 +01:00
break ;
2019-06-09 02:36:21 +01:00
case 3 : // Remove console specific data
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . removeConsoleData = true ;
2019-06-09 02:36:21 +01:00
break ;
case 4 : // Generate ticket-less dump
2019-10-17 21:15:35 +01:00
dumpCfg . nspDumpCfg . tiklessDump = true ;
2019-06-09 02:36:21 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 5 : // Change NPDM RSA key/sig in Program NCA || DLC to dump
if ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
dumpCfg . nspDumpCfg . npdmAcidRsaPatch = true ;
} else {
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( titleAddOnCount > 1 & & ( selectedAddOnIndex + 1 ) < titleAddOnCount )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedAddOnIndex + + ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
if ( ! orphanMode )
{
2019-11-06 18:22:40 +00:00
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedAddOnIndex , selectedAppInfoIndex , true ) ;
if ( newIndex ! = selectedAddOnIndex )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedAddOnIndex = newIndex ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
}
2019-06-05 23:44:18 +01:00
}
2019-11-06 18:22:40 +00:00
}
break ;
2019-12-11 08:56:58 +00:00
case 6 : // Application to dump || Dump delta fragments || Output naming scheme (DLC)
2019-11-06 18:22:40 +00:00
if ( uiState = = stateNspAppDumpMenu )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
{
2019-11-06 18:22:40 +00:00
if ( titleAppCount > 1 & & ( selectedAppIndex + 1 ) < titleAppCount )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedAppIndex + + ;
titleSelectorStr [ 0 ] = ' \0 ' ;
}
}
2019-12-11 08:56:58 +00:00
} else
if ( uiState = = stateNspPatchDumpMenu )
{
dumpCfg . nspDumpCfg . dumpDeltaFragments = true ;
} else
if ( uiState = = stateNspAddOnDumpMenu )
{
dumpCfg . nspDumpCfg . useBrackets = true ;
}
break ;
case 7 : // Output naming scheme (base application) || Update to dump
if ( uiState = = stateNspAppDumpMenu )
{
dumpCfg . nspDumpCfg . useBrackets = true ;
} else
if ( uiState = = stateNspPatchDumpMenu )
{
2019-11-06 18:22:40 +00:00
if ( menuType = = MENUTYPE_GAMECARD )
{
if ( titlePatchCount > 1 & & ( selectedPatchIndex + 1 ) < titlePatchCount )
{
selectedPatchIndex + + ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
} else
if ( menuType = = MENUTYPE_SDCARD_EMMC )
2019-06-05 23:44:18 +01:00
{
2019-06-09 02:36:21 +01:00
if ( ! orphanMode )
{
2019-11-06 18:22:40 +00:00
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppInfoIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
2019-06-09 02:36:21 +01:00
{
2019-11-06 18:22:40 +00:00
selectedPatchIndex = newIndex ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
}
2019-06-05 23:44:18 +01:00
}
}
break ;
2019-12-11 08:56:58 +00:00
case 8 : // Output naming scheme (update)
dumpCfg . nspDumpCfg . useBrackets = true ;
break ;
2019-06-05 23:44:18 +01:00
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-06-05 23:44:18 +01:00
}
// Go up
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
2019-06-05 23:44:18 +01:00
// Go down
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
2019-06-05 23:44:18 +01:00
} else
2019-06-28 21:13:54 +01:00
if ( uiState = = stateSdCardEmmcBatchModeMenu )
{
// Select
2019-10-17 21:15:35 +01:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 & & ( dumpCfg . batchDumpCfg . dumpAppTitles | | dumpCfg . batchDumpCfg . dumpPatchTitles | | dumpCfg . batchDumpCfg . dumpAddOnTitles ) ) res = resultSdCardEmmcBatchDump ;
2019-06-28 21:13:54 +01:00
// Back
if ( keysDown & KEY_B ) res = resultShowSdCardEmmcMenu ;
// Change option to false
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
case 1 : // Dump base applications
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = false ;
2019-06-28 21:13:54 +01:00
break ;
case 2 : // Dump updates
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpPatchTitles = false ;
2019-06-28 21:13:54 +01:00
break ;
case 3 : // Dump DLCs
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAddOnTitles = false ;
2019-06-28 21:13:54 +01:00
break ;
case 4 : // Split output dumps (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . isFat32 = false ;
2019-06-28 21:13:54 +01:00
break ;
case 5 : // Remove console specific data
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . removeConsoleData = dumpCfg . batchDumpCfg . tiklessDump = false ;
2019-06-28 21:13:54 +01:00
break ;
case 6 : // Generate ticket-less dumps
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . tiklessDump = false ;
2019-06-28 21:13:54 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 7 : // Change NPDM RSA key/sig in Program NCA
dumpCfg . batchDumpCfg . npdmAcidRsaPatch = false ;
break ;
2019-12-11 08:56:58 +00:00
case 8 : // Dump delta fragments from updates
dumpCfg . batchDumpCfg . dumpDeltaFragments = false ;
break ;
case 9 : // Skip already dumped titles
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . skipDumpedTitles = false ;
2019-06-28 21:13:54 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 10 : // Remember dumped titles
2019-11-06 18:22:40 +00:00
dumpCfg . batchDumpCfg . rememberDumpedTitles = false ;
break ;
2019-12-11 08:56:58 +00:00
case 11 : // Halt dump process on errors
dumpCfg . batchDumpCfg . haltOnErrors = false ;
break ;
case 12 : // Output naming scheme
dumpCfg . batchDumpCfg . useBrackets = false ;
break ;
case 13 : // Source storage
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc ! = BATCH_SOURCE_ALL )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . batchModeSrc - - ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( titleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( titlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( titleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
} else
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( sdCardTitleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( sdCardTitlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( sdCardTitleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
} else
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( emmcTitleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( emmcTitlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( emmcTitleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
}
}
break ;
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-06-28 21:13:54 +01:00
}
// Change option to true
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
case 1 : // Dump base applications
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = true ;
2019-06-28 21:13:54 +01:00
break ;
case 2 : // Dump updates
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpPatchTitles = true ;
2019-06-28 21:13:54 +01:00
break ;
case 3 : // Dump DLCs
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAddOnTitles = true ;
2019-06-28 21:13:54 +01:00
break ;
case 4 : // Split output dumps (FAT32 support)
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . isFat32 = true ;
2019-06-28 21:13:54 +01:00
break ;
case 5 : // Remove console specific data
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . removeConsoleData = true ;
2019-06-28 21:13:54 +01:00
break ;
case 6 : // Generate ticket-less dumps
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . tiklessDump = true ;
2019-06-28 21:13:54 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 7 : // Change NPDM RSA key/sig in Program NCA
dumpCfg . batchDumpCfg . npdmAcidRsaPatch = true ;
break ;
2019-12-11 08:56:58 +00:00
case 8 : // Dump delta fragments from updates
dumpCfg . batchDumpCfg . dumpDeltaFragments = true ;
break ;
case 9 : // Skip already dumped titles
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . skipDumpedTitles = true ;
2019-06-28 21:13:54 +01:00
break ;
2019-12-11 08:56:58 +00:00
case 10 : // Remember dumped titles
2019-11-06 18:22:40 +00:00
dumpCfg . batchDumpCfg . rememberDumpedTitles = true ;
break ;
2019-12-11 08:56:58 +00:00
case 11 : // Halt dump process on errors
dumpCfg . batchDumpCfg . haltOnErrors = true ;
break ;
case 12 : // Output naming scheme
dumpCfg . batchDumpCfg . useBrackets = true ;
break ;
case 13 : // Source storage
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc ! = BATCH_SOURCE_EMMC )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . batchModeSrc + + ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( titleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( titlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( titleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
} else
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD )
2019-06-28 21:13:54 +01:00
{
2019-10-17 21:15:35 +01:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( sdCardTitleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( sdCardTitlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( sdCardTitleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
} else
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
dumpCfg . batchDumpCfg . dumpAppTitles = ( emmcTitleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( emmcTitlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( emmcTitleAddOnCount > 0 ) ;
2019-06-28 21:13:54 +01:00
}
}
break ;
default :
break ;
}
2019-10-17 21:15:35 +01:00
// Save settings to configuration file
saveConfig ( ) ;
2019-06-28 21:13:54 +01:00
}
// Go up
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
// Go down
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
} else
2019-09-15 03:45:27 +01:00
if ( uiState = = stateExeFsMenu )
2019-06-28 21:13:54 +01:00
{
// Select
if ( keysDown & KEY_A )
{
// Reset option to its default value
selectedAppIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
switch ( cursor )
{
case 0 :
2019-09-15 03:45:27 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowExeFsSectionDataDumpMenu : resultDumpExeFsSectionData ) ;
2019-06-28 21:13:54 +01:00
break ;
case 1 :
2019-09-15 03:45:27 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowExeFsSectionBrowserMenu : resultExeFsSectionBrowserGetList ) ;
2019-06-28 21:13:54 +01:00
break ;
default :
break ;
}
}
// Back
if ( keysDown & KEY_B )
{
if ( menuType = = MENUTYPE_GAMECARD )
{
2019-12-11 08:56:58 +00:00
freeTitlesFromSdCardAndEmmc ( NcmContentMetaType_Patch ) ;
2019-06-28 21:13:54 +01:00
res = resultShowGameCardMenu ;
} else {
res = resultShowSdCardEmmcTitleMenu ;
}
}
// Go left
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
dumpCfg . exeFsDumpCfg . isFat32 = false ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
dumpCfg . exeFsDumpCfg . useLayeredFSDir = false ;
break ;
case 4 : // Use update
2019-06-28 21:13:54 +01:00
if ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 & & checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) )
{
2019-09-15 03:45:27 +01:00
if ( exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , appIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
{
selectedPatchIndex = newIndex ;
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2019-06-28 21:13:54 +01:00
} else {
2019-09-15 03:45:27 +01:00
exeFsUpdateFlag = false ;
2019-06-28 21:13:54 +01:00
}
}
}
break ;
default :
break ;
}
}
// Go right
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
dumpCfg . exeFsDumpCfg . isFat32 = true ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
dumpCfg . exeFsDumpCfg . useLayeredFSDir = true ;
break ;
case 4 : // Use update
2019-06-28 21:13:54 +01:00
if ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 & & checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) )
{
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
2019-09-15 03:45:27 +01:00
if ( exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , appIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
{
selectedPatchIndex = newIndex ;
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2019-06-28 21:13:54 +01:00
}
} else {
2019-09-15 03:45:27 +01:00
exeFsUpdateFlag = true ;
2019-06-28 21:13:54 +01:00
selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( appIndex , false ) ;
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2019-06-28 21:13:54 +01:00
}
}
break ;
default :
break ;
}
}
// Go up
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
// Go down
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu )
2019-06-05 23:44:18 +01:00
{
// Select
2019-11-06 18:22:40 +00:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 ) res = ( uiState = = stateExeFsSectionDataDumpMenu ? resultDumpExeFsSectionData : resultExeFsSectionBrowserGetList ) ;
// Back
if ( keysDown & KEY_B ) res = resultShowExeFsMenu ;
// Change option to false
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
case 1 : // Bundled application to dump/browse
if ( menuType = = MENUTYPE_GAMECARD )
{
if ( selectedAppIndex > 0 )
{
selectedAppIndex - - ;
titleSelectorStr [ 0 ] = ' \0 ' ;
exeFsUpdateFlag = false ;
}
}
break ;
case 2 : // Use update
if ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) )
{
if ( exeFsUpdateFlag )
{
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
{
selectedPatchIndex = newIndex ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
} else {
exeFsUpdateFlag = false ;
}
}
}
break ;
default :
break ;
}
}
// Change option to true
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
case 1 : // Bundled application to dump/browse
if ( menuType = = MENUTYPE_GAMECARD )
{
if ( titleAppCount > 1 & & ( selectedAppIndex + 1 ) < titleAppCount )
{
selectedAppIndex + + ;
titleSelectorStr [ 0 ] = ' \0 ' ;
exeFsUpdateFlag = false ;
}
}
break ;
case 2 : // Use update
if ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) )
{
if ( exeFsUpdateFlag )
{
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( selectedPatchIndex , selectedAppIndex , false ) ;
if ( newIndex ! = selectedPatchIndex )
{
selectedPatchIndex = newIndex ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
} else {
exeFsUpdateFlag = true ;
selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppIndex , false ) ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
}
break ;
default :
break ;
}
}
// Go up
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
// Go down
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
} else
if ( uiState = = stateRomFsMenu )
{
// Select
if ( keysDown & KEY_A )
{
// Reset option to its default value
2019-09-15 03:45:27 +01:00
if ( ! orphanMode ) selectedAppIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
switch ( cursor )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
case 0 :
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionDataDumpMenu : resultDumpRomFsSectionData ) ;
break ;
case 1 :
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionBrowserMenu : resultRomFsSectionBrowserGetEntries ) ;
break ;
default :
break ;
2019-06-09 02:36:21 +01:00
}
}
2019-06-05 23:44:18 +01:00
// Back
2019-09-15 03:45:27 +01:00
if ( keysDown & KEY_B )
{
if ( menuType = = MENUTYPE_GAMECARD )
{
2019-12-11 08:56:58 +00:00
freeTitlesFromSdCardAndEmmc ( NcmContentMetaType_Patch ) ;
freeTitlesFromSdCardAndEmmc ( NcmContentMetaType_AddOnContent ) ;
2019-09-15 03:45:27 +01:00
res = resultShowGameCardMenu ;
} else {
res = resultShowSdCardEmmcTitleMenu ;
}
}
2019-06-05 23:44:18 +01:00
2019-09-15 03:45:27 +01:00
// Go left
2019-06-05 23:44:18 +01:00
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
dumpCfg . romFsDumpCfg . isFat32 = false ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
dumpCfg . romFsDumpCfg . useLayeredFSDir = false ;
break ;
case 4 : // Use update/DLC
2019-09-15 03:45:27 +01:00
if ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 & & ( checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( 0 , true ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) )
2019-06-05 23:44:18 +01:00
{
2019-09-15 03:45:27 +01:00
if ( curRomFsType ! = ROMFS_TYPE_APP )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
u32 curIndex = ( curRomFsType = = ROMFS_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( curIndex , appIndex , ( curRomFsType = = ROMFS_TYPE_ADDON ) ) ;
2019-06-28 21:13:54 +01:00
2019-09-15 03:45:27 +01:00
if ( newIndex ! = curIndex )
{
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
} else {
if ( curRomFsType = = ROMFS_TYPE_ADDON )
{
if ( checkIfBaseApplicationHasPatchOrAddOn ( appIndex , false ) )
{
curRomFsType = ROMFS_TYPE_PATCH ;
selectedPatchIndex = retrieveLastPatchOrAddOnIndexFromBaseApplication ( appIndex , false ) ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
} else {
curRomFsType = ROMFS_TYPE_APP ;
}
} else {
curRomFsType = ROMFS_TYPE_APP ;
}
}
2019-06-28 21:13:54 +01:00
}
}
break ;
2019-09-15 03:45:27 +01:00
default :
break ;
}
}
// Go right
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
2019-12-11 08:56:58 +00:00
case 2 : // Split files bigger than 4 GiB (FAT32 support)
dumpCfg . romFsDumpCfg . isFat32 = true ;
break ;
case 3 : // Save data to CFW directory (LayeredFS)
dumpCfg . romFsDumpCfg . useLayeredFSDir = true ;
break ;
case 4 : // Use update/DLC
2019-09-15 03:45:27 +01:00
if ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount = = 1 & & ( checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( 0 , true ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) )
{
u32 appIndex = ( menuType = = MENUTYPE_GAMECARD ? 0 : selectedAppInfoIndex ) ;
if ( curRomFsType ! = ROMFS_TYPE_APP )
{
u32 curIndex = ( curRomFsType = = ROMFS_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( curIndex , appIndex , ( curRomFsType = = ROMFS_TYPE_ADDON ) ) ;
if ( newIndex ! = curIndex )
{
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
} else {
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
if ( checkIfBaseApplicationHasPatchOrAddOn ( appIndex , true ) )
{
curRomFsType = ROMFS_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( appIndex , true ) ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
}
}
} else {
if ( checkIfBaseApplicationHasPatchOrAddOn ( appIndex , false ) )
{
curRomFsType = ROMFS_TYPE_PATCH ;
selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( appIndex , false ) ;
} else {
curRomFsType = ROMFS_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( appIndex , true ) ;
}
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
}
break ;
default :
break ;
}
}
// Go up
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
// Go down
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu )
2019-09-15 03:45:27 +01:00
{
// Select
2019-11-06 18:22:40 +00:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 ) res = ( uiState = = stateRomFsSectionDataDumpMenu ? resultDumpRomFsSectionData : resultRomFsSectionBrowserGetEntries ) ;
2019-09-15 03:45:27 +01:00
// Back
2019-11-06 18:22:40 +00:00
if ( keysDown & KEY_B ) res = resultShowRomFsMenu ;
2019-09-15 03:45:27 +01:00
// Change option to false
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
case 1 : // Bundled application to dump/browse
if ( menuType = = MENUTYPE_GAMECARD )
{
if ( selectedAppIndex > 0 )
{
selectedAppIndex - - ;
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-11-06 18:22:40 +00:00
curRomFsType = ROMFS_TYPE_APP ;
2019-09-15 03:45:27 +01:00
}
}
break ;
2019-11-06 18:22:40 +00:00
case 2 : // Use update/DLC
if ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curRomFsType ! = ROMFS_TYPE_APP )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
u32 curIndex = ( curRomFsType = = ROMFS_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( curIndex , selectedAppIndex , ( curRomFsType = = ROMFS_TYPE_ADDON ) ) ;
if ( newIndex ! = curIndex )
2019-06-28 21:13:54 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2019-06-28 21:13:54 +01:00
} else {
2019-11-06 18:22:40 +00:00
if ( curRomFsType = = ROMFS_TYPE_ADDON )
{
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) )
{
curRomFsType = ROMFS_TYPE_PATCH ;
selectedPatchIndex = retrieveLastPatchOrAddOnIndexFromBaseApplication ( selectedAppIndex , false ) ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
} else {
curRomFsType = ROMFS_TYPE_APP ;
}
} else {
curRomFsType = ROMFS_TYPE_APP ;
}
2019-06-28 21:13:54 +01:00
}
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
}
break ;
default :
break ;
}
}
// Change option to true
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
case 1 : // Bundled application to dump/browse
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_GAMECARD )
2019-05-01 21:24:13 +01:00
{
2019-06-20 04:56:14 +01:00
if ( titleAppCount > 1 & & ( selectedAppIndex + 1 ) < titleAppCount )
2019-06-09 02:36:21 +01:00
{
selectedAppIndex + + ;
2019-06-20 04:56:14 +01:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-11-06 18:22:40 +00:00
curRomFsType = ROMFS_TYPE_APP ;
2019-06-28 21:13:54 +01:00
}
}
break ;
case 2 : // Use update
2019-11-06 18:22:40 +00:00
if ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) )
2019-06-28 21:13:54 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curRomFsType ! = ROMFS_TYPE_APP )
2019-06-28 21:13:54 +01:00
{
2019-11-06 18:22:40 +00:00
u32 curIndex = ( curRomFsType = = ROMFS_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( curIndex , selectedAppIndex , ( curRomFsType = = ROMFS_TYPE_ADDON ) ) ;
if ( newIndex ! = curIndex )
2019-06-28 21:13:54 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
2019-11-06 18:22:40 +00:00
} else {
if ( curRomFsType = = ROMFS_TYPE_PATCH )
{
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) )
{
curRomFsType = ROMFS_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppIndex , true ) ;
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
}
2019-06-28 21:13:54 +01:00
}
} else {
2019-11-06 18:22:40 +00:00
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) )
{
curRomFsType = ROMFS_TYPE_PATCH ;
selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppIndex , false ) ;
} else {
curRomFsType = ROMFS_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppIndex , true ) ;
}
2019-09-15 03:45:27 +01:00
exeFsAndRomFsSelectorStr [ 0 ] = ' \0 ' ;
}
}
break ;
default :
break ;
}
}
// Go up
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
// Go down
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateTicketMenu )
2019-09-15 03:45:27 +01:00
{
// Select
2019-11-06 18:22:40 +00:00
if ( ( keysDown & KEY_A ) & & cursor = = 0 ) res = resultDumpTicket ;
2019-09-15 03:45:27 +01:00
// Back
2019-11-06 18:22:40 +00:00
if ( keysDown & KEY_B ) res = resultShowSdCardEmmcTitleMenu ;
2019-09-15 03:45:27 +01:00
2019-11-06 18:22:40 +00:00
// Go left
2019-09-15 03:45:27 +01:00
if ( keysDown & KEY_LEFT )
{
switch ( cursor )
{
2019-11-06 18:22:40 +00:00
case 1 : // Remove console specific data
dumpCfg . tikDumpCfg . removeConsoleData = false ;
saveConfig ( ) ;
2019-09-15 03:45:27 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 2 : // Use ticket from title
if ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curTikType ! = TICKET_TYPE_APP )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
u32 curIndex = ( curTikType = = TICKET_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrievePreviousPatchOrAddOnIndexFromBaseApplication ( curIndex , selectedAppInfoIndex , ( curTikType = = TICKET_TYPE_ADDON ) ) ;
2019-09-15 03:45:27 +01:00
if ( newIndex ! = curIndex )
{
2019-11-06 18:22:40 +00:00
if ( curTikType = = TICKET_TYPE_PATCH )
2019-09-15 03:45:27 +01:00
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
2019-11-06 18:22:40 +00:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
} else {
2019-11-06 18:22:40 +00:00
if ( curTikType = = TICKET_TYPE_ADDON )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_PATCH ;
selectedPatchIndex = retrieveLastPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , false ) ;
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
} else {
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_APP ;
2019-09-15 03:45:27 +01:00
}
} else {
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_APP ;
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
}
}
}
}
break ;
default :
break ;
}
}
2019-11-06 18:22:40 +00:00
// Go right
2019-09-15 03:45:27 +01:00
if ( keysDown & KEY_RIGHT )
{
switch ( cursor )
{
2019-11-06 18:22:40 +00:00
case 1 : // Remove console specific data
dumpCfg . tikDumpCfg . removeConsoleData = true ;
saveConfig ( ) ;
2019-09-15 03:45:27 +01:00
break ;
2019-11-06 18:22:40 +00:00
case 2 : // Use update/DLC
if ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) | | checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
if ( curTikType ! = TICKET_TYPE_APP )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
u32 curIndex = ( curTikType = = TICKET_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ;
u32 newIndex = retrieveNextPatchOrAddOnIndexFromBaseApplication ( curIndex , selectedAppInfoIndex , ( curTikType = = TICKET_TYPE_ADDON ) ) ;
2019-09-15 03:45:27 +01:00
if ( newIndex ! = curIndex )
{
2019-11-06 18:22:40 +00:00
if ( curTikType = = TICKET_TYPE_PATCH )
2019-09-15 03:45:27 +01:00
{
selectedPatchIndex = newIndex ;
} else {
selectedAddOnIndex = newIndex ;
}
2019-11-06 18:22:40 +00:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
} else {
2019-11-06 18:22:40 +00:00
if ( curTikType = = TICKET_TYPE_PATCH )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , true ) ;
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-09-15 03:45:27 +01:00
}
}
}
} else {
2019-11-06 18:22:40 +00:00
if ( checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) )
2019-09-15 03:45:27 +01:00
{
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_PATCH ;
selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , false ) ;
2019-09-15 03:45:27 +01:00
} else {
2019-11-06 18:22:40 +00:00
curTikType = TICKET_TYPE_ADDON ;
selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , true ) ;
2019-09-15 03:45:27 +01:00
}
2019-11-06 18:22:40 +00:00
titleSelectorStr [ 0 ] = ' \0 ' ;
2019-06-09 02:36:21 +01:00
}
2019-05-01 21:24:13 +01:00
}
break ;
default :
break ;
}
}
// Go up
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
2019-05-01 21:24:13 +01:00
2019-04-21 17:27:33 +01:00
// Go down
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
2019-04-21 17:27:33 +01:00
} else {
// Select
if ( keysDown & KEY_A )
{
if ( uiState = = stateMainMenu )
2019-06-09 02:36:21 +01:00
{
selectedAppInfoIndex = 0 ;
switch ( cursor )
{
case 0 :
res = resultShowGameCardMenu ;
menuType = MENUTYPE_GAMECARD ;
break ;
case 1 :
2019-11-06 18:22:40 +00:00
if ( keysFileAvailable )
{
res = resultShowSdCardEmmcMenu ;
menuType = MENUTYPE_SDCARD_EMMC ;
} else {
uiStatusMsg ( " Keys file unavailable at \" %s \" . Option disabled. " , KEYS_FILE_PATH ) ;
}
2019-06-09 02:36:21 +01:00
break ;
case 2 :
res = resultShowUpdateMenu ;
break ;
default :
break ;
}
} else
if ( uiState = = stateGameCardMenu )
2019-04-21 17:27:33 +01:00
{
switch ( cursor )
{
case 0 :
res = resultShowXciDumpMenu ;
break ;
case 1 :
2019-11-06 18:22:40 +00:00
if ( keysFileAvailable )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( ! titlePatchCount & & ! titleAddOnCount )
{
res = resultShowNspAppDumpMenu ;
// Reset option to its default value
selectedAppIndex = 0 ;
} else {
res = resultShowNspDumpMenu ;
}
2019-06-05 23:44:18 +01:00
} else {
2019-11-06 18:22:40 +00:00
uiStatusMsg ( " Keys file unavailable at \" %s \" . Option disabled. " , KEYS_FILE_PATH ) ;
2019-06-05 23:44:18 +01:00
}
2019-04-21 17:27:33 +01:00
break ;
case 2 :
2019-06-05 23:44:18 +01:00
res = resultShowHfs0Menu ;
2019-04-21 17:27:33 +01:00
break ;
case 3 :
2019-11-06 18:22:40 +00:00
if ( keysFileAvailable )
{
2019-12-11 08:56:58 +00:00
loadTitlesFromSdCardAndEmmc ( NcmContentMetaType_Patch ) ;
2019-11-06 18:22:40 +00:00
res = resultShowExeFsMenu ;
// Reset options to their default values
exeFsUpdateFlag = false ;
selectedPatchIndex = 0 ;
} else {
uiStatusMsg ( " Keys file unavailable at \" %s \" . Option disabled. " , KEYS_FILE_PATH ) ;
}
2019-09-15 03:45:27 +01:00
break ;
case 4 :
2019-11-06 18:22:40 +00:00
if ( keysFileAvailable )
{
2019-12-11 08:56:58 +00:00
loadTitlesFromSdCardAndEmmc ( NcmContentMetaType_Patch ) ;
loadTitlesFromSdCardAndEmmc ( NcmContentMetaType_AddOnContent ) ;
2019-11-06 18:22:40 +00:00
res = resultShowRomFsMenu ;
// Reset options to their default values
selectedPatchIndex = selectedAddOnIndex = 0 ;
curRomFsType = ROMFS_TYPE_APP ;
} else {
uiStatusMsg ( " Keys file unavailable at \" %s \" . Option disabled. " , KEYS_FILE_PATH ) ;
}
2019-04-21 17:27:33 +01:00
break ;
case 5 :
2019-06-09 02:36:21 +01:00
res = resultDumpGameCardCertificate ;
2019-04-21 17:27:33 +01:00
break ;
2019-06-05 23:44:18 +01:00
default :
2019-05-01 21:24:13 +01:00
break ;
2019-06-05 23:44:18 +01:00
}
} else
if ( uiState = = stateNspDumpMenu )
{
2019-06-09 02:36:21 +01:00
// Reset options to their default values
selectedAppIndex = 0 ;
selectedPatchIndex = 0 ;
selectedAddOnIndex = 0 ;
2019-06-05 23:44:18 +01:00
switch ( cursor )
{
case 0 :
res = resultShowNspAppDumpMenu ;
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_SDCARD_EMMC ) selectedAppIndex = selectedAppInfoIndex ;
2019-06-05 23:44:18 +01:00
break ;
case 1 :
2019-11-06 18:22:40 +00:00
res = resultShowNspPatchDumpMenu ;
if ( menuType = = MENUTYPE_SDCARD_EMMC ) selectedPatchIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , false ) ;
2019-06-05 23:44:18 +01:00
break ;
case 2 :
res = resultShowNspAddOnDumpMenu ;
2019-11-06 18:22:40 +00:00
if ( menuType = = MENUTYPE_SDCARD_EMMC ) selectedAddOnIndex = retrieveFirstPatchOrAddOnIndexFromBaseApplication ( selectedAppInfoIndex , true ) ;
2019-06-05 23:44:18 +01:00
break ;
default :
break ;
}
} else
if ( uiState = = stateHfs0Menu )
{
switch ( cursor )
{
case 0 :
res = resultShowRawHfs0PartitionDumpMenu ;
break ;
case 1 :
res = resultShowHfs0PartitionDataDumpMenu ;
break ;
case 2 :
res = resultShowHfs0BrowserMenu ;
2019-04-21 17:27:33 +01:00
break ;
default :
break ;
}
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateRawHfs0PartitionDumpMenu )
2019-04-21 17:27:33 +01:00
{
2019-04-23 06:14:57 +01:00
// Save selected partition index
selectedPartitionIndex = ( u32 ) cursor ;
2019-06-05 23:44:18 +01:00
res = resultDumpRawHfs0Partition ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateHfs0PartitionDataDumpMenu )
2019-04-21 17:27:33 +01:00
{
2019-04-23 06:14:57 +01:00
// Save selected partition index
selectedPartitionIndex = ( u32 ) cursor ;
2019-06-05 23:44:18 +01:00
res = resultDumpHfs0PartitionData ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateHfs0BrowserMenu )
2019-04-21 17:27:33 +01:00
{
2019-04-23 06:14:57 +01:00
// Save selected partition index
selectedPartitionIndex = ( u32 ) cursor ;
2019-06-05 23:44:18 +01:00
res = resultHfs0BrowserGetList ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateHfs0Browser )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
if ( menu & & menuItemsCount )
{
// Save selected file index
selectedFileIndex = ( u32 ) cursor ;
res = resultHfs0BrowserCopyFile ;
}
2019-06-05 23:44:18 +01:00
} else
2019-06-09 02:36:21 +01:00
if ( uiState = = stateExeFsSectionBrowser )
{
if ( menu & & menuItemsCount )
{
// Save selected file index
selectedFileIndex = ( u32 ) cursor ;
res = resultExeFsSectionBrowserCopyFile ;
}
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateRomFsSectionBrowser )
{
if ( menu & & menuItemsCount )
{
// Save selected file index
selectedFileIndex = ( u32 ) cursor ;
2019-11-06 18:22:40 +00:00
if ( strlen ( curRomFsPath ) < = 1 ) selectedFileIndex + + ; // Adjust index if we're at the root directory
2019-12-11 08:56:58 +00:00
res = ( romFsBrowserEntries [ selectedFileIndex ] . type = = ROMFS_ENTRY_DIR ? resultRomFsSectionBrowserChangeDir : resultRomFsSectionBrowserCopyFile ) ;
2019-06-05 23:44:18 +01:00
}
} else
2019-06-09 02:36:21 +01:00
if ( uiState = = stateSdCardEmmcMenu )
{
// Save selected base application index
selectedAppInfoIndex = ( u32 ) cursor ;
res = resultShowSdCardEmmcTitleMenu ;
} else
if ( uiState = = stateSdCardEmmcTitleMenu )
{
switch ( cursor )
{
case 0 :
2019-09-15 03:45:27 +01:00
if ( ! orphanMode )
2019-06-09 02:36:21 +01:00
{
2019-09-15 03:45:27 +01:00
if ( ( ! titlePatchCount | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) & & ( ! titleAddOnCount | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) )
{
res = resultShowNspAppDumpMenu ;
selectedAppIndex = selectedAppInfoIndex ;
} else {
res = resultShowNspDumpMenu ;
}
2019-06-09 02:36:21 +01:00
} else {
2019-11-06 18:22:40 +00:00
res = ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? resultShowNspPatchDumpMenu : resultShowNspAddOnDumpMenu ) ;
2019-06-09 02:36:21 +01:00
}
break ;
case 1 :
2019-12-11 08:56:58 +00:00
res = resultShowExeFsMenu ;
2019-09-15 03:45:27 +01:00
if ( ! orphanMode )
{
// Reset options to their default values
exeFsUpdateFlag = false ;
selectedPatchIndex = 0 ;
2019-12-11 08:56:58 +00:00
} else {
exeFsUpdateFlag = true ;
2019-09-15 03:45:27 +01:00
}
2019-12-11 08:56:58 +00:00
2019-09-15 03:45:27 +01:00
break ;
2019-06-09 02:36:21 +01:00
case 2 :
2019-09-15 03:45:27 +01:00
res = resultShowRomFsMenu ;
2019-06-28 21:13:54 +01:00
2019-09-15 03:45:27 +01:00
if ( ! orphanMode )
{
// Reset options to their default values
selectedPatchIndex = selectedAddOnIndex = 0 ;
curRomFsType = ROMFS_TYPE_APP ;
} else {
curRomFsType = ROMFS_TYPE_ADDON ;
}
2019-06-28 21:13:54 +01:00
2019-11-06 18:22:40 +00:00
break ;
case 3 :
res = resultShowTicketMenu ;
if ( ! orphanMode )
{
// Reset options to their default values
selectedPatchIndex = selectedAddOnIndex = 0 ;
curTikType = TICKET_TYPE_APP ;
} else {
curTikType = ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH ? TICKET_TYPE_PATCH : TICKET_TYPE_ADDON ) ;
}
2019-06-09 02:36:21 +01:00
break ;
default :
break ;
}
} else
if ( uiState = = stateSdCardEmmcOrphanPatchAddOnMenu )
{
if ( menu & & menuItemsCount )
{
if ( orphanEntries [ cursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH )
{
selectedPatchIndex = orphanEntries [ cursor ] . index ;
} else
if ( orphanEntries [ cursor ] . type = = ORPHAN_ENTRY_TYPE_ADDON )
{
selectedAddOnIndex = orphanEntries [ cursor ] . index ;
}
2019-11-06 18:22:40 +00:00
res = resultShowSdCardEmmcTitleMenu ;
2019-06-09 02:36:21 +01:00
}
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateUpdateMenu )
{
switch ( cursor )
{
case 0 :
res = resultUpdateNSWDBXml ;
break ;
case 1 :
2019-11-06 18:22:40 +00:00
if ( ! updatePerformed )
{
res = resultUpdateApplication ;
} else {
uiStatusMsg ( " Update already performed. Please restart the application. " ) ;
}
2019-06-05 23:44:18 +01:00
break ;
default :
break ;
}
2019-04-21 17:27:33 +01:00
}
}
// Back
if ( keysDown & KEY_B )
{
2019-06-09 02:36:21 +01:00
if ( uiState = = stateGameCardMenu | | uiState = = stateSdCardEmmcMenu | | uiState = = stateUpdateMenu )
2019-04-21 17:27:33 +01:00
{
res = resultShowMainMenu ;
2019-06-09 02:36:21 +01:00
menuType = MENUTYPE_MAIN ;
} else
2019-06-28 21:13:54 +01:00
if ( menuType = = MENUTYPE_GAMECARD & & ( uiState = = stateNspDumpMenu | | uiState = = stateHfs0Menu ) )
2019-06-09 02:36:21 +01:00
{
res = resultShowGameCardMenu ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateRawHfs0PartitionDumpMenu | | uiState = = stateHfs0PartitionDataDumpMenu | | uiState = = stateHfs0BrowserMenu )
{
res = resultShowHfs0Menu ;
} else
if ( uiState = = stateHfs0Browser )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
freeHfs0ExeFsEntriesSizes ( ) ;
2019-04-23 06:14:57 +01:00
2019-06-05 23:44:18 +01:00
res = resultShowHfs0BrowserMenu ;
} else
2019-06-09 02:36:21 +01:00
if ( uiState = = stateExeFsSectionBrowser )
{
2019-12-11 08:56:58 +00:00
freeHfs0ExeFsEntriesSizes ( ) ;
2019-06-09 02:36:21 +01:00
freeExeFsContext ( ) ;
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowExeFsSectionBrowserMenu : resultShowExeFsMenu ) ;
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateRomFsSectionBrowser )
{
if ( strlen ( curRomFsPath ) > 1 )
{
// Point to the parent directory entry ("..")
selectedFileIndex = 0 ;
res = resultRomFsSectionBrowserChangeDir ;
} else {
2019-12-11 08:56:58 +00:00
freeRomFsBrowserEntries ( ) ;
2019-06-05 23:44:18 +01:00
2019-09-15 03:45:27 +01:00
if ( curRomFsType = = ROMFS_TYPE_PATCH ) freeBktrContext ( ) ;
2019-06-28 21:13:54 +01:00
2019-06-05 23:44:18 +01:00
freeRomFsContext ( ) ;
2019-06-09 02:36:21 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionBrowserMenu : resultShowRomFsMenu ) ;
}
} else
if ( uiState = = stateSdCardEmmcTitleMenu )
{
2019-09-15 03:45:27 +01:00
res = ( ! orphanMode ? resultShowSdCardEmmcMenu : resultShowSdCardEmmcOrphanPatchAddOnMenu ) ;
2019-06-09 02:36:21 +01:00
} else
2019-11-06 18:22:40 +00:00
if ( menuType = = MENUTYPE_SDCARD_EMMC & & ! orphanMode & & uiState = = stateNspDumpMenu )
2019-06-09 02:36:21 +01:00
{
res = resultShowSdCardEmmcTitleMenu ;
} else
if ( uiState = = stateSdCardEmmcOrphanPatchAddOnMenu )
{
res = resultShowSdCardEmmcMenu ;
orphanMode = false ;
2019-04-21 17:27:33 +01:00
}
}
2019-06-28 21:13:54 +01:00
// Special action #1
if ( keysDown & KEY_Y )
2019-06-09 02:36:21 +01:00
{
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcMenu & & ( calculateOrphanPatchOrAddOnCount ( false ) | | calculateOrphanPatchOrAddOnCount ( true ) ) )
2019-06-28 21:13:54 +01:00
{
// SD/eMMC menu: Dump installed content with missing base application
res = resultShowSdCardEmmcOrphanPatchAddOnMenu ;
orphanMode = true ;
} else
if ( uiState = = stateRomFsSectionBrowser & & strlen ( curRomFsPath ) > 1 )
{
// RomFS section browser: dump current directory
res = resultRomFsSectionBrowserCopyDir ;
}
}
// Special action #2
if ( keysDown & KEY_X )
{
if ( uiState = = stateSdCardEmmcMenu & & ( titleAppCount | | titlePatchCount | | titleAddOnCount ) )
{
// Batch mode
res = resultShowSdCardEmmcBatchModeMenu ;
2019-10-17 21:15:35 +01:00
// Check if we're using the default configuration
if ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & ! dumpCfg . batchDumpCfg . dumpAppTitles & & ! dumpCfg . batchDumpCfg . dumpPatchTitles & & ! dumpCfg . batchDumpCfg . dumpAddOnTitles )
{
dumpCfg . batchDumpCfg . dumpAppTitles = ( titleAppCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpPatchTitles = ( titlePatchCount > 0 ) ;
dumpCfg . batchDumpCfg . dumpAddOnTitles = ( titleAddOnCount > 0 ) ;
}
2019-06-28 21:13:54 +01:00
}
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
if ( menu & & menuItemsCount )
{
// Go up
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) | | ( keysHeld & KEY_RSTICK_UP ) )
{
scrollAmount = - 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DUP ) | | ( keysDown & KEY_LSTICK_UP ) ) ;
}
2019-06-05 23:44:18 +01:00
if ( ( keysDown & KEY_DLEFT ) | | ( keysDown & KEY_LSTICK_LEFT ) | | ( keysHeld & KEY_RSTICK_LEFT ) ) scrollAmount = - 5 ;
// Go down
2019-06-20 04:56:14 +01:00
if ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) | | ( keysHeld & KEY_RSTICK_DOWN ) )
{
scrollAmount = 1 ;
scrollWithKeysDown = ( ( keysDown & KEY_DDOWN ) | | ( keysDown & KEY_LSTICK_DOWN ) ) ;
}
2019-06-05 23:44:18 +01:00
if ( ( keysDown & KEY_DRIGHT ) | | ( keysDown & KEY_LSTICK_RIGHT ) | | ( keysHeld & KEY_RSTICK_RIGHT ) ) scrollAmount = 5 ;
}
2019-04-21 17:27:33 +01:00
}
// Calculate scroll only if the UI state hasn't been changed
if ( res = = resultNone )
{
if ( scrollAmount > 0 )
{
2019-06-20 04:56:14 +01:00
if ( scrollWithKeysDown & & ( cursor + scrollAmount ) > ( menuItemsCount - 1 ) )
2019-04-21 17:27:33 +01:00
{
2019-06-20 04:56:14 +01:00
cursor = 0 ;
scroll = 0 ;
} else {
for ( i = 0 ; i < scrollAmount ; i + + )
2019-04-21 17:27:33 +01:00
{
2019-11-06 18:22:40 +00:00
if ( cursor > = ( menuItemsCount - 1 ) ) break ;
cursor + + ;
if ( ( cursor - scroll ) > = maxElements ) scroll + + ;
2019-04-21 17:27:33 +01:00
}
}
} else
if ( scrollAmount < 0 )
{
2019-06-20 04:56:14 +01:00
if ( scrollWithKeysDown & & ( cursor + scrollAmount ) < 0 )
2019-04-21 17:27:33 +01:00
{
2019-06-20 04:56:14 +01:00
cursor = ( menuItemsCount - 1 ) ;
scroll = ( menuItemsCount - maxElements ) ;
if ( scroll < 0 ) scroll = 0 ;
} else {
for ( i = 0 ; i < - scrollAmount ; i + + )
2019-04-21 17:27:33 +01:00
{
2019-11-06 18:22:40 +00:00
if ( cursor < = 0 ) break ;
cursor - - ;
if ( ( cursor - scroll ) < 0 ) scroll - - ;
2019-04-21 17:27:33 +01:00
}
}
}
2019-05-01 21:24:13 +01:00
2019-06-05 23:44:18 +01:00
// Avoid placing the cursor on the "Create directory with archive bit set" option in the XCI dump menu if "Split output dump" is disabled
2019-10-17 21:15:35 +01:00
if ( uiState = = stateXciDumpMenu & & cursor = = 2 & & ! dumpCfg . xciDumpCfg . isFat32 )
2019-06-05 23:44:18 +01:00
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
2019-12-11 08:56:58 +00:00
// Avoid placing the cursor on the "Dump verification method" option if "CRC32 checksum calculation + dump verification" is disabled
if ( uiState = = stateXciDumpMenu & & cursor = = 6 & & ! dumpCfg . xciDumpCfg . calcCrc )
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
2019-11-06 18:22:40 +00:00
// Avoid placing the cursor on the "Dump bundled update NSP" / "Dump installed update NSP" option in the NSP dump menu if we're dealing with a gamecard and it doesn't include any bundled updates, or if we're dealing with a SD/eMMC title without installed updates
// Also avoid placing the cursor on the "Dump bundled DLC NSP" / "Dump installed DLC NSP" option in the NSP dump menu if we're dealing with a gamecard and it doesn't include any bundled DLCs, or if we're dealing with a SD/eMMC title without installed DLCs
if ( uiState = = stateNspDumpMenu & & ( ( cursor = = 1 & & ( ! titlePatchCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) ) ) | | ( cursor = = 2 & & ( ! titleAddOnCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) ) ) )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( cursor = = 1 )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( ( ! titleAddOnCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) )
2019-06-09 02:36:21 +01:00
{
// Just in case
cursor = 0 ;
2019-11-06 18:22:40 +00:00
} else {
if ( scrollAmount > 0 )
{
cursor = 2 ;
} else
if ( scrollAmount < 0 )
{
cursor = 0 ;
}
2019-06-09 02:36:21 +01:00
}
2019-06-05 23:44:18 +01:00
} else
2019-11-06 18:22:40 +00:00
if ( cursor = = 2 )
2019-06-05 23:44:18 +01:00
{
2019-11-06 18:22:40 +00:00
if ( ! titlePatchCount | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) )
2019-06-09 02:36:21 +01:00
{
// Just in case
cursor = 0 ;
2019-11-06 18:22:40 +00:00
} else {
if ( scrollAmount > 0 )
{
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
} else
if ( scrollAmount < 0 )
{
cursor = 1 ;
}
2019-06-09 02:36:21 +01:00
}
}
}
2019-12-11 08:56:58 +00:00
// Avoid placing the cursor on the "Verify dump using No-Intro database" option in the NSP dump menus if we're dealing with a gamecard title
// Also, avoid placing the cursor on the "Remove console specific data" option in the NSP dump menus if we're dealing with a gamecard title
2019-06-20 04:56:14 +01:00
// Also, avoid placing the cursor on the "Generate ticket-less dump" option in the NSP dump menus if we're dealing with a gamecard Application/AddOn title
2019-12-11 08:56:58 +00:00
if ( menuType = = MENUTYPE_GAMECARD & & ( ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & ( cursor = = 2 | | cursor = = 3 ) ) | | ( ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & cursor = = 4 ) ) )
2019-06-09 02:36:21 +01:00
{
if ( scrollAmount > 0 )
{
2019-06-20 04:56:14 +01:00
cursor = ( ( uiState = = stateNspPatchDumpMenu & & cursor = = 3 ) ? 4 : 5 ) ;
2019-06-09 02:36:21 +01:00
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = 1 ;
}
}
// Avoid printing the "Dump delta fragments" option in the update NSP dump menu if we're dealing with a gamecard update
if ( menuType = = MENUTYPE_GAMECARD & & uiState = = stateNspPatchDumpMenu & & cursor = = 6 )
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
2019-06-09 02:36:21 +01:00
}
}
// Avoid placing the cursor on the "Generate ticket-less dump" option in the NSP dump menus if we're dealing with a SD/eMMC title and the "Remove console specific data" option is disabled
2019-10-17 21:15:35 +01:00
if ( menuType = = MENUTYPE_SDCARD_EMMC & & ( uiState = = stateNspAppDumpMenu | | uiState = = stateNspPatchDumpMenu | | uiState = = stateNspAddOnDumpMenu ) & & cursor = = 4 & & ! dumpCfg . nspDumpCfg . removeConsoleData )
2019-06-09 02:36:21 +01:00
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
2019-06-05 23:44:18 +01:00
}
}
2019-06-28 21:13:54 +01:00
// Avoid placing the cursor on the "Dump base applications", "Dump updates" and/or "Dump DLCs" options in the batch mode menu if we're dealing with a storage source that doesn't hold any title belonging to the current category
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & ( ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & ( ( ! titleAppCount & & cursor = = 1 ) | | ( ! titlePatchCount & & cursor = = 2 ) | | ( ! titleAddOnCount & & cursor = = 3 ) ) ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD & & ( ( ! sdCardTitleAppCount & & cursor = = 1 ) | | ( ! sdCardTitlePatchCount & & cursor = = 2 ) | | ( ! sdCardTitleAddOnCount & & cursor = = 3 ) ) ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC & & ( ( ! emmcTitleAppCount & & cursor = = 1 ) | | ( ! emmcTitlePatchCount & & cursor = = 2 ) | | ( ! emmcTitleAddOnCount & & cursor = = 3 ) ) ) ) )
2019-06-28 21:13:54 +01:00
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
// Avoid placing the cursor on the "Generate ticket-less dumps" option in the batch mode menu if the "Remove console specific data" option is disabled
2019-10-17 21:15:35 +01:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & cursor = = 6 & & ! dumpCfg . batchDumpCfg . removeConsoleData )
2019-06-28 21:13:54 +01:00
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
2019-12-11 08:56:58 +00:00
// Avoid placing the cursor on the "Dump delta fragments from updates" option in the batch mode menu if the "Dump updates" option is disabled
if ( uiState = = stateSdCardEmmcBatchModeMenu & & cursor = = 8 & & ! dumpCfg . batchDumpCfg . dumpPatchTitles )
{
if ( scrollAmount > 0 )
{
cursor + + ;
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
2019-06-28 21:13:54 +01:00
// Avoid placing the cursor on the "Source storage" option in the batch mode menu if we only have titles available in a single source storage device
2019-12-11 08:56:58 +00:00
if ( uiState = = stateSdCardEmmcBatchModeMenu & & cursor = = 13 & & ( ( ! sdCardTitleAppCount & & ! sdCardTitlePatchCount & & ! sdCardTitleAddOnCount ) | | ( ! emmcTitleAppCount & & ! emmcTitlePatchCount & & ! emmcTitleAddOnCount ) ) )
2019-06-28 21:13:54 +01:00
{
if ( scrollAmount > 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 0 : 12 ) ;
2019-06-28 21:13:54 +01:00
} else
if ( scrollAmount < 0 )
{
cursor - - ;
}
}
2019-09-15 03:45:27 +01:00
// Avoid placing the cursor on the "Use update" option in the ExeFS menu if we're dealing with a gamecard and either its base application count is greater than 1 or it has no available patches
2019-12-11 08:56:58 +00:00
// Also avoid placing the cursor on it if we're dealing with a SD/eMMC title and it has no available patches, or if we're dealing with an orphan Patch
if ( uiState = = stateExeFsMenu & & cursor = = 4 & & ( ( menuType = = MENUTYPE_GAMECARD & & ( titleAppCount > 1 | | ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ( ( ! orphanMode & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) ) | | orphanMode ) ) ) )
2019-09-15 03:45:27 +01:00
{
if ( scrollAmount > 0 )
{
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 1 : 0 ) ;
2019-09-15 03:45:27 +01:00
}
}
// Avoid placing the cursor on the "Use update" option in the ExeFS data dump and browser menus if we're not dealing with a gamecard, if the base application count is equal to or less than 1, or if the selected base application has no available patches
if ( ( uiState = = stateExeFsSectionDataDumpMenu | | uiState = = stateExeFsSectionBrowserMenu ) & & cursor = = 2 & & ( menuType ! = MENUTYPE_GAMECARD | | titleAppCount < = 1 | | ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) ) )
{
if ( scrollAmount > 0 )
{
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 1 : 0 ) ;
2019-09-15 03:45:27 +01:00
}
}
// Avoid placing the cursor on the "Use update/DLC" option in the RomFS menu if we're dealing with a gamecard and either its base application count is greater than 1 or it has no available patches/DLCs
// Also avoid placing the cursor on it if we're dealing with a SD/eMMC title and it has no available patches/DLCs (or if its an orphan title)
2019-12-11 08:56:58 +00:00
if ( uiState = = stateRomFsMenu & & cursor = = 4 & & ( ( menuType = = MENUTYPE_GAMECARD & & ( titleAppCount > 1 | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( 0 , true ) ) ) ) | | ( menuType = = MENUTYPE_SDCARD_EMMC & & ( orphanMode | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppInfoIndex , true ) ) ) ) ) )
2019-06-28 21:13:54 +01:00
{
if ( scrollAmount > 0 )
{
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 1 : 0 ) ;
2019-06-28 21:13:54 +01:00
}
}
2019-09-15 03:45:27 +01:00
// Avoid placing the cursor on the "Use update/DLC" option in the RomFS data dump and browser menus if we're not dealing with a gamecard, if the base application count is equal to or less than 1, or if the selected base application has no available patches/DLCs
if ( ( uiState = = stateRomFsSectionDataDumpMenu | | uiState = = stateRomFsSectionBrowserMenu ) & & cursor = = 2 & & ( menuType ! = MENUTYPE_GAMECARD | | titleAppCount < = 1 | | ( ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , false ) & & ! checkIfBaseApplicationHasPatchOrAddOn ( selectedAppIndex , true ) ) ) )
2019-06-28 21:13:54 +01:00
{
if ( scrollAmount > 0 )
{
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 1 : 0 ) ;
2019-06-28 21:13:54 +01:00
}
}
2019-12-11 08:56:58 +00:00
// Avoid placing the cursor on the "RomFS options" element in the SD card / eMMC title menu if we're dealing with an orphan Patch
// Also avoid placing the cursor on the "ExeFS options" element in the SD card / eMMC title menu if we're dealing with an orphan DLC
if ( uiState = = stateSdCardEmmcTitleMenu & & orphanMode & & ( ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_PATCH & & cursor = = 2 ) | | ( orphanEntries [ orphanListCursor ] . type = = ORPHAN_ENTRY_TYPE_ADDON & & cursor = = 1 ) ) )
2019-06-20 04:56:14 +01:00
{
2019-11-06 18:22:40 +00:00
if ( scrollAmount > 0 )
2019-06-20 04:56:14 +01:00
{
2019-12-11 08:56:58 +00:00
cursor + + ;
2019-11-06 18:22:40 +00:00
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor - - ;
2019-06-20 04:56:14 +01:00
}
}
2019-09-15 03:45:27 +01:00
2019-11-06 18:22:40 +00:00
// Avoid placing the cursor on the "Use ticket from title" element in the Ticket menu if we're dealing with an orphan title
if ( uiState = = stateTicketMenu & & orphanMode & & cursor = = 2 )
2019-09-15 03:45:27 +01:00
{
if ( scrollAmount > 0 )
{
2019-11-06 18:22:40 +00:00
cursor = ( scrollWithKeysDown ? 0 : 1 ) ;
2019-09-15 03:45:27 +01:00
} else
if ( scrollAmount < 0 )
{
2019-12-11 08:56:58 +00:00
cursor = ( scrollWithKeysDown ? 1 : 0 ) ;
2019-09-15 03:45:27 +01:00
}
}
2019-04-21 17:27:33 +01:00
}
}
} else
if ( uiState = = stateDumpXci )
{
2019-12-11 08:56:58 +00:00
char tmp [ 128 ] = { ' \0 ' } ;
strbuf [ 0 ] = ' \0 ' ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 0 ] ) ;
2019-04-21 17:27:33 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s " , xciDumpMenuItems [ 1 ] , ( dumpCfg . xciDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-04-21 17:27:33 +01:00
2019-10-17 21:15:35 +01:00
if ( dumpCfg . xciDumpCfg . isFat32 )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , xciDumpMenuItems [ 2 ] , ( dumpCfg . xciDumpCfg . setXciArchiveBit ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-06-05 23:44:18 +01:00
}
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
breaks + + ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , xciDumpMenuItems [ 3 ] , ( dumpCfg . xciDumpCfg . keepCert ? " Yes " : " No " ) ) ;
2019-04-21 17:27:33 +01:00
breaks + + ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , xciDumpMenuItems [ 4 ] , ( dumpCfg . xciDumpCfg . trimDump ? " Yes " : " No " ) ) ;
2019-04-21 17:27:33 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s " , xciDumpMenuItems [ 5 ] , ( dumpCfg . xciDumpCfg . calcCrc ? " Yes " : " No " ) ) ;
if ( dumpCfg . xciDumpCfg . calcCrc )
{
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , xciDumpMenuItems [ 6 ] , ( dumpCfg . xciDumpCfg . useNoIntroLookup ? xciChecksumLookupMethods [ 1 ] : xciChecksumLookupMethods [ 0 ] ) ) ;
strcat ( strbuf , tmp ) ;
}
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
breaks + + ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , xciDumpMenuItems [ 7 ] , ( dumpCfg . xciDumpCfg . useBrackets ? xciNamingSchemes [ 1 ] : xciNamingSchemes [ 0 ] ) ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-04-23 06:14:57 +01:00
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
dumpNXCardImage ( & ( dumpCfg . xciDumpCfg ) ) ;
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-04-21 17:27:33 +01:00
res = resultShowXciDumpMenu ;
2019-06-28 21:13:54 +01:00
dumpedContentInfoStr [ 0 ] = ' \0 ' ;
2019-04-21 17:27:33 +01:00
} else
2019-05-01 21:24:13 +01:00
if ( uiState = = stateDumpNsp )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( menuType = = MENUTYPE_GAMECARD ? nspDumpGameCardMenuItems [ selectedNspDumpType ] : nspDumpSdCardEmmcMenuItems [ selectedNspDumpType ] ) ) ;
2019-05-01 21:24:13 +01:00
breaks + + ;
2019-06-05 23:44:18 +01:00
menu = ( selectedNspDumpType = = DUMP_APP_NSP ? nspAppDumpMenuItems : ( selectedNspDumpType = = DUMP_PATCH_NSP ? nspPatchDumpMenuItems : nspAddOnDumpMenuItems ) ) ;
2019-12-11 08:56:58 +00:00
char tmp [ 128 ] = { ' \0 ' } ;
strbuf [ 0 ] = ' \0 ' ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 1 ] , ( dumpCfg . nspDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-05-01 21:24:13 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
if ( menuType ! = MENUTYPE_GAMECARD )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 2 ] , ( dumpCfg . nspDumpCfg . useNoIntroLookup ? " Yes " : " No " ) ) ;
breaks + + ;
}
2019-05-01 21:24:13 +01:00
2019-06-20 04:56:14 +01:00
if ( menuType = = MENUTYPE_GAMECARD & & selectedNspDumpType = = DUMP_PATCH_NSP )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s " , menu [ 4 ] , ( dumpCfg . nspDumpCfg . tiklessDump ? " Yes " : " No " ) ) ;
2019-06-20 04:56:14 +01:00
} else
2019-06-09 02:36:21 +01:00
if ( menuType = = MENUTYPE_SDCARD_EMMC )
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s " , menu [ 3 ] , ( dumpCfg . nspDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
2019-06-09 02:36:21 +01:00
2019-10-17 21:15:35 +01:00
if ( dumpCfg . nspDumpCfg . removeConsoleData )
2019-06-09 02:36:21 +01:00
{
2019-12-11 08:56:58 +00:00
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 4 ] , ( dumpCfg . nspDumpCfg . tiklessDump ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-06-09 02:36:21 +01:00
}
}
2019-11-06 18:22:40 +00:00
if ( selectedNspDumpType = = DUMP_APP_NSP | | selectedNspDumpType = = DUMP_PATCH_NSP )
2019-06-05 23:44:18 +01:00
{
2019-12-11 08:56:58 +00:00
if ( ( menuType = = MENUTYPE_GAMECARD & & selectedNspDumpType = = DUMP_PATCH_NSP ) | | menuType = = MENUTYPE_SDCARD_EMMC ) strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 5 ] , ( dumpCfg . nspDumpCfg . npdmAcidRsaPatch ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-11-06 18:22:40 +00:00
2019-12-11 08:56:58 +00:00
if ( selectedNspDumpType = = DUMP_PATCH_NSP )
2019-11-06 18:22:40 +00:00
{
2019-12-11 08:56:58 +00:00
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 6 ] , ( dumpCfg . nspDumpCfg . dumpDeltaFragments ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-11-06 18:22:40 +00:00
}
2019-05-01 21:24:13 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-12-11 08:56:58 +00:00
breaks + + ;
if ( selectedNspDumpType = = DUMP_APP_NSP )
{
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , menu [ 6 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
} else
if ( selectedNspDumpType = = DUMP_PATCH_NSP )
{
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , menu [ 7 ] , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
} else
if ( selectedNspDumpType = = DUMP_ADDON_NSP )
{
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , menu [ 5 ] , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
}
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
breaks + + ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , ( selectedNspDumpType = = DUMP_ADDON_NSP ? menu [ 6 ] : ( selectedNspDumpType = = DUMP_APP_NSP ? menu [ 7 ] : menu [ 8 ] ) ) , ( dumpCfg . nspDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) ) ;
2019-05-01 21:24:13 +01:00
breaks + = 2 ;
uiRefreshDisplay ( ) ;
2019-10-17 21:15:35 +01:00
dumpNintendoSubmissionPackage ( selectedNspDumpType , ( selectedNspDumpType = = DUMP_APP_NSP ? selectedAppIndex : ( selectedNspDumpType = = DUMP_PATCH_NSP ? selectedPatchIndex : selectedAddOnIndex ) ) , & ( dumpCfg . nspDumpCfg ) , false ) ;
2019-05-01 21:24:13 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = ( selectedNspDumpType = = DUMP_APP_NSP ? resultShowNspAppDumpMenu : ( selectedNspDumpType = = DUMP_PATCH_NSP ? resultShowNspPatchDumpMenu : resultShowNspAddOnDumpMenu ) ) ;
2019-06-28 21:13:54 +01:00
dumpedContentInfoStr [ 0 ] = ' \0 ' ;
} else
if ( uiState = = stateSdCardEmmcBatchDump )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Batch dump " ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
menu = batchModeMenuItems ;
2019-12-11 08:56:58 +00:00
char tmp [ 128 ] = { ' \0 ' } ;
strbuf [ 0 ] = ' \0 ' ;
if ( ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & titleAppCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD & & sdCardTitleAppCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC & & emmcTitleAppCount ) )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 1 ] , ( dumpCfg . batchDumpCfg . dumpAppTitles ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-06-28 21:13:54 +01:00
}
2019-12-11 08:56:58 +00:00
if ( ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & titlePatchCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD & & sdCardTitlePatchCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC & & emmcTitlePatchCount ) )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( strlen ( strbuf ) ) strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 2 ] , ( dumpCfg . batchDumpCfg . dumpPatchTitles ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-06-28 21:13:54 +01:00
}
2019-12-11 08:56:58 +00:00
if ( ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL & & titleAddOnCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD & & sdCardTitleAddOnCount ) | | ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_EMMC & & emmcTitleAddOnCount ) )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
if ( strlen ( strbuf ) ) strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 3 ] , ( dumpCfg . batchDumpCfg . dumpAddOnTitles ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
}
if ( strlen ( strbuf ) )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 4 ] , ( dumpCfg . batchDumpCfg . isFat32 ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s " , menu [ 5 ] , ( dumpCfg . batchDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
2019-06-28 21:13:54 +01:00
2019-10-17 21:15:35 +01:00
if ( dumpCfg . batchDumpCfg . removeConsoleData )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 6 ] , ( dumpCfg . batchDumpCfg . tiklessDump ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
2019-06-28 21:13:54 +01:00
}
2019-12-11 08:56:58 +00:00
strcat ( strbuf , " | " ) ;
snprintf ( tmp , MAX_CHARACTERS ( tmp ) , " %s%s " , menu [ 7 ] , ( dumpCfg . batchDumpCfg . npdmAcidRsaPatch ? " Yes " : " No " ) ) ;
strcat ( strbuf , tmp ) ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-11-06 18:22:40 +00:00
breaks + + ;
2019-12-11 08:56:58 +00:00
if ( dumpCfg . batchDumpCfg . dumpPatchTitles )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 8 ] , ( dumpCfg . batchDumpCfg . dumpDeltaFragments ? " Yes " : " No " ) ) ;
breaks + + ;
}
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s | %s%s " , menu [ 9 ] , ( dumpCfg . batchDumpCfg . skipDumpedTitles ? " Yes " : " No " ) , menu [ 10 ] , ( dumpCfg . batchDumpCfg . rememberDumpedTitles ? " Yes " : " No " ) , menu [ 11 ] , ( dumpCfg . batchDumpCfg . haltOnErrors ? " Yes " : " No " ) ) ;
2019-11-06 18:22:40 +00:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 12 ] , ( dumpCfg . batchDumpCfg . useBrackets ? nspNamingSchemes [ 1 ] : nspNamingSchemes [ 0 ] ) ) ;
2019-10-17 21:15:35 +01:00
breaks + + ;
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
if ( ( sdCardTitleAppCount | | sdCardTitlePatchCount | | sdCardTitleAddOnCount ) & & ( emmcTitleAppCount | | emmcTitlePatchCount | | emmcTitleAddOnCount ) )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 13 ] , ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_ALL ? " All (SD card + eMMC) " : ( dumpCfg . batchDumpCfg . batchModeSrc = = BATCH_SOURCE_SDCARD ? " SD card " : " eMMC " ) ) ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
}
2019-11-06 18:22:40 +00:00
breaks + + ;
2019-06-28 21:13:54 +01:00
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
int ret = dumpNintendoSubmissionPackageBatch ( & ( dumpCfg . batchDumpCfg ) ) ;
2019-06-28 21:13:54 +01:00
2019-12-11 08:56:58 +00:00
if ( ret = = - 2 )
{
uiRefreshDisplay ( ) ;
res = resultExit ;
} else {
waitForButtonPress ( ) ;
updateFreeSpace ( ) ;
res = resultShowSdCardEmmcBatchModeMenu ;
}
2019-05-01 21:24:13 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateDumpRawHfs0Partition )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Raw %s " , ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0PartitionDumpType1MenuItems [ selectedPartitionIndex ] : hfs0PartitionDumpType2MenuItems [ selectedPartitionIndex ] ) ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-04-23 06:14:57 +01:00
uiRefreshDisplay ( ) ;
2019-06-09 02:36:21 +01:00
dumpRawHfs0Partition ( selectedPartitionIndex , true ) ;
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowRawHfs0PartitionDumpMenu ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateDumpHfs0PartitionData )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Data %s " , ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0PartitionDumpType1MenuItems [ selectedPartitionIndex ] : hfs0PartitionDumpType2MenuItems [ selectedPartitionIndex ] ) ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-04-23 06:14:57 +01:00
uiRefreshDisplay ( ) ;
2019-06-28 21:13:54 +01:00
dumpHfs0PartitionData ( selectedPartitionIndex , true ) ;
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowHfs0PartitionDataDumpMenu ;
2019-04-21 17:27:33 +01:00
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateHfs0BrowserGetList )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , ( gameCardInfo . hfs0PartitionCnt = = GAMECARD_TYPE1_PARTITION_CNT ? hfs0BrowserType1MenuItems [ selectedPartitionIndex ] : hfs0BrowserType2MenuItems [ selectedPartitionIndex ] ) ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-05-01 21:24:13 +01:00
uiPleaseWait ( 0 ) ;
breaks + = 2 ;
2019-04-23 06:14:57 +01:00
2019-05-01 21:24:13 +01:00
if ( getHfs0FileList ( selectedPartitionIndex ) )
2019-04-21 17:27:33 +01:00
{
2019-06-05 23:44:18 +01:00
res = resultShowHfs0Browser ;
2019-04-21 17:27:33 +01:00
} else {
waitForButtonPress ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowHfs0BrowserMenu ;
2019-04-21 17:27:33 +01:00
}
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateHfs0BrowserCopyFile )
2019-04-21 17:27:33 +01:00
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Manual File Dump: %s (HFS0 partition %u [%s]) " , filenames [ selectedFileIndex ] , selectedPartitionIndex , GAMECARD_PARTITION_NAME ( gameCardInfo . hfs0PartitionCnt , selectedPartitionIndex ) ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-04-23 06:14:57 +01:00
uiRefreshDisplay ( ) ;
2019-06-28 21:13:54 +01:00
dumpFileFromHfs0Partition ( selectedPartitionIndex , selectedFileIndex , filenames [ selectedFileIndex ] , true ) ;
2019-06-05 23:44:18 +01:00
waitForButtonPress ( ) ;
2019-04-21 17:27:33 +01:00
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowHfs0Browser ;
} else
2019-06-09 02:36:21 +01:00
if ( uiState = = stateDumpExeFsSectionData )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , exeFsMenuItems [ 0 ] ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , exeFsMenuItems [ 2 ] , ( dumpCfg . exeFsDumpCfg . isFat32 ? " Yes " : " No " ) , exeFsMenuItems [ 3 ] , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
if ( ! exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , exeFsSectionDumpMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to dump: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-09 02:36:21 +01:00
breaks + = 2 ;
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
u32 curIndex = ( ! exeFsUpdateFlag ? selectedAppIndex : selectedPatchIndex ) ;
dumpExeFsSectionData ( curIndex , exeFsUpdateFlag , & ( dumpCfg . exeFsDumpCfg ) ) ;
2019-06-09 02:36:21 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-09 02:36:21 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowExeFsSectionDataDumpMenu : resultShowExeFsMenu ) ;
} else
if ( uiState = = stateExeFsSectionBrowserGetList )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , exeFsMenuItems [ 1 ] ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , exeFsMenuItems [ 2 ] , ( dumpCfg . exeFsDumpCfg . isFat32 ? " Yes " : " No " ) , exeFsMenuItems [ 3 ] , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
if ( ! exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , exeFsSectionBrowserMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-09 02:36:21 +01:00
breaks + = 2 ;
uiPleaseWait ( 0 ) ;
breaks + = 2 ;
bool exefs_fail = false ;
2019-12-11 08:56:58 +00:00
u32 curIndex = ( ! exeFsUpdateFlag ? selectedAppIndex : selectedPatchIndex ) ;
if ( readNcaExeFsSection ( curIndex , exeFsUpdateFlag ) )
2019-06-09 02:36:21 +01:00
{
if ( getExeFsFileList ( ) )
{
res = resultShowExeFsSectionBrowser ;
} else {
freeExeFsContext ( ) ;
exefs_fail = true ;
}
} else {
exefs_fail = true ;
}
if ( exefs_fail )
{
breaks + = 2 ;
waitForButtonPress ( ) ;
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowExeFsSectionBrowserMenu : resultShowExeFsMenu ) ;
}
} else
if ( uiState = = stateExeFsSectionBrowserCopyFile )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Manual File Dump: %s (ExeFS) " , filenames [ selectedFileIndex ] ) ;
2019-06-09 02:36:21 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , exeFsMenuItems [ 2 ] , ( dumpCfg . exeFsDumpCfg . isFat32 ? " Yes " : " No " ) , exeFsMenuItems [ 3 ] , ( dumpCfg . exeFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
if ( ! exeFsUpdateFlag )
2019-06-28 21:13:54 +01:00
{
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " Base application: %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-06-28 21:13:54 +01:00
} else {
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-09 02:36:21 +01:00
breaks + = 2 ;
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
u32 curIndex = ( ! exeFsUpdateFlag ? selectedAppIndex : selectedPatchIndex ) ;
dumpFileFromExeFsSection ( curIndex , selectedFileIndex , exeFsUpdateFlag , & ( dumpCfg . exeFsDumpCfg ) ) ;
2019-06-09 02:36:21 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-09 02:36:21 +01:00
res = resultShowExeFsSectionBrowser ;
} else
2019-06-05 23:44:18 +01:00
if ( uiState = = stateDumpRomFsSectionData )
{
2019-09-15 03:45:27 +01:00
u32 curIndex = 0 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 0 ] ) ;
2019-06-05 23:44:18 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , romFsSectionDumpMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAppIndex ;
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to dump: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedPatchIndex ;
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC to dump: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAddOnIndex ;
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-06-05 23:44:18 +01:00
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
dumpRomFsSectionData ( curIndex , curRomFsType , & ( dumpCfg . romFsDumpCfg ) ) ;
2019-06-05 23:44:18 +01:00
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-09 02:36:21 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionDataDumpMenu : resultShowRomFsMenu ) ;
2019-06-05 23:44:18 +01:00
} else
if ( uiState = = stateRomFsSectionBrowserGetEntries )
{
2019-09-15 03:45:27 +01:00
u32 curIndex = 0 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 1 ] ) ;
2019-06-05 23:44:18 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , romFsSectionBrowserMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAppIndex ;
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedPatchIndex ;
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAddOnIndex ;
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
uiPleaseWait ( 0 ) ;
breaks + = 2 ;
bool romfs_fail = false ;
2019-09-15 03:45:27 +01:00
if ( readNcaRomFsSection ( curIndex , curRomFsType ) )
2019-06-05 23:44:18 +01:00
{
2019-09-15 03:45:27 +01:00
if ( getRomFsFileList ( 0 , ( curRomFsType = = ROMFS_TYPE_PATCH ) ) )
2019-06-05 23:44:18 +01:00
{
res = resultShowRomFsSectionBrowser ;
} else {
2019-09-15 03:45:27 +01:00
if ( curRomFsType = = ROMFS_TYPE_PATCH ) freeBktrContext ( ) ;
2019-06-05 23:44:18 +01:00
freeRomFsContext ( ) ;
romfs_fail = true ;
}
} else {
romfs_fail = true ;
}
if ( romfs_fail )
{
breaks + = 2 ;
waitForButtonPress ( ) ;
2019-06-09 02:36:21 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionBrowserMenu : resultShowRomFsMenu ) ;
2019-06-05 23:44:18 +01:00
}
} else
if ( uiState = = stateRomFsSectionBrowserChangeDir )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , romFsMenuItems [ 1 ] ) ;
2019-06-05 23:44:18 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s v%s " , romFsSectionBrowserMenuItems [ 1 ] , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC to browse: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
bool romfs_fail = false ;
if ( romFsBrowserEntries [ selectedFileIndex ] . type = = ROMFS_ENTRY_DIR )
{
2019-09-15 03:45:27 +01:00
if ( getRomFsFileList ( romFsBrowserEntries [ selectedFileIndex ] . offset , ( curRomFsType = = ROMFS_TYPE_PATCH ) ) )
2019-06-05 23:44:18 +01:00
{
res = resultShowRomFsSectionBrowser ;
} else {
romfs_fail = true ;
}
} else {
// Unexpected condition
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Error: the selected entry is not a directory! " ) ;
2019-06-05 23:44:18 +01:00
romfs_fail = true ;
}
if ( romfs_fail )
{
2019-12-11 08:56:58 +00:00
freeRomFsBrowserEntries ( ) ;
2019-09-15 03:45:27 +01:00
if ( curRomFsType = = ROMFS_TYPE_PATCH ) freeBktrContext ( ) ;
2019-06-05 23:44:18 +01:00
freeRomFsContext ( ) ;
breaks + = 2 ;
waitForButtonPress ( ) ;
2019-06-09 02:36:21 +01:00
res = ( ( menuType = = MENUTYPE_GAMECARD & & titleAppCount > 1 ) ? resultShowRomFsSectionBrowserMenu : resultShowRomFsMenu ) ;
2019-06-05 23:44:18 +01:00
}
} else
if ( uiState = = stateRomFsSectionBrowserCopyFile )
{
2019-09-15 03:45:27 +01:00
u32 curIndex = 0 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Manual File Dump: %s (RomFS) " , filenames [ selectedFileIndex ] ) ;
2019-06-05 23:44:18 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " Base application: %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAppIndex ;
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedPatchIndex ;
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAddOnIndex ;
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-05 23:44:18 +01:00
breaks + = 2 ;
uiRefreshDisplay ( ) ;
if ( romFsBrowserEntries [ selectedFileIndex ] . type = = ROMFS_ENTRY_FILE )
{
2019-12-11 08:56:58 +00:00
dumpFileFromRomFsSection ( curIndex , romFsBrowserEntries [ selectedFileIndex ] . offset , curRomFsType , & ( dumpCfg . romFsDumpCfg ) ) ;
2019-06-05 23:44:18 +01:00
} else {
// Unexpected condition
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Error: the selected entry is not a file! " ) ;
2019-12-11 08:56:58 +00:00
breaks + = 2 ;
2019-06-05 23:44:18 +01:00
}
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowRomFsSectionBrowser ;
2019-04-21 17:27:33 +01:00
} else
2019-06-28 21:13:54 +01:00
if ( uiState = = stateRomFsSectionBrowserCopyDir )
{
2019-09-15 03:45:27 +01:00
u32 curIndex = 0 ;
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Manual Directory Dump: romfs:%s (RomFS) " , curRomFsPath ) ;
2019-06-28 21:13:54 +01:00
breaks + + ;
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s | %s%s " , romFsMenuItems [ 2 ] , ( dumpCfg . romFsDumpCfg . isFat32 ? " Yes " : " No " ) , romFsMenuItems [ 3 ] , ( dumpCfg . romFsDumpCfg . useLayeredFSDir ? " Yes " : " No " ) ) ;
breaks + + ;
2019-09-15 03:45:27 +01:00
switch ( curRomFsType )
2019-06-28 21:13:54 +01:00
{
2019-09-15 03:45:27 +01:00
case ROMFS_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " Base application: %s v%s " , baseAppEntries [ selectedAppIndex ] . name , baseAppEntries [ selectedAppIndex ] . versionStr ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAppIndex ;
break ;
case ROMFS_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , " Update: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedPatchIndex ;
break ;
case ROMFS_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , " DLC: " , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-09-15 03:45:27 +01:00
curIndex = selectedAddOnIndex ;
break ;
default :
break ;
2019-06-28 21:13:54 +01:00
}
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
2019-06-28 21:13:54 +01:00
breaks + = 2 ;
uiRefreshDisplay ( ) ;
2019-12-11 08:56:58 +00:00
dumpCurrentDirFromRomFsSection ( curIndex , curRomFsType , & ( dumpCfg . romFsDumpCfg ) ) ;
2019-06-28 21:13:54 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-28 21:13:54 +01:00
res = resultShowRomFsSectionBrowser ;
} else
2019-04-21 17:27:33 +01:00
if ( uiState = = stateDumpGameCardCertificate )
{
2019-12-11 08:56:58 +00:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , gameCardMenuItems [ 5 ] ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-06-09 02:36:21 +01:00
dumpGameCardCertificate ( ) ;
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-09 02:36:21 +01:00
res = resultShowGameCardMenu ;
2019-04-21 17:27:33 +01:00
} else
2019-11-06 18:22:40 +00:00
if ( uiState = = stateDumpTicket )
{
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " Dump ticket " ) ;
breaks + + ;
menu = ticketMenuItems ;
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , " %s%s " , menu [ 1 ] , ( dumpCfg . tikDumpCfg . removeConsoleData ? " Yes " : " No " ) ) ;
breaks + + ;
switch ( curTikType )
{
case TICKET_TYPE_APP :
2019-12-11 08:56:58 +00:00
snprintf ( strbuf , MAX_CHARACTERS ( strbuf ) , " %s%s | %016lX v%s (BASE) " , menu [ 2 ] , baseAppEntries [ selectedAppInfoIndex ] . name , baseAppEntries [ selectedAppInfoIndex ] . titleId , baseAppEntries [ selectedAppInfoIndex ] . versionStr ) ;
2019-11-06 18:22:40 +00:00
break ;
case TICKET_TYPE_PATCH :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedPatchIndex , false , true , menu [ 2 ] , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-11-06 18:22:40 +00:00
strcat ( strbuf , " (UPD) " ) ;
break ;
case TICKET_TYPE_ADDON :
2019-12-11 08:56:58 +00:00
retrieveDescriptionForPatchOrAddOn ( selectedAddOnIndex , true , true , menu [ 2 ] , strbuf , MAX_CHARACTERS ( strbuf ) ) ;
2019-11-06 18:22:40 +00:00
strcat ( strbuf , " (DLC) " ) ;
break ;
default :
break ;
}
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , strbuf ) ;
breaks + = 2 ;
u32 titleIndex = ( curTikType = = TICKET_TYPE_APP ? selectedAppInfoIndex : ( curTikType = = TICKET_TYPE_PATCH ? selectedPatchIndex : selectedAddOnIndex ) ) ;
dumpTicketFromTitle ( titleIndex , curTikType , & ( dumpCfg . tikDumpCfg ) ) ;
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-11-06 18:22:40 +00:00
res = resultShowTicketMenu ;
} else
2019-04-21 17:27:33 +01:00
if ( uiState = = stateUpdateNSWDBXml )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , updateMenuItems [ 0 ] ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
updateNSWDBXml ( ) ;
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowUpdateMenu ;
2019-04-21 17:27:33 +01:00
} else
if ( uiState = = stateUpdateApplication )
{
2019-10-17 21:15:35 +01:00
uiDrawString ( STRING_X_POS , STRING_Y_POS ( breaks ) , FONT_COLOR_TITLE_RGB , updateMenuItems [ 1 ] ) ;
2019-04-21 17:27:33 +01:00
breaks + = 2 ;
2019-11-06 18:22:40 +00:00
updatePerformed = updateApplication ( ) ;
2019-04-21 17:27:33 +01:00
waitForButtonPress ( ) ;
2019-12-11 08:56:58 +00:00
updateFreeSpace ( ) ;
2019-06-05 23:44:18 +01:00
res = resultShowUpdateMenu ;
2019-04-21 17:27:33 +01:00
}
return res ;
2018-06-21 07:42:46 +01:00
}