mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-12-27 12:21:57 +01:00
4a566375e0
-added 'noflash' arg for meta.xml if you don't want the flash screen image to appear. and no i can't make it load a image from a folder. it must be compiled in the code. -added 'sdonly' arg for meta.xml for those of you that have everything on SD and hate the 20 second wait for wiiflow to search for usb devices. thanks einsteinx2! -added meta.xml args support. meaning when a homebrew boot.dol or elf is launched the meta.xml (if exist) will be read for arguments and those args sent when the app is launched. this fixes the issue of custom wait images when changing themes. -added spanish translation file 'spanish.ini'. thanks to ravmn for sending it to me! -other minor changes, mainly remarks added for myself.
471 lines
14 KiB
C++
471 lines
14 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2013 FIX94
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#include <algorithm>
|
|
#include "menu.hpp"
|
|
#include "channel/nand.hpp"
|
|
#include "defines.h"
|
|
|
|
TexData m_explorerBg;
|
|
s16 entries[7];
|
|
s16 entries_sel[7];
|
|
s16 m_explorerLblSelFolderBg;
|
|
s16 m_explorerLblSelFolder;
|
|
s16 m_explorerBtnSet;
|
|
s16 m_explorerBtnBack;
|
|
s16 m_explorerLblPage;
|
|
s16 m_explorerBtnPageM;
|
|
s16 m_explorerBtnPageP;
|
|
s16 m_explorerLblUser[4];
|
|
|
|
u32 dirs = 0;
|
|
u32 files = 0;
|
|
u32 start_pos = 0;
|
|
typedef struct {
|
|
char name[NAME_MAX];
|
|
} list_element;
|
|
list_element *elements = NULL;
|
|
u32 elements_num = 0;
|
|
char file[MAX_FAT_PATH];
|
|
char dir[MAX_FAT_PATH];
|
|
char folderPath[MAX_FAT_PATH];
|
|
char tmpPath[MAX_FAT_PATH];
|
|
u8 explorer_partition = 0;
|
|
bool folderExplorer = false;
|
|
bool wadsOnly = false;
|
|
|
|
void CMenu::_hideExplorer(bool instant)
|
|
{
|
|
for(u8 i = 0; i < 7; ++i)
|
|
{
|
|
m_btnMgr.hide(entries[i], instant);
|
|
m_btnMgr.hide(entries_sel[i], instant);
|
|
}
|
|
m_btnMgr.hide(m_explorerLblSelFolderBg, instant);
|
|
m_btnMgr.hide(m_explorerLblSelFolder, instant);
|
|
m_btnMgr.hide(m_explorerLblPage, instant);
|
|
m_btnMgr.hide(m_explorerBtnPageM, instant);
|
|
m_btnMgr.hide(m_explorerBtnPageP, instant);
|
|
m_btnMgr.hide(m_explorerBtnSet, instant);
|
|
m_btnMgr.hide(m_explorerBtnBack, instant);
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_explorerLblUser); ++i)
|
|
{
|
|
if(m_explorerLblUser[i] != -1)
|
|
m_btnMgr.hide(m_explorerLblUser[i], instant);
|
|
}
|
|
if(elements != NULL)
|
|
free(elements);
|
|
elements = NULL;
|
|
elements_num = 0;
|
|
}
|
|
|
|
void CMenu::_showExplorer(void)
|
|
{
|
|
_setBg(m_explorerBg, m_explorerBg);
|
|
|
|
m_btnMgr.show(m_explorerLblSelFolderBg);
|
|
m_btnMgr.show(m_explorerLblSelFolder);
|
|
m_btnMgr.show(m_explorerBtnBack);
|
|
if(folderExplorer)
|
|
m_btnMgr.show(m_explorerBtnSet);
|
|
|
|
for(u8 i = 0; i < ARRAY_SIZE(m_explorerLblUser); ++i)
|
|
{
|
|
if(m_explorerLblUser[i] != -1)
|
|
m_btnMgr.show(m_explorerLblUser[i]);
|
|
}
|
|
_refreshExplorer();
|
|
}
|
|
|
|
void CMenu::_Explorer(void)
|
|
{
|
|
CoverFlow.clear();
|
|
strcpy(folderPath, dir);
|
|
_showExplorer();
|
|
while(!m_exit)
|
|
{
|
|
_mainLoopCommon();
|
|
if(BTN_B_PRESSED)
|
|
{
|
|
memset(folderPath, 0, MAX_FAT_PATH);
|
|
break;
|
|
}
|
|
else if(BTN_HOME_PRESSED)
|
|
{
|
|
memset(dir, 0, MAX_FAT_PATH);
|
|
memset(folderPath, 0, MAX_FAT_PATH);
|
|
_refreshExplorer();
|
|
}
|
|
else if(BTN_PLUS_PRESSED || BTN_RIGHT_PRESSED)
|
|
{
|
|
_refreshExplorer(1);
|
|
}
|
|
else if(BTN_MINUS_PRESSED || BTN_LEFT_PRESSED)
|
|
{
|
|
_refreshExplorer(-1);
|
|
}
|
|
else if(BTN_A_PRESSED)
|
|
{
|
|
if(m_btnMgr.selected(m_explorerBtnPageP))
|
|
{
|
|
_refreshExplorer(1);
|
|
}
|
|
else if(m_btnMgr.selected(m_explorerBtnPageM))
|
|
{
|
|
_refreshExplorer(-1);
|
|
}
|
|
else if(m_btnMgr.selected(m_explorerBtnSet))
|
|
{
|
|
strcpy(folderPath, dir);
|
|
break;
|
|
}
|
|
else if(m_btnMgr.selected(m_explorerBtnBack))
|
|
{
|
|
memset(folderPath, 0, MAX_FAT_PATH);
|
|
break;
|
|
}
|
|
//if "..." is selected and path is not empty then go up(back) one folder
|
|
else if(m_btnMgr.selected(entries_sel[0]) && dir[0] != '\0')
|
|
{
|
|
//remove last folder or device+partition
|
|
if(strchr(dir, '/') != NULL)
|
|
{
|
|
*strrchr(dir, '/') = '\0';
|
|
if(strchr(dir, '/') != NULL)
|
|
*(strrchr(dir, '/')+1) = '\0';
|
|
}
|
|
strcpy(folderPath, dir);
|
|
//if dir is just device and : then clear path completely
|
|
if(strchr(dir, '/') == NULL)
|
|
{
|
|
memset(dir, 0, MAX_FAT_PATH);
|
|
memset(folderPath, 0, MAX_FAT_PATH);
|
|
}
|
|
else if(strchr(folderPath, '/') != strrchr(folderPath, '/'))
|
|
{
|
|
*strrchr(folderPath, '/') = '\0';
|
|
while(strlen(folderPath) > 48)
|
|
{
|
|
if(strchr(folderPath, '/') == strrchr(folderPath, '/'))
|
|
break;
|
|
memset(tmpPath, 0, MAX_FAT_PATH);
|
|
strncpy(tmpPath, strchr(folderPath, '/') + 1, MAX_FAT_PATH - 1);
|
|
strcpy(folderPath, tmpPath);
|
|
}
|
|
memset(tmpPath, 0, MAX_FAT_PATH);
|
|
if(strchr(folderPath, ':') == NULL)
|
|
strcpy(tmpPath, "/");
|
|
strcat(tmpPath, folderPath);
|
|
strcat(tmpPath, "/");
|
|
strcpy(folderPath, tmpPath);
|
|
}
|
|
_refreshExplorer();
|
|
}
|
|
for(u8 i = 1; i < 7; ++i)
|
|
{
|
|
if(m_btnMgr.selected(entries_sel[i]))
|
|
{
|
|
//if path is empty add device+partition#:/ to start path
|
|
if(dir[0] == '\0')
|
|
{
|
|
explorer_partition = i-1;
|
|
strcpy(dir, fmt("%s:/", DeviceName[i-1]));
|
|
strcpy(folderPath, dir);
|
|
_refreshExplorer();
|
|
}
|
|
//if it's a folder add folder+/ to path
|
|
else if(!fsop_FileExist(fmt("%s%s", dir, elements[start_pos+(i-1)].name)))
|
|
{
|
|
strcat(dir, elements[start_pos+(i-1)].name);
|
|
strcpy(folderPath, dir);
|
|
strcat(dir, "/");
|
|
while(strlen(folderPath) > 48)
|
|
{
|
|
if(strchr(folderPath, '/') == strrchr(folderPath, '/'))
|
|
break;
|
|
memset(tmpPath, 0, MAX_FAT_PATH);
|
|
strncpy(tmpPath, strchr(folderPath, '/') + 1, MAX_FAT_PATH - 1);
|
|
strcpy(folderPath, tmpPath);
|
|
}
|
|
memset(tmpPath, 0, MAX_FAT_PATH);
|
|
if(strchr(folderPath, ':') == NULL)
|
|
strcpy(tmpPath, "/");
|
|
strcat(tmpPath, folderPath);
|
|
strcat(tmpPath, "/");
|
|
strcpy(folderPath, tmpPath);
|
|
_refreshExplorer();
|
|
}
|
|
else
|
|
{
|
|
memset(file, 0, MAX_FAT_PATH);
|
|
strncpy(file, fmt("%s%s", dir, elements[start_pos+(i-1)].name), MAX_FAT_PATH);
|
|
if(strcasestr(file, ".mp3") != NULL || strcasestr(file, ".ogg") != NULL)
|
|
MusicPlayer.LoadFile(file, false);
|
|
else if(strcasestr(file, ".iso") != NULL || strcasestr(file, ".wbfs") != NULL)
|
|
{
|
|
_hideExplorer();
|
|
/* create header for id and path */
|
|
dir_discHdr tmpHdr;
|
|
memset(&tmpHdr, 0, sizeof(dir_discHdr));
|
|
memcpy(tmpHdr.path, file, 255);
|
|
/* check wii or gc */
|
|
FILE *fp = fopen(file, "rb");
|
|
fseek(fp, strcasestr(file, ".wbfs") != NULL ? 512 : 0, SEEK_SET);
|
|
fread((void*)&wii_hdr, 1, sizeof(discHdr), fp);
|
|
fclose(fp);
|
|
memcpy(tmpHdr.id, wii_hdr.id, 6);
|
|
if(wii_hdr.magic == WII_MAGIC)
|
|
{
|
|
currentPartition = explorer_partition;
|
|
_launchGame(&tmpHdr, false);
|
|
}
|
|
else if(wii_hdr.gc_magic == GC_MAGIC)
|
|
{
|
|
currentPartition = explorer_partition;
|
|
_launchGC(&tmpHdr, false);
|
|
}
|
|
_showExplorer();
|
|
}
|
|
else if(strcasestr(file, ".dol") != NULL || strcasestr(file, ".elf") != NULL)
|
|
{
|
|
_hideExplorer();
|
|
vector<string> arguments = _getMetaXML(file);
|
|
_launchHomebrew(file, arguments);
|
|
_showExplorer();
|
|
}
|
|
else if(strcasestr(file, ".txt") != NULL || strcasestr(file, ".nfo") != NULL
|
|
|| strcasestr(file, ".ini") != NULL || strcasestr(file, ".conf") != NULL
|
|
|| strcasestr(file, ".cfg") != NULL || strcasestr(file, ".xml") != NULL
|
|
|| strcasestr(file, ".log") != NULL)
|
|
{
|
|
_hideExplorer();
|
|
m_txt_view = true;
|
|
m_txt_path = file;
|
|
_about(false);
|
|
m_txt_view = false;
|
|
m_txt_path = NULL;
|
|
_showExplorer();
|
|
}
|
|
else if(strcasestr(file, ".wad") != NULL)
|
|
{
|
|
_hideExplorer();
|
|
_Wad(file);
|
|
_showExplorer();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_hideExplorer();
|
|
_initCF();
|
|
}
|
|
|
|
void CMenu::_initExplorer()
|
|
{
|
|
memset(dir, 0, MAX_FAT_PATH);
|
|
TexData blank_btn;
|
|
TexHandle.fromImageFile(blank_btn, fmt("%s/blank.png", m_imgsDir.c_str()));
|
|
|
|
m_explorerBg = _texture("EXPLORER/BG", "texture", theme.bg, false);
|
|
_addUserLabels(m_explorerLblUser, ARRAY_SIZE(m_explorerLblUser), "EXPLORER");
|
|
m_explorerLblSelFolderBg = _addLabel("EXPLORER/SELECTED_FOLDER_BG", theme.txtFont, L"", 0, 18, 640, 48, theme.txtFontColor, FTGX_JUSTIFY_LEFT, theme.btnTexC);
|
|
m_explorerLblSelFolder = _addText("EXPLORER/SELECTED_FOLDER", theme.txtFont, L"", 30, 30, 560, 40, theme.txtFontColor, FTGX_JUSTIFY_LEFT);
|
|
m_explorerBtnSet = _addButton("EXPLORER/SET_BTN", theme.btnFont, L"", 220, 400, 200, 48, theme.btnFontColor);
|
|
m_explorerBtnBack = _addButton("EXPLORER/BACK_BTN", theme.btnFont, L"", 420, 400, 200, 48, theme.btnFontColor);
|
|
m_explorerBtnPageM = _addPicButton("EXPLORER/PAGE_MINUS", theme.btnTexMinus, theme.btnTexMinusS, 20, 400, 48, 48);
|
|
m_explorerLblPage = _addLabel("EXPLORER/PAGE_BTN", theme.btnFont, L"", 68, 400, 104, 48, theme.btnFontColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE, theme.btnTexC);
|
|
m_explorerBtnPageP = _addPicButton("EXPLORER/PAGE_PLUS", theme.btnTexPlus, theme.btnTexPlusS, 172, 400, 48, 48);
|
|
|
|
_setHideAnim(m_explorerLblSelFolderBg, "EXPLORER/SELECTED_FOLDER_BG", 0, 0, -2.f, 0.f);
|
|
_setHideAnim(m_explorerLblSelFolder, "EXPLORER/SELECTED_FOLDER", 0, 0, -2.f, 0.f);
|
|
_setHideAnim(m_explorerBtnSet, "EXPLORER/SET_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_explorerBtnBack, "EXPLORER/BACK_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_explorerLblPage, "EXPLORER/PAGE_BTN", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_explorerBtnPageM, "EXPLORER/PAGE_MINUS", 0, 0, 1.f, -1.f);
|
|
_setHideAnim(m_explorerBtnPageP, "EXPLORER/PAGE_PLUS", 0, 0, 1.f, -1.f);
|
|
|
|
for(u8 i = 0; i < 7; ++i)
|
|
{
|
|
entries_sel[i] = _addPicButton(fmt("EXPLORER/ENTRY_%i_BTN", i), blank_btn, blank_btn, 40, 75+(i*45), 380, 45);
|
|
entries[i] = _addText(fmt("EXPLORER/ENTRY_%i", i), theme.txtFont, L"", 40, 75+(i*45), 480, 40, theme.txtFontColor, FTGX_JUSTIFY_LEFT);
|
|
_setHideAnim(entries[i], fmt("EXPLORER/ENTRY_%i", i), 0, 0, 1.f, 0.f);
|
|
_setHideAnim(entries_sel[i], fmt("EXPLORER/ENTRY_%i_BTN", i), 0, 0, 1.f, 0.f);
|
|
}
|
|
_hideExplorer(true);
|
|
_textExplorer();
|
|
}
|
|
|
|
void CMenu::_textExplorer(void)
|
|
{
|
|
m_btnMgr.setText(m_explorerBtnSet, _t("cfgne34", L"Set"));
|
|
m_btnMgr.setText(m_explorerBtnBack, _t("cfgne35", L"Back"));
|
|
}
|
|
|
|
static bool list_element_cmp(list_element a, list_element b)
|
|
{
|
|
const char *first = a.name;
|
|
const char *second = b.name;
|
|
return char_cmp(first, second, strlen(first), strlen(second));
|
|
}
|
|
|
|
void CMenu::_refreshExplorer(s8 direction)
|
|
{
|
|
for(u8 i = 0; i < 7; ++i)
|
|
{
|
|
m_btnMgr.hide(entries[i], true);
|
|
m_btnMgr.hide(entries_sel[i], true);
|
|
m_btnMgr.setText(entries[i], L" ");
|
|
}
|
|
m_btnMgr.setText(entries[0], L". . .");
|
|
wstringEx path(_t("cfgne36", L"Path ="));
|
|
path.append(wfmt(L" %.48s", folderPath));
|
|
m_btnMgr.setText(m_explorerLblSelFolder, path, true);
|
|
|
|
if(direction == 0)
|
|
start_pos = 0;
|
|
|
|
//if path is empty show device+partitions only
|
|
if(dir[0] == '\0')
|
|
{
|
|
elements_num = 0;
|
|
for(u8 i = 1; i < 7; ++i)
|
|
{
|
|
if(DeviceHandle.IsInserted(i-1))
|
|
{
|
|
m_btnMgr.setText(entries[i], wfmt(L"%s:/", DeviceName[i-1]));
|
|
m_btnMgr.show(entries[i]);
|
|
m_btnMgr.show(entries_sel[i]);
|
|
}
|
|
}
|
|
}
|
|
//else show folders and files
|
|
else
|
|
{
|
|
m_btnMgr.show(entries[0]);
|
|
m_btnMgr.show(entries_sel[0]);
|
|
if(direction == 0)
|
|
{
|
|
dirent *pent = NULL;
|
|
DIR *pdir = NULL;
|
|
pdir = opendir(dir);
|
|
/* some sorting */
|
|
dirs = 0;
|
|
files = 0;
|
|
while((pent = readdir(pdir)) != NULL)
|
|
{
|
|
if(pent->d_name[0] == '.')
|
|
continue;
|
|
if(pent->d_type == DT_DIR)
|
|
dirs++;
|
|
else if(pent->d_type == DT_REG)
|
|
{
|
|
const char *fileType = strrchr(pent->d_name, '.');
|
|
if(!wadsOnly || (fileType != NULL && strcasecmp(fileType, ".wad") == 0))
|
|
files++;
|
|
}
|
|
}
|
|
u32 pos = 0;
|
|
if(elements != NULL)
|
|
free(elements);
|
|
elements_num = (folderExplorer ? dirs : dirs+files);
|
|
elements = (list_element*)MEM2_alloc(elements_num*sizeof(list_element));
|
|
if(dirs > 0)
|
|
{
|
|
rewinddir(pdir);
|
|
while((pent = readdir(pdir)) != NULL)
|
|
{
|
|
if(pent->d_name[0] == '.')
|
|
continue;
|
|
if(pent->d_type == DT_DIR)
|
|
{
|
|
memcpy(elements[pos].name, pent->d_name, NAME_MAX);
|
|
pos++;
|
|
}
|
|
}
|
|
std::sort(elements, elements+pos, list_element_cmp);
|
|
}
|
|
if(folderExplorer == false && files > 0)
|
|
{
|
|
rewinddir(pdir);
|
|
while((pent = readdir(pdir)) != NULL)
|
|
{
|
|
if(pent->d_name[0] == '.')
|
|
continue;
|
|
if(pent->d_type == DT_REG)
|
|
{
|
|
// here we will check pent->d_name to make sure it's a wad file and add it if it is
|
|
const char *fileType = strrchr(pent->d_name, '.');
|
|
if(!wadsOnly || (fileType != NULL && strcasecmp(fileType, ".wad") == 0))
|
|
{
|
|
memcpy(elements[pos].name, pent->d_name, NAME_MAX);
|
|
pos++;
|
|
}
|
|
}
|
|
}
|
|
std::sort(elements+dirs, elements+pos, list_element_cmp);
|
|
}
|
|
closedir(pdir);
|
|
}
|
|
if(direction == -1) /* dont question */
|
|
start_pos = start_pos >= 6 ? start_pos - 6 : (elements_num % 6 ? (elements_num - elements_num % 6) : elements_num - 6);
|
|
else if(direction == 1)
|
|
start_pos = start_pos + 6 >= elements_num ? 0 : start_pos + 6;
|
|
|
|
for(u8 i = 1; i < 7; i++)
|
|
{
|
|
if(start_pos+i > elements_num)
|
|
break;
|
|
if(start_pos+i <= dirs)
|
|
m_btnMgr.setText(entries[i], wfmt(L"/%.48s", elements[start_pos+i-1].name));
|
|
else
|
|
m_btnMgr.setText(entries[i], wfmt(L"%.48s", elements[start_pos+i-1].name));
|
|
m_btnMgr.show(entries[i]);
|
|
m_btnMgr.show(entries_sel[i]);
|
|
}
|
|
}
|
|
if(elements_num > 0)
|
|
m_btnMgr.setText(m_explorerLblPage, wfmt(L"%i / %i", (start_pos/6 + 1), ((elements_num - 1)/6 +1)));
|
|
else
|
|
m_btnMgr.setText(m_explorerLblPage, L"1 / 1");
|
|
m_btnMgr.show(m_explorerLblPage);
|
|
m_btnMgr.show(m_explorerBtnPageM);
|
|
m_btnMgr.show(m_explorerBtnPageP);
|
|
}
|
|
|
|
const char *CMenu::_FolderExplorer(const char *startPath)
|
|
{
|
|
folderExplorer = true;
|
|
memset(dir, 0, MAX_FAT_PATH);
|
|
strcpy(dir, startPath);
|
|
if(dir[strlen(dir) - 1] != '/')
|
|
strcat(dir, "/");
|
|
_Explorer();
|
|
folderExplorer = false;
|
|
if(strrchr(folderPath, '/') != NULL)
|
|
*strrchr(folderPath, '/') = '\0';
|
|
return folderPath;
|
|
}
|
|
|
|
void CMenu::_wadExplorer(void)
|
|
{
|
|
wadsOnly = true;
|
|
_Explorer();
|
|
wadsOnly = false;
|
|
}
|