WiiFlow_Lite/source/list/list.cpp

537 lines
18 KiB
C++
Raw Normal View History

2012-01-21 21:57:41 +01:00
#include "list.hpp"
#include "gecko.h"
#include "GameTDB.hpp"
#include "config.hpp"
#include "defines.h"
#include "channels.h"
#include "gc.h"
#include "fileOps.h"
2012-01-21 21:57:41 +01:00
template <typename T>
2012-05-22 20:06:43 +02:00
void CList<T>::GetPaths(vector<string> &pathlist, string containing, string directory, bool wbfs_fs, bool dml, bool depth_limit)
2012-01-21 21:57:41 +01:00
{
if (!wbfs_fs)
{
/* Open primary directory */
DIR *dir_itr = opendir(directory.c_str());
if (!dir_itr) return;
vector<string> compares = stringToVector(containing, '|');
vector<string> temp_pathlist;
2012-01-21 21:57:41 +01:00
struct dirent *ent;
/* Read primary entries */
while((ent = readdir(dir_itr)) != NULL)
{
2012-05-22 20:06:43 +02:00
if(ent->d_name[0] == '.')
continue;
2012-01-21 21:57:41 +01:00
if(ent->d_type == DT_REG)
{
for(vector<string>::iterator compare = compares.begin(); compare != compares.end(); compare++)
2012-05-22 20:06:43 +02:00
{
2012-01-21 21:57:41 +01:00
if (strcasestr(ent->d_name, (*compare).c_str()) != NULL)
{
//gprintf("Pushing %s to the list.\n", sfmt("%s/%s", directory.c_str(), ent->d_name).c_str());
pathlist.push_back(sfmt("%s/%s", directory.c_str(), ent->d_name));
break;
}
2012-05-22 20:06:43 +02:00
}
2012-01-21 21:57:41 +01:00
}
else
temp_pathlist.push_back(sfmt("%s/%s", directory.c_str(), ent->d_name));
}
closedir(dir_itr);
bool FoundFile;
while(temp_pathlist.size())
2012-01-21 21:57:41 +01:00
{
2012-05-22 20:06:43 +02:00
while((dir_itr = opendir(temp_pathlist[0].c_str())) && !dir_itr)
temp_pathlist.erase(temp_pathlist.begin());
FoundFile = false;
2012-01-21 21:57:41 +01:00
/* Read subdirectory */
while((ent = readdir(dir_itr)) != NULL)
{
2012-05-22 20:06:43 +02:00
if(ent->d_name[0] == '.')
continue;
2012-05-22 20:06:43 +02:00
if(dml && FoundFile)
break;
if(ent->d_type == DT_REG)
2012-01-21 21:57:41 +01:00
{
for(vector<string>::iterator compare = compares.begin(); compare != compares.end(); compare++)
{
if(strcasestr(ent->d_name, (*compare).c_str()) != NULL)
2012-01-21 21:57:41 +01:00
{
FoundFile = true;
//gprintf("Pushing %s to the list.\n", sfmt("%s/%s", temp_pathlist[0].c_str(), ent->d_name).c_str());
pathlist.push_back(sfmt("%s/%s", temp_pathlist[0].c_str(), ent->d_name));
break;
}
}
}
else
{
2012-05-22 20:06:43 +02:00
if(!depth_limit)
temp_pathlist.push_back(sfmt("%s/%s", temp_pathlist[0].c_str(), ent->d_name));
else if(dml && !FoundFile && strncasecmp(ent->d_name, "sys", 3) == 0 &&
fsop_FileExist(fmt("%s/%s/boot.bin", temp_pathlist[0].c_str(), ent->d_name)))
{
FoundFile = true;
//gprintf("Pushing %s to the list.\n", sfmt("%s/%s/boot.bin", temp_pathlist[0].c_str(), ent->d_name).c_str());
pathlist.push_back(sfmt("%s/%s/boot.bin", temp_pathlist[0].c_str(), ent->d_name));
}
2012-01-21 21:57:41 +01:00
}
}
closedir(dir_itr);
/* Finished reading subdirectory, erase it */
temp_pathlist.erase(temp_pathlist.begin());
2012-01-21 21:57:41 +01:00
}
}
else
{
if(strcasestr(containing.c_str(), ".dol") != 0) return;
int partition = DeviceHandler::Instance()->PathToDriveType(directory.c_str());
wbfs_t* handle = DeviceHandler::Instance()->GetWbfsHandle(partition);
if (!handle) return;
u32 count = wbfs_count_discs(handle);
for(u32 i = 0; i < count; i++)
pathlist.push_back(directory);
}
}
template <>
void CList<string>::GetHeaders(vector<string> pathlist, vector<string> &headerlist, string, string, string, Config&)
2012-01-21 21:57:41 +01:00
{
//gprintf("Getting headers for CList<string>\n");
if(pathlist.size() < 1) return;
headerlist.reserve(pathlist.size() + headerlist.size());
for(vector<string>::iterator itr = pathlist.begin(); itr != pathlist.end(); itr++)
2012-01-21 21:57:41 +01:00
headerlist.push_back((*itr).c_str());
}
template <>
void CList<dir_discHdr>::GetHeaders(vector<string> pathlist, vector<dir_discHdr> &headerlist, string settingsDir, string curLanguage, string DMLgameUSBDir, Config &plugin)
2012-01-21 21:57:41 +01:00
{
if(pathlist.size() < 1) return;
headerlist.reserve(pathlist.size() + headerlist.size());
gprintf("Getting headers for paths in pathlist (%d)\n", pathlist.size());
dir_discHdr tmp;
u32 count = 0;
string GTitle;
Config custom_titles;
if (settingsDir.size() > 0)
{
string custom_titles_path = sfmt("%s/" CTITLES_FILENAME, settingsDir.c_str());
custom_titles.load(custom_titles_path.c_str());
}
GameTDB gameTDB;
if (settingsDir.size() > 0)
{
gameTDB.OpenFile(fmt("%s/wiitdb.xml", settingsDir.c_str()));
2012-01-21 21:57:41 +01:00
if(curLanguage.size() == 0) curLanguage = "EN";
gameTDB.SetLanguageCode(curLanguage.c_str());
}
for(vector<string>::iterator itr = pathlist.begin(); itr != pathlist.end(); itr++)
2012-01-21 21:57:41 +01:00
{
bzero(&tmp, sizeof(dir_discHdr));
strncpy(tmp.path, (*itr).c_str(), sizeof(tmp.path));
tmp.hdr.index = headerlist.size();
tmp.hdr.casecolor = 1;
2012-01-21 21:57:41 +01:00
bool wbfs = (*itr).rfind(".wbfs") != string::npos || (*itr).rfind(".WBFS") != string::npos;
if (wbfs || (*itr).rfind(".iso") != string::npos || (*itr).rfind(".ISO") != string::npos
|| (*itr).rfind(".bin") != string::npos || (*itr).rfind(".BIN") != string::npos)
2012-01-21 21:57:41 +01:00
{
char* filename = &(*itr)[(*itr).find_last_of('/')+1];
const char* dml_partition = DeviceName[DeviceHandler::Instance()->PathToDriveType((*itr).c_str())];
if((strcasecmp(filename, "game.iso") == 0 || strcasecmp(filename, "boot.bin") == 0) && strstr((*itr).c_str(), sfmt((strncmp(dml_partition, "sd", 2) != 0) ? DMLgameUSBDir.c_str() : DML_DIR, dml_partition).c_str()) != NULL)
{
FILE *fp = fopen((*itr).c_str(), "rb");
if( fp )
{
fseek( fp, 0, SEEK_SET );
fread( tmp.hdr.id, 1, 6, fp );
u8 gc_disc[1];
fread(gc_disc, 1, 1, fp);
GTitle = custom_titles.getString( "TITLES", (const char *) tmp.hdr.id );
int ccolor = custom_titles.getColor( "COVERS", (const char *) tmp.hdr.id, tmp.hdr.casecolor ).intVal();
if( GTitle.size() > 0 || ( gameTDB.IsLoaded() && gameTDB.GetTitle( (char *)tmp.hdr.id, GTitle ) ) )
{
//mbstowcs( tmp.title, GTitle.c_str(), sizeof(tmp.title) );
//Asciify( tmp.title );
wstringEx tmpString;
tmpString.fromUTF8(GTitle.c_str());
wcsncpy(tmp.title, tmpString.c_str(), 64);
if(gc_disc[0])
wcslcat(tmp.title, L" disc 2", sizeof(tmp.title));
tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor( (char *)tmp.hdr.id );
if( tmp.hdr.casecolor == 0xffffffff )
tmp.hdr.casecolor = 0;
tmp.hdr.gc_magic = 0xc2339f3d;
(*itr)[(*itr).find_last_of('/')] = 0;
if(strcasecmp(filename, "boot.bin") == 0)
(*itr)[(*itr).find_last_of('/')] = 0;
(*itr).assign(&(*itr)[(*itr).find_last_of('/') + 1]);
strcpy( tmp.path, (*itr).c_str() );
if(strncmp(dml_partition, "sd", 2) != 0)
{
if (GC_GameIsInstalled((char*)tmp.hdr.id, DeviceName[SD], DML_DIR) || GC_GameIsInstalled((char*)fmt("%s [%s]", tmp.hdr.title, (char *)tmp.hdr.id), DeviceName[SD], DML_DIR) || GC_GameIsInstalled(tmp.path, DeviceName[SD], DML_DIR))
wcslcat(tmp.title, L" \n(on SD)", sizeof(tmp.title));
}
gprintf("Found: %s\n", tmp.path);
headerlist.push_back( tmp );
continue;
}
fseek( fp, 0, SEEK_SET );
fread( &tmp.hdr, sizeof( discHdr ), 1, fp);
fclose(fp);
if ( tmp.hdr.gc_magic == 0xc2339f3d )
{
//mbstowcs( tmp.title, (const char *)tmp.hdr.title, sizeof( tmp.hdr.title ) );
//Asciify(tmp.title);
wstringEx tmpString;
tmpString.fromUTF8((const char *)tmp.hdr.title);
wcsncpy(tmp.title, tmpString.c_str(), 64);
if(gc_disc[0])
wcslcat(tmp.title, L" disc 2", sizeof(tmp.title));
tmp.hdr.casecolor = 0;
(*itr)[(*itr).find_last_of('/')] = 0;
if(strcasecmp(filename, "boot.bin") == 0)
(*itr)[(*itr).find_last_of('/')] = 0;
(*itr).assign(&(*itr)[(*itr).find_last_of('/') + 1]);
strcpy( tmp.path, (*itr).c_str() );
if(strncmp(dml_partition, "sd", 2) != 0)
{
if (GC_GameIsInstalled((char*)tmp.hdr.id, DeviceName[SD], DML_DIR) || GC_GameIsInstalled((char*)fmt("%s [%s]", tmp.hdr.title, (char *)tmp.hdr.id), DeviceName[SD], DML_DIR) || GC_GameIsInstalled(tmp.path, DeviceName[SD], DML_DIR))
wcslcat(tmp.title, L" \n(on SD)", sizeof(tmp.title));
}
gprintf("Found: %s\n", tmp.path);
headerlist.push_back( tmp );
continue;
}
}
continue;
}
2012-01-21 21:57:41 +01:00
Check_For_ID(tmp.hdr.id, (*itr).c_str(), "[", "]"); /* [GAMEID] Title, [GAMEID]_Title, Title [GAMEID], Title_[GAMEID] */
if(tmp.hdr.id[0] == 0)
{
Check_For_ID(tmp.hdr.id, (*itr).c_str(), "/", "."); /* GAMEID.wbfs, GAMEID.iso */
if(tmp.hdr.id[0] == 0)
{
Check_For_ID(tmp.hdr.id, (*itr).c_str(), "/", "_"); /* GAMEID_Title */
if(tmp.hdr.id[0] == 0)
{
Check_For_ID(tmp.hdr.id, (*itr).c_str(), "_", "."); /* Title_GAMEID */ // <-- Unsafe?
if(tmp.hdr.id[0] == 0)
Check_For_ID(tmp.hdr.id, (*itr).c_str(), " ", "."); /* Title GAMEID */ //<-- Unsafe?
}
}
}
if (!isalnum(tmp.hdr.id[0]) || tmp.hdr.id[0] == 0 || memcmp(tmp.hdr.id, "__CFG_", sizeof tmp.hdr.id) == 0)
{
gprintf("Skipping file: '%s'\n", (*itr).c_str());
continue;
}
2012-01-21 21:57:41 +01:00
// Get info from custom titles
GTitle = custom_titles.getString("TITLES", (const char *) tmp.hdr.id);
int ccolor = custom_titles.getColor("COVERS", (const char *) tmp.hdr.id, tmp.hdr.casecolor).intVal();
2012-01-21 21:57:41 +01:00
if(GTitle.size() > 0 || (gameTDB.IsLoaded() && gameTDB.GetTitle((char *)tmp.hdr.id, GTitle)))
{
//mbstowcs(tmp.title, GTitle.c_str(), sizeof(tmp.title));
//Asciify(tmp.title);
wstringEx tmpString;
tmpString.fromUTF8(GTitle.c_str());
wcsncpy(tmp.title, tmpString.c_str(), 64);
2012-01-21 21:57:41 +01:00
tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor((char *)tmp.hdr.id);
2012-01-21 21:57:41 +01:00
tmp.hdr.wifi = gameTDB.GetWifiPlayers((char *)tmp.hdr.id);
tmp.hdr.players = gameTDB.GetPlayers((char *)tmp.hdr.id);
//tmp.hdr.controllers = gameTDB.GetAccessories((char *)tmp.hdr.id);
tmp.hdr.magic = 0x5D1C9EA3;
headerlist.push_back(tmp);
continue;
}
FILE *fp = fopen((*itr).c_str(), "rb");
if (fp)
{
fseek(fp, wbfs ? 512 : 0, SEEK_SET);
fread(&tmp.hdr, sizeof(discHdr), 1, fp);
fclose(fp);
2012-01-21 21:57:41 +01:00
}
if (tmp.hdr.magic == 0x5D1C9EA3)
{
//mbstowcs(tmp.title, (const char *)tmp.hdr.title, sizeof(tmp.hdr.title));
//Asciify(tmp.title);
wstringEx tmpString;
tmpString.fromUTF8((const char *)tmp.hdr.title);
wcsncpy(tmp.title, tmpString.c_str(), 64);
tmp.hdr.casecolor = ccolor != 1 ? ccolor : 1;
2012-01-21 21:57:41 +01:00
headerlist.push_back(tmp);
continue;
}
/*if(wbfs)
2012-01-21 21:57:41 +01:00
{
wbfs_t *part = WBFS_Ext_OpenPart((char *)(*itr).c_str());
if (!part) continue;
// Get header
2012-01-21 21:57:41 +01:00
if(wbfs_get_disc_info(part, 0, (u8*)&tmp.hdr, sizeof(discHdr), NULL) == 0
&& memcmp(tmp.hdr.id, "__CFG_", sizeof tmp.hdr.id) != 0)
{
mbstowcs(tmp.title, (const char *)tmp.hdr.title, sizeof(tmp.title));
Asciify(tmp.title);
headerlist.push_back(tmp);
}
WBFS_Ext_ClosePart(part);
continue;
}*/
2012-01-21 21:57:41 +01:00
}
else if((*itr).rfind(".dol") != string::npos || (*itr).rfind(".DOL") != string::npos
|| (*itr).rfind(".elf") != string::npos || (*itr).rfind(".ELF") != string::npos)
{
char *filename = &(*itr)[(*itr).find_last_of('/')+1];
if(strcasecmp(filename, "boot.dol") != 0 && strcasecmp(filename, "boot.elf") != 0) continue;
(*itr)[(*itr).find_last_of('/')] = 0;
(*itr).assign(&(*itr)[(*itr).find_last_of('/') + 1]);
(*itr)[0] = toupper((*itr)[0]);
for (u32 i = 1; i < (*itr).size(); ++i)
{
if((*itr)[i] == '_' || (*itr)[i] == '-')
(*itr)[i] = ' ';
if((*itr)[i] == ' ')
{
(*itr)[i + 1] = toupper((*itr)[i + 1]);
i++;
}
else (*itr)[i] = tolower((*itr)[i]);
}
memcpy(tmp.hdr.id, (*itr).c_str(), 6);
for (u32 i = 0; i < 6; ++i)
2012-01-30 00:48:50 +01:00
{
tmp.hdr.id[i] = toupper(tmp.hdr.id[i]);
2012-01-21 21:57:41 +01:00
if(!isalnum(tmp.hdr.id[i]) || tmp.hdr.id[i] == ' ' || tmp.hdr.id[i] == '\0')
tmp.hdr.id[i] = '_';
2012-01-30 00:48:50 +01:00
}
2012-01-21 21:57:41 +01:00
2012-01-30 00:48:50 +01:00
// Get info from custom titles
wstringEx tmpString;
2012-01-30 00:48:50 +01:00
GTitle = custom_titles.getString("TITLES", (const char *) tmp.hdr.id);
int ccolor = custom_titles.getColor("COVERS", (const char *) tmp.hdr.id, tmp.hdr.casecolor).intVal();
if(GTitle.size() > 0 || (gameTDB.GetTitle((char *)tmp.hdr.id, GTitle)))
{
//mbstowcs(tmp.title, GTitle.c_str(), sizeof(tmp.title));
tmpString.fromUTF8(GTitle.c_str());
2012-01-30 00:48:50 +01:00
tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor((char *)tmp.hdr.id);
}
else
{
//mbstowcs(tmp.title, (*itr).c_str(), sizeof(tmp.title));
tmpString.fromUTF8((*itr).c_str());
2012-01-30 00:48:50 +01:00
tmp.hdr.casecolor = ccolor != 1 ? ccolor : 1;
}
//Asciify(tmp.title);
wcsncpy(tmp.title, tmpString.c_str(), 64);
2012-01-21 21:57:41 +01:00
headerlist.push_back(tmp);
continue;
}
else if(strncasecmp(DeviceHandler::Instance()->PathToFSName((*itr).c_str()), "WBFS", 4) == 0)
{
u8 partition = DeviceHandler::Instance()->PathToDriveType((*itr).c_str());
wbfs_t* handle = DeviceHandler::Instance()->GetWbfsHandle(partition);
if (!handle)
return;
2012-01-21 21:57:41 +01:00
s32 ret = wbfs_get_disc_info(handle, count, (u8 *)&tmp.hdr, sizeof(struct discHdr), NULL);
count++;
if(ret != 0)
continue;
GTitle = custom_titles.getString("TITLES", (const char *) tmp.hdr.id);
int ccolor = custom_titles.getColor("COVERS", (const char *) tmp.hdr.id, 1).intVal();
wstringEx tmpString;
if(GTitle.size() > 0 || (gameTDB.IsLoaded() && gameTDB.GetTitle((char *)tmp.hdr.id, GTitle)))
2012-01-21 21:57:41 +01:00
{
//mbstowcs(tmp.title, GTitle.c_str(), sizeof(tmp.title));
tmpString.fromUTF8(GTitle.c_str());
tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor((char *)tmp.hdr.id);
tmp.hdr.wifi = gameTDB.GetWifiPlayers((char *)tmp.hdr.id);
tmp.hdr.players = gameTDB.GetPlayers((char *)tmp.hdr.id);
//tmp.hdr.controllers = gameTDB.GetAccessories((char *)tmp.hdr.id);
if (tmp.hdr.magic == 0x5D1C9EA3)
{
//Asciify(tmp.title);
wcsncpy(tmp.title, tmpString.c_str(), 64);
headerlist.push_back(tmp);
}
continue;
}
if (tmp.hdr.magic == 0x5D1C9EA3)
{
//mbstowcs(tmp.title, (const char *)tmp.hdr.title, sizeof(tmp.hdr.title));
//Asciify(tmp.title);
tmpString.fromUTF8((const char *)tmp.hdr.title);
wcsncpy(tmp.title, tmpString.c_str(), 64);
tmp.hdr.casecolor = ccolor != 1 ? ccolor : 1;
2012-01-21 21:57:41 +01:00
headerlist.push_back(tmp);
}
2012-01-21 21:57:41 +01:00
continue;
}
else if(plugin.loaded())
{
vector<string> types = plugin.getStrings("PLUGIN","fileTypes",'|');
if (types.size() > 0)
{
for(vector<string>::iterator type_itr = types.begin(); type_itr != types.end(); type_itr++)
{
if(lowerCase(*itr).rfind((*type_itr).c_str()) != string::npos)
{
strncpy(tmp.path, (*itr).c_str(), sizeof(tmp.path));
int plugin_ccolor;
sscanf(plugin.getString("PLUGIN","coverColor","").c_str(), "%08x", &plugin_ccolor);
int ccolor = custom_titles.getColor("COVERS", (const char *) tmp.hdr.id, plugin_ccolor).intVal();
tmp.hdr.casecolor = ccolor != plugin_ccolor ? ccolor : plugin_ccolor;
char tempname[64];
(*itr).assign(&(*itr)[(*itr).find_last_of('/') + 1]);
if((*itr).find_last_of('.') != string::npos)
(*itr).erase((*itr).find_last_of('.'), (*itr).size() - (*itr).find_last_of('.'));
strncpy(tempname, (*itr).c_str(), sizeof(tempname));
//mbstowcs(tmp.title, tempname, sizeof(tmp.title));
//Asciify(tmp.title);
wstringEx tmpString;
tmpString.fromUTF8(tempname);
wcsncpy(tmp.title, tmpString.c_str(), 64);
gprintf("Found: %s\n", tmp.path);
sscanf(plugin.getString("PLUGIN","magic","").c_str(), "%08x", &tmp.hdr.magic); //Plugin magic
tmp.hdr.gc_magic = 0x4c4f4c4f; //Abusing gc_magic for general emu detection ;)
headerlist.push_back(tmp);
break;
}
}
}
continue;
}
2012-01-21 21:57:41 +01:00
}
if(gameTDB.IsLoaded())
gameTDB.CloseFile();
}
template <>
void CList<dir_discHdr>::GetChannels(vector<dir_discHdr> &headerlist, string settingsDir, u32 channelType, string curLanguage)
2012-01-21 21:57:41 +01:00
{
Channels m_channels;
m_channels.Init(channelType, curLanguage, true);
Config custom_titles;
if (settingsDir.size() > 0)
{
string custom_titles_path = sfmt("%s/" CTITLES_FILENAME, settingsDir.c_str());
custom_titles.load(custom_titles_path.c_str());
}
GameTDB gameTDB;
if (settingsDir.size() > 0)
{
gameTDB.OpenFile(fmt("%s/wiitdb.xml", settingsDir.c_str()));
2012-01-21 21:57:41 +01:00
if(curLanguage.size() == 0) curLanguage = "EN";
gameTDB.SetLanguageCode(curLanguage.c_str());
}
u32 count = m_channels.Count();
headerlist.reserve(count);
for (u32 i = 0; i < count; ++i)
{
Channel *chan = m_channels.GetChannel(i);
if (chan->id == NULL) continue; // Skip invalid channels
dir_discHdr tmp;
bzero(&tmp, sizeof(dir_discHdr));
tmp.hdr.index = headerlist.size();
tmp.hdr.casecolor = 1;
memcpy(tmp.hdr.id, chan->id, 4);
memcpy(tmp.title, chan->name, sizeof(tmp.title));
string GTitle = custom_titles.getString("TITLES", (const char *) tmp.hdr.id);
int ccolor = custom_titles.getColor("COVERS", (const char *) tmp.hdr.id, tmp.hdr.casecolor).intVal();
if(GTitle.size() > 0 || (gameTDB.IsLoaded() && gameTDB.GetTitle((char *)tmp.hdr.id, GTitle)))
mbstowcs(tmp.title, GTitle.c_str(), sizeof(tmp.title));
Asciify(tmp.title);
tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor((char *)tmp.hdr.id);
tmp.hdr.wifi = gameTDB.GetWifiPlayers((char *)tmp.hdr.id);
tmp.hdr.players = gameTDB.GetPlayers((char *)tmp.hdr.id);
//tmp.hdr.controllers = gameTDB.GetAccessories((char *)tmp.hdr.id);
tmp.hdr.chantitle = chan->title;
headerlist.push_back(tmp);
}
if(gameTDB.IsLoaded())
gameTDB.CloseFile();
}
template <typename T>
void CList<T>::Check_For_ID(u8 *id, string path, string one, string two)
{
size_t idstart = path.find_last_of(one);
size_t idend = path.find_last_of(two);
if (idend != string::npos && idstart != string::npos && idend - idstart == 7)
for(u8 pos = 0; pos < 6; pos++)
id[pos] = toupper(path[idstart + 1 + pos]);
}
template class CList<dir_discHdr>;
2012-01-30 00:48:50 +01:00
template class CList<string>;