1 /*
2  * Kuklomenos
3  * Copyright (C) 2008-2009 Martin Bays <mbays@sdf.lonestar.org>
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 3 of the License, or
8  * (at your option) 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 License
16  * along with this program.  If not, see http://www.gnu.org/licenses/.
17  */
18 
19 #include <iostream>
20 #include <fstream>
21 #include <string>
22 #include <cstdlib>
23 #include <sstream>
24 using namespace std;
25 
26 #include "conffile.h"
27 #include "keybindings.h"
28 #include "SDL_gfxPrimitivesDirty.h"
29 
powmod(int n,int m,int p)30 int powmod(int n, int m, int p)
31 {
32     int out = 1;
33     while (m > 0)
34 	if (m % 2 == 0)
35 	{
36 	    n = (n*n) % p;
37 	    m /= 2;
38 	}
39 	else
40 	{
41 	    out = (out*n) % p;
42 	    m -= 1;
43 	}
44     return out;
45 
46 }
47 
48 /* obfuscate the rating string: if you want to cheat, you at least have to
49  * source-dive...
50  */
obfuscatedRating(double rating)51 int obfuscatedRating(double rating)
52 {
53     int pertinentRating = (int)(round(10*rating));
54     return powmod(pertinentRating, 5, 45953);
55 }
unobfuscatedRating(int obfuscated)56 double unobfuscatedRating(int obfuscated)
57 {
58     double unobf = powmod(obfuscated, 18381, 45953)/10.0;
59     if (unobf < 0 || unobf > 20)
60 	return 0.0;
61     return unobf;
62 }
63 
Config()64 Config::Config() :
65     useAA(AA_YES), showGrid(true), zoomEnabled(true), rotatingView(true),
66     turnRateFactor(1.0), fps(30), showFPS(true), sound(true), volume(1.0),
67     soundFreq(44100),
68     aaGamma(2.2),
69     shouldUpdateRating(false), uuid(0),
70     rebindings(),
71     bgType(BG_NONE),
72     width(0), height(0), bpp(16), fullscreen(false),
73     confFileVersion(CONFFILE_VERSION_FIRST)
74 {
75     username[0] = '\0';
76     for (int i=0; i<3; i++)
77 	rating[i] = highestRating[i] = 5.0;
78 }
79 
read()80 void Config::read()
81 {
82     ifstream f;
83     char* home = getenv("HOME");
84 
85     if (home != NULL)
86     {
87 	string homeStr = home;
88 	f.open((home + (string)"/.kuklomenosrc").c_str());
89     }
90     if (!f.is_open())
91 	f.open("./kuklomenosrc.txt");
92 
93     if (f.is_open())
94     {
95 	string line;
96 	double val, val2, val3, val4, val5, val6;
97 	char buf[31];
98 	char buf2[31];
99 	unsigned int uint;
100 	int i, i2, i3;
101 	int n;
102 
103 	while (!f.eof())
104 	{
105 	    std::getline(f, line);
106 	    const char* cstr = line.c_str();
107 	    n = sscanf(cstr, "data: %lf %lf %lf %lf %lf %lf", &val, &val2,
108 		    &val3, &val4, &val5, &val6);
109 	    if (n > 0)
110 		for (int i=0; i<3; i++)
111 		{
112 		    if (n > 2*i)
113 		    {
114 			rating[i] = unobfuscatedRating( (int)(
115 				    i==0 ? val : i==1 ? val3 : val5
116 				    ) );
117 			if (n > 2*i+1)
118 			    highestRating[i] = unobfuscatedRating( ((int)(
119 					    i==0 ? val2 : i==1 ? val4 : val6
120 					    )-1337-37*i)/2 );
121 		    }
122 		}
123 	    else if (sscanf(cstr, "confversion: %lf", &val) == 1)
124 		confFileVersion = val;
125 	    else if (sscanf(cstr, "showGrid: %lf", &val) == 1)
126 		showGrid = val;
127 	    else if (sscanf(cstr, "zoomEnabled: %lf", &val) == 1)
128 		zoomEnabled = val;
129 	    else if (sscanf(cstr, "rotatingView: %lf", &val) == 1)
130 		rotatingView = val;
131 	    else if (sscanf(cstr, "turnRate: %lf", &val) == 1)
132 		turnRateFactor = val;
133 	    else if (sscanf(cstr, "showFPS: %lf", &val) == 1)
134 		showFPS = val;
135 	    else if (sscanf(cstr, "fullscreen: %lf", &val) == 1)
136 		fullscreen = val;
137 	    else if (sscanf(cstr, "speed: %lf", &val) == 1)
138 	    {
139 		speed = (int) val;
140 		if (speed < 0) speed = 0;
141 		if (speed > 2) speed = 2;
142 	    }
143 	    else if (sscanf(cstr, "sound: %lf", &val) == 1)
144 		sound = val;
145 	    else if (sscanf(cstr, "volume: %lf", &val) == 1)
146 		volume = val;
147 	    else if (sscanf(cstr, "freq: %lf", &val) == 1)
148 		soundFreq = int(val);
149 	    else if (sscanf(cstr, "antialiasGamma: %lf", &val) == 1)
150 		aaGamma = val;
151 	    else if (sscanf(cstr, "fps: %lf", &val) == 1)
152 		fps = (int) val;
153 	    else if (sscanf(cstr, "useAA: %lf", &val) == 1)
154 		useAA = (val == 0 ? AA_NO :
155 			val == 2 ? AA_FORCE :
156 			AA_YES);
157 	    else if (sscanf(cstr,
158 			"mode: %dx%dx%d", &i, &i2, &i3) == 3)
159 	    {
160 		width = (int) i;
161 		height = (int) i2;
162 		bpp = (int) i3;
163 	    }
164 	    else if (sscanf(cstr, "username: %16s", buf) == 1)
165 		strncpy(username, buf, 17);
166 	    else if (strcmp(cstr, "username: ") == 0)
167 		username[0] = '\0';
168 	    else if (sscanf(cstr, "uuid: %x", &uint) == 1)
169 		uuid = uint;
170 	    else if (sscanf(cstr, "background: %30s", buf) == 1)
171 	    {
172 		for (BGType bg = BG_FIRST; bg <= BG_LAST; bg = BGType(bg+1))
173 		    if (bgTypeStrings[bg].compare(buf) == 0)
174 			bgType = bg;
175 	    }
176 	    else if (sscanf(cstr, "bind %30s %30s", buf, buf2) == 2)
177 	    {
178 		command c = commandOfString(buf);
179 		Key k(buf2);
180 		if (c == C_NONE)
181 		    fprintf(stderr, "Unparsable command: %s\n", buf);
182 		else if (k == KEY_NONE)
183 		    fprintf(stderr, "Unparsable key description: %s\n", buf2);
184 		else
185 		    rebindings[c] = k;
186 	    }
187 	    else if (*cstr != '\0' && *cstr != '#')
188 		fprintf(stderr, "Unparsable line in config file: %s\n", cstr);
189 	}
190     }
191 }
192 
importSettings(const Settings & settings)193 void Config::importSettings(const Settings& settings)
194 {
195     useAA = settings.useAA;
196     showGrid = settings.showGrid;
197     zoomEnabled = settings.zoomEnabled;
198     rotatingView = settings.rotatingView;
199     turnRateFactor = settings.turnRateFactor;
200     fps = settings.fps;
201     showFPS = settings.showFPS;
202     sound = settings.sound;
203     volume = settings.volume;
204     soundFreq = settings.soundFreq;
205     speed = settings.speed;
206     bgType = settings.bgType;
207 
208     width = settings.width;
209     height = settings.height;
210     bpp = settings.bpp;
211     fullscreen = (settings.videoFlags & SDL_FULLSCREEN);
212 
213     aaGamma = antialiasGamma;
214 
215     rebindings.clear();
216     for (command c=C_FIRST; c <= C_LASTDEBUG; c = command(c+1))
217     {
218 	if (settings.keybindings.get(c) != defaultKeybindings().get(c))
219 	    rebindings[c] = settings.keybindings.get(c);
220     }
221 }
exportSettings(Settings & settings) const222 void Config::exportSettings(Settings& settings) const
223 {
224     settings.useAA = useAA;
225     settings.showGrid = showGrid;
226     settings.zoomEnabled = zoomEnabled;
227     settings.rotatingView = rotatingView;
228     settings.turnRateFactor = turnRateFactor;
229     settings.fps = fps;
230     settings.showFPS = showFPS;
231     settings.sound = sound;
232     settings.volume = volume;
233     settings.soundFreq = soundFreq;
234     settings.speed = speed;
235     settings.bgType = bgType;
236 
237     settings.width = width;
238     settings.height = height;
239     settings.bpp = bpp;
240     if (fullscreen)
241 	settings.videoFlags |= SDL_FULLSCREEN;
242     else
243 	settings.videoFlags &= ~SDL_FULLSCREEN;
244 
245     antialiasGamma = aaGamma;
246 
247     for ( map<command,Key>::const_iterator it = rebindings.begin();
248 	    it != rebindings.end(); it++)
249 	settings.keybindings[it->first] = it->second;
250 }
251 
write() const252 void Config::write() const
253 {
254     ofstream f;
255     char* home = getenv("HOME");
256 
257     if (home != NULL)
258     {
259 	string homeStr = home;
260 	f.open((home + (string)"/.kuklomenosrc").c_str());
261     }
262     if (!f.is_open())
263 	f.open("./kuklomenosrc.txt");
264 
265     if (!f.is_open())
266 	fprintf(stderr, "Couldn't write config file.\n");
267     else
268     {
269 	ostringstream s;
270 	string bindingsString;
271 	int aanum = (useAA == AA_NO ? 0 :
272 		useAA == AA_YES ? 1 : 2);
273 	if (!rebindings.empty())
274 	{
275 	    bindingsString = '\n';
276 	    for ( map<command,Key>::const_iterator it = rebindings.begin();
277 		    it != rebindings.end(); it++)
278 		bindingsString += ( string("bind ") + shortCommandNames[it->first] +
279 		    string(" ") + (it->second).getString() + string("\n"));
280 	}
281 	s <<
282 	    "useAA: " << aanum << endl <<
283 	    "showGrid: " << showGrid << endl <<
284 	    "zoomEnabled: " << zoomEnabled << endl <<
285 	    "rotatingView: " << rotatingView << endl <<
286 	    "turnRate: " << turnRateFactor << endl <<
287 	    "fps: " << fps << endl <<
288 	    "showFPS: " << showFPS << endl <<
289 	    "speed: " << speed << endl <<
290 	    "sound: " << sound << endl <<
291 	    "volume: " << volume << endl <<
292 	    "freq: " << soundFreq << endl <<
293 	    "antialiasGamma: " << aaGamma << endl << endl <<
294 	    "mode: " << width << "x" << height << "x" << bpp << endl <<
295 	    "fullscreen: " << fullscreen << endl << endl <<
296 	    "background: " << bgTypeStrings[bgType] << endl << endl <<
297 	    "username: " << username << endl <<
298 	    "uuid: " << hex << uuid << dec << endl <<
299 	    bindingsString <<
300 	    endl << "# Warning: Do not edit following lines" << endl <<
301 	    "confversion: " << confFileVersion << endl <<
302 	    "data: " << obfuscatedRating(rating[0]) << " " << (obfuscatedRating(highestRating[0])*2+1337)
303 	    << " " << obfuscatedRating(rating[1]) << " " << (obfuscatedRating(highestRating[1])*2+1337+37)
304 	    << " " << obfuscatedRating(rating[2]) << " " << (obfuscatedRating(highestRating[2])*2+1337+37*2)
305 	    << endl;
306 	f << s.str();
307     }
308 }
309 
310 Config config;
311