Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Ini.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation; either version 2 of the License, or7* any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*14* You should have received a copy of the GNU General Public15* Licence along with this program; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,17* Boston, MA 02110-1301, USA18*/1920//****************************************************************21//22// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)23// Project started on December 29th, 200124//25// To modify Glide64:26// * 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.27// * 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.28//29// Official Glide64 development channel: #Glide64 on EFnet30//31// Original author: Dave2001 ([email protected])32// Other authors: Gonetz, Gugaman33//34//****************************************************************3536// INI code v1.13738#include "m64p.h"3940#include "Ini.h"41#include "Gfx_1.3.h"42#include <limits.h>43#ifndef _WIN3244#include <unistd.h>45#include <string.h>46#include <dirent.h>47#include <stdlib.h>48#else49#include <io.h>50#endif // _WIN325152#include <errno.h>53#ifndef _WIN3254#include <sys/resource.h>55#endif5657#ifdef _WIN3258#define PATH_MAX _MAX_PATH59#define stricmp _stricmp60#endif6162FILE *ini;63int sectionstart;64int last_line; // last good line65int last_line_ret; // last line ended in return?66wxUint16 cr = 0x0A0D;67static char configdir[PATH_MAX] = {0};686970//TODO: move INI_xxxx() function code into class and clean up71Ini *Ini::singleton = 0;7273Ini::Ini()74{75if (!INI_Open())76{77printf("Could not find INI file!");78exit(1);79}80}8182Ini *Ini::OpenIni()83{84if (!singleton)85singleton = new Ini();86return singleton;87}8889void Ini::SetPath(const char *path)90{91if (!INI_FindSection(path, false))92{93printf("Could not find [%s] section in INI file!", path);94}95}969798bool Ini::Read(const char *key, int *l)99{100int undef = 0xDEADBEEF;101int tmpVal = INI_ReadInt(key, undef, false);102if (tmpVal == undef)103{104return false;105}106else107{108*l = tmpVal;109return true;110}111}112113bool Ini::Read(const char *key, int *l, int defaultVal)114{115*l = INI_ReadInt(key, defaultVal, false);116return true;117}118119int Ini::Read(const char *key, int defaultVal)120{121return INI_ReadInt(key, defaultVal, false);122}123124125BOOL INI_Open ()126{127//TODO: use ConfigGetSharedDataFilepath128129// Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll130char path[PATH_MAX];131if(strlen(configdir) > 0)132{133strncpy(path, configdir, PATH_MAX);134// make sure there's a trailing '/'135//if(path[strlen(path)-1] != '/')136// strncat(path, "/", PATH_MAX - strlen(path));137}138else139{140#ifdef _WIN32141GetModuleFileName (NULL, path, PATH_MAX);142#else // _WIN32143# ifdef __FreeBSD__144int n = readlink("/proc/curproc/files", path, PATH_MAX);145#else146int n = readlink("/proc/self/exe", path, PATH_MAX);147#endif148if (n == -1) strcpy(path, "./");149else150{151char path2[PATH_MAX];152int i;153154path[n] = '\0';155strcpy(path2, path);156for (i=strlen(path2)-1; i>0; i--)157{158if(path2[i] == '/') break;159}160if(i == 0) strcpy(path, "./");161else162{163DIR *dir;164struct dirent *entry;165int gooddir = 0;166167path2[i+1] = '\0';168dir = opendir(path2);169while((entry = readdir(dir)) != NULL)170{171if(!strcmp(entry->d_name, "plugins"))172gooddir = 1;173}174closedir(dir);175if(!gooddir) strcpy(path, "./");176}177}178179#endif // _WIN32180181// Find the previous backslash182int i;183for (i=strlen(path)-1; i>0; i--)184{185#ifdef _WIN32186if (path[i] == '\\')187#else // _WIN32188if (path[i] == '/')189#endif // _WIN32190break;191}192if (path == 0) return FALSE;193path[i+1] = 0;194195#ifndef _WIN32196strcat(path, "plugins/");197#endif // _WIN32198}199200//strncat (path, "Glide64mk2.ini", PATH_MAX - strlen(path));201LOG("opening %s\n", path);202// Open the file203ini = fopen (path, "rb");204if (ini == NULL)205{206ERRLOG("Could not find Glide64mk2.ini!");207return FALSE;208/*209ini = fopen (path, "w+b");210if (ini == NULL)211{212return FALSE;213}214*/215}216217sectionstart = 0;218last_line = 0;219last_line_ret = 1;220221return TRUE;222}223224void INI_Close ()225{226//if (ini)227// fclose(ini);228}229230void INI_InsertSpace(int space)231{232printf("Inserting space, space to insert is %d\n", space);233// Since there is no good way to normally insert to or delete from a certain location in234// a file, this function was added. It will insert (or delete) space bytes at the235// current location.236237// note: negative count means delete238char chunk[2048];239int len, file, start_pos, cur_pos;240241#ifdef _WIN32242file = _fileno(ini);243#else // _WIN32244file = fileno(ini);245#endif // _WIN32246247start_pos = ftell(ini);248fseek(ini,0,SEEK_END);249250// if adding, extend the file251if (space > 0)252#ifdef _WIN32253_chsize (file, _filelength(file)+space);254#else // _WIN32255{256int t1 = ftell(ini);257fseek(ini, 0L, SEEK_END);258int t2 = ftell(ini);259fseek(ini, t1, SEEK_SET);260if (ftruncate(file, t2+space) != 0)261ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);262}263#endif // _WIN32264265while (1) {266cur_pos = ftell(ini);267len = cur_pos - start_pos;268if (len == 0) break;269if (len > 2048) len = 2048;270271fseek (ini,-len,SEEK_CUR);272if (fread(chunk,1,len,ini) != (size_t) len)273ERRLOG("Failed to read %i bytes from .ini file", len);274fseek (ini,-len+space,SEEK_CUR);275if (fwrite(chunk,1,len,ini) != (size_t) len)276ERRLOG("Failed to write %i bytes to .ini file", len);277fseek (ini,-len-space,SEEK_CUR);278}279280// if deleted, make the file shorter281if (space < 0)282#ifdef _WIN32283_chsize (file, _filelength(file)+space);284#else // _WIN32285{286int t1 = ftell(ini);287fseek(ini, 0L, SEEK_END);288int t2 = ftell(ini);289fseek(ini, t1, SEEK_SET);290if (ftruncate(file, t2+space) != 0)291ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);292}293#endif // _WIN32294}295296BOOL INI_FindSection (const char *sectionname, BOOL create)297{298if (ini == NULL)299return FALSE;300printf("INI_FindSection trying to find name for %s\n", sectionname);301302char line[256], section[64];303char *p;304int i, sectionfound, ret;305306rewind (ini);307308last_line = 0;309sectionfound = 0;310311while(!feof(ini)) {312ret = 0;313*line=0;314if (fgets(line,255,ini) == NULL)315break;316317// remove enter318i=strlen(line);319// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line320// with just EOL), it would write into line[-1]321if(i>=1 && line[i-1]==0xa) {322ret=1;323line[i-1]=0;324if (i>=2 && line[i-2]==0xd) line[i-2]=0;325}326327// remove comments328p=line;329while(*p)330{331if (p[0]=='/' && p[1]=='/')332{333p[0]=0;334break;335}336p++;337}338339// skip starting space340p=line;341while(*p<=' ' && *p) p++;342343// empty line344if(!*p) continue;345346last_line=ftell(ini); // where to add if not found347last_line_ret = ret;348349if(*p!='[') continue;350351p++;352for (i=0;i<63;i++)353{354if(*p==']' || !*p) break;355section[i]=*p++;356}357section[i]=0;358359#ifdef _WIN32360if(!stricmp(section,sectionname))361#else // _WIN32362if (!strcasecmp(section,sectionname))363#endif // _WIN32364{365sectionstart=ftell(ini);366sectionfound=1;367return TRUE;368}369}370371if (!sectionfound && create)372{373// create the section374fseek(ini,last_line,SEEK_SET);375INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));376if (!last_line_ret)377if (fwrite(&cr, 1, 2, ini) != 2)378ERRLOG("Failed to write <CR><LF> to .ini file");379sprintf (section, "[%s]", sectionname);380if (fwrite(&cr, 1, 2, ini) != 2 ||381fwrite(section, 1, strlen(section), ini) != strlen(section) ||382fwrite(&cr, 1, 2, ini) != 2)383ERRLOG("Failed to write Section line to .ini file");384sectionstart = ftell(ini);385last_line = sectionstart;386last_line_ret = 1;387return TRUE;388}389390return FALSE;391}392393// Reads the value of item 'itemname' as a string.394const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)395{396char line[256], name[64];397char *p, *n;398int ret, i;399*value = 0;400401fseek(ini,sectionstart,SEEK_SET);402403while(!feof(ini)) {404ret = 0;405*line=0;406if (fgets(line,255,ini) == NULL)407break;408409// remove enter410i=strlen(line);411// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line412// with just EOL), it would write into line[-1]413// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;414if(i>=1 && line[i-1]==0xa) {415ret=1;416line[i-1]=0;417if (i>=2 && line[i-2]==0xd) line[i-2]=0;418}419420// remove comments421p=line;422while(*p)423{424if (p[0]==';')425{426p[0]=0;427break;428}429p++;430}431432// skip starting space433p=line;434while(*p<=' ' && *p) p++;435436// empty line437if(!*p) continue;438439// new section440if(*p=='[') break;441442last_line=ftell(ini); // where to add if not found443last_line_ret = ret;444445// read name446n = name;447while(*p && *p!='=' && *p>' ') *n++ = *p++;448*n = 0;449450#ifdef _WIN32451if(!stricmp(name,itemname))452#else // _WIN32453if(!strcasecmp(name,itemname))454#endif // _WIN32455{456// skip spaces/equal sign457while(*p<=' ' || *p=='=') p++;458459// read value460n = value;461while(*p) *n++ = *p++;462463// remove trailing spaces464while (*(n-1) == ' ') n--;465466*n=0;467468return value;469}470}471472// uh-oh, not found. we need to create473if (create)474{475fseek(ini,last_line,SEEK_SET);476INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);477if (!last_line_ret)478if (fwrite(&cr, 1, 2, ini) != 2)479ERRLOG("Failed to write <CR><LF> to .ini file");480sprintf (line, "%s = %s", itemname, def_value);481if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||482fwrite(&cr, 1, 2, ini) != 2)483ERRLOG("Failed to write key,value line to .ini file");484last_line = ftell(ini);485last_line_ret = 1;486}487488strcpy (value, def_value);489return value;490}491492// Reads the value of item 'itemname' as a string.493void INI_WriteString (const char *itemname, const char *value)494{495char line[256], name[64];496char *p, *n;497int ret, i;498499fseek(ini,sectionstart,SEEK_SET);500501while(!feof(ini)) {502ret = 0;503*line=0;504if (fgets(line,255,ini) == NULL) break;505506// remove enter507i=strlen(line);508// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line509// with just EOL), it would write into line[-1]510// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;511if(i>=1 && line[i-1]==0xa) {512ret=1;513line[i-1]=0;514if (i>=2 && line[i-2]==0xd) line[i-2]=0;515}516517// remove comments518p=line;519while(*p)520{521if (p[0]=='/' && p[1]=='/')522{523p[0]=0;524break;525}526p++;527}528529// skip starting space530p=line;531while(*p<=' ' && *p) p++;532533// empty line534if(!*p) continue;535536// new section537if(*p=='[') break;538539last_line=ftell(ini); // where to add if not found540last_line_ret = ret;541542// read name543n = name;544while(*p && *p!='=' && *p>' ') *n++ = *p++;545*n = 0;546547#ifdef _WIN32548if(!stricmp(name,itemname))549#else // _WIN32550if(!strcasecmp(name,itemname))551#endif // _WIN32552{553INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));554sprintf (line, "%s = %s", itemname, value);555fseek (ini, -i, SEEK_CUR);556if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||557fwrite(&cr, 1, 2, ini) != 2)558{559ERRLOG("Failed to write line '%s' to .ini file", line);560}561last_line = ftell(ini);562last_line_ret = 1;563return;564}565}566567// uh-oh, not found. we need to create568fseek(ini,last_line,SEEK_SET);569INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);570sprintf (line, "%s = %s", itemname, value);571if (!last_line_ret)572if (fwrite(&cr, 1, 2, ini) != 2)573ERRLOG("Failed to write <CR> to .ini file");574if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||575fwrite(&cr, 1, 2, ini) != 2)576{577ERRLOG("Failed to write line '%s' to .ini file", line);578}579last_line = ftell(ini);580last_line_ret = 1;581return;582}583584int INI_ReadInt (const char *itemname, int def_value, BOOL create)585{586if (ini == NULL)587return def_value;588589char value[64], def[64];590#ifdef _WIN32591_itoa (def_value, def, 10);592#else // _WIN32593sprintf(def, "%d", def_value);594#endif // _WIN32595INI_ReadString (itemname, value, def, create);596return atoi (value);597}598599void INI_WriteInt (const char *itemname, int value)600{601char valstr[64];602#ifdef _WIN32603_itoa (value, valstr, 10);604#else // _WIN32605sprintf(valstr, "%d", value);606#endif // _WIN32607INI_WriteString (itemname, valstr);608}609610void SetConfigDir( const char *configDir )611{612strncpy(configdir, configDir, PATH_MAX);613}614615616617