ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/Daodan/src/Daodan_Config.c
(Generate patch)

Comparing Daodan/src/Daodan_Config.c (file contents):
Revision 983 by alloc, Sun Mar 16 20:06:52 2014 UTC vs.
Revision 1163 by rossy, Sun Oct 24 02:50:48 2021 UTC

# Line 1 | Line 1
1   #include <windows.h>
2   #include <string.h>
3 + #include <time.h>
4  
5 < #include "Daodan_Cheater.h"
5 > #include "Daodan.h"
6   #include "Daodan_Config.h"
7   #include "Daodan_Patch.h"
8 < #include "Daodan_Utility.h"
8 > #include "Patches/Utility.h"
9  
10 < #include "Oni_Symbols.h"
10 > #include "Oni/Oni.h"
11 > #include "_Version.h"
12  
13   #include "Inifile_Reader.h"
14  
15 < bool patch_alttab = true;
16 < bool patch_argb8888 = true;
15 < bool patch_binkplay = true;
16 < bool patch_bsl = true;
17 < bool patch_cheater = true;
18 < bool patch_cheatsenabled = true;
19 < bool patch_cheattable = true;
20 < bool patch_clipcursor = true;
21 < bool patch_cooldowntimer = true;
22 < bool patch_daodandisplayenum = true;
23 < bool patch_directinput = true;
24 < bool patch_disablecmdline = true;
25 < bool patch_flatline = true;
26 < bool patch_fonttexturecache = true;
27 < bool patch_getcmdline = true;
28 < bool patch_hdscreens_lowres = true;
29 < bool patch_highres_console = true;
30 < bool patch_kickguns = false;
31 < bool patch_killvtune = true;
32 < bool patch_largetextures = true;
33 < bool patch_levelplugins = true;
34 < bool patch_newweapon = true;
35 < bool patch_nomultibyte = true;
36 < bool patch_optionsvisible = true;
37 < bool patch_particledisablebit = false;
38 < bool patch_pathfinding = true;
39 < bool patch_projaware = true;
40 < bool patch_safeprintf = true;
41 < bool patch_showalllasersights = false;
42 < bool patch_throwtest = false;
43 < bool patch_usedaodangl = true;
44 < bool patch_usegettickcount = true;
45 < bool patch_wpfadetime = true;
46 <
47 < bool opt_border = true;
48 < bool opt_gamma = true;
49 < bool opt_topmost = false;
50 < bool opt_usedaodanbsl = true;
15 > static const char* iniName = "daodan.ini";
16 > static const char* helpFile = "daodan_help.txt";
17  
18 < bool patch_chinese = true;
18 > static const char* defaultSection = "options";
19  
20 + static char invalidCurParamaters[2000] = "";
21 + static char invalidTotalParamaters[4000] = "";
22  
23 < enum {s_unknown, s_options, s_patch, s_bsl, s_language} ini_section;
23 > void DDrConfig_PrintHelp();
24 >
25 >
26 > ConfigSection_t config[] = {
27 >        { "", "Command line only", {
28 >                { "help",
29 >                        "Generates this help file.",
30 >                        C_CMD,
31 >                        {.intBoolVal = 0},
32 >                        {.callback = DDrConfig_PrintHelp} },
33 >                { 0, 0, 0, {0}, {0} }
34 >        } },
35 >        { "devmode", "Developer Mode", {
36 >                { "highres_console",
37 >                        "Fixes bug where console line becomes invisible at higher resolutions.",
38 >                        C_BOOL,
39 >                        {.intBoolVal = true},
40 >                        {.intBoolVal = true} },
41 >                { "showtriggervolumes",
42 >                        "Allows BSL variable \"show_triggervolumes\" and Ctrl+Shift+X (in devmode) to work.",
43 >                        C_BOOL,
44 >                        {.intBoolVal = true},
45 >                        {.intBoolVal = true} },
46 >                { 0, 0, 0, {0}, {0} }
47 >        } },
48 >        { "gameplay", "Gameplay", {
49 >                { "bindablecheats",
50 >                        "Allows cheats to be bound to keys. Requires 'customactions' and 'cheattable' to be true.",
51 >                        C_BOOL,
52 >                        {.intBoolVal = true},
53 >                        {.intBoolVal = true} },
54 >                { "characterawareness",
55 >                        "Makes AI remember the player.",
56 >                        C_BOOL,
57 >                        {.intBoolVal = true},
58 >                        {.intBoolVal = true} },
59 >                { "cheatsenabled",
60 >                        "Enables cheats without having to beat the game first.",
61 >                        C_BOOL,
62 >                        {.intBoolVal = true},
63 >                        {.intBoolVal = true} },
64 >                { "cheattable",
65 >                        "Replaces Oni's cheat table with table that includes new cheats including devmode.",
66 >                        C_BOOL,
67 >                        {.intBoolVal = true},
68 >                        {.intBoolVal = true} },
69 >                { "cooldowntimer",
70 >                        "Disables weapon cooldown exploit.",
71 >                        C_BOOL,
72 >                        {.intBoolVal = true},
73 >                        {.intBoolVal = true} },
74 >                { "customactions",
75 >                        "Allows more actions to be bound through Daodan.",
76 >                        C_BOOL,
77 >                        {.intBoolVal = true},
78 >                        {.intBoolVal = true} },
79 >                { "kickguns",
80 >                        "EXPERIMENTAL! Unfinished, do not use.",
81 >                        C_BOOL,
82 >                        {.intBoolVal = false},
83 >                        {.intBoolVal = false} },
84 >                { "pathfinding",
85 >                        "Size of pathfinding grid cache increased by eight times in order to prevent crashes in large levels.",
86 >                        C_BOOL,
87 >                        {.intBoolVal = true},
88 >                        {.intBoolVal = true} },
89 >                { "projaware",
90 >                        "Allows AI to dodge incoming gunfire properly.",
91 >                        C_BOOL,
92 >                        {.intBoolVal = true},
93 >                        {.intBoolVal = true} },
94 >                { "throwtest",
95 >                        "EXPERIMENTAL! Experiment with allowing enemies to be thrown over railings.",
96 >                        C_BOOL,
97 >                        {.intBoolVal = false},
98 >                        {.intBoolVal = false} },
99 >                { "wpfadetime",
100 >                        "Adds working function for existing BSL command wp_fadetime, sets fade time to 4800.",
101 >                        C_BOOL,
102 >                        {.intBoolVal = true},
103 >                        {.intBoolVal = true} },
104 >                { 0, 0, 0, {0}, {0} }
105 >        } },
106 >        { "graphics", "Graphics", {
107 >                { "binkplay",
108 >                        "Fix binkplay calls to use GDI and outro same mode as intro.",
109 >                        C_BOOL,
110 >                        {.intBoolVal = true},
111 >                        {.intBoolVal = true} },
112 >                { "daodangl",
113 >                        "Provides an improved windowed mode (-noswitch).",
114 >                        C_BOOL,
115 >                        {.intBoolVal = true},
116 >                        {.intBoolVal = true} },
117 >                { "displayenum",
118 >                        "Offers a more accurate list of available display modes in the Options menu.",
119 >                        C_BOOL,
120 >                        {.intBoolVal = true},
121 >                        {.intBoolVal = true} },
122 >                { "gamma",
123 >                        "Enable gamma slider in fullscreen, disable in windowed mode.",
124 >                        C_BOOL,
125 >                        {.intBoolVal = true},
126 >                        {.intBoolVal = true} },
127 >                { "newweap",
128 >                        "Standing above a weapon displays a message containing the weapon name and amount of ammo.",
129 >                        C_BOOL,
130 >                        {.intBoolVal = true},
131 >                        {.intBoolVal = true} },
132 >                { "optionsvisible",
133 >                        "Always show options button in main menu, even when pausing from a game.",
134 >                        C_BOOL,
135 >                        {.intBoolVal = true},
136 >                        {.intBoolVal = true} },
137 >                { "showalllasersights",
138 >                        "Show all (also enemies') weapon lasersights.",
139 >                        C_BOOL,
140 >                        {.intBoolVal = false},
141 >                        {.intBoolVal = false} },
142 >                { "widescreenportraits",
143 >                        "Prevents fly-in portraits from being stretched when playing in widescreen resolutions.",
144 >                        C_BOOL,
145 >                        {.intBoolVal = true},
146 >                        {.intBoolVal = true} },
147 >                { 0, 0, 0, {0}, {0} }
148 >        } },
149 >        { "language", "Language", {
150 >                { "chinese",
151 >                        "Allow for chinese fonts to be shown if the required DLL is available.",
152 >                        C_BOOL,
153 >                        {.intBoolVal = true},
154 >                        {.intBoolVal = true} },
155 >                { "fonttexturecache",
156 >                        "Doubles size of font texture cache.",
157 >                        C_BOOL,
158 >                        {.intBoolVal = true},
159 >                        {.intBoolVal = true} },
160 >                { "language",
161 >                        "Localization for hardcoded strings (e.g. \"Savepoints\").",
162 >                        C_STRING,
163 >                        {.stringVal = "en"},
164 >                        {.stringVal = "en"} },
165 >                { "nomultibyte",
166 >                        "Enables languages which use multibyte coding (such as Chinese).",
167 >                        C_BOOL,
168 >                        {.intBoolVal = true},
169 >                        {.intBoolVal = true} },
170 >                { 0, 0, 0, {0}, {0} }
171 >        } },
172 >        { "modding", "Modding", {
173 >                { "argb8888",
174 >                        "Allows using textures with ARGB8888.",
175 >                        C_BOOL,
176 >                        {.intBoolVal = true},
177 >                        {.intBoolVal = true} },
178 >                { "d_regen",
179 >                        "Enables script command d_regen (query/set regeneration for any character).",
180 >                        C_BOOL,
181 >                        {.intBoolVal = true},
182 >                        {.intBoolVal = true} },
183 >                { "daodanbsl",
184 >                        "Adds new BSL commands.",
185 >                        C_BOOL,
186 >                        {.intBoolVal = true},
187 >                        {.intBoolVal = true} },
188 >                { "hdscreens_lowres",
189 >                        "Allow HD intro/ending screens on game resolutions smaller than 1024x768.",
190 >                        C_BOOL,
191 >                        {.intBoolVal = true},
192 >                        {.intBoolVal = true} },
193 >                { "largetextures",
194 >                        "Textures up to 512x512 can be used.",
195 >                        C_BOOL,
196 >                        {.intBoolVal = true},
197 >                        {.intBoolVal = true} },
198 >                { "levelplugins",
199 >                        "Allows level files to be loaded which do not end in \"_Final\".",
200 >                        C_BOOL,
201 >                        {.intBoolVal = true},
202 >                        {.intBoolVal = true} },
203 >                { 0, 0, 0, {0}, {0} }
204 >        } },
205 >        { "oni", "Original Oni Options", {
206 >                { "debug",
207 >                        "Not useful, probably does nothing.",
208 >                        EXT_BOOL,
209 >                        {.intBoolVal = false },
210 >                        {.extBoolVal = &AKgDebug_DebugMaps } },
211 >                { "debugfiles",
212 >                        "Logs called BSL functions to script_debug.txt.",
213 >                        EXT_BOOL,
214 >                        {.intBoolVal = false },
215 >                        {.extBoolVal = &BFgDebugFileEnable } },
216 >                { "findsounds",
217 >                        "Not useful, extends output of sound_list_broken_links.",
218 >                        EXT_BOOL,
219 >                        {.intBoolVal = false },
220 >                        {.extBoolVal = &SSgSearchOnDisk } },
221 >                { "ignore_private_data",
222 >                        "Not useful, probably does nothing.",
223 >                        EXT_BOOL,
224 >                        {.intBoolVal = false },
225 >                        {.extBoolVal = &opt_ignore_private_data } },
226 >                { "sound",
227 >                        "Enable sound.",
228 >                        EXT_BOOL,
229 >                        {.intBoolVal = true },
230 >                        {.extBoolVal = &opt_sound } },
231 >                { "switch",
232 >                        "Switch to fullscreen instead of staying in a window.",
233 >                        EXT_BOOL,
234 >                        {.intBoolVal = true},
235 >                        {.extBoolVal = &M3gResolutionSwitch} },
236 >                { 0, 0, 0, {0}, {0} }
237 >        } },
238 >        { "windows", "Windows", {
239 >                { "alttab",
240 >                        "Allows to Alt-Tab out of Oni and use Windows key. May enable the screensaver as well.",
241 >                        C_BOOL,
242 >                        {.intBoolVal = true},
243 >                        {.intBoolVal = true} },
244 >                { "border",
245 >                        "Add a border if in windowed mode and \"usedaodangl\" patch is active.",
246 >                        C_BOOL,
247 >                        {.intBoolVal = true},
248 >                        {.intBoolVal = true} },
249 >                { "clipcursor",
250 >                        "Limit cursor to Oni's window.",
251 >                        C_BOOL,
252 >                        {.intBoolVal = true},
253 >                        {.intBoolVal = true} },
254 >                { "daodaninput",
255 >                        "New input system that reports input on every frame, supports Raw Input for mice.",
256 >                        C_BOOL,
257 >                        {.intBoolVal = true},
258 >                        {.intBoolVal = true} },
259 >                { "directinput",
260 >                        "Enforces the usage of DirectInput on every system. Should be off for Linux/Wine.",
261 >                        C_BOOL,
262 >                        {.intBoolVal = true},
263 >                        {.intBoolVal = true} },
264 >                { "mousesensitivity",
265 >                        "Multiplier for Oni's mouse sensitivity. 1.0 is Oni's default.",
266 >                        C_FLOAT,
267 >                        {.floatVal = 1.0f},
268 >                        {.floatVal = 1.0f} },
269 >                { "disablecmdline",
270 >                        "Disables Oni's existing command line parser as Daodan has its own.",
271 >                        C_BOOL,
272 >                        {.intBoolVal = true},
273 >                        {.intBoolVal = true} },
274 >                { "killvtune",
275 >                        "Prevent loading of vtuneapi.dll.",
276 >                        C_BOOL,
277 >                        {.intBoolVal = false},
278 >                        {.intBoolVal = false} },
279 >                { "safeprintf",
280 >                        "Replaces Oni's function that prints to startup.txt with a safer one.",
281 >                        C_BOOL,
282 >                        {.intBoolVal = true},
283 >                        {.intBoolVal = true} },
284 >                { "topmost",
285 >                        "Keep game window on top in windowed mode, even when switching applications.",
286 >                        C_BOOL,
287 >                        {.intBoolVal = false},
288 >                        {.intBoolVal = false} },
289 >                { "usegettickcount",
290 >                        "Replaces Oni's timing functions with more accurate ones.",
291 >                        C_BOOL,
292 >                        {.intBoolVal = true},
293 >                        {.intBoolVal = true} },
294 >                { 0, 0, 0, {0}, {0} }
295 >        } }
296 > };
297  
298 < bool DDrIniCallback(char* section, bool newsection, char* name, char* value)
298 >
299 > void DDrConfig_Print()
300 > {
301 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
302 >                for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
303 >                        switch (co->type) {
304 >                                case C_STRING:
305 >                                        STARTUPMESSAGE("Option %s.%s = %s (def %s)", config[s].name, co->name, co->value.stringVal, co->defaultValue.stringVal);
306 >                                        break;
307 >                                case EXT_BOOL:
308 >                                        STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, *co->value.extBoolVal, co->defaultValue.intBoolVal);
309 >                                        break;
310 >                                case C_CMD:
311 >                                        break;
312 >                                case C_FLOAT:
313 >                                        STARTUPMESSAGE("Option %s.%s = %f (def %f)", config[s].name, co->name, co->value.floatVal, co->defaultValue.floatVal);
314 >                                        break;
315 >                                default:
316 >                                        STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, co->value.intBoolVal, co->defaultValue.intBoolVal);
317 >                        }
318 >                }
319 >        }
320 > }
321 >
322 > void DDrConfig_PrintHelp()
323   {
324 <        if (newsection)
324 >        STARTUPMESSAGE("Writing Daodan help file (%s)", helpFile);
325 >
326 >        FILE* fp;
327 >        remove(helpFile);
328 >        fp = fopen(helpFile, "w");
329 >        if (fp)
330          {
331 <                if (!_stricmp(section, "options"))
332 <                        ini_section = s_options;
333 <                else if (!_stricmp(section, "patch"))
334 <                        ini_section = s_patch;
335 <                else if (!_stricmp(section, "bsl"))
336 <                        ini_section = s_bsl;
337 <                else if (!_stricmp(section, "language"))
338 <                        ini_section = s_language;
339 <                else
340 <                {
341 <                        ini_section = s_unknown;
342 <                        DDrStartupMessage("Daodan: Unrecognised ini section \"%s\"", section);
331 >                time_t rawtime;
332 >                struct tm* timeinfo;
333 >                char buffer[80];
334 >                time(&rawtime);
335 >                timeinfo = localtime(&rawtime);
336 >                strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
337 >                
338 >                fprintf(fp, "Daodan help - generated on %s for Daodan v."DAODAN_VERSION_STRING"\n\n", buffer);
339 >                fprintf(fp, "List of Daodan configuration parameters:\n");
340 >                for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
341 >                        fprintf(fp, "    %s - %s:\n", config[s].name, config[s].description);
342 >                        for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
343 >                                char* name = co->name;
344 >                                char* desc = co->description;
345 >                                const char* tName = DDrConfig_GetOptionTypeName(co->type);
346 >                                const char* val = DDrConfig_GetOptionValueString(co, 1);
347 >                                if (!val)
348 >                                        val = "";
349 >                                fprintf(fp, "        %-22s %6s=%-5s %s\n", name, tName, val, desc);
350 >                        }
351 >                        fprintf(fp, "\n");
352                  }
353 +                fprintf(fp, "\nConfiguration parameters can be either set in daodan.ini or passed on command line.\n\n");
354 +                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");
355 +                fprintf(fp, "    [sectionX]\n    parameterName = false\n");
356 +                fprintf(fp, "\nTo pass the parameter on the command line:\n");
357 +                fprintf(fp, "    Oni.exe -parameterName false\n");
358 +                fprintf(fp, "For bool parameters the value can be ommitted so it is regarded as \"true\":\n");
359 +                fprintf(fp, "    Oni.exe -parameterName\n");
360 +                fprintf(fp, "To disable a bool parameter you can prefix \"no\" to the parameter name like this:\n");
361 +                fprintf(fp, "    Oni.exe -noparameterName\n");
362 +
363 +                fclose(fp);
364          }
365 <        
76 <        switch (ini_section)
365 >        else
366          {
367 <                case s_options:
368 <                        if (!_stricmp(name, "border"))
369 <                                opt_border = !_stricmp(inifile_cleanstr(value), "true");
370 <                        else if (!_stricmp(name, "debug"))
371 <                                AKgDebug_DebugMaps = !_stricmp(inifile_cleanstr(value), "true");
372 <                        else if (!_stricmp(name, "debugfiles"))
373 <                                BFgDebugFileEnable = !_stricmp(inifile_cleanstr(value), "true");
374 <                        else if (!_stricmp(name, "findsounds"))
375 <                                SSgSearchOnDisk = !_stricmp(inifile_cleanstr(value), "true");
376 <                        else if (!_stricmp(name, "gamma"))
377 <                                opt_gamma = !_stricmp(inifile_cleanstr(value), "true");
378 <                        else if (!_stricmp(name, "ignore_private_data"))
379 <                                opt_ignore_private_data = !_stricmp(inifile_cleanstr(value), "true");
380 <                        else if (!_stricmp(name, "nomultibyte"))
381 <                                patch_nomultibyte = !_stricmp(inifile_cleanstr(value), "true");
382 <                        else if (!_stricmp(name, "sound"))
383 <                                opt_sound = !_stricmp(inifile_cleanstr(value), "true");
384 <                        else if (!_stricmp(name, "switch"))
385 <                                M3gResolutionSwitch = !_stricmp(inifile_cleanstr(value), "true");
386 <                        else if (!_stricmp(name, "topmost"))
387 <                                opt_topmost = !_stricmp(inifile_cleanstr(value), "true");
388 <                        else if (!_stricmp(name, "usedaodanbsl"))
389 <                                opt_usedaodanbsl = !_stricmp(inifile_cleanstr(value), "true");
390 <                        else
391 <                                DDrStartupMessage("Daodan: Unrecognised ini option \"%s\"", name);
392 <                        break;
393 <                case s_patch:
394 <                        if (!_stricmp(name, "alttab"))
395 <                                patch_alttab = !_stricmp(inifile_cleanstr(value), "true");
396 <                        else if (!_stricmp(name, "argb8888"))
397 <                                patch_argb8888 = !_stricmp(inifile_cleanstr(value), "true");
398 <                        else if (!_stricmp(name, "binkplay"))
399 <                                patch_binkplay = !_stricmp(inifile_cleanstr(value), "true");
400 <                        else if (!_stricmp(name, "bsl"))
401 <                                patch_bsl = !_stricmp(inifile_cleanstr(value), "true");
113 <                        else if (!_stricmp(name, "cheater"))
114 <                                patch_cheater = !_stricmp(inifile_cleanstr(value), "true");
115 <                        else if (!_stricmp(name, "cheatsenabled"))
116 <                                patch_cheatsenabled = !_stricmp(inifile_cleanstr(value), "true");
117 <                        else if (!_stricmp(name, "cheattable"))
118 <                                patch_cheattable = !_stricmp(inifile_cleanstr(value), "true");
119 <                        else if (!_stricmp(name, "clipcursor"))
120 <                                patch_clipcursor = !_stricmp(inifile_cleanstr(value), "true");
121 <                        else if (!_stricmp(name, "cooldowntimer"))
122 <                                patch_cooldowntimer = !_stricmp(inifile_cleanstr(value), "true");
123 <                        else if (!_stricmp(name, "daodandisplayenum"))
124 <                                patch_daodandisplayenum = !_stricmp(inifile_cleanstr(value), "true");
125 <                        else if (!_stricmp(name, "directinput"))
126 <                                patch_directinput = !_stricmp(inifile_cleanstr(value), "true");
127 <                        else if (!_stricmp(name, "disablecmdline"))
128 <                                patch_disablecmdline = !_stricmp(inifile_cleanstr(value), "true");
129 <                        else if (!_stricmp(name, "flatline"))
130 <                                patch_flatline = !_stricmp(inifile_cleanstr(value), "true");
131 <                        else if (!_stricmp(name, "fonttexturecache"))
132 <                                patch_fonttexturecache = !_stricmp(inifile_cleanstr(value), "true");
133 <                        else if (!_stricmp(name, "getcmdline"))
134 <                                patch_getcmdline = !_stricmp(inifile_cleanstr(value), "true");
135 <                        else if (!_stricmp(name, "hdscreens_lowres"))
136 <                                patch_hdscreens_lowres = !_stricmp(inifile_cleanstr(value), "true");
137 <                        else if (!_stricmp(name, "highres_console"))
138 <                                patch_highres_console = !_stricmp(inifile_cleanstr(value), "true");
139 <                        else if (!_stricmp(name, "kickguns"))
140 <                                patch_kickguns = !_stricmp(inifile_cleanstr(value), "true");
141 <                        else if (!_stricmp(name, "killvtune"))
142 <                                patch_killvtune = !_stricmp(inifile_cleanstr(value), "true");
143 <                        else if (!_stricmp(name, "largetextures"))
144 <                                patch_largetextures = !_stricmp(inifile_cleanstr(value), "true");
145 <                        else if (!_stricmp(name, "levelplugins"))
146 <                                patch_levelplugins = !_stricmp(inifile_cleanstr(value), "true");
147 <                        else if (!_stricmp(name, "nomultibyte"))
148 <                                patch_nomultibyte = !_stricmp(inifile_cleanstr(value), "true");
149 <                        else if (!_stricmp(name, "newweap"))
150 <                                patch_newweapon = !_stricmp(inifile_cleanstr(value), "true");
151 <                        else if (!_stricmp(name, "optionsvisible"))
152 <                                patch_optionsvisible = !_stricmp(inifile_cleanstr(value), "true");
153 <                        else if (!_stricmp(name, "particledisablebit"))
154 <                                patch_particledisablebit = !_stricmp(inifile_cleanstr(value), "true");
155 <                        else if (!_stricmp(name, "pathfinding"))
156 <                                patch_pathfinding = !_stricmp(inifile_cleanstr(value), "true");
157 <                        else if (!_stricmp(name, "projaware"))
158 <                                patch_projaware = !_stricmp(inifile_cleanstr(value), "true");
159 <                        else if (!_stricmp(name, "safeprintf"))
160 <                                patch_safeprintf = !_stricmp(inifile_cleanstr(value), "true");
161 <                        else if (!_stricmp(name, "showalllasersights"))
162 <                                patch_showalllasersights = !_stricmp(inifile_cleanstr(value), "true");
163 <                        else if (!_stricmp(name, "throwtest"))
164 <                                patch_throwtest = !_stricmp(inifile_cleanstr(value), "true");
165 <                        else if (!_stricmp(name, "usedaodangl"))
166 <                                patch_usedaodangl = !_stricmp(inifile_cleanstr(value), "true");
167 <                        else if (!_stricmp(name, "usegettickcount"))
168 <                                patch_usegettickcount = !_stricmp(inifile_cleanstr(value), "true");
169 <                        else if (!_stricmp(name, "wpfadetime"))
170 <                                patch_wpfadetime = !_stricmp(inifile_cleanstr(value), "true");
367 >                STARTUPMESSAGE("Writing Daodan help file failed", 0);
368 >        }
369 > }
370 >
371 > const char* DDrConfig_GetOptionTypeName(OptionType_t type)
372 > {
373 >        switch (type) {
374 >                case C_INT:
375 >                        return "Int";
376 >                case C_FLOAT:
377 >                        return "Float";
378 >                case C_BOOL:
379 >                        return "Bool";
380 >                case C_STRING:
381 >                        return "String";
382 >                case C_CMD:
383 >                        return "Cmd";
384 >                case EXT_BOOL:
385 >                        return "pBool";
386 >                default:
387 >                        return "unknown";
388 >        }
389 > }
390 >
391 > const char* DDrConfig_GetOptionValueString(ConfigOption_t* opt, char printdefault)
392 > {
393 >        OptionValue_t* optVal = (printdefault ? &opt->defaultValue : &opt->value);
394 >        int boolV = optVal->intBoolVal;
395 >        char* val = 0;
396 >        switch (opt->type) {
397 >                case C_STRING:
398 >                        return optVal->stringVal;
399 >                case EXT_BOOL:
400 >                        if (printdefault)
401 >                                return (boolV ? "true" : "false");
402                          else
403 <                                DDrStartupMessage("Daodan: Unrecognised ini patch \"%s\"", name);
404 <                        break;
405 <                case s_language:
406 <                        if (!_stricmp(name, "chinese"))
407 <                                patch_chinese = !_stricmp(inifile_cleanstr(value), "true");
408 <                        else if (!_stricmp(name, "blam"))
409 <                                DDrPatch__strdup((int*)(OniExe + 0x0010fb73), value);
410 <                        else if (!_stricmp(name, "damn"))
411 <                                DDrPatch__strdup((int*)(OniExe + 0x0010fb6e), value);
412 <                        else if (!_stricmp(name, "savepoint"))
413 <                        {
414 <                                char* str = _strdup(value);
415 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd730), (int)str);
416 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd738), (int)str);
417 <                        }
418 <                        else if (!_stricmp(name, "syndicatewarehouse"))
419 <                        {
420 <                                char* str = _strdup(value);
421 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd71a), (int)str);
422 <                                DDrPatch_Int32((int*)(OniExe + 0x0010ef75), (int)str);
423 <                        }
424 <                        else if (!_stricmp(name, "shapeshifter_on"))
425 <                                DDr_CheatTable[0].message_on = _strdup(value);
426 <                        else if (!_stricmp(name, "shapeshifter_off"))
427 <                                DDr_CheatTable[0].message_off = _strdup(value);
428 <                        else if (!_stricmp(name, "liveforever_on"))
429 <                                DDr_CheatTable[1].message_on = _strdup(value);
430 <                        else if (!_stricmp(name, "liveforever_off"))
431 <                                DDr_CheatTable[1].message_off = _strdup(value);
432 <                        else if (!_stricmp(name, "touchofdeath_on"))
433 <                                DDr_CheatTable[2].message_on = _strdup(value);
434 <                        else if (!_stricmp(name, "touchofdeath_off"))
435 <                                DDr_CheatTable[2].message_off = _strdup(value);
436 <                        else if (!_stricmp(name, "canttouchthis_on"))
437 <                                DDr_CheatTable[3].message_on = _strdup(value);
438 <                        else if (!_stricmp(name, "canttouchthis_off"))
439 <                                DDr_CheatTable[3].message_off = _strdup(value);
440 <                        else if (!_stricmp(name, "fatloot_on"))
441 <                                DDr_CheatTable[4].message_on = _strdup(value);
442 <                        else if (!_stricmp(name, "glassworld_on"))
443 <                                DDr_CheatTable[5].message_on = _strdup(value);
444 <                        else if (!_stricmp(name, "glassworld_off"))
445 <                                DDr_CheatTable[5].message_off = _strdup(value);
446 <                        else if (!_stricmp(name, "winlevel_on"))
447 <                                DDr_CheatTable[6].message_on = _strdup(value);
448 <                        else if (!_stricmp(name, "loselevel_on"))
449 <                                DDr_CheatTable[7].message_on = _strdup(value);
450 <                        else if (!_stricmp(name, "bighead_on"))
451 <                                DDr_CheatTable[8].message_on = _strdup(value);
452 <                        else if (!_stricmp(name, "bighead_off"))
453 <                                DDr_CheatTable[8].message_off = _strdup(value);
454 <                        else if (!_stricmp(name, "minime_on"))
455 <                                DDr_CheatTable[9].message_on = _strdup(value);
456 <                        else if (!_stricmp(name, "minime_off"))
457 <                                DDr_CheatTable[9].message_off = _strdup(value);
227 <                        else if (!_stricmp(name, "superammo_on"))
228 <                                DDr_CheatTable[10].message_on = _strdup(value);
229 <                        else if (!_stricmp(name, "superammo_off"))
230 <                                DDr_CheatTable[10].message_off = _strdup(value);
231 <                        else if (!_stricmp(name, "devmode_on"))
232 <                        {
233 <                                char* str = _strdup(value);
234 <                                DDr_CheatTable[11].message_on = str;
235 <                                DDr_CheatTable[cheat_x].message_on = str;
403 >                                return (*optVal->extBoolVal ? "true" : "false");
404 >                case C_BOOL:
405 >                        return (boolV ? "true" : "false");
406 >                case C_CMD:
407 >                        return 0;
408 >                case C_FLOAT:
409 >                        val = malloc(50);
410 >                        sprintf(val, "%f", optVal->floatVal);
411 >                        return val;
412 >                default:
413 >                        val = malloc(20);
414 >                        sprintf(val, "%d", boolV);
415 >                        return val;
416 >        }
417 > }
418 >
419 > char DDrConfig_NonDefaultOptionValue(ConfigOption_t* opt)
420 > {
421 >        switch (opt->type) {
422 >                case C_STRING:
423 >                        return _stricmp(opt->defaultValue.stringVal, opt->value.stringVal);
424 >                case EXT_BOOL:
425 >                        return !opt->defaultValue.intBoolVal != !*opt->value.extBoolVal;
426 >                case C_BOOL:
427 >                        return !opt->defaultValue.intBoolVal != !opt->value.intBoolVal;
428 >                case C_CMD:
429 >                        return 0;
430 >                case C_INT:
431 >                        return opt->defaultValue.intBoolVal != opt->value.intBoolVal;
432 >                case C_FLOAT:
433 >                        return opt->defaultValue.floatVal != opt->value.floatVal;
434 >        }
435 >        return 0;
436 > }
437 >
438 > static ConfigOption_t* DDrConfig_GetOption(const char* fullOptName)
439 > {
440 >        char section[50];
441 >        strcpy(section, fullOptName);
442 >
443 >        char* option = strchr(section, '.');
444 >        if (option == 0) {
445 >                STARTUPMESSAGE("Could not find option separator in \"%s\"", fullOptName);
446 >                return 0;
447 >        }
448 >        *option++ = 0;
449 >
450 >        char isWildcardSection = !_stricmp(section, "*");
451 >
452 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
453 >                if (isWildcardSection || !_stricmp(config[s].name, section)) {
454 >                        for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
455 >                                if (!_stricmp(co->name, option)) {
456 >                                        return co;
457 >                                }
458                          }
459 <                        else if (!_stricmp(name, "devmode_off"))
460 <                        {
461 <                                char* str = _strdup(value);
240 <                                DDr_CheatTable[11].message_off = str;
241 <                                DDr_CheatTable[cheat_x].message_off = str;
459 >                        if (!isWildcardSection) {
460 >                                STARTUPMESSAGE("Could not find option \"%s\" in section \"%s\"", option, section);
461 >                                return 0;
462                          }
463 <                        else if (!_stricmp(name, "reservoirdogs_on"))
244 <                                DDr_CheatTable[12].message_on = _strdup(value);
245 <                        else if (!_stricmp(name, "reservoirdogs_off"))
246 <                                DDr_CheatTable[12].message_off = _strdup(value);
247 <                        else if (!_stricmp(name, "roughjustice_on"))
248 <                                DDr_CheatTable[13].message_on = _strdup(value);
249 <                        else if (!_stricmp(name, "roughjustice_off"))
250 <                                DDr_CheatTable[13].message_off = _strdup(value);
251 <                        else if (!_stricmp(name, "chenille_on"))
252 <                                DDr_CheatTable[14].message_on = _strdup(value);
253 <                        else if (!_stricmp(name, "chenille_off"))
254 <                                DDr_CheatTable[14].message_off = _strdup(value);
255 <                        else if (!_stricmp(name, "behemoth_on"))
256 <                                DDr_CheatTable[15].message_on = _strdup(value);
257 <                        else if (!_stricmp(name, "behemoth_off"))
258 <                                DDr_CheatTable[15].message_off = _strdup(value);
259 <                        else if (!_stricmp(name, "elderrune_on"))
260 <                                DDr_CheatTable[16].message_on = _strdup(value);
261 <                        else if (!_stricmp(name, "elderrune_off"))
262 <                                DDr_CheatTable[16].message_off = _strdup(value);
263 <                        else if (!_stricmp(name, "moonshadow_on"))
264 <                                DDr_CheatTable[17].message_on = _strdup(value);
265 <                        else if (!_stricmp(name, "moonshadow_off"))
266 <                                DDr_CheatTable[17].message_off = _strdup(value);
267 <                        else if (!_stricmp(name, "munitionfrenzy_on"))
268 <                                DDr_CheatTable[18].message_on = _strdup(value);
269 <                        else if (!_stricmp(name, "fistsoflegend_on"))
270 <                                DDr_CheatTable[19].message_on = _strdup(value);
271 <                        else if (!_stricmp(name, "fistsoflegend_off"))
272 <                                DDr_CheatTable[19].message_off = _strdup(value);
273 <                        else if (!_stricmp(name, "killmequick_on"))
274 <                                DDr_CheatTable[20].message_on = _strdup(value);
275 <                        else if (!_stricmp(name, "killmequick_off"))
276 <                                DDr_CheatTable[20].message_off = _strdup(value);
277 <                        else if (!_stricmp(name, "carousel_on"))
278 <                                DDr_CheatTable[21].message_on = _strdup(value);
279 <                        else if (!_stricmp(name, "carousel_off"))
280 <                                DDr_CheatTable[21].message_off = _strdup(value);
281 <                        else
282 <                                DDrStartupMessage("Daodan: Unrecognised ini language item \"%s\"", name);
283 <                        break;
284 <                case s_bsl:
285 <                default:
286 <                        break;
463 >                }
464          }
465 <        
466 <        return true;
465 >        if (!isWildcardSection)
466 >                STARTUPMESSAGE("Could not find section \"%s\" for option \"%s\"", section, option);
467 >        else
468 >                STARTUPMESSAGE("Could not find option \"%s\"", option);
469 >        return 0;
470   }
471  
472 < void DDrConfig(int argc, char* argv[])
472 >
473 >
474 > ConfigOption_t* DDrConfig_GetOptOfType(const char* fullOptName, OptionType_t type)
475   {
476 <        int i;
477 <        char* section;
478 <        char* option;
479 <        bool falseoption;
476 >        ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
477 >        if (co == 0)
478 >                return 0;
479 >
480 >        if (co->type != type) {
481 >                STARTUPMESSAGE("Option \"%s\" is not of type %s", fullOptName, DDrConfig_GetOptionTypeName(type));
482 >                return 0;
483 >        }
484 >        return co;
485 > }
486 >
487  
488  
489 <        // Tell Oni to not load non levelX_final-files by default:
490 <        opt_ignore_private_data = false;
489 > void DDrConfig_InitExtBools()
490 > {
491 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
492 >                for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
493 >                        if (co->type == EXT_BOOL) {
494 >                                *co->value.extBoolVal = co->defaultValue.intBoolVal;
495 >                        }
496 >                }
497 >        }
498 > }
499  
303        // Enable sound by default:
304        opt_sound = true;
500  
501  
502 <        if (GetFileAttributes("daodan.ini") == INVALID_FILE_ATTRIBUTES)
502 > void DDrConfig_WriteIni()
503 > {
504 >        FILE* fp;
505 >        STARTUPMESSAGE("%s doesn't exist, creating", iniName);
506 >        fp = fopen(iniName, "w");
507 >        if (fp)
508          {
509 <                FILE* fp;
510 <                DDrStartupMessage("Daodan: daodan.ini doesn't exist, creating");
511 <                fp = fopen("daodan.ini", "w");
512 <                if (fp)
513 <                {
514 <                        fputs("[Options]\n", fp);
515 <                        fputs("[Patch]\n", fp);
516 <                        fputs("[BSL]\n", fp);
517 <                        fputs("[Language]\n", fp);
518 <                        fclose(fp);
509 >                for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
510 >                        if (strlen(config[s].name)) {
511 >                                fprintf(fp, "[%s]\n", config[s].name);
512 >                                for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
513 >                                        char* name = co->name;
514 >                                        const char* val = DDrConfig_GetOptionValueString(co, 0);
515 >                                        if (val && DDrConfig_NonDefaultOptionValue(co))
516 >                                                fprintf(fp, "%s = %s\n", name, val);
517 >                                }
518 >                                fprintf(fp, "\n");
519 >                        }
520                  }
521 +                fclose(fp);
522          }
523 <        
524 <        DDrStartupMessage("Daodan: Parsing daodan.ini...");
525 <        if (!inifile_read("daodan.ini", DDrIniCallback))
526 <                DDrStartupMessage("Daodan: Error reading daodan.ini, check your syntax!");
527 <        DDrStartupMessage("Daodan: Finished parsing");
523 >        else
524 >        {
525 >                STARTUPMESSAGE("Writing %s template file failed", iniName);
526 >        }
527 > }
528 >
529 >
530 > void DDrIniCallback(const char* section, const char* name, const char* value)
531 > {
532 >        char fullOptName[50];
533 >
534 >        if (!_stricmp(section, "patch"))
535 >                section = "patches";
536 >
537 >        strcpy(fullOptName, section);
538 >        fullOptName[strlen(section)] = '.';
539 >        strcpy(fullOptName+strlen(section)+1, name);
540  
541 +        ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
542 +
543 +        if (co)
544 +        {
545 +                char* buf = 0;
546 +                switch (co->type) {
547 +                        case C_INT:
548 +                                co->value.intBoolVal = strtol(value, NULL, 0);
549 +                                break;
550 +                        case C_FLOAT:
551 +                                co->value.floatVal = strtof(value, NULL);
552 +                                break;
553 +                        case C_BOOL:
554 +                                co->value.intBoolVal = !_stricmp(value, "true");
555 +                                break;
556 +                        case C_STRING:
557 +                                buf = malloc(strlen(value)+1);
558 +                                strcpy(buf, value);
559 +                                co->value.stringVal = buf;
560 +                                break;
561 +                        case C_CMD:
562 +                                co->value.callback();
563 +                                break;
564 +                        case EXT_BOOL:
565 +                                *(co->value.extBoolVal) = !_stricmp(value, "true");
566 +                                break;
567 +                        default:
568 +                                STARTUPMESSAGE("Config value type unknown: %d", co->type);
569 +                }
570 +        } else {
571 +                char buf[100];
572 +                if (!_stricmp(section, "*"))
573 +                        sprintf(buf, "  %s\n", name);
574 +                else
575 +                        sprintf(buf, "  %s.%s\n", section, name);
576 +                if (strlen(buf) + strlen(invalidCurParamaters) < sizeof(invalidCurParamaters) - 1) {
577 +                        strcpy(invalidCurParamaters + strlen(invalidCurParamaters), buf);
578 +                }
579 +        }
580 + }
581  
582  
583 <        DDrStartupMessage("Daodan: Parsing command line...");
584 <        for (i = 1; i < argc; i ++)
583 > bool DDrConfig_ParseCommandLine(int argc, char* argv[])
584 > {
585 >        for (int i = 1; i < argc; i ++)
586          {
587                  if (argv[i][0] == '-')
588                  {
589 <                        section = argv[i] + 1;
590 <                        if ((option = strchr(argv[i], '.')))
589 >                        char* option;
590 >                        bool invertedOption;
591 >
592 >                        option = argv[i]+1;
593 >
594 >                        invertedOption = (option[0] == 'n' || option[0] == 'N') && (option[1] == 'o' || option[1] == 'O');
595 >                        if (invertedOption)
596 >                                option += 2;
597 >
598 >                        if (i < (argc - 1) && argv[i+1][0] != '-')
599 >                        // Has value in next field
600                          {
601 <                                *option = '\0';
338 <                                falseoption = (option[1] == 'n' || option[1] == 'N') && (option[2] == 'o' || option[2] == 'O');
339 <                                if (i < (argc - 1) && argv[i + 1][0] != '-')
340 <                                        DDrIniCallback(section, true, option + 1, argv[++i]);
341 <                                else
342 <                                        DDrIniCallback(section, true, option + (falseoption ? 3 : 1), (falseoption ? "false" : "true"));
343 <                                *option = '.';
601 >                                DDrIniCallback("*", option, argv[++i]);
602                          }
603                          else
604 +                        // Implicit value
605                          {
606 <                                falseoption = (section[0] == 'n' || section[0] == 'N') && (section[1] == 'o' || section[1] == 'O');
348 <                                ini_section = s_options;
349 <                                if (i < (argc - 1) && argv[i + 1][0] != '-')
350 <                                        DDrIniCallback(NULL, false, section, argv[++i]);
351 <                                else
352 <                                        DDrIniCallback(NULL, false, section + (falseoption ? 2 : 0), (falseoption ? "false" : "true"));
606 >                                DDrIniCallback("*", option, (invertedOption ? "false" : "true"));
607                          }
608                  }
609                  else
610                  {
611 <                        DDrStartupMessage("Daodan: Parse error \"%s\"", argv[i]);
612 <                        break;
611 >                        STARTUPMESSAGE("Parse error \"%s\"", argv[i]);
612 >                        return false;
613                  }
614          }
615 <        DDrStartupMessage("Daodan: Finished parsing");
615 >        return true;
616 > }
617 >
618 > void DDrConfig(int argc, char* argv[])
619 > {
620 >        STARTUPMESSAGE("Initializing standard booleans", 0);
621 >        DDrConfig_InitExtBools();
622 >
623 >        if (GetFileAttributes(iniName) == INVALID_FILE_ATTRIBUTES)
624 >                DDrConfig_WriteIni();
625 >        
626 >        STARTUPMESSAGE("Parsing daodan.ini...", 0);
627 >        if (!Inifile_Read(iniName, DDrIniCallback))
628 >                STARTUPMESSAGE("Error reading daodan.ini, check your syntax!", 0);
629 >        STARTUPMESSAGE("Finished parsing", 0);
630 >
631 >        if (strlen(invalidCurParamaters) > 0)
632 >        {
633 >                sprintf(invalidTotalParamaters, "In %s:\n%s\n", iniName, invalidCurParamaters);
634 >                invalidCurParamaters[0] = 0;
635 >        }
636 >
637 >        STARTUPMESSAGE("Parsing command line...", 0);
638 >        DDrConfig_ParseCommandLine(argc, argv);
639 >        STARTUPMESSAGE("Finished parsing", 0);
640 >
641 >        if (strlen(invalidCurParamaters) > 0)
642 >        {
643 >                sprintf(invalidTotalParamaters, "%sOn command line:\n%s\n", invalidTotalParamaters, invalidCurParamaters);
644 >        }
645 >
646 >        if (strlen(invalidTotalParamaters) > 0)
647 >        {
648 >                char msg[4096];
649 >                sprintf(msg, "Invalid parameters given:\n%sContinue launching Oni?", invalidTotalParamaters);
650 >                int res = MessageBox(NULL, msg, "Parameters invalid", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1);
651 >                if (res == IDNO) {
652 >                        exit(0);
653 >                }
654 >        }
655 >
656 >        DDrConfig_WriteIni();
657 >
658 > //      DDrConfig_Print();
659   }
660  

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)