5 * Copyright (C) 2010-2011 Scott Smith
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 CProfile::CProfile() : CBase(),
26 LaunchableDirs (false),
41 AlphabeticIndices.resize(TOTAL_LETTERS, 0);
48 int8_t CProfile::Load( const string& location, const string& delimiter )
54 fin.open(location.c_str(), ios_base::in);
58 Log( "Error: Failed to open profile\n" );
62 // Read in the profile
73 if (line.length() > 0)
76 if (UnprefixString( TargetApp, line, PROFILE_TARGETAPP ) == true)
81 if (UnprefixString( FilePath, line, PROFILE_FILEPATH ) == true)
87 if (line.at(0) == '<' && line.at(line.length()-1) == '>')
89 if (LoadCmd(fin, line, delimiter))
91 Log( "Error: Loading command from %s\n", location.c_str() );
97 if (line.at(0) == '[' && line.at(line.length()-1) == ']')
99 if (LoadExt(fin, line, delimiter))
101 Log( "Error: Loading extension from %s\n", location.c_str() );
107 if (line.at(0) == '{' && line.at(line.length()-1) == '}')
109 if (LoadEntry(fin, line, delimiter))
111 Log( "Error: Loading entry from %s\n", location.c_str() );
130 Log( "Error: Failed to open profile\n" );
137 Log( "Error: Loading plugin from %s\n", location.c_str() );
142 if (FilePath.length()<=0)
144 Log( "Error: file path was not read from profile\n" );
147 if (Extensions.size()<=0)
149 Log( "Error: no extensions were read from profile\n" );
156 int8_t CProfile::LoadCmd( ifstream& fin, string& line, const string& delimiter )
162 vector<string> parts;
165 cmd.Name = line.substr( 1, line.length()-2 );
167 // Command location and script
169 if (UnprefixString( line, line, PROFILE_CMDPATH ) == true)
171 cmd.Command = line.substr( line.find_last_of('/')+1 );
172 cmd.Path = line.substr( 0, line.find_last_of('/')+1 );
174 if (cmd.Command.compare("./") == 0)
176 cmd.Command = string(getenv("PWD"))+"/";
184 Log( "Error: %s not found\n", PROFILE_CMDPATH );
188 // Command arguments and values
190 while (UnprefixString( line, line, PROFILE_CMDARG ) == true)
192 SplitString( delimiter, line, parts );
194 if (parts.size() >= ARG_MIN_COUNT)
196 arg.Flag = parts.at(0);
197 arg.Default = a_to_i( parts.at(1) );
201 for (i=2; i<parts.size(); i++)
203 arg.Names.push_back( parts.at(i) );
207 arg.Values.push_back( parts.at(i) );
211 Log( "Error: Uneven number of argument names to values\n" );
216 if (arg.Default >= arg.Values.size())
218 arg.Default = arg.Values.size()-1;
221 cmd.Arguments.push_back( arg );
224 getline( fin, line );
228 Log( "Error: Not enough argument parts detected\n" );
235 Log( "Error: %s not found at least once\n", PROFILE_CMDARG );
239 Commands.push_back(cmd);
243 int8_t CProfile::LoadPlugins()
250 // all hardcoded for now!
251 // init video plugins
252 plugin.Name=string("Video Plugin");
253 plugin.TextFile=string("videodriver");
254 // plugin.TextFile+=string(".txt");
256 one.Name="Glide GLES2";
257 one.So="mupen64plus-video-glide64mk2";
258 plugin.Plugins.push_back(one);
259 one.Name="Rice GLES2";
260 one.So="mupen64plus-video-rice";
261 plugin.Plugins.push_back(one);
262 one.Name="Rice GLES1.1";
263 one.So="mupen64plus-video-ricees1";
264 plugin.Plugins.push_back(one);
266 one.So="mupen64plus-video-gles2n64";
267 plugin.Plugins.push_back(one);
268 one.Name="Arachnoid GLES1.1";
269 one.So="mupen64plus-video-arachnoid";
270 plugin.Plugins.push_back(one);
272 Plugins.push_back(plugin);
274 plugin.Plugins.clear();
275 // init audio plugins
276 plugin.Name="Audio Plugin";
277 plugin.TextFile="audiodriver";
278 // plugin.TextFile+=".txt";
280 one.Name="Notaz Audio";
281 one.So="notaz_audio";
282 plugin.Plugins.push_back(one);
283 one.Name="SDL Audio";
284 one.So="mupen64plus-audio-sdl";
285 plugin.Plugins.push_back(one);
287 Plugins.push_back(plugin);
289 plugin.Plugins.clear();
291 plugin.Name="RSP Plugin";
292 plugin.TextFile="rspdriver";
293 // plugin.TextFile+=".txt";
295 one.Name="Default HLE RSP";
296 one.So="mupen64plus-rsp-hle";
297 plugin.Plugins.push_back(one);
298 one.Name="Z64 LLE RSP with HLE Video";
299 one.So="mupen64plus-rsp-z64-hlevideo";
300 plugin.Plugins.push_back(one);
301 one.Name="Z64 LLE RSP";
302 one.So="mupen64plus-rsp-z64";
303 plugin.Plugins.push_back(one);
305 Plugins.push_back(plugin);
309 for (index=0; index<Plugins.size(); index++) {
310 fplug.open((Plugins.at(index).TextFile+".txt").c_str(), ios_base::in);
312 Plugins.at(index).Which=0;
314 // Read in the default value
315 if (fplug && fplug.is_open())
318 if (line.length() > 0)
321 for (i=0; i<Plugins[index].Plugins.size(); i++)
322 if (lowercase(Plugins[index].Plugins[i].So).compare(lowercase(line))==0)
323 Plugins[index].Which=i;
332 int8_t CProfile::LoadExt( ifstream& fin, string& line, const string& delimiter )
336 vector<string> parts;
344 extensions = line.substr(1, line.length()-2);
345 SplitString( delimiter, extensions, parts );
347 for (i=0; i<parts.size(); i++)
349 ext.extName.push_back( lowercase(parts.at(i)) );
352 if (ext.extName.size() == 0)
354 Log( "Error: no extensions detected\n" );
358 // Extension executable
360 if (UnprefixString( line, line, PROFILE_EXEPATH ) == true)
362 ext.exeName = line.substr( line.find_last_of('/')+1 );
363 ext.exePath = line.substr( 0, line.find_last_of('/')+1 );
365 if (ext.exePath.compare("./") == 0)
367 ext.exePath = string(getenv("PWD"))+"/";
374 Log( "Error: %s not found\n", PROFILE_EXEPATH );
378 // Extension blacklist
379 if (UnprefixString( line, line, PROFILE_BLACKLIST ) == true)
381 SplitString( delimiter, line, ext.Blacklist );
386 // Extension arguments
388 while (UnprefixString( line, line, PROFILE_EXTARG ) == true)
390 SplitString( delimiter, line, parts );
392 if (parts.size() >= ARG_MIN_COUNT)
394 arg.Flag = parts.at(0);
395 arg.Default = a_to_i( parts.at(1) );
399 for (i=2; i<parts.size(); i++)
401 arg.Names.push_back( parts.at(i) );
405 arg.Values.push_back( parts.at(i) );
409 Log( "Error: Uneven number of argument names to values\n" );
414 if (arg.Default >= arg.Values.size())
416 arg.Default = arg.Values.size()-1;
419 ext.Arguments.push_back(arg);
426 Log( "Error: Not enough argument parts detected\n" );
433 Log( "Error: %s not found at least once\n", PROFILE_EXTARG );
437 // Extension argforces
438 while (UnprefixString( line, line, PROFILE_ARGFORCE ) == true)
440 SplitString( delimiter, line, parts );
442 if (parts.size() == ARGFORCE_COUNT)
444 argforce.Path = parts.at(0);
445 CheckPath(argforce.Path);
447 argforce.Argument = a_to_i( parts.at(1) );
448 argforce.Value = parts.at(2);
449 ext.ArgForces.push_back( argforce );
453 Log( "Error: %s wrong number of parts actual: %d expected: %s\n", PROFILE_ARGFORCE, parts.size(), ARGFORCE_COUNT );
456 getline( fin, line );
460 while (UnprefixString( line, line, PROFILE_EXEFORCE ) == true)
462 SplitString( delimiter, line, parts );
464 if (parts.size()>=EXEFORCE_COUNT)
466 exeforce.exeName = parts.at(0).substr( line.find_last_of('/')+1 );
467 exeforce.exePath = parts.at(0).substr( 0, line.find_last_of('/')+1 );
469 if (exeforce.exePath.compare("./") == 0)
471 exeforce.exePath = string(getenv("PWD"))+"/";
474 exeforce.Files.clear();
475 for (i=1; i<parts.size(); i++)
477 exeforce.Files.push_back( parts.at(i) );
479 ext.ExeForces.push_back( exeforce );
483 Log( "Error: %s wrong number of parts actual: %d expected: %s\n", PROFILE_EXEFORCE, parts.size(), EXEFORCE_COUNT );
486 getline( fin, line );
488 Extensions.push_back(ext);
490 // Check for directory exe
491 if (ext.exeName.length() > 0)
493 for (i=0; i<ext.extName.size(); i++)
495 if (CheckExtension( ext.extName.at(i), EXT_DIRS) >= 0)
497 LaunchableDirs = true;
505 int8_t CProfile::LoadEntry( ifstream& fin, string& line, const string& delimiter )
508 string::size_type pos1,pos2;
510 vector<string> parts;
513 pos1 = line.find_last_of('/');
514 pos2 = line.find_last_of(delimiter);
515 entry.Path = line.substr( 1, pos1 );
516 entry.Name = line.substr( pos1+1, pos2-pos1-1 );
517 entry.Alias = line.substr( pos2+1, line.length()-pos2-2 );
520 // Extension executable
522 if (UnprefixString( line, line, PROFILE_ENTRY_CMDS ) == true)
524 SplitString( delimiter, line, parts );
525 for (i=0; i<parts.size(); i++)
527 entry.CmdValues.push_back( a_to_i( parts.at(i) ) );
532 Log( "Error: %s not found\n", PROFILE_ENTRY_CMDS );
537 if (UnprefixString( line, line, PROFILE_ENTRY_ARGS ) == true)
539 SplitString( delimiter, line, parts );
540 for (i=0; i<parts.size(); i++)
542 entry.ArgValues.push_back( a_to_i( parts.at(i) ) );
547 Log( "Error: %s not found\n", PROFILE_ENTRY_ARGS );
550 Entries.push_back( entry );
555 int16_t CProfile::AddEntry( listoption_t& argument, const string& name )
561 entry.Path = FilePath;
563 entry.CmdValues.clear();
564 for (i=0; i<Commands.size(); i++)
566 for (j=0; j<Commands.size(); j++)
568 entry.CmdValues.push_back(Commands.at(i).Arguments.at(j).Default);
571 entry.ArgValues.clear();
572 if (CheckRange( argument.Extension, Extensions.size() ))
574 for (i=0; i<Extensions.at(argument.Extension).Arguments.size(); i++)
576 entry.ArgValues.push_back(Extensions.at(argument.Extension).Arguments.at(i).Default);
581 Log( "Warning: AddEntry argument.Extension out of range for Extensions\n" );
584 Entries.push_back(entry);
586 return Entries.size()-1;
589 int8_t CProfile::Save( const string& location, const string& delimiter )
591 uint16_t index, i, j;
594 fout.open( location.c_str(), ios_base::trunc );
598 Log( "Failed to open profile\n" );
602 // Write out the profile
605 fout << "# Global Settings" << endl;
606 fout << PROFILE_TARGETAPP << TargetApp << endl;
607 fout << PROFILE_FILEPATH << FilePath << endl;
609 fout << endl << "# Command Settings" << endl;
610 for (index=0; index<Commands.size(); index++)
612 fout << "<" << Commands.at(index).Name << ">" << endl;
613 fout << PROFILE_CMDPATH << Commands.at(index).Path << Commands.at(index).Command << endl;
615 for (i=0; i<Commands.at(index).Arguments.size(); i++)
617 fout << PROFILE_CMDARG << Commands.at(index).Arguments.at(i).Flag
619 << i_to_a(Commands.at(index).Arguments.at(i).Default);
620 for (j=0; j<Commands.at(index).Arguments.at(i).Values.size(); j++)
622 fout << delimiter << Commands.at(index).Arguments.at(i).Names.at(j);
623 fout << delimiter << Commands.at(index).Arguments.at(i).Values.at(j);
630 fout << endl << "# Extension Settings" << endl;
631 for (index=0; index<Extensions.size(); index++)
634 for ( i=0; i<Extensions.at(index).extName.size(); i++ )
640 fout << Extensions.at(index).extName.at(i);
645 fout << PROFILE_EXEPATH + Extensions.at(index).exePath + Extensions.at(index).exeName << endl;
648 if (Extensions.at(index).Blacklist.size()>0)
650 fout << PROFILE_BLACKLIST;
651 for (i=0; i<Extensions.at(index).Blacklist.size(); i++)
657 fout << Extensions.at(index).Blacklist.at(i);
662 for (i=0; i<Extensions.at(index).Arguments.size(); i++)
664 fout << PROFILE_EXTARG << Extensions.at(index).Arguments.at(i).Flag
666 << i_to_a(Extensions.at(index).Arguments.at(i).Default);
667 for (j=0; j<Extensions.at(index).Arguments.at(i).Values.size(); j++)
669 fout << delimiter << Extensions.at(index).Arguments.at(i).Names.at(j);
670 fout << delimiter << Extensions.at(index).Arguments.at(i).Values.at(j);
675 for (i=0; i<Extensions.at(index).ArgForces.size(); i++)
677 fout << PROFILE_ARGFORCE << Extensions.at(index).ArgForces.at(i).Path
678 << delimiter << i_to_a(Extensions.at(index).ArgForces.at(i).Argument)
679 << delimiter << Extensions.at(index).ArgForces.at(i).Value << endl;
682 for (i=0; i<Extensions.at(index).ExeForces.size(); i++)
684 fout << PROFILE_EXEFORCE << Extensions.at(index).ExeForces.at(i).exePath
685 << Extensions.at(index).ExeForces.at(i).exeName;
686 for (j=0; j<Extensions.at(index).ExeForces.at(i).Files.size(); j++)
688 fout << delimiter << Extensions.at(index).ExeForces.at(i).Files.at(j);
695 fout << endl << "# Custom Entries Settings" << endl;
696 for (index=0; index<Entries.size(); index++)
698 if (Entries.at(index).Custom == true)
700 // Entry path, name, and alias
701 fout << "{" << Entries.at(index).Path << Entries.at(index).Name
703 << Entries.at(index).Alias << "}" << endl;
704 // Entry command values
705 fout << PROFILE_ENTRY_CMDS;
706 for (i=0; i<Entries.at(index).CmdValues.size(); i++)
712 fout << Entries.at(index).CmdValues.at(i);
715 // Entry argument values
716 fout << PROFILE_ENTRY_ARGS;
717 for (i=0; i<Entries.at(index).ArgValues.size(); i++)
723 fout << Entries.at(index).ArgValues.at(i);
733 Log( "Failed to open profile\n" );
739 int8_t CProfile::ScanEntry( listitem_t& item, vector<listoption_t>& items )
747 // Find the extension
748 if (item.Type == TYPE_DIR && LaunchableDirs == true)
750 ext_index = FindExtension(EXT_DIRS);
754 ext_index = FindExtension(item.Name);
757 if (CheckRange( ext_index, Extensions.size()))
759 option.Extension = ext_index;
761 // Scan for command arguments
762 for (i=0; i<Commands.size(); i++)
764 for (j=0; j<Commands.at(i).Arguments.size(); j++)
766 option.Name = Commands.at(i).Name + " " + Commands.at(i).Arguments.at(j).Flag + " ";
767 if (CheckRange( item.Entry, Entries.size() ))
769 if (Entries.at(item.Entry).CmdValues.at(j) < Commands.at(i).Arguments.at(j).Names.size())
771 option.Name += Commands.at(i).Arguments.at(j).Names.at( Entries.at(item.Entry).CmdValues.at(j) );
775 option.Name += "Error: ScanEntry Entry out of range";
780 if (CheckRange( Commands.at(i).Arguments.at(j).Default, Commands.at(i).Arguments.at(j).Names.size() ))
782 option.Name += Commands.at(i).Arguments.at(j).Names.at( Commands.at(i).Arguments.at(j).Default );
786 option.Name += "Error: ScanEntry Default out of range";
791 items.push_back(option);
795 // Scan for extension arguments
796 for (i=0; i<Extensions.at(ext_index).Arguments.size(); i++)
798 option.Name = Extensions.at(ext_index).Arguments.at(i).Flag + " ";
799 if (CheckRange( item.Entry, Entries.size() ))
801 if (CheckRange( Entries.at(item.Entry).ArgValues.at(i), Extensions.at(ext_index).Arguments.at(i).Names.size()) &&
802 CheckRange( Entries.at(item.Entry).ArgValues.at(i), Extensions.at(ext_index).Arguments.at(i).Values.size()) )
804 option.Name += Extensions.at(ext_index).Arguments.at(i).Names.at( Entries.at(item.Entry).ArgValues.at(i) ) + " ";
805 option.Name += Extensions.at(ext_index).Arguments.at(i).Values.at( Entries.at(item.Entry).ArgValues.at(i) );
809 option.Name += "Error: bad custom entry";
814 if (CheckRange( Extensions.at(ext_index).Arguments.at(i).Default, Extensions.at(ext_index).Arguments.at(i).Names.size()) &&
815 CheckRange( Extensions.at(ext_index).Arguments.at(i).Default, Extensions.at(ext_index).Arguments.at(i).Values.size()) )
817 option.Name += Extensions.at(ext_index).Arguments.at(i).Names.at( Extensions.at(ext_index).Arguments.at(i).Default ) + " ";
818 option.Name += Extensions.at(ext_index).Arguments.at(i).Values.at( Extensions.at(ext_index).Arguments.at(i).Default );
822 option.Name += "Error: index not found";
827 items.push_back(option);
832 Log( "Error ScanEntry ext_index out of range\n" );
838 void CProfile::ScanArgument( listoption_t& item, vector<string>& values )
844 if (CheckRange( item.Command, Commands.size() ))
846 if (CheckRange(item.Argument, Commands.at(item.Command).Arguments.size() ))
848 for (index=0; index<Commands.at(item.Command).Arguments.at(item.Argument).Values.size(); index++)
850 values.push_back( Commands.at(item.Command).Arguments.at(item.Argument).Values.at(index) );
855 Log( "Error: ScanArgument Commands item.Argument out of range\n" );
856 values.push_back( "Error: Check log" );
859 else if (CheckRange( item.Extension, Extensions.size() ))
861 if (CheckRange( item.Argument, Extensions.at(item.Extension).Arguments.size() ))
863 for (index=0; index<Extensions.at(item.Extension).Arguments.at(item.Argument).Values.size(); index++)
865 values.push_back( Extensions.at(item.Extension).Arguments.at(item.Argument).Values.at(index) );
870 Log( "Error: ScanArgument Extensions item.Argument out of range\n" );
871 values.push_back( "Error: Check log" );
876 Log( "Error: ScanArgument item type undefined\n" );
877 values.push_back( "Error: Check log" );
881 int8_t CProfile::ScanDir( string location, bool showhidden, bool showzip, vector<listitem_t>& items )
893 vector<string> files;
894 vector<listitem_t>::iterator sort_index;
900 if (ZipFile.length() == 0)
902 if((dp = opendir(location.c_str())) == NULL)
904 Log( "Failed to open dir path %s\n", location.c_str() );
908 while ((dirp = readdir(dp)) != NULL)
910 filename = string(dirp->d_name);
912 if (filename.length() > 0)
915 if (filename.compare(".") == 0 || filename.compare("..") == 0)
918 // Skip hidden files and folders
919 if (showhidden == false && filename.at(0) == '.')
923 item.Name = filename;
924 if (dirp->d_type == DT_DIR) // Directories
926 // Filter out by blacklist
927 ext_index = FindExtension( EXT_DIRS );
929 if (CheckRange( ext_index, Extensions.size() ))
931 for (i=0; i<Extensions.at(ext_index).Blacklist.size(); i++)
933 if (Extensions.at(ext_index).Blacklist.at(i).compare(filename) == 0)
943 item.Type = TYPE_DIR;
944 items.push_back(item);
949 files.push_back(filename);
954 Log( "Error: filename length was 0\n" );
961 Minizip.ListFiles( FilePath + ZipFile, files );
965 for (file=0; file<files.size(); file++)
968 if (CheckExtension( files.at(file), ZIP_EXT) < 0 || // Any non-zip ext should be filtered
969 (CheckExtension( files.at(file), ZIP_EXT) >= 0 && showzip == false)) // only filter zip if internal support is off
971 // Filter out files by extension
972 ext_index = FindExtension( files.at(file) );
974 // Filter out by blacklist
976 if (CheckRange( ext_index, Extensions.size() ))
978 for (i=0; i<Extensions.at(ext_index).Blacklist.size(); i++)
980 if (Extensions.at(ext_index).Blacklist.at(i).compare(files.at(file)) == 0)
993 // Filter by search string
994 if (found != true && EntryFilter.length() > 0)
996 if (lowercase(files.at(file)).find( lowercase(EntryFilter), 0) != string::npos)
1006 // If here then item is valid and determine if an entry exists
1009 // Add to display list
1010 item.Name = files.at(file);
1011 // Check for zip file
1012 if (CheckExtension( files.at(file), ZIP_EXT) >= 0)
1014 item.Type = TYPE_ZIP;
1018 item.Type = TYPE_FILE;
1021 // Find if an entry has been defined
1023 for (i=0; i<Entries.size(); i++)
1025 if (Entries.at(i).Name.compare(files.at(file)) == 0 &&
1026 Entries.at(i).Path.compare(location) == 0)
1034 items.push_back(item);
1039 sort( items.begin(), items.end(), CompareItems );
1041 // Build alphabetic indices
1042 AlphabeticIndices.clear();
1043 AlphabeticIndices.resize(TOTAL_LETTERS, 0);
1044 for (i=0; i<items.size(); i++)
1046 if (items.at(i).Type != TYPE_DIR)
1048 if (items.at(i).Name.length() > 0 )
1050 alpha_index = tolower(items.at(i).Name.at(0))-'a';
1051 if (alpha_index < 'a' || alpha_index > 'z')
1053 alpha_index = TOTAL_LETTERS-1;
1056 if (CheckRange( alpha_index, AlphabeticIndices.size() ))
1058 if (AlphabeticIndices.at(alpha_index) == 0)
1060 AlphabeticIndices.at(alpha_index) = i;
1065 Log( "Error: Scandir alpha_index out of range\n" );
1072 for (i=0; i<AlphabeticIndices.size(); i++)
1074 if (AlphabeticIndices.at(i) == 0)
1076 AlphabeticIndices.at(i) = alpha_index;
1078 alpha_index = AlphabeticIndices.at(i);
1083 int16_t CProfile::FindExtension( const string& ext )
1087 for (i=0; i<Extensions.size(); i++)
1089 for (j=0; j<Extensions.at(i).extName.size(); j++)
1091 if (CheckExtension( ext, Extensions.at(i).extName.at(j)) >= 0)
1101 void CProfile::ScanDefPlugins( vector<listoption_t>& items )
1105 for (int i=0; i<Plugins.size(); i++)
1108 itm.Name = Plugins.at(i).Name;
1109 items.push_back(itm);
1113 void CProfile::ScanDef1Plugins( int8_t which, vector<listitem_t>& items )
1117 for (int i=0; i<Plugins.at(which).Plugins.size(); i++)
1119 itm.Type = (i==Plugins[which].Which)?TYPE_DIR:TYPE_FILE;
1121 itm.Name = Plugins.at(which).Plugins.at(i).Name;
1122 items.push_back(itm);
1128 bool CompareItems( listitem_t a, listitem_t b )
1130 // Folders should be above files
1131 if (a.Type == TYPE_DIR && b.Type >= TYPE_FILE)
1135 else if (a.Type >= TYPE_FILE && b.Type == TYPE_DIR)
1141 // Convert to lower cases, so that upper case files are sorted with lower case files
1142 transform( a.Name.begin(), a.Name.end(), a.Name.begin(), (int (*)(int))tolower );
1143 transform( b.Name.begin(), b.Name.end(), b.Name.begin(), (int (*)(int))tolower );
1145 if (a.Name.compare(b.Name) >= 0)
1156 void CProfile::SaveDef1Plugin( int8_t which, int8_t index )
1160 fout.open( (Plugins.at(which).TextFile+".txt").c_str(), ios_base::trunc );
1163 Log( "Failed to open profile\n" );
1167 // Write out the profile
1170 fout << Plugins.at(which).Plugins.at(index).So << endl;
1173 // Change the default
1174 Plugins[which].Which = index;
1178 void CProfile::ScanRomPlugins( const string& name, vector<listoption_t>& items )
1181 vector<string> parts;
1187 for (int i=0; i<Plugins.size(); i++)
1190 itm.Name = Plugins.at(i).Name;
1191 items.push_back(itm);
1192 Plugins.at(i).Rom = -1;
1195 //look for value in pandora/crc file
1196 if (Rom.compare("")!=0)
1200 fin.open( (string("pandora/")+Rom).c_str(), ios_base::in );
1202 if (fin && fin.is_open())
1204 // file exist; read and interpret
1208 SplitString( "=", line, parts );
1209 if (parts.size()==2)
1211 int8_t plug = FindPlugin(parts[0]);
1213 Plugins[plug].Rom = Find1Plugin(plug, parts[1]);
1221 void CProfile::ScanRom1Plugins( int8_t which, vector<listitem_t>& items )
1227 itm.Type = (itm.Entry == Plugins[which].Rom)?TYPE_DIR:TYPE_FILE;
1228 itm.Name = "default";
1229 items.push_back(itm);
1230 for (int i=0; i<Plugins[which].Plugins.size(); i++)
1232 itm.Type = TYPE_FILE;
1234 itm.Type = (itm.Entry == Plugins[which].Rom)?TYPE_DIR:TYPE_FILE;
1235 itm.Name = Plugins[which].Plugins.at(i).Name;
1236 items.push_back(itm);
1240 string CProfile::RomCRC(const string& name)
1242 char rom_header[0x40]; // rom header
1245 f = fopen(name.c_str(), "rb");
1247 Log("Unable to open file\n");
1250 fread(rom_header, 0x40, 1, f);
1257 // now, check header to unswap things...
1258 /* Btyeswap if .v64 image. */
1259 if(rom_header[0]==0x37)
1261 for (i = 0; i < 0x40; i+=2)
1264 rom_header[i]=rom_header[i+1];
1265 rom_header[i+1]=temp;
1268 /* Wordswap if .n64 image. */
1269 else if(rom_header[0]==0x40)
1271 for (i = 0; i < 0x40; i+=4)
1274 rom_header[i]=rom_header[i+3];
1275 rom_header[i+3]=temp;
1276 temp=rom_header[i+1];
1277 rom_header[i+1]=rom_header[i+2];
1278 rom_header[i+2]=temp;
1281 // check it's a Valid rom
1282 if ((rom_header[0]!=0x80)||(rom_header[1]!=0x37)||(rom_header[2]!=0x12)||(rom_header[3]!=0x40))
1284 Log("Unable to open file\n");
1290 sprintf(buff, "%02x%02x%02x%02x%02x%02x%02x%02x",
1291 rom_header[0x13], rom_header[0x12], rom_header[0x11], rom_header[0x10],
1292 rom_header[0x17], rom_header[0x16], rom_header[0x15], rom_header[0x14] );
1295 return string(buff);
1298 int8_t CProfile::FindPlugin(const string& name)
1301 for (i=0; i<Plugins.size(); i++)
1302 if (Plugins[i].TextFile.compare(name)==0)
1308 int8_t CProfile::Find1Plugin(int8_t which, const string& name)
1311 for (i=0; i<Plugins[which].Plugins.size(); i++)
1312 if (Plugins[which].Plugins[i].So.compare(name)==0)
1318 void CProfile::SaveRom1Plugin( int8_t which, int8_t index )
1320 if (Plugins[which].Rom == index)
1323 Plugins[which].Rom = index;
1324 //check if we want all default (i.e delete conf.) or not
1326 for (int i=0; i<Plugins.size(); i++)
1327 if (Plugins[i].Rom!=-1)
1332 remove((string("pandora/")+Rom).c_str());
1338 fout.open( (string("pandora/")+Rom).c_str(), ios_base::trunc );
1341 Log( "Failed to open Rom special conf\n" );
1345 // Write out the profile
1348 for (int i=0; i<Plugins.size(); i++)
1349 if (Plugins[i].Rom!=-1)
1350 fout << Plugins[i].TextFile << "=" << Plugins[i].Plugins[Plugins[i].Rom].So << endl;