/* * UAE - The Un*x Amiga Emulator * * Config file handling * This still needs some thought before it's complete... * * Copyright 1998 Brian King, Bernd Schmidt */ #include "sysconfig.h" #include "sysdeps.h" #include #include "options.h" #include "uae.h" #include "audio.h" #include "autoconf.h" #include "inputdevice.h" #include "savestate.h" #include "gui.h" #include "memory.h" #include "rommgr.h" #include "newcpu.h" #include "custom.h" #include "zfile.h" #include "filesys.h" #include "fsdb.h" #include "disk.h" #include "sd-pandora/sound.h" static int config_newfilesystem; static struct strlist *temp_lines; static struct zfile *default_file; static int uaeconfig; /* @@@ need to get rid of this... just cut part of the manual and print that * as a help text. */ struct cfg_lines { const TCHAR *config_label, *config_help; }; static const TCHAR *guimode1[] = { _T("no"), _T("yes"), _T("nowait"), 0 }; static const TCHAR *guimode2[] = { _T("false"), _T("true"), _T("nowait"), 0 }; static const TCHAR *guimode3[] = { _T("0"), _T("1"), _T("nowait"), 0 }; static const TCHAR *csmode[] = { _T("ocs"), _T("ecs_agnus"), _T("ecs_denise"), _T("ecs"), _T("aga"), 0 }; static const TCHAR *speedmode[] = { _T("max"), _T("real"), 0 }; static const TCHAR *soundmode1[] = { _T("none"), _T("interrupts"), _T("normal"), _T("exact"), 0 }; static const TCHAR *soundmode2[] = { _T("none"), _T("interrupts"), _T("good"), _T("best"), 0 }; static const TCHAR *stereomode[] = { _T("mono"), _T("stereo"), _T("clonedstereo"), _T("4ch"), _T("clonedstereo6ch"), _T("6ch"), _T("mixed"), 0 }; static const TCHAR *interpolmode[] = { _T("none"), _T("anti"), _T("sinc"), _T("rh"), _T("crux"), 0 }; static const TCHAR *collmode[] = { _T("none"), _T("sprites"), _T("playfields"), _T("full"), 0 }; static const TCHAR *soundfiltermode1[] = { _T("off"), _T("emulated"), _T("on"), 0 }; static const TCHAR *soundfiltermode2[] = { _T("standard"), _T("enhanced"), 0 }; static const TCHAR *lorestype1[] = { _T("lores"), _T("hires"), _T("superhires"), 0 }; static const TCHAR *lorestype2[] = { _T("true"), _T("false"), 0 }; static const TCHAR *abspointers[] = { _T("none"), _T("mousehack"), _T("tablet"), 0 }; static const TCHAR *rtgtype[] = { _T("ZorroII"), _T("ZorroIII"), 0 }; static const TCHAR *obsolete[] = { _T("accuracy"), _T("gfx_opengl"), _T("gfx_32bit_blits"), _T("32bit_blits"), _T("gfx_immediate_blits"), _T("gfx_ntsc"), _T("win32"), _T("gfx_filter_bits"), _T("sound_pri_cutoff"), _T("sound_pri_time"), _T("sound_min_buff"), _T("sound_bits"), _T("gfx_test_speed"), _T("gfxlib_replacement"), _T("enforcer"), _T("catweasel_io"), _T("kickstart_key_file"), _T("sound_adjust"), _T("sound_latency"), _T("serial_hardware_dtrdsr"), _T("gfx_filter_upscale"), _T("gfx_autoscale"), _T("parallel_sampler"), _T("parallel_ascii_emulation"), _T("avoid_vid"), _T("avoid_dga"), _T("z3chipmem_size"), _T("state_replay_buffer"), _T("state_replay"), NULL }; #define UNEXPANDED _T("$(FILE_PATH)") static void trimwsa (char *s) { /* Delete trailing whitespace. */ int len = strlen (s); while (len > 0 && strcspn (s + len - 1, "\t \r\n") == 0) s[--len] = '\0'; } static int match_string (const TCHAR *table[], const TCHAR *str) { int i; for (i = 0; table[i] != 0; i++) if (strcasecmp (table[i], str) == 0) return i; return -1; } static TCHAR *cfgfile_subst_path2 (const TCHAR *path, const TCHAR *subst, const TCHAR *file) { /* @@@ use strcasecmp for some targets. */ if (_tcslen (path) > 0 && _tcsncmp (file, path, _tcslen (path)) == 0) { int l; TCHAR *p2, *p = xmalloc (TCHAR, _tcslen (file) + _tcslen (subst) + 2); _tcscpy (p, subst); l = _tcslen (p); while (l > 0 && p[l - 1] == '/') p[--l] = '\0'; l = _tcslen (path); while (file[l] == '/') l++; _tcscat (p, _T("/")); _tcscat (p, file + l); p2 = target_expand_environment (p); xfree (p); return p2; } return NULL; } TCHAR *cfgfile_subst_path (const TCHAR *path, const TCHAR *subst, const TCHAR *file) { TCHAR *s = cfgfile_subst_path2 (path, subst, file); if (s) return s; s = target_expand_environment (file); return s; } static bool isdefault (const TCHAR *s) { TCHAR tmp[MAX_DPATH]; if (!default_file || uaeconfig) return false; zfile_fseek (default_file, 0, SEEK_SET); while (zfile_fgets (tmp, sizeof tmp / sizeof (TCHAR), default_file)) { if (tmp[0] && tmp[_tcslen (tmp) - 1] == '\n') tmp[_tcslen (tmp) - 1] = 0; if (!_tcscmp (tmp, s)) return true; } return false; } static size_t cfg_write (const void *b, struct zfile *z) { size_t v; TCHAR lf = 10; v = zfile_fwrite ((void *)b, _tcslen ((TCHAR*)b), sizeof (TCHAR), z); zfile_fwrite (&lf, 1, 1, z); return v; } static void cfg_dowrite (struct zfile *f, const TCHAR *option, const TCHAR *value, int d, int target) { TCHAR tmp[CONFIG_BLEN]; if (value == NULL) return; if (target) _stprintf (tmp, _T("%s.%s=%s"), TARGET_NAME, option, value); else _stprintf (tmp, _T("%s=%s"), option, value); if (d && isdefault (tmp)) goto end; cfg_write (tmp, f); end:; } void cfgfile_write_bool (struct zfile *f, const TCHAR *option, bool b) { cfg_dowrite (f, option, b ? _T("true") : _T("false"), 0, 0); } void cfgfile_dwrite_bool (struct zfile *f, const TCHAR *option, bool b) { cfg_dowrite (f, option, b ? _T("true") : _T("false"), 1, 0); } void cfgfile_dwrite_bool (struct zfile *f, const TCHAR *option, int b) { cfgfile_dwrite_bool (f, option, b != 0); } void cfgfile_write_str (struct zfile *f, const TCHAR *option, const TCHAR *value) { cfg_dowrite (f, option, value, 0, 0); } void cfgfile_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value) { cfg_dowrite (f, option, value, 1, 0); } void cfgfile_target_write_bool (struct zfile *f, const TCHAR *option, bool b) { cfg_dowrite (f, option, b ? _T("true") : _T("false"), 0, 1); } void cfgfile_target_dwrite_bool (struct zfile *f, const TCHAR *option, bool b) { cfg_dowrite (f, option, b ? _T("true") : _T("false"), 1, 1); } void cfgfile_target_write_str (struct zfile *f, const TCHAR *option, const TCHAR *value) { cfg_dowrite (f, option, value, 0, 1); } void cfgfile_target_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value) { cfg_dowrite (f, option, value, 1, 1); } void cfgfile_write (struct zfile *f, const TCHAR *option, const TCHAR *format,...) { va_list parms; TCHAR tmp[CONFIG_BLEN]; va_start (parms, format); _vsntprintf (tmp, CONFIG_BLEN, format, parms); cfg_dowrite (f, option, tmp, 0, 0); va_end (parms); } void cfgfile_dwrite (struct zfile *f, const TCHAR *option, const TCHAR *format,...) { va_list parms; TCHAR tmp[CONFIG_BLEN]; va_start (parms, format); _vsntprintf (tmp, CONFIG_BLEN, format, parms); cfg_dowrite (f, option, tmp, 1, 0); va_end (parms); } void cfgfile_target_write (struct zfile *f, const TCHAR *option, const TCHAR *format,...) { va_list parms; TCHAR tmp[CONFIG_BLEN]; va_start (parms, format); _vsntprintf (tmp, CONFIG_BLEN, format, parms); cfg_dowrite (f, option, tmp, 0, 1); va_end (parms); } void cfgfile_target_dwrite (struct zfile *f, const TCHAR *option, const TCHAR *format,...) { va_list parms; TCHAR tmp[CONFIG_BLEN]; va_start (parms, format); _vsntprintf (tmp, CONFIG_BLEN, format, parms); cfg_dowrite (f, option, tmp, 1, 1); va_end (parms); } static void cfgfile_write_rom (struct zfile *f, const TCHAR *path, const TCHAR *romfile, const TCHAR *name) { TCHAR *str = cfgfile_subst_path (path, UNEXPANDED, romfile); cfgfile_write_str (f, name, str); struct zfile *zf = zfile_fopen (str, _T("rb"), ZFD_ALL); if (zf) { struct romdata *rd = getromdatabyzfile (zf); if (rd) { TCHAR name2[MAX_DPATH], str2[MAX_DPATH]; _tcscpy (name2, name); _tcscat (name2, _T("_id")); _stprintf (str2, _T("%08X,%s"), rd->crc32, rd->name); cfgfile_write_str (f, name2, str2); } zfile_fclose (zf); } xfree (str); } static void write_filesys_config (struct uae_prefs *p, const TCHAR *unexpanded, const TCHAR *default_path, struct zfile *f) { int i; TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH]; const TCHAR *hdcontrollers[] = { _T("uae"), _T("ide0"), _T("ide1"), _T("ide2"), _T("ide3"), _T("scsi0"), _T("scsi1"), _T("scsi2"), _T("scsi3"), _T("scsi4"), _T("scsi5"), _T("scsi6"), _T("scsram"), _T("scide") }; /* scsram = smart card sram = pcmcia sram card */ for (i = 0; i < p->mountitems; i++) { struct uaedev_config_info *uci = &p->mountconfig[i]; TCHAR *str; int bp = uci->bootpri; if (!uci->autoboot) bp = -128; if (uci->donotmount) bp = -129; str = cfgfile_subst_path (default_path, unexpanded, uci->rootdir); if (!uci->ishdf) { _stprintf (tmp, _T("%s,%s:%s:%s,%d"), uci->readonly ? _T("ro") : _T("rw"), uci->devname ? uci->devname : _T(""), uci->volname, str, bp); cfgfile_write_str (f, _T("filesystem2"), tmp); } else { _stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"), uci->readonly ? _T("ro") : _T("rw"), uci->devname ? uci->devname : _T(""), str, uci->sectors, uci->surfaces, uci->reserved, uci->blocksize, bp, uci->filesys ? uci->filesys : _T(""), hdcontrollers[uci->controller]); cfgfile_write_str (f, _T("hardfile2"), tmp); } _stprintf (tmp2, _T("uaehf%d"), i); cfgfile_write (f, tmp2, _T("%s,%s"), uci->ishdf ? _T("hdf") : _T("dir"), tmp); xfree (str); } } static void write_compatibility_cpu(struct zfile *f, struct uae_prefs *p) { TCHAR tmp[100]; int model; model = p->cpu_model; if (model == 68030) model = 68020; if (model == 68060) model = 68040; if (p->address_space_24 && model == 68020) _tcscpy (tmp, _T("68ec020")); else _stprintf(tmp, _T("%d"), model); if (model == 68020 && (p->fpu_model == 68881 || p->fpu_model == 68882)) _tcscat(tmp, _T("/68881")); cfgfile_write (f, _T("cpu_type"), tmp); } void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) { struct strlist *sl; TCHAR *str, tmp[MAX_DPATH]; int i; cfgfile_write_str (f, _T("config_description"), p->description); cfgfile_write_bool (f, _T("config_hardware"), type & CONFIG_TYPE_HARDWARE); cfgfile_write_bool (f, _T("config_host"), !!(type & CONFIG_TYPE_HOST)); if (p->info[0]) cfgfile_write (f, _T("config_info"), p->info); cfgfile_write (f, _T("config_version"), _T("%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV); for (sl = p->all_lines; sl; sl = sl->next) { if (sl->unknown) { if (sl->option) cfgfile_write_str (f, sl->option, sl->value); } } _stprintf (tmp, _T("%s.rom_path"), TARGET_NAME); cfgfile_write_str (f, tmp, p->path_rom); _stprintf (tmp, _T("%s.floppy_path"), TARGET_NAME); cfgfile_write_str (f, tmp, p->path_floppy); _stprintf (tmp, _T("%s.hardfile_path"), TARGET_NAME); cfgfile_write_str (f, tmp, p->path_hardfile); cfg_write (_T("; host-specific"), f); target_save_options (f, p); cfg_write (_T("; common"), f); cfgfile_write_str (f, _T("use_gui"), guimode1[p->start_gui]); cfgfile_write_rom (f, p->path_rom, p->romfile, _T("kickstart_rom_file")); cfgfile_write_rom (f, p->path_rom, p->romextfile, _T("kickstart_ext_rom_file")); p->nr_floppies = 4; for (i = 0; i < 4; i++) { str = cfgfile_subst_path (p->path_floppy, UNEXPANDED, p->floppyslots[i].df); _stprintf (tmp, _T("floppy%d"), i); cfgfile_write_str (f, tmp, str); xfree (str); _stprintf (tmp, _T("floppy%dtype"), i); cfgfile_dwrite (f, tmp, _T("%d"), p->floppyslots[i].dfxtype); if (p->floppyslots[i].dfxtype < 0 && p->nr_floppies > i) p->nr_floppies = i; } cfgfile_write (f, _T("nr_floppies"), _T("%d"), p->nr_floppies); cfgfile_write (f, _T("floppy_speed"), _T("%d"), p->floppy_speed); cfgfile_write_str (f, _T("sound_output"), soundmode1[p->produce_sound]); cfgfile_write_str (f, _T("sound_channels"), stereomode[p->sound_stereo]); cfgfile_write (f, _T("sound_stereo_separation"), _T("%d"), p->sound_stereo_separation); cfgfile_write (f, _T("sound_stereo_mixing_delay"), _T("%d"), p->sound_mixed_stereo_delay >= 0 ? p->sound_mixed_stereo_delay : 0); cfgfile_write (f, _T("sound_frequency"), _T("%d"), p->sound_freq); cfgfile_write_str (f, _T("sound_interpol"), interpolmode[p->sound_interpol]); cfgfile_write_str (f, _T("sound_filter"), soundfiltermode1[p->sound_filter]); cfgfile_write_str (f, _T("sound_filter_type"), soundfiltermode2[p->sound_filter_type]); cfgfile_write (f, _T("cachesize"), _T("%d"), p->cachesize); cfgfile_write_bool (f, _T("bsdsocket_emu"), p->socket_emu); cfgfile_write_bool (f, _T("synchronize_clock"), p->tod_hack); cfgfile_dwrite_str (f, _T("absolute_mouse"), abspointers[p->input_tablet]); cfgfile_write (f, _T("gfx_framerate"), _T("%d"), p->gfx_framerate); cfgfile_write (f, _T("gfx_width"), _T("%d"), p->gfx_size.width); cfgfile_write (f, _T("gfx_height"), _T("%d"), p->gfx_size.height); cfgfile_write (f, _T("gfx_width_windowed"), _T("%d"), p->gfx_size_win.width); cfgfile_write (f, _T("gfx_height_windowed"), _T("%d"), p->gfx_size_win.height); cfgfile_write (f, _T("gfx_width_fullscreen"), _T("%d"), p->gfx_size_fs.width); cfgfile_write (f, _T("gfx_height_fullscreen"), _T("%d"), p->gfx_size_fs.height); cfgfile_write_bool (f, _T("gfx_lores"), p->gfx_resolution == 0); cfgfile_write_str (f, _T("gfx_resolution"), lorestype1[p->gfx_resolution]); #ifdef RASPBERRY cfgfile_write (f, _T("gfx_correct_aspect"), _T("%d"), p->gfx_correct_aspect); cfgfile_write (f, _T("gfx_fullscreen_ratio"), _T("%d"), p->gfx_fullscreen_ratio); #endif cfgfile_write_bool (f, _T("immediate_blits"), p->immediate_blits); cfgfile_write_bool (f, _T("fast_copper"), p->fast_copper); cfgfile_write_bool (f, _T("ntsc"), p->ntscmode); cfgfile_dwrite_bool (f, _T("show_leds"), p->leds_on_screen); if (p->chipset_mask & CSMASK_AGA) cfgfile_dwrite (f, _T("chipset"), _T("aga")); else if ((p->chipset_mask & CSMASK_ECS_AGNUS) && (p->chipset_mask & CSMASK_ECS_DENISE)) cfgfile_dwrite (f, _T("chipset"), _T("ecs")); else if (p->chipset_mask & CSMASK_ECS_AGNUS) cfgfile_dwrite (f, _T("chipset"), _T("ecs_agnus")); else if (p->chipset_mask & CSMASK_ECS_DENISE) cfgfile_dwrite (f, _T("chipset"), _T("ecs_denise")); else cfgfile_dwrite (f, _T("chipset"), _T("ocs")); cfgfile_write_str (f, _T("collision_level"), collmode[p->collision_level]); cfgfile_write (f, _T("fastmem_size"), _T("%d"), p->fastmem_size / 0x100000); cfgfile_write (f, _T("z3mem_size"), _T("%d"), p->z3fastmem_size / 0x100000); cfgfile_write (f, _T("z3mem_start"), _T("0x%x"), p->z3fastmem_start); cfgfile_write (f, _T("bogomem_size"), _T("%d"), p->bogomem_size / 0x40000); cfgfile_write (f, _T("gfxcard_size"), _T("%d"), p->rtgmem_size / 0x100000); cfgfile_write_str (f, _T("gfxcard_type"), rtgtype[p->rtgmem_type]); cfgfile_write (f, _T("chipmem_size"), _T("%d"), p->chipmem_size == 0x20000 ? -1 : (p->chipmem_size == 0x40000 ? 0 : p->chipmem_size / 0x80000)); if (p->m68k_speed > 0) { cfgfile_write (f, _T("finegrain_cpu_speed"), _T("%d"), p->m68k_speed); } else { cfgfile_write_str (f, _T("cpu_speed"), p->m68k_speed < 0 ? _T("max") : _T("real")); } /* do not reorder start */ write_compatibility_cpu(f, p); cfgfile_write (f, _T("cpu_model"), _T("%d"), p->cpu_model); if (p->fpu_model) cfgfile_write (f, _T("fpu_model"), _T("%d"), p->fpu_model); cfgfile_write_bool (f, _T("cpu_compatible"), p->cpu_compatible); cfgfile_write_bool (f, _T("cpu_24bit_addressing"), p->address_space_24); /* do not reorder end */ cfgfile_write (f, _T("rtg_modes"), _T("0x%x"), p->picasso96_modeflags); #ifdef FILESYS write_filesys_config (p, UNEXPANDED, p->path_hardfile, f); #endif write_inputdevice_config (p, f); } int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location) { if (name != NULL && _tcscmp (option, name) != 0) return 0; if (strcasecmp (value, _T("yes")) == 0 || strcasecmp (value, _T("y")) == 0 || strcasecmp (value, _T("true")) == 0 || strcasecmp (value, _T("t")) == 0) *location = 1; else if (strcasecmp (value, _T("no")) == 0 || strcasecmp (value, _T("n")) == 0 || strcasecmp (value, _T("false")) == 0 || strcasecmp (value, _T("f")) == 0 || strcasecmp (value, _T("0")) == 0) *location = 0; else { write_log (_T("Option `%s' requires a value of either `yes' or `no' (was '%s').\n"), option, value); return -1; } return 1; } int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, bool *location) { int val; int ret = cfgfile_yesno (option, value, name, &val); if (ret == 0) return 0; if (ret < 0) *location = false; else *location = val != 0; return 1; } int cfgfile_doubleval (const TCHAR *option, const TCHAR *value, const TCHAR *name, double *location) { int base = 10; TCHAR *endptr; if (name != NULL && _tcscmp (option, name) != 0) return 0; *location = _tcstod (value, &endptr); return 1; } int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, unsigned int *location, int scale) { int base = 10; TCHAR *endptr; if (name != NULL && _tcscmp (option, name) != 0) return 0; /* I guess octal isn't popular enough to worry about here... */ if (value[0] == '0' && _totupper(value[1]) == 'X') value += 2, base = 16; *location = _tcstol (value, &endptr, base) * scale; if (*endptr != '\0' || *value == '\0') { if (strcasecmp (value, _T("false")) == 0 || strcasecmp (value, _T("no")) == 0) { *location = 0; return 1; } if (strcasecmp (value, _T("true")) == 0 || strcasecmp (value, _T("yes")) == 0) { *location = 1; return 1; } write_log (_T("Option '%s' requires a numeric argument but got '%s'\n"), option, value); return -1; } return 1; } int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, int scale) { unsigned int v = 0; int r = cfgfile_intval (option, value, name, &v, scale); if (!r) return 0; *location = (int)v; return r; } int cfgfile_strval (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, const TCHAR *table[], int more) { int val; if (name != NULL && _tcscmp (option, name) != 0) return 0; val = match_string (table, value); if (val == -1) { if (more) return 0; write_log (_T("Unknown value ('%s') for option '%s'.\n"), value, option); return -1; } *location = val; return 1; } int cfgfile_strboolval (const TCHAR *option, const TCHAR *value, const TCHAR *name, bool *location, const TCHAR *table[], int more) { int locationint; if (!cfgfile_strval (option, value, name, &locationint, table, more)) return 0; *location = locationint != 0; return 1; } int cfgfile_string (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz) { if (_tcscmp (option, name) != 0) return 0; _tcsncpy (location, value, maxsz - 1); location[maxsz - 1] = '\0'; return 1; } int cfgfile_path (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz) { if (!cfgfile_string (option, value, name, location, maxsz)) return 0; TCHAR *s = target_expand_environment (location); _tcsncpy (location, s, maxsz - 1); location[maxsz - 1] = 0; xfree (s); return 1; } int cfgfile_rom (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz) { TCHAR id[MAX_DPATH]; if (!cfgfile_string (option, value, name, id, sizeof id / sizeof (TCHAR))) return 0; if (zfile_exists (location)) return 1; TCHAR *p = _tcschr (id, ','); if (p) { TCHAR *endptr, tmp; *p = 0; tmp = id[4]; id[4] = 0; uae_u32 crc32 = _tcstol (id, &endptr, 16) << 16; id[4] = tmp; crc32 |= _tcstol (id + 4, &endptr, 16); struct romdata *rd = getromdatabycrc (crc32); if (rd) { struct romlist *rl = getromlistbyromdata (rd); if (rl) { write_log (_T("%s: %s -> %s\n"), name, location, rl->path); _tcsncpy (location, rl->path, maxsz); } } } return 1; } static int getintval (TCHAR **p, int *result, int delim) { TCHAR *value = *p; int base = 10; TCHAR *endptr; TCHAR *p2 = _tcschr (*p, delim); if (p2 == 0) return 0; *p2++ = '\0'; if (value[0] == '0' && _totupper (value[1]) == 'X') value += 2, base = 16; *result = _tcstol (value, &endptr, base); *p = p2; if (*endptr != '\0' || *value == '\0') return 0; return 1; } static int getintval2 (TCHAR **p, int *result, int delim) { TCHAR *value = *p; int base = 10; TCHAR *endptr; TCHAR *p2 = _tcschr (*p, delim); if (p2 == 0) { p2 = _tcschr (*p, 0); if (p2 == 0) { *p = 0; return 0; } } if (*p2 != 0) *p2++ = '\0'; if (value[0] == '0' && _totupper (value[1]) == 'X') value += 2, base = 16; *result = _tcstol (value, &endptr, base); *p = p2; if (*endptr != '\0' || *value == '\0') { *p = 0; return 0; } return 1; } static void set_chipset_mask (struct uae_prefs *p, int val) { p->chipset_mask = (val == 0 ? 0 : val == 1 ? CSMASK_ECS_AGNUS : val == 2 ? CSMASK_ECS_DENISE : val == 3 ? CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS : CSMASK_AGA | CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS); } static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) { int i; bool vb; TCHAR *section = 0; TCHAR *tmpp; TCHAR tmpbuf[CONFIG_BLEN]; if (_tcsncmp (option, _T("input."), 6) == 0) { read_inputdevice_config (p, option, value); return 1; } for (tmpp = option; *tmpp != '\0'; tmpp++) if (_istupper (*tmpp)) *tmpp = _totlower (*tmpp); tmpp = _tcschr (option, '.'); if (tmpp) { section = option; option = tmpp + 1; *tmpp = '\0'; if (_tcscmp (section, TARGET_NAME) == 0) { /* We special case the various path options here. */ if (cfgfile_path (option, value, _T("rom_path"), p->path_rom, sizeof p->path_rom / sizeof (TCHAR)) || cfgfile_path (option, value, _T("floppy_path"), p->path_floppy, sizeof p->path_floppy / sizeof (TCHAR)) || cfgfile_path (option, value, _T("hardfile_path"), p->path_hardfile, sizeof p->path_hardfile / sizeof (TCHAR))) return 1; return target_parse_option (p, option, value); } return 0; } if (cfgfile_intval (option, value, _T("sound_frequency"), &p->sound_freq, 1) || cfgfile_intval (option, value, _T("sound_stereo_separation"), &p->sound_stereo_separation, 1) || cfgfile_intval (option, value, _T("sound_stereo_mixing_delay"), &p->sound_mixed_stereo_delay, 1) || cfgfile_intval (option, value, _T("gfx_framerate"), &p->gfx_framerate, 1) || cfgfile_intval (option, value, _T("gfx_width_windowed"), &p->gfx_size_win.width, 1) || cfgfile_intval (option, value, _T("gfx_height_windowed"), &p->gfx_size_win.height, 1) || cfgfile_intval (option, value, _T("gfx_width_fullscreen"), &p->gfx_size_fs.width, 1) || cfgfile_intval (option, value, _T("gfx_height_fullscreen"), &p->gfx_size_fs.height, 1)) return 1; #ifdef RASPBERRY if (cfgfile_intval (option, value, "gfx_correct_aspect", &p->gfx_correct_aspect, 1)) return 1; if (cfgfile_intval (option, value, "gfx_fullscreen_ratio", &p->gfx_fullscreen_ratio, 1)) return 1; #endif if (cfgfile_string (option, value, _T("config_info"), p->info, sizeof p->info / sizeof (TCHAR)) || cfgfile_string (option, value, _T("config_description"), p->description, sizeof p->description / sizeof (TCHAR))) return 1; if (cfgfile_yesno (option, value, _T("synchronize_clock"), &p->tod_hack) || cfgfile_yesno (option, value, _T("bsdsocket_emu"), &p->socket_emu)) return 1; if (cfgfile_strval (option, value, _T("sound_output"), &p->produce_sound, soundmode1, 1) || cfgfile_strval (option, value, _T("sound_output"), &p->produce_sound, soundmode2, 0) || cfgfile_strval (option, value, _T("sound_interpol"), &p->sound_interpol, interpolmode, 0) || cfgfile_strval (option, value, _T("sound_filter"), &p->sound_filter, soundfiltermode1, 0) || cfgfile_strval (option, value, _T("sound_filter_type"), &p->sound_filter_type, soundfiltermode2, 0) || cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode1, 1) || cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode2, 1) || cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode3, 0) || cfgfile_strval (option, value, _T("gfx_resolution"), &p->gfx_resolution, lorestype1, 0) || cfgfile_strval (option, value, _T("gfx_lores"), &p->gfx_resolution, lorestype2, 0) || cfgfile_strval (option, value, _T("absolute_mouse"), &p->input_tablet, abspointers, 0)) return 1; if(cfgfile_yesno (option, value, _T("show_leds"), &vb)) { p->leds_on_screen = vb; return 1; } if (_tcscmp (option, _T("gfx_width")) == 0 || _tcscmp (option, _T("gfx_height")) == 0) { cfgfile_intval (option, value, _T("gfx_width"), &p->gfx_size.width, 1); cfgfile_intval (option, value, _T("gfx_height"), &p->gfx_size.height, 1); return 1; } if (cfgfile_string (option, value, _T("statefile"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) { _tcscpy (savestate_fname, tmpbuf); if (zfile_exists (savestate_fname)) { savestate_state = STATE_DORESTORE; } else { int ok = 0; if (savestate_fname[0]) { for (;;) { TCHAR *p; if (my_existsdir (savestate_fname)) { ok = 1; break; } p = _tcsrchr (savestate_fname, '\\'); if (!p) p = _tcsrchr (savestate_fname, '/'); if (!p) break; *p = 0; } } if (!ok) savestate_fname[0] = 0; } return 1; } if (cfgfile_strval (option, value, _T("sound_channels"), &p->sound_stereo, stereomode, 1)) { if (p->sound_stereo == SND_NONE) { /* "mixed stereo" compatibility hack */ p->sound_stereo = SND_STEREO; p->sound_mixed_stereo_delay = 5; p->sound_stereo_separation = 7; } return 1; } if (cfgfile_string (option, value, _T("config_version"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) { TCHAR *tmpp2; tmpp = _tcschr (value, '.'); if (tmpp) { *tmpp++ = 0; tmpp2 = tmpp; p->config_version = _tstol (tmpbuf) << 16; tmpp = _tcschr (tmpp, '.'); if (tmpp) { *tmpp++ = 0; p->config_version |= _tstol (tmpp2) << 8; p->config_version |= _tstol (tmpp); } } return 1; } return 0; } static struct uaedev_config_info *getuci(struct uae_prefs *p) { if (p->mountitems < MOUNT_CONFIG_SIZE) return &p->mountconfig[p->mountitems++]; return NULL; } struct uaedev_config_info *add_filesys_config (struct uae_prefs *p, int index, TCHAR *devname, TCHAR *volname, TCHAR *rootdir, bool readonly, int secspertrack, int surfaces, int reserved, int blocksize, int bootpri, TCHAR *filesysdir, int hdc, int flags) { struct uaedev_config_info *uci; int i; TCHAR *s; if (index < 0 && devname && _tcslen (devname) > 0) { for (i = 0; i < p->mountitems; i++) { if (p->mountconfig[i].devname && !_tcscmp (p->mountconfig[i].devname, devname)) return 0; } } if (index < 0) { uci = getuci(p); uci->configoffset = -1; } else { uci = &p->mountconfig[index]; } if (!uci) return 0; uci->ishdf = volname == NULL ? 1 : 0; _tcscpy (uci->devname, devname ? devname : _T("")); _tcscpy (uci->volname, volname ? volname : _T("")); _tcscpy (uci->rootdir, rootdir ? rootdir : _T("")); validatedevicename (uci->devname); validatevolumename (uci->volname); uci->readonly = readonly; uci->sectors = secspertrack; uci->surfaces = surfaces; uci->reserved = reserved; uci->blocksize = blocksize; uci->bootpri = bootpri; uci->donotmount = 0; uci->autoboot = 0; if (bootpri < -128) uci->donotmount = 1; else if (bootpri >= -127) uci->autoboot = 1; uci->controller = hdc; _tcscpy (uci->filesys, filesysdir ? filesysdir : _T("")); if (!uci->devname[0]) { TCHAR base[32]; TCHAR base2[32]; int num = 0; if (uci->rootdir[0] == 0 && !uci->ishdf) _tcscpy (base, _T("RDH")); else _tcscpy (base, _T("DH")); _tcscpy (base2, base); for (i = 0; i < p->mountitems; i++) { _stprintf (base2, _T("%s%d"), base, num); if (!_tcscmp(base2, p->mountconfig[i].devname)) { num++; i = -1; continue; } } _tcscpy (uci->devname, base2); validatedevicename (uci->devname); } s = filesys_createvolname (volname, rootdir, _T("Harddrive")); _tcscpy (uci->volname, s); xfree (s); return uci; } static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHAR *value) { int secs, heads, reserved, bs, bp, hdcv; bool ro; TCHAR *dname = NULL, *aname = _T(""), *root = NULL, *fs = NULL, *hdc; TCHAR *tmpp = _tcschr (value, ','); TCHAR *str = NULL; config_newfilesystem = 1; if (tmpp == 0) goto invalid_fs; *tmpp++ = '\0'; if (strcasecmp (value, _T("ro")) == 0) ro = true; else if (strcasecmp (value, _T("rw")) == 0) ro = false; else goto invalid_fs; secs = 0; heads = 0; reserved = 0; bs = 0; bp = 0; fs = 0; hdc = 0; hdcv = 0; value = tmpp; if (!hdf) { tmpp = _tcschr (value, ':'); if (tmpp == 0) goto empty_fs; *tmpp++ = 0; dname = value; aname = tmpp; tmpp = _tcschr (tmpp, ':'); if (tmpp == 0) goto empty_fs; *tmpp++ = 0; root = tmpp; tmpp = _tcschr (tmpp, ','); if (tmpp == 0) goto empty_fs; *tmpp++ = 0; if (! getintval (&tmpp, &bp, 0)) goto empty_fs; } else { tmpp = _tcschr (value, ':'); if (tmpp == 0) goto invalid_fs; *tmpp++ = '\0'; dname = value; root = tmpp; tmpp = _tcschr (tmpp, ','); if (tmpp == 0) goto invalid_fs; *tmpp++ = 0; aname = 0; if (! getintval (&tmpp, &secs, ',') || ! getintval (&tmpp, &heads, ',') || ! getintval (&tmpp, &reserved, ',') || ! getintval (&tmpp, &bs, ',')) goto invalid_fs; if (getintval2 (&tmpp, &bp, ',')) { fs = tmpp; tmpp = _tcschr (tmpp, ','); if (tmpp != 0) { *tmpp++ = 0; hdc = tmpp; if(_tcslen(hdc) >= 4 && !_tcsncmp(hdc, _T("ide"), 3)) { hdcv = hdc[3] - '0' + HD_CONTROLLER_IDE0; if (hdcv < HD_CONTROLLER_IDE0 || hdcv > HD_CONTROLLER_IDE3) hdcv = 0; } if(_tcslen(hdc) >= 5 && !_tcsncmp(hdc, _T("scsi"), 4)) { hdcv = hdc[4] - '0' + HD_CONTROLLER_SCSI0; if (hdcv < HD_CONTROLLER_SCSI0 || hdcv > HD_CONTROLLER_SCSI6) hdcv = 0; } if (_tcslen (hdc) >= 6 && !_tcsncmp (hdc, _T("scsram"), 6)) hdcv = HD_CONTROLLER_PCMCIA_SRAM; if (_tcslen (hdc) >= 5 && !_tcsncmp (hdc, _T("scide"), 6)) hdcv = HD_CONTROLLER_PCMCIA_IDE; } } } empty_fs: if (root) { if (_tcslen (root) > 3 && root[0] == 'H' && root[1] == 'D' && root[2] == '_') { root += 2; *root = ':'; } str = cfgfile_subst_path (UNEXPANDED, p->path_hardfile, root); } #ifdef FILESYS add_filesys_config (p, nr, dname, aname, str, ro, secs, heads, reserved, bs, bp, fs, hdcv, 0); #endif xfree (str); return 1; invalid_fs: write_log (_T("Invalid filesystem/hardfile specification.\n")); return 1; } static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHAR *value) { int i; for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) { TCHAR tmp[100]; _stprintf (tmp, _T("uaehf%d"), i); if (_tcscmp (option, tmp) == 0) { for (;;) { bool hdf = false; TCHAR *tmpp = _tcschr (value, ','); if (tmpp == NULL) return 1; *tmpp++ = 0; if (strcasecmp (value, _T("hdf")) == 0) { hdf = true; } else if (strcasecmp (value, _T("dir")) != 0) { return 1; } #if 0 // not yet return cfgfile_parse_newfilesys (p, i, hdf, tmpp); #else return 1; #endif } return 1; } } if (_tcscmp (option, _T("filesystem")) == 0 || _tcscmp (option, _T("hardfile")) == 0) { int secs, heads, reserved, bs; bool ro; TCHAR *aname, *root; TCHAR *tmpp = _tcschr (value, ','); TCHAR *str; if (config_newfilesystem) return 1; if (tmpp == 0) goto invalid_fs; *tmpp++ = '\0'; if (_tcscmp (value, _T("1")) == 0 || strcasecmp (value, _T("ro")) == 0 || strcasecmp (value, _T("readonly")) == 0 || strcasecmp (value, _T("read-only")) == 0) ro = true; else if (_tcscmp (value, _T("0")) == 0 || strcasecmp (value, _T("rw")) == 0 || strcasecmp (value, _T("readwrite")) == 0 || strcasecmp (value, _T("read-write")) == 0) ro = false; else goto invalid_fs; secs = 0; heads = 0; reserved = 0; bs = 0; value = tmpp; if (_tcscmp (option, _T("filesystem")) == 0) { tmpp = _tcschr (value, ':'); if (tmpp == 0) goto invalid_fs; *tmpp++ = '\0'; aname = value; root = tmpp; } else { if (! getintval (&value, &secs, ',') || ! getintval (&value, &heads, ',') || ! getintval (&value, &reserved, ',') || ! getintval (&value, &bs, ',')) goto invalid_fs; root = value; aname = 0; } str = cfgfile_subst_path (UNEXPANDED, p->path_hardfile, root); #ifdef FILESYS add_filesys_config (p, -1, NULL, aname, str, ro, secs, heads, reserved, bs, 0, NULL, 0, 0); #endif free (str); return 1; invalid_fs: write_log (_T("Invalid filesystem/hardfile specification.\n")); return 1; } if (_tcscmp (option, _T("filesystem2")) == 0) return cfgfile_parse_newfilesys (p, -1, false, value); if (_tcscmp (option, _T("hardfile2")) == 0) return cfgfile_parse_newfilesys (p, -1, true, value); return 0; } static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCHAR *value) { int tmpval, dummyint, i; TCHAR *section = 0; TCHAR tmpbuf[CONFIG_BLEN]; if (cfgfile_yesno (option, value, _T("immediate_blits"), &p->immediate_blits) || cfgfile_yesno (option, value, _T("fast_copper"), &p->fast_copper) || cfgfile_yesno (option, value, _T("ntsc"), &p->ntscmode) || cfgfile_yesno (option, value, _T("cpu_compatible"), &p->cpu_compatible) || cfgfile_yesno (option, value, _T("cpu_24bit_addressing"), &p->address_space_24)) return 1; if (cfgfile_intval (option, value, _T("cachesize"), &p->cachesize, 1) || cfgfile_intval (option, value, _T("chipset_refreshrate"), &p->chipset_refreshrate, 1) || cfgfile_intval (option, value, _T("fastmem_size"), &p->fastmem_size, 0x100000) || cfgfile_intval (option, value, _T("z3mem_size"), &p->z3fastmem_size, 0x100000) || cfgfile_intval (option, value, _T("z3mem_start"), &p->z3fastmem_start, 1) || cfgfile_intval (option, value, _T("bogomem_size"), &p->bogomem_size, 0x40000) || cfgfile_intval (option, value, _T("gfxcard_size"), &p->rtgmem_size, 0x100000) || cfgfile_strval (option, value, _T("gfxcard_type"), &p->rtgmem_type, rtgtype, 0) || cfgfile_intval (option, value, _T("rtg_modes"), &p->picasso96_modeflags, 1) || cfgfile_intval (option, value, _T("floppy_speed"), &p->floppy_speed, 1) || cfgfile_intval (option, value, _T("floppy_write_length"), &p->floppy_write_length, 1) || cfgfile_intval (option, value, _T("nr_floppies"), &p->nr_floppies, 1) || cfgfile_intval (option, value, _T("floppy0type"), &p->floppyslots[0].dfxtype, 1) || cfgfile_intval (option, value, _T("floppy1type"), &p->floppyslots[1].dfxtype, 1) || cfgfile_intval (option, value, _T("floppy2type"), &p->floppyslots[2].dfxtype, 1) || cfgfile_intval (option, value, _T("floppy3type"), &p->floppyslots[3].dfxtype, 1)) return 1; if (cfgfile_strval (option, value, _T("collision_level"), &p->collision_level, collmode, 0)) return 1; if (cfgfile_string (option, value, _T("kickstart_rom_file"), p->romfile, sizeof p->romfile) || cfgfile_string (option, value, _T("kickstart_ext_rom_file"), p->romextfile, sizeof p->romextfile)) return 1; for (i = 0; i < 4; i++) { _stprintf (tmpbuf, _T("floppy%d"), i); if (cfgfile_path (option, value, tmpbuf, p->floppyslots[i].df, sizeof p->floppyslots[i].df / sizeof (TCHAR))) return 1; } if (cfgfile_intval (option, value, _T("chipmem_size"), &dummyint, 1)) { if (dummyint < 0) p->chipmem_size = 0x20000; /* 128k, prototype support */ else if (dummyint == 0) p->chipmem_size = 0x40000; /* 256k */ else p->chipmem_size = dummyint * 0x80000; return 1; } if (cfgfile_strval (option, value, _T("chipset"), &tmpval, csmode, 0)) { set_chipset_mask (p, tmpval); return 1; } if (cfgfile_string (option, value, _T("fpu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) { p->fpu_model = _tstol(tmpbuf); return 1; } if (cfgfile_string (option, value, _T("cpu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) { p->cpu_model = _tstol(tmpbuf); p->fpu_model = 0; return 1; } /* old-style CPU configuration */ if (cfgfile_string (option, value, _T("cpu_type"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) { p->fpu_model = 0; p->address_space_24 = 0; p->cpu_model = 680000; if (!_tcscmp (tmpbuf, _T("68000"))) { p->cpu_model = 68000; } else if (!_tcscmp (tmpbuf, _T("68010"))) { p->cpu_model = 68010; } else if (!_tcscmp (tmpbuf, _T("68ec020"))) { p->cpu_model = 68020; p->address_space_24 = 1; } else if (!_tcscmp (tmpbuf, _T("68020"))) { p->cpu_model = 68020; } else if (!_tcscmp (tmpbuf, _T("68ec020/68881"))) { p->cpu_model = 68020; p->fpu_model = 68881; p->address_space_24 = 1; } else if (!_tcscmp (tmpbuf, _T("68020/68881"))) { p->cpu_model = 68020; p->fpu_model = 68881; } else if (!_tcscmp (tmpbuf, _T("68040"))) { p->cpu_model = 68040; p->fpu_model = 68040; } else if (!_tcscmp (tmpbuf, _T("68060"))) { p->cpu_model = 68060; p->fpu_model = 68060; } return 1; } if (p->config_version < (21 << 16)) { if (cfgfile_strval (option, value, _T("cpu_speed"), &p->m68k_speed, speedmode, 1) /* Broken earlier versions used to write this out as a string. */ || cfgfile_strval (option, value, _T("finegraincpu_speed"), &p->m68k_speed, speedmode, 1)) { p->m68k_speed--; return 1; } } if (cfgfile_intval (option, value, _T("cpu_speed"), &p->m68k_speed, 1)) { p->m68k_speed *= CYCLE_UNIT; return 1; } if (cfgfile_intval (option, value, _T("finegrain_cpu_speed"), &p->m68k_speed, 1)) { if (OFFICIAL_CYCLE_UNIT > CYCLE_UNIT) { int factor = OFFICIAL_CYCLE_UNIT / CYCLE_UNIT; p->m68k_speed = (p->m68k_speed + factor - 1) / factor; } if (strcasecmp (value, _T("max")) == 0) p->m68k_speed = -1; return 1; } if (cfgfile_parse_filesys (p, option, value)) return 1; return 0; } int cfgfile_parse_option (struct uae_prefs *p, TCHAR *option, TCHAR *value, int type) { if (!_tcscmp (option, _T("config_hardware"))) return 1; if (!_tcscmp (option, _T("config_host"))) return 1; if (type == 0 || (type & CONFIG_TYPE_HARDWARE)) { if (cfgfile_parse_hardware (p, option, value)) return 1; } if (type == 0 || (type & CONFIG_TYPE_HOST)) { if (cfgfile_parse_host (p, option, value)) return 1; } if (type > 0 && (type & (CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST)) != (CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST)) return 1; return 0; } static int cfgfile_separate_linea (char *line, TCHAR *line1b, TCHAR *line2b) { char *line1, *line2; int i; line1 = line; line1 += strspn (line1, "\t \r\n"); if (*line1 == ';') return 0; line2 = strchr (line, '='); if (! line2) { write_log ("CFGFILE: line was incomplete with only %s\n", line1); return 0; } *line2++ = '\0'; /* Get rid of whitespace. */ i = strlen (line2); while (i > 0 && (line2[i - 1] == '\t' || line2[i - 1] == ' ' || line2[i - 1] == '\r' || line2[i - 1] == '\n')) line2[--i] = '\0'; line2 += strspn (line2, "\t \r\n"); i = strlen (line); while (i > 0 && (line[i - 1] == '\t' || line[i - 1] == ' ' || line[i - 1] == '\r' || line[i - 1] == '\n')) line[--i] = '\0'; line += strspn (line, "\t \r\n"); _tcscpy (line1b, line); _tcscpy (line2b, line2); return 1; } static int cfgfile_separate_line (TCHAR *line, TCHAR *line1b, TCHAR *line2b) { return cfgfile_separate_linea(line, line1b, line2b); } static int isobsolete (TCHAR *s) { int i = 0; while (obsolete[i]) { if (!strcasecmp (s, obsolete[i])) { write_log (_T("obsolete config entry '%s'\n"), s); return 1; } i++; } if (_tcslen (s) > 2 && !_tcsncmp (s, _T("w."), 2)) return 1; if (_tcslen (s) >= 10 && !_tcsncmp (s, _T("gfx_opengl"), 10)) { write_log (_T("obsolete config entry '%s\n"), s); return 1; } if (_tcslen (s) >= 6 && !_tcsncmp (s, _T("gfx_3d"), 6)) { write_log (_T("obsolete config entry '%s\n"), s); return 1; } return 0; } static void cfgfile_parse_separated_line (struct uae_prefs *p, TCHAR *line1b, TCHAR *line2b, int type) { TCHAR line3b[CONFIG_BLEN], line4b[CONFIG_BLEN]; struct strlist *sl; int ret; _tcscpy (line3b, line1b); _tcscpy (line4b, line2b); ret = cfgfile_parse_option (p, line1b, line2b, type); if (!isobsolete (line3b)) { for (sl = p->all_lines; sl; sl = sl->next) { if (sl->option && !strcasecmp (line1b, sl->option)) break; } if (!sl) { struct strlist *u = xcalloc (struct strlist, 1); u->option = my_strdup(line3b); u->value = my_strdup(line4b); u->next = p->all_lines; p->all_lines = u; if (!ret) { u->unknown = 1; write_log (_T("unknown config entry: '%s=%s'\n"), u->option, u->value); } } } } void cfgfile_parse_line (struct uae_prefs *p, TCHAR *line, int type) { TCHAR line1b[CONFIG_BLEN], line2b[CONFIG_BLEN]; if (!cfgfile_separate_line (line, line1b, line2b)) return; cfgfile_parse_separated_line (p, line1b, line2b, type); } static void subst (TCHAR *p, TCHAR *f, int n) { TCHAR *str = cfgfile_subst_path (UNEXPANDED, p, f); _tcsncpy (f, str, n - 1); f[n - 1] = '\0'; free (str); } static char *cfg_fgets (char *line, int max, struct zfile *fh) { if (fh) return zfile_fgetsa (line, max, fh); return 0; } static int cfgfile_load_2 (struct uae_prefs *p, const TCHAR *filename, bool real, int *type) { int i; struct zfile *fh; char linea[CONFIG_BLEN]; TCHAR line[CONFIG_BLEN], line1b[CONFIG_BLEN], line2b[CONFIG_BLEN]; struct strlist *sl; bool type1 = false, type2 = false; int askedtype = 0; if (type) { askedtype = *type; *type = 0; } if (real) { p->config_version = 0; config_newfilesystem = 0; //reset_inputdevice_config (p); } fh = zfile_fopen (filename, _T("r"), ZFD_NORMAL); if (! fh) return 0; while (cfg_fgets (linea, sizeof (linea), fh) != 0) { trimwsa (linea); if (strlen (linea) > 0) { if (linea[0] == '#' || linea[0] == ';') { struct strlist *u = xcalloc (struct strlist, 1); u->option = NULL; u->value = my_strdup (linea); u->unknown = 1; u->next = p->all_lines; p->all_lines = u; continue; } if (!cfgfile_separate_linea (linea, line1b, line2b)) continue; type1 = type2 = 0; if (cfgfile_yesno (line1b, line2b, _T("config_hardware"), &type1) || cfgfile_yesno (line1b, line2b, _T("config_host"), &type2)) { if (type1 && type) *type |= CONFIG_TYPE_HARDWARE; if (type2 && type) *type |= CONFIG_TYPE_HOST; continue; } if (real) { cfgfile_parse_separated_line (p, line1b, line2b, askedtype); } else { cfgfile_string (line1b, line2b, _T("config_description"), p->description, sizeof p->description / sizeof (TCHAR)); } } } if (type && *type == 0) *type = CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST; zfile_fclose (fh); if (!real) return 1; for (sl = temp_lines; sl; sl = sl->next) { _stprintf (line, _T("%s=%s"), sl->option, sl->value); cfgfile_parse_line (p, line, 0); } for (i = 0; i < 4; i++) { subst (p->path_floppy, p->floppyslots[i].df, sizeof p->floppyslots[i].df / sizeof (TCHAR)); if(i >= p->nr_floppies) p->floppyslots[i].dfxtype = DRV_NONE; } subst (p->path_rom, p->romfile, sizeof p->romfile / sizeof (TCHAR)); subst (p->path_rom, p->romextfile, sizeof p->romextfile / sizeof (TCHAR)); return 1; } int cfgfile_load (struct uae_prefs *p, const TCHAR *filename, int *type, int ignorelink, int userconfig) { int v; TCHAR tmp[MAX_DPATH]; int type2; static int recursive; if (recursive > 1) return 0; recursive++; write_log (_T("load config '%s':%d\n"), filename, type ? *type : -1); v = cfgfile_load_2 (p, filename, 1, type); if (!v) { write_log (_T("load failed\n")); goto end; } end: recursive--; fixup_prefs (p); return v; } int cfgfile_save (struct uae_prefs *p, const TCHAR *filename, int type) { struct zfile *fh; fh = zfile_fopen (filename, _T("w"), ZFD_NORMAL); if (! fh) return 0; if (!type) type = CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST; cfgfile_save_options (fh, p, type); zfile_fclose (fh); return 1; } int cfgfile_get_description (const TCHAR *filename, TCHAR *description) { int result = 0; struct uae_prefs *p = xmalloc (struct uae_prefs, 1); p->description[0] = 0; if (cfgfile_load_2 (p, filename, 0, 0)) { result = 1; if (description) _tcscpy (description, p->description); } xfree (p); return result; } int cfgfile_configuration_change(int v) { static int mode; if (v >= 0) mode = v; return mode; } static void parse_sound_spec (struct uae_prefs *p, const TCHAR *spec) { TCHAR *x0 = my_strdup (spec); TCHAR *x1, *x2 = NULL, *x3 = NULL, *x4 = NULL, *x5 = NULL; x1 = _tcschr (x0, ':'); if (x1 != NULL) { *x1++ = '\0'; x2 = _tcschr (x1 + 1, ':'); if (x2 != NULL) { *x2++ = '\0'; x3 = _tcschr (x2 + 1, ':'); if (x3 != NULL) { *x3++ = '\0'; x4 = _tcschr (x3 + 1, ':'); if (x4 != NULL) { *x4++ = '\0'; x5 = _tcschr (x4 + 1, ':'); } } } } p->produce_sound = _tstoi (x0); if (x1) { p->sound_stereo_separation = 0; if (*x1 == 'S') { p->sound_stereo = SND_STEREO; p->sound_stereo_separation = 7; } else if (*x1 == 's') p->sound_stereo = SND_STEREO; else p->sound_stereo = SND_MONO; } if (x3) p->sound_freq = _tstoi (x3); free (x0); } static void parse_filesys_spec (struct uae_prefs *p, bool readonly, const TCHAR *spec) { TCHAR buf[256]; TCHAR *s2; _tcsncpy (buf, spec, 255); buf[255] = 0; s2 = _tcschr (buf, ':'); if (s2) { *s2++ = '\0'; #ifdef __DOS__ { TCHAR *tmp; while ((tmp = _tcschr (s2, '\\'))) *tmp = '/'; } #endif #ifdef FILESYS add_filesys_config (p, -1, NULL, buf, s2, readonly, 0, 0, 0, 0, 0, 0, 0, 0); #endif } else { write_log (_T("Usage: [-m | -M] VOLNAME:mount_point\n")); } } static void parse_hardfile_spec (struct uae_prefs *p, const TCHAR *spec) { TCHAR *x0 = my_strdup (spec); TCHAR *x1, *x2, *x3, *x4; x1 = _tcschr (x0, ':'); if (x1 == NULL) goto argh; *x1++ = '\0'; x2 = _tcschr (x1 + 1, ':'); if (x2 == NULL) goto argh; *x2++ = '\0'; x3 = _tcschr (x2 + 1, ':'); if (x3 == NULL) goto argh; *x3++ = '\0'; x4 = _tcschr (x3 + 1, ':'); if (x4 == NULL) goto argh; *x4++ = '\0'; #ifdef FILESYS add_filesys_config (p, -1, NULL, NULL, x4, 0, _tstoi (x0), _tstoi (x1), _tstoi (x2), _tstoi (x3), 0, 0, 0, 0); #endif free (x0); return; argh: free (x0); write_log (_T("Bad hardfile parameter specified - type \"uae -h\" for help.\n")); return; } static void parse_cpu_specs (struct uae_prefs *p, const TCHAR *spec) { if (*spec < '0' || *spec > '4') { write_log (_T("CPU parameter string must begin with '0', '1', '2', '3' or '4'.\n")); return; } p->cpu_model = (*spec++) * 10 + 68000; p->address_space_24 = p->cpu_model < 68020; p->cpu_compatible = 0; while (*spec != '\0') { switch (*spec) { case 'a': if (p->cpu_model < 68020) write_log (_T("In 68000/68010 emulation, the address space is always 24 bit.\n")); else if (p->cpu_model >= 68040) write_log (_T("In 68040/060 emulation, the address space is always 32 bit.\n")); else p->address_space_24 = 1; break; case 'c': if (p->cpu_model != 68000) write_log (_T("The more compatible CPU emulation is only available for 68000\n") _T("emulation, not for 68010 upwards.\n")); else p->cpu_compatible = 1; break; default: write_log (_T("Bad CPU parameter specified - type \"uae -h\" for help.\n")); break; } spec++; } } static void cmdpath (TCHAR *dst, const TCHAR *src, int maxsz) { TCHAR *s = target_expand_environment (src); _tcsncpy (dst, s, maxsz); dst[maxsz] = 0; xfree (s); } /* Returns the number of args used up (0 or 1). */ int parse_cmdline_option (struct uae_prefs *p, TCHAR c, const TCHAR *arg) { struct strlist *u = xcalloc (struct strlist, 1); const TCHAR arg_required[] = _T("0123rKpImWSAJwNCZUFcblOdHRv"); if (_tcschr (arg_required, c) && ! arg) { write_log (_T("Missing argument for option `-%c'!\n"), c); return 0; } u->option = xmalloc (TCHAR, 2); u->option[0] = c; u->option[1] = 0; u->value = my_strdup(arg); u->next = p->all_lines; p->all_lines = u; switch (c) { case '0': cmdpath (p->floppyslots[0].df, arg, 255); break; case '1': cmdpath (p->floppyslots[1].df, arg, 255); break; case '2': cmdpath (p->floppyslots[2].df, arg, 255); break; case '3': cmdpath (p->floppyslots[3].df, arg, 255); break; case 'r': cmdpath (p->romfile, arg, 255); break; case 'K': cmdpath (p->romextfile, arg, 255); break; case 'm': case 'M': parse_filesys_spec (p, c == 'M', arg); break; case 'W': parse_hardfile_spec (p, arg); break; case 'S': parse_sound_spec (p, arg); break; case 'R': p->gfx_framerate = _tstoi (arg); break; case 'w': p->m68k_speed = _tstoi (arg); break; case 'G': p->start_gui = 0; break; case 'n': if (_tcschr (arg, 'i') != 0) p->immediate_blits = 1; break; case 'v': set_chipset_mask (p, _tstoi (arg)); break; case 'C': parse_cpu_specs (p, arg); break; case 'Z': p->z3fastmem_size = _tstoi (arg) * 0x100000; break; case 'U': p->rtgmem_size = _tstoi (arg) * 0x100000; break; case 'F': p->fastmem_size = _tstoi (arg) * 0x100000; break; case 'b': p->bogomem_size = _tstoi (arg) * 0x40000; break; case 'c': p->chipmem_size = _tstoi (arg) * 0x80000; break; default: write_log (_T("Unknown option `-%c'!\n"), c); break; } return !! _tcschr (arg_required, c); } void cfgfile_addcfgparam (TCHAR *line) { struct strlist *u; TCHAR line1b[CONFIG_BLEN], line2b[CONFIG_BLEN]; if (!line) { struct strlist **ps = &temp_lines; while (*ps) { struct strlist *s = *ps; *ps = s->next; xfree (s->value); xfree (s->option); xfree (s); } temp_lines = 0; return; } if (!cfgfile_separate_line (line, line1b, line2b)) return; u = xcalloc (struct strlist, 1); u->option = my_strdup(line1b); u->value = my_strdup(line2b); u->next = temp_lines; temp_lines = u; } void default_prefs (struct uae_prefs *p, int type) { int i; TCHAR zero = 0; struct zfile *f; reset_inputdevice_config (p); memset (p, 0, sizeof (struct uae_prefs)); _tcscpy (p->description, _T("UAE default configuration")); p->start_gui = 1; p->all_lines = 0; p->produce_sound = 3; p->sound_stereo = SND_STEREO; p->sound_stereo_separation = 7; p->sound_mixed_stereo_delay = 0; p->sound_freq = DEFAULT_SOUND_FREQ; p->sound_interpol = 0; p->sound_filter = FILTER_SOUND_OFF; p->sound_filter_type = 0; p->cachesize = DEFAULT_JIT_CACHE_SIZE; for (i = 0;i < 10; i++) p->optcount[i] = -1; p->optcount[0] = 4; /* How often a block has to be executed before it is translated */ p->optcount[1] = 0; /* How often to use the naive translation */ p->optcount[2] = 0; p->optcount[3] = 0; p->optcount[4] = 0; p->optcount[5] = 0; p->gfx_framerate = 0; p->gfx_size_fs.width = 640; p->gfx_size_fs.height = 480; p->gfx_size_win.width = 320; p->gfx_size_win.height = 240; #ifdef RASPBERRY p->gfx_size.width = 640; p->gfx_size.height = 262; #else p->gfx_size.width = 320; p->gfx_size.height = 240; #endif p->gfx_resolution = RES_LORES; #ifdef RASPBERRY p->gfx_correct_aspect = 1; p->gfx_fullscreen_ratio = 100; #endif p->immediate_blits = 0; p->chipset_refreshrate = 50; p->collision_level = 2; p->leds_on_screen = 0; p->fast_copper = 1; p->tod_hack = 1; _tcscpy (p->floppyslots[0].df, _T("")); _tcscpy (p->floppyslots[1].df, _T("")); _tcscpy (p->floppyslots[2].df, _T("")); _tcscpy (p->floppyslots[3].df, _T("")); // Choose automatically first rom. if (lstAvailableROMs.size() >= 1) { strncpy(currprefs.romfile,lstAvailableROMs[0]->Path,255); //_tcscpy(currprefs.romfile,lstAvailableROMs[0]->Path,255); } else _tcscpy (p->romfile, _T("kick.rom")); _tcscpy (p->romextfile, _T("")); sprintf (p->path_rom, _T("%s/kickstarts/"), start_path_data); sprintf (p->path_floppy, _T("%s/disks/"), start_path_data); sprintf (p->path_hardfile, _T("%s/"), start_path_data); p->fpu_model = 0; p->cpu_model = 68000; p->m68k_speed = 0; p->cpu_compatible = 0; p->address_space_24 = 1; p->chipset_mask = CSMASK_ECS_AGNUS; p->ntscmode = 0; p->fastmem_size = 0x00000000; p->z3fastmem_size = 0x00000000; p->z3fastmem_start = z3_start_adr; p->chipmem_size = 0x00100000; p->bogomem_size = 0x00000000; p->rtgmem_size = 0x00000000; p->rtgmem_type = 1; p->nr_floppies = 2; p->floppyslots[0].dfxtype = DRV_35_DD; p->floppyslots[1].dfxtype = DRV_35_DD; p->floppyslots[2].dfxtype = DRV_NONE; p->floppyslots[3].dfxtype = DRV_NONE; p->floppy_speed = 100; p->floppy_write_length = 0; p->socket_emu = 0; p->input_tablet = TABLET_OFF; target_default_options (p, type); inputdevice_default_prefs (p); } int bip_a500 (struct uae_prefs *p, int rom) { int roms[4]; if(rom == 130) { roms[0] = 6; roms[1] = 5; roms[2] = 4; roms[3] = -1; } else { roms[0] = 5; roms[1] = 4; roms[2] = 3; roms[3] = -1; } p->chipmem_size = 0x00080000; p->chipset_mask = 0; p->cpu_compatible = 0; p->fast_copper = 0; p->nr_floppies = 1; p->floppyslots[1].dfxtype = DRV_NONE; return configure_rom (p, roms, 0); } int bip_a500plus (struct uae_prefs *p, int rom) { int roms[4]; if(rom == 130) { roms[0] = 6; roms[1] = 5; roms[2] = 4; roms[3] = -1; } else { roms[0] = 7; roms[1] = 6; roms[2] = 5; roms[3] = -1; } p->chipmem_size = 0x00100000; p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE; p->cpu_compatible = 0; p->fast_copper = 0; p->nr_floppies = 1; p->floppyslots[1].dfxtype = DRV_NONE; return configure_rom (p, roms, 0); } int bip_a1200 (struct uae_prefs *p, int rom) { int roms[4]; if(rom == 310) { roms[0] = 15; roms[1] = 11; roms[2] = 31; roms[3] = -1; } else { roms[0] = 11; roms[1] = 15; roms[2] = 31; roms[3] = -1; } p->cpu_model = 68020; p->address_space_24 = 1; p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE | CSMASK_AGA; p->chipmem_size = 0x200000; p->bogomem_size = 0; p->m68k_speed = M68K_SPEED_14MHZ_CYCLES; p->nr_floppies = 1; p->floppyslots[1].dfxtype = DRV_NONE; return configure_rom (p, roms, 0); } int bip_a2000 (struct uae_prefs *p, int rom) { int roms[4]; if(rom == 130) { roms[0] = 6; roms[1] = 5; roms[2] = 4; roms[3] = -1; } else { roms[0] = 5; roms[1] = 4; roms[2] = 3; roms[3] = -1; } p->chipmem_size = 0x00080000; p->bogomem_size = 0x00080000; p->chipset_mask = 0; p->cpu_compatible = 0; p->fast_copper = 0; p->nr_floppies = 1; p->floppyslots[1].dfxtype = DRV_NONE; return configure_rom (p, roms, 0); } int bip_a4000 (struct uae_prefs *p, int rom) { int roms[4]; roms[0] = 15; roms[1] = 14; roms[2] = 11; roms[3] = -1; p->immediate_blits = 1; p->bogomem_size = 0; p->chipmem_size = 0x200000; p->cpu_model = 68030; p->fpu_model = 68882; p->address_space_24 = 0; p->cpu_compatible = 0; p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE | CSMASK_AGA; p->m68k_speed = -1; p->cachesize = 8192; p->nr_floppies = 2; p->floppyslots[0].dfxtype = DRV_35_HD; p->floppyslots[1].dfxtype = DRV_35_HD; return configure_rom (p, roms, 0); }