1 // This parses the RC file.
17 char *ctv_names
[NUM_CTV
] = { "off", "blur", "scanline", "interlace" };
19 // The table of strings and the keysyms they map to.
20 // The order is a bit weird, since this was originally a mapping for the SVGALib
21 // scancodes, and I just added the SDL stuff on top of it.
26 { "ESCAPE", PDK_ESCAPE
},
40 { "BACKSPACE", PDK_BACKSPACE
},
52 { "[", PDK_LEFTBRACKET
},
53 { "{", PDK_LEFTBRACKET
},
54 { "]", PDK_RIGHTBRACKET
},
55 { "}", PDK_RIGHTBRACKET
},
56 { "RETURN", PDK_RETURN
},
57 { "ENTER", PDK_RETURN
},
67 { ";", PDK_SEMICOLON
},
68 { ":", PDK_SEMICOLON
},
71 { "`", PDK_BACKQUOTE
},
72 { "~", PDK_BACKQUOTE
},
73 { "\\", PDK_BACKSLASH
},
74 { "|", PDK_BACKSLASH
},
88 { "KP_MULTIPLY", PDK_KP_MULTIPLY
},
89 { "SPACE", PDK_SPACE
},
101 { "KP_HOME", PDK_KP7
},
103 { "KP_UP", PDK_KP8
},
105 { "KP_PAGE_UP", PDK_KP9
},
106 { "KP_PAGEUP", PDK_KP9
},
107 { "KP_MINUS", PDK_KP_MINUS
},
109 { "KP_LEFT", PDK_KP4
},
112 { "KP_RIGHT", PDK_KP6
},
113 { "KP_PLUS", PDK_KP_PLUS
},
115 { "KP_END", PDK_KP1
},
117 { "KP_DOWN", PDK_KP2
},
119 { "KP_PAGE_DOWN", PDK_KP3
},
120 { "KP_PAGEDOWN", PDK_KP3
},
122 { "KP_INSERT", PDK_KP0
},
123 { "KP_PERIOD", PDK_KP_PERIOD
},
124 { "KP_DELETE", PDK_KP_PERIOD
},
127 { "KP_ENTER", PDK_KP_ENTER
},
128 { "KP_DIVIDE", PDK_KP_DIVIDE
},
129 { "HOME", PDK_HOME
},
131 { "PAGE_UP", PDK_PAGEUP
},
132 { "PAGEUP", PDK_PAGEUP
},
133 { "LEFT", PDK_LEFT
},
134 { "RIGHT", PDK_RIGHT
},
136 { "DOWN", PDK_DOWN
},
137 { "PAGE_DOWN", PDK_PAGEDOWN
},
138 { "PAGEDOWN", PDK_PAGEDOWN
},
139 { "INSERT", PDK_INSERT
},
140 { "DELETE", PDK_DELETE
},
141 { "NUMLOCK", PDK_NUMLOCK
},
142 { "NUM_LOCK", PDK_NUMLOCK
},
143 { "CAPSLOCK", PDK_CAPSLOCK
},
144 { "CAPS_LOCK", PDK_CAPSLOCK
},
145 { "SCROLLOCK", PDK_SCROLLOCK
},
146 { "SCROLL_LOCK", PDK_SCROLLOCK
},
147 { "LSHIFT", PDK_LSHIFT
},
148 { "SHIFT_L", PDK_LSHIFT
},
149 { "RSHIFT", PDK_RSHIFT
},
150 { "SHIFT_R", PDK_RSHIFT
},
151 { "LCTRL", PDK_LCTRL
},
152 { "CTRL_L", PDK_LCTRL
},
153 { "RCTRL", PDK_RCTRL
},
154 { "CTRL_R", PDK_RCTRL
},
155 { "LALT", PDK_LALT
},
156 { "ALT_L", PDK_LALT
},
157 { "RALT", PDK_RALT
},
158 { "ALT_R", PDK_RALT
},
159 { "LMETA", PDK_LMETA
},
160 { "META_L", PDK_LMETA
},
161 { "RMETA", PDK_RMETA
},
162 { "META_R", PDK_RMETA
},
163 { NULL
, 0 } // Terminator
166 /* Define all the external RC variables */
169 long js_map_button
[2][16] = {
171 MD_A_MASK
, MD_C_MASK
, MD_A_MASK
,
172 MD_B_MASK
, MD_Y_MASK
, MD_Z_MASK
,
173 MD_X_MASK
, MD_X_MASK
, MD_START_MASK
,
174 MD_MODE_MASK
, 0, 0, 0, 0, 0, 0
177 MD_A_MASK
, MD_C_MASK
, MD_A_MASK
,
178 MD_B_MASK
, MD_Y_MASK
, MD_Z_MASK
,
179 MD_X_MASK
, MD_X_MASK
, MD_START_MASK
,
180 MD_MODE_MASK
, 0, 0, 0, 0, 0, 0
185 * If the string matches one of the strings in the keysym table above,
186 * return the keysym, otherwise -1. */
187 static long keysym(const char *code
)
189 struct rc_keysym
*s
= keysyms
;
192 // Check for modifier prefixes shift-, ctrl-, alt-, meta-
194 if(!strncasecmp("shift-", code
, 6)) {
195 r
|= KEYSYM_MOD_SHIFT
;
199 if(!strncasecmp("ctrl-", code
, 5)) {
200 r
|= KEYSYM_MOD_CTRL
;
204 if(!strncasecmp("alt-", code
, 4)) {
209 if(!strncasecmp("meta-", code
, 5)) {
210 r
|= KEYSYM_MOD_META
;
218 if(!strcasecmp(s
->name
, code
)) return r
|= s
->keysym
;
219 } while ((++s
)->name
);
224 /* Parse a boolean value.
225 * If the string is "yes" or "true", return 1.
226 * If the string is "no" or "false", return 0.
227 * Otherwise, just return atoi(value). */
228 static long boolean(const char *value
)
230 if(!strcasecmp(value
, "yes") || !strcasecmp(value
, "true"))
232 if(!strcasecmp(value
, "no") || !strcasecmp(value
, "false"))
237 // Made GCC happy about unused things when we don't want a joystick. :) [PKH]
238 // Cheesy hack to set joystick mappings from the RC file. [PKH]
239 static long jsmap(const char *value
) {
240 if(!strcasecmp(value
, "mode"))
241 snprintf((char*)value
, 2, "%c", 'm');
242 if(!strcasecmp(value
, "start"))
243 snprintf((char*)value
, 2, "%c", 's');
271 return(MD_MODE_MASK
);
275 return(MD_START_MASK
);
282 /* Parse the CTV type. As new CTV filters get submitted expect this to grow ;)
283 * Current values are:
285 * blur - blur bitmap (from DirectX DGen), by Dave <dave@dtmnt.com>
286 * scanline - attenuates every other line, looks cool! by Phillip K. Hornung <redx@pknet.com>
288 static long ctv(const char *value
)
290 for(int i
= 0; i
< NUM_CTV
; ++i
)
291 if(!strcasecmp(value
, ctv_names
[i
])) return i
;
295 static long number(const char *value
)
300 /* This is a table of all the RC options, the variables they affect, and the
301 * functions to parse their values. */
304 long (*parser
)(const char*);
307 { "key_pad1_up", keysym
, &pad1_up
},
308 { "key_pad1_down", keysym
, &pad1_down
},
309 { "key_pad1_left", keysym
, &pad1_left
},
310 { "key_pad1_right", keysym
, &pad1_right
},
311 { "key_pad1_a", keysym
, &pad1_a
},
312 { "key_pad1_b", keysym
, &pad1_b
},
313 { "key_pad1_c", keysym
, &pad1_c
},
314 { "key_pad1_x", keysym
, &pad1_x
},
315 { "key_pad1_y", keysym
, &pad1_y
},
316 { "key_pad1_z", keysym
, &pad1_z
},
317 { "key_pad1_mode", keysym
, &pad1_mode
},
318 { "key_pad1_start", keysym
, &pad1_start
},
319 { "key_pad2_up", keysym
, &pad2_up
},
320 { "key_pad2_down", keysym
, &pad2_down
},
321 { "key_pad2_left", keysym
, &pad2_left
},
322 { "key_pad2_right", keysym
, &pad2_right
},
323 { "key_pad2_a", keysym
, &pad2_a
},
324 { "key_pad2_b", keysym
, &pad2_b
},
325 { "key_pad2_c", keysym
, &pad2_c
},
326 { "key_pad2_x", keysym
, &pad2_x
},
327 { "key_pad2_y", keysym
, &pad2_y
},
328 { "key_pad2_z", keysym
, &pad2_z
},
329 { "key_pad2_mode", keysym
, &pad2_mode
},
330 { "key_pad2_start", keysym
, &pad2_start
},
331 { "key_fix_checksum", keysym
, &dgen_fix_checksum
},
332 { "key_quit", keysym
, &dgen_quit
},
333 { "key_splitscreen_toggle", keysym
, &dgen_splitscreen_toggle
},
334 { "key_craptv_toggle", keysym
, &dgen_craptv_toggle
},
335 { "key_screenshot", keysym
, &dgen_screenshot
},
336 { "key_reset", keysym
, &dgen_reset
},
337 { "key_slot_0", keysym
, &dgen_slot_0
},
338 { "key_slot_1", keysym
, &dgen_slot_1
},
339 { "key_slot_2", keysym
, &dgen_slot_2
},
340 { "key_slot_3", keysym
, &dgen_slot_3
},
341 { "key_slot_4", keysym
, &dgen_slot_4
},
342 { "key_slot_5", keysym
, &dgen_slot_5
},
343 { "key_slot_6", keysym
, &dgen_slot_6
},
344 { "key_slot_7", keysym
, &dgen_slot_7
},
345 { "key_slot_8", keysym
, &dgen_slot_8
},
346 { "key_slot_9", keysym
, &dgen_slot_9
},
347 { "key_save", keysym
, &dgen_save
},
348 { "key_load", keysym
, &dgen_load
},
349 { "key_cpu_toggle", keysym
, &dgen_cpu_toggle
},
350 { "key_stop", keysym
, &dgen_stop
},
351 { "key_fullscreen_toggle", keysym
, &dgen_fullscreen_toggle
},
352 { "bool_splitscreen_startup", boolean
, &dgen_splitscreen_startup
},
353 { "bool_autoload", boolean
, &dgen_autoload
},
354 { "bool_autosave", boolean
, &dgen_autosave
},
355 { "bool_frameskip", boolean
, &dgen_frameskip
},
356 { "bool_show_carthead", boolean
, &dgen_show_carthead
},
357 { "ctv_craptv_startup", ctv
, &dgen_craptv
},
358 { "bool_sound", boolean
, &dgen_sound
},
359 { "int_soundrate", number
, &dgen_soundrate
},
360 { "bool_16bit", boolean
, &dgen_16bit
},
361 { "int_soundsegs", number
, &dgen_soundsegs
},
362 { "int_nice", number
, &dgen_nice
},
363 { "bool_fullscreen", boolean
, &dgen_fullscreen
},
364 { "int_scale", number
, &dgen_scale
},
365 { "bool_opengl", boolean
, &dgen_opengl
},
366 { "int_opengl_width", number
, &dgen_opengl_width
},
367 { "int_opengl_height", number
, &dgen_opengl_height
},
368 { "bool_joystick", boolean
, &dgen_joystick
},
369 { "joypad1_b0", jsmap
, &js_map_button
[0][0] },
370 { "joypad1_b1", jsmap
, &js_map_button
[0][1] },
371 { "joypad1_b2", jsmap
, &js_map_button
[0][2] },
372 { "joypad1_b3", jsmap
, &js_map_button
[0][3] },
373 { "joypad1_b4", jsmap
, &js_map_button
[0][4] },
374 { "joypad1_b5", jsmap
, &js_map_button
[0][5] },
375 { "joypad1_b6", jsmap
, &js_map_button
[0][6] },
376 { "joypad1_b7", jsmap
, &js_map_button
[0][7] },
377 { "joypad1_b8", jsmap
, &js_map_button
[0][8] },
378 { "joypad1_b9", jsmap
, &js_map_button
[0][9] },
379 { "joypad1_b10", jsmap
, &js_map_button
[0][10] },
380 { "joypad1_b11", jsmap
, &js_map_button
[0][11] },
381 { "joypad1_b12", jsmap
, &js_map_button
[0][12] },
382 { "joypad1_b13", jsmap
, &js_map_button
[0][13] },
383 { "joypad1_b14", jsmap
, &js_map_button
[0][14] },
384 { "joypad1_b15", jsmap
, &js_map_button
[0][15] },
385 { "joypad2_b0", jsmap
, &js_map_button
[1][0] },
386 { "joypad2_b1", jsmap
, &js_map_button
[1][1] },
387 { "joypad2_b2", jsmap
, &js_map_button
[1][2] },
388 { "joypad2_b3", jsmap
, &js_map_button
[1][3] },
389 { "joypad2_b4", jsmap
, &js_map_button
[1][4] },
390 { "joypad2_b5", jsmap
, &js_map_button
[1][5] },
391 { "joypad2_b6", jsmap
, &js_map_button
[1][6] },
392 { "joypad2_b7", jsmap
, &js_map_button
[1][7] },
393 { "joypad2_b8", jsmap
, &js_map_button
[1][8] },
394 { "joypad2_b9", jsmap
, &js_map_button
[1][9] },
395 { "joypad2_b10", jsmap
, &js_map_button
[1][10] },
396 { "joypad2_b11", jsmap
, &js_map_button
[1][11] },
397 { "joypad2_b12", jsmap
, &js_map_button
[1][12] },
398 { "joypad2_b13", jsmap
, &js_map_button
[1][13] },
399 { "joypad2_b14", jsmap
, &js_map_button
[1][14] },
400 { "joypad2_b15", jsmap
, &js_map_button
[1][15] },
401 { NULL
, NULL
, NULL
} // Terminator
404 /* Parse the rc file */
405 void parse_rc(const char *file
)
408 char temp
[1024] = "", line
[2048] = "", field
[1024] = "", value
[1024] = "";
409 /* If the filename is NULL, use default of $HOME/.dgen/dgenrc */
412 strncat(temp
, getenv("HOME"), 1023);
413 strncat(temp
, "/.dgen/dgenrc", 1023 - strlen(temp
));
416 /* Open the file. If it's "-", open standard input instead. */
417 rc
= fopen(file
, "r");
421 fprintf(stderr
, "rc: Couldn't open rc file %s, trying to create\n", file
);
422 strncat(field
, getenv("HOME"), 1023);
423 strncat(field
, "/.dgen", 1023 - strlen(field
));
424 mkdir(field
, 0777); /* Create the .dgen directory */
425 rc
= fopen(file
, "w");
428 fprintf(stderr
, "rc: Couldn't create rc file %s!\n", file
);
435 while(fgets(line
, 2047, rc
))
439 /* If it starts with hash (#) or is blank, we have a comment */
440 if(*line
== '#' || *line
== '\0' || *line
== '\n') continue;
441 /* Each line is in the format field=value */
442 sscanf(line
, " %s = %s", field
, value
);
443 /* Check field against all supported fields */
445 if(!strcasecmp(s
->fieldname
, field
))
448 potential
= (*(s
->parser
))(value
);
449 /* If we got a bad value, discard and warn user */
451 fprintf(stderr
, "rc: Invalid RC value for %s: %s\n", field
, value
);
453 *(s
->variable
) = potential
;
456 } while((++s
)->fieldname
);
457 // If we reached the end of the table, bad field, bad line
458 if(!s
->fieldname
) fprintf(stderr
, "rc: Invalid RC line: %s", line
);