Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glide64/Ini.cpp
2 views
1
/*
2
* Glide64 - Glide video plugin for Nintendo 64 emulators.
3
* Copyright (c) 2002 Dave2001
4
*
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
8
* any later version.
9
*
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.
14
*
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
19
*/
20
21
//****************************************************************
22
//
23
// Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64)
24
// Project started on December 29th, 2001
25
//
26
// To modify Glide64:
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.
29
//
30
// Official Glide64 development channel: #Glide64 on EFnet
31
//
32
// Original author: Dave2001 ([email protected])
33
// Other authors: Gonetz, Gugaman
34
//
35
//****************************************************************
36
37
// INI code v1.1
38
39
#include "m64p.h"
40
41
#include "Ini.h"
42
#include "Gfx_1.3.h"
43
#include <limits.h>
44
#ifndef _WIN32
45
#include <unistd.h>
46
#include <string.h>
47
#include <dirent.h>
48
#include <stdlib.h>
49
#else
50
#include <io.h>
51
#endif // _WIN32
52
53
#include <errno.h>
54
#ifndef _WIN32
55
#include <sys/resource.h>
56
#endif
57
58
#ifdef _WIN32
59
#define PATH_MAX _MAX_PATH
60
#define stricmp _stricmp
61
#endif
62
63
FILE *ini;
64
int sectionstart;
65
int last_line; // last good line
66
int last_line_ret; // last line ended in return?
67
wxUint16 cr = 0x0A0D;
68
static char configdir[PATH_MAX] = {0};
69
70
71
//TODO: move INI_xxxx() function code into class and clean up
72
Ini *Ini::singleton = 0;
73
74
Ini::Ini()
75
{
76
if (!INI_Open())
77
{
78
printf("Could not find INI file!");
79
exit(1);
80
}
81
}
82
83
Ini *Ini::OpenIni()
84
{
85
if (!singleton)
86
singleton = new Ini();
87
return singleton;
88
}
89
90
void Ini::SetPath(const char *path)
91
{
92
if (!INI_FindSection(path, false))
93
{
94
printf("Could not find [%s] section in INI file!", path);
95
}
96
}
97
98
99
bool Ini::Read(const char *key, int *l)
100
{
101
int undef = 0xDEADBEEF;
102
int tmpVal = INI_ReadInt(key, undef, false);
103
if (tmpVal == undef)
104
{
105
return false;
106
}
107
else
108
{
109
*l = tmpVal;
110
return true;
111
}
112
}
113
114
bool Ini::Read(const char *key, int *l, int defaultVal)
115
{
116
*l = INI_ReadInt(key, defaultVal, false);
117
return true;
118
}
119
120
int Ini::Read(const char *key, int defaultVal)
121
{
122
return INI_ReadInt(key, defaultVal, false);
123
}
124
125
126
BOOL INI_Open ()
127
{
128
//TODO: use ConfigGetSharedDataFilepath
129
130
// Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll
131
char path[PATH_MAX];
132
if(strlen(configdir) > 0)
133
{
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));
138
}
139
else
140
{
141
#ifdef _WIN32
142
GetModuleFileName (NULL, path, PATH_MAX);
143
#else // _WIN32
144
# ifdef __FreeBSD__
145
int n = readlink("/proc/curproc/files", path, PATH_MAX);
146
#else
147
int n = readlink("/proc/self/exe", path, PATH_MAX);
148
#endif
149
if (n == -1) strcpy(path, "./");
150
else
151
{
152
char path2[PATH_MAX];
153
int i;
154
155
path[n] = '\0';
156
strcpy(path2, path);
157
for (i=strlen(path2)-1; i>0; i--)
158
{
159
if(path2[i] == '/') break;
160
}
161
if(i == 0) strcpy(path, "./");
162
else
163
{
164
DIR *dir;
165
struct dirent *entry;
166
int gooddir = 0;
167
168
path2[i+1] = '\0';
169
dir = opendir(path2);
170
while((entry = readdir(dir)) != NULL)
171
{
172
if(!strcmp(entry->d_name, "plugins"))
173
gooddir = 1;
174
}
175
closedir(dir);
176
if(!gooddir) strcpy(path, "./");
177
}
178
}
179
180
#endif // _WIN32
181
182
// Find the previous backslash
183
int i;
184
for (i=strlen(path)-1; i>0; i--)
185
{
186
#ifdef _WIN32
187
if (path[i] == '\\')
188
#else // _WIN32
189
if (path[i] == '/')
190
#endif // _WIN32
191
break;
192
}
193
if (path == 0) return FALSE;
194
path[i+1] = 0;
195
196
#ifndef _WIN32
197
strcat(path, "plugins/");
198
#endif // _WIN32
199
}
200
201
//strncat (path, "Glide64mk2.ini", PATH_MAX - strlen(path));
202
LOG("opening %s\n", path);
203
// Open the file
204
ini = fopen (path, "rb");
205
if (ini == NULL)
206
{
207
ERRLOG("Could not find Glide64mk2.ini!");
208
return FALSE;
209
/*
210
ini = fopen (path, "w+b");
211
if (ini == NULL)
212
{
213
return FALSE;
214
}
215
*/
216
}
217
218
sectionstart = 0;
219
last_line = 0;
220
last_line_ret = 1;
221
222
return TRUE;
223
}
224
225
void INI_Close ()
226
{
227
//if (ini)
228
// fclose(ini);
229
}
230
231
void INI_InsertSpace(int space)
232
{
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
236
// current location.
237
238
// note: negative count means delete
239
char chunk[2048];
240
int len, file, start_pos, cur_pos;
241
242
#ifdef _WIN32
243
file = _fileno(ini);
244
#else // _WIN32
245
file = fileno(ini);
246
#endif // _WIN32
247
248
start_pos = ftell(ini);
249
fseek(ini,0,SEEK_END);
250
251
// if adding, extend the file
252
if (space > 0)
253
#ifdef _WIN32
254
_chsize (file, _filelength(file)+space);
255
#else // _WIN32
256
{
257
int t1 = ftell(ini);
258
fseek(ini, 0L, SEEK_END);
259
int t2 = ftell(ini);
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);
263
}
264
#endif // _WIN32
265
266
while (1) {
267
cur_pos = ftell(ini);
268
len = cur_pos - start_pos;
269
if (len == 0) break;
270
if (len > 2048) len = 2048;
271
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);
279
}
280
281
// if deleted, make the file shorter
282
if (space < 0)
283
#ifdef _WIN32
284
_chsize (file, _filelength(file)+space);
285
#else // _WIN32
286
{
287
int t1 = ftell(ini);
288
fseek(ini, 0L, SEEK_END);
289
int t2 = ftell(ini);
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);
293
}
294
#endif // _WIN32
295
}
296
297
BOOL INI_FindSection (const char *sectionname, BOOL create)
298
{
299
if (ini == NULL)
300
return FALSE;
301
printf("INI_FindSection trying to find name for %s\n", sectionname);
302
303
char line[256], section[64];
304
char *p;
305
int i, sectionfound, ret;
306
307
rewind (ini);
308
309
last_line = 0;
310
sectionfound = 0;
311
312
while(!feof(ini)) {
313
ret = 0;
314
*line=0;
315
if (fgets(line,255,ini) == NULL)
316
break;
317
318
// remove enter
319
i=strlen(line);
320
// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
321
// with just EOL), it would write into line[-1]
322
if(i>=1 && line[i-1]==0xa) {
323
ret=1;
324
line[i-1]=0;
325
if (i>=2 && line[i-2]==0xd) line[i-2]=0;
326
}
327
328
// remove comments
329
p=line;
330
while(*p)
331
{
332
if (p[0]=='/' && p[1]=='/')
333
{
334
p[0]=0;
335
break;
336
}
337
p++;
338
}
339
340
// skip starting space
341
p=line;
342
while(*p<=' ' && *p) p++;
343
344
// empty line
345
if(!*p) continue;
346
347
last_line=ftell(ini); // where to add if not found
348
last_line_ret = ret;
349
350
if(*p!='[') continue;
351
352
p++;
353
for (i=0;i<63;i++)
354
{
355
if(*p==']' || !*p) break;
356
section[i]=*p++;
357
}
358
section[i]=0;
359
360
#ifdef _WIN32
361
if(!stricmp(section,sectionname))
362
#else // _WIN32
363
if (!strcasecmp(section,sectionname))
364
#endif // _WIN32
365
{
366
sectionstart=ftell(ini);
367
sectionfound=1;
368
return TRUE;
369
}
370
}
371
372
if (!sectionfound && create)
373
{
374
// create the section
375
fseek(ini,last_line,SEEK_SET);
376
INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname));
377
if (!last_line_ret)
378
if (fwrite(&cr, 1, 2, ini) != 2)
379
ERRLOG("Failed to write <CR><LF> to .ini file");
380
sprintf (section, "[%s]", sectionname);
381
if (fwrite(&cr, 1, 2, ini) != 2 ||
382
fwrite(section, 1, strlen(section), ini) != strlen(section) ||
383
fwrite(&cr, 1, 2, ini) != 2)
384
ERRLOG("Failed to write Section line to .ini file");
385
sectionstart = ftell(ini);
386
last_line = sectionstart;
387
last_line_ret = 1;
388
return TRUE;
389
}
390
391
return FALSE;
392
}
393
394
// Reads the value of item 'itemname' as a string.
395
const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create)
396
{
397
char line[256], name[64];
398
char *p, *n;
399
int ret, i;
400
*value = 0;
401
402
fseek(ini,sectionstart,SEEK_SET);
403
404
while(!feof(ini)) {
405
ret = 0;
406
*line=0;
407
if (fgets(line,255,ini) == NULL)
408
break;
409
410
// remove enter
411
i=strlen(line);
412
// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
413
// with just EOL), it would write into line[-1]
414
// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
415
if(i>=1 && line[i-1]==0xa) {
416
ret=1;
417
line[i-1]=0;
418
if (i>=2 && line[i-2]==0xd) line[i-2]=0;
419
}
420
421
// remove comments
422
p=line;
423
while(*p)
424
{
425
if (p[0]==';')
426
{
427
p[0]=0;
428
break;
429
}
430
p++;
431
}
432
433
// skip starting space
434
p=line;
435
while(*p<=' ' && *p) p++;
436
437
// empty line
438
if(!*p) continue;
439
440
// new section
441
if(*p=='[') break;
442
443
last_line=ftell(ini); // where to add if not found
444
last_line_ret = ret;
445
446
// read name
447
n = name;
448
while(*p && *p!='=' && *p>' ') *n++ = *p++;
449
*n = 0;
450
451
#ifdef _WIN32
452
if(!stricmp(name,itemname))
453
#else // _WIN32
454
if(!strcasecmp(name,itemname))
455
#endif // _WIN32
456
{
457
// skip spaces/equal sign
458
while(*p<=' ' || *p=='=') p++;
459
460
// read value
461
n = value;
462
while(*p) *n++ = *p++;
463
464
// remove trailing spaces
465
while (*(n-1) == ' ') n--;
466
467
*n=0;
468
469
return value;
470
}
471
}
472
473
// uh-oh, not found. we need to create
474
if (create)
475
{
476
fseek(ini,last_line,SEEK_SET);
477
INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5);
478
if (!last_line_ret)
479
if (fwrite(&cr, 1, 2, ini) != 2)
480
ERRLOG("Failed to write <CR><LF> to .ini file");
481
sprintf (line, "%s = %s", itemname, def_value);
482
if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
483
fwrite(&cr, 1, 2, ini) != 2)
484
ERRLOG("Failed to write key,value line to .ini file");
485
last_line = ftell(ini);
486
last_line_ret = 1;
487
}
488
489
strcpy (value, def_value);
490
return value;
491
}
492
493
// Reads the value of item 'itemname' as a string.
494
void INI_WriteString (const char *itemname, const char *value)
495
{
496
char line[256], name[64];
497
char *p, *n;
498
int ret, i;
499
500
fseek(ini,sectionstart,SEEK_SET);
501
502
while(!feof(ini)) {
503
ret = 0;
504
*line=0;
505
if (fgets(line,255,ini) == NULL) break;
506
507
// remove enter
508
i=strlen(line);
509
// ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line
510
// with just EOL), it would write into line[-1]
511
// OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0;
512
if(i>=1 && line[i-1]==0xa) {
513
ret=1;
514
line[i-1]=0;
515
if (i>=2 && line[i-2]==0xd) line[i-2]=0;
516
}
517
518
// remove comments
519
p=line;
520
while(*p)
521
{
522
if (p[0]=='/' && p[1]=='/')
523
{
524
p[0]=0;
525
break;
526
}
527
p++;
528
}
529
530
// skip starting space
531
p=line;
532
while(*p<=' ' && *p) p++;
533
534
// empty line
535
if(!*p) continue;
536
537
// new section
538
if(*p=='[') break;
539
540
last_line=ftell(ini); // where to add if not found
541
last_line_ret = ret;
542
543
// read name
544
n = name;
545
while(*p && *p!='=' && *p>' ') *n++ = *p++;
546
*n = 0;
547
548
#ifdef _WIN32
549
if(!stricmp(name,itemname))
550
#else // _WIN32
551
if(!strcasecmp(name,itemname))
552
#endif // _WIN32
553
{
554
INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5));
555
sprintf (line, "%s = %s", itemname, value);
556
fseek (ini, -i, SEEK_CUR);
557
if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
558
fwrite(&cr, 1, 2, ini) != 2)
559
{
560
ERRLOG("Failed to write line '%s' to .ini file", line);
561
}
562
last_line = ftell(ini);
563
last_line_ret = 1;
564
return;
565
}
566
}
567
568
// uh-oh, not found. we need to create
569
fseek(ini,last_line,SEEK_SET);
570
INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5);
571
sprintf (line, "%s = %s", itemname, value);
572
if (!last_line_ret)
573
if (fwrite(&cr, 1, 2, ini) != 2)
574
ERRLOG("Failed to write <CR> to .ini file");
575
if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
576
fwrite(&cr, 1, 2, ini) != 2)
577
{
578
ERRLOG("Failed to write line '%s' to .ini file", line);
579
}
580
last_line = ftell(ini);
581
last_line_ret = 1;
582
return;
583
}
584
585
int INI_ReadInt (const char *itemname, int def_value, BOOL create)
586
{
587
if (ini == NULL)
588
return def_value;
589
590
char value[64], def[64];
591
#ifdef _WIN32
592
_itoa (def_value, def, 10);
593
#else // _WIN32
594
sprintf(def, "%d", def_value);
595
#endif // _WIN32
596
INI_ReadString (itemname, value, def, create);
597
return atoi (value);
598
}
599
600
void INI_WriteInt (const char *itemname, int value)
601
{
602
char valstr[64];
603
#ifdef _WIN32
604
_itoa (value, valstr, 10);
605
#else // _WIN32
606
sprintf(valstr, "%d", value);
607
#endif // _WIN32
608
INI_WriteString (itemname, valstr);
609
}
610
611
void SetConfigDir( const char *configDir )
612
{
613
strncpy(configdir, configDir, PATH_MAX);
614
}
615
616
617