- improved cover loader by adding 3 tries to load the covers. 2nd and third tries are there just to get any missing covers that didn't load the first time.

- homebrew list is now cached again. if you add or delete an app you must do a reload cache.
- if you use the custom blank covers by Abz they now need to go in wiiflow/boxcovers/blank_covers folder.
- homebrew covers must go in wiiflow/boxcovers/homebrew for full covers or wiiflow/covers/homebrew for 2d front covers.
- now using a cache subfolder named homebrew for homebrew covers wfc files. to keep them separate from the game ID games.
- sourceflow now does cache covers the first time and any time you load a new tier. if the covers are already cached then you will only see the progress bar for a split second.
- other minor changes.
- one problem. when using small_box for homebrew covers it will use the apps icon.png and if it has transparency it will look like crap.
This commit is contained in:
Fledge68 2019-03-27 11:45:43 -05:00
parent f581b3f193
commit 90fd389aac
12 changed files with 114 additions and 54 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -6,7 +6,7 @@
#else
#define APP_NAME "WiiFlow Lite"
#endif
#define APP_VERSION "5.3.0 beta 2"
#define APP_VERSION "5.3.0 beta 3"
#define APP_DATA_DIR "wiiflow"
#ifdef APP_WIIFLOW

View File

@ -2839,7 +2839,8 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
/* try to find the wfc texture file in the cache folder */
if(!m_cachePath.empty())
{
const char *wfcTitle = NULL;
char wfcTitle[64];
wfcTitle[63] = '\0';
const char *wfcCoverDir = NULL;
char *full_path = (char*)MEM2_alloc(MAX_FAT_PATH+1);
if(full_path == NULL)
@ -2851,18 +2852,20 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
{
const char *blankCoverPath = mainMenu.getBlankCoverPath(m_items[i].hdr);
if(blankCoverPath != NULL && strrchr(blankCoverPath, '/') != NULL)
wfcTitle = strrchr(blankCoverPath, '/') + 1;
strncpy(wfcTitle, strrchr(blankCoverPath, '/') + 1, sizeof(wfcTitle) - 1);
else
return CL_ERROR;
}
else
wfcTitle = getFilenameId(m_items[i].hdr);
strncpy(wfcTitle, getFilenameId(m_items[i].hdr), sizeof(wfcTitle) - 1);
/* get coverfolder for plugins and sourceflow */
/* get coverfolder for plugins, sourceflow, and homebrew */
if(m_items[i].hdr->type == TYPE_PLUGIN && m_pluginCacheFolders && !blankBoxCover)
wfcCoverDir = m_plugin.GetCoverFolderName(m_items[i].hdr->settings[0]);
if(m_items[i].hdr->type == TYPE_SOURCE && !blankBoxCover)
wfcCoverDir = "sourceflow";
if(m_items[i].hdr->type == TYPE_HOMEBREW)
wfcCoverDir = "homebrew";
/* set full path of wfc file */
if(wfcCoverDir != NULL)
@ -2879,7 +2882,6 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
else
strncpy(full_path, fmt("%s/%s.wfc", m_cachePath.c_str(), wfcTitle), MAX_FAT_PATH);
}
DCFlushRange(full_path, MAX_FAT_PATH+1);
/* load wfc file */
@ -2890,13 +2892,17 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
if(fp != NULL)//if wfc chache file is found
{
bool success = false;
struct stat stat_buf;
if(fstat(fileno(fp), &stat_buf) != 0)
if(fseek(fp, 0, SEEK_END) != 0)
{
fclose(fp);
return _loadCoverTexPNG(i, box, hq, blankBoxCover) ? CL_OK : CL_ERROR;
return CL_ERROR;
}
u32 fileSize = ftell(fp);
if(fseek(fp, 0, SEEK_SET) != 0)
{
fclose(fp);
return CL_ERROR;
}
u32 fileSize = stat_buf.st_size;
SWFCHeader header;
if(fileSize > sizeof(header))
@ -2904,7 +2910,7 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
if(fread(&header, 1, sizeof(header), fp) != sizeof(header))
{
fclose(fp);
return _loadCoverTexPNG(i, box, hq, blankBoxCover) ? CL_OK : CL_ERROR;
return CL_ERROR;
}
DCFlushRange(&header, sizeof(header));
//make sure wfc cache file matches what we want
@ -2929,15 +2935,9 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
{
/* if not HQ cover then skip (bufSize - texLen) texture data after header */
fseek(fp, sizeof(header) + (bufSize - texLen), SEEK_SET);
if(fread(tex.data, 1, texLen, fp) != texLen)
if(fread(tex.data, 1, texLen, fp) == texLen)
{
fclose(fp);
return _loadCoverTexPNG(i, box, hq, blankBoxCover) ? CL_OK : CL_ERROR;
}
DCFlushRange(tex.data, texLen);
}
if(!allocFailed)
{
LockMutex lock(m_mutex);
TexHandle.Cleanup(m_items[i].texture);
m_items[i].texture = tex;
@ -2945,6 +2945,7 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
m_items[i].boxTexture = header.full != 0;
success = true;
}
}
if(!success && tex.data != NULL)
{
free(tex.data);
@ -2960,8 +2961,7 @@ CCoverFlow::CLRet CCoverFlow::_loadCoverTex(u32 i, bool box, bool hq, bool blank
if(allocFailed)
return CL_NOMEM;
// If wfc cache file not found, load the PNG and create a wfc cache file
return _loadCoverTexPNG(i, box, hq, blankBoxCover) ? CL_OK : CL_ERROR;
return CL_ERROR;
}
void * CCoverFlow::_coverLoader(void *obj)
@ -2993,20 +2993,31 @@ void * CCoverFlow::_coverLoader(void *obj)
}
}
ret = CL_OK;
bool hq_done = false;
/* we try 3 passes to get the full cover. because the cover loader randomly skips the wfc file for unknown reasons */
/* first time is full cover only */
/* second time is full then front */
/* third is full then front then custom blank cover */
for(u8 k = 1; k < 4 && !cf->m_moved && update && ret != CL_NOMEM; k++)
{
for(j = 0; j <= bufferSize && !cf->m_moved && update && ret != CL_NOMEM; ++j)
{
i = loopNum((j & 1) ? firstItem - (j + 1) / 2 : firstItem + j / 2, cf->m_items.size());
cur_pos_hq = (hq_req && i == firstItem);
if((!hq_req || !cur_pos_hq) && cf->m_items[i].state != STATE_Loading)
if(!cur_pos_hq && cf->m_items[i].state != STATE_Loading)
continue;
if((ret = cf->_loadCoverTex(i, cf->m_box, cur_pos_hq, false)) == CL_ERROR)
if(cur_pos_hq && hq_done)
continue;
if(((ret = cf->_loadCoverTex(i, true, cur_pos_hq, false)) == CL_ERROR) && k > 1)
{
if ((ret = cf->_loadCoverTex(i, !cf->m_box, cur_pos_hq, false)) == CL_ERROR)
if(((ret = cf->_loadCoverTex(i, false, cur_pos_hq, false)) == CL_ERROR) && k > 2)
{
if((ret = cf->_loadCoverTex(i, cf->m_box, cur_pos_hq, true)) == CL_ERROR)
if((ret = cf->_loadCoverTex(i, true, cur_pos_hq, true)) == CL_ERROR)
cf->m_items[i].state = STATE_NoCover;
}
}
hq_done = (hq_done == false && ret == CL_OK && cur_pos_hq);
}
}
if(ret == CL_NOMEM && bufferSize > 3)
bufferSize -= 2;

View File

@ -79,6 +79,7 @@ CMenu::CMenu()
m_clearCats = true;
m_catStartPage = 1;
cacheCovers = false;
SF_cacheCovers = true;
/* Explorer stuff */
m_txt_view = false;
m_txt_path = NULL;
@ -2241,6 +2242,11 @@ bool CMenu::_loadList(void)
for(vector<dir_discHdr>::iterator tmp_itr = m_cacheList.begin(); tmp_itr != m_cacheList.end(); tmp_itr++)
m_gameList.push_back(*tmp_itr);
m_cacheList.Clear();
if(SF_cacheCovers)
{
SF_cacheCovers = false;
cacheCovers = true;
}
return true;
}
gprintf("Creating Gamelist\n");
@ -2294,7 +2300,12 @@ bool CMenu::_loadHomebrewList(const char *HB_Dir)
gprintf("Adding homebrew list\n");
string gameDir(fmt("%s:/%s", DeviceName[currentPartition], HB_Dir));
m_cacheList.CreateList(COVERFLOW_HOMEBREW, currentPartition, gameDir, stringToVector(".dol|.elf", '|'), std::string(), false);
string cacheDir(fmt("%s/%s_%s.db", m_listCacheDir.c_str(), DeviceName[currentPartition], HB_Dir));
bool updateCache = m_cfg.getBool(HOMEBREW_DOMAIN, "update_cache");
if(updateCache || !fsop_FileExist(cacheDir.c_str()))
cacheCovers = true;
m_cacheList.CreateList(COVERFLOW_HOMEBREW, currentPartition, gameDir, stringToVector(".dol|.elf", '|'), cacheDir, updateCache);
m_cfg.remove(HOMEBREW_DOMAIN, "update_cache");
for(vector<dir_discHdr>::iterator tmp_itr = m_cacheList.begin(); tmp_itr != m_cacheList.end(); tmp_itr++)
m_gameList.push_back(*tmp_itr);
return true;
@ -2671,8 +2682,7 @@ const char *CMenu::getBlankCoverPath(const dir_discHdr *element)
default:
blankCoverKey = "wii";
}
return fmt("%s/%s", m_boxPicDir.c_str(), m_theme.getString("BLANK_COVERS", blankCoverKey, fmt("%s.jpg", blankCoverKey)).c_str());
//return fmt("%s/%s.jpg", m_boxPicDir.c_str(), blankCoverKey);
return fmt("%s/blank_covers/%s", m_boxPicDir.c_str(), m_theme.getString("BLANK_COVERS", blankCoverKey, fmt("%s.jpg", blankCoverKey)).c_str());
}
const char *CMenu::getBoxPath(const dir_discHdr *element)
@ -2689,7 +2699,7 @@ const char *CMenu::getBoxPath(const dir_discHdr *element)
return fmt("%s/%s.png", m_boxPicDir.c_str(), tempname);
}
else if(element->type == TYPE_HOMEBREW)
return fmt("%s/%s.png", m_boxPicDir.c_str(), strrchr(element->path, '/') + 1);
return fmt("%s/homebrew/%s.png", m_boxPicDir.c_str(), strrchr(element->path, '/') + 1);
else if(element->type == TYPE_SOURCE)//sourceflow
{
const char *coverImg = strrchr(element->path, '/') + 1;
@ -2714,7 +2724,12 @@ const char *CMenu::getFrontPath(const dir_discHdr *element)
return fmt("%s/%s.png", m_picDir.c_str(), tempname);
}
else if(element->type == TYPE_HOMEBREW)
{
if(m_cfg.getBool(HOMEBREW_DOMAIN, "smallbox"))
return fmt("%s/icon.png", element->path);
else
return fmt("%s/homebrew/%s.png", m_picDir.c_str(), strrchr(element->path, '/') + 1);
}
else if(element->type == TYPE_SOURCE)//sourceflow
{
const char *coverImg = strrchr(element->path, '/') + 1;

View File

@ -62,6 +62,7 @@ private:
bool m_newGame;
bool show_mem;
bool cacheCovers;
bool SF_cacheCovers;
bool CFLocked;
vector<dir_discHdr> m_gameList;

View File

@ -103,6 +103,7 @@ void CMenu::_CfgHB(void)
else if (m_btnMgr.selected(m_cfghbBtnSmallbox))
{
m_refreshGameList = true;
m_cfg.setBool(HOMEBREW_DOMAIN, "update_cache", true);
m_cfg.setBool(HOMEBREW_DOMAIN, "smallbox", !m_cfg.getBool(HOMEBREW_DOMAIN, "smallbox", false));
m_btnMgr.setText(m_cfghbBtnSmallbox, m_cfg.getBool(HOMEBREW_DOMAIN, "smallbox") ? _t("on", L"On") : _t("off", L"Off"));
}
@ -115,6 +116,7 @@ void CMenu::_CfgHB(void)
else if (m_btnMgr.selected(m_cfghbBtnPartitionP) || m_btnMgr.selected(m_cfghbBtnPartitionM))
{
m_refreshGameList = true;
m_cfg.setBool(HOMEBREW_DOMAIN, "update_cache", true);
s8 direction = m_btnMgr.selected(m_cfghbBtnPartitionP) ? 1 : -1;
_setPartition(direction);
const char *partitionname = DeviceName[currentPartition];

View File

@ -125,12 +125,14 @@ void CMenu::_CfgSrc(void)
}
else if(m_btnMgr.selected(m_cfgsrcBtnSmallbox))
{
SF_cacheCovers = true;
temp = !m_cfg.getBool(SOURCEFLOW_DOMAIN, "smallbox", false);
m_cfg.setBool(SOURCEFLOW_DOMAIN, "smallbox", temp);
m_btnMgr.setText(m_cfgsrcBtnSmallbox, temp ? _t("on", L"On") : _t("off", L"Off"));
}
else if(m_btnMgr.selected(m_cfgsrcBtnBoxMode))
{
SF_cacheCovers = true;
temp = !m_cfg.getBool(SOURCEFLOW_DOMAIN, "box_mode", false);
m_cfg.setBool(SOURCEFLOW_DOMAIN, "box_mode", temp);
m_btnMgr.setText(m_cfgsrcBtnBoxMode, temp ? _t("on", L"On") : _t("off", L"Off"));

View File

@ -90,6 +90,8 @@ bool CMenu::_Home(void)
m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true);
if(m_current_view & COVERFLOW_PLUGIN)
m_cfg.setBool(PLUGIN_DOMAIN, "update_cache", true);
if(m_current_view & COVERFLOW_HOMEBREW)
m_cfg.setBool(HOMEBREW_DOMAIN, "update_cache", true);
m_refreshGameList = true;
break;
}
@ -416,13 +418,25 @@ int CMenu::_cacheCovers()
bool m_pluginCacheFolders = m_cfg.getBool(PLUGIN_DOMAIN, "subfolder_cache", true);
char coverPath[MAX_FAT_PATH];
char wfcPath[MAX_FAT_PATH+5];
char wfcPath[MAX_FAT_PATH+20];
char cachePath[MAX_FAT_PATH];
u32 total = m_gameList.size();
m_thrdTotal = total;
u32 index = 0;
bool smallBox = false;
if(m_current_view == COVERFLOW_HOMEBREW && !m_sourceflow)
smallBox = m_cfg.getBool(HOMEBREW_DOMAIN, "smallbox", false);
else if(m_sourceflow)
smallBox = m_cfg.getBool(SOURCEFLOW_DOMAIN, "smallbox", false);
else if(m_current_view == COVERFLOW_PLUGIN && !m_sourceflow)
{
m_plugin.GetEnabledPlugins(m_cfg, &enabledPluginsCount);
if(enabledPluginsCount == 1 && m_cfg.getBool(PLUGIN_ENABLED, "48425257"))
smallBox = m_cfg.getBool(HOMEBREW_DOMAIN, "smallbox", false);
}
for(vector<dir_discHdr>::iterator hdr = m_gameList.begin(); hdr != m_gameList.end(); ++hdr)
{
index++;
@ -430,29 +444,41 @@ int CMenu::_cacheCovers()
m_thrdMessage = wfmt(_fmt("dlmsg31", L"converting cover %i of %i"), index, total);
m_thrdMessageAdded = true;
bool fullCover = true;
/* get game name or ID */
const char *gameNameOrID = CoverFlow.getFilenameId(&(*hdr));// &(*hdr) converts iterator to pointer to mem address
const char *gameNameOrID = NULL;
gameNameOrID = CoverFlow.getFilenameId(&(*hdr));// &(*hdr) converts iterator to pointer to mem address
/* get cover png path */
bool fullCover = true;
strlcpy(coverPath, getBoxPath(&(*hdr)), sizeof(coverPath));
if(!fsop_FileExist(coverPath))
if(!fsop_FileExist(coverPath) || smallBox)
{
fullCover = false;
strlcpy(coverPath, getFrontPath(&(*hdr)), sizeof(coverPath));
if(!fsop_FileExist(coverPath) && !smallBox)
{
fullCover = true;
strlcpy(coverPath, getBlankCoverPath(&(*hdr)), sizeof(coverPath));
gameNameOrID = strrchr(coverPath, '/') + 1;
if(!fsop_FileExist(coverPath))
continue;
}
/* get cover wfc path */
if(hdr->type == TYPE_PLUGIN && m_pluginCacheFolders)
{
snprintf(cachePath, sizeof(cachePath), "%s/%s", m_cacheDir.c_str(), m_plugin.GetCoverFolderName(hdr->settings[0]));
}
/* get cache folder path */
if(hdr->type == TYPE_PLUGIN && m_pluginCacheFolders)
snprintf(cachePath, sizeof(cachePath), "%s/%s", m_cacheDir.c_str(), m_plugin.GetCoverFolderName(hdr->settings[0]));
else if(m_sourceflow)
snprintf(cachePath, sizeof(cachePath), "%s/sourceflow", m_cacheDir.c_str());
else if(hdr->type == TYPE_HOMEBREW)
snprintf(cachePath, sizeof(cachePath), "%s/homebrew", m_cacheDir.c_str());
else
snprintf(cachePath, sizeof(cachePath), "%s", m_cacheDir.c_str());
/* get cover wfc path */
if(smallBox)
snprintf(wfcPath, sizeof(wfcPath), "%s/%s_small.wfc", cachePath, gameNameOrID);
else
snprintf(wfcPath, sizeof(wfcPath), "%s/%s.wfc", cachePath, gameNameOrID);
/* if wfc doesn't exist or is flat and have full cover */

View File

@ -188,6 +188,8 @@ void CMenu::_showCF(bool refreshList)
_stop_pThread();
m_btnMgr.setText(m_wbfsLblDialog, _t("dlmsg14", L"Done."));
u8 pause = 150;
if(m_sourceflow)
pause = 1;
while(!m_exit)
{
_mainLoopCommon();

View File

@ -160,7 +160,7 @@ void CMenu::_checkEmuNandSettings(void)
}
}
}
gprintf("emu nand path = %s:/%s/%s\n", DeviceName[emuPart], emu_nands_dir, emuNands[curEmuNand]);
gprintf("emu nand path = %s:/%s/%s\n", DeviceName[emuPart], emu_nands_dir, emuNands[curEmuNand].c_str());
_listEmuNands(fmt("%s:/%s", DeviceName[savesPart], emu_nands_dir), savesNands);
curSavesNand = 0;
@ -183,7 +183,7 @@ void CMenu::_checkEmuNandSettings(void)
}
}
}
gprintf("saves nand path = %s:/%s/%s\n", DeviceName[savesPart], emu_nands_dir, savesNands[curSavesNand]);
gprintf("saves nand path = %s:/%s/%s\n", DeviceName[savesPart], emu_nands_dir, savesNands[curSavesNand].c_str());
m_cfg.setString(WII_DOMAIN, "current_save_emunand", savesNands[curSavesNand]);
m_cfg.setInt(WII_DOMAIN, "savepartition", savesPart);

View File

@ -99,6 +99,7 @@ void CMenu::_sourceFlow()
tiers.push_back(fn);
m_source.unload();
m_source.load(fmt("%s/%s", m_sourceDir.c_str(), fn.c_str()));
SF_cacheCovers = true;
curflow = m_source.getInt("general", "flow", m_cfg.getInt(SOURCEFLOW_DOMAIN, "last_cf_mode", 1));
/* get max source button # */
m_max_source_btn = 0;