Path: blob/master/libmupen64plus/mupen64plus-video-glide64/src/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#define M64P_PLUGIN_PROTOTYPES 139#include "m64p_types.h"40#include "m64p_plugin.h"41#include "m64p_config.h"42#include "m64p_vidext.h"43#include "Ini.h"44#include "Gfx1.3.h"45#include <limits.h>46#ifndef _WIN3247#include <unistd.h>48#include <string.h>49#include <dirent.h>50#include <stdlib.h>51#endif // _WIN325253#include <errno.h>54#ifndef _WIN3255#include <sys/resource.h>56#endif5758#ifdef _WIN3259#define PATH_MAX _MAX_PATH60#endif6162/* PATH_MAX only may be defined by limits.h */63#ifndef PATH_MAX64#define PATH_MAX 409665#endif6667FILE *ini;68int sectionstart;69int last_line; // last good line70int last_line_ret; // last line ended in return?71WORD cr = 0x0A0D;72static char configdir[PATH_MAX] = {0};7374BOOL INI_Open ()75{76// Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll77char path[PATH_MAX];78if(strlen(configdir) > 0)79{80strncpy(path, configdir, PATH_MAX);81// make sure there's a trailing '/'82//if(path[strlen(path)-1] != '/')83// strncat(path, "/", PATH_MAX - strlen(path));84}85else86{87#ifdef _WIN3288GetModuleFileName (hInstance, path, PATH_MAX);89#else // _WIN3290# ifdef __FreeBSD__91int n = readlink("/proc/curproc/files", path, PATH_MAX);92#else93int n = readlink("/proc/self/exe", path, PATH_MAX);94#endif95if (n == -1) strcpy(path, "./");96else97{98char path2[PATH_MAX];99int i;100101path[n] = '\0';102strcpy(path2, path);103for (i=strlen(path2)-1; i>0; i--)104{105if(path2[i] == '/') break;106}107if(i == 0) strcpy(path, "./");108else109{110DIR *dir;111struct dirent *entry;112int gooddir = 0;113114path2[i+1] = '\0';115dir = opendir(path2);116while((entry = readdir(dir)) != NULL)117{118if(!strcmp(entry->d_name, "plugins"))119gooddir = 1;120}121closedir(dir);122if(!gooddir) strcpy(path, "./");123}124}125126#endif // _WIN32127128// Find the previous backslash129int i;130for (i=strlen(path)-1; i>0; i--)131{132#ifdef _WIN32133if (path[i] == '\\')134#else // _WIN32135if (path[i] == '/')136#endif // _WIN32137break;138}139if (path == 0) return FALSE;140path[i+1] = 0;141142#ifndef _WIN32143strcat(path, "plugins/");144#endif // _WIN32145}146147//strncat (path, "Glide64.ini", PATH_MAX - strlen(path));148WriteLog(M64MSG_INFO, "opening %s\n", path);149// Open the file150ini = fopen (path, "rb");151if (ini == NULL)152{153WriteLog(M64MSG_ERROR, "Could not find Glide64.ini!");154return FALSE;155/*156ini = fopen (path, "w+b");157if (ini == NULL)158{159return FALSE;160}161*/162}163164sectionstart = 0;165last_line = 0;166last_line_ret = 1;167168return TRUE;169}170171void INI_Close ()172{173//if (ini)174// fclose(ini);175}176177void INI_InsertSpace(int space)178{179// Since there is no good way to normally insert to or delete from a certain location in180// a file, this function was added. It will insert (or delete) space bytes at the181// current location.182183// note: negative count means delete184char chunk[2048];185int len, file, start_pos, cur_pos;186187#ifdef _WIN32188file = _fileno(ini);189#else // _WIN32190file = fileno(ini);191#endif // _WIN32192193start_pos = ftell(ini);194fseek(ini,0,SEEK_END);195196// if adding, extend the file197if (space > 0)198#ifdef _WIN32199_chsize (file, _filelength(file)+space);200#else // _WIN32201{202int t1 = ftell(ini);203fseek(ini, 0L, SEEK_END);204int t2 = ftell(ini);205fseek(ini, t1, SEEK_SET);206ftruncate(file, t2+space);207}208#endif // _WIN32209210while (1) {211cur_pos = ftell(ini);212len = cur_pos - start_pos;213if (len == 0) break;214if (len > 2048) len = 2048;215216fseek (ini,-len,SEEK_CUR);217fread (chunk,1,len,ini);218fseek (ini,-len+space,SEEK_CUR);219fwrite (chunk,1,len,ini);220fseek (ini,-len-space,SEEK_CUR);221}222223// if deleted, make the file shorter224if (space < 0)225#ifdef _WIN32226_chsize (file, _filelength(file)+space);227#else // _WIN32228{229int t1 = ftell(ini);230fseek(ini, 0L, SEEK_END);231int t2 = ftell(ini);232fseek(ini, t1, SEEK_SET);233ftruncate(file, t2+space);234}235#endif // _WIN32236}237238BOOL INI_FindSection (const char *sectionname, BOOL create)239{240if (ini == NULL)241return FALSE;242243char line[256], section[64];244char *p;245int i, sectionfound, ret;246247rewind (ini);248249last_line = 0;250sectionfound = 0;251252while(!feof(ini)) {253ret = 0;254*line=0;255fgets(line,255,ini);256257// remove enter258i=strlen(line);259// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line260// with just EOL), it would write into line[-1]261if(i>=1 && line[i-1]==0xa) {262ret=1;263line[i-1]=0;264if (i>=2 && line[i-2]==0xd) line[i-2]=0;265}266267// remove comments268p=line;269while(*p)270{271if (p[0]=='/' && p[1]=='/')272{273p[0]=0;274break;275}276p++;277}278279// skip starting space280p=line;281while(*p<=' ' && *p) p++;282283// empty line284if(!*p) continue;285286last_line=ftell(ini); // where to add if not found287last_line_ret = ret;288289if(*p!='[') continue;290291p++;292for (i=0;i<63;i++)293{294if(*p==']' || !*p) break;295section[i]=*p++;296}297section[i]=0;298299#ifdef _WIN32300if(!stricmp(section,sectionname))301#else // _WIN32302if (!strcasecmp(section,sectionname))303#endif // _WIN32304{305sectionstart=ftell(ini);306sectionfound=1;307return TRUE;308}309}310311if (!sectionfound && create)312{313// create the section314fseek(ini,last_line,SEEK_SET);315INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));316if (!last_line_ret) fwrite (&cr, 1, 2, ini);317fwrite (&cr, 1, 2, ini);318sprintf (section, "[%s]", sectionname);319fwrite (section, 1, strlen(section), ini);320fwrite (&cr, 1, 2, ini);321sectionstart = ftell(ini);322last_line = sectionstart;323last_line_ret = 1;324return TRUE;325}326327return FALSE;328}329330// Reads the value of item 'itemname' as a string.331const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)332{333char line[256], name[64];334char *p, *n;335int ret, i;336*value = 0;337338fseek(ini,sectionstart,SEEK_SET);339340while(!feof(ini)) {341ret = 0;342*line=0;343fgets(line,255,ini);344345// remove enter346i=strlen(line);347// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line348// with just EOL), it would write into line[-1]349// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;350if(i>=1 && line[i-1]==0xa) {351ret=1;352line[i-1]=0;353if (i>=2 && line[i-2]==0xd) line[i-2]=0;354}355356// remove comments357p=line;358while(*p)359{360if (p[0]==';')361{362p[0]=0;363break;364}365p++;366}367368// skip starting space369p=line;370while(*p<=' ' && *p) p++;371372// empty line373if(!*p) continue;374375// new section376if(*p=='[') break;377378last_line=ftell(ini); // where to add if not found379last_line_ret = ret;380381// read name382n = name;383while(*p && *p!='=' && *p>' ') *n++ = *p++;384*n = 0;385386#ifdef _WIN32387if(!stricmp(name,itemname))388#else // _WIN32389if(!strcasecmp(name,itemname))390#endif // _WIN32391{392// skip spaces/equal sign393while(*p<=' ' || *p=='=') p++;394395// read value396n = value;397while(*p) *n++ = *p++;398399// remove trailing spaces400while (*(n-1) == ' ') n--;401402*n=0;403404return value;405}406}407408// uh-oh, not found. we need to create409if (create)410{411fseek(ini,last_line,SEEK_SET);412INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);413if (!last_line_ret) fwrite (&cr, 1, 2, ini);414sprintf (line, "%s = %s", itemname, def_value);415fwrite (line, 1, strlen(line), ini);416fwrite (&cr, 1, 2, ini);417last_line = ftell(ini);418last_line_ret = 1;419}420421strcpy (value, def_value);422return value;423}424425// Reads the value of item 'itemname' as a string.426void INI_WriteString (const char *itemname, const char *value)427{428char line[256], name[64];429char *p, *n;430int ret, i;431432fseek(ini,sectionstart,SEEK_SET);433434while(!feof(ini)) {435ret = 0;436*line=0;437fgets(line,255,ini);438439// remove enter440i=strlen(line);441// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line442// with just EOL), it would write into line[-1]443// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;444if(i>=1 && line[i-1]==0xa) {445ret=1;446line[i-1]=0;447if (i>=2 && line[i-2]==0xd) line[i-2]=0;448}449450// remove comments451p=line;452while(*p)453{454if (p[0]=='/' && p[1]=='/')455{456p[0]=0;457break;458}459p++;460}461462// skip starting space463p=line;464while(*p<=' ' && *p) p++;465466// empty line467if(!*p) continue;468469// new section470if(*p=='[') break;471472last_line=ftell(ini); // where to add if not found473last_line_ret = ret;474475// read name476n = name;477while(*p && *p!='=' && *p>' ') *n++ = *p++;478*n = 0;479480#ifdef _WIN32481if(!stricmp(name,itemname))482#else // _WIN32483if(!strcasecmp(name,itemname))484#endif // _WIN32485{486INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));487sprintf (line, "%s = %s", itemname, value);488fseek (ini, -i, SEEK_CUR);489fwrite (line, 1, strlen(line), ini);490fwrite (&cr, 1, 2, ini);491last_line = ftell(ini);492last_line_ret = 1;493return;494}495}496497// uh-oh, not found. we need to create498fseek(ini,last_line,SEEK_SET);499INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);500if (!last_line_ret) fwrite (&cr, 1, 2, ini);501sprintf (line, "%s = %s", itemname, value);502fwrite (line, 1, strlen(line), ini);503fwrite (&cr, 1, 2, ini);504last_line = ftell(ini);505last_line_ret = 1;506return;507}508509int INI_ReadInt (const char *itemname, int def_value, BOOL create)510{511if (ini == NULL)512return def_value;513514char value[64], def[64];515#ifdef _WIN32516_itoa (def_value, def, 10);517#else // _WIN32518sprintf(def, "%d", def_value);519#endif // _WIN32520INI_ReadString (itemname, value, def, create);521return atoi (value);522}523524void INI_WriteInt (const char *itemname, int value)525{526char valstr[64];527#ifdef _WIN32528_itoa (value, valstr, 10);529#else // _WIN32530sprintf(valstr, "%d", value);531#endif // _WIN32532INI_WriteString (itemname, valstr);533}534535void SetConfigDir( const char *configDir )536{537strncpy(configdir, configDir, PATH_MAX);538}539540541542