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
68 int last_line; // last good line
69 int last_line_ret; // last line ended in return?
71 static char configdir[PATH_MAX] = {0};
74 //TODO: move INI_xxxx() function code into class and clean up
75 Ini *Ini::singleton = 0;
81 printf("Could not find INI file!");
89 singleton = new Ini();
93 void Ini::SetPath(const char *path)
95 if (!INI_FindSection(path, false))
97 printf("Could not find [%s] section in INI file!", path);
102 bool Ini::Read(const char *key, int *l)
104 int undef = 0xDEADBEEF;
105 int tmpVal = INI_ReadInt(key, undef, false);
117 bool Ini::Read(const char *key, int *l, int defaultVal)
119 *l = INI_ReadInt(key, defaultVal, false);
123 int Ini::Read(const char *key, int defaultVal)
125 return INI_ReadInt(key, defaultVal, false);
131 //TODO: use ConfigGetSharedDataFilepath
133 // Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll
135 if(strlen(configdir) > 0)
137 strncpy(path, configdir, PATH_MAX);
138 // make sure there's a trailing '/'
139 //if(path[strlen(path)-1] != '/')
140 // strncat(path, "/", PATH_MAX - strlen(path));
145 GetModuleFileName (NULL, path, PATH_MAX);
148 int n = readlink("/proc/curproc/files", path, PATH_MAX);
150 int n = readlink("/proc/self/exe", path, PATH_MAX);
152 if (n == -1) strcpy(path, "./");
155 char path2[PATH_MAX];
160 for (i=strlen(path2)-1; i>0; i--)
162 if(path2[i] == '/') break;
164 if(i == 0) strcpy(path, "./");
168 struct dirent *entry;
172 dir = opendir(path2);
173 while((entry = readdir(dir)) != NULL)
175 if(!strcmp(entry->d_name, "plugins"))
179 if(!gooddir) strcpy(path, "./");
185 // Find the previous backslash
187 for (i=strlen(path)-1; i>0; i--)
196 if (path == 0) return FALSE;
200 strcat(path, "plugins/");
204 //strncat (path, "Glide64mk2.ini", PATH_MAX - strlen(path));
205 LOG("opening %s\n", path);
207 ini = fopen (path, "rb");
210 ERRLOG("Could not find Glide64mk2.ini!");
213 ini = fopen (path, "w+b");
234 void INI_InsertSpace(int space)
236 printf("Inserting space, space to insert is %d\n", space);
237 // Since there is no good way to normally insert to or delete from a certain location in
238 // a file, this function was added. It will insert (or delete) space bytes at the
241 // note: negative count means delete
243 int len, file, start_pos, cur_pos;
251 start_pos = ftell(ini);
252 fseek(ini,0,SEEK_END);
254 // if adding, extend the file
257 _chsize (file, _filelength(file)+space);
261 fseek(ini, 0L, SEEK_END);
263 fseek(ini, t1, SEEK_SET);
264 if (ftruncate(file, t2+space) != 0)
265 ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
270 cur_pos = ftell(ini);
271 len = cur_pos - start_pos;
273 if (len > 2048) len = 2048;
275 fseek (ini,-len,SEEK_CUR);
276 if (fread(chunk,1,len,ini) != (size_t) len)
277 ERRLOG("Failed to read %i bytes from .ini file", len);
278 fseek (ini,-len+space,SEEK_CUR);
279 if (fwrite(chunk,1,len,ini) != (size_t) len)
280 ERRLOG("Failed to write %i bytes to .ini file", len);
281 fseek (ini,-len-space,SEEK_CUR);
284 // if deleted, make the file shorter
287 _chsize (file, _filelength(file)+space);
291 fseek(ini, 0L, SEEK_END);
293 fseek(ini, t1, SEEK_SET);
294 if (ftruncate(file, t2+space) != 0)
295 ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
300 BOOL INI_FindSection (const char *sectionname, BOOL create)
304 /* static char cached_secion[200]="\0";
305 static BOOL cached_result;
306 if (!strcasecmp(section,sectionname))
307 return cached_result;*/
310 // printf("INI_FindSection trying to find name for %s\n", sectionname);
312 char line[256], section[64];
314 int i, sectionfound, ret;
324 if (fgets(line,255,ini) == NULL)
329 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
330 // with just EOL), it would write into line[-1]
331 if(i>=1 && line[i-1]==0xa) {
334 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
341 if (p[0]=='/' && p[1]=='/')
349 // skip starting space
351 while(*p<=' ' && *p) p++;
356 last_line=ftell(ini); // where to add if not found
359 if(*p!='[') continue;
364 if(*p==']' || !*p) break;
370 if(!stricmp(section,sectionname))
372 if (!strcasecmp(section,sectionname))
375 sectionstart=ftell(ini);
381 if (!sectionfound && create)
383 // create the section
384 fseek(ini,last_line,SEEK_SET);
385 INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));
387 if (fwrite(&cr, 1, 2, ini) != 2)
388 ERRLOG("Failed to write <CR><LF> to .ini file");
389 sprintf (section, "[%s]", sectionname);
390 if (fwrite(&cr, 1, 2, ini) != 2 ||
391 fwrite(section, 1, strlen(section), ini) != strlen(section) ||
392 fwrite(&cr, 1, 2, ini) != 2)
393 ERRLOG("Failed to write Section line to .ini file");
394 sectionstart = ftell(ini);
395 last_line = sectionstart;
403 // Reads the value of item 'itemname' as a string.
404 const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)
406 char line[256], name[64];
411 fseek(ini,sectionstart,SEEK_SET);
416 if (fgets(line,255,ini) == NULL)
421 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
422 // with just EOL), it would write into line[-1]
423 // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
424 if(i>=1 && line[i-1]==0xa) {
427 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
442 // skip starting space
444 while(*p<=' ' && *p) p++;
452 last_line=ftell(ini); // where to add if not found
457 while(*p && *p!='=' && *p>' ') *n++ = *p++;
461 if(!stricmp(name,itemname))
463 if(!strcasecmp(name,itemname))
466 // skip spaces/equal sign
467 while(*p<=' ' || *p=='=') p++;
471 while(*p) *n++ = *p++;
473 // remove trailing spaces
474 while (*(n-1) == ' ') n--;
482 // uh-oh, not found. we need to create
485 fseek(ini,last_line,SEEK_SET);
486 INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);
488 if (fwrite(&cr, 1, 2, ini) != 2)
489 ERRLOG("Failed to write <CR><LF> to .ini file");
490 sprintf (line, "%s = %s", itemname, def_value);
491 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
492 fwrite(&cr, 1, 2, ini) != 2)
493 ERRLOG("Failed to write key,value line to .ini file");
494 last_line = ftell(ini);
498 strcpy (value, def_value);
502 // Reads the value of item 'itemname' as a string.
503 void INI_WriteString (const char *itemname, const char *value)
505 char line[256], name[64];
509 fseek(ini,sectionstart,SEEK_SET);
514 if (fgets(line,255,ini) == NULL) break;
518 // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
519 // with just EOL), it would write into line[-1]
520 // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
521 if(i>=1 && line[i-1]==0xa) {
524 if (i>=2 && line[i-2]==0xd) line[i-2]=0;
531 if (p[0]=='/' && p[1]=='/')
539 // skip starting space
541 while(*p<=' ' && *p) p++;
549 last_line=ftell(ini); // where to add if not found
554 while(*p && *p!='=' && *p>' ') *n++ = *p++;
558 if(!stricmp(name,itemname))
560 if(!strcasecmp(name,itemname))
563 INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));
564 sprintf (line, "%s = %s", itemname, value);
565 fseek (ini, -i, SEEK_CUR);
566 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
567 fwrite(&cr, 1, 2, ini) != 2)
569 ERRLOG("Failed to write line '%s' to .ini file", line);
571 last_line = ftell(ini);
577 // uh-oh, not found. we need to create
578 fseek(ini,last_line,SEEK_SET);
579 INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);
580 sprintf (line, "%s = %s", itemname, value);
582 if (fwrite(&cr, 1, 2, ini) != 2)
583 ERRLOG("Failed to write <CR> to .ini file");
584 if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
585 fwrite(&cr, 1, 2, ini) != 2)
587 ERRLOG("Failed to write line '%s' to .ini file", line);
589 last_line = ftell(ini);
594 int INI_ReadInt (const char *itemname, int def_value, BOOL create)
599 char value[64], def[64];
601 _itoa (def_value, def, 10);
603 sprintf(def, "%d", def_value);
605 INI_ReadString (itemname, value, def, create);
609 void INI_WriteInt (const char *itemname, int value)
613 _itoa (value, valstr, 10);
615 sprintf(valstr, "%d", value);
617 INI_WriteString (itemname, valstr);
620 void SetConfigDir( const char *configDir )
622 strncpy(configdir, configDir, PATH_MAX);