Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glide64 / Ini.cpp
diff --git a/source/gles2glide64/src/Glide64/Ini.cpp b/source/gles2glide64/src/Glide64/Ini.cpp
new file mode 100755 (executable)
index 0000000..b6ab0b0
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+*   Glide64 - Glide video plugin for Nintendo 64 emulators.
+*   Copyright (c) 2002  Dave2001
+*
+*   This program is free software; you can redistribute it and/or modify
+*   it under the terms of the GNU General Public License as published by
+*   the Free Software Foundation; either version 2 of the License, or
+*   any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU General Public License for more details.
+*
+*   You should have received a copy of the GNU General Public
+*   Licence along with this program; if not, write to the Free
+*   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+*   Boston, MA  02110-1301, USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
+// Project started on December 29th, 2001
+//
+// To modify Glide64:
+// * 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.
+// * 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.
+//
+// Official Glide64 development channel: #Glide64 on EFnet
+//
+// Original author: Dave2001 (Dave2999@hotmail.com)
+// Other authors: Gonetz, Gugaman
+//
+//****************************************************************
+
+// INI code v1.1
+
+#include "m64p.h"
+
+#include "Ini.h"
+#include "Gfx_1.3.h"
+#include <limits.h>
+#ifndef _WIN32
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+#else
+#include <io.h>
+#endif // _WIN32
+
+#include <errno.h>
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+
+#ifdef _WIN32
+  #define PATH_MAX _MAX_PATH
+  #define stricmp _stricmp
+#endif
+
+FILE *ini;
+int sectionstart;
+int last_line;      // last good line
+int last_line_ret;  // last line ended in return?
+wxUint16 cr = 0x0A0D;
+static char configdir[PATH_MAX] = {0};
+
+
+//TODO: move INI_xxxx() function code into class and clean up
+Ini *Ini::singleton = 0;
+
+Ini::Ini()
+{
+       if (!INI_Open())
+       {
+               printf("Could not find INI file!");
+               exit(1);
+       }
+}
+
+Ini *Ini::OpenIni()
+{
+       if (!singleton)
+               singleton = new Ini();
+       return singleton;
+}
+
+void Ini::SetPath(const char *path)
+{
+       if (!INI_FindSection(path, false))
+       {
+               printf("Could not find [%s] section in INI file!", path);
+       }
+}
+
+
+bool Ini::Read(const char *key, int *l)
+{
+       int undef = 0xDEADBEEF;
+       int tmpVal = INI_ReadInt(key, undef, false);
+       if (tmpVal == undef)
+       {
+               return false;
+       }
+       else
+       {
+               *l = tmpVal;
+               return true;
+       }
+}
+
+bool Ini::Read(const char *key, int *l, int defaultVal)
+{
+       *l = INI_ReadInt(key, defaultVal, false);
+       return true;
+}
+
+int Ini::Read(const char *key, int defaultVal)
+{
+       return INI_ReadInt(key, defaultVal, false);
+}
+
+
+BOOL INI_Open ()
+{
+       //TODO: use ConfigGetSharedDataFilepath
+       
+    // Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll
+    char path[PATH_MAX];
+    if(strlen(configdir) > 0)
+    {
+        strncpy(path, configdir, PATH_MAX);
+        // make sure there's a trailing '/'
+        //if(path[strlen(path)-1] != '/')
+        //    strncat(path, "/", PATH_MAX - strlen(path));
+    }
+    else
+    {
+#ifdef _WIN32
+    GetModuleFileName (NULL, path, PATH_MAX);
+#else // _WIN32
+# ifdef __FreeBSD__
+   int n = readlink("/proc/curproc/files", path, PATH_MAX);
+#else
+   int n = readlink("/proc/self/exe", path, PATH_MAX);
+#endif
+   if (n == -1) strcpy(path, "./");
+   else
+     {
+    char path2[PATH_MAX];
+    int i;
+    
+    path[n] = '\0';
+    strcpy(path2, path);
+    for (i=strlen(path2)-1; i>0; i--)
+      {
+         if(path2[i] == '/') break;
+      }
+    if(i == 0) strcpy(path, "./");
+    else
+      {
+         DIR *dir;
+         struct dirent *entry;
+         int gooddir = 0;
+         
+         path2[i+1] = '\0';
+         dir = opendir(path2);
+         while((entry = readdir(dir)) != NULL)
+           {
+          if(!strcmp(entry->d_name, "plugins"))
+            gooddir = 1;
+           }
+         closedir(dir);
+         if(!gooddir) strcpy(path, "./");
+      }
+     }
+
+#endif // _WIN32
+
+    // Find the previous backslash
+    int i;
+    for (i=strlen(path)-1; i>0; i--)
+    {
+#ifdef _WIN32
+        if (path[i] == '\\')
+#else // _WIN32
+            if (path[i] == '/')
+#endif // _WIN32
+            break;
+    }
+    if (path == 0) return FALSE;
+    path[i+1] = 0;
+
+#ifndef _WIN32
+   strcat(path, "plugins/");
+#endif // _WIN32
+    }
+   
+    //strncat (path, "Glide64mk2.ini", PATH_MAX - strlen(path));
+    LOG("opening %s\n", path);
+    // Open the file
+    ini = fopen (path, "rb");
+    if (ini == NULL)
+    {
+        ERRLOG("Could not find Glide64mk2.ini!");
+        return FALSE;
+        /*
+        ini = fopen (path, "w+b");
+        if (ini == NULL)
+        {
+            return FALSE;
+        }
+        */
+    }
+
+    sectionstart = 0;
+    last_line = 0;
+    last_line_ret = 1;
+
+    return TRUE;
+}
+
+void INI_Close ()
+{
+    //if (ini)
+      //  fclose(ini);
+}
+
+void INI_InsertSpace(int space)
+{
+  printf("Inserting space, space to insert is %d\n", space);
+    // Since there is no good way to normally insert to or delete from a certain location in
+    //  a file, this function was added.  It will insert (or delete) space bytes at the
+    //  current location.
+
+    // note: negative count means delete
+    char chunk[2048];
+    int len, file, start_pos, cur_pos;
+
+#ifdef _WIN32
+    file = _fileno(ini);
+#else // _WIN32
+   file = fileno(ini);
+#endif // _WIN32
+
+    start_pos = ftell(ini);
+    fseek(ini,0,SEEK_END);
+
+    // if adding, extend the file
+    if (space > 0)
+#ifdef _WIN32
+        _chsize (file, _filelength(file)+space);
+#else // _WIN32
+     {
+    int t1 = ftell(ini);
+    fseek(ini, 0L, SEEK_END);
+    int t2 = ftell(ini);
+    fseek(ini, t1, SEEK_SET);
+    if (ftruncate(file, t2+space) != 0)
+        ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
+    }
+#endif // _WIN32
+
+    while (1) {
+        cur_pos = ftell(ini);
+        len = cur_pos - start_pos;
+        if (len == 0) break;
+        if (len > 2048) len = 2048;
+
+        fseek (ini,-len,SEEK_CUR);
+        if (fread(chunk,1,len,ini) != (size_t) len)
+            ERRLOG("Failed to read %i bytes from .ini file", len);
+        fseek (ini,-len+space,SEEK_CUR);
+        if (fwrite(chunk,1,len,ini) != (size_t) len)
+            ERRLOG("Failed to write %i bytes to .ini file", len);
+        fseek (ini,-len-space,SEEK_CUR);
+    }
+
+    // if deleted, make the file shorter
+    if (space < 0)
+#ifdef _WIN32
+        _chsize (file, _filelength(file)+space);
+#else // _WIN32
+     {
+    int t1 = ftell(ini);
+    fseek(ini, 0L, SEEK_END);
+    int t2 = ftell(ini);
+    fseek(ini, t1, SEEK_SET);
+    if (ftruncate(file, t2+space) != 0)
+        ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
+     }
+#endif // _WIN32
+}
+
+BOOL INI_FindSection (const char *sectionname, BOOL create)
+{
+    if (ini == NULL)
+        return FALSE;
+/*    static char cached_secion[200]="\0";
+    static BOOL cached_result;
+    if (!strcasecmp(section,sectionname))
+       return cached_result;*/
+
+
+//    printf("INI_FindSection trying to find name for %s\n", sectionname);
+
+    char line[256], section[64];
+    char *p;
+    int  i, sectionfound, ret;
+
+    rewind (ini);
+
+    last_line = 0;
+    sectionfound = 0;
+
+    while(!feof(ini)) {
+        ret = 0;
+        *line=0;
+        if (fgets(line,255,ini) == NULL)
+            break;
+
+        // remove enter
+        i=strlen(line);
+    // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
+    // with just EOL), it would write into line[-1]
+        if(i>=1 && line[i-1]==0xa) {
+      ret=1;
+      line[i-1]=0;
+      if (i>=2 && line[i-2]==0xd) line[i-2]=0;
+    }
+
+        // remove comments
+        p=line;
+        while(*p)
+        {
+            if (p[0]=='/' && p[1]=='/')
+            {
+                p[0]=0;
+                break;
+            }
+            p++;
+        }
+
+        // skip starting space
+        p=line;
+        while(*p<=' ' && *p) p++;
+
+        // empty line
+        if(!*p) continue;
+
+        last_line=ftell(ini);   // where to add if not found
+        last_line_ret = ret;
+
+        if(*p!='[') continue;
+
+        p++;
+        for (i=0;i<63;i++)
+        {
+            if(*p==']' || !*p) break;
+            section[i]=*p++;
+        }
+        section[i]=0;
+
+#ifdef _WIN32
+        if(!stricmp(section,sectionname))
+#else // _WIN32
+         if (!strcasecmp(section,sectionname))
+#endif // _WIN32
+        {
+            sectionstart=ftell(ini);
+            sectionfound=1;
+            return TRUE;
+        }
+    }
+
+    if (!sectionfound && create)
+    {
+        // create the section
+        fseek(ini,last_line,SEEK_SET);
+        INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));
+        if (!last_line_ret)
+            if (fwrite(&cr, 1, 2, ini) != 2)
+                ERRLOG("Failed to write <CR><LF> to .ini file");
+        sprintf (section, "[%s]", sectionname);
+        if (fwrite(&cr, 1, 2, ini) != 2 ||
+            fwrite(section, 1, strlen(section), ini) != strlen(section) ||
+            fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write Section line to .ini file");
+        sectionstart = ftell(ini);
+        last_line = sectionstart;
+        last_line_ret = 1;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+// Reads the value of item 'itemname' as a string.
+const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)
+{
+    char line[256], name[64];
+    char *p, *n;
+    int ret, i;
+    *value = 0;
+
+    fseek(ini,sectionstart,SEEK_SET);
+
+    while(!feof(ini)) {
+        ret = 0;
+        *line=0;
+        if (fgets(line,255,ini) == NULL)
+            break;
+
+        // remove enter
+        i=strlen(line);
+    // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
+    // with just EOL), it would write into line[-1]
+        // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
+        if(i>=1 && line[i-1]==0xa) {
+      ret=1;
+      line[i-1]=0;
+      if (i>=2 && line[i-2]==0xd) line[i-2]=0;
+    }
+
+        // remove comments
+        p=line;
+        while(*p)
+        {
+            if (p[0]==';')
+            {
+                p[0]=0;
+                break;
+            }
+            p++;
+        }
+
+        // skip starting space
+        p=line;
+        while(*p<=' ' && *p) p++;
+
+        // empty line
+        if(!*p) continue;
+
+        // new section
+        if(*p=='[') break;
+
+        last_line=ftell(ini);   // where to add if not found
+        last_line_ret = ret;
+
+        // read name
+        n = name;
+        while(*p && *p!='=' && *p>' ') *n++ = *p++;
+        *n = 0;
+
+#ifdef _WIN32
+        if(!stricmp(name,itemname))
+#else // _WIN32
+         if(!strcasecmp(name,itemname))
+#endif // _WIN32
+        {
+            // skip spaces/equal sign
+            while(*p<=' ' || *p=='=') p++;
+
+            // read value
+            n = value;
+            while(*p) *n++ = *p++;
+
+            // remove trailing spaces
+            while (*(n-1) == ' ') n--;
+
+            *n=0;
+
+            return value;
+        }
+    }
+
+    // uh-oh, not found.  we need to create
+    if (create)
+    {
+        fseek(ini,last_line,SEEK_SET);
+        INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);
+        if (!last_line_ret)
+            if (fwrite(&cr, 1, 2, ini) != 2)
+                ERRLOG("Failed to write <CR><LF> to .ini file");
+        sprintf (line, "%s = %s", itemname, def_value);
+        if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+            fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write key,value line to .ini file");
+        last_line = ftell(ini);
+        last_line_ret = 1;
+    }
+
+    strcpy (value, def_value);
+    return value;
+}
+
+// Reads the value of item 'itemname' as a string.
+void INI_WriteString (const char *itemname, const char *value)
+{
+    char line[256], name[64];
+    char *p, *n;
+    int ret, i;
+
+    fseek(ini,sectionstart,SEEK_SET);
+
+    while(!feof(ini)) {
+        ret = 0;
+        *line=0;
+        if (fgets(line,255,ini) == NULL) break;
+
+        // remove enter
+        i=strlen(line);
+    // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
+    // with just EOL), it would write into line[-1]
+        // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
+        if(i>=1 && line[i-1]==0xa) {
+      ret=1;
+      line[i-1]=0;
+      if (i>=2 && line[i-2]==0xd) line[i-2]=0;
+    }
+
+        // remove comments
+        p=line;
+        while(*p)
+        {
+            if (p[0]=='/' && p[1]=='/')
+            {
+                p[0]=0;
+                break;
+            }
+            p++;
+        }
+
+        // skip starting space
+        p=line;
+        while(*p<=' ' && *p) p++;
+
+        // empty line
+        if(!*p) continue;
+
+        // new section
+        if(*p=='[') break;
+
+        last_line=ftell(ini);   // where to add if not found
+        last_line_ret = ret;
+
+        // read name
+        n = name;
+        while(*p && *p!='=' && *p>' ') *n++ = *p++;
+        *n = 0;
+
+#ifdef _WIN32
+        if(!stricmp(name,itemname))
+#else // _WIN32
+         if(!strcasecmp(name,itemname))
+#endif // _WIN32
+        {
+            INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));
+            sprintf (line, "%s = %s", itemname, value);
+            fseek (ini, -i, SEEK_CUR);
+            if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+                fwrite(&cr, 1, 2, ini) != 2)
+            {
+                ERRLOG("Failed to write line '%s' to .ini file", line);
+            }
+            last_line = ftell(ini);
+            last_line_ret = 1;
+            return;
+        }
+    }
+
+    // uh-oh, not found.  we need to create
+    fseek(ini,last_line,SEEK_SET);
+    INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);
+    sprintf (line, "%s = %s", itemname, value);
+    if (!last_line_ret)
+        if (fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write <CR> to .ini file");
+    if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+        fwrite(&cr, 1, 2, ini) != 2)
+    {
+        ERRLOG("Failed to write line '%s' to .ini file", line);
+    }
+    last_line = ftell(ini);
+    last_line_ret = 1;
+    return;
+}
+
+int INI_ReadInt (const char *itemname, int def_value, BOOL create)
+{
+    if (ini == NULL)
+        return def_value;
+
+    char value[64], def[64];
+#ifdef _WIN32
+    _itoa (def_value, def, 10);
+#else // _WIN32
+   sprintf(def, "%d", def_value);
+#endif // _WIN32
+    INI_ReadString (itemname, value, def, create);
+    return atoi (value);
+}
+
+void INI_WriteInt (const char *itemname, int value)
+{
+    char valstr[64];
+#ifdef _WIN32
+    _itoa (value, valstr, 10);
+#else // _WIN32
+   sprintf(valstr, "%d", value);
+#endif // _WIN32
+    INI_WriteString (itemname, valstr);
+}
+
+void SetConfigDir( const char *configDir )
+{
+    strncpy(configdir, configDir, PATH_MAX);
+}
+