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 994 by alloc, Mon Apr 7 10:33:27 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_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;
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 > void DDrConfig_PrintHelp();
22  
23 < bool DDrIniCallback(char* section, bool newsection, char* name, char* value)
23 >
24 > ConfigSection_t config[] = {
25 >        { "patches", "Patches", {
26 >                { "alttab",
27 >                        "Allows user to switch applications while in Oni (Alt-Tab) and use Windows key, however it may enable the screensaver as well.",
28 >                        C_BOOL,
29 >                        {.intBoolVal = true},
30 >                        {.intBoolVal = true} },
31 >                { "argb8888",
32 >                        "Textures using ARGB8888 can be used.",
33 >                        C_BOOL,
34 >                        {.intBoolVal = true},
35 >                        {.intBoolVal = true} },
36 >                { "binkplay",
37 >                        "Fix binkplay calls to use GDI and outro same mode as intro.",
38 >                        C_BOOL,
39 >                        {.intBoolVal = true},
40 >                        {.intBoolVal = true} },
41 >                { "bsl",
42 >                        "Enables d_regen (unfinished) and prevents fly-in portraits from being stretched when playing in widescreen resolutions.",
43 >                        C_BOOL,
44 >                        {.intBoolVal = true},
45 >                        {.intBoolVal = true} },
46 >                { "cheater",
47 >                        "Adds new cheat codes (see section below).",
48 >                        C_BOOL,
49 >                        {.intBoolVal = true},
50 >                        {.intBoolVal = true} },
51 >                { "cheatsenabled",
52 >                        "Enables cheats without having to beat the game first.",
53 >                        C_BOOL,
54 >                        {.intBoolVal = true},
55 >                        {.intBoolVal = true} },
56 >                { "cheattable",
57 >                        "Replaces Oni's cheat table with table that includes new cheats (see section below).",
58 >                        C_BOOL,
59 >                        {.intBoolVal = true},
60 >                        {.intBoolVal = true} },
61 >                { "chinese",
62 >                        "Allow for chinese fonts to be shown.",
63 >                        C_BOOL,
64 >                        {.intBoolVal = true},
65 >                        {.intBoolVal = true} },
66 >                { "clipcursor",
67 >                        "Limit cursor to Oni's window.",
68 >                        C_BOOL,
69 >                        {.intBoolVal = true},
70 >                        {.intBoolVal = true} },
71 >                { "cooldowntimer",
72 >                        "Disables weapon cooldown exploit.",
73 >                        C_BOOL,
74 >                        {.intBoolVal = true},
75 >                        {.intBoolVal = true} },
76 >                { "daodandisplayenum",
77 >                        "Offers more display modes in the Options menu.",
78 >                        C_BOOL,
79 >                        {.intBoolVal = true},
80 >                        {.intBoolVal = true} },
81 >                { "directinput",
82 >                        "Forces on DirectInput.",
83 >                        C_BOOL,
84 >                        {.intBoolVal = true},
85 >                        {.intBoolVal = true} },
86 >                { "disablecmdline",
87 >                        "Replaces existing command line parser with Daodan's in order to add new commands. Meant to be used with getcmdline.",
88 >                        C_BOOL,
89 >                        {.intBoolVal = true},
90 >                        {.intBoolVal = true} },
91 >                { "fonttexturecache",
92 >                        "Doubles size of font texture cache.",
93 >                        C_BOOL,
94 >                        {.intBoolVal = true},
95 >                        {.intBoolVal = true} },
96 >                { "getcmdline",
97 >                        "Replaces existing command line parser with Daodan's in order to add new commands. Meant to be used with disablecmdline.",
98 >                        C_BOOL,
99 >                        {.intBoolVal = true},
100 >                        {.intBoolVal = true} },
101 >                { "hdscreens_lowres",
102 >                        "Allow HD screens with resolution < 1024*768.",
103 >                        C_BOOL,
104 >                        {.intBoolVal = true},
105 >                        {.intBoolVal = true} },
106 >                { "highres_console",
107 >                        "Fixes bug where console line becomes invisible at higher resolutions.",
108 >                        C_BOOL,
109 >                        {.intBoolVal = true},
110 >                        {.intBoolVal = true} },
111 >                { "kickguns",
112 >                        "Unfinished, do not use.",
113 >                        C_BOOL,
114 >                        {.intBoolVal = false},
115 >                        {.intBoolVal = false} },
116 >                { "largetextures",
117 >                        "Textures up to 512x512 can be used.",
118 >                        C_BOOL,
119 >                        {.intBoolVal = true},
120 >                        {.intBoolVal = true} },
121 >                { "levelplugins",
122 >                        "Allows level files to be loaded from the GDF which do not end in \"_Final\".",
123 >                        C_BOOL,
124 >                        {.intBoolVal = true},
125 >                        {.intBoolVal = true} },
126 >                { "newweap",
127 >                        "Picking up a weapon displays a message containing the weapon name and amount of ammo.",
128 >                        C_BOOL,
129 >                        {.intBoolVal = true},
130 >                        {.intBoolVal = true} },
131 >                { "nomultibyte",
132 >                        "Enables languages which use multibyte coding (such as Chinese).",
133 >                        C_BOOL,
134 >                        {.intBoolVal = true},
135 >                        {.intBoolVal = true} },
136 >                { "optionsvisible",
137 >                        "Always show options button in main menu, even when pausing from a game.",
138 >                        C_BOOL,
139 >                        {.intBoolVal = true},
140 >                        {.intBoolVal = true} },
141 >                { "particledisablebit",
142 >                        "Unlocks particle action disabling/enabling bits for all events so that a particle event can occur multiple times.",
143 >                        C_BOOL,
144 >                        {.intBoolVal = false},
145 >                        {.intBoolVal = false} },
146 >                { "pathfinding",
147 >                        "Multiplies size of pathfinding grid cache by eight in order to prevent crashes in large levels.",
148 >                        C_BOOL,
149 >                        {.intBoolVal = true},
150 >                        {.intBoolVal = true} },
151 >                { "projaware",
152 >                        "Allows AI to dodge incoming gunfire properly.",
153 >                        C_BOOL,
154 >                        {.intBoolVal = true},
155 >                        {.intBoolVal = true} },
156 >                { "safeprintf",
157 >                        "Replaces Oni's function that prints to startup.txt with a safer one.",
158 >                        C_BOOL,
159 >                        {.intBoolVal = true},
160 >                        {.intBoolVal = true} },
161 >                { "showalllasersights",
162 >                        "Show all (also enemies') weapon lasersights.",
163 >                        C_BOOL,
164 >                        {.intBoolVal = false},
165 >                        {.intBoolVal = false} },
166 >                { "showtriggervolumes",
167 >                        "Allows BSL variable \"show_triggervolumes\" to work when set to 1.",
168 >                        C_BOOL,
169 >                        {.intBoolVal = true},
170 >                        {.intBoolVal = true} },
171 >                { "throwtest",
172 >                        "Not recommended for use; experiment with allowing enemies to be thrown over railings.",
173 >                        C_BOOL,
174 >                        {.intBoolVal = false},
175 >                        {.intBoolVal = false} },
176 >                { "usedaodangl",
177 >                        "Provides an improved windowed mode (-noswitch); this patch is known to break the hiding of the Windows taskbar in fullscreen mode.",
178 >                        C_BOOL,
179 >                        {.intBoolVal = true},
180 >                        {.intBoolVal = true} },
181 >                { "usegettickcount",
182 >                        "Replaces Oni's timing functions with more accurate ones.",
183 >                        C_BOOL,
184 >                        {.intBoolVal = true},
185 >                        {.intBoolVal = true} },
186 >                { "wpfadetime",
187 >                        "Adds working function for existing BSL command wp_fadetime, sets fade time to 4800.",
188 >                        C_BOOL,
189 >                        {.intBoolVal = true},
190 >                        {.intBoolVal = true} },
191 >                { 0, 0, 0, {0}, {0} }
192 >        } },
193 >        { "options", "Options", {
194 >                { "border",
195 >                        "If \"windowhack\" patch is active, make sure game window has border in windowed mode.",
196 >                        C_BOOL,
197 >                        {.intBoolVal = true},
198 >                        {.intBoolVal = true} },
199 >                { "debug",
200 >                        "???",
201 >                        EXT_BOOL,
202 >                        {.intBoolVal = false },
203 >                        {.extBoolVal = &AKgDebug_DebugMaps } },
204 >                { "debugfiles",
205 >                        "???",
206 >                        EXT_BOOL,
207 >                        {.intBoolVal = false },
208 >                        {.extBoolVal = &BFgDebugFileEnable } },
209 >                { "findsounds",
210 >                        "???",
211 >                        EXT_BOOL,
212 >                        {.intBoolVal = false },
213 >                        {.extBoolVal = &SSgSearchOnDisk } },
214 >                { "gamma",
215 >                        "Enable gamma slider in fullscreen.",
216 >                        C_BOOL,
217 >                        {.intBoolVal = true},
218 >                        {.intBoolVal = true} },
219 >                { "help",
220 >                        "Generates this help file.",
221 >                        C_CMD,
222 >                        {.intBoolVal = 0},
223 >                        {.callback = DDrConfig_PrintHelp} },
224 >                { "ignore_private_data",
225 >                        "? No effect ?",
226 >                        EXT_BOOL,
227 >                        {.intBoolVal = false },
228 >                        {.extBoolVal = &opt_ignore_private_data } },
229 >                { "sound",
230 >                        "???",
231 >                        EXT_BOOL,
232 >                        {.intBoolVal = true },
233 >                        {.extBoolVal = &opt_sound } },
234 >                { "switch",
235 >                        "Always switch screen to resolution on Oni's Options screen, making the game fullscreen; opposite of Oni's built-in argument \"noswitch\".",
236 >                        EXT_BOOL,
237 >                        {.intBoolVal = true},
238 >                        {.extBoolVal = &M3gResolutionSwitch} },
239 >                { "topmost",
240 >                        "Keep game window on top in windowed mode, even when switching applications.",
241 >                        C_BOOL,
242 >                        {.intBoolVal = false},
243 >                        {.intBoolVal = false} },
244 >                { "usedaodanbsl",
245 >                        "Adds new BSL commands (see below).",
246 >                        C_BOOL,
247 >                        {.intBoolVal = true},
248 >                        {.intBoolVal = true} },
249 >                { "language",
250 >                        "Localization for hardcoded strings (e.g. \"Savepoints\").",
251 >                        C_STRING,
252 >                        {.stringVal = "en"},
253 >                        {.stringVal = "en"} },
254 >                { 0, 0, 0, {0}, {0} }
255 >        } }
256 > };
257 >
258 >
259 > void DDrConfig_Print()
260   {
261 <        if (newsection)
262 <        {
263 <                if (!_stricmp(section, "options"))
264 <                        ini_section = s_options;
265 <                else if (!_stricmp(section, "patch"))
266 <                        ini_section = s_patch;
267 <                else if (!_stricmp(section, "bsl"))
268 <                        ini_section = s_bsl;
269 <                else if (!_stricmp(section, "language"))
270 <                        ini_section = s_language;
271 <                else
272 <                {
273 <                        ini_section = s_unknown;
274 <                        DDrStartupMessage("Daodan: Unrecognised ini section \"%s\"", section);
261 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
262 >                for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
263 >                        switch (co->type) {
264 >                                case C_STRING:
265 >                                        STARTUPMESSAGE("Option %s.%s = %s (def %s)", config[s].name, co->name, co->value.stringVal, co->defaultValue.stringVal);
266 >                                        break;
267 >                                case EXT_BOOL:
268 >                                        STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, *co->value.extBoolVal, co->defaultValue.intBoolVal);
269 >                                        break;
270 >                                case C_CMD:
271 >                                        break;
272 >                                default:
273 >                                        STARTUPMESSAGE("Option %s.%s = %d (def %d)", config[s].name, co->name, co->value.intBoolVal, co->defaultValue.intBoolVal);
274 >                        }
275                  }
276          }
277 <        
278 <        switch (ini_section)
277 > }
278 >
279 > void DDrConfig_PrintHelp()
280 > {
281 >        STARTUPMESSAGE("Writing Daodan help file (%s)", helpFile);
282 >
283 >        FILE* fp;
284 >        remove(helpFile);
285 >        fp = fopen(helpFile, "w");
286 >        if (fp)
287          {
288 <                case s_options:
289 <                        if (!_stricmp(name, "border"))
290 <                                opt_border = !_stricmp(inifile_cleanstr(value), "true");
291 <                        else if (!_stricmp(name, "debug"))
292 <                                AKgDebug_DebugMaps = !_stricmp(inifile_cleanstr(value), "true");
293 <                        else if (!_stricmp(name, "debugfiles"))
294 <                                BFgDebugFileEnable = !_stricmp(inifile_cleanstr(value), "true");
295 <                        else if (!_stricmp(name, "findsounds"))
296 <                                SSgSearchOnDisk = !_stricmp(inifile_cleanstr(value), "true");
297 <                        else if (!_stricmp(name, "gamma"))
298 <                                opt_gamma = !_stricmp(inifile_cleanstr(value), "true");
299 <                        else if (!_stricmp(name, "ignore_private_data"))
300 <                                opt_ignore_private_data = !_stricmp(inifile_cleanstr(value), "true");
301 <                        else if (!_stricmp(name, "nomultibyte"))
302 <                                patch_nomultibyte = !_stricmp(inifile_cleanstr(value), "true");
303 <                        else if (!_stricmp(name, "sound"))
304 <                                opt_sound = !_stricmp(inifile_cleanstr(value), "true");
305 <                        else if (!_stricmp(name, "switch"))
306 <                                M3gResolutionSwitch = !_stricmp(inifile_cleanstr(value), "true");
307 <                        else if (!_stricmp(name, "topmost"))
308 <                                opt_topmost = !_stricmp(inifile_cleanstr(value), "true");
309 <                        else if (!_stricmp(name, "usedaodanbsl"))
310 <                                opt_usedaodanbsl = !_stricmp(inifile_cleanstr(value), "true");
311 <                        else
312 <                                DDrStartupMessage("Daodan: Unrecognised ini option \"%s\"", name);
313 <                        break;
314 <                case s_patch:
315 <                        if (!_stricmp(name, "alttab"))
316 <                                patch_alttab = !_stricmp(inifile_cleanstr(value), "true");
317 <                        else if (!_stricmp(name, "argb8888"))
318 <                                patch_argb8888 = !_stricmp(inifile_cleanstr(value), "true");
319 <                        else if (!_stricmp(name, "binkplay"))
320 <                                patch_binkplay = !_stricmp(inifile_cleanstr(value), "true");
321 <                        else if (!_stricmp(name, "bsl"))
322 <                                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");
171 <                        else
172 <                                DDrStartupMessage("Daodan: Unrecognised ini patch \"%s\"", name);
173 <                        break;
174 <                case s_language:
175 <                        if (!_stricmp(name, "chinese"))
176 <                                patch_chinese = !_stricmp(inifile_cleanstr(value), "true");
177 <                        else if (!_stricmp(name, "blam"))
178 <                                DDrPatch__strdup((int*)(OniExe + 0x0010fb73), value);
179 <                        else if (!_stricmp(name, "damn"))
180 <                                DDrPatch__strdup((int*)(OniExe + 0x0010fb6e), value);
181 <                        else if (!_stricmp(name, "savepoint"))
182 <                        {
183 <                                char* str = _strdup(value);
184 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd730), (int)str);
185 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd738), (int)str);
288 >                time_t rawtime;
289 >                struct tm* timeinfo;
290 >                char buffer[80];
291 >                time(&rawtime);
292 >                timeinfo = localtime(&rawtime);
293 >                strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
294 >                
295 >                fprintf(fp, "Daodan help - generated on %s for Daodan v."DAODAN_VERSION_STRING"\n\n", buffer);
296 >                fprintf(fp, "List of Daodan configuration parameters:\n");
297 >                for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
298 >                        fprintf(fp, "    %s - %s:\n", config[s].name, config[s].description);
299 >                        for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
300 >                                char* name = co->name;
301 >                                char* desc = co->description;
302 >                                const char* tName = DDrConfig_GetOptionTypeName(co->type);
303 >                                int boolV = co->defaultValue.intBoolVal;
304 >                                char* val;
305 >                                switch (co->type) {
306 >                                        case C_STRING:
307 >                                                val = co->defaultValue.stringVal;
308 >                                                break;
309 >                                        case EXT_BOOL:
310 >                                                val = (boolV ? "true" : "false");
311 >                                                break;
312 >                                        case C_BOOL:
313 >                                                val = (boolV ? "true" : "false");
314 >                                                break;
315 >                                        case C_CMD:
316 >                                                val = "";
317 >                                                break;
318 >                                        default:
319 >                                                val = malloc(20);
320 >                                                sprintf(val, "%d", boolV);
321 >                                }
322 >                                fprintf(fp, "        %-22s %6s=%-5s %s\n", name, tName, val, desc);
323                          }
324 <                        else if (!_stricmp(name, "syndicatewarehouse"))
325 <                        {
326 <                                char* str = _strdup(value);
327 <                                DDrPatch_Int32((int*)(OniExe + 0x000fd71a), (int)str);
328 <                                DDrPatch_Int32((int*)(OniExe + 0x0010ef75), (int)str);
329 <                        }
330 <                        else if (!_stricmp(name, "shapeshifter_on"))
331 <                                DDr_CheatTable[0].message_on = _strdup(value);
332 <                        else if (!_stricmp(name, "shapeshifter_off"))
333 <                                DDr_CheatTable[0].message_off = _strdup(value);
334 <                        else if (!_stricmp(name, "liveforever_on"))
335 <                                DDr_CheatTable[1].message_on = _strdup(value);
336 <                        else if (!_stricmp(name, "liveforever_off"))
337 <                                DDr_CheatTable[1].message_off = _strdup(value);
338 <                        else if (!_stricmp(name, "touchofdeath_on"))
339 <                                DDr_CheatTable[2].message_on = _strdup(value);
340 <                        else if (!_stricmp(name, "touchofdeath_off"))
341 <                                DDr_CheatTable[2].message_off = _strdup(value);
342 <                        else if (!_stricmp(name, "canttouchthis_on"))
343 <                                DDr_CheatTable[3].message_on = _strdup(value);
344 <                        else if (!_stricmp(name, "canttouchthis_off"))
345 <                                DDr_CheatTable[3].message_off = _strdup(value);
346 <                        else if (!_stricmp(name, "fatloot_on"))
347 <                                DDr_CheatTable[4].message_on = _strdup(value);
348 <                        else if (!_stricmp(name, "glassworld_on"))
349 <                                DDr_CheatTable[5].message_on = _strdup(value);
350 <                        else if (!_stricmp(name, "glassworld_off"))
351 <                                DDr_CheatTable[5].message_off = _strdup(value);
352 <                        else if (!_stricmp(name, "winlevel_on"))
353 <                                DDr_CheatTable[6].message_on = _strdup(value);
354 <                        else if (!_stricmp(name, "loselevel_on"))
355 <                                DDr_CheatTable[7].message_on = _strdup(value);
356 <                        else if (!_stricmp(name, "bighead_on"))
357 <                                DDr_CheatTable[8].message_on = _strdup(value);
358 <                        else if (!_stricmp(name, "bighead_off"))
359 <                                DDr_CheatTable[8].message_off = _strdup(value);
360 <                        else if (!_stricmp(name, "minime_on"))
224 <                                DDr_CheatTable[9].message_on = _strdup(value);
225 <                        else if (!_stricmp(name, "minime_off"))
226 <                                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;
236 <                        }
237 <                        else if (!_stricmp(name, "devmode_off"))
238 <                        {
239 <                                char* str = _strdup(value);
240 <                                DDr_CheatTable[11].message_off = str;
241 <                                DDr_CheatTable[cheat_x].message_off = str;
242 <                        }
243 <                        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:
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 -sectionX.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 -sectionX.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 -sectionX.noparameterName\n");
335 >                fprintf(fp, "If no section is given it is assumed to be \"%s\", e.g.\n", defaultSection);
336 >                fprintf(fp, "    Oni.exe -%s.parametername\n", defaultSection);
337 >                fprintf(fp, "can simply be written as\n");
338 >                fprintf(fp, "    Oni.exe -parametername\n");
339 >
340 >                fclose(fp);
341 >        }
342 >        else
343 >        {
344 >                STARTUPMESSAGE("Writing Daodan help file failed", 0);
345 >        }
346 > }
347 >
348 > const char* DDrConfig_GetOptionTypeName(OptionType_t type)
349 > {
350 >        switch (type) {
351 >                case C_INT:
352 >                        return "Int";
353 >                case C_BOOL:
354 >                        return "Bool";
355 >                case C_STRING:
356 >                        return "String";
357 >                case C_CMD:
358 >                        return "Cmd";
359 >                case EXT_BOOL:
360 >                        return "pBool";
361                  default:
362 <                        break;
362 >                        return "unknown";
363          }
288        
289        return true;
364   }
365  
366 < void DDrConfig(int argc, char* argv[])
366 > static ConfigOption_t* DDrConfig_GetOption(const char* fullOptName)
367 > {
368 >        char section[50];
369 >        strcpy(section, fullOptName);
370 >
371 >        char* option = strchr(section, '.');
372 >        if (option == 0) {
373 >                STARTUPMESSAGE("Could not find option separator in \"%s\"", fullOptName);
374 >                return 0;
375 >        }
376 >        *option++ = 0;
377 >
378 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
379 >                if (!_stricmp(config[s].name, section)) {
380 >                        for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
381 >                                if (!_stricmp(co->name, option)) {
382 >                                        return co;
383 >                                }
384 >                        }
385 >                        STARTUPMESSAGE("Could not find option \"%s\" in section \"%s\"", option, section);
386 >                        return 0;
387 >                }
388 >        }
389 >        STARTUPMESSAGE("Could not find section \"%s\" for option \"%s\"", section, option);
390 >        return 0;
391 > }
392 >
393 >
394 >
395 > ConfigOption_t* DDrConfig_GetOptOfType(const char* fullOptName, OptionType_t type)
396   {
397 <        int i;
398 <        char* section;
399 <        char* option;
400 <        bool falseoption;
397 >        ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
398 >        if (co == 0)
399 >                return 0;
400 >
401 >        if (co->type != type) {
402 >                STARTUPMESSAGE("Option \"%s\" is not of type %s", fullOptName, DDrConfig_GetOptionTypeName(type));
403 >                return 0;
404 >        }
405 >        return co;
406 > }
407 >
408  
409  
410 <        // Tell Oni to not load non levelX_final-files by default:
411 <        opt_ignore_private_data = false;
410 > void DDrConfig_InitExtBools()
411 > {
412 >        for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
413 >                for (ConfigOption_t* co = config[s].options; co->name != 0; co++) {
414 >                        if (co->type == EXT_BOOL) {
415 >                                *co->value.extBoolVal = co->defaultValue.intBoolVal;
416 >                        }
417 >                }
418 >        }
419 > }
420  
303        // Enable sound by default:
304        opt_sound = true;
421  
422  
423 <        if (GetFileAttributes("daodan.ini") == INVALID_FILE_ATTRIBUTES)
423 > void DDrConfig_WriteTemplateIni()
424 > {
425 >        FILE* fp;
426 >        STARTUPMESSAGE("%s doesn't exist, creating", iniName);
427 >        fp = fopen(iniName, "w");
428 >        if (fp)
429          {
430 <                FILE* fp;
431 <                DDrStartupMessage("Daodan: daodan.ini doesn't exist, creating");
311 <                fp = fopen("daodan.ini", "w");
312 <                if (fp)
313 <                {
314 <                        fputs("[Options]\n", fp);
315 <                        fputs("[Patch]\n", fp);
316 <                        fputs("[BSL]\n", fp);
317 <                        fputs("[Language]\n", fp);
318 <                        fclose(fp);
430 >                for (unsigned int s = 0; s < ARRAY_SIZE(config); s++) {
431 >                        fprintf(fp, "[%s]\n", config[s].name);
432                  }
433 +                fclose(fp);
434          }
435 <        
436 <        DDrStartupMessage("Daodan: Parsing daodan.ini...");
437 <        if (!inifile_read("daodan.ini", DDrIniCallback))
438 <                DDrStartupMessage("Daodan: Error reading daodan.ini, check your syntax!");
439 <        DDrStartupMessage("Daodan: Finished parsing");
435 >        else
436 >        {
437 >                STARTUPMESSAGE("Writing %s template file failed", iniName);
438 >        }
439 > }
440 >
441 >
442 > void DDrIniCallback(const char* section, const char* name, const char* value)
443 > {
444 >        static char curSection[20];
445 >        char fullOptName[50];
446 >
447 >        if (!_stricmp(section, "patch"))
448 >                section = "patches";
449 >
450 >        strcpy(curSection, section);
451  
452 +        strcpy(fullOptName, curSection);
453 +        fullOptName[strlen(curSection)] = '.';
454 +        strcpy(fullOptName+strlen(curSection)+1, name);
455  
456 +        ConfigOption_t* co = DDrConfig_GetOption(fullOptName);
457  
458 <        DDrStartupMessage("Daodan: Parsing command line...");
459 <        for (i = 1; i < argc; i ++)
458 >        if (co)
459 >        {
460 >                char* buf = 0;
461 >                switch (co->type) {
462 >                        case C_INT:
463 >                                co->value.intBoolVal = strtol(value, NULL, 0);
464 >                                break;
465 >                        case C_BOOL:
466 >                                co->value.intBoolVal = !_stricmp(value, "true");
467 >                                break;
468 >                        case C_STRING:
469 >                                buf = malloc(strlen(value)+1);
470 >                                strcpy(buf, value);
471 >                                co->value.stringVal = buf;
472 >                                break;
473 >                        case C_CMD:
474 >                                co->value.callback();
475 >                                break;
476 >                        case EXT_BOOL:
477 >                                *(co->value.extBoolVal) = !_stricmp(value, "true");
478 >                                break;
479 >                        default:
480 >                                STARTUPMESSAGE("Config value type unknown: %d", co->type);
481 >                }
482 >        }
483 > }
484 >
485 >
486 > bool DDrConfig_ParseCommandLine(int argc, char* argv[])
487 > {
488 >        for (int i = 1; i < argc; i ++)
489          {
490                  if (argv[i][0] == '-')
491                  {
492 <                        section = argv[i] + 1;
493 <                        if ((option = strchr(argv[i], '.')))
492 >                        const char* section;
493 >                        char* optionsep;
494 >                        char* option;
495 >                        bool invertedOption;
496 >
497 >                        if ((optionsep = strchr(argv[i], '.')))
498 >                        // Is "section.option"
499                          {
500 <                                *option = '\0';
501 <                                falseoption = (option[1] == 'n' || option[1] == 'N') && (option[2] == 'o' || option[2] == 'O');
502 <                                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 = '.';
500 >                                *optionsep = 0;
501 >                                option = optionsep+1;
502 >                                section = argv[i]+1;
503                          }
504                          else
505 +                        // Is just "option"
506                          {
507 <                                falseoption = (section[0] == 'n' || section[0] == 'N') && (section[1] == 'o' || section[1] == 'O');
508 <                                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"));
507 >                                section = defaultSection;
508 >                                option = argv[i]+1;
509                          }
510 +
511 +                        invertedOption = (option[0] == 'n' || option[0] == 'N') && (option[1] == 'o' || option[1] == 'O');
512 +                        if (invertedOption)
513 +                                option += 2;
514 +
515 +                        if (i < (argc - 1) && argv[i+1][0] != '-')
516 +                        // Has value in next field
517 +                        {
518 +                                DDrIniCallback(section, option, argv[++i]);
519 +                        }
520 +                        else
521 +                        // Implicit value
522 +                        {
523 +                                DDrIniCallback(section, option, (invertedOption ? "false" : "true"));
524 +                        }
525 +
526 +                        if (optionsep)
527 +                                *optionsep = '.';
528                  }
529                  else
530                  {
531 <                        DDrStartupMessage("Daodan: Parse error \"%s\"", argv[i]);
532 <                        break;
531 >                        STARTUPMESSAGE("Parse error \"%s\"", argv[i]);
532 >                        return false;
533                  }
534          }
535 <        DDrStartupMessage("Daodan: Finished parsing");
535 >        return true;
536 > }
537 >
538 > void DDrConfig(int argc, char* argv[])
539 > {
540 >        STARTUPMESSAGE("Initializing standard booleans", 0);
541 >        DDrConfig_InitExtBools();
542 >
543 >        if (GetFileAttributes(iniName) == INVALID_FILE_ATTRIBUTES)
544 >                DDrConfig_WriteTemplateIni();
545 >        
546 >        STARTUPMESSAGE("Parsing daodan.ini...", 0);
547 >        if (!Inifile_Read(iniName, DDrIniCallback))
548 >                STARTUPMESSAGE("Error reading daodan.ini, check your syntax!", 0);
549 >        STARTUPMESSAGE("Finished parsing", 0);
550 >
551 >
552 >
553 >        STARTUPMESSAGE("Parsing command line...", 0);
554 >        DDrConfig_ParseCommandLine(argc, argv);
555 >        STARTUPMESSAGE("Finished parsing", 0);
556 >
557 > //      DDrConfig_Print();
558   }
559  

Diff Legend

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