2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002 Dave2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * Licence along with this program; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA
21 //****************************************************************
23 // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
24 // Project started on December 29th, 2001
27 // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
28 // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
30 // Official Glide64 development channel: #Glide64 on EFnet
32 // Original author: Dave2001 (Dave2999@hotmail.com)
33 // Other authors: Gonetz, Gugaman
35 //****************************************************************
55 #include <sys/resource.h>
59 #define PATH_MAX _MAX_PATH
60 #define stricmp _stricmp
65 int last_line; // last good line
66 int last_line_ret; // last line ended in return?
68 static char configdir[PATH_MAX] = {0};
71 //TODO: move INI_xxxx() function code into class and clean up
72 Ini *Ini::singleton = 0;
78 printf("Could not find INI file!");
86 singleton = new Ini();
90 void Ini::SetPath(const char *path)
92 if (!INI_FindSection(path, false))
94 printf("Could not find [%s] section in INI file!", path);
99 bool Ini::Read(const char *key, int *l)
101 int undef = 0xDEADBEEF;
102 int tmpVal = INI_ReadInt(key, undef, false);
114 bool Ini::Read(const char *key, int *l, int defaultVal)
116 *l = INI_ReadInt(key, defaultVal, false);
120 int Ini::Read(const char *key, int defaultVal)
122 return INI_ReadInt(key, defaultVal, false);
128 //TODO: use ConfigGetSharedDataFilepath
130 // Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll
132 if(strlen(configdir) > 0)
134 strncpy(path, configdir, PATH_MAX);
135 // make sure there's a trailing '/'
136 //if(path[strlen(path)-1] != '/')
137 // strncat(path, "/", PATH_MAX - strlen(path));
142 GetModuleFileName (NULL, path, PATH_MAX);
145 int n = readlink("/proc/curproc/files", path, PATH_MAX);
147 int n = readlink("/proc/self/exe", path, PATH_MAX);
149 if (n == -1) strcpy(path, "./");
152 char path2[PATH_MAX];
157 for (i=strlen(path2)-1; i>0; i--)
159 if(path2[i] == '/') break;
161 if(i == 0) strcpy(path, "./");
165 struct dirent *entry;
169 dir = opendir(path2);
170 while((entry = readdir(dir)) != NULL)
172 if(!strcmp(entry->d_name, "plugins"))
176 if(!gooddir) strcpy(path, "./");
182 // Find the previous backslash
184 for (i=strlen(path)-1; i>0; i--)
193 if (path == 0) return FALSE;
197 strcat(path, "plugins/");
201 //strncat (path, "Glide64mk2.ini", PATH_MAX - strlen(path));
202 LOG("opening %s\n", path);
204 ini = fopen (path, "rb");
207 ERRLOG("Could not find Glide64mk2.ini!");
210 ini = fopen (path, "w+b");
231 void INI_InsertSpace(int space)
233 printf("Inserting space, space to insert is %d\n", space);
234 // Since there is no good way to normally insert to or delete from a certain location in
235 // a file, this function was added. It will insert (or delete) space bytes at the
238 // note: negative count means delete
240 int len, file, start_pos, cur_pos;
248 start_pos = ftell(ini);
249 fseek(ini,0,SEEK_END);
251 // if adding, extend the file
254 _chsize (file, _filelength(file)+space);
258 fseek(ini, 0L, SEEK_END);
260 fseek(ini, t1, SEEK_SET);
261 if (ftruncate(file, t2+space) != 0)
262 ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
267 cur_pos = ftell(ini);
268 len = cur_pos - start_pos;
270 if (len > 2048) len = 2048;
272 fseek (ini,-len,SEEK_CUR);
273 if (fread(chunk,1,len,ini) != (size_t) len)
274 ERRLOG("Failed to read %i bytes from .ini file", len);
275 fseek (ini,-len+space,SEEK_CUR);
276 if (fwrite(chunk,1,len,ini) != (size_t) len)
277 ERRLOG("Failed to write %i bytes to .ini file", len);
278 fseek (ini,-len-space,SEEK_CUR);
281 // if deleted, make the file shorter
284 _chsize (file, _filelength(file)+space);
288 fseek(ini, 0L, SEEK_END);
290 fseek(ini, t1, SEEK_SET);
291 if (ftruncate(file, t2+space) != 0)
292 ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
297 BOOL INI_FindSection (const char *sectionname, BOOL create)
301 /* static char cached_secion[200]="\0";
302 static BOOL cached_result;
303 if (!strcasecmp(section,sectionname))
304 return cached_result;*/
307 // printf("INI_FindSection trying to find name for %s\n", sectionname);
309 char line[256], section[64];
311 int i, sectionfound, ret;
321 if (fgets(line,255,ini) == NULL)
326 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
327 // with just EOL), it would write into line[-1]
328 if(i>=1 && line[i-1]==0xa) {
331 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
338 if (p[0]=='/' && p[1]=='/')
346 // skip starting space
348 while(*p<=' ' && *p) p++;
353 last_line=ftell(ini); // where to add if not found
356 if(*p!='[') continue;
361 if(*p==']' || !*p) break;
367 if(!stricmp(section,sectionname))
369 if (!strcasecmp(section,sectionname))
372 sectionstart=ftell(ini);
378 if (!sectionfound && create)
380 // create the section
381 fseek(ini,last_line,SEEK_SET);
382 INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));
384 if (fwrite(&cr, 1, 2, ini) != 2)
385 ERRLOG("Failed to write <CR><LF> to .ini file");
386 sprintf (section, "[%s]", sectionname);
387 if (fwrite(&cr, 1, 2, ini) != 2 ||
388 fwrite(section, 1, strlen(section), ini) != strlen(section) ||
389 fwrite(&cr, 1, 2, ini) != 2)
390 ERRLOG("Failed to write Section line to .ini file");
391 sectionstart = ftell(ini);
392 last_line = sectionstart;
400 // Reads the value of item 'itemname' as a string.
401 const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)
403 char line[256], name[64];
408 fseek(ini,sectionstart,SEEK_SET);
413 if (fgets(line,255,ini) == NULL)
418 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
419 // with just EOL), it would write into line[-1]
420 // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
421 if(i>=1 && line[i-1]==0xa) {
424 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
439 // skip starting space
441 while(*p<=' ' && *p) p++;
449 last_line=ftell(ini); // where to add if not found
454 while(*p && *p!='=' && *p>' ') *n++ = *p++;
458 if(!stricmp(name,itemname))
460 if(!strcasecmp(name,itemname))
463 // skip spaces/equal sign
464 while(*p<=' ' || *p=='=') p++;
468 while(*p) *n++ = *p++;
470 // remove trailing spaces
471 while (*(n-1) == ' ') n--;
479 // uh-oh, not found. we need to create
482 fseek(ini,last_line,SEEK_SET);
483 INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);
485 if (fwrite(&cr, 1, 2, ini) != 2)
486 ERRLOG("Failed to write <CR><LF> to .ini file");
487 sprintf (line, "%s = %s", itemname, def_value);
488 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
489 fwrite(&cr, 1, 2, ini) != 2)
490 ERRLOG("Failed to write key,value line to .ini file");
491 last_line = ftell(ini);
495 strcpy (value, def_value);
499 // Reads the value of item 'itemname' as a string.
500 void INI_WriteString (const char *itemname, const char *value)
502 char line[256], name[64];
506 fseek(ini,sectionstart,SEEK_SET);
511 if (fgets(line,255,ini) == NULL) break;
515 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
516 // with just EOL), it would write into line[-1]
517 // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
518 if(i>=1 && line[i-1]==0xa) {
521 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
528 if (p[0]=='/' && p[1]=='/')
536 // skip starting space
538 while(*p<=' ' && *p) p++;
546 last_line=ftell(ini); // where to add if not found
551 while(*p && *p!='=' && *p>' ') *n++ = *p++;
555 if(!stricmp(name,itemname))
557 if(!strcasecmp(name,itemname))
560 INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));
561 sprintf (line, "%s = %s", itemname, value);
562 fseek (ini, -i, SEEK_CUR);
563 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
564 fwrite(&cr, 1, 2, ini) != 2)
566 ERRLOG("Failed to write line '%s' to .ini file", line);
568 last_line = ftell(ini);
574 // uh-oh, not found. we need to create
575 fseek(ini,last_line,SEEK_SET);
576 INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);
577 sprintf (line, "%s = %s", itemname, value);
579 if (fwrite(&cr, 1, 2, ini) != 2)
580 ERRLOG("Failed to write <CR> to .ini file");
581 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
582 fwrite(&cr, 1, 2, ini) != 2)
584 ERRLOG("Failed to write line '%s' to .ini file", line);
586 last_line = ftell(ini);
591 int INI_ReadInt (const char *itemname, int def_value, BOOL create)
596 char value[64], def[64];
598 _itoa (def_value, def, 10);
600 sprintf(def, "%d", def_value);
602 INI_ReadString (itemname, value, def, create);
606 void INI_WriteInt (const char *itemname, int value)
610 _itoa (value, valstr, 10);
612 sprintf(valstr, "%d", value);
614 INI_WriteString (itemname, valstr);
617 void SetConfigDir( const char *configDir )
619 strncpy(configdir, configDir, PATH_MAX);