|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Config file handling
5: * This still needs some thought before it's complete...
6: *
7: * Copyright 1998 Brian King, Bernd Schmidt
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include <ctype.h>
14:
15: #include "options.h"
1.1.1.10 root 16: #include "threaddep/thread.h"
1.1 root 17: #include "uae.h"
18: #include "autoconf.h"
1.1.1.18 root 19: #include "filesys.h"
1.1.1.8 root 20: #include "events.h"
1.1.1.3 root 21: #include "custom.h"
1.1.1.18 root 22: #include "audio.h"
1.1.1.16 root 23: #include "inputdevice.h"
1.1.1.18 root 24: #include "romlist.h"
25: #include "gui.h"
1.1.1.16 root 26:
27: #define cfgfile_write fprintf
1.1 root 28:
1.1.1.20! root 29: static int config_newfilesystem;
! 30:
1.1 root 31: /* @@@ need to get rid of this... just cut part of the manual and print that
32: * as a help text. */
33: struct cfg_lines
34: {
35: const char *config_label, *config_help;
36: };
37:
38: static struct cfg_lines opttable[] =
39: {
40: {"help", "Prints this help" },
41: {"config_description", "" },
42: {"use_gui", "Enable the GUI? If no, then goes straight to emulator" },
43: {"use_debugger", "Enable the debugger?" },
44: {"cpu_speed", "can be max, real, or a number between 1 and 20" },
45: {"cpu_type", "Can be 68000, 68010, 68020, 68020/68881" },
46: {"cpu_24bit_addressing", "must be set to 'no' in order for Z3mem or P96mem to work" },
47: {"log_illegal_mem", "print illegal memory access by Amiga software?" },
48: {"fastmem_size", "Size in megabytes of fast-memory" },
49: {"chipmem_size", "Size in megabytes of chip-memory" },
50: {"bogomem_size", "Size in megabytes of bogo-memory at 0xC00000" },
51: {"a3000mem_size", "Size in megabytes of A3000 memory" },
52: {"gfxcard_size", "Size in megabytes of Picasso96 graphics-card memory" },
53: {"z3mem_size", "Size in megabytes of Zorro-III expansion memory" },
54: {"gfx_test_speed", "Test graphics speed?" },
55: {"framerate", "Print every nth frame" },
56: {"gfx_width", "Screen width" },
57: {"gfx_height", "Screen height" },
58: {"gfx_lores", "Treat display as lo-res?" },
59: {"gfx_linemode", "Can be none, double, or scanlines" },
60: {"gfx_fullscreen_amiga", "Amiga screens are fullscreen?" },
61: {"gfx_fullscreen_picasso", "Picasso screens are fullscreen?" },
62: {"gfx_correct_aspect", "Correct aspect ratio?" },
63: {"gfx_center_horizontal", "Center display horizontally?" },
64: {"gfx_center_vertical", "Center display vertically?" },
65: {"gfx_colour_mode", "" },
66: {"32bit_blits", "Enable 32 bit blitter emulation" },
67: {"immediate_blits", "Perform blits immediately" },
1.1.1.15 root 68: {"show_leds", "LED display" },
1.1 root 69: {"sound_output", "" },
70: {"sound_frequency", "" },
71: {"sound_channels", "" },
72: {"sound_max_buff", "" },
73: {"parallel_on_demand", "" },
74: {"serial_on_demand", "" },
75: {"joyport0", "" },
76: {"joyport1", "" },
77: {"kickstart_rom_file", "Kickstart ROM image, (C) Copyright Amiga, Inc." },
1.1.1.12 root 78: {"kickstart_ext_rom_file", "Extended Kickstart ROM image, (C) Copyright Amiga, Inc." },
1.1 root 79: {"kickstart_key_file", "Key-file for encrypted ROM images (from Cloanto's Amiga Forever)" },
80: {"floppy0", "Diskfile for drive 0" },
81: {"floppy1", "Diskfile for drive 1" },
82: {"floppy2", "Diskfile for drive 2" },
83: {"floppy3", "Diskfile for drive 3" },
84: {"hardfile", "access,sectors, surfaces, reserved, blocksize, path format" },
85: {"filesystem", "access,'Amiga volume-name':'host directory path' - where 'access' can be 'read-only' or 'read-write'" }
86: };
87:
1.1.1.10 root 88: static const char *guimode1[] = { "no", "yes", "nowait", 0 };
89: static const char *guimode2[] = { "false", "true", "nowait", 0 };
90: static const char *guimode3[] = { "0", "1", "nowait", 0 };
91: static const char *csmode[] = { "ocs", "ecs_agnus", "ecs_denise", "ecs", "aga", 0 };
1.1 root 92: static const char *linemode1[] = { "none", "double", "scanlines", 0 };
93: static const char *linemode2[] = { "n", "d", "s", 0 };
94: static const char *speedmode[] = { "max", "real", 0 };
1.1.1.7 root 95: static const char *cpumode[] = {
1.1.1.18 root 96: "68000", "68010",
97: "68ec020", "68ec020/68881", "68ec020/68882",
98: "68020", "68020/68881", "68020/68882",
99: "68030", "68030/68881", "68030/68882",
100: "68040", "68060", 0
101: };
102: static int mode_to_cpumodel[] = {
103: 68000, 68010,
104: 68020, 68020, 68020,
105: 68020, 68020, 68020,
106: 68030, 68030, 68030,
107: 68040, 68060
108: };
109: static int mode_to_fpumodel[] = {
110: 0, 0,
111: 0, 68881, 68882,
112: 0, 68881, 68882,
113: 0, 68881, 68882,
114: 68040, 68060
1.1.1.7 root 115: };
1.1 root 116: static const char *colormode1[] = { "8bit", "15bit", "16bit", "8bit_dither", "4bit_dither", "32bit", 0 };
117: static const char *colormode2[] = { "8", "15", "16", "8d", "4d", "32", 0 };
118: static const char *soundmode[] = { "none", "interrupts", "normal", "exact", 0 };
1.1.1.2 root 119: static const char *centermode1[] = { "none", "simple", "smart", 0 };
120: static const char *centermode2[] = { "false", "true", "smart", 0 };
1.1.1.18 root 121: static const char *stereomode[] = { "mono", "stereo", "mixed", 0 };
1.1.1.19 root 122: static const char *interpolmode[] = { "none", "sinc", "anti", 0 };
1.1.1.18 root 123: static const char *soundfiltermode1[] = { "off", "emulated", "on", 0 };
124: static const char *soundfiltermode2[] = { "standard", "enhanced", 0 };
1.1.1.9 root 125: static const char *collmode[] = { "none", "sprites", "playfields", "full", 0 };
1.1.1.18 root 126: static const char *idemode[] = { "none", "a600/a1200", "a4000", 0 };
127:
128: static const char *obsolete[] = {
129: "accuracy", "gfx_opengl", "gfx_32bit_blits", "32bit_blits",
130: "gfx_immediate_blits", "gfx_ntsc", "win32", "gfx_filter_bits",
131: "sound_pri_cutoff", "sound_pri_time", "sound_min_buff", "sound_bits",
132: "gfx_test_speed", "gfxlib_replacement", "enforcer", "catweasel_io",
133: "fast_copper", "sound_adjust", "serial_hardware_dtrdsr", "cpu_compatible",
134: 0
135: };
1.1 root 136:
137: #define UNEXPANDED "$(FILE_PATH)"
138:
139: static int match_string (const char *table[], const char *str)
140: {
141: int i;
142: for (i = 0; table[i] != 0; i++)
143: if (strcasecmp (table[i], str) == 0)
144: return i;
145: return -1;
146: }
147:
148: char *cfgfile_subst_path (const char *path, const char *subst, const char *file)
149: {
150: /* @@@ use strcasecmp for some targets. */
151: if (strlen (path) > 0 && strncmp (file, path, strlen (path)) == 0) {
152: int l;
153: char *p = xmalloc (strlen (file) + strlen (subst) + 2);
154: strcpy (p, subst);
155: l = strlen (p);
156: while (l > 0 && p[l - 1] == '/')
157: p[--l] = '\0';
158: l = strlen (path);
159: while (file[l] == '/')
160: l++;
161: strcat (p, "/"); strcat (p, file + l);
162: return p;
163: }
164: return my_strdup (file);
165: }
166:
1.1.1.18 root 167: static void write_gfx_params (FILE *f, const struct gfx_params *p, const char *suffix)
1.1.1.17 root 168: {
169: cfgfile_write (f, "gfx_width_%s=%d\n", suffix, p->width);
170: cfgfile_write (f, "gfx_height_%s=%d\n", suffix, p->height);
171: cfgfile_write (f, "gfx_lores_%s=%s\n", suffix, p->lores ? "true" : "false");
172: cfgfile_write (f, "gfx_linemode_%s=%s\n", suffix, linemode1[p->linedbl]);
173: cfgfile_write (f, "gfx_correct_aspect_%s=%s\n", suffix, p->correct_aspect ? "true" : "false");
174: cfgfile_write (f, "gfx_center_horizontal_%s=%s\n", suffix, centermode1[p->xcenter]);
175: cfgfile_write (f, "gfx_center_vertical_%s=%s\n", suffix, centermode1[p->ycenter]);
1.1.1.18 root 176: cfgfile_write (f, "gfx_show_leds_%s=%s\n", suffix, p->leds_on_screen ? "true" : "false");
1.1.1.17 root 177: }
178:
1.1.1.18 root 179: void save_options (FILE *f, const struct uae_prefs *p)
1.1 root 180: {
181: struct strlist *sl;
182: char *str;
183: int i;
184:
1.1.1.16 root 185: cfgfile_write (f, "config_description=%s\n", p->description);
1.1 root 186:
187: for (sl = p->unknown_lines; sl; sl = sl->next)
1.1.1.16 root 188: cfgfile_write (f, "%s\n", sl->str);
1.1 root 189:
1.1.1.16 root 190: cfgfile_write (f, "%s.rom_path=%s\n", TARGET_NAME, p->path_rom);
191: cfgfile_write (f, "%s.floppy_path=%s\n", TARGET_NAME, p->path_floppy);
192: cfgfile_write (f, "%s.hardfile_path=%s\n", TARGET_NAME, p->path_hardfile);
1.1 root 193:
1.1.1.2 root 194: target_save_options (f, p);
195:
1.1.1.16 root 196: cfgfile_write (f, "use_gui=%s\n", guimode1[p->start_gui]);
197: cfgfile_write (f, "use_debugger=%s\n", p->start_debugger ? "true" : "false");
1.1 root 198: str = cfgfile_subst_path (p->path_rom, UNEXPANDED, p->romfile);
1.1.1.16 root 199: cfgfile_write (f, "kickstart_rom_file=%s\n", str);
1.1 root 200: free (str);
1.1.1.18 root 201: if (currprefs.rom_crc32)
202: cfgfile_write (f, "kickstart_rom_crc=0x%x\n", currprefs.rom_crc32);
1.1.1.12 root 203: str = cfgfile_subst_path (p->path_rom, UNEXPANDED, p->romextfile);
1.1.1.16 root 204: cfgfile_write (f, "kickstart_ext_rom_file=%s\n", str);
1.1.1.12 root 205: free (str);
1.1 root 206: str = cfgfile_subst_path (p->path_rom, UNEXPANDED, p->keyfile);
1.1.1.16 root 207: cfgfile_write (f, "kickstart_key_file=%s\n", str);
1.1 root 208: free (str);
1.1.1.16 root 209: cfgfile_write (f, "kickshifter=%s\n", p->kickshifter ? "true" : "false");
1.1 root 210:
211: for (i = 0; i < 4; i++) {
212: str = cfgfile_subst_path (p->path_floppy, UNEXPANDED, p->df[i]);
1.1.1.16 root 213: cfgfile_write (f, "floppy%d=%s\n", i, str);
1.1 root 214: free (str);
1.1.1.18 root 215: cfgfile_write (f, "floppy%dtype=%d\n", i, p->dfxtype[i]);
1.1 root 216: }
1.1.1.16 root 217: cfgfile_write (f, "nr_floppies=%d\n", p->nr_floppies);
218: cfgfile_write (f, "parallel_on_demand=%s\n", p->parallel_demand ? "true" : "false");
219: cfgfile_write (f, "serial_on_demand=%s\n", p->serial_demand ? "true" : "false");
220:
221: cfgfile_write (f, "sound_output=%s\n", soundmode[p->produce_sound]);
1.1.1.18 root 222: cfgfile_write (f, "sound_channels=%s\n", stereomode[p->sound_stereo]);
223: cfgfile_write (f, "sound_stereo_separation=%d\n", p->sound_stereo_separation);
224: cfgfile_write (f, "sound_stereo_mixing_delay=%d\n", p->sound_mixed_stereo_delay >= 0 ? p->sound_mixed_stereo_delay : 0);
1.1.1.16 root 225: cfgfile_write (f, "sound_max_buff=%d\n", p->sound_maxbsiz);
226: cfgfile_write (f, "sound_frequency=%d\n", p->sound_freq);
227: cfgfile_write (f, "sound_interpol=%s\n", interpolmode[p->sound_interpol]);
1.1.1.18 root 228: cfgfile_write (f, "sound_filter=%s\n", soundfiltermode1[p->sound_filter]);
229: cfgfile_write (f, "sound_filter_type=%s\n", soundfiltermode2[p->sound_filter_type]);
1.1.1.16 root 230:
231: for (i = 0; i < 2; i++) {
232: int v = i == 0 ? p->jport0 : p->jport1;
233: char tmp1[100], tmp2[50];
234: if (v < JSEM_JOYS) {
235: sprintf (tmp2, "kbd%d", v + 1);
236: } else if (v < JSEM_MICE) {
237: sprintf (tmp2, "joy%d", v - JSEM_JOYS);
238: } else {
239: strcpy (tmp2, "mouse");
240: if (v - JSEM_MICE > 0)
241: sprintf (tmp2, "mouse%d", v - JSEM_MICE);
242: }
243: sprintf (tmp1, "joyport%d=%s\n", i, tmp2);
244: cfgfile_write (f, tmp1);
245: }
246:
247: cfgfile_write (f, "bsdsocket_emu=%s\n", p->socket_emu ? "true" : "false");
248:
249: cfgfile_write (f, "gfx_framerate=%d\n", p->gfx_framerate);
1.1.1.17 root 250: write_gfx_params (f, &p->gfx_w, "windowed");
251: write_gfx_params (f, &p->gfx_f, "fullscreen");
1.1.1.16 root 252: cfgfile_write (f, "gfx_fullscreen_amiga=%s\n", p->gfx_afullscreen ? "true" : "false");
253: cfgfile_write (f, "gfx_fullscreen_picasso=%s\n", p->gfx_pfullscreen ? "true" : "false");
254: cfgfile_write (f, "gfx_colour_mode=%s\n", colormode1[p->color_mode]);
255:
256: cfgfile_write (f, "immediate_blits=%s\n", p->immediate_blits ? "true" : "false");
257: cfgfile_write (f, "ntsc=%s\n", p->ntscmode ? "true" : "false");
1.1.1.3 root 258: if (p->chipset_mask & CSMASK_AGA)
1.1.1.16 root 259: cfgfile_write (f, "chipset=aga\n");
1.1.1.3 root 260: else if ((p->chipset_mask & CSMASK_ECS_AGNUS) && (p->chipset_mask & CSMASK_ECS_AGNUS))
1.1.1.16 root 261: cfgfile_write (f, "chipset=ecs\n");
1.1.1.3 root 262: else if (p->chipset_mask & CSMASK_ECS_AGNUS)
1.1.1.16 root 263: cfgfile_write (f, "chipset=ecs_agnus\n");
1.1.1.3 root 264: else if (p->chipset_mask & CSMASK_ECS_DENISE)
1.1.1.16 root 265: cfgfile_write (f, "chipset=ecs_denise\n");
1.1.1.3 root 266: else
1.1.1.16 root 267: cfgfile_write (f, "chipset=ocs\n");
268: cfgfile_write (f, "collision_level=%s\n", collmode[p->collision_level]);
1.1 root 269:
1.1.1.18 root 270: cfgfile_write (f, "ide=%s\n", p->cs_ide == 1 ? "a600/a1200" : (p->cs_ide == 2 ? "a4000" : "none"));
271: cfgfile_write (f, "a1000ram=%s\n", p->cs_a1000ram ? "true" : "false");
272: cfgfile_write (f, "fatgary=%d\n", p->cs_fatgaryrev);
273: cfgfile_write (f, "ramsey=%d\n", p->cs_ramseyrev);
274:
1.1.1.16 root 275: cfgfile_write (f, "fastmem_size=%d\n", p->fastmem_size / 0x100000);
1.1.1.18 root 276: cfgfile_write (f, "a3000mem_size=%d\n", p->mbresmem_low_size / 0x100000);
277: cfgfile_write (f, "mbresmem_size=%d\n", p->mbresmem_high_size / 0x100000);
1.1.1.16 root 278: cfgfile_write (f, "z3mem_size=%d\n", p->z3fastmem_size / 0x100000);
279: cfgfile_write (f, "bogomem_size=%d\n", p->bogomem_size / 0x40000);
280: cfgfile_write (f, "gfxcard_size=%d\n", p->gfxmem_size / 0x100000);
281: cfgfile_write (f, "chipmem_size=%d\n", p->chipmem_size / 0x80000);
1.1 root 282:
1.1.1.3 root 283: if (p->m68k_speed > 0)
1.1.1.16 root 284: cfgfile_write (f, "finegrain_cpu_speed=%d\n", p->m68k_speed);
1.1 root 285: else
1.1.1.16 root 286: cfgfile_write (f, "cpu_speed=%s\n", p->m68k_speed == -1 ? "max" : "real");
1.1 root 287:
1.1.1.18 root 288: for (i = 0; cpumode[i] != NULL; i++)
289: if (mode_to_cpumodel[i] == p->cpu_model && mode_to_fpumodel[i] == p->fpu_model) {
290: cfgfile_write (f, "cpu_type=%s\n", cpumode[i]);
291: break;
292: }
1.1 root 293:
1.1.1.16 root 294: cfgfile_write (f, "log_illegal_mem=%s\n", p->illegal_mem ? "true" : "false");
1.1 root 295:
1.1.1.16 root 296: cfgfile_write (f, "kbd_lang=%s\n", (p->keyboard_lang == KBD_LANG_DE ? "de"
1.1.1.18 root 297: : p->keyboard_lang == KBD_LANG_DK ? "dk"
298: : p->keyboard_lang == KBD_LANG_ES ? "es"
299: : p->keyboard_lang == KBD_LANG_US ? "us"
300: : p->keyboard_lang == KBD_LANG_SE ? "se"
301: : p->keyboard_lang == KBD_LANG_FR ? "fr"
302: : p->keyboard_lang == KBD_LANG_IT ? "it"
303: : "FOO"));
1.1 root 304:
305: write_filesys_config (p->mountinfo, UNEXPANDED, p->path_hardfile, f);
306:
307: /* Don't write gfxlib/gfx_test_speed options. */
308: }
309:
1.1.1.18 root 310: int cfgfile_yesno (const char *option, const char *value, const char *name, int *location)
1.1 root 311: {
312: if (strcmp (option, name) != 0)
313: return 0;
314: if (strcasecmp (value, "yes") == 0 || strcasecmp (value, "y") == 0
315: || strcasecmp (value, "true") == 0 || strcasecmp (value, "t") == 0)
316: *location = 1;
317: else if (strcasecmp (value, "no") == 0 || strcasecmp (value, "n") == 0
318: || strcasecmp (value, "false") == 0 || strcasecmp (value, "f") == 0)
319: *location = 0;
320: else
321: write_log ("Option `%s' requires a value of either `yes' or `no'.\n", option);
322: return 1;
323: }
324:
1.1.1.18 root 325: int cfgfile_intval (const char *option, const char *value, const char *name, int *location, int scale)
1.1 root 326: {
327: int base = 10;
328: char *endptr;
329: if (strcmp (option, name) != 0)
330: return 0;
331: if (value[0] == '0' && value[1] == 'x')
1.1.1.18 root 332: base = 16;
1.1 root 333: *location = strtol (value, &endptr, base) * scale;
334:
335: if (*endptr != '\0' || *value == '\0')
336: write_log ("Option `%s' requires a numeric argument.\n", option);
337: return 1;
338: }
339:
1.1.1.18 root 340: int cfgfile_uintval (const char *option, const char *value, const char *name, unsigned int *location, int scale)
341: {
342: int base = 10;
343: char *endptr;
344: if (strcmp (option, name) != 0)
345: return 0;
346: if (value[0] == '0' && value[1] == 'x')
347: base = 16;
348: *location = strtoul (value, &endptr, base) * scale;
349:
350: if (*endptr != '\0' || *value == '\0')
351: write_log ("Option `%s' requires a numeric argument.\n", option);
352: return 1;
353: }
354:
355: int cfgfile_strval (const char *option, const char *value, const char *name, int *location, const char *table[], int more)
1.1 root 356: {
357: int val;
358: if (strcmp (option, name) != 0)
359: return 0;
360: val = match_string (table, value);
361: if (val == -1) {
1.1.1.6 root 362: if (more)
363: return 0;
364:
365: write_log ("Unknown value for option `%s'.\n", option);
1.1 root 366: return 1;
367: }
368: *location = val;
369: return 1;
370: }
371:
1.1.1.18 root 372: int cfgfile_string (const char *option, const char *value, const char *name, char *location, int maxsz)
1.1 root 373: {
374: if (strcmp (option, name) != 0)
375: return 0;
376: strncpy (location, value, maxsz - 1);
377: location[maxsz - 1] = '\0';
378: return 1;
379: }
380:
381: static int getintval (char **p, int *result, int delim)
382: {
383: char *value = *p;
384: int base = 10;
385: char *endptr;
386: char *p2 = strchr (*p, delim);
387:
388: if (p2 == 0)
389: return 0;
390:
391: *p2++ = '\0';
392:
393: if (value[0] == '0' && value[1] == 'x')
394: value += 2, base = 16;
395: *result = strtol (value, &endptr, base);
396: *p = p2;
397:
398: if (*endptr != '\0' || *value == '\0')
399: return 0;
400:
401: return 1;
402: }
403:
1.1.1.20! root 404: static int getintval2 (char **p, int *result, int delim)
! 405: {
! 406: char *value = *p;
! 407: int base = 10;
! 408: char *endptr;
! 409: char *p2 = strchr (*p, delim);
! 410:
! 411: if (p2 == 0) {
! 412: p2 = strchr (*p, 0);
! 413: if (p2 == 0) {
! 414: *p = 0;
! 415: return 0;
! 416: }
! 417: }
! 418: if (*p2 != 0)
! 419: *p2++ = '\0';
! 420:
! 421: if (value[0] == '0' && value[1] == 'x')
! 422: value += 2, base = 16;
! 423: *result = strtol (value, &endptr, base);
! 424: *p = p2;
! 425:
! 426: if (*endptr != '\0' || *value == '\0') {
! 427: *p = 0;
! 428: return 0;
! 429: }
! 430:
! 431: return 1;
! 432: }
! 433:
1.1.1.8 root 434: static void set_chipset_mask (struct uae_prefs *p, int val)
1.1.1.5 root 435: {
436: p->chipset_mask = (val == 0 ? 0
437: : val == 1 ? CSMASK_ECS_AGNUS
438: : val == 2 ? CSMASK_ECS_DENISE
439: : val == 3 ? CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS
440: : CSMASK_AGA | CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS);
441: }
442:
1.1.1.18 root 443: static int cfgfile_parse_host (struct uae_prefs *p, char *option, char *value)
1.1 root 444: {
1.1.1.3 root 445: int tmpval;
1.1.1.9 root 446: int dummy;
1.1 root 447: char *section = 0;
448: char *tmpp;
1.1.1.3 root 449:
1.1.1.17 root 450: if (memcmp (option, "input.", 6) == 0) {
451: read_inputdevice_config (p, option, value);
452: return 1;
453: }
454:
1.1 root 455: for (tmpp = option; *tmpp != '\0'; tmpp++)
456: if (isupper (*tmpp))
457: *tmpp = tolower (*tmpp);
458: tmpp = strchr (option, '.');
459: if (tmpp) {
460: section = option;
461: option = tmpp + 1;
462: *tmpp = '\0';
463: if (strcmp (section, TARGET_NAME) == 0) {
464: /* We special case the various path options here. */
465: if (cfgfile_string (option, value, "rom_path", p->path_rom, 256)
466: || cfgfile_string (option, value, "floppy_path", p->path_floppy, 256)
467: || cfgfile_string (option, value, "hardfile_path", p->path_hardfile, 256))
468: return 1;
469: return target_parse_option (p, option, value);
470: }
471: return 0;
472: }
1.1.1.18 root 473:
1.1 root 474: if (cfgfile_yesno (option, value, "use_debugger", &p->start_debugger)
1.1.1.3 root 475: || cfgfile_yesno (option, value, "bsdsocket_emu", &p->socket_emu)
1.1.1.18 root 476:
1.1.1.17 root 477: || (cfgfile_yesno (option, value, "gfx_lores", &p->gfx_w.lores)
478: && cfgfile_yesno (option, value, "gfx_lores", &p->gfx_f.lores))
479: || cfgfile_yesno (option, value, "gfx_lores_windowed", &p->gfx_w.lores)
480: || cfgfile_yesno (option, value, "gfx_lores_fullscreen", &p->gfx_f.lores)
1.1.1.18 root 481:
1.1.1.17 root 482: || (cfgfile_yesno (option, value, "gfx_correct_aspect", &p->gfx_w.correct_aspect)
483: && cfgfile_yesno (option, value, "gfx_correct_aspect", &p->gfx_f.correct_aspect))
484: || cfgfile_yesno (option, value, "gfx_correct_aspect_windowed", &p->gfx_w.correct_aspect)
485: || cfgfile_yesno (option, value, "gfx_correct_aspect_fullscreen", &p->gfx_f.correct_aspect)
1.1.1.18 root 486:
487: || (cfgfile_yesno (option, value, "show_leds", &p->gfx_w.leds_on_screen)
488: && cfgfile_yesno (option, value, "show_leds", &p->gfx_f.leds_on_screen))
489: || cfgfile_yesno (option, value, "gfx_show_leds_windowed", &p->gfx_w.leds_on_screen)
490: || cfgfile_yesno (option, value, "gfx_show_leds_fullscreen", &p->gfx_f.leds_on_screen)
491:
1.1 root 492: || cfgfile_yesno (option, value, "gfx_fullscreen_amiga", &p->gfx_afullscreen)
493: || cfgfile_yesno (option, value, "gfx_fullscreen_picasso", &p->gfx_pfullscreen)
494: || cfgfile_yesno (option, value, "log_illegal_mem", &p->illegal_mem))
495: return 1;
1.1.1.18 root 496: if (cfgfile_intval (option, value, "sound_max_buff", &p->sound_maxbsiz, 1)
1.1 root 497: || cfgfile_intval (option, value, "sound_frequency", &p->sound_freq, 1)
1.1.1.18 root 498: || cfgfile_intval (option, value, "sound_stereo_separation", &p->sound_stereo_separation, 1)
499: || cfgfile_intval (option, value, "sound_stereo_mixing_delay", &p->sound_mixed_stereo_delay, 1)
500:
1.1.1.3 root 501: || cfgfile_intval (option, value, "gfx_framerate", &p->gfx_framerate, 1)
1.1.1.17 root 502: || (cfgfile_intval (option, value, "gfx_width", &p->gfx_w.width, 1)
503: && cfgfile_intval (option, value, "gfx_width", &p->gfx_f.width, 1))
504: || cfgfile_intval (option, value, "gfx_width_windowed", &p->gfx_w.width, 1)
505: || cfgfile_intval (option, value, "gfx_width_fullscreen", &p->gfx_f.width, 1)
506: || (cfgfile_intval (option, value, "gfx_height", &p->gfx_w.height, 1)
507: && cfgfile_intval (option, value, "gfx_height", &p->gfx_f.height, 1))
508: || cfgfile_intval (option, value, "gfx_height_windowed", &p->gfx_w.height, 1)
1.1.1.18 root 509: || cfgfile_intval (option, value, "gfx_height_fullscreen", &p->gfx_f.height, 1))
1.1 root 510: return 1;
511: if (cfgfile_strval (option, value, "sound_output", &p->produce_sound, soundmode, 0)
1.1.1.4 root 512: || cfgfile_strval (option, value, "sound_interpol", &p->sound_interpol, interpolmode, 0)
1.1.1.18 root 513: || cfgfile_strval (option, value, "sound_filter", &p->sound_filter, soundfiltermode1, 0)
514: || cfgfile_strval (option, value, "sound_filter_type", &p->sound_filter_type, soundfiltermode2, 0)
1.1.1.10 root 515: || cfgfile_strval (option, value, "use_gui", &p->start_gui, guimode1, 1)
516: || cfgfile_strval (option, value, "use_gui", &p->start_gui, guimode2, 1)
517: || cfgfile_strval (option, value, "use_gui", &p->start_gui, guimode3, 0)
1.1.1.17 root 518: || (cfgfile_strval (option, value, "gfx_linemode", &p->gfx_w.linedbl, linemode1, 1)
519: && cfgfile_strval (option, value, "gfx_linemode", &p->gfx_f.linedbl, linemode1, 1))
520: || (cfgfile_strval (option, value, "gfx_linemode", &p->gfx_w.linedbl, linemode2, 0)
521: && cfgfile_strval (option, value, "gfx_linemode", &p->gfx_f.linedbl, linemode2, 0))
522: || cfgfile_strval (option, value, "gfx_linemode_windowed", &p->gfx_w.linedbl, linemode1, 1)
523: || cfgfile_strval (option, value, "gfx_linemode_windowed", &p->gfx_w.linedbl, linemode2, 0)
524: || cfgfile_strval (option, value, "gfx_linemode_fullscreen", &p->gfx_f.linedbl, linemode1, 1)
525: || cfgfile_strval (option, value, "gfx_linemode_fullscreen", &p->gfx_f.linedbl, linemode2, 0)
526: || (cfgfile_strval (option, value, "gfx_center_horizontal", &p->gfx_w.xcenter, centermode1, 1)
527: && cfgfile_strval (option, value, "gfx_center_horizontal", &p->gfx_f.xcenter, centermode1, 1))
528: || (cfgfile_strval (option, value, "gfx_center_horizontal", &p->gfx_w.xcenter, centermode2, 0)
529: && cfgfile_strval (option, value, "gfx_center_horizontal", &p->gfx_f.xcenter, centermode2, 0))
530: || cfgfile_strval (option, value, "gfx_center_horizontal_windowed", &p->gfx_w.xcenter, centermode1, 1)
531: || cfgfile_strval (option, value, "gfx_center_horizontal_windowed", &p->gfx_w.xcenter, centermode2, 0)
532: || cfgfile_strval (option, value, "gfx_center_horizontal_fullscreen", &p->gfx_f.xcenter, centermode1, 1)
533: || cfgfile_strval (option, value, "gfx_center_horizontal_fullscreen", &p->gfx_f.xcenter, centermode2, 0)
534: || (cfgfile_strval (option, value, "gfx_center_vertical", &p->gfx_w.ycenter, centermode1, 1)
535: && cfgfile_strval (option, value, "gfx_center_vertical", &p->gfx_f.ycenter, centermode1, 1))
536: || (cfgfile_strval (option, value, "gfx_center_vertical", &p->gfx_w.ycenter, centermode2, 0)
537: && cfgfile_strval (option, value, "gfx_center_vertical", &p->gfx_f.ycenter, centermode2, 0))
538: || cfgfile_strval (option, value, "gfx_center_vertical_windowed", &p->gfx_w.ycenter, centermode1, 1)
539: || cfgfile_strval (option, value, "gfx_center_vertical_windowed", &p->gfx_w.ycenter, centermode2, 0)
540: || cfgfile_strval (option, value, "gfx_center_vertical_fullscreen", &p->gfx_f.ycenter, centermode1, 1)
541: || cfgfile_strval (option, value, "gfx_center_vertical_fullscreen", &p->gfx_f.ycenter, centermode2, 0)
1.1 root 542: || cfgfile_strval (option, value, "gfx_colour_mode", &p->color_mode, colormode1, 1)
543: || cfgfile_strval (option, value, "gfx_colour_mode", &p->color_mode, colormode2, 0)
544: || cfgfile_strval (option, value, "gfx_color_mode", &p->color_mode, colormode1, 1)
545: || cfgfile_strval (option, value, "gfx_color_mode", &p->color_mode, colormode2, 0))
546: return 1;
1.1.1.16 root 547:
548: if (strcmp (option, "joyport0") == 0 || strcmp (option, "joyport1") == 0) {
549: int port = strcmp (option, "joyport0") == 0 ? 0 : 1;
550: int start = -1;
551: char *pp = 0;
552: if (strncmp (value, "kbd", 3) == 0) {
553: start = JSEM_KBDLAYOUT;
554: pp = value + 3;
555: } else if (strncmp (value, "joy", 3) == 0) {
556: start = JSEM_JOYS;
557: pp = value + 3;
558: } else if (strncmp (value, "mouse", 5) == 0) {
559: start = JSEM_MICE;
560: pp = value + 5;
561: }
562: if (pp) {
563: int v = atol (pp);
564: if (start >= 0) {
565: if (start == JSEM_KBDLAYOUT)
566: v--;
567: if (v >= 0) {
568: start += v;
569: if (port)
570: p->jport1 = start;
571: else
572: p->jport0 = start;
573: }
574: }
575: }
576: return 1;
577: }
578:
1.1.1.18 root 579: if (cfgfile_string (option, value, "config_description", p->description, 256)
580: || cfgfile_string (option, value, "config_sortstr", p->sortstr, 256))
1.1 root 581: return 1;
582:
583: /* Tricky ones... */
1.1.1.18 root 584: if (cfgfile_strval (option, value, "sound_channels", &p->sound_stereo, stereomode, 1)) {
1.1.1.19 root 585: if (p->sound_stereo == SND_MONO) {
586: write_log ("Mono sound no longer supported, switching to stereo.\n");
587: p->sound_stereo = SND_STEREO;
588: p->sound_mixed_stereo_delay = 0;
589: p->sound_stereo_separation = 15;
590: }
1.1.1.18 root 591: if (p->sound_stereo == SND_NONE) { /* "mixed stereo" compatibility hack */
592: p->sound_stereo = SND_STEREO;
593: p->sound_mixed_stereo_delay = 5;
594: p->sound_stereo_separation = 7;
1.1.1.9 root 595: }
1.1 root 596: return 1;
1.1.1.9 root 597: }
1.1 root 598:
599: if (strcmp (option, "kbd_lang") == 0) {
600: KbdLang l;
601: if ((l = KBD_LANG_DE, strcasecmp (value, "de") == 0)
1.1.1.9 root 602: || (l = KBD_LANG_DK, strcasecmp (value, "dk") == 0)
1.1 root 603: || (l = KBD_LANG_SE, strcasecmp (value, "se") == 0)
604: || (l = KBD_LANG_US, strcasecmp (value, "us") == 0)
605: || (l = KBD_LANG_FR, strcasecmp (value, "fr") == 0)
606: || (l = KBD_LANG_IT, strcasecmp (value, "it") == 0)
607: || (l = KBD_LANG_ES, strcasecmp (value, "es") == 0))
608: p->keyboard_lang = l;
609: else
610: write_log ("Unknown keyboard language\n");
611: return 1;
612: }
613:
614: if (strcmp (option, "filesystem") == 0
615: || strcmp (option, "hardfile") == 0)
616: {
1.1.1.18 root 617: int secs, heads, reserved, bs, ro, pri;
1.1.1.2 root 618: char *aname, *root;
1.1 root 619: char *tmpp = strchr (value, ',');
1.1.1.2 root 620: char *str;
1.1.1.20! root 621:
! 622: /* New versions of the emulator write out both types of config string,
! 623: with the new variant going first. When reading in the config file,
! 624: we see the new variant and sest config_newfilesystem, and here we
! 625: proceed to ignore the old variant since it contains duplicated
! 626: information. */
! 627: if (config_newfilesystem)
! 628: return 1;
! 629:
1.1 root 630: if (tmpp == 0)
631: goto invalid_fs;
632:
633: *tmpp++ = '\0';
634: if (strcmp (value, "0") == 0 || strcasecmp (value, "ro") == 0
635: || strcasecmp (value, "readonly") == 0
636: || strcasecmp (value, "read-only") == 0)
1.1.1.2 root 637: ro = 1;
1.1 root 638: else if (strcmp (value, "1") == 0 || strcasecmp (value, "rw") == 0
639: || strcasecmp (value, "readwrite") == 0
640: || strcasecmp (value, "read-write") == 0)
1.1.1.2 root 641: ro = 0;
1.1 root 642: else
643: goto invalid_fs;
1.1.1.2 root 644: secs = 0; heads = 0; reserved = 0; bs = 0;
1.1 root 645:
646: value = tmpp;
647: if (strcmp (option, "filesystem") == 0) {
648: tmpp = strchr (value, ':');
649: if (tmpp == 0)
650: goto invalid_fs;
651: *tmpp++ = '\0';
1.1.1.2 root 652: aname = value;
653: root = tmpp;
1.1 root 654: } else {
1.1.1.2 root 655: if (! getintval (&value, &secs, ',')
656: || ! getintval (&value, &heads, ',')
657: || ! getintval (&value, &reserved, ',')
658: || ! getintval (&value, &bs, ','))
1.1 root 659: goto invalid_fs;
1.1.1.2 root 660: root = value;
661: aname = 0;
1.1 root 662: }
1.1.1.2 root 663: str = cfgfile_subst_path (UNEXPANDED, p->path_hardfile, root);
1.1.1.18 root 664: tmpp = add_filesys_unit (p->mountinfo, NULL, aname, str, ro, secs,
665: heads, reserved, bs, -1);
1.1.1.2 root 666: free (str);
667: if (tmpp)
1.1.1.18 root 668: gui_message (tmpp);
1.1 root 669: return 1;
1.1.1.20! root 670: }
! 671:
! 672: if (strcmp (option, "filesystem2") == 0
! 673: || strcmp (option, "hardfile2") == 0)
! 674: {
! 675: int secs, heads, reserved, bs, ro, bp, hdcv;
! 676: char *dname = NULL, *aname = "", *root = NULL, *fs = NULL, *hdc;
! 677: char *tmpp = strchr (value, ',');
! 678: char *str = NULL;
! 679:
! 680: config_newfilesystem = 1;
! 681: if (tmpp == 0)
! 682: goto invalid_fs;
! 683:
! 684: *tmpp++ = '\0';
! 685: if (strcasecmp (value, "ro") == 0)
! 686: ro = 1;
! 687: else if (strcasecmp (value, "rw") == 0)
! 688: ro = 0;
! 689: else
! 690: goto invalid_fs;
! 691: secs = 0; heads = 0; reserved = 0; bs = 0; bp = 0;
! 692: fs = 0; hdc = 0; hdcv = 0;
! 693:
! 694: value = tmpp;
! 695: if (strcmp (option, "filesystem2") == 0) {
! 696: tmpp = strchr (value, ':');
! 697: if (tmpp == 0)
! 698: goto empty_fs;
! 699: *tmpp++ = 0;
! 700: dname = value;
! 701: aname = tmpp;
! 702: tmpp = strchr (tmpp, ':');
! 703: if (tmpp == 0)
! 704: goto empty_fs;
! 705: *tmpp++ = 0;
! 706: root = tmpp;
! 707: tmpp = strchr (tmpp, ',');
! 708: if (tmpp == 0)
! 709: goto empty_fs;
! 710: *tmpp++ = 0;
! 711: if (! getintval (&tmpp, &bp, 0))
! 712: goto empty_fs;
! 713: } else {
! 714: tmpp = strchr (value, ':');
! 715: if (tmpp == 0)
! 716: goto invalid_fs;
! 717: *tmpp++ = '\0';
! 718: dname = value;
! 719: root = tmpp;
! 720: tmpp = strchr (tmpp, ',');
! 721: if (tmpp == 0)
! 722: goto invalid_fs;
! 723: *tmpp++ = 0;
! 724: aname = 0;
! 725: if (! getintval (&tmpp, &secs, ',')
! 726: || ! getintval (&tmpp, &heads, ',')
! 727: || ! getintval (&tmpp, &reserved, ',')
! 728: || ! getintval (&tmpp, &bs, ','))
! 729: goto invalid_fs;
! 730: if (getintval2 (&tmpp, &bp, ',')) {
! 731: fs = tmpp;
! 732: tmpp = strchr (tmpp, ',');
! 733: if (tmpp != 0) {
! 734: *tmpp++ = 0;
! 735: hdc = tmpp;
! 736: }
! 737: }
! 738: }
! 739: empty_fs:
! 740: if (root)
! 741: str = cfgfile_subst_path (UNEXPANDED, p->path_hardfile, root);
! 742: tmpp = add_filesys_unit (p->mountinfo, NULL, aname, str, ro, secs,
! 743: heads, reserved, bs, bp);
! 744: free (str);
! 745: if (tmpp)
! 746: gui_message (tmpp);
! 747: return 1;
1.1 root 748:
749: invalid_fs:
750: write_log ("Invalid filesystem/hardfile specification.\n");
751: return 1;
752: }
753:
754: return 0;
755: }
756:
1.1.1.18 root 757: static int cfgfile_parse_hardware (struct uae_prefs *p, char *option, char *value)
758: {
759: int tmpval, dummy, i;
760: unsigned int crc32;
761:
762: if (cfgfile_yesno (option, value, "immediate_blits", &p->immediate_blits)
763: || cfgfile_yesno (option, value, "a1000ram", &p->cs_a1000ram)
764: || cfgfile_yesno (option, value, "kickshifter", &p->kickshifter)
765: || cfgfile_yesno (option, value, "ntsc", &p->ntscmode)
766: || cfgfile_yesno (option, value, "cpu_24bit_addressing", &p->address_space_24)
767: || cfgfile_yesno (option, value, "parallel_on_demand", &p->parallel_demand)
768: || cfgfile_yesno (option, value, "serial_on_demand", &p->serial_demand))
769: return 1;
770:
771: if (cfgfile_intval (option, value, "fatgary", &p->cs_fatgaryrev, 1)
772: || cfgfile_intval (option, value, "ramsey", &p->cs_ramseyrev, 1)
773: || cfgfile_uintval (option, value, "fastmem_size", &p->fastmem_size, 0x100000)
774: || cfgfile_uintval (option, value, "a3000mem_size", &p->mbresmem_low_size, 0x100000)
775: || cfgfile_uintval (option, value, "mbresmem_size", &p->mbresmem_high_size, 0x100000)
776: || cfgfile_uintval (option, value, "z3mem_size", &p->z3fastmem_size, 0x100000)
777: || cfgfile_uintval (option, value, "bogomem_size", &p->bogomem_size, 0x40000)
778: || cfgfile_uintval (option, value, "gfxcard_size", &p->gfxmem_size, 0x100000)
779: || cfgfile_uintval (option, value, "chipmem_size", &p->chipmem_size, 0x80000)
780: || cfgfile_uintval (option, value, "kickstart_rom_crc", &p->rom_crc32, 1)
781: || cfgfile_intval (option, value, "nr_floppies", &p->nr_floppies, 1)
782: || cfgfile_intval (option, value, "floppy0type", &p->dfxtype[0], 1)
783: || cfgfile_intval (option, value, "floppy1type", &p->dfxtype[1], 1)
784: || cfgfile_intval (option, value, "floppy2type", &p->dfxtype[2], 1)
785: || cfgfile_intval (option, value, "floppy3type", &p->dfxtype[3], 1))
786: return 1;
787:
788: /* Default configurations want to allow multiple possible ROMs. For these,
789: * we have the following option, which validates the CRC32 against the list
790: * of available ROMs.
791: * Config files should sort these entries so that the most desired ROM appears
792: * last. */
793: if (cfgfile_uintval (option, value, "kickstart_rom_crc_attempt", &crc32, 1)) {
794: for (i = 0;; i++) {
795: struct romlist *rl = romlist_from_idx (i, ROMTYPE_KICK, 1);
796: if (!rl)
797: break;
798: if (rl->rd->crc32 == crc32) {
799: p->rom_crc32 = crc32;
800: break;
801: }
802: }
803: return 1;
804: }
805:
806: if (cfgfile_strval (option, value, "ide", &p->cs_ide, idemode, 0)
807: || cfgfile_strval (option, value, "collision_level", &p->collision_level, collmode, 0))
808: return 1;
809:
810: if (cfgfile_string (option, value, "floppy0", p->df[0], 256)
811: || cfgfile_string (option, value, "floppy1", p->df[1], 256)
812: || cfgfile_string (option, value, "floppy2", p->df[2], 256)
813: || cfgfile_string (option, value, "floppy3", p->df[3], 256)
814: || cfgfile_string (option, value, "kickstart_rom_file", p->romfile, 256)
815: || cfgfile_string (option, value, "kickstart_ext_rom_file", p->romextfile, 256)
816: || cfgfile_string (option, value, "kickstart_key_file", p->keyfile, 256))
817: return 1;
818:
819: if (cfgfile_strval (option, value, "chipset", &tmpval, csmode, 0)) {
820: set_chipset_mask (p, tmpval);
821: return 1;
822: }
823:
824: if (cfgfile_strval (option, value, "cpu_type", &tmpval, cpumode, 0)) {
825: p->fpu_model = 0;
826: p->address_space_24 = 0;
827: p->cpu_model = 68000;
828: switch (tmpval) {
829: case 0:
830: p->cpu_model = 68000;
831: break;
832: case 1:
833: p->cpu_model = 68010;
834: break;
835: case 2: case 3: case 4:
836: case 5: case 6: case 7:
837: p->cpu_model = 68020;
838: p->address_space_24 = tmpval < 5;
839: p->fpu_model = (tmpval == 3 || tmpval == 6 ? 68881
840: : tmpval == 4 || tmpval == 7 ? 68882
841: : 0);
842: break;
843: case 8: case 9: case 10:
844: p->cpu_model = 68030;
845: p->fpu_model = (tmpval == 9 ? 68881 : tmpval == 10 ? 68882 : 0);
846: break;
847: case 11:
848: p->cpu_model = 68040;
849: p->fpu_model = 68040;
850: break;
851: case 12:
852: p->cpu_model = 68060;
853: p->fpu_model = 68060;
854: break;
855: }
856: return 1;
857: }
858:
859: if (cfgfile_strval (option, value, "cpu_speed", &p->m68k_speed, speedmode, 1)
860: /* Broken earlier versions used to write this out as a string. */
861: || cfgfile_strval (option, value, "finegraincpu_speed", &p->m68k_speed, speedmode, 1))
862: {
863: p->m68k_speed--;
864: return 1;
865: }
866:
867: if (cfgfile_intval (option, value, "cpu_speed", &p->m68k_speed, 1)) {
868: p->m68k_speed *= CYCLE_UNIT;
869: return 1;
870: }
871:
872: if (cfgfile_intval (option, value, "finegrain_cpu_speed", &p->m68k_speed, 1)) {
873: if (OFFICIAL_CYCLE_UNIT > CYCLE_UNIT) {
874: int factor = OFFICIAL_CYCLE_UNIT / CYCLE_UNIT;
875: p->m68k_speed = (p->m68k_speed + factor - 1) / factor;
876: }
877: return 1;
878: }
879:
880: return 0;
881: }
882:
883: int cfgfile_parse_option (struct uae_prefs *p, char *option, char *value)
884: {
885: if (cfgfile_parse_hardware (p, option, value))
886: return 1;
887: if (cfgfile_parse_host (p, option, value))
888: return 1;
889:
890: return 0;
891: }
892:
1.1.1.2 root 893: void cfgfile_parse_line (struct uae_prefs *p, char *line)
1.1 root 894: {
895: int i;
896: char *orig_line = my_strdup (line);
897: char *line1, *line2;
898:
899: line1 = line;
900: line2 = strchr (line, '=');
901: if (! line2) {
902: write_log ("CFGFILE: line was incomplete with only %s\n", line1);
903: return;
904: }
905:
906: *line2++ = '\0';
907:
908: /* Get rid of whitespace. */
1.1.1.2 root 909: i = strlen (line2);
910: while (i > 0 && (line2[i - 1] == '\t' || line2[i - 1] == ' '
911: || line2[i - 1] == '\r' || line2[i - 1] == '\n'))
912: line2[--i] = '\0';
1.1 root 913: line2 += strspn (line2, "\t \r\n");
1.1.1.2 root 914: i = strlen (line);
915: while (i > 0 && (line[i - 1] == '\t' || line[i - 1] == ' '
916: || line[i - 1] == '\r' || line[i - 1] == '\n'))
917: line[--i] = '\0';
1.1 root 918: line += strspn (line, "\t \r\n");
919:
1.1.1.2 root 920: if (! cfgfile_parse_option (p, line, line2)) {
1.1 root 921: struct strlist *u = xmalloc (sizeof (struct strlist));
922: u->str = orig_line;
923: u->next = p->unknown_lines;
924: p->unknown_lines = u;
925: } else
926: free (orig_line);
927: }
928:
929: static void subst (char *p, char *f, int n)
930: {
931: char *str = cfgfile_subst_path (UNEXPANDED, p, f);
932: strncpy (f, str, n - 1);
933: f[n - 1] = '\0';
934: free (str);
935: }
936:
937: int cfgfile_load (struct uae_prefs *p, const char *filename)
938: {
939: int i;
940:
941: FILE *fh;
942: char line[256];
943:
1.1.1.4 root 944: fh = fopen (filename, "r");
1.1 root 945: if (! fh)
946: return 0;
947:
948: while (fgets (line, 256, fh) != 0) {
1.1.1.13 root 949: int len = strlen (line);
950: /* Delete trailing whitespace. */
1.1.1.18 root 951: while (len > 0 && strcspn (line + len - 1, "\t \r\n") == 0)
1.1.1.13 root 952: line[--len] = '\0';
1.1.1.18 root 953: if (strlen (line) > 0) {
954: if (line[0] == '#' || line[0] == ';')
955: continue;
1.1.1.2 root 956: cfgfile_parse_line (p, line);
1.1.1.18 root 957: }
1.1 root 958: }
959: fclose (fh);
960:
961: for (i = 0; i < 4; i++)
962: subst (p->path_floppy, p->df[i], sizeof p->df[i]);
963: subst (p->path_rom, p->romfile, sizeof p->romfile);
1.1.1.12 root 964: subst (p->path_rom, p->romextfile, sizeof p->romextfile);
1.1 root 965: subst (p->path_rom, p->keyfile, sizeof p->keyfile);
966:
967: return 1;
968: }
969:
970: int cfgfile_save (struct uae_prefs *p, const char *filename)
971: {
972: FILE *fh = fopen (filename, "w");
973: if (! fh)
974: return 0;
975:
976: save_options (fh, p);
977: fclose (fh);
978: return 1;
979: }
980:
981: int cfgfile_get_description (const char *filename, char *description)
982: {
983: int result = 0;
984: struct uae_prefs p;
985: default_prefs (&p);
986: strcpy (p.description, "");
1.1.1.12 root 987: if (cfgfile_load (&p, filename)) {
1.1 root 988: result = 1;
989: strcpy (description, p.description);
990: }
991: discard_prefs (&p);
992: return result;
993: }
994:
995: void cfgfile_show_usage (void)
996: {
997: int i;
998: fprintf (stderr, "UAE Configuration Help:\n" \
999: "=======================\n");
1000: for (i = 0; i < sizeof opttable / sizeof *opttable; i++)
1001: fprintf (stderr, "%s: %s\n", opttable[i].config_label, opttable[i].config_help);
1002: }
1.1.1.4 root 1003:
1004: /* This implements the old commandline option parsing. I've re-added this
1005: because the new way of doing things is painful for me (it requires me
1006: to type a couple hundred characters when invoking UAE). The following
1007: is far less annoying to use. */
1.1.1.16 root 1008: static void parse_gfx_specs (struct uae_prefs *p, char *spec)
1.1.1.4 root 1009: {
1010: char *x0 = my_strdup (spec);
1011: char *x1, *x2;
1012:
1013: x1 = strchr (x0, ':');
1014: if (x1 == 0)
1015: goto argh;
1016: x2 = strchr (x1+1, ':');
1017: if (x2 == 0)
1018: goto argh;
1019: *x1++ = 0; *x2++ = 0;
1020:
1.1.1.17 root 1021: p->gfx_w.width = atoi (x0);
1022: p->gfx_w.height = atoi (x1);
1023: p->gfx_w.lores = strchr (x2, 'l') != 0;
1024: p->gfx_w.xcenter = strchr (x2, 'x') != 0 ? 1 : strchr (x2, 'X') != 0 ? 2 : 0;
1025: p->gfx_w.ycenter = strchr (x2, 'y') != 0 ? 1 : strchr (x2, 'Y') != 0 ? 2 : 0;
1026: p->gfx_w.linedbl = strchr (x2, 'd') != 0;
1027: p->gfx_w.linedbl += 2 * (strchr (x2, 'D') != 0);
1028: p->gfx_w.correct_aspect = strchr (x2, 'c') != 0;
1029:
1030: p->gfx_f = p->gfx_w;
1031:
1.1.1.16 root 1032: p->gfx_afullscreen = strchr (x2, 'a') != 0;
1033: p->gfx_pfullscreen = strchr (x2, 'p') != 0;
1.1.1.4 root 1034:
1.1.1.17 root 1035: if (p->gfx_w.linedbl == 3) {
1.1.1.4 root 1036: fprintf (stderr, "You can't use both 'd' and 'D' modifiers in the display mode specification.\n");
1037: }
1.1.1.16 root 1038:
1.1.1.4 root 1039: free (x0);
1040: return;
1041:
1042: argh:
1043: fprintf (stderr, "Bad display mode specification.\n");
1044: fprintf (stderr, "The format to use is: \"width:height:modifiers\"\n");
1045: fprintf (stderr, "Type \"uae -h\" for detailed help.\n");
1046: free (x0);
1047: }
1048:
1.1.1.16 root 1049: static void parse_sound_spec (struct uae_prefs *p, char *spec)
1.1.1.4 root 1050: {
1051: char *x0 = my_strdup (spec);
1.1.1.18 root 1052: char *x1, *x2 = NULL, *x3 = NULL, *x4 = NULL;
1.1.1.4 root 1053:
1054: x1 = strchr (x0, ':');
1055: if (x1 != NULL) {
1056: *x1++ = '\0';
1057: x2 = strchr (x1 + 1, ':');
1058: if (x2 != NULL) {
1059: *x2++ = '\0';
1060: x3 = strchr (x2 + 1, ':');
1061: if (x3 != NULL) {
1062: *x3++ = '\0';
1063: x4 = strchr (x3 + 1, ':');
1064: }
1065: }
1066: }
1.1.1.16 root 1067: p->produce_sound = atoi (x0);
1.1.1.4 root 1068: if (x1) {
1.1.1.18 root 1069: p->sound_mixed_stereo_delay = 0;
1.1.1.19 root 1070: p->sound_stereo = SND_STEREO;
1.1.1.18 root 1071: if (*x1 == 'S') {
1072: p->sound_stereo_separation = 7;
1.1.1.19 root 1073: }
1.1.1.4 root 1074: }
1.1.1.18 root 1075: /* x2 used to be bits, now fixed at 16 bit. */
1.1.1.4 root 1076: if (x3)
1.1.1.16 root 1077: p->sound_freq = atoi (x3);
1.1.1.4 root 1078: if (x4)
1.1.1.18 root 1079: p->sound_maxbsiz = atoi (x4);
1.1.1.4 root 1080: free (x0);
1081: }
1082:
1083:
1.1.1.16 root 1084: static void parse_joy_spec (struct uae_prefs *p, char *spec)
1.1.1.4 root 1085: {
1086: int v0 = 2, v1 = 0;
1087: if (strlen(spec) != 2)
1088: goto bad;
1089:
1090: switch (spec[0]) {
1.1.1.16 root 1091: case '0': v0 = JSEM_JOYS; break;
1092: case '1': v0 = JSEM_JOYS + 1; break;
1093: case 'M': case 'm': v0 = JSEM_MICE; break;
1094: case 'A': case 'a': v0 = JSEM_KBDLAYOUT; break;
1095: case 'B': case 'b': v0 = JSEM_KBDLAYOUT + 1; break;
1096: case 'C': case 'c': v0 = JSEM_KBDLAYOUT + 2; break;
1.1.1.4 root 1097: default: goto bad;
1098: }
1099:
1100: switch (spec[1]) {
1.1.1.16 root 1101: case '0': v1 = JSEM_JOYS; break;
1102: case '1': v1 = JSEM_JOYS + 1; break;
1103: case 'M': case 'm': v1 = JSEM_MICE; break;
1104: case 'A': case 'a': v1 = JSEM_KBDLAYOUT; break;
1105: case 'B': case 'b': v1 = JSEM_KBDLAYOUT + 1; break;
1106: case 'C': case 'c': v1 = JSEM_KBDLAYOUT + 2; break;
1.1.1.4 root 1107: default: goto bad;
1108: }
1109: if (v0 == v1)
1110: goto bad;
1111: /* Let's scare Pascal programmers */
1112: if (0)
1113: bad:
1.1.1.16 root 1114: write_log ("Bad joystick mode specification. Use -J xy, where x and y\n"
1.1.1.4 root 1115: "can be 0 for joystick 0, 1 for joystick 1, M for mouse, and\n"
1116: "a, b or c for different keyboard settings.\n");
1117:
1.1.1.16 root 1118: p->jport0 = v0;
1119: p->jport1 = v1;
1.1.1.4 root 1120: }
1121:
1.1.1.18 root 1122: static void parse_filesys_spec (struct uae_prefs *p, int readonly, char *spec)
1.1.1.4 root 1123: {
1124: char buf[256];
1125: char *s2;
1126:
1127: strncpy (buf, spec, 255); buf[255] = 0;
1128: s2 = strchr (buf, ':');
1129: if (s2) {
1130: *s2++ = '\0';
1131: #ifdef __DOS__
1132: {
1133: char *tmp;
1.1.1.16 root 1134:
1.1.1.4 root 1135: while ((tmp = strchr (s2, '\\')))
1136: *tmp = '/';
1137: }
1138: #endif
1.1.1.18 root 1139: s2 = add_filesys_unit (p->mountinfo, NULL, buf, s2, readonly, 0, 0, 0, 0, -1);
1.1.1.4 root 1140: if (s2)
1141: fprintf (stderr, "%s\n", s2);
1142: } else {
1143: fprintf (stderr, "Usage: [-m | -M] VOLNAME:mount_point\n");
1144: }
1145: }
1.1.1.16 root 1146:
1.1.1.18 root 1147: static void parse_hardfile_spec (struct uae_prefs *p, char *spec)
1.1.1.4 root 1148: {
1149: char *x0 = my_strdup (spec);
1150: char *x1, *x2, *x3, *x4;
1151:
1152: x1 = strchr (x0, ':');
1153: if (x1 == NULL)
1154: goto argh;
1155: *x1++ = '\0';
1156: x2 = strchr (x1 + 1, ':');
1157: if (x2 == NULL)
1158: goto argh;
1159: *x2++ = '\0';
1160: x3 = strchr (x2 + 1, ':');
1161: if (x3 == NULL)
1162: goto argh;
1163: *x3++ = '\0';
1164: x4 = strchr (x3 + 1, ':');
1165: if (x4 == NULL)
1166: goto argh;
1167: *x4++ = '\0';
1.1.1.18 root 1168: x4 = add_filesys_unit (p->mountinfo, NULL, 0, x4, 0, atoi (x0), atoi (x1), atoi (x2), atoi (x3), -1);
1.1.1.4 root 1169: if (x4)
1170: fprintf (stderr, "%s\n", x4);
1171:
1172: free (x0);
1173: return;
1174:
1175: argh:
1176: free (x0);
1177: fprintf (stderr, "Bad hardfile parameter specified - type \"uae -h\" for help.\n");
1178: return;
1179: }
1180:
1.1.1.18 root 1181: static void parse_cpu_specs (struct uae_prefs *p, char *spec)
1.1.1.4 root 1182: {
1.1.1.18 root 1183: int lvl;
1.1.1.7 root 1184: if (*spec < '0' || *spec > '4') {
1185: fprintf (stderr, "CPU parameter string must begin with '0', '1', '2', '3' or '4'.\n");
1.1.1.4 root 1186: return;
1187: }
1.1.1.16 root 1188:
1.1.1.18 root 1189: lvl = *spec++ - '0';
1190: p->fpu_model = 0;
1191: p->cpu_model = lvl * 10 + 68000;
1192: if (p->cpu_model >= 68040)
1193: p->fpu_model = p->cpu_model;
1194: p->address_space_24 = p->cpu_model < 68020;
1.1.1.4 root 1195: while (*spec != '\0') {
1196: switch (*spec) {
1.1.1.18 root 1197: case 'a':
1198: if (p->cpu_model < 68020)
1.1.1.4 root 1199: fprintf (stderr, "In 68000/68010 emulation, the address space is always 24 bit.\n");
1.1.1.18 root 1200: else if (p->cpu_model >= 68040)
1.1.1.7 root 1201: fprintf (stderr, "In 68040 emulation, the address space is always 32 bit.\n");
1.1.1.4 root 1202: else
1.1.1.18 root 1203: p->address_space_24 = 1;
1.1.1.4 root 1204: break;
1.1.1.18 root 1205: case 'c':
1206: fprintf (stderr, "Obsolete CPU type modifier 'c'.\n");
1.1.1.4 root 1207: break;
1.1.1.18 root 1208: default:
1.1.1.4 root 1209: fprintf (stderr, "Bad CPU parameter specified - type \"uae -h\" for help.\n");
1210: break;
1211: }
1212: spec++;
1213: }
1214: }
1215:
1216: /* Returns the number of args used up (0 or 1). */
1.1.1.18 root 1217: int parse_cmdline_option (struct uae_prefs *p, char c, char *arg)
1.1.1.4 root 1218: {
1.1.1.5 root 1219: const char arg_required[] = "0123rKpImWSAJwNCZUFcblOdHRv";
1.1.1.4 root 1220:
1221: if (strchr (arg_required, c) && ! arg) {
1222: fprintf (stderr, "Missing argument for option `-%c'!\n", c);
1223: return 0;
1224: }
1225:
1226: switch (c) {
1.1.1.5 root 1227: case 'h': usage (); exit (0);
1.1.1.4 root 1228:
1.1.1.18 root 1229: case '0': strncpy (p->df[0], arg, 255); p->df[0][255] = 0; break;
1230: case '1': strncpy (p->df[1], arg, 255); p->df[1][255] = 0; break;
1231: case '2': strncpy (p->df[2], arg, 255); p->df[2][255] = 0; break;
1232: case '3': strncpy (p->df[3], arg, 255); p->df[3][255] = 0; break;
1233: case 'r': strncpy (p->romfile, arg, 255); p->romfile[255] = 0; break;
1234: case 'K': strncpy (p->keyfile, arg, 255); p->keyfile[255] = 0; break;
1235: case 'p': strncpy (p->prtname, arg, 255); p->prtname[255] = 0; break;
1236: /* case 'I': strncpy (p->sername, arg, 255); p->sername[255] = 0; p->use_serial = 1; break; */
1237: case 'm': case 'M': parse_filesys_spec (p, c == 'M', arg); break;
1238: case 'W': parse_hardfile_spec (p, arg); break;
1239: case 'S': parse_sound_spec (p, arg); break;
1240: case 'R': p->gfx_framerate = atoi (arg); break;
1241: case 'i': p->illegal_mem = 1; break;
1242: case 'J': parse_joy_spec (p, arg); break;
1243:
1244: case 't': p->test_drawing_speed = 1; break;
1245: case 'L': p->x11_use_low_bandwidth = 1; break;
1246: case 'T': p->x11_use_mitshm = 1; break;
1247: case 'w': p->m68k_speed = atoi (arg); break;
1248:
1249: case 'G': p->start_gui = 0; break;
1250: case 'D': p->start_debugger = 1; break;
1.1.1.4 root 1251:
1.1.1.5 root 1252: case 'n':
1.1.1.4 root 1253: if (strchr (arg, '3') != 0)
1.1.1.18 root 1254: p->blits_32bit_enabled = 1;
1.1.1.4 root 1255: if (strchr (arg, 'i') != 0)
1.1.1.18 root 1256: p->immediate_blits = 1;
1.1.1.4 root 1257: break;
1258:
1.1.1.5 root 1259: case 'v':
1.1.1.18 root 1260: set_chipset_mask (p, atoi (arg));
1.1.1.5 root 1261: break;
1262:
1263: case 'C':
1.1.1.18 root 1264: parse_cpu_specs (p, arg);
1.1.1.4 root 1265: break;
1266:
1.1.1.5 root 1267: case 'Z':
1.1.1.18 root 1268: p->z3fastmem_size = atoi (arg) * 0x100000;
1.1.1.4 root 1269: break;
1270:
1.1.1.5 root 1271: case 'U':
1.1.1.18 root 1272: p->gfxmem_size = atoi (arg) * 0x100000;
1.1.1.4 root 1273: break;
1274:
1.1.1.5 root 1275: case 'F':
1.1.1.18 root 1276: p->fastmem_size = atoi (arg) * 0x100000;
1.1.1.4 root 1277: break;
1278:
1.1.1.5 root 1279: case 'b':
1.1.1.18 root 1280: p->bogomem_size = atoi (arg) * 0x40000;
1.1.1.4 root 1281: break;
1282:
1.1.1.5 root 1283: case 'c':
1.1.1.18 root 1284: p->chipmem_size = atoi (arg) * 0x80000;
1.1.1.4 root 1285: break;
1286:
1.1.1.5 root 1287: case 'l':
1.1.1.18 root 1288: if (0 == strcasecmp (arg, "de"))
1289: p->keyboard_lang = KBD_LANG_DE;
1290: else if (0 == strcasecmp (arg, "dk"))
1291: p->keyboard_lang = KBD_LANG_DK;
1292: else if (0 == strcasecmp (arg, "us"))
1293: p->keyboard_lang = KBD_LANG_US;
1294: else if (0 == strcasecmp (arg, "se"))
1295: p->keyboard_lang = KBD_LANG_SE;
1296: else if (0 == strcasecmp (arg, "fr"))
1297: p->keyboard_lang = KBD_LANG_FR;
1298: else if (0 == strcasecmp (arg, "it"))
1299: p->keyboard_lang = KBD_LANG_IT;
1300: else if (0 == strcasecmp (arg, "es"))
1301: p->keyboard_lang = KBD_LANG_ES;
1.1.1.4 root 1302: break;
1303:
1.1.1.18 root 1304: case 'O': parse_gfx_specs (p, arg); break;
1.1.1.5 root 1305: case 'd':
1.1.1.4 root 1306: if (strchr (arg, 'S') != NULL || strchr (arg, 's')) {
1307: write_log (" Serial on demand.\n");
1.1.1.18 root 1308: p->serial_demand = 1;
1.1.1.4 root 1309: }
1310: if (strchr (arg, 'P') != NULL || strchr (arg, 'p')) {
1311: write_log (" Parallel on demand.\n");
1.1.1.18 root 1312: p->parallel_demand = 1;
1.1.1.4 root 1313: }
1314:
1315: break;
1316:
1.1.1.5 root 1317: case 'H':
1.1.1.18 root 1318: p->color_mode = atoi (arg);
1319: if (p->color_mode < 0) {
1.1.1.4 root 1320: fprintf (stderr, "Bad color mode selected. Using default.\n");
1.1.1.18 root 1321: p->color_mode = 0;
1.1.1.4 root 1322: }
1323: break;
1.1.1.5 root 1324: default:
1.1.1.4 root 1325: fprintf (stderr, "Unknown option `-%c'!\n", c);
1326: break;
1327: }
1328: return !! strchr (arg_required, c);
1329: }
1.1.1.18 root 1330:
1331: int cstype_from_prefs (struct uae_prefs *p)
1332: {
1333: if ((p->chipset_mask & CSMASK_AGA) == 0) {
1334: if (p->cs_ramseyrev == -1 && p->cs_fatgaryrev == -1) {
1335: if (p->cs_ide == 0) {
1336: if (p->cs_a1000ram && p->chipset_mask == CSMASK_OCS)
1337: return CP_A1000;
1338: if (p->chipset_mask == CSMASK_FULL_ECS)
1339: return CP_A500P;
1340: return CP_A500;
1341: }
1342: if (p->chipset_mask == CSMASK_FULL_ECS)
1343: return CP_A600;
1344: return CP_GENERIC;
1345: }
1346: if (p->cs_ide == 0 && p->cs_fatgaryrev == 0 && p->cs_ramseyrev == 0xd)
1347: return CP_A3000;
1348: return CP_GENERIC;
1349: }
1350: if (p->cs_ide == 1 && p->cs_ramseyrev == -1 && p->cs_fatgaryrev == -1)
1351: return CP_A1200;
1352: if (p->cs_ide == 2 && p->cs_ramseyrev == 0xf && p->cs_fatgaryrev == 0)
1353: return CP_A4000;
1354: return CP_GENERIC;
1355: }
1356:
1357: void built_in_chipset_prefs (struct uae_prefs *p, int cstype)
1358: {
1359: p->cs_a1000ram = 0;
1360: p->cs_fatgaryrev = -1;
1361: p->cs_ide = 0;
1362: p->cs_ramseyrev = -1;
1363:
1364: switch (cstype)
1365: {
1366: case CP_GENERIC: // generic
1367: p->cs_fatgaryrev = 0;
1368: p->cs_ide = -1;
1369: p->cs_ramseyrev = 0x0f;
1370: break;
1371: case CP_CDTV: // CDTV
1372: break;
1373: case CP_CD32: // CD32
1374: break;
1375: case CP_A500: // A500
1376: if (p->chipset_mask & CSMASK_AGA)
1377: p->chipset_mask = CSMASK_ECS_AGNUS;
1378: break;
1379: case CP_A500P: // A500+
1380: p->chipset_mask = CSMASK_FULL_ECS;
1381: break;
1382: case CP_A600: // A600
1383: p->cs_ide = 1;
1384: p->chipset_mask = CSMASK_FULL_ECS;
1385: break;
1386: case CP_A1000: // A1000
1387: p->cs_a1000ram = 1;
1388: p->chipset_mask = CSMASK_OCS;
1389: break;
1390: case CP_A1200: // A1200
1391: p->cs_ide = 1;
1392: p->chipset_mask = CSMASK_AGA;
1393: break;
1394: case CP_A2000: // A2000
1395: if (p->chipset_mask & CSMASK_AGA)
1396: p->chipset_mask = CSMASK_ECS_AGNUS;
1397: p->cs_rtc = 1;
1398: break;
1399: case CP_A3000: // A3000
1400: p->cs_rtc = 2;
1401: p->cs_fatgaryrev = 0;
1402: p->cs_ramseyrev = 0x0d;
1403: p->chipset_mask = CSMASK_FULL_ECS;
1404: break;
1405: case CP_A3000T: // A3000T
1406: p->cs_rtc = 2;
1407: p->cs_fatgaryrev = 0;
1408: p->cs_ramseyrev = 0x0d;
1409: p->chipset_mask = CSMASK_FULL_ECS;
1410: break;
1411: case CP_A4000: // A4000
1412: p->cs_rtc = 2;
1413: p->cs_fatgaryrev = 0;
1414: p->cs_ramseyrev = 0x0f;
1415: p->cs_ide = 2;
1416: p->chipset_mask = CSMASK_AGA;
1417: break;
1418: case CP_A4000T: // A4000T
1419: p->cs_rtc = 2;
1420: p->cs_fatgaryrev = 0;
1421: p->cs_ramseyrev = 0x0f;
1422: p->cs_ide = 2;
1423: p->chipset_mask = CSMASK_AGA;
1424: break;
1425: }
1426: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.