diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 4d3382d25..97b8bc0a3 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,7 @@ Changes towards version 0.5: +- Options selected in the Setup Menu now persist across runs -Michael +- Added a simple implementation of key-value pair "resource" files + for organizing simple data such as configuration options -Michael - Added a 'fullscreen' setup menu option - Alex - Fixed a bug that prevented Slylandro Probes from ever showing up in interplanetary exploration (found by SvdB, bug #768) diff --git a/sc2/src/msvc++/UrQuanMasters.dsp b/sc2/src/msvc++/UrQuanMasters.dsp index 72642773a..8d0bcca41 100644 --- a/sc2/src/msvc++/UrQuanMasters.dsp +++ b/sc2/src/msvc++/UrQuanMasters.dsp @@ -480,6 +480,14 @@ SOURCE=..\sc2code\libs\memory\w_memlib.c # PROP Default_Filter "" # Begin Source File +SOURCE=..\sc2code\libs\resource\alist.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\alist.h +# End Source File +# Begin Source File + SOURCE=..\sc2code\libs\resource\direct.c # End Source File # Begin Source File @@ -500,6 +508,10 @@ SOURCE=..\sc2code\libs\resource\loadres.c # End Source File # Begin Source File +SOURCE=..\sc2code\libs\resource\mapres.c +# End Source File +# Begin Source File + SOURCE=..\sc2code\libs\resource\resdata.c # End Source File # Begin Source File @@ -510,6 +522,14 @@ SOURCE=..\sc2code\libs\resource\resinit.c SOURCE=..\sc2code\libs\resource\resintrn.h # End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\stringbank.c +# End Source File +# Begin Source File + +SOURCE=..\sc2code\libs\resource\stringbank.h +# End Source File # End Group # Begin Group "sound" diff --git a/sc2/src/sc2code/libs/reslib.h b/sc2/src/sc2code/libs/reslib.h index b4ccbe1ac..dec48dddf 100644 --- a/sc2/src/sc2code/libs/reslib.h +++ b/sc2/src/sc2code/libs/reslib.h @@ -120,5 +120,27 @@ extern DIRENTRY_REF LoadDirEntryTable (uio_DirHandle *dirHandle, #define GetDirEntryAddress GetStringAddress #define GetDirEntryContents GetStringContents +/* Key-Value resources */ +void res_ClearTables (void); + +void res_LoadFilename (uio_DirHandle *path, const char *fname); +void res_SaveFilename (uio_DirHandle *path, const char *fname, const char *root); + +void res_LoadFile (uio_Stream *fname); +void res_SaveFile (uio_Stream *fname, const char *root); + +BOOLEAN res_HasKey (const char *key); + +const char *res_GetString (const char *key); +void res_PutString (const char *key, const char *value); + +BOOLEAN res_IsInteger (const char *key); +int res_GetInteger (const char *key); +void res_PutInteger (const char *key, int value); + +BOOLEAN res_IsBoolean (const char *key); +BOOLEAN res_GetBoolean (const char *key); +void res_PutBoolean (const char *key, BOOLEAN value); + #endif /* _RESLIB_H */ diff --git a/sc2/src/sc2code/libs/resource/Makeinfo b/sc2/src/sc2code/libs/resource/Makeinfo index 0c3d79c15..65f944fb8 100644 --- a/sc2/src/sc2code/libs/resource/Makeinfo +++ b/sc2/src/sc2code/libs/resource/Makeinfo @@ -1 +1,2 @@ -uqm_CFILES="direct.c filecntl.c getres.c loadres.c resdata.c resinit.c" +uqm_CFILES="alist.c direct.c filecntl.c getres.c loadres.c mapres.c + resdata.c resinit.c stringbank.c" diff --git a/sc2/src/sc2code/libs/resource/alist.c b/sc2/src/sc2code/libs/resource/alist.c new file mode 100644 index 000000000..40311b642 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/alist.c @@ -0,0 +1,232 @@ +/* alist.c, Copyright (c) 2005 Michael C. Martin */ + +/* + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope thta it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "libs/reslib.h" +#include "alist.h" +#include "stringbank.h" + +alist_entry * +AlistEntry_New (const char *key, const char *value) +{ + alist_entry *e; + e = malloc (sizeof(alist_entry)); + e->key = key; + e->value = value; + e->next = NULL; + return e; +} + +void +AlistEntry_Free (alist_entry *e) +{ + if (e == NULL) + return; + AlistEntry_Free (e->next); + free (e); +} + +alist * +Alist_New (void) +{ + alist *result = malloc (sizeof(alist)); + result->first = NULL; + return result; +} + +void +Alist_Free (alist *m) { + if (m == NULL) return; + AlistEntry_Free (m->first); + free (m); +} + +alist_entry * +Alist_GetEntry (alist *m, const char *key) +{ + alist_entry *x = m->first; + while (x != NULL) { + if (!strcmp (x->key, key)) + return x; + x = x->next; + } + return NULL; +} + +const char * +Alist_GetString (alist *m, const char *key) +{ + alist_entry *x = Alist_GetEntry (m, key); + return x ? x->value : NULL; +} + +void +Alist_PutString (alist *m, const char *key, const char *value) +{ + alist_entry *e = Alist_GetEntry (m, key); + if (e == NULL) { + e = AlistEntry_New(key, value); + e->next = m->first; + m->first = e; + } else { + e->value = value; + } +} + +void +Alist_PutAll (alist *dst, alist *src) +{ + alist_entry *e = src->first; + while (e) { + Alist_PutString (dst, e->key, e->value); + e = e->next; + } +} + +alist * +Alist_New_FromFile (uio_Stream *f) +{ + long flen; + alist *m; + char *data; + + flen = LengthResFile (f); + + data = malloc (flen + 1); + if (!data) { + return NULL; + } + + ReadResFile (data, 1, flen, f); + data[flen] = '\0'; + + m = Alist_New_FromString (data); + free (data); + return m; +} + +alist * +Alist_New_FromFilename (uio_DirHandle *path, const char *fname) +{ + alist *result; + uio_Stream *f = res_OpenResFile (path, fname, "rt"); + if (!f) { + return NULL; + } + result = Alist_New_FromFile (f); + res_CloseResFile(f); + return result; +} + +alist * +Alist_New_FromString (char *d) +{ + alist *m = Alist_New (); + int len, i; + if (!m) return NULL; + + len = strlen(d); + i = 0; + while (i < len) { + int key_start, key_end, value_start, value_end; + /* Starting a line: search for non-whitespace */ + while ((i < len) && isspace (d[i])) i++; + if (i >= len) break; /* Done parsing! */ + /* If it was a comment, skip to end of comment/file */ + if (d[i] == '#') { + while ((i < len) && (d[i] != '\n')) i++; + if (i >= len) break; + continue; /* Back to keyword search */ + } + key_start = i; + /* Find the = on this line */ + while ((i < len) && (d[i] != '=') && + (d[i] != '\n') && (d[i] != '#')) i++; + if (i >= len) { /* Bare key at EOF */ + fprintf (stderr, "Warning: Bare keyword at EOF"); + break; + } + /* Comments here mean incomplete line too */ + if (d[i] != '=') { + fprintf (stderr, "Warning: Key without value"); + while ((i < len) && (d[i] != '\n')) i++; + if (i >= len) break; + continue; /* Back to keyword search */ + } + /* Key ends at first whitespace before = , or at key_start*/ + key_end = i; + while ((key_end > key_start) && isspace (d[key_end-1])) + key_end--; + + /* Consume the = */ + i++; + /* Value starts at first non-whitespace after = on line... */ + while ((i < len) && (d[i] != '#') && (d[i] != '\n') && + isspace (d[i])) + i++; + value_start = i; + /* Until first non-whitespace before terminator */ + while ((i < len) && (d[i] != '#') && (d[i] != '\n')) + i++; + value_end = i; + while ((value_end > value_start) && isspace (d[value_end-1])) + value_end--; + /* Skip past EOL or EOF */ + while ((i < len) && (d[i] != '\n')) + i++; + i++; + + /* We now have start and end values for key and value. + We terminate the strings for both by writing \0s, then + make a new map entry. */ + d[key_end] = '\0'; + d[value_end] = '\0'; + Alist_PutString (m, StringBank_AddOrFindString(d+key_start), + StringBank_AddOrFindString(d+value_start)); + } + return m; +} + +void +Alist_Dump (alist *m, uio_Stream *s, const char *prefix) +{ + alist_entry *e = m->first; + int prefix_len = 0; + if (prefix) + prefix_len = strlen (prefix); + while (e) { + if (!prefix || !strncmp (prefix, e->key, prefix_len)) { + char *i = e->key; + while (*i) { + PutResFileChar (*i++, s); + } + PutResFileChar(' ', s); + PutResFileChar('=', s); + PutResFileChar(' ', s); + i = e->value; + while (*i) { + PutResFileChar (*i++, s); + } + PutResFileChar ('\n', s); + } + e = e->next; + } + return; +} diff --git a/sc2/src/sc2code/libs/resource/alist.h b/sc2/src/sc2code/libs/resource/alist.h new file mode 100644 index 000000000..de1b110cb --- /dev/null +++ b/sc2/src/sc2code/libs/resource/alist.h @@ -0,0 +1,65 @@ +/* alist.h, Copyright (c) 2005 Michael C. Martin */ + +/* + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope thta it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _ALIST_H_ +#define _ALIST_H_ + +#include "libs/uio.h" + +/* Associative List types. */ + +typedef struct _alist_entry { + const char *key, *value; + struct _alist_entry *next; +} alist_entry; + +typedef struct _alist_map { + alist_entry *first; +} alist; + +/* ***** alist_entry operations ***** */ + +/* Constructor and destructor */ +alist_entry *AlistEntry_New (const char *key, const char *value); +void AlistEntry_Free (alist_entry *e); + +/* ***** alist operations ***** */ + +/* Standard constructor and destructor */ +alist *Alist_New (void); +void Alist_Free (alist *m); + +/* Specialized constructors: Parse an alist out of a stream, file, or + string. It expects a bunch of key=value statements, one per + line. */ +alist *Alist_New_FromFile (uio_Stream *f); +alist *Alist_New_FromFilename (uio_DirHandle *path, const char *fname); +alist *Alist_New_FromString (char *d); + +/* Getting and Setting operations */ +alist_entry *Alist_GetEntry (alist *m, const char *key); +const char *Alist_GetString (alist *m, const char *key); +void Alist_PutString (alist *m, const char *key, const char *value); +void Alist_PutAll (alist *dest, alist *src); + +/* Dump the alist to the specified stream in a form that could be + read later by the Alist_New_From* routines. Dump only keys + that begin with the prefix; NULL means all keys. */ +void Alist_Dump (alist *m, uio_Stream *s, const char *prefix); + +#endif /* _ALIST_H_ */ diff --git a/sc2/src/sc2code/libs/resource/mapres.c b/sc2/src/sc2code/libs/resource/mapres.c new file mode 100644 index 000000000..76f352b2e --- /dev/null +++ b/sc2/src/sc2code/libs/resource/mapres.c @@ -0,0 +1,199 @@ +/* mapres.h, Copyright (c) 2005 Michael C. Martin */ + +/* + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope thta it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "libs/reslib.h" +#include "alist.h" +#include "stringbank.h" + +static alist *map = NULL; + +static void +check_map_init (void) +{ + if (map == NULL) { + map = Alist_New (); + } +} + +void +res_ClearTables (void) +{ + if (map != NULL) { + Alist_Free (map); + map = NULL; + } +} + +/* Type conversion routines. */ +static const char * +bool2str (BOOLEAN b) +{ + return b ? "yes" : "no"; +} + +static const char * +int2str (int i) { + char buf[20]; + sprintf (buf, "%d", i); + return StringBank_AddOrFindString (buf); +} + +static int +str2int (const char *s) { + return atoi(s); +} + +static BOOLEAN +str2bool (const char *s) { + if (!stricmp (s, "yes") || + !stricmp (s, "true") || + !stricmp (s, "1") ) + return TRUE; + return FALSE; +} + +void +res_LoadFile (uio_Stream *s) +{ + alist *d; + check_map_init (); + + d = Alist_New_FromFile (s); + if (d) { + Alist_PutAll (map, d); + Alist_Free (d); + } +} + +void +res_LoadFilename (uio_DirHandle *path, const char *fname) +{ + alist *d; + check_map_init (); + + d = Alist_New_FromFilename (path, fname); + if (d) { + Alist_PutAll (map, d); + Alist_Free (d); + } +} + +void +res_SaveFile (uio_Stream *f, const char *root) +{ + check_map_init (); + Alist_Dump (map, f, root); +} + +void +res_SaveFilename (uio_DirHandle *path, const char *fname, const char *root) +{ + uio_Stream *f; + + check_map_init (); + f = res_OpenResFile (path, fname, "wt"); + if (f) { + res_SaveFile (f, root); + res_CloseResFile (f); + } +} + +BOOLEAN +res_IsBoolean (const char *key) +{ + const char *d; + check_map_init (); + + d = res_GetString (key); + if (!d) return 0; + + return !stricmp (d, "yes") || + !stricmp (d, "no") || + !stricmp (d, "true") || + !stricmp (d, "false") || + !stricmp (d, "0") || + !stricmp (d, "1") || + !stricmp (d, ""); +} + +BOOLEAN +res_IsInteger (const char *key) +{ + const char *d; + check_map_init (); + + d = res_GetString (key); + while (*d) { + if (!isdigit (*d)) + return 0; + d++; + } + return 1; +} + +const char * +res_GetString (const char *key) +{ + check_map_init (); + return Alist_GetString (map, key); +} + +void +res_PutString (const char *key, const char *value) +{ + check_map_init (); + Alist_PutString (map, key, value); +} + +int +res_GetInteger (const char *key) +{ + check_map_init (); + return str2int (res_GetString (key)); +} + +void +res_PutInteger (const char *key, int value) +{ + check_map_init (); + res_PutString (key, int2str(value)); +} + +BOOLEAN +res_GetBoolean (const char *key) +{ + check_map_init (); + return str2bool (res_GetString (key)); +} + +void +res_PutBoolean (const char *key, BOOLEAN value) +{ + check_map_init (); + res_PutString (key, bool2str(value)); +} + +BOOLEAN +res_HasKey (const char *key) +{ + check_map_init (); + return (res_GetString (key) != NULL); +} \ No newline at end of file diff --git a/sc2/src/sc2code/libs/resource/stringbank.c b/sc2/src/sc2code/libs/resource/stringbank.c new file mode 100644 index 000000000..059c850d7 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/stringbank.c @@ -0,0 +1,106 @@ +/* stringbank.c, Copyright (c) 2005 Michael C. Martin */ + +/* + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope thta it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "stringbank.h" + +#define CHUNK_SIZE (1024 - sizeof (void *) - sizeof (int)) + +typedef struct _stringbank_chunk { + char data[CHUNK_SIZE]; + int len; + struct _stringbank_chunk *next; +} chunk; + +static chunk *bank = NULL; + +static void +add_chunk (void) +{ + chunk *n = malloc (sizeof (chunk)); + n->len = 0; + n->next = bank; + bank = n; +} + +const char * +StringBank_AddString (const char *str) +{ + int len = strlen (str); + chunk *x = bank; + if (len > CHUNK_SIZE) + return NULL; + while (x) { + int remaining = CHUNK_SIZE - x->len; + if (len < remaining) { + char *result = x->data + x->len; + strcpy (result, str); + x->len += len + 1; + return result; + } + x = x->next; + } + /* No room in any currently existing chunk */ + add_chunk (); + strcpy (bank->data, str); + bank->len += len + 1; + return bank->data; +} + +const char * +StringBank_AddOrFindString (const char *str) +{ + int len = strlen (str); + chunk *x = bank; + if (len > CHUNK_SIZE) + return NULL; + while (x) { + int i = 0; + while (i < x->len) { + if (!strcmp (x->data + i, str)) + return x->data + i; + while (x->data[i]) i++; + i++; + } + x = x->next; + } + /* We didn't find it, so add it */ + return StringBank_AddString (str); +} + +#ifdef DEBUG + +void +StringBank_Dump (FILE *s) +{ + chunk *x = bank; + while (x) { + int i = 0; + while (i < x->len) { + fprintf (s, "\"%s\"\n", x->data + i); + while (x->data[i]) i++; + i++; + } + x = x->next; + } +} + +#endif diff --git a/sc2/src/sc2code/libs/resource/stringbank.h b/sc2/src/sc2code/libs/resource/stringbank.h new file mode 100644 index 000000000..94e0aa807 --- /dev/null +++ b/sc2/src/sc2code/libs/resource/stringbank.h @@ -0,0 +1,37 @@ +/* stringbank.h, Copyright (c) 2005 Michael C. Martin */ + +/* + * 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 + * (at your option) any later version. + * + * This program is distributed in the hope thta it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _STRINGBANK_H_ +#define _STRINGBANK_H_ + +#ifdef DEBUG +#include +#endif + +/* Put str into the string bank. */ +const char *StringBank_AddString (const char *str); + +/* Put str into the string bank if it's not already there. Much slower. */ +const char *StringBank_AddOrFindString (const char *str); + +#ifdef DEBUG +/* Print out a list of the contents of the string bank to the named stream. */ +void StringBank_Dump (FILE *s); +#endif /* DEBUG */ + +#endif /* _STRINGBANK_H_ */ diff --git a/sc2/src/sc2code/setupmenu.c b/sc2/src/sc2code/setupmenu.c index 8eadd3525..8697d98cb 100644 --- a/sc2/src/sc2code/setupmenu.c +++ b/sc2/src/sc2code/setupmenu.c @@ -26,6 +26,7 @@ #include "libs/graphics/gfx_common.h" #include "libs/graphics/widgets.h" #include "libs/graphics/tfb_draw.h" +#include "libs/reslib.h" #define MENU_BKG "lbm/setupmenu.ani" @@ -333,9 +334,9 @@ static WIDGET_MENU_SCREEN graphics_menu = { "Graphics Options", { {0, 0}, NULL }, #ifdef HAVE_OPENGL - 6, graphics_widgets, + 7, graphics_widgets, #else - 5, graphics_widgets, + 6, graphics_widgets, #endif 0 }; @@ -759,21 +760,32 @@ SetGlobalOptions (GLOBALOPTS *opts) break; } + res_PutInteger ("config.reswidth", NewWidth); + res_PutInteger ("config.resheight", NewHeight); + res_PutInteger ("config.bpp", NewDepth); + res_PutBoolean ("config.alwaysgl", opts->driver == OPTVAL_ALWAYS_GL); + + switch (opts->scaler) { case OPTVAL_BILINEAR_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; + res_PutString ("config.scaler", "bilinear"); break; case OPTVAL_BIADAPT_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; + res_PutString ("config.scaler", "biadapt"); break; case OPTVAL_BIADV_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; + res_PutString ("config.scaler", "biadv"); break; case OPTVAL_TRISCAN_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; + res_PutString ("config.scaler", "triscan"); break; default: /* OPTVAL_NO_SCALE has no equivalent in gfxflags. */ + res_PutString ("config.scaler", "no"); break; } if (opts->scanlines) { @@ -786,6 +798,10 @@ SetGlobalOptions (GLOBALOPTS *opts) else NewGfxFlags &= ~TFB_GFXFLAGS_FULLSCREEN; + res_PutBoolean ("config.scanlines", opts->scanlines); + res_PutBoolean ("config.fullscreen", opts->fullscreen); + + if ((NewWidth != ScreenWidthActual) || (NewHeight != ScreenHeightActual) || (NewDepth != ScreenColorDepth) || @@ -803,4 +819,11 @@ SetGlobalOptions (GLOBALOPTS *opts) optWhichCoarseScan = (opts->cscan == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optSmoothScroll = (opts->scroll == OPTVAL_3DO) ? OPT_3DO : OPT_PC; + res_PutBoolean ("config.subtitles", opts->subtitles == OPTVAL_ENABLED); + res_PutBoolean ("config.textmenu", opts->menu == OPTVAL_PC); + res_PutBoolean ("config.textgradients", opts->text == OPTVAL_PC); + res_PutBoolean ("config.iconicscan", opts->cscan == OPTVAL_3DO); + res_PutBoolean ("config.smoothscroll", opts->scroll == OPTVAL_3DO); + + res_SaveFilename (configDir, "uqm.cfg", "config."); } diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c index ecb6a4620..d842288cc 100644 --- a/sc2/src/starcon2.c +++ b/sc2/src/starcon2.c @@ -175,6 +175,69 @@ main (int argc, char *argv[]) TFB_PreInit (); mem_init (); InitThreadSystem (); + initIO (); + prepareConfigDir (options.configDir); + + // Fill in the options struct based on uqm.cfg + res_LoadFilename (configDir, "uqm.cfg"); + if (res_HasKey ("config.reswidth")) + { + options.width = res_GetInteger ("config.reswidth"); + } + if (res_HasKey ("config.resheight")) + { + options.height = res_GetInteger ("config.resheight"); + } + if (res_HasKey ("config.bpp")) + { + options.bpp = res_GetInteger ("config.bpp"); + } + if (res_HasKey ("config.alwaysgl")) + { + options.gfxDriver = res_GetBoolean ("config.alwaysgl") ? + TFB_GFXDRIVER_SDL_OPENGL : TFB_GFXDRIVER_SDL_PURE; + } + if (res_HasKey ("config.scaler")) + { + const char *optarg = res_GetString ("config.scaler"); + + if (!strcmp (optarg, "bilinear")) + options.gfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; + else if (!strcmp (optarg, "biadapt")) + options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; + else if (!strcmp (optarg, "biadv")) + options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; + else if (!strcmp (optarg, "triscan")) + options.gfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; + } + if (res_HasKey ("config.scanlines") && res_GetBoolean ("config.scanlines")) + { + options.gfxFlags |= TFB_GFXFLAGS_SCANLINES; + } + if (res_HasKey ("config.fullscreen") && res_GetBoolean ("config.fullscreen")) + { + options.gfxFlags |= TFB_GFXFLAGS_FULLSCREEN; + } + if (res_HasKey ("config.subtitles")) + { + options.subTitles = res_GetBoolean ("config.subtitles"); + } + if (res_HasKey ("config.textmenu")) + { + options.whichMenu = res_GetBoolean ("config.textmenu") ? OPT_PC : OPT_3DO; + } + if (res_HasKey ("config.textgradients")) + { + options.whichFonts = res_GetBoolean ("config.textgradients") ? OPT_PC : OPT_3DO; + } + if (res_HasKey ("config.iconicscan")) + { + options.whichCoarseScan = res_GetBoolean ("config.iconicscan") ? OPT_3DO : OPT_PC; + } + if (res_HasKey ("config.smoothscroll")) + { + options.smoothScroll = res_GetBoolean ("config.smoothscroll") ? OPT_3DO : OPT_PC; + } optionsResult = parseOptions(argc, argv, &options); if (optionsResult != 0) @@ -206,10 +269,8 @@ main (int argc, char *argv[]) sfxVolumeScale = options.sfxVolumeScale; speechVolumeScale = options.speechVolumeScale; - initIO (); prepareContentDir (options.contentDir, options.addons); HFree ((void *) options.addons); - prepareConfigDir (options.configDir); prepareMeleeDir (); prepareSaveDir (); initTempDir (); @@ -316,6 +377,11 @@ preParseOptions(int argc, char *argv[], struct options_struct *options) options->logFile = optarg; break; } + case 'C': + { + options->configDir = optarg; + break; + } case '?': case 'h': options->runMode = runMode_usage; @@ -353,9 +419,6 @@ parseOptions(int argc, char *argv[], struct options_struct *options) break; switch (c) { - case 'C': - options->configDir = optarg; - break; case 'r': { int width, height; @@ -501,8 +564,9 @@ parseOptions(int argc, char *argv[], struct options_struct *options) break; } case 'l': - // -l is a no-op on the second pass.. - break; + case 'C': + // -l and -C are no-ops on the second pass. + break; case 'i': { if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,