void Key7X(void) { size_t bytesRead; if (FSFileOpen("/slot0x25KeyX.bin")) { u8 slot0x25KeyX[16] = { 0 }; bytesRead = FSFileRead(&slot0x25KeyX, 16, 0); FSFileClose(); if (bytesRead != 16) { DrawDebug(0, 1, "slot0x25KeyX.bin is too small!"); } DrawDebug(0, 1, "slot0x25KeyX.bin Found!"); DrawDebug(0, 1, ""); u8 zero[16] = { 0x00 }; memcpy((u32*)0x01FFCD00, zero, 16); setup_aeskeyX(0x25, slot0x25KeyX); } else { DrawDebug(0, 1, "You can't perform firmlaunch without slot0x25KeyX.bin"); int a; while (1) { a += 1; a -= 1; } } }
RETCODE _reentrant GetWmaMetaData_ReadObjectHeaderPrologue(BYTE iHandle, ASFOBJECTHEADER*pObjectHeader) { int iError; //this zero's out the non even sized pieces pObjectHeader->ObjectGUID.wValues[5] = 0; iError = FSFileRead(16,iHandle,MEM_SPACE_Y,-1,(void*)pObjectHeader); pObjectHeader->ObjectSize = GetWmaMetaData_ReadQWORD(iHandle); return iError; }
DWORD _reentrant GetWmaMetaData_ReadQWORD(BYTE iHandle) {//this reads in a QWORD from the ASF file, but truncates to a DWORD WORD TmpVal[3]; TmpVal[2]=0; FSFileRead(8,iHandle,MEM_SPACE_Y,-1,TmpVal);//read in 8 bytes return ((DWORD)TmpVal[0] + ((DWORD)TmpVal[1]<<24));//we only use the bottom two words (6 bytes). }
DWORD _reentrant GetWmaMetaData_ReadDWORD(BYTE iHandle) { WORD TmpVal[2]; TmpVal[1]=0;//zero out the upper word. FSFileRead(4,iHandle,MEM_SPACE_Y,-1,TmpVal);//read in 4 bytes return ((DWORD)TmpVal[0] + ((DWORD)TmpVal[1]<<24));//they just so happen to be in that order }
WORD _reentrant GetWmaMetaData_ReadWORD(BYTE iHandle) { WORD TmpVal; TmpVal=0;//zero out FSFileRead(2,iHandle,MEM_SPACE_Y,-1,&TmpVal);//read in 2 bytes return (WORD)TmpVal; }
BYTE _reentrant GetWmaMetaData_ReadBYTE(BYTE iHandle) { WORD TmpVal; TmpVal=0;//zero out FSFileRead(1,iHandle,MEM_SPACE_Y,-1,&TmpVal);//read in 1 byte return (BYTE)TmpVal; }
// @breif This reads the system version from the configuration file. // @note So please make sure you've have the file in your SD. // Also, if we use binary data to store the system version.. void CFW_getSystemVersion(void) { char settings[16]; if (FSFileOpen("/3ds/PastaCFW/system.txt")){ FSFileRead(settings, 16, 0); FSFileClose(); } cfw_FWValue = settings[0]; switch (settings[0]) { case '1': // 4.x cfw_FWString = platform_FWStrings[0]; key7Xneeded = true; break; case '2': // 5.0 cfw_FWString = platform_FWStrings[1]; key7Xneeded = true; break; case '3': // 5.1 cfw_FWString = platform_FWStrings[2]; key7Xneeded = true; break; case '4': // 6.0 cfw_FWString = platform_FWStrings[3]; key7Xneeded = true; break; case '5': // 6.1 - 6.3 cfw_FWString = platform_FWStrings[4]; key7Xneeded = true; break; case '6': // 7.0-7.1 cfw_FWString = platform_FWStrings[5]; break; case '7': // 7.2 cfw_FWString = platform_FWStrings[6]; break; case '8': // 8.x cfw_FWString = platform_FWStrings[7]; break; case '9': // 9.x cfw_FWString = platform_FWStrings[8]; break; case 'a': // 8.x cfw_FWString = platform_FWStrings[9]; break; case 'b': // 9.x cfw_FWString = platform_FWStrings[10]; break; } //Check if to boot the GUI if (settings[1] == '0' || settings[1] == '2') cfw_bootGUI = true; //Check if firmlaunch is enabled if (settings[2] == '2' || settings[2] == '1') cfw_enablefirmlaunch = true; //Check theme sprintf(str, "/3ds/PastaCFW/UI/%c/menu0.bin", settings[3]); if (FSFileOpen(str)) cfw_theme = settings[3]; //check if the theme exists, else load theme 0 (default) else cfw_theme = 0; }
// @breif Copy and initialize FIRM void PrepareFirmLaunch(void) { DrawDebug(0, 1, "Preparing for firmlaunch"); DrawDebug(0, 1, ""); uint32_t magic = 0x4D524946; size_t bytesRead; if (key7Xneeded) Key7X(); FSFileOpen("/3ds/PastaCFW/firm.bin"); bytesRead = FSFileRead(&firm, 0x200, 0); if (bytesRead != 0x200) error(); if (firm.magic != magic) error(); FSFileRead(firm.sect[0].p, firm.sect[0].size, firm.sect[0].offset); FSFileRead(firm.sect[1].p, firm.sect[1].size, firm.sect[1].offset); FSFileRead(firm.sect[2].p, firm.sect[2].size, firm.sect[2].offset); if (cfw_FWValue == 'd') { u8 key[16] = { 0 }; FSFileRead(&key, 0x10, (firm.sect[2].offset + 0x60)); KeyInit(key); } }
INT _reentrant AAGetActivationRecords( INT pNumRecords, INT unused2, INT * pActivationBuf ) { int fp; int bytesToRead; int retCode = 0; int i; // _packed BYTE tempFilename[16]; // _packed BYTE *p; // Do a little error checking if ( !pActivationBuf ) return -1; /* // Copy the filename over to local storage p = tempFilename; for ( i = 0; i < sizeof(tempFilename); i++, p++ ) { int temp; temp = *p = ActivationFilename[i]; if ( !(temp & 0xFF0000) || !(temp & 0x00FF00) || !(temp & 0x0000FF) ) break; } */ // Activation records are always stored in file on internal Flash fp = FSFileOpen( (_packed BYTE *) ActivationFilename, READ, 0 ); if ( fp < 0 ) return -2; // Read all the activation records at once bytesToRead = 8 * 70; if ( FSFileRead( bytesToRead, fp, MEM_SPACE_Y, -1, (WORD *) pActivationBuf ) != bytesToRead ) retCode = -3; else { // All records were read in. Return the count. if ( pNumRecords ) *((int *) pNumRecords) = 8; } FSFileClose( fp ); return retCode; }
//////////////////////////////////////////////////////////////////////////////// // //> Name: GetWavMetaData // // Type: Function // // Description: Finds the meta-data within a .wav file. // // Inputs: Ptr to pathname, current device id, ptr to meta-data struct. // // Outputs: RETCODE // // Notes: none //< //////////////////////////////////////////////////////////////////////////////// RETCODE _reentrant GetWavMetaData(INT PackedPathNameAddress, INT btCurrentDevice, FILE_META_DATA * MetaData) { RETCODE rtn = META_DATA_NOT_FOUND; INT iHandle = NOERROR; // indicates the handle of file opened (or error if failure) DWORD dwNumBytesTemp; // stores 48 bits, number of bytes in file DWORD dwAvgBytesPerSec; // average bytes per second WORD wBufferPacked[ADPCM_READ_BUFFER_SIZE]; // read file (packed bytes) into this buffer BYTE btUnpack[ADPCM_READ_BUFFER_SIZE]; // uppack bytes into this buffer _packed BYTE * pcFilePathName = (_packed BYTE*)PackedPathNameAddress; // Open the file. #ifdef USE_PLAYLIST3 if (g_Rebuild == TRUE) iHandle = FSFastOpen(g_FileKey,READ); else { if(g_CurrentSongFastkey==0) { iHandle = FSFileOpen(pcFilePathName, READ, btCurrentDevice); g_CurrentSongFastkey=FgetFastHandle(iHandle); } else iHandle = FSFastOpen(g_CurrentSongFastkey,READ); //if((iHandle = FSFileOpen(pcFilePathName, READ, btCurrentDevice)) != ERROR) } #endif #ifdef USE_PLAYLIST2 iHandle = FSFileOpen(pcFilePathName, READ, btCurrentDevice); #endif #ifdef USE_PLAYLIST5 g_CurrentFastKey = (g_PL5_PL_queue.pos + g_PL5_Playback.currentplay)->file.lFastKey; iHandle = FSFastOpen(g_CurrentFastKey,READ); #endif if(iHandle!= ERROR) { #ifdef USE_PLAYLIST3 if (g_Rebuild == TRUE) { filegetdate(iHandle,CREATION_DATE,&g_dirdate,&g_dirtime); } #endif // Get the number of bytes in song dwNumBytesTemp = FSFileSize(iHandle); MetaData->dwNumBytes = dwNumBytesTemp; // Clear MetaData members that do not apply MetaData->dwNumFrames = (DWORD)0; MetaData->bVBR = (BOOL)0; MetaData->wBitRate = (WORD)0; // Read from start of file if (FSFileRead(20, iHandle, MEM_SPACE_Y, (INT)(-1), wBufferPacked) != ERROR) //read RIFF header { unpack_data((_packed BYTE *)wBufferPacked, btUnpack,20); if ((btUnpack[0]=='R') && (btUnpack[1]=='I') && (btUnpack[2]=='F') && (btUnpack[3]=='F') && (btUnpack[8]=='W') && (btUnpack[9]=='A') && (btUnpack[10]=='V') && (btUnpack[11]=='E') && (btUnpack[12]=='f') && (btUnpack[13]=='m') && (btUnpack[14]=='t') && (btUnpack[15]==' ')) { // success, header is found dwNumBytesTemp = ((DWORD)btUnpack[16] | ((DWORD)btUnpack[17]<<8) | ((DWORD)btUnpack[18]<<16) | ((DWORD)btUnpack[19]<<24)) - 12; MetaData->iResourceNum = -1; // Set Resource Number to -1 if WAV file type NOT supported. if (FSFileRead(12, iHandle, MEM_SPACE_Y, (INT)(-1), wBufferPacked) != ERROR) // read 'fmt ' chunk { unpack_data((_packed BYTE *)wBufferPacked, btUnpack,12); // Identify the file type with the wformattag (2 bytes) switch(((WORD)btUnpack[0])|((WORD)btUnpack[1]<<8)) { case WAVE_FORMAT_ADPCM: MetaData->iFileType = (INT)MS_ADPCM_TYPE; MetaData->iResourceNum = RSRC_DEC_ADPCM_MOD_CODE; break; case WAVE_FORMAT_IMA_ADPCM: MetaData->iFileType = (INT)IMA_ADPCM_TYPE; MetaData->iResourceNum = RSRC_DEC_ADPCM_MOD_CODE; break; case WAVE_FORMAT_PCM: MetaData->iFileType = (INT)PCM_WAV_TYPE; MetaData->iResourceNum = RSRC_DEC_ADPCM_MOD_CODE; break; default: rtn = META_DATA_FILE_NOT_SUPPORTED; } if (rtn != META_DATA_FILE_NOT_SUPPORTED) { // nchannels next 2 bytes MetaData->wNumChannels = ((WORD)btUnpack[2])|((WORD)btUnpack[3]<<8); // Get nsamplespersec MetaData->wSampRate =((WORD)btUnpack[4])|((WORD)btUnpack[5]<<8)|((WORD)btUnpack[6]<<16); // next byte is 00 // next 4 bytes are navgbytespersec dwAvgBytesPerSec = (DWORD)btUnpack[8] | ((DWORD)btUnpack[9]<<8) | ((DWORD)btUnpack[10]<<16) | ((DWORD)btUnpack[11]<<24); // Calculate the song time while (fseek(iHandle,dwNumBytesTemp,SEEK_CUR) != ERROR) // search 'data' chunk { if (FSFileRead(8, iHandle, MEM_SPACE_Y, (INT)(-1), wBufferPacked) != ERROR) { unpack_data((_packed BYTE *)wBufferPacked, btUnpack,8); dwNumBytesTemp = (DWORD)btUnpack[4] | ((DWORD)btUnpack[5]<<8) | ((DWORD)btUnpack[6]<<16) | ((DWORD)btUnpack[7]<<24); if ((btUnpack[0]=='d') && (btUnpack[1]=='a') && (btUnpack[2]=='t') && (btUnpack[3]=='a')) { // 'data' chunk is found MetaData->iTime = (DWORD) dwNumBytesTemp / (DWORD)dwAvgBytesPerSec; // get wave length in seconds rtn = META_DATA_FOUND; break; } } else break; } } } } } else rtn = META_DATA_FILEREAD_ERROR; #ifdef USE_PLAYLIST3 if (g_Rebuild == TRUE) { if ((Fclose(iHandle)) == ERROR) rtn = META_DATA_FILECLOSE_ERROR; } else #endif { if ((FSFileClose(iHandle)) == ERROR) rtn = META_DATA_FILECLOSE_ERROR; } } else rtn = META_DATA_FILEOPEN_ERROR; #ifdef USE_PLAYLIST3 if (g_Rebuild == TRUE) { if(iHandle) { if ((Fclose(iHandle)) == ERROR) rtn = META_DATA_FILECLOSE_ERROR; } } #endif return(rtn); }
RETCODE _reentrant GetWmaMetaData(INT PackedPathNameAddress, INT btCurrentDevice, FILE_META_DATA * MetaData) { int bContinue = FALSE; int iError; RETCODE rtn = META_DATA_NOT_FOUND; ASFOBJECTHEADER HeaderHeader; GUID TempGUID; WORD wObjectCount=0; int iHandle; _packed BYTE * pcFilePathName = (_packed BYTE*)PackedPathNameAddress; WORD TmpVal[3]; // Open the file. iHandle = FSFileOpen(pcFilePathName, READ, btCurrentDevice); if(iHandle != ERROR) { MetaData->iFileType = (INT)WMA_TYPE; MetaData->iResourceNum = -1;//RSRC_WMADEC_CODE; MetaData->bVBR = FALSE; iError = fseek(iHandle,0,SEEK_SET); //verify that that header object is there. if(iError != -1) { rtn = META_DATA_FOUND; TempGUID.wValues[0]=ASF_HEADER_GUID_0; TempGUID.wValues[1]=ASF_HEADER_GUID_1; TempGUID.wValues[2]=ASF_HEADER_GUID_2; TempGUID.wValues[3]=ASF_HEADER_GUID_3; TempGUID.wValues[4]=ASF_HEADER_GUID_4; TempGUID.wValues[5]=ASF_HEADER_GUID_5; GetWmaMetaData_ReadObjectHeaderPrologue(iHandle,&HeaderHeader); if(GetWmaMetaData_CompareGUID(&HeaderHeader.ObjectGUID,&TempGUID)) { wObjectCount = GetWmaMetaData_ReadDWORD(iHandle); GetWmaMetaData_ReadBYTE(iHandle); if(GetWmaMetaData_ReadBYTE(iHandle)==0x02) { bContinue = TRUE; } } } else rtn = META_DATA_FILESEEK_ERROR; if(bContinue) { int wSize; //we've got a header object, so lets start getting objects out of it //first, the TempGUID.wValues[0]=ASF_FILE_PROPERTIES_GUID_0; TempGUID.wValues[1]=ASF_FILE_PROPERTIES_GUID_1; TempGUID.wValues[2]=ASF_FILE_PROPERTIES_GUID_2; TempGUID.wValues[3]=ASF_FILE_PROPERTIES_GUID_3; TempGUID.wValues[4]=ASF_FILE_PROPERTIES_GUID_4; TempGUID.wValues[5]=ASF_FILE_PROPERTIES_GUID_5; if(GetWmaMetaData_FindFirstObject(iHandle,wObjectCount,&TempGUID)>0) { // The following code should work properly, but doesn't because the Windows Media // Player messes up the File Size parameter (adds a 00100 to it). Thus, we'll use // our own file size function. // fseek(iHandle,16,SEEK_CUR);//skip the FILE ID // MetaData->dwNumBytes = GetWmaMetaData_ReadQWORD(iHandle); MetaData->dwNumBytes = FSFileSize(iHandle); MetaData->dwDataBytes = (MetaData->dwNumBytes - HeaderHeader.ObjectSize); // Skip the File ID, the File Size, and the creation date. (16 + 8 + 8) fseek(iHandle,32,SEEK_CUR); MetaData->dwNumFrames= GetWmaMetaData_ReadQWORD(iHandle); MetaData->iTime = GetWmaMetaData_ReadQWORD(iHandle)/10000; fseek(iHandle,8,SEEK_CUR);//skip the send duration MetaData->iTime -= GetWmaMetaData_ReadQWORD(iHandle);//subtract off the preroll amount MetaData->iTime /= 1000; //convert the time to seconds TempGUID.wValues[0]=ASF_STREAM_PROPERTIES_GUID_0; TempGUID.wValues[1]=ASF_STREAM_PROPERTIES_GUID_1; TempGUID.wValues[2]=ASF_STREAM_PROPERTIES_GUID_2; TempGUID.wValues[3]=ASF_STREAM_PROPERTIES_GUID_3; TempGUID.wValues[4]=ASF_STREAM_PROPERTIES_GUID_4; TempGUID.wValues[5]=ASF_STREAM_PROPERTIES_GUID_5; } else { bContinue = FALSE; } } //get information from the STREAM object if(bContinue) { int wSize; wSize = GetWmaMetaData_FindFirstObject(iHandle,wObjectCount,&TempGUID); while(wSize > 0) { GUID TempGUID2; TempGUID2.wValues[0] = ASF_AUDIO_MEDIA_GUID_0; TempGUID2.wValues[1] = ASF_AUDIO_MEDIA_GUID_1; TempGUID2.wValues[2] = ASF_AUDIO_MEDIA_GUID_2; TempGUID2.wValues[3] = ASF_AUDIO_MEDIA_GUID_3; TempGUID2.wValues[4] = ASF_AUDIO_MEDIA_GUID_4; TempGUID2.wValues[5] = ASF_AUDIO_MEDIA_GUID_5; FSFileRead(16,iHandle,MEM_SPACE_Y,-1,(void*)&TempGUID); if(GetWmaMetaData_CompareGUID(&TempGUID,&TempGUID2)) { break; } //seek to the next object fseek(iHandle,wSize-16,SEEK_CUR); wSize = GetWmaMetaData_FindNextObject(iHandle,wObjectCount,&TempGUID); } if(wSize > 0) {//wSize will be positive when we've found our stream iError = fseek(iHandle,16+8+4+4+2+4+2+2,SEEK_CUR);//skip past error correction type, time offset, type specific data length(since we know what //it is),error correction data length, flags, reserved //plus parts of the codec specific data (codec,channels) MetaData->wSampRate= GetWmaMetaData_ReadDWORD(iHandle); MetaData->wBitRate = GetWmaMetaData_ReadDWORD(iHandle)*8; } else { bContinue = FALSE; } } //now get the song information, etc. if(bContinue) { TempGUID.wValues[0]=ASF_CONTENT_DESCRIPTION_GUID_0; TempGUID.wValues[1]=ASF_CONTENT_DESCRIPTION_GUID_1; TempGUID.wValues[2]=ASF_CONTENT_DESCRIPTION_GUID_2; TempGUID.wValues[3]=ASF_CONTENT_DESCRIPTION_GUID_3; TempGUID.wValues[4]=ASF_CONTENT_DESCRIPTION_GUID_4; TempGUID.wValues[5]=ASF_CONTENT_DESCRIPTION_GUID_5; if(GetWmaMetaData_FindFirstObject(iHandle,wObjectCount,&TempGUID)>0) { int wTitleLength = GetWmaMetaData_ReadWORD(iHandle)/2; int wArtistLength = GetWmaMetaData_ReadWORD(iHandle)/2; fseek(iHandle,2+2+2,SEEK_CUR);//seek passed Copyright Length, Description Length, Rating Length GetWmaMetaData_ReadString(iHandle, MetaData->wTitle,MetaData->iTitleBufferLength,wTitleLength); GetWmaMetaData_ReadString(iHandle, MetaData->wArtist,MetaData->iArtistBufferLength,wArtistLength); //Find the album information if(MetaData->wAlbum) { TempGUID.wValues[0]=ASF_EXTENDED_CONTENT_GUID_0; TempGUID.wValues[1]=ASF_EXTENDED_CONTENT_GUID_1; TempGUID.wValues[2]=ASF_EXTENDED_CONTENT_GUID_2; TempGUID.wValues[3]=ASF_EXTENDED_CONTENT_GUID_3; TempGUID.wValues[4]=ASF_EXTENDED_CONTENT_GUID_4; TempGUID.wValues[5]=ASF_EXTENDED_CONTENT_GUID_5; if(GetWmaMetaData_FindFirstObject(iHandle,wObjectCount,&TempGUID)>0) { int i; int wContentDescriptorCount ; UCS3 sDescriptorName[15]; wContentDescriptorCount = GetWmaMetaData_ReadWORD(iHandle); for(i=0;i<wContentDescriptorCount;i++) { int wDescriptorNameLength = GetWmaMetaData_ReadWORD(iHandle)/2; GetWmaMetaData_ReadString(iHandle, sDescriptorName, 14,wDescriptorNameLength); if(sDescriptorName[ 0]=='W' && sDescriptorName[ 1]=='M' && sDescriptorName[ 2]=='/' && sDescriptorName[ 3]=='A' && sDescriptorName[ 4]=='l' && sDescriptorName[ 5]=='b' && sDescriptorName[ 6]=='u' && sDescriptorName[ 7]=='m' && sDescriptorName[ 8]=='T' && sDescriptorName[ 9]=='i' && sDescriptorName[10]=='t' && sDescriptorName[11]=='l' && sDescriptorName[12]=='e') { if(GetWmaMetaData_ReadWORD(iHandle)==0)//must be a unicode string { wDescriptorNameLength = GetWmaMetaData_ReadWORD(iHandle)/2; GetWmaMetaData_ReadString(iHandle, MetaData->wAlbum,MetaData->iAlbumBufferLength,wDescriptorNameLength); } break; } else {//skip over this extended content descriptor fseek(iHandle,2,SEEK_CUR);//seek past the data type //get the descriptor value length, and skip past it fseek(iHandle,GetWmaMetaData_ReadWORD(iHandle),SEEK_CUR); } } } } } } if(iHandle != -1) { FSFileClose(iHandle); } } else rtn = META_DATA_FILEOPEN_ERROR; return rtn; }
void CFW_Settings(void) { TOP_Current = 0; int settings_idx = 0; bool autobootgui = false; bool enable_firmlaunch = false; char settings[4]; if (FSFileOpen("/3ds/PastaCFW/system.txt")){ FSFileRead(settings, 4, 0); FSFileClose(); if (settings[1] == '2')autobootgui = true; if (settings[2] == '1' || settings[2] == '3')enable_firmlaunch = true; cfw_theme = settings[3]; } while (true) { //DRAW GUI sprintf(str, "/3ds/PastaCFW/UI/%c/options.bin", cfw_theme); DrawBottomSplash(str); TOP_Current = 0; drawInternalY = 0; DrawDebug(1, 1, ""); DrawDebug(1, 1, ""); DrawDebug(1, 1, ""); DrawDebug(1, 1, ""); int i; char* beg; for (i = 0; i < SETTINGS_ITEMS; i++) { if (i == settings_idx) beg = "->"; else beg = " "; if (i == 0)DrawSettingsDebug(1, "%s Always boot the GUI <%s>", beg, autobootgui ? "YES" : "NO "); else if (i == 1)DrawSettingsDebug(1, "%s Enable FirmLaunch <%s>", beg, enable_firmlaunch ? "YES" : "NO "); else if (i == 2)DrawSettingsDebug(1, "%s Change theme < %c >", beg, cfw_theme); DrawDebug(1, 1, ""); } //APP CONTROLS u32 pad_state = HidWaitForInput(); if (pad_state & BUTTON_DOWN) { if (settings_idx != SETTINGS_ITEMS - 1) settings_idx++; //MOVE DOWN else settings_idx = 0; //MOVE DOWN While at bottom -> go to top } else if (pad_state & BUTTON_UP) { if (settings_idx != 0) settings_idx--; //MOVE UP else settings_idx = SETTINGS_ITEMS - 1; //MOVE UP While at top -> go to bottom } else if (pad_state & BUTTON_LEFT || pad_state & BUTTON_RIGHT) { if (settings_idx == 0) autobootgui = !autobootgui; //autobootgui settings else if (settings_idx == 1) enable_firmlaunch = !enable_firmlaunch; //enable firmlaunch else if (settings_idx == 2) //theme selection { if (pad_state & BUTTON_LEFT && cfw_theme != '0') { cfw_theme--; sprintf(str, "/3ds/PastaCFW/UI/%c/menuTOP.bin", cfw_theme); //DRAW TOP SCREEN TO SEE THE NEW THEME DrawTopSplash(str); //TOP SCREEN } else if (pad_state & BUTTON_RIGHT && cfw_theme != '9') { sprintf(str, "/3ds/PastaCFW/UI/%c/options.bin", cfw_theme + 1); if (FSFileOpen(str)) { cfw_theme++; sprintf(str, "/3ds/PastaCFW/UI/%c/menuTOP.bin", cfw_theme);//DRAW TOP SCREEN TO SEE THE NEW THEME DrawTopSplash(str); } } } } else if (pad_state & BUTTON_A) { //SAVE SETTINGS FSFileOpen("/3ds/PastaCFW/system.txt"); char tobewritten[4]; tobewritten[0] = cfw_FWValue; tobewritten[1] = autobootgui ? '2' : '1'; tobewritten[2] = enable_firmlaunch ? '1' : '0'; tobewritten[3] = cfw_theme; cfw_enablefirmlaunch = enable_firmlaunch; FSFileWrite(tobewritten, 4, 0); FSFileClose(); break; } else if (pad_state & BUTTON_B) { cfw_theme = settings[3]; break; } //EXIT WITHOUT SAVING } }