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 843 by alloc, Tue Apr 30 01:06:45 2013 UTC vs.
Revision 1007 by alloc, Fri Jul 4 15:42:25 2014 UTC

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

Diff Legend

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