source: Daodan/src/Daodan_Config.c@ 996

Last change on this file since 996 was 996, checked in by alloc, 11 years ago

Daodan: Updated config help

File size: 16.1 KB
Line 
1#include <windows.h>
2#include <string.h>
3#include <time.h>
4
5#include "Daodan_Config.h"
6#include "Daodan_Patch.h"
7#include "Patches/Utility.h"
8
9#include "Oni/Oni.h"
10#include "_Version.h"
11
12#include "Inifile_Reader.h"
13
14#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
15
16static const char* iniName = "daodan.ini";
17static const char* helpFile = "daodan_help.txt";
18
19static const char* defaultSection = "options";
20
21static char invalidCurParamaters[1000] = "";
22static char invalidTotalParamaters[3000] = "";
23
24void DDrConfig_PrintHelp();
25
26
27ConfigSection_t config[] = {
28 { "patches", "Patches", {
29 { "alttab",
30 "Allows to Alt-Tab out of Oni and use Windows key. May enable the screensaver as well.",
31 C_BOOL,
32 {.intBoolVal = true},
33 {.intBoolVal = true} },
34 { "argb8888",
35 "Allows using textures with ARGB8888.",
36 C_BOOL,
37 {.intBoolVal = true},
38 {.intBoolVal = true} },
39 { "binkplay",
40 "Fix binkplay calls to use GDI and outro same mode as intro.",
41 C_BOOL,
42 {.intBoolVal = true},
43 {.intBoolVal = true} },
44 { "cheatsenabled",
45 "Enables cheats without having to beat the game first.",
46 C_BOOL,
47 {.intBoolVal = true},
48 {.intBoolVal = true} },
49 { "cheattable",
50 "Replaces Oni's cheat table with table that includes new cheats including devmode.",
51 C_BOOL,
52 {.intBoolVal = true},
53 {.intBoolVal = true} },
54 { "chinese",
55 "Allow for chinese fonts to be shown if the required DLL is available.",
56 C_BOOL,
57 {.intBoolVal = true},
58 {.intBoolVal = true} },
59 { "clipcursor",
60 "Limit cursor to Oni's window.",
61 C_BOOL,
62 {.intBoolVal = true},
63 {.intBoolVal = true} },
64 { "cooldowntimer",
65 "Disables weapon cooldown exploit.",
66 C_BOOL,
67 {.intBoolVal = true},
68 {.intBoolVal = true} },
69 { "d_regen",
70 "Enables script command d_regen (query/set regeneration for any character).",
71 C_BOOL,
72 {.intBoolVal = true},
73 {.intBoolVal = true} },
74 { "daodandisplayenum",
75 "Offers a more accurate list of available display modes in the Options menu.",
76 C_BOOL,
77 {.intBoolVal = true},
78 {.intBoolVal = true} },
79 { "directinput",
80 "Enforces the usage of DirectInput on every system. Should be off for Linux/Wine.",
81 C_BOOL,
82 {.intBoolVal = true},
83 {.intBoolVal = true} },
84 { "disablecmdline",
85 "Disables Oni's existing command line parser as Daodan has its own.",
86 C_BOOL,
87 {.intBoolVal = true},
88 {.intBoolVal = true} },
89 { "fonttexturecache",
90 "Doubles size of font texture cache.",
91 C_BOOL,
92 {.intBoolVal = true},
93 {.intBoolVal = true} },
94 { "hdscreens_lowres",
95 "Allow HD intro/ending screens on game resolutions smaller than 1024x768.",
96 C_BOOL,
97 {.intBoolVal = true},
98 {.intBoolVal = true} },
99 { "highres_console",
100 "Fixes bug where console line becomes invisible at higher resolutions.",
101 C_BOOL,
102 {.intBoolVal = true},
103 {.intBoolVal = true} },
104 { "kickguns",
105 "EXPERIMENTAL! Unfinished, do not use.",
106 C_BOOL,
107 {.intBoolVal = false},
108 {.intBoolVal = false} },
109 { "killvtune",
110 "Prevent loading of vtuneapi.dll.",
111 C_BOOL,
112 {.intBoolVal = false},
113 {.intBoolVal = false} },
114 { "largetextures",
115 "Textures up to 512x512 can be used.",
116 C_BOOL,
117 {.intBoolVal = true},
118 {.intBoolVal = true} },
119 { "levelplugins",
120 "Allows level files to be loaded which do not end in \"_Final\".",
121 C_BOOL,
122 {.intBoolVal = true},
123 {.intBoolVal = true} },
124 { "newweap",
125 "Standing above a weapon displays a message containing the weapon name and amount of ammo.",
126 C_BOOL,
127 {.intBoolVal = true},
128 {.intBoolVal = true} },
129 { "nomultibyte",
130 "Enables languages which use multibyte coding (such as Chinese).",
131 C_BOOL,
132 {.intBoolVal = true},
133 {.intBoolVal = true} },
134 { "optionsvisible",
135 "Always show options button in main menu, even when pausing from a game.",
136 C_BOOL,
137 {.intBoolVal = true},
138 {.intBoolVal = true} },
139 { "pathfinding",
140 "Size of pathfinding grid cache increased by eight times in order to prevent crashes in large levels.",
141 C_BOOL,
142 {.intBoolVal = true},
143 {.intBoolVal = true} },
144 { "projaware",
145 "Allows AI to dodge incoming gunfire properly.",
146 C_BOOL,
147 {.intBoolVal = true},
148 {.intBoolVal = true} },
149 { "safeprintf",
150 "Replaces Oni's function that prints to startup.txt with a safer one.",
151 C_BOOL,
152 {.intBoolVal = true},
153 {.intBoolVal = true} },
154 { "showalllasersights",
155 "Show all (also enemies') weapon lasersights.",
156 C_BOOL,
157 {.intBoolVal = false},
158 {.intBoolVal = false} },
159 { "showtriggervolumes",
160 "Allows BSL variable \"show_triggervolumes\" and Ctrl+Shift+X (in devmode) to work.",
161 C_BOOL,
162 {.intBoolVal = true},
163 {.intBoolVal = true} },
164 { "throwtest",
165 "EXPERIMENTAL! Experiment with allowing enemies to be thrown over railings.",
166 C_BOOL,
167 {.intBoolVal = false},
168 {.intBoolVal = false} },
169 { "usedaodanbsl",
170 "Adds new BSL commands.",
171 C_BOOL,
172 {.intBoolVal = true},
173 {.intBoolVal = true} },
174 { "usedaodangl",
175 "Provides an improved windowed mode (-noswitch).",
176 C_BOOL,
177 {.intBoolVal = true},
178 {.intBoolVal = true} },
179 { "usegettickcount",
180 "Replaces Oni's timing functions with more accurate ones.",
181 C_BOOL,
182 {.intBoolVal = true},
183 {.intBoolVal = true} },
184 { "widescreenportraits",
185 "Prevents fly-in portraits from being stretched when playing in widescreen resolutions.",
186 C_BOOL,
187 {.intBoolVal = true},
188 {.intBoolVal = true} },
189 { "wpfadetime",
190 "Adds working function for existing BSL command wp_fadetime, sets fade time to 4800.",
191 C_BOOL,
192 {.intBoolVal = true},
193 {.intBoolVal = true} },
194 { 0, 0, 0, {0}, {0} }
195 } },
196 { "options", "Options", {
197 { "border",
198 "Add a border if in windowed mode and \"usedaodangl\" patch is active.",
199 C_BOOL,
200 {.intBoolVal = true},
201 {.intBoolVal = true} },
202 { "debug",
203 "Not useful, probably does nothing.",
204 EXT_BOOL,
205 {.intBoolVal = false },
206 {.extBoolVal = &AKgDebug_DebugMaps } },
207 { "debugfiles",
208 "Logs called BSL functions to script_debug.txt.",
209 EXT_BOOL,
210 {.intBoolVal = false },
211 {.extBoolVal = &BFgDebugFileEnable } },
212 { "findsounds",
213 "Not useful, extends output of sound_list_broken_links.",
214 EXT_BOOL,
215 {.intBoolVal = false },
216 {.extBoolVal = &SSgSearchOnDisk } },
217 { "gamma",
218 "Enable gamma slider in fullscreen, disable in windowed mode.",
219 C_BOOL,
220 {.intBoolVal = true},
221 {.intBoolVal = true} },
222 { "help",
223 "Generates this help file.",
224 C_CMD,
225 {.intBoolVal = 0},
226 {.callback = DDrConfig_PrintHelp} },
227 { "ignore_private_data",
228 "Not useful, probably does nothing.",
229 EXT_BOOL,
230 {.intBoolVal = false },
231 {.extBoolVal = &opt_ignore_private_data } },
232 { "sound",
233 "Enable sound.",
234 EXT_BOOL,
235 {.intBoolVal = true },
236 {.extBoolVal = &opt_sound } },
237 { "switch",
238 "Switch to fullscreen instead of staying in a window.",
239 EXT_BOOL,
240 {.intBoolVal = true},
241 {.extBoolVal = &M3gResolutionSwitch} },
242 { "topmost",
243 "Keep game window on top in windowed mode, even when switching applications.",
244 C_BOOL,
245 {.intBoolVal = false},
246 {.intBoolVal = false} },
247 { "language",
248 "Localization for hardcoded strings (e.g. \"Savepoints\").",
249 C_STRING,
250 {.stringVal = "en"},
251 {.stringVal = "en"} },
252 { 0, 0, 0, {0}, {0} }
253 } }
254};
255
256
257void DDrConfig_Print()
258{
259 for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
260 for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
261 switch (co->type) {
262 case C_STRING:
263 STARTUPMESSAGE("Option %s.%s = %s (def %s)", config[s].name, co->name, co->value.stringVal, co->defaultValue.stringVal);
264 break;
265 case EXT_BOOL:
266 STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, *co->value.extBoolVal, co->defaultValue.intBoolVal);
267 break;
268 case C_CMD:
269 break;
270 default:
271 STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, co->value.intBoolVal, co->defaultValue.intBoolVal);
272 }
273 }
274 }
275}
276
277void DDrConfig_PrintHelp()
278{
279 STARTUPMESSAGE("Writing Daodan help file (%s)", helpFile);
280
281 FILE* fp;
282 remove(helpFile);
283 fp = fopen(helpFile, "w");
284 if (fp)
285 {
286 time_t rawtime;
287 struct tm* timeinfo;
288 char buffer[80];
289 time(&rawtime);
290 timeinfo = localtime(&rawtime);
291 strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
292
293 fprintf(fp, "Daodan help - generated on %s for Daodan v."DAODAN_VERSION_STRING"\n\n", buffer);
294 fprintf(fp, "List of Daodan configuration parameters:\n");
295 for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
296 fprintf(fp, " %s - %s:\n", config[s].name, config[s].description);
297 for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
298 char* name = co->name;
299 char* desc = co->description;
300 const char* tName = DDrConfig_GetOptionTypeName(co->type);
301 int boolV = co->defaultValue.intBoolVal;
302 char* val;
303 switch (co->type) {
304 case C_STRING:
305 val = co->defaultValue.stringVal;
306 break;
307 case EXT_BOOL:
308 val = (boolV ? "true" : "false");
309 break;
310 case C_BOOL:
311 val = (boolV ? "true" : "false");
312 break;
313 case C_CMD:
314 val = "";
315 break;
316 default:
317 val = malloc(20);
318 sprintf(val, "%d", boolV);
319 }
320 fprintf(fp, " %-22s %6s=%-5s %s\n", name, tName, val, desc);
321 }
322 fprintf(fp, "\n");
323 }
324 fprintf(fp, "\nConfiguration parameters can be either set in daodan.ini or passed on command line.\n\n");
325 fprintf(fp, "In daodan.ini each section of parameters has its own section in the ini file started by [section name]. Parameters are given within that section by their name only, followed by an equals sign and the desired value. Example:\n");
326 fprintf(fp, " [sectionX]\n parameterName = false\n");
327 fprintf(fp, "\nTo pass the parameter on the command line:\n");
328 fprintf(fp, " Oni.exe -sectionX.parameterName false\n");
329 fprintf(fp, "For bool parameters the value can be ommitted so it is regarded as \"true\":\n");
330 fprintf(fp, " Oni.exe -sectionX.parameterName\n");
331 fprintf(fp, "To disable a bool parameter you can prefix \"no\" to the parameter name like this:\n");
332 fprintf(fp, " Oni.exe -sectionX.noparameterName\n");
333 fprintf(fp, "If no section is given it is assumed to be \"%s\", e.g.\n", defaultSection);
334 fprintf(fp, " Oni.exe -%s.parametername\n", defaultSection);
335 fprintf(fp, "can simply be written as\n");
336 fprintf(fp, " Oni.exe -parametername\n");
337
338 fclose(fp);
339 }
340 else
341 {
342 STARTUPMESSAGE("Writing Daodan help file failed", 0);
343 }
344}
345
346const char* DDrConfig_GetOptionTypeName(OptionType_t type)
347{
348 switch (type) {
349 case C_INT:
350 return "Int";
351 case C_BOOL:
352 return "Bool";
353 case C_STRING:
354 return "String";
355 case C_CMD:
356 return "Cmd";
357 case EXT_BOOL:
358 return "pBool";
359 default:
360 return "unknown";
361 }
362}
363
364static ConfigOption_t* DDrConfig_GetOption(const char* fullOptName)
365{
366 char section[50];
367 strcpy(section, fullOptName);
368
369 char* option = strchr(section, '.');
370 if (option == 0) {
371 STARTUPMESSAGE("Could not find option separator in \"%s\"", fullOptName);
372 return 0;
373 }
374 *option++ = 0;
375
376 for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
377 if (!_stricmp(config[s].name, section)) {
378 for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
379 if (!_stricmp(co->name, option)) {
380 return co;
381 }
382 }
383 STARTUPMESSAGE("Could not find option \"%s\" in section \"%s\"", option, section);
384 return 0;
385 }
386 }
387 STARTUPMESSAGE("Could not find section \"%s\" for option \"%s\"", section, option);
388 return 0;
389}
390
391
392
393ConfigOption_t* DDrConfig_GetOptOfType(const char* fullOptName, OptionType_t type)
394{
395 ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
396 if (co == 0)
397 return 0;
398
399 if (co->type != type) {
400 STARTUPMESSAGE("Option \"%s\" is not of type %s", fullOptName, DDrConfig_GetOptionTypeName(type));
401 return 0;
402 }
403 return co;
404}
405
406
407
408void DDrConfig_InitExtBools()
409{
410 for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
411 for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
412 if (co->type == EXT_BOOL) {
413 *co->value.extBoolVal = co->defaultValue.intBoolVal;
414 }
415 }
416 }
417}
418
419
420
421void DDrConfig_WriteTemplateIni()
422{
423 FILE* fp;
424 STARTUPMESSAGE("%s doesn't exist, creating", iniName);
425 fp = fopen(iniName, "w");
426 if (fp)
427 {
428 for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
429 fprintf(fp, "[%s]\n", config[s].name);
430 }
431 fclose(fp);
432 }
433 else
434 {
435 STARTUPMESSAGE("Writing %s template file failed", iniName);
436 }
437}
438
439
440void DDrIniCallback(const char* section, const char* name, const char* value)
441{
442 static char curSection[20];
443 char fullOptName[50];
444
445 if (!_stricmp(section, "patch"))
446 section = "patches";
447
448 strcpy(curSection, section);
449
450 strcpy(fullOptName, curSection);
451 fullOptName[strlen(curSection)] = '.';
452 strcpy(fullOptName+strlen(curSection)+1, name);
453
454 ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
455
456 if (co)
457 {
458 char* buf = 0;
459 switch (co->type) {
460 case C_INT:
461 co->value.intBoolVal = strtol(value, NULL, 0);
462 break;
463 case C_BOOL:
464 co->value.intBoolVal = !_stricmp(value, "true");
465 break;
466 case C_STRING:
467 buf = malloc(strlen(value)+1);
468 strcpy(buf, value);
469 co->value.stringVal = buf;
470 break;
471 case C_CMD:
472 co->value.callback();
473 break;
474 case EXT_BOOL:
475 *(co->value.extBoolVal) = !_stricmp(value, "true");
476 break;
477 default:
478 STARTUPMESSAGE("Config value type unknown: %d", co->type);
479 }
480 } else {
481 char buf[50];
482 sprintf_s(buf, sizeof(buf), " %s.%s\n", section, name);
483 if (strlen(buf) + strlen(invalidCurParamaters) < sizeof(invalidCurParamaters) - 1) {
484 strcpy(invalidCurParamaters + strlen(invalidCurParamaters), buf);
485 }
486 }
487}
488
489
490bool DDrConfig_ParseCommandLine(int argc, char* argv[])
491{
492 for (int i = 1; i < argc; i ++)
493 {
494 if (argv[i][0] == '-')
495 {
496 const char* section;
497 char* optionsep;
498 char* option;
499 bool invertedOption;
500
501 if ((optionsep = strchr(argv[i], '.')))
502 // Is "section.option"
503 {
504 *optionsep = 0;
505 option = optionsep+1;
506 section = argv[i]+1;
507 }
508 else
509 // Is just "option"
510 {
511 section = defaultSection;
512 option = argv[i]+1;
513 }
514
515 invertedOption = (option[0] == 'n' || option[0] == 'N') && (option[1] == 'o' || option[1] == 'O');
516 if (invertedOption)
517 option += 2;
518
519 if (i < (argc - 1) && argv[i+1][0] != '-')
520 // Has value in next field
521 {
522 DDrIniCallback(section, option, argv[++i]);
523 }
524 else
525 // Implicit value
526 {
527 DDrIniCallback(section, option, (invertedOption ? "false" : "true"));
528 }
529
530 if (optionsep)
531 *optionsep = '.';
532 }
533 else
534 {
535 STARTUPMESSAGE("Parse error \"%s\"", argv[i]);
536 return false;
537 }
538 }
539 return true;
540}
541
542void DDrConfig(int argc, char* argv[])
543{
544 STARTUPMESSAGE("Initializing standard booleans", 0);
545 DDrConfig_InitExtBools();
546
547 if (GetFileAttributes(iniName) == INVALID_FILE_ATTRIBUTES)
548 DDrConfig_WriteTemplateIni();
549
550 STARTUPMESSAGE("Parsing daodan.ini...", 0);
551 if (!Inifile_Read(iniName, DDrIniCallback))
552 STARTUPMESSAGE("Error reading daodan.ini, check your syntax!", 0);
553 STARTUPMESSAGE("Finished parsing", 0);
554
555 if (strlen(invalidCurParamaters) > 0)
556 {
557 sprintf_s(invalidTotalParamaters, sizeof(invalidTotalParamaters), "In %s:\n%s\n", iniName, invalidCurParamaters);
558 invalidCurParamaters[0] = 0;
559 }
560
561 STARTUPMESSAGE("Parsing command line...", 0);
562 DDrConfig_ParseCommandLine(argc, argv);
563 STARTUPMESSAGE("Finished parsing", 0);
564
565 if (strlen(invalidCurParamaters) > 0)
566 {
567 sprintf_s(invalidTotalParamaters, sizeof(invalidTotalParamaters), "%sOn command line:\n%s\n", invalidTotalParamaters, invalidCurParamaters);
568 }
569
570 if (strlen(invalidTotalParamaters) > 0)
571 {
572 char msg[3200];
573 sprintf_s(msg, sizeof(msg), "Invalid parameters given:\n%sContinue launching Oni?", invalidTotalParamaters);
574 int res = MessageBox(NULL, msg, "Parameters invalid", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1);
575 if (res == IDNO) {
576 exit(0);
577 }
578 }
579
580// DDrConfig_Print();
581}
582
Note: See TracBrowser for help on using the repository browser.