wall noise and arbitrary render resolution option
[raydungeon] / src / options.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include "options.h"
6 #include "game.h"
7 #include "treestor.h"
8
9 #define DEF_XRES                1280
10 #define DEF_YRES                720
11 #define DEF_VSYNC               1
12 #define DEF_VOL                 255
13 #define DEF_MUS                 1
14 #define DEF_FULLSCR             0
15 #define DEF_INVMOUSEY   0
16 #define DEF_MOUSE_SPEED 50
17
18 #define DEF_GFX_RENDRES 1
19
20 struct options opt = {
21         DEF_XRES, DEF_YRES,
22         DEF_VSYNC,
23         DEF_FULLSCR,
24         DEF_VOL, DEF_VOL, DEF_VOL,
25         DEF_MUS,
26         DEF_INVMOUSEY,
27         DEF_MOUSE_SPEED,
28
29         { DEF_GFX_RENDRES }
30 };
31
32 int parse_options(int argc, char **argv)
33 {
34         int i;
35         static const char *usage_fmt = "Usage: %s [options]\n"
36                 "Options:\n"
37                 " -screen <name>: select starting screen\n"
38                 " -h,-help: print usage information and exit\n\n";
39
40         for(i=1; i<argc; i++) {
41                 if(argv[i][0] == '-') {
42                         if(strcmp(argv[i], "-scr") == 0 || strcmp(argv[i], "-screen") == 0) {
43                                 if(!argv[++i]) {
44                                         fprintf(stderr, "%s must be followed by a screen name\n", argv[i - 1]);
45                                         return -1;
46                                 }
47                                 start_scr_name = argv[i];
48
49                         } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
50                                 printf(usage_fmt, argv[0]);
51                                 exit(0);
52                         } else {
53                                 fprintf(stderr, "invalid option: %s\n", argv[i]);
54                                 return -1;
55                         }
56                 } else {
57                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
58                         return -1;
59                 }
60         }
61
62         return 0;
63 }
64
65 int load_options(const char *fname)
66 {
67         struct ts_node *cfg;
68
69         if(!(cfg = ts_load(fname))) {
70                 return -1;
71         }
72         printf("loaded config: %s\n", fname);
73
74         opt.xres = ts_lookup_int(cfg, "options.video.xres", DEF_XRES);
75         opt.yres = ts_lookup_int(cfg, "options.video.yres", DEF_YRES);
76         opt.vsync = ts_lookup_int(cfg, "options.video.vsync", DEF_VSYNC);
77         opt.fullscreen = ts_lookup_int(cfg, "options.video.fullscreen", DEF_FULLSCR);
78
79         opt.vol_master = ts_lookup_int(cfg, "options.audio.volmaster", DEF_VOL);
80         opt.vol_mus = ts_lookup_int(cfg, "options.audio.volmusic", DEF_VOL);
81         opt.vol_sfx = ts_lookup_int(cfg, "options.audio.volsfx", DEF_VOL);
82         opt.music = ts_lookup_int(cfg, "options.audio.music", DEF_MUS);
83
84         opt.inv_mouse_y = ts_lookup_int(cfg, "options.controls.invmousey", DEF_INVMOUSEY);
85         opt.mouse_speed = ts_lookup_int(cfg, "options.controls.mousespeed", DEF_MOUSE_SPEED);
86
87         opt.gfx.render_res = ts_lookup_num(cfg, "options.gfx.render_res", DEF_GFX_RENDRES);
88
89         ts_free_tree(cfg);
90         return 0;
91 }
92
93 #define WROPT(lvl, fmt, val, defval) \
94         do { \
95                 int i; \
96                 if((val) == (defval)) fputc('#', fp); \
97                 for(i=0; i<lvl; i++) fputc('\t', fp); \
98                 fprintf(fp, fmt "\n", val); \
99         } while(0)
100
101 int save_options(const char *fname)
102 {
103         FILE *fp;
104         static const char *hdr = "# Game options\n# ------------\n"
105                 "# Lines starting with '#' are comments. Options set to their default value are\n"
106                 "# automatically commented when this file is written. If you want to change some\n"
107                 "# option, make sure to remove the '#' from the beginning of the line, or your\n"
108                 "# change will have no effect.\n";
109
110
111         printf("writing config: %s\n", fname);
112
113         if(!(fp = fopen(fname, "wb"))) {
114                 fprintf(stderr, "failed to save options (%s): %s\n", fname, strerror(errno));
115         }
116         fprintf(fp, "%s\n", hdr);
117         fprintf(fp, "options {\n");
118         fprintf(fp, "\tvideo {\n");
119         WROPT(2, "xres = %d", opt.xres, DEF_XRES);
120         WROPT(2, "yres = %d", opt.yres, DEF_YRES);
121         WROPT(2, "vsync = %d", opt.vsync, DEF_VSYNC);
122         WROPT(2, "fullscreen = %d", opt.fullscreen, DEF_FULLSCR);
123         fprintf(fp, "\t}\n");
124
125         fprintf(fp, "\tgfx {\n");
126         WROPT(2, "render_res = %f", opt.gfx.render_res, DEF_GFX_RENDRES);
127         fprintf(fp, "\t}\n");
128
129         fprintf(fp, "\taudio {\n");
130         WROPT(2, "volmaster = %d", opt.vol_master, DEF_VOL);
131         WROPT(2, "volmusic = %d", opt.vol_mus, DEF_VOL);
132         WROPT(2, "volsfx = %d", opt.vol_sfx, DEF_VOL);
133         WROPT(2, "music = %d", opt.music ? 1 : 0, DEF_MUS);
134         fprintf(fp, "\t}\n");
135
136         fprintf(fp, "\tcontrols {\n");
137         WROPT(2, "invmousey = %d", opt.inv_mouse_y, DEF_INVMOUSEY);
138         WROPT(2, "mousespeed = %d", opt.mouse_speed, DEF_MOUSE_SPEED);
139         fprintf(fp, "\t}\n");
140
141         fprintf(fp, "}\n");
142         fprintf(fp, "# v" "i:ts=4 sts=4 sw=4 noexpandtab:\n");
143
144         fclose(fp);
145         return 0;
146 }