2019-11-27 19:49:58 -05:00
# include <string>
2019-12-09 22:23:21 -05:00
# include <thread>
2019-11-30 18:12:59 +01:00
# include "util/error.hpp"
2019-11-17 16:01:06 +01:00
# include "usbInstall.hpp"
# include "install/usb_nsp.hpp"
2019-12-17 00:15:40 +01:00
# include "install/install_nsp.hpp"
2019-11-17 16:01:06 +01:00
# include "util/usb_util.hpp"
# include "util/util.hpp"
# include "util/config.hpp"
# include "ui/usbInstPage.hpp"
2019-11-30 17:12:45 +01:00
# include "install/usb_xci.hpp"
# include "install/install_xci.hpp"
# include "sdInstall.hpp"
2019-11-17 16:01:06 +01:00
# include "ui/MainApplication.hpp"
namespace inst : : ui {
extern MainApplication * mainApp ;
2019-11-27 19:49:58 -05:00
void setUsbInfoText ( std : : string ourText ) {
mainApp - > usbinstPage - > pageInfoText - > SetText ( ourText ) ;
mainApp - > CallForRender ( ) ;
}
2019-11-17 16:01:06 +01:00
}
namespace usbInstStuff {
struct TUSHeader
{
u32 magic ; // TUL0 (Tinfoil Usb List 0)
2019-11-30 17:12:45 +01:00
u32 titleListSize ;
2019-11-17 16:01:06 +01:00
u64 padding ;
} PACKED ;
2019-12-08 18:59:37 -05:00
std : : vector < std : : string > OnSelected ( ) {
2019-11-17 16:01:06 +01:00
TUSHeader header ;
2019-12-06 17:25:11 -05:00
while ( true ) {
if ( tin : : util : : USBRead ( & header , sizeof ( TUSHeader ) ) ! = 0 ) break ;
2019-12-08 18:59:37 -05:00
hidScanInput ( ) ;
u64 kDown = hidKeysDown ( CONTROLLER_P1_AUTO ) ;
if ( kDown & KEY_B ) return { } ;
if ( kDown & KEY_X ) inst : : ui : : mainApp - > CreateShowDialog ( " Help " , " Files can be installed over USB from other devices using tools such as \n ns-usbloader in Tinfoil mode. To send files to your Switch, open one of \n these pieces of software on your PC, select your files, then upload to \n your console! \n \n Unfortunately USB installations require a specific setup on some \n platforms, and can be rather buggy at times. If you can't figure it out, \n give LAN/internet installs a try, or copy your files to your SD card and \n try the \" Install from SD Card \" option on the main menu! " , { " OK " } , true ) ;
if ( inst : : util : : getUsbState ( ) ! = 5 ) return { } ;
2019-12-06 17:25:11 -05:00
}
2019-11-17 16:01:06 +01:00
2019-12-08 18:59:37 -05:00
if ( header . magic ! = 0x304C5554 ) return { } ;
2019-11-17 16:01:06 +01:00
2019-11-30 17:12:45 +01:00
auto titleListBuf = std : : make_unique < char [ ] > ( header . titleListSize + 1 ) ;
std : : vector < std : : string > titleNames ;
memset ( titleListBuf . get ( ) , 0 , header . titleListSize + 1 ) ;
2019-11-17 16:01:06 +01:00
2019-11-30 17:12:45 +01:00
tin : : util : : USBRead ( titleListBuf . get ( ) , header . titleListSize ) ;
2019-11-17 16:01:06 +01:00
2019-11-30 17:12:45 +01:00
// Split the string up into individual title names
std : : stringstream titleNamesStream ( titleListBuf . get ( ) ) ;
2019-11-17 16:01:06 +01:00
std : : string segment ;
2019-11-30 17:12:45 +01:00
while ( std : : getline ( titleNamesStream , segment , ' \n ' ) ) {
titleNames . push_back ( segment ) ;
2019-11-17 16:01:06 +01:00
}
2019-12-08 18:59:37 -05:00
return titleNames ;
2019-11-17 16:01:06 +01:00
}
2019-11-30 17:12:45 +01:00
void installTitleUsb ( std : : vector < std : : string > ourTitleList , int ourStorage )
2019-11-27 19:49:58 -05:00
{
2019-11-17 16:01:06 +01:00
inst : : util : : initInstallServices ( ) ;
inst : : ui : : loadInstallScreen ( ) ;
2019-11-27 19:49:58 -05:00
bool nspInstalled = true ;
2019-11-17 16:01:06 +01:00
NcmStorageId m_destStorageId = NcmStorageId_SdCard ;
if ( ourStorage ) m_destStorageId = NcmStorageId_BuiltInUser ;
2019-11-27 19:49:58 -05:00
unsigned int fileItr ;
2019-11-17 16:01:06 +01:00
2019-11-27 19:49:58 -05:00
std : : vector < std : : string > fileNames ;
2019-11-30 17:12:45 +01:00
for ( long unsigned int i = 0 ; i < ourTitleList . size ( ) ; i + + ) {
2019-11-30 12:21:01 -05:00
fileNames . push_back ( inst : : util : : shortenString ( inst : : util : : formatUrlString ( ourTitleList [ i ] ) , 40 , true ) ) ;
2019-11-27 19:49:58 -05:00
}
2019-11-30 12:21:01 -05:00
2019-11-27 19:49:58 -05:00
std : : vector < int > previousClockValues ;
if ( inst : : config : : overClock ) {
previousClockValues . push_back ( inst : : util : : setClockSpeed ( 0 , 1785000000 ) [ 0 ] ) ;
previousClockValues . push_back ( inst : : util : : setClockSpeed ( 1 , 76800000 ) [ 0 ] ) ;
previousClockValues . push_back ( inst : : util : : setClockSpeed ( 2 , 1600000000 ) [ 0 ] ) ;
}
2019-11-30 12:21:01 -05:00
2019-11-27 19:49:58 -05:00
try {
2019-11-30 17:12:45 +01:00
for ( fileItr = 0 ; fileItr < ourTitleList . size ( ) ; fileItr + + ) {
2019-11-30 12:06:49 -05:00
inst : : ui : : setTopInstInfoText ( " Installing " + fileNames [ fileItr ] + " over USB " ) ;
2019-12-17 00:15:40 +01:00
std : : unique_ptr < tin : : install : : Install > installTask ;
2019-11-30 17:12:45 +01:00
if ( ourTitleList [ fileItr ] . compare ( ourTitleList [ fileItr ] . size ( ) - 3 , 2 , " xc " ) = = 0 ) {
2019-12-17 00:15:40 +01:00
auto usbXCI = std : : make_shared < tin : : install : : xci : : USBXCI > ( ourTitleList [ fileItr ] ) ;
installTask = std : : make_unique < tin : : install : : xci : : XCIInstallTask > ( m_destStorageId , inst : : config : : ignoreReqVers , usbXCI ) ;
2019-11-30 17:12:45 +01:00
} else {
2019-12-17 00:15:40 +01:00
auto usbNSP = std : : make_shared < tin : : install : : nsp : : USBNSP > ( ourTitleList [ fileItr ] ) ;
installTask = std : : make_unique < tin : : install : : nsp : : NSPInstall > ( m_destStorageId , inst : : config : : ignoreReqVers , usbNSP ) ;
2019-11-30 17:12:45 +01:00
}
2019-11-17 16:01:06 +01:00
2019-11-30 18:12:59 +01:00
LOG_DEBUG ( " %s \n " , " Preparing installation " ) ;
2019-11-27 19:49:58 -05:00
inst : : ui : : setInstInfoText ( " Preparing installation... " ) ;
inst : : ui : : setInstBarPerc ( 0 ) ;
2019-11-30 17:12:45 +01:00
installTask - > Prepare ( ) ;
2019-11-27 19:49:58 -05:00
2019-11-30 17:12:45 +01:00
installTask - > Begin ( ) ;
2019-11-17 16:01:06 +01:00
}
}
2019-11-27 19:49:58 -05:00
catch ( std : : exception & e ) {
2019-11-30 18:12:59 +01:00
LOG_DEBUG ( " Failed to install " ) ;
LOG_DEBUG ( " %s " , e . what ( ) ) ;
2019-11-27 19:49:58 -05:00
fprintf ( stdout , " %s " , e . what ( ) ) ;
inst : : ui : : setInstInfoText ( " Failed to install " + fileNames [ fileItr ] ) ;
inst : : ui : : setInstBarPerc ( 0 ) ;
2019-12-09 22:23:21 -05:00
std : : thread audioThread ( inst : : util : : playAudio , " romfs:/audio/bark.wav " ) ;
2019-11-27 19:49:58 -05:00
inst : : ui : : mainApp - > CreateShowDialog ( " Failed to install " + fileNames [ fileItr ] + " ! " , " Partially installed contents can be removed from the System Settings applet. \n \n " + ( std : : string ) e . what ( ) , { " OK " } , true ) ;
2019-12-09 22:23:21 -05:00
audioThread . join ( ) ;
2019-11-27 19:49:58 -05:00
nspInstalled = false ;
}
2019-11-17 16:01:06 +01:00
2019-11-27 19:49:58 -05:00
if ( previousClockValues . size ( ) > 0 ) {
inst : : util : : setClockSpeed ( 0 , previousClockValues [ 0 ] ) ;
inst : : util : : setClockSpeed ( 1 , previousClockValues [ 1 ] ) ;
inst : : util : : setClockSpeed ( 2 , previousClockValues [ 2 ] ) ;
}
2019-11-30 12:21:01 -05:00
2019-11-27 19:49:58 -05:00
if ( nspInstalled ) {
2019-11-30 23:06:00 -05:00
tin : : util : : USBCmdManager : : SendExitCmd ( ) ;
2019-11-27 19:49:58 -05:00
inst : : ui : : setInstInfoText ( " Install complete " ) ;
inst : : ui : : setInstBarPerc ( 100 ) ;
2019-12-09 22:23:21 -05:00
std : : thread audioThread ( inst : : util : : playAudio , " romfs:/audio/awoo.wav " ) ;
2019-11-30 17:12:45 +01:00
if ( ourTitleList . size ( ) > 1 ) inst : : ui : : mainApp - > CreateShowDialog ( std : : to_string ( ourTitleList . size ( ) ) + " files installed successfully! " , nspInstStuff : : finishedMessage ( ) , { " OK " } , true ) ;
2019-11-27 19:49:58 -05:00
else inst : : ui : : mainApp - > CreateShowDialog ( fileNames [ 0 ] + " installed! " , nspInstStuff : : finishedMessage ( ) , { " OK " } , true ) ;
2019-12-09 22:23:21 -05:00
audioThread . join ( ) ;
2019-11-27 19:49:58 -05:00
}
2019-11-30 18:12:59 +01:00
LOG_DEBUG ( " Done " ) ;
2019-11-17 16:01:06 +01:00
inst : : ui : : loadMainMenu ( ) ;
2019-11-27 19:49:58 -05:00
inst : : util : : deinitInstallServices ( ) ;
return ;
2019-11-17 16:01:06 +01:00
}
}