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 #ifdef FSUAE // NL
16 #ifdef _WIN32
17 #include <winsock2.h>
18 #else
19 #include <arpa/inet.h>
20 #endif
21 #endif
22 
23 #include "options.h"
24 #include "uae.h"
25 #include "audio.h"
26 #include "events.h"
27 #include "custom.h"
28 #include "inputdevice.h"
29 #include "gfxfilter.h"
30 #include "savestate.h"
31 #include "uae/memory.h"
32 #include "autoconf.h"
33 #include "rommgr.h"
34 #include "gui.h"
35 #include "newcpu.h"
36 #include "zfile.h"
37 #include "filesys.h"
38 #include "fsdb.h"
39 #include "disk.h"
40 #include "blkdev.h"
41 #include "statusline.h"
42 #include "debug.h"
43 #include "calc.h"
44 #include "gfxboard.h"
45 #include "cpuboard.h"
46 #include "luascript.h"
47 
48 #ifdef FSUAE
49 #include <uae/fs.h>
50 #define cfgfile_warning error_log
51 #define cfgfile_warning_obsolete error_log
52 #else
53 #define cfgfile_warning write_log
54 #define cfgfile_warning_obsolete write_log
55 #endif
56 
57 #if SIZEOF_TCHAR != 1
58 /* FIXME: replace strcasecmp with _tcsicmp in source code instead */
59 #undef strcasecmp
60 #define strcasecmp _tcsicmp
61 #endif
62 
63 static int config_newfilesystem;
64 static struct strlist *temp_lines;
65 static struct strlist *error_lines;
66 static struct zfile *default_file, *configstore;
67 static int uaeconfig;
68 static int unicode_config = 0;
69 
70 /* @@@ need to get rid of this... just cut part of the manual and print that
71 * as a help text.  */
72 struct cfg_lines
73 {
74 	const TCHAR *config_label, *config_help;
75 };
76 
77 static const struct cfg_lines opttable[] =
78 {
79 	{_T("help"), _T("Prints this help") },
80 	{_T("config_description"), _T("") },
81 	{_T("config_info"), _T("") },
82 	{_T("use_gui"), _T("Enable the GUI?  If no, then goes straight to emulator") },
83 	{_T("use_debugger"), _T("Enable the debugger?") },
84 	{_T("cpu_speed"), _T("can be max, real, or a number between 1 and 20") },
85 	{_T("cpu_model"), _T("Can be 68000, 68010, 68020, 68030, 68040, 68060") },
86 	{_T("fpu_model"), _T("Can be 68881, 68882, 68040, 68060") },
87 	{_T("cpu_compatible"), _T("yes enables compatibility-mode") },
88 	{_T("cpu_24bit_addressing"), _T("must be set to 'no' in order for Z3mem or P96mem to work") },
89 	{_T("autoconfig"), _T("yes = add filesystems and extra ram") },
90 	{_T("log_illegal_mem"), _T("print illegal memory access by Amiga software?") },
91 	{_T("fastmem_size"), _T("Size in megabytes of fast-memory") },
92 	{_T("chipmem_size"), _T("Size in megabytes of chip-memory") },
93 	{_T("bogomem_size"), _T("Size in megabytes of bogo-memory at 0xC00000") },
94 	{_T("a3000mem_size"), _T("Size in megabytes of A3000 memory") },
95 	{_T("gfxcard_size"), _T("Size in megabytes of Picasso96 graphics-card memory") },
96 	{_T("z3mem_size"), _T("Size in megabytes of Zorro-III expansion memory") },
97 	{_T("gfx_test_speed"), _T("Test graphics speed?") },
98 	{_T("gfx_framerate"), _T("Print every nth frame") },
99 	{_T("gfx_width"), _T("Screen width") },
100 	{_T("gfx_height"), _T("Screen height") },
101 	{_T("gfx_refreshrate"), _T("Fullscreen refresh rate") },
102 	{_T("gfx_vsync"), _T("Sync screen refresh to refresh rate") },
103 	{_T("gfx_lores"), _T("Treat display as lo-res?") },
104 	{_T("gfx_linemode"), _T("Can be none, double, or scanlines") },
105 	{_T("gfx_fullscreen_amiga"), _T("Amiga screens are fullscreen?") },
106 	{_T("gfx_fullscreen_picasso"), _T("Picasso screens are fullscreen?") },
107 	{_T("gfx_center_horizontal"), _T("Center display horizontally?") },
108 	{_T("gfx_center_vertical"), _T("Center display vertically?") },
109 	{_T("gfx_colour_mode"), _T("") },
110 	{_T("32bit_blits"), _T("Enable 32 bit blitter emulation") },
111 	{_T("immediate_blits"), _T("Perform blits immediately") },
112 	{_T("show_leds"), _T("LED display") },
113 	{_T("keyboard_leds"), _T("Keyboard LEDs") },
114 	{_T("gfxlib_replacement"), _T("Use graphics.library replacement?") },
115 	{_T("sound_output"), _T("") },
116 	{_T("sound_frequency"), _T("") },
117 	{_T("sound_bits"), _T("") },
118 	{_T("sound_channels"), _T("") },
119 	{_T("sound_max_buff"), _T("") },
120 	{_T("comp_trustbyte"), _T("How to access bytes in compiler (direct/indirect/indirectKS/afterPic") },
121 	{_T("comp_trustword"), _T("How to access words in compiler (direct/indirect/indirectKS/afterPic") },
122 	{_T("comp_trustlong"), _T("How to access longs in compiler (direct/indirect/indirectKS/afterPic") },
123 	{_T("comp_nf"), _T("Whether to optimize away flag generation where possible") },
124 	{_T("comp_fpu"), _T("Whether to provide JIT FPU emulation") },
125 	{_T("cachesize"), _T("How many MB to use to buffer translated instructions")},
126 	{_T("override_dga_address"),_T("Address from which to map the frame buffer (upper 16 bits) (DANGEROUS!)")},
127 	{_T("avoid_dga"), _T("Set to yes if the use of DGA extension creates problems") },
128 	{_T("avoid_vid"), _T("Set to yes if the use of the Vidmode extension creates problems") },
129 	{_T("parallel_on_demand"), _T("") },
130 	{_T("serial_on_demand"), _T("") },
131 	{_T("scsi"), _T("scsi.device emulation") },
132 	{_T("joyport0"), _T("") },
133 	{_T("joyport1"), _T("") },
134 	{_T("pci_devices"), _T("List of PCI devices to make visible to the emulated Amiga") },
135 	{_T("kickstart_rom_file"), _T("Kickstart ROM image, (C) Copyright Amiga, Inc.") },
136 	{_T("kickstart_ext_rom_file"), _T("Extended Kickstart ROM image, (C) Copyright Amiga, Inc.") },
137 	{_T("kickstart_key_file"), _T("Key-file for encrypted ROM images (from Cloanto's Amiga Forever)") },
138 	{_T("flash_ram_file"), _T("Flash/battery backed RAM image file.") },
139 	{_T("cart_file"), _T("Freezer cartridge ROM image file.") },
140 	{_T("floppy0"), _T("Diskfile for drive 0") },
141 	{_T("floppy1"), _T("Diskfile for drive 1") },
142 	{_T("floppy2"), _T("Diskfile for drive 2") },
143 	{_T("floppy3"), _T("Diskfile for drive 3") },
144 	{_T("hardfile"), _T("access,sectors, surfaces, reserved, blocksize, path format") },
145 	{_T("filesystem"), _T("access,'Amiga volume-name':'host directory path' - where 'access' can be 'read-only' or 'read-write'") },
146 	{_T("catweasel"), _T("Catweasel board io base address") }
147 };
148 
149 static const TCHAR *guimode1[] = { _T("no"), _T("yes"), _T("nowait"), 0 };
150 static const TCHAR *guimode2[] = { _T("false"), _T("true"), _T("nowait"), 0 };
151 static const TCHAR *guimode3[] = { _T("0"), _T("1"), _T("nowait"), 0 };
152 static const TCHAR *csmode[] = { _T("ocs"), _T("ecs_agnus"), _T("ecs_denise"), _T("ecs"), _T("aga"), 0 };
153 static const TCHAR *linemode[] = {
154 	_T("none"),
155 	_T("double"), _T("scanlines"), _T("scanlines2p"), _T("scanlines3p"),
156 	_T("double2"), _T("scanlines2"), _T("scanlines2p2"), _T("scanlines2p3"),
157 	_T("double3"), _T("scanlines3"), _T("scanlines3p2"), _T("scanlines3p3"),
158 	0 };
159 static const TCHAR *speedmode[] = { _T("max"), _T("real"), 0 };
160 static const TCHAR *colormode1[] = { _T("8bit"), _T("15bit"), _T("16bit"), _T("8bit_dither"), _T("4bit_dither"), _T("32bit"), 0 };
161 static const TCHAR *colormode2[] = { _T("8"), _T("15"), _T("16"), _T("8d"), _T("4d"), _T("32"), 0 };
162 static const TCHAR *soundmode1[] = { _T("none"), _T("interrupts"), _T("normal"), _T("exact"), 0 };
163 static const TCHAR *soundmode2[] = { _T("none"), _T("interrupts"), _T("good"), _T("best"), 0 };
164 static const TCHAR *centermode1[] = { _T("none"), _T("simple"), _T("smart"), 0 };
165 static const TCHAR *centermode2[] = { _T("false"), _T("true"), _T("smart"), 0 };
166 static const TCHAR *stereomode[] = { _T("mono"), _T("stereo"), _T("clonedstereo"), _T("4ch"), _T("clonedstereo6ch"), _T("6ch"), _T("mixed"), 0 };
167 static const TCHAR *interpolmode[] = { _T("none"), _T("anti"), _T("sinc"), _T("rh"), _T("crux"), 0 };
168 static const TCHAR *collmode[] = { _T("none"), _T("sprites"), _T("playfields"), _T("full"), 0 };
169 static const TCHAR *compmode[] = { _T("direct"), _T("indirect"), _T("indirectKS"), _T("afterPic"), 0 };
170 static const TCHAR *flushmode[] = { _T("soft"), _T("hard"), 0 };
171 static const TCHAR *kbleds[] = { _T("none"), _T("POWER"), _T("DF0"), _T("DF1"), _T("DF2"), _T("DF3"), _T("HD"), _T("CD"), _T("DFx"), 0 };
172 static const TCHAR *onscreenleds[] = { _T("false"), _T("true"), _T("rtg"), _T("both"), 0 };
173 static const TCHAR *soundfiltermode1[] = { _T("off"), _T("emulated"), _T("on"), 0 };
174 static const TCHAR *soundfiltermode2[] = { _T("standard"), _T("enhanced"), 0 };
175 static const TCHAR *lorestype1[] = { _T("lores"), _T("hires"), _T("superhires"), 0 };
176 static const TCHAR *lorestype2[] = { _T("true"), _T("false"), 0 };
177 static const TCHAR *loresmode[] = { _T("normal"), _T("filtered"), 0 };
178 static const TCHAR *horizmode[] = { _T("vertical"), _T("lores"), _T("hires"), _T("superhires"), 0 };
179 static const TCHAR *vertmode[] = { _T("horizontal"), _T("single"), _T("double"), _T("quadruple"), 0 };
180 #ifdef GFXFILTER
181 static const TCHAR *filtermode2[] = { _T("1x"), _T("2x"), _T("3x"), _T("4x"), 0 };
182 #endif
183 static const TCHAR *cartsmode[] = { _T("none"), _T("hrtmon"), 0 };
184 static const TCHAR *idemode[] = { _T("none"), _T("a600/a1200"), _T("a4000"), 0 };
185 static const TCHAR *rtctype[] = { _T("none"), _T("MSM6242B"), _T("RP5C01A"), _T("MSM6242B_A2000"), 0 };
186 static const TCHAR *ciaatodmode[] = { _T("vblank"), _T("50hz"), _T("60hz"), 0 };
187 static const TCHAR *ksmirrortype[] = { _T("none"), _T("e0"), _T("a8+e0"), 0 };
188 static const TCHAR *cscompa[] = {
189 	_T("-"), _T("Generic"), _T("CDTV"), _T("CDTV-CR"), _T("CD32"), _T("A500"), _T("A500+"), _T("A600"),
190 	_T("A1000"), _T("A1200"), _T("A2000"), _T("A3000"), _T("A3000T"), _T("A4000"), _T("A4000T"),
191 	_T("Velvet"),
192 	NULL
193 };
194 static const TCHAR *qsmodes[] = {
195 	_T("A500"), _T("A500+"), _T("A600"), _T("A1000"), _T("A1200"), _T("A3000"), _T("A4000"), _T(""), _T("CD32"), _T("CDTV"), _T("CDTV-CR"), _T("ARCADIA"), NULL };
196 /* 3-state boolean! */
197 static const TCHAR *fullmodes[] = { _T("false"), _T("true"), /* "FILE_NOT_FOUND", */ _T("fullwindow"), 0 };
198 /* bleh for compatibility */
199 static const TCHAR *scsimode[] = { _T("false"), _T("true"), _T("scsi"), 0 };
200 static const TCHAR *maxhoriz[] = { _T("lores"), _T("hires"), _T("superhires"), 0 };
201 static const TCHAR *maxvert[] = { _T("nointerlace"), _T("interlace"), 0 };
202 static const TCHAR *abspointers[] = { _T("none"), _T("mousehack"), _T("tablet"), 0 };
203 static const TCHAR *magiccursors[] = { _T("both"), _T("native"), _T("host"), 0 };
204 static const TCHAR *autoscale[] = { _T("none"), _T("auto"), _T("standard"), _T("max"), _T("scale"), _T("resize"), _T("center"), _T("manual"),
205 	_T("integer"), _T("integer_auto"), _T("separator"), _T("overscan_blanking"), 0 };
206 static const TCHAR *autoscale_rtg[] = { _T("resize"), _T("scale"), _T("center"), _T("integer"), 0 };
207 static const TCHAR *autoscalelimit[] = { _T("1/1"), _T("1/2"), _T("1/4"), _T("1/8"), 0 };
208 static const TCHAR *joyportmodes[] = { _T(""), _T("mouse"), _T("mousenowheel"), _T("djoy"), _T("gamepad"), _T("ajoy"), _T("cdtvjoy"), _T("cd32joy"), _T("lightpen"), 0 };
209 static const TCHAR *joyaf[] = { _T("none"), _T("normal"), _T("toggle"), _T("always"), 0 };
210 static const TCHAR *epsonprinter[] = { _T("none"), _T("ascii"), _T("epson_matrix_9pin"), _T("epson_matrix_24pin"), _T("epson_matrix_48pin"), 0 };
211 static const TCHAR *aspects[] = { _T("none"), _T("vga"), _T("tv"), 0 };
212 static const TCHAR *vsyncmodes[] = { _T("false"), _T("true"), _T("autoswitch"), 0 };
213 static const TCHAR *vsyncmodes2[] = { _T("normal"), _T("busywait"), 0 };
214 static const TCHAR *filterapi[] = { _T("directdraw"), _T("direct3d"), 0 };
215 static const TCHAR *dongles[] =
216 {
217 	_T("none"),
218 	_T("robocop 3"), _T("leaderboard"), _T("b.a.t. ii"), _T("italy'90 soccer"), _T("dames grand maitre"),
219 	_T("rugby coach"), _T("cricket captain"), _T("leviathan"),
220 	NULL
221 };
222 static const TCHAR *cdmodes[] = { _T("disabled"), _T(""), _T("image"), _T("ioctl"), _T("spti"), _T("aspi"), 0 };
223 static const TCHAR *cdconmodes[] = { _T(""), _T("uae"), _T("ide"), _T("scsi"), _T("cdtv"), _T("cd32"), 0 };
224 static const TCHAR *specialmonitors[] = { _T("none"), _T("autodetect"), _T("a2024"), _T("graffiti"),
225 _T("ham_e"), _T("ham_e_plus"), _T("videodac18"), _T("avideo12"), _T("avideo24"), _T("firecracker24"), _T("dctv"), 0 };
226 static const TCHAR *genlockmodes[] = { _T("none"), _T("noise"), _T("testcard"), NULL };
227 static const TCHAR *ppc_implementations[] = {
228 	_T("auto"),
229 	_T("dummy"),
230 	_T("pearpc"),
231 	_T("qemu"),
232 	NULL
233 };
234 #ifdef FSUAE
235 static const TCHAR *slirp_implementations[] = {
236 	_T("auto"),
237 	_T("none"),
238 	_T("builtin"),
239 	_T("qemu"),
240 	NULL
241 };
242 #endif
243 static const TCHAR *ppc_cpu_idle[] = {
244 	_T("disabled"),
245 	_T("1"),
246 	_T("2"),
247 	_T("3"),
248 	_T("4"),
249 	_T("5"),
250 	_T("6"),
251 	_T("7"),
252 	_T("8"),
253 	_T("9"),
254 	_T("max"),
255 	NULL
256 };
257 static const TCHAR *waitblits[] = { _T("disabled"), _T("automatic"), _T("noidleonly"), _T("always"), 0 };
258 static const TCHAR *autoext2[] = { _T("disabled"), _T("copy"), _T("replace"), 0 };
259 static const TCHAR *leds[] = { _T("power"), _T("df0"), _T("df1"), _T("df2"), _T("df3"), _T("hd"), _T("cd"), _T("fps"), _T("cpu"), _T("snd"), _T("md"), 0 };
260 static const int leds_order[] = { 3, 6, 7, 8, 9, 4, 5, 2, 1, 0, 9 };
261 static const TCHAR *lacer[] = { _T("off"), _T("i"), _T("p"), 0 };
262 /* another boolean to choice update.. */
263 static const TCHAR *cycleexact[] = { _T("false"), _T("memory"), _T("true"), 0  };
264 
265 static const TCHAR *hdcontrollers[] = {
266 	_T("uae"),
267 
268 	_T("ide%d"),
269 	_T("ide%d_mainboard"),
270 
271 	_T("scsi%d"),
272 	_T("scsi%d_a3000"),
273 	_T("scsi%d_a4000t"),
274 	_T("scsi%d_cdtv"),
275 
276 	_T("scsram"),
277 	_T("scide"),
278 	NULL
279 };
280 static const TCHAR *z3mapping[] = {
281 	_T("auto"),
282 	_T("uae"),
283 	_T("real"),
284 	NULL
285 };
286 static const TCHAR *uaescsidevmodes[] = {
287 	_T("original"),
288 	_T("rename_scsi"),
289 	NULL
290 };
291 static const TCHAR *uaebootrom[] = {
292 	_T("automatic"),
293 	_T("disabled"),
294 	_T("min"),
295 	_T("full"),
296 	NULL
297 };
298 static const TCHAR *serialcrlf[] = {
299 	_T("disabled"),
300 	_T("crlf_cr"),
301 	NULL
302 };
303 static const TCHAR *obsolete[] = {
304 	_T("accuracy"), _T("gfx_opengl"), _T("gfx_32bit_blits"), _T("32bit_blits"),
305 	_T("gfx_immediate_blits"), _T("gfx_ntsc"), _T("win32"), _T("gfx_filter_bits"),
306 	_T("sound_pri_cutoff"), _T("sound_pri_time"), _T("sound_min_buff"), _T("sound_bits"),
307 	_T("gfx_test_speed"), _T("gfxlib_replacement"), _T("enforcer"), _T("catweasel_io"),
308 	_T("kickstart_key_file"), _T("fast_copper"), _T("sound_adjust"), _T("sound_latency"),
309 	_T("serial_hardware_dtrdsr"), _T("gfx_filter_upscale"),
310 	_T("gfx_correct_aspect"), _T("gfx_autoscale"), _T("parallel_sampler"), _T("parallel_ascii_emulation"),
311 	_T("avoid_vid"), _T("avoid_dga"), _T("z3chipmem_size"), _T("state_replay_buffer"), _T("state_replay"),
312 	_T("z3realmapping"), _T("force_0x10000000_z3"),
313 
314 	_T("gfx_filter_vert_zoom"),_T("gfx_filter_horiz_zoom"),
315 	_T("gfx_filter_vert_zoom_mult"), _T("gfx_filter_horiz_zoom_mult"),
316 	_T("gfx_filter_vert_offset"), _T("gfx_filter_horiz_offset"),
317 
318 	// created by some buggy beta
319 	_T("uaehf0%s,%s"),
320 	_T("uaehf1%s,%s"),
321 	_T("uaehf2%s,%s"),
322 	_T("uaehf3%s,%s"),
323 	_T("uaehf4%s,%s"),
324 	_T("uaehf5%s,%s"),
325 	_T("uaehf6%s,%s"),
326 	_T("uaehf7%s,%s"),
327 
328 	_T("pcibridge_rom_file"),
329 	_T("pcibridge_rom_options"),
330 
331 	_T("cpuboard_ext_rom_file"),
332 
333 	_T("comp_oldsegv"),
334 	_T("comp_midopt"),
335 	_T("comp_lowopt"),
336 	_T("avoid_cmov"),
337 	_T("compforcesettings"),
338 
339 	NULL
340 };
341 
342 #define UNEXPANDED _T("$(FILE_PATH)")
343 
cfgfile_option_find_it(const TCHAR * s,const TCHAR * option,bool checkequals)344 static TCHAR *cfgfile_option_find_it(const TCHAR *s, const TCHAR *option, bool checkequals)
345 {
346 	TCHAR buf[MAX_DPATH];
347 	if (!s)
348 		return NULL;
349 	_tcscpy(buf, s);
350 	_tcscat(buf, _T(","));
351 	TCHAR *p = buf;
352 	for (;;) {
353 		TCHAR *tmpp = _tcschr(p, ',');
354 		TCHAR *tmpp2 = NULL;
355 		if (tmpp == NULL)
356 			return NULL;
357 		*tmpp++ = 0;
358 		if (checkequals) {
359 			tmpp2 = _tcschr(p, '=');
360 			if (tmpp2)
361 				*tmpp2++ = 0;
362 		}
363 		if (!strcasecmp(p, option)) {
364 			if (checkequals && tmpp2)
365 				return tmpp2;
366 			return p;
367 		}
368 		p = tmpp;
369 	}
370 }
371 
cfgfile_option_find(const TCHAR * s,const TCHAR * option)372 static bool cfgfile_option_find(const TCHAR *s, const TCHAR *option)
373 {
374 	return cfgfile_option_find_it(s, option, false) != NULL;
375 }
376 
cfgfile_option_get(const TCHAR * s,const TCHAR * option)377 static TCHAR *cfgfile_option_get(const TCHAR *s, const TCHAR *option)
378 {
379 	return cfgfile_option_find_it(s, option, true);
380 }
381 
trimwsa(char * s)382 static void trimwsa (char *s)
383 {
384 	/* Delete trailing whitespace.  */
385 	int len = strlen (s);
386 	while (len > 0 && strcspn (s + len - 1, "\t \r\n") == 0)
387 		s[--len] = '\0';
388 }
389 
match_string(const TCHAR * table[],const TCHAR * str)390 static int match_string (const TCHAR *table[], const TCHAR *str)
391 {
392 	int i;
393 	for (i = 0; table[i] != 0; i++)
394 		if (strcasecmp (table[i], str) == 0)
395 			return i;
396 	return -1;
397 }
398 
399 // escape config file separators and control characters
cfgfile_escape(const TCHAR * s,const TCHAR * escstr,bool quote)400 static TCHAR *cfgfile_escape (const TCHAR *s, const TCHAR *escstr, bool quote)
401 {
402 	bool doquote = false;
403 	int cnt = 0;
404 	for (int i = 0; s[i]; i++) {
405 		TCHAR c = s[i];
406 		if (c == 0)
407 			break;
408 		if (c < 32 || c == '\\' || c == '\"' || c == '\'') {
409 			cnt++;
410 		}
411 		for (int j = 0; escstr && escstr[j]; j++) {
412 			if (c == escstr[j]) {
413 				cnt++;
414 				if (quote) {
415 					doquote = true;
416 					cnt++;
417 				}
418 			}
419 		}
420 	}
421 	TCHAR *s2 = xmalloc (TCHAR, _tcslen (s) + cnt * 4 + 1);
422 	TCHAR *p = s2;
423 	if (doquote)
424 		*p++ = '\"';
425 	for (int i = 0; s[i]; i++) {
426 		TCHAR c = s[i];
427 		if (c == 0)
428 			break;
429 		if (c == '\\' || c == '\"' || c == '\'') {
430 			*p++ = '\\';
431 			*p++ = c;
432 		} else if (c >= 32 && !quote) {
433 			bool escaped = false;
434 			for (int j = 0; escstr && escstr[j]; j++) {
435 				if (c == escstr[j]) {
436 					*p++ = '\\';
437 					*p++ = c;
438 					escaped = true;
439 					break;
440 				}
441 			}
442 			if (!escaped)
443 				*p++ = c;
444 		} else if (c < 32) {
445 			*p++ = '\\';
446 			switch (c)
447 			{
448 				case '\t':
449 				*p++ = 't';
450 				break;
451 				case '\n':
452 				*p++ = 'n';
453 				break;
454 				case '\r':
455 				*p++ = 'r';
456 				break;
457 				default:
458 				*p++ = 'x';
459 				*p++ = (c >> 4) >= 10 ? (c >> 4) + 'a' : (c >> 4) + '0';
460 				*p++ = (c & 15) >= 10 ? (c & 15) + 'a' : (c & 15) + '0';
461 				break;
462 			}
463 		} else {
464 			*p++ = c;
465 		}
466 	}
467 	if (doquote)
468 		*p++ = '\"';
469 	*p = 0;
470 	return s2;
471 }
cfgfile_unescape(const TCHAR * s,const TCHAR ** endpos,TCHAR separator)472 static TCHAR *cfgfile_unescape (const TCHAR *s, const TCHAR **endpos, TCHAR separator)
473 {
474 	bool quoted = false;
475 	TCHAR *s2 = xmalloc (TCHAR, _tcslen (s) + 1);
476 	TCHAR *p = s2;
477 	if (s[0] == '\"') {
478 		s++;
479 		quoted = true;
480 	}
481 	int i;
482 	for (i = 0; s[i]; i++) {
483 		TCHAR c = s[i];
484 		if (quoted && c == '\"') {
485 			i++;
486 			break;
487 		}
488 		if (c == separator) {
489 			i++;
490 			break;
491 		}
492 		if (c == '\\') {
493 			char v = 0;
494 			TCHAR c2;
495 			c = s[i + 1];
496 			switch (c)
497 			{
498 				case 'X':
499 				case 'x':
500 				c2 = _totupper (s[i + 2]);
501 				v = ((c2 >= 'A') ? c2 - 'A' : c2 - '0') << 4;
502 				c2 = _totupper (s[i + 3]);
503 				v |= (c2 >= 'A') ? c2 - 'A' : c2 - '0';
504 				*p++ = c2;
505 				i += 2;
506 				break;
507 				case 'r':
508 				*p++ = '\r';
509 				break;
510 				case '\n':
511 				*p++ = '\n';
512 				break;
513 				default:
514 				*p++ = c;
515 				break;
516 			}
517 			i++;
518 		} else {
519 			*p++ = c;
520 		}
521 	}
522 	*p = 0;
523 	if (endpos)
524 		*endpos = &s[i];
525 	return s2;
526 }
cfgfile_unescape(const TCHAR * s,const TCHAR ** endpos)527 static TCHAR *cfgfile_unescape (const TCHAR *s, const TCHAR **endpos)
528 {
529 	return cfgfile_unescape (s, endpos, 0);
530 }
531 
getnextentry(const TCHAR ** valuep,const TCHAR separator)532 static TCHAR *getnextentry (const TCHAR **valuep, const TCHAR separator)
533 {
534 	TCHAR *s;
535 	const TCHAR *value = *valuep;
536 	if (value[0] == '\"') {
537 		s = cfgfile_unescape (value, valuep);
538 		value = *valuep;
539 		if (*value != 0 && *value != separator) {
540 			xfree (s);
541 			return NULL;
542 		}
543 		value++;
544 		*valuep = value;
545 	} else {
546 		s = cfgfile_unescape (value, valuep, separator);
547 	}
548 	return s;
549 }
550 
cfgfile_subst_path2(const TCHAR * path,const TCHAR * subst,const TCHAR * file)551 static TCHAR *cfgfile_subst_path2 (const TCHAR *path, const TCHAR *subst, const TCHAR *file)
552 {
553 	/* @@@ use strcasecmp for some targets.  */
554 	if (_tcslen (path) > 0 && _tcsncmp (file, path, _tcslen (path)) == 0) {
555 		int l;
556 		TCHAR *p2, *p = xmalloc (TCHAR, _tcslen (file) + _tcslen (subst) + 2);
557 		_tcscpy (p, subst);
558 		l = _tcslen (p);
559 		while (l > 0 && p[l - 1] == '/')
560 			p[--l] = '\0';
561 		l = _tcslen (path);
562 		while (file[l] == '/')
563 			l++;
564 		_tcscat (p, _T("/"));
565 		_tcscat (p, file + l);
566 		p2 = target_expand_environment (p);
567 		xfree (p);
568 		return p2;
569 	}
570 	return NULL;
571 }
572 
cfgfile_subst_path(const TCHAR * path,const TCHAR * subst,const TCHAR * file)573 TCHAR *cfgfile_subst_path (const TCHAR *path, const TCHAR *subst, const TCHAR *file)
574 {
575 	TCHAR *s = cfgfile_subst_path2 (path, subst, file);
576 	if (s)
577 		return s;
578 	s = target_expand_environment (file);
579 	if (s) {
580 		TCHAR tmp[MAX_DPATH];
581 		_tcscpy (tmp, s);
582 		xfree (s);
583 		fullpath (tmp, sizeof tmp / sizeof (TCHAR));
584 		s = my_strdup (tmp);
585 	}
586 	return s;
587 }
588 
cfgfile_get_multipath2(struct multipath * mp,const TCHAR * path,const TCHAR * file,bool dir)589 static TCHAR *cfgfile_get_multipath2 (struct multipath *mp, const TCHAR *path, const TCHAR *file, bool dir)
590 {
591 	for (int i = 0; i < MAX_PATHS; i++) {
592 		if (mp->path[i][0] && _tcscmp (mp->path[i], _T(".\\")) != 0 && _tcscmp (mp->path[i], _T("./")) != 0 && (file[0] != '/' && file[0] != '\\' && !_tcschr(file, ':'))) {
593 			TCHAR *s = NULL;
594 			if (path)
595 				s = cfgfile_subst_path2 (path, mp->path[i], file);
596 			if (!s) {
597 				TCHAR np[MAX_DPATH];
598 				_tcscpy (np, mp->path[i]);
599 				fixtrailing (np);
600 				_tcscat (np, file);
601 				fullpath (np, sizeof np / sizeof (TCHAR));
602 				s = my_strdup (np);
603 			}
604 			if (dir) {
605 				if (my_existsdir (s))
606 					return s;
607 			} else {
608 				if (zfile_exists (s))
609 					return s;
610 			}
611 			xfree (s);
612 		}
613 	}
614 	return NULL;
615 }
616 
cfgfile_get_multipath(struct multipath * mp,const TCHAR * path,const TCHAR * file,bool dir)617 static TCHAR *cfgfile_get_multipath (struct multipath *mp, const TCHAR *path, const TCHAR *file, bool dir)
618 {
619 	TCHAR *s = cfgfile_get_multipath2 (mp, path, file, dir);
620 	if (s)
621 		return s;
622 	return my_strdup (file);
623 }
624 
cfgfile_put_multipath(struct multipath * mp,const TCHAR * s)625 static TCHAR *cfgfile_put_multipath (struct multipath *mp, const TCHAR *s)
626 {
627 	for (int i = 0; i < MAX_PATHS; i++) {
628 		if (mp->path[i][0] && _tcscmp (mp->path[i], _T(".\\")) != 0 && _tcscmp (mp->path[i], _T("./")) != 0) {
629 			if (_tcsnicmp (mp->path[i], s, _tcslen (mp->path[i])) == 0) {
630 				return my_strdup (s + _tcslen (mp->path[i]));
631 			}
632 		}
633 	}
634 	return my_strdup (s);
635 }
636 
cfgfile_subst_path_load(const TCHAR * path,struct multipath * mp,const TCHAR * file,bool dir)637 static TCHAR *cfgfile_subst_path_load (const TCHAR *path, struct multipath *mp, const TCHAR *file, bool dir)
638 {
639 	TCHAR *s = cfgfile_get_multipath2 (mp, path, file, dir);
640 	if (s)
641 		return s;
642 	return cfgfile_subst_path (path, mp->path[0], file);
643 }
644 
isdefault(const TCHAR * s)645 static bool isdefault (const TCHAR *s)
646 {
647 	TCHAR tmp[MAX_DPATH];
648 	if (!default_file || uaeconfig)
649 		return false;
650 	zfile_fseek (default_file, 0, SEEK_SET);
651 	while (zfile_fgets (tmp, sizeof tmp / sizeof (TCHAR), default_file)) {
652 		if (tmp[0] && tmp[_tcslen (tmp) - 1] == '\n')
653 			tmp[_tcslen (tmp) - 1] = 0;
654 		if (!_tcscmp (tmp, s))
655 			return true;
656 	}
657 	return false;
658 }
659 
cfg_write(const void * b,struct zfile * z)660 static size_t cfg_write (const void *b, struct zfile *z)
661 {
662 	size_t v;
663 	if (unicode_config) {
664 		TCHAR lf = 10;
665 		v = zfile_fwrite (b, _tcslen ((TCHAR*)b), sizeof (TCHAR), z);
666 		zfile_fwrite (&lf, 1, 1, z);
667 	} else {
668 		char lf = 10;
669 		char *s = ua ((TCHAR*)b);
670 		v = zfile_fwrite (s, strlen (s), 1, z);
671 		zfile_fwrite (&lf, 1, 1, z);
672 		xfree (s);
673 	}
674 	return v;
675 }
676 
677 #define UTF8NAME _T(".utf8")
678 
cfg_dowrite(struct zfile * f,const TCHAR * option,const TCHAR * optionext,const TCHAR * value,int d,int target)679 static void cfg_dowrite (struct zfile *f, const TCHAR *option, const TCHAR *optionext, const TCHAR *value, int d, int target)
680 {
681 	char lf = 10;
682 	TCHAR tmp[CONFIG_BLEN], tmpext[CONFIG_BLEN];
683 	const TCHAR *optionp;
684 	char tmpa[CONFIG_BLEN];
685 	char *tmp1, *tmp2;
686 	int utf8;
687 
688 	if (value == NULL)
689 		return;
690 	if (optionext) {
691 		_tcscpy (tmpext, option);
692 		_tcscat (tmpext, optionext);
693 		optionp = tmpext;
694 	} else {
695 		optionp = option;
696 	}
697 	utf8 = 0;
698 	tmp1 = ua (value);
699 	tmp2 = uutf8 (value);
700 	if (strcmp (tmp1, tmp2) && tmp2[0] != 0)
701 		utf8 = 1;
702 
703 	if (target)
704 		_stprintf (tmp, _T("%s.%s=%s"), TARGET_NAME, optionp, value);
705 	else
706 		_stprintf (tmp, _T("%s=%s"), optionp, value);
707 	if (d && isdefault (tmp))
708 		goto end;
709 	cfg_write (tmp, f);
710 	if (utf8 && !unicode_config) {
711 		char *opt = ua (optionp);
712 		if (target) {
713 			char *tna = ua (TARGET_NAME);
714 			sprintf (tmpa, "%s.%s.utf8=%s", tna, opt, tmp2);
715 			xfree (tna);
716 		} else {
717 			sprintf (tmpa, "%s.utf8=%s", opt, tmp2);
718 		}
719 		xfree (opt);
720 		zfile_fwrite (tmpa, strlen (tmpa), 1, f);
721 		zfile_fwrite (&lf, 1, 1, f);
722 	}
723 end:
724 	xfree (tmp2);
725 	xfree (tmp1);
726 }
cfg_dowrite(struct zfile * f,const TCHAR * option,const TCHAR * value,int d,int target)727 static void cfg_dowrite (struct zfile *f, const TCHAR *option, const TCHAR *value, int d, int target)
728 {
729 	cfg_dowrite (f, option, NULL, value, d, target);
730 }
cfgfile_write_bool(struct zfile * f,const TCHAR * option,bool b)731 void cfgfile_write_bool (struct zfile *f, const TCHAR *option, bool b)
732 {
733 	cfg_dowrite (f, option, b ? _T("true") : _T("false"), 0, 0);
734 }
cfgfile_dwrite_bool(struct zfile * f,const TCHAR * option,bool b)735 void cfgfile_dwrite_bool (struct zfile *f, const TCHAR *option, bool b)
736 {
737 	cfg_dowrite (f, option, b ? _T("true") : _T("false"), 1, 0);
738 }
cfgfile_dwrite_bool(struct zfile * f,const TCHAR * option,const TCHAR * optionext,bool b)739 static void cfgfile_dwrite_bool (struct zfile *f, const TCHAR *option, const TCHAR *optionext, bool b)
740 {
741 	cfg_dowrite (f, option, optionext, b ? _T("true") : _T("false"), 1, 0);
742 }
cfgfile_dwrite_bool(struct zfile * f,const TCHAR * option,int b)743 static void cfgfile_dwrite_bool (struct zfile *f, const TCHAR *option, int b)
744 {
745 	cfgfile_dwrite_bool (f, option, b != 0);
746 }
cfgfile_write_str(struct zfile * f,const TCHAR * option,const TCHAR * value)747 void cfgfile_write_str (struct zfile *f, const TCHAR *option, const TCHAR *value)
748 {
749 	cfg_dowrite (f, option, value, 0, 0);
750 }
cfgfile_write_str(struct zfile * f,const TCHAR * option,const TCHAR * optionext,const TCHAR * value)751 static void cfgfile_write_str (struct zfile *f, const TCHAR *option, const TCHAR *optionext, const TCHAR *value)
752 {
753 	cfg_dowrite (f, option, optionext, value, 0, 0);
754 }
cfgfile_dwrite_str(struct zfile * f,const TCHAR * option,const TCHAR * value)755 void cfgfile_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value)
756 {
757 	cfg_dowrite (f, option, value, 1, 0);
758 }
cfgfile_dwrite_str(struct zfile * f,const TCHAR * option,const TCHAR * optionext,const TCHAR * value)759 static void cfgfile_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *optionext, const TCHAR *value)
760 {
761 	cfg_dowrite (f, option, optionext, value, 1, 0);
762 }
763 
cfgfile_target_write_bool(struct zfile * f,const TCHAR * option,bool b)764 void cfgfile_target_write_bool (struct zfile *f, const TCHAR *option, bool b)
765 {
766 	cfg_dowrite (f, option, b ? _T("true") : _T("false"), 0, 1);
767 }
cfgfile_target_dwrite_bool(struct zfile * f,const TCHAR * option,bool b)768 void cfgfile_target_dwrite_bool (struct zfile *f, const TCHAR *option, bool b)
769 {
770 	cfg_dowrite (f, option, b ? _T("true") : _T("false"), 1, 1);
771 }
cfgfile_target_write_str(struct zfile * f,const TCHAR * option,const TCHAR * value)772 void cfgfile_target_write_str (struct zfile *f, const TCHAR *option, const TCHAR *value)
773 {
774 	cfg_dowrite (f, option, value, 0, 1);
775 }
cfgfile_target_dwrite_str(struct zfile * f,const TCHAR * option,const TCHAR * value)776 void cfgfile_target_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value)
777 {
778 	cfg_dowrite (f, option, value, 1, 1);
779 }
780 
cfgfile_write_ext(struct zfile * f,const TCHAR * option,const TCHAR * optionext,const TCHAR * format,...)781 static void cfgfile_write_ext (struct zfile *f, const TCHAR *option, const TCHAR *optionext, const TCHAR *format,...)
782 {
783 	va_list parms;
784 	TCHAR tmp[CONFIG_BLEN], tmp2[CONFIG_BLEN];
785 
786 	if (optionext) {
787 		_tcscpy (tmp2, option);
788 		_tcscat (tmp2, optionext);
789 	}
790 	va_start (parms, format);
791 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
792 	cfg_dowrite (f, optionext ? tmp2 : option, tmp, 0, 0);
793 	va_end (parms);
794 }
cfgfile_write(struct zfile * f,const TCHAR * option,const TCHAR * format,...)795 void cfgfile_write (struct zfile *f, const TCHAR *option, const TCHAR *format,...)
796 {
797 	va_list parms;
798 	TCHAR tmp[CONFIG_BLEN];
799 
800 	va_start (parms, format);
801 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
802 	cfg_dowrite (f, option, tmp, 0, 0);
803 	va_end (parms);
804 }
805 
cfgfile_dwrite_ext(struct zfile * f,const TCHAR * option,const TCHAR * optionext,const TCHAR * format,...)806 static void cfgfile_dwrite_ext (struct zfile *f, const TCHAR *option, const TCHAR *optionext, const TCHAR *format,...)
807 {
808 	va_list parms;
809 	TCHAR tmp[CONFIG_BLEN], tmp2[CONFIG_BLEN];
810 
811 	if (optionext) {
812 		_tcscpy (tmp2, option);
813 		_tcscat (tmp2, optionext);
814 	}
815 	va_start (parms, format);
816 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
817 	cfg_dowrite (f, optionext ? tmp2 : option, tmp, 1, 0);
818 	va_end (parms);
819 }
cfgfile_dwrite(struct zfile * f,const TCHAR * option,const TCHAR * format,...)820 void cfgfile_dwrite (struct zfile *f, const TCHAR *option, const TCHAR *format,...)
821 {
822 	va_list parms;
823 	TCHAR tmp[CONFIG_BLEN];
824 
825 	va_start (parms, format);
826 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
827 	cfg_dowrite (f, option, tmp, 1, 0);
828 	va_end (parms);
829 }
cfgfile_target_write(struct zfile * f,const TCHAR * option,const TCHAR * format,...)830 void cfgfile_target_write (struct zfile *f, const TCHAR *option, const TCHAR *format,...)
831 {
832 	va_list parms;
833 	TCHAR tmp[CONFIG_BLEN];
834 
835 	va_start (parms, format);
836 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
837 	cfg_dowrite (f, option, tmp, 0, 1);
838 	va_end (parms);
839 }
cfgfile_target_dwrite(struct zfile * f,const TCHAR * option,const TCHAR * format,...)840 void cfgfile_target_dwrite (struct zfile *f, const TCHAR *option, const TCHAR *format,...)
841 {
842 	va_list parms;
843 	TCHAR tmp[CONFIG_BLEN];
844 
845 	va_start (parms, format);
846 	_vsntprintf (tmp, CONFIG_BLEN, format, parms);
847 	cfg_dowrite (f, option, tmp, 1, 1);
848 	va_end (parms);
849 }
850 
cfgfile_write_rom(struct zfile * f,struct multipath * mp,const TCHAR * romfile,const TCHAR * name)851 static void cfgfile_write_rom (struct zfile *f, struct multipath *mp, const TCHAR *romfile, const TCHAR *name)
852 {
853 	TCHAR *str = cfgfile_subst_path (mp->path[0], UNEXPANDED, romfile);
854 	str = cfgfile_put_multipath (mp, str);
855 	cfgfile_write_str (f, name, str);
856 	struct zfile *zf = zfile_fopen (str, _T("rb"), ZFD_ALL);
857 	if (zf) {
858 		struct romdata *rd = getromdatabyzfile (zf);
859 		if (rd) {
860 			TCHAR name2[MAX_DPATH], str2[MAX_DPATH];
861 			_tcscpy (name2, name);
862 			_tcscat (name2, _T("_id"));
863 			_stprintf (str2, _T("%08X,%s"), rd->crc32, rd->name);
864 			cfgfile_write_str (f, name2, str2);
865 		}
866 		zfile_fclose (zf);
867 	}
868 	xfree (str);
869 
870 }
871 
cfgfile_write_path(struct zfile * f,struct multipath * mp,const TCHAR * option,const TCHAR * value)872 static void cfgfile_write_path (struct zfile *f, struct multipath *mp, const TCHAR *option, const TCHAR *value)
873 {
874 	TCHAR *s = cfgfile_put_multipath (mp, value);
875 	cfgfile_write_str (f, option, s);
876 	xfree (s);
877 }
cfgfile_dwrite_path(struct zfile * f,struct multipath * mp,const TCHAR * option,const TCHAR * value)878 static void cfgfile_dwrite_path (struct zfile *f, struct multipath *mp, const TCHAR *option, const TCHAR *value)
879 {
880 	TCHAR *s = cfgfile_put_multipath (mp, value);
881 	cfgfile_dwrite_str (f, option, s);
882 	xfree (s);
883 }
884 
write_filesys_config(struct uae_prefs * p,struct zfile * f)885 static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
886 {
887 	int i;
888 	TCHAR tmp[MAX_DPATH], tmp2[MAX_DPATH], tmp3[MAX_DPATH], hdcs[MAX_DPATH];
889 
890 	for (i = 0; i < p->mountitems; i++) {
891 		struct uaedev_config_data *uci = &p->mountconfig[i];
892 		struct uaedev_config_info *ci = &uci->ci;
893 		TCHAR *str1, *str1b, *str2b;
894 		const TCHAR *str2;
895 		int bp = ci->bootpri;
896 
897 		str2 = _T("");
898 		if (ci->rootdir[0] == ':') {
899 			TCHAR *ptr;
900 			// separate harddrive names
901 			str1 = my_strdup (ci->rootdir);
902 			ptr = _tcschr (str1 + 1, ':');
903 			if (ptr) {
904 				*ptr++ = 0;
905 				str2 = ptr;
906 				ptr = (TCHAR *) _tcschr (str2, ',');
907 				if (ptr)
908 					*ptr = 0;
909 			}
910 		} else {
911 			str1 = cfgfile_put_multipath (&p->path_hardfile, ci->rootdir);
912 		}
913 		int ct = ci->controller_type;
914 		if (ct >= HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST && ct <= HD_CONTROLLER_TYPE_SCSI_LAST) {
915 			_stprintf(hdcs, _T("scsi%d_%s"), ci->controller_unit, expansionroms[ct - HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST].name);
916 		} else if (ct >= HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST && ct <= HD_CONTROLLER_TYPE_IDE_LAST) {
917 			_stprintf(hdcs, _T("ide%d_%s"), ci->controller_unit, expansionroms[ct - HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST].name);
918 		} else if (ct >= HD_CONTROLLER_TYPE_SCSI_FIRST && ct < HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST) {
919 			_stprintf(hdcs, hdcontrollers[ct - HD_CONTROLLER_EXPANSION_MAX], ci->controller_unit);
920 		} else if (ct >= HD_CONTROLLER_TYPE_PCMCIA_SRAM && ct <= HD_CONTROLLER_TYPE_PCMCIA_IDE) {
921 			_stprintf(hdcs, hdcontrollers[ct - 2 * HD_CONTROLLER_EXPANSION_MAX], ci->controller_unit);
922 		} else {
923 			_stprintf(hdcs, hdcontrollers[ct], ci->controller_unit);
924 		}
925 		if (ci->controller_type_unit > 0)
926 			_stprintf(hdcs + _tcslen(hdcs), _T("-%d"), ci->controller_type_unit + 1);
927 
928 		str1b = cfgfile_escape (str1, _T(":,"), true);
929 		str2b = cfgfile_escape (str2, _T(":,"), true);
930 		if (ci->type == UAEDEV_DIR) {
931 			_stprintf (tmp, _T("%s,%s:%s:%s,%d"), ci->readonly ? _T("ro") : _T("rw"),
932 				ci->devname ? ci->devname : _T(""), ci->volname, str1, bp);
933 			cfgfile_write_str (f, _T("filesystem2"), tmp);
934 			_tcscpy (tmp3, tmp);
935 #if 0
936 			_stprintf (tmp2, _T("filesystem=%s,%s:%s"), uci->readonly ? _T("ro") : _T("rw"),
937 				uci->volname, str);
938 			zfile_fputs (f, tmp2);
939 #endif
940 		} else if (ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD || ci->type == UAEDEV_TAPE) {
941 			_stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"),
942 				ci->readonly ? _T("ro") : _T("rw"),
943 				ci->devname ? ci->devname : _T(""), str1,
944 				ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
945 				bp, ci->filesys ? ci->filesys : _T(""), hdcs);
946 			_stprintf (tmp3, _T("%s,%s:%s%s%s,%d,%d,%d,%d,%d,%s,%s"),
947 				ci->readonly ? _T("ro") : _T("rw"),
948 				ci->devname ? ci->devname : _T(""), str1b, str2b[0] ? _T(":") : _T(""), str2b,
949 				ci->sectors, ci->surfaces, ci->reserved, ci->blocksize,
950 				bp, ci->filesys ? ci->filesys : _T(""), hdcs);
951 			if (ci->highcyl || ci->physical_geometry) {
952 				TCHAR *s = tmp + _tcslen (tmp);
953 				TCHAR *s2 = s;
954 				_stprintf (s2, _T(",%d"), ci->highcyl);
955 				if (ci->physical_geometry && ci->pheads && ci->psecs) {
956 					TCHAR *s = tmp + _tcslen (tmp);
957 					_stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs);
958 				}
959 				_tcscat (tmp3, s2);
960 			}
961 			if (ci->controller_media_type) {
962 				_tcscat(tmp, _T(",CF"));
963 				_tcscat(tmp3, _T(",CF"));
964 			}
965 			const TCHAR *extras = NULL;
966 			if (ct >= HD_CONTROLLER_TYPE_SCSI_FIRST && ct <= HD_CONTROLLER_TYPE_SCSI_LAST) {
967 				if (ci->unit_feature_level == HD_LEVEL_SCSI_1){
968 					extras = _T("SCSI1");
969 				}	else if (ci->unit_feature_level == HD_LEVEL_SASI) {
970 					extras = _T("SASI");
971 				} else if (ci->unit_feature_level == HD_LEVEL_SASI_ENHANCED) {
972 					extras = _T("SASIE");
973 				} else if (ci->unit_feature_level == HD_LEVEL_SASI_CHS) {
974 					extras = _T("SASI_CHS");
975 				}
976 			} else if (ct >= HD_CONTROLLER_TYPE_IDE_FIRST && ct <= HD_CONTROLLER_TYPE_IDE_LAST) {
977 				if (ci->unit_feature_level == HD_LEVEL_ATA_1) {
978 					extras = _T("ATA1");
979 				} else if (ci->unit_feature_level == HD_LEVEL_ATA_2S) {
980 					extras = _T("ATA2+S");
981 				}
982 			}
983 			if (extras) {
984 				_tcscat(tmp, _T(","));
985 				_tcscat(tmp3, _T(","));
986 				_tcscat(tmp, extras);
987 				_tcscat(tmp3, extras);
988 			}
989 			if (ci->unit_special_flags) {
990 				TCHAR tmpx[32];
991 				_stprintf(tmpx, _T(",flags=0x%x"), ci->unit_special_flags);
992 				_tcscat(tmp, tmpx);
993 				_tcscat(tmp3, tmpx);
994 			}
995 			if (ci->type == UAEDEV_HDF)
996 				cfgfile_write_str (f, _T("hardfile2"), tmp);
997 #if 0
998 			_stprintf (tmp2, _T("hardfile=%s,%d,%d,%d,%d,%s"),
999 				uci->readonly ? "ro" : "rw", uci->sectors,
1000 				uci->surfaces, uci->reserved, uci->blocksize, str);
1001 			zfile_fputs (f, tmp2);
1002 #endif
1003 		}
1004 		_stprintf (tmp2, _T("uaehf%d"), i);
1005 		if (ci->type == UAEDEV_CD) {
1006 			cfgfile_write (f, tmp2, _T("cd%d,%s"), ci->device_emu_unit, tmp);
1007 		} else if (ci->type == UAEDEV_TAPE) {
1008 			cfgfile_write (f, tmp2, _T("tape%d,%s"), ci->device_emu_unit, tmp);
1009 		} else {
1010 			cfgfile_write (f, tmp2, _T("%s,%s"), ci->type == UAEDEV_HDF ? _T("hdf") : _T("dir"), tmp3);
1011 		}
1012 		if (ci->type == UAEDEV_DIR) {
1013 			bool add_extra = false;
1014 			if (ci->inject_icons) {
1015 				add_extra = true;
1016 			}
1017 			if (add_extra) {
1018 				_stprintf(tmp2, _T("%s,inject_icons=%s"), ci->devname, ci->inject_icons ? _T("true") : _T("false"));
1019 				cfgfile_write(f, _T("filesystem_extra"), tmp2);
1020 			}
1021 		}
1022 		xfree (str1b);
1023 		xfree (str2b);
1024 		xfree (str1);
1025 
1026 	}
1027 }
1028 
write_compatibility_cpu(struct zfile * f,struct uae_prefs * p)1029 static void write_compatibility_cpu (struct zfile *f, struct uae_prefs *p)
1030 {
1031 	TCHAR tmp[100];
1032 	int model;
1033 
1034 	model = p->cpu_model;
1035 	if (model == 68030)
1036 		model = 68020;
1037 	if (model == 68060)
1038 		model = 68040;
1039 	if (p->address_space_24 && model == 68020)
1040 		_tcscpy (tmp, _T("68ec020"));
1041 	else
1042 		_stprintf (tmp, _T("%d"), model);
1043 	if (model == 68020 && (p->fpu_model == 68881 || p->fpu_model == 68882))
1044 		_tcscat (tmp, _T("/68881"));
1045 	cfgfile_write (f, _T("cpu_type"), tmp);
1046 }
1047 
write_leds(struct zfile * f,const TCHAR * name,int mask)1048 static void write_leds (struct zfile *f, const TCHAR *name, int mask)
1049 {
1050 	TCHAR tmp[MAX_DPATH];
1051 	tmp[0] = 0;
1052 	for (int i = 0; leds[i]; i++) {
1053 		bool got = false;
1054 		for (int j = 0; leds[j]; j++) {
1055 			if (leds_order[j] == i) {
1056 				if (mask & (1 << j)) {
1057 					if (got)
1058 						_tcscat (tmp, _T(":"));
1059 					_tcscat (tmp, leds[j]);
1060 					got = true;
1061 				}
1062 			}
1063 		}
1064 		if (leds[i + 1] && got)
1065 			_tcscat (tmp, _T(","));
1066 	}
1067 	while (tmp[0] && tmp[_tcslen (tmp) - 1] == ',')
1068 		tmp[_tcslen (tmp) - 1] = 0;
1069 	cfgfile_dwrite_str (f, name, tmp);
1070 }
1071 
write_resolution(struct zfile * f,const TCHAR * ws,const TCHAR * hs,struct wh * wh)1072 static void write_resolution (struct zfile *f, const TCHAR *ws, const TCHAR *hs, struct wh *wh)
1073 {
1074 	if (wh->width <= 0 || wh->height <= 0 || wh->special == WH_NATIVE) {
1075 		cfgfile_write_str (f, ws, _T("native"));
1076 		cfgfile_write_str (f, hs, _T("native"));
1077 	} else {
1078 		cfgfile_write (f, ws, _T("%d"), wh->width);
1079 		cfgfile_write (f, hs, _T("%d"), wh->height);
1080 	}
1081 }
1082 
cfgfile_read_rom_settings(const struct expansionboardsettings * ebs,const TCHAR * buf)1083 static int cfgfile_read_rom_settings(const struct expansionboardsettings *ebs, const TCHAR *buf)
1084 {
1085 	int settings = 0;
1086 	int bitcnt = 0;
1087 	for (int i = 0; ebs[i].name; i++) {
1088 		const struct expansionboardsettings *eb = &ebs[i];
1089 		bitcnt += eb->bitshift;
1090 		if (eb->multiselect) {
1091 			int itemcnt = -1;
1092 			int itemfound = 0;
1093 			const TCHAR *p = eb->configname;
1094 			while (p[0]) {
1095 				if (itemcnt >= 0) {
1096 					if (cfgfile_option_find(buf, p)) {
1097 						itemfound = itemcnt;
1098 					}
1099 				}
1100 				itemcnt++;
1101 				p += _tcslen(p) + 1;
1102 			}
1103 			int cnt = 1;
1104 			int bits = 1;
1105 			for (int i = 0; i < 8; i++) {
1106 				if ((1 << i) >= itemcnt) {
1107 					cnt = 1 << i;
1108 					bits = i;
1109 					break;
1110 				}
1111 			}
1112 			int multimask = cnt - 1;
1113 			if (eb->invert)
1114 				itemfound ^= 0x7fffffff;
1115 			itemfound &= multimask;
1116 			settings |= itemfound << bitcnt;
1117 			bitcnt += bits;
1118 		} else {
1119 			int mask = 1 << bitcnt;
1120 			if (cfgfile_option_find(buf, eb->configname)) {
1121 				settings |= mask;
1122 			}
1123 			if (eb->invert)
1124 				settings ^= mask;
1125 			bitcnt++;
1126 		}
1127 	}
1128 	return settings;
1129 }
1130 
cfgfile_write_rom_settings(const struct expansionboardsettings * ebs,TCHAR * buf,int settings)1131 static void cfgfile_write_rom_settings(const struct expansionboardsettings *ebs, TCHAR *buf, int settings)
1132 {
1133 	int bitcnt = 0;
1134 	for (int j = 0; ebs[j].name; j++) {
1135 		const struct expansionboardsettings *eb = &ebs[j];
1136 		bitcnt += eb->bitshift;
1137 		if (eb->multiselect) {
1138 			int itemcnt = -1;
1139 			const TCHAR *p = eb->configname;
1140 			while (p[0]) {
1141 				itemcnt++;
1142 				p += _tcslen(p) + 1;
1143 			}
1144 			int cnt = 1;
1145 			int bits = 1;
1146 			for (int i = 0; i < 8; i++) {
1147 				if ((1 << i) >= itemcnt) {
1148 					cnt = 1 << i;
1149 					bits = i;
1150 					break;
1151 				}
1152 			}
1153 			int multimask = cnt - 1;
1154 			int multivalue = settings;
1155 			if (eb->invert)
1156 				multivalue ^= 0x7fffffff;
1157 			multivalue = (multivalue >> bitcnt) & multimask;
1158 			p = eb->configname;
1159 			while (multivalue >= 0) {
1160 				multivalue--;
1161 				p += _tcslen(p) + 1;
1162 			}
1163 			if (buf[0])
1164 				_tcscat(buf, _T(","));
1165 			_tcscat(buf, p);
1166 			bitcnt += bits;
1167 		} else {
1168 			int value = settings;
1169 			if (eb->invert)
1170 				value ^= 0x7fffffff;
1171 			if (value & (1 << bitcnt)) {
1172 				if (buf[0])
1173 					_tcscat(buf, _T(","));
1174 				_tcscat(buf, eb->configname);
1175 			}
1176 			bitcnt++;
1177 		}
1178 	}
1179 }
1180 
cfgfile_write_board_rom(struct zfile * f,struct multipath * mp,struct boardromconfig * br)1181 static void cfgfile_write_board_rom(struct zfile *f, struct multipath *mp, struct boardromconfig *br)
1182 {
1183 	TCHAR buf[256];
1184 	TCHAR name[256];
1185 	const struct expansionromtype *ert;
1186 
1187 	if (br->device_type == 0)
1188 		return;
1189 	ert = get_device_expansion_rom(br->device_type);
1190 	if (!ert)
1191 		return;
1192 	for (int i = 0; i < MAX_BOARD_ROMS; i++) {
1193 		if (br->device_num == 0)
1194 			_tcscpy(name, ert->name);
1195 		else
1196 			_stprintf(name, _T("%s-%d"), ert->name, br->device_num + 1);
1197 		if (i == 0 || _tcslen(br->roms[i].romfile)) {
1198 			_stprintf(buf, _T("%s%s_rom_file"), name, i ? _T("_ext") : _T(""));
1199 			cfgfile_write_rom (f, mp, br->roms[i].romfile, buf);
1200 			if (br->roms[i].romident[0]) {
1201 				_stprintf(buf, _T("%s%s_rom"), name, i ? _T("_ext") : _T(""));
1202 				cfgfile_dwrite_str (f, buf, br->roms[i].romident);
1203 			}
1204 			if (br->roms[i].autoboot_disabled || ert->subtypes || ert->settings || ert->id_jumper) {
1205 				TCHAR buf2[256], *p;
1206 				buf2[0] = 0;
1207 				p = buf2;
1208 				_stprintf(buf, _T("%s%s_rom_options"), name, i ? _T("_ext") : _T(""));
1209 				if (ert->subtypes) {
1210 					const struct expansionsubromtype *srt = ert->subtypes;
1211 					int k = br->roms[i].subtype;
1212 					while (k && srt[1].name) {
1213 						srt++;
1214 						k--;
1215 					}
1216 					_stprintf(p, _T("subtype=%s"), srt->configname);
1217 				}
1218 				if (br->roms[i].autoboot_disabled) {
1219 					if (buf2[0])
1220 						_tcscat(buf2, _T(","));
1221 					_tcscat(buf2, _T("autoboot_disabled=true"));
1222 				}
1223 				if (ert->id_jumper) {
1224 					TCHAR tmp[256];
1225 					_stprintf(tmp, _T("id=%d"), br->roms[i].device_id);
1226 					if (buf2[0])
1227 						_tcscat(buf2, _T(","));
1228 					_tcscat(buf2, tmp);
1229 				}
1230 				if (br->roms[i].device_settings && ert->settings) {
1231 					cfgfile_write_rom_settings(ert->settings, buf2, br->roms[i].device_settings);
1232 				}
1233 				if (buf2[0])
1234 					cfgfile_dwrite_str (f, buf, buf2);
1235 			}
1236 
1237 			if (br->roms[i].board_ram_size) {
1238 				_stprintf(buf, _T("%s%s_mem_size"), name, i ? _T("_ext") : _T(""));
1239 				cfgfile_write(f, buf, _T("%d"), br->roms[i].board_ram_size / 0x40000);
1240 			}
1241 		}
1242 	}
1243 }
1244 
cfgfile_save_options(struct zfile * f,struct uae_prefs * p,int type)1245 void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
1246 {
1247 	struct strlist *sl;
1248 	TCHAR tmp[MAX_DPATH];
1249 	int i;
1250 
1251 	cfgfile_write_str (f, _T("config_description"), p->description);
1252 	cfgfile_write_bool (f, _T("config_hardware"), type & CONFIG_TYPE_HARDWARE);
1253 	cfgfile_write_bool (f, _T("config_host"), !!(type & CONFIG_TYPE_HOST));
1254 	if (p->info[0])
1255 		cfgfile_write (f, _T("config_info"), p->info);
1256 	cfgfile_write (f, _T("config_version"), _T("%d.%d.%d"), UAEMAJOR, UAEMINOR, UAESUBREV);
1257 	cfgfile_write_str (f, _T("config_hardware_path"), p->config_hardware_path);
1258 	cfgfile_write_str (f, _T("config_host_path"), p->config_host_path);
1259 	cfgfile_write_str (f, _T("config_all_path"), p->config_all_path);
1260 	if (p->config_window_title[0])
1261 		cfgfile_write_str (f, _T("config_window_title"), p->config_window_title);
1262 
1263 	for (sl = p->all_lines; sl; sl = sl->next) {
1264 		if (sl->unknown) {
1265 			if (sl->option)
1266 				cfgfile_write_str (f, sl->option, sl->value);
1267 		}
1268 	}
1269 
1270 	for (i = 0; i < MAX_PATHS; i++) {
1271 		if (p->path_rom.path[i][0]) {
1272 			_stprintf (tmp, _T("%s.rom_path"), TARGET_NAME);
1273 			cfgfile_write_str (f, tmp, p->path_rom.path[i]);
1274 		}
1275 	}
1276 	for (i = 0; i < MAX_PATHS; i++) {
1277 		if (p->path_floppy.path[i][0]) {
1278 			_stprintf (tmp, _T("%s.floppy_path"), TARGET_NAME);
1279 			cfgfile_write_str (f, tmp, p->path_floppy.path[i]);
1280 		}
1281 	}
1282 	for (i = 0; i < MAX_PATHS; i++) {
1283 		if (p->path_hardfile.path[i][0]) {
1284 			_stprintf (tmp, _T("%s.hardfile_path"), TARGET_NAME);
1285 			cfgfile_write_str (f, tmp, p->path_hardfile.path[i]);
1286 		}
1287 	}
1288 	for (i = 0; i < MAX_PATHS; i++) {
1289 		if (p->path_cd.path[i][0]) {
1290 			_stprintf (tmp, _T("%s.cd_path"), TARGET_NAME);
1291 			cfgfile_write_str (f, tmp, p->path_cd.path[i]);
1292 		}
1293 	}
1294 
1295 	cfg_write (_T("; host-specific"), f);
1296 
1297 	target_save_options (f, p);
1298 
1299 	cfg_write (_T("; common"), f);
1300 
1301 	cfgfile_write_str (f, _T("use_gui"), guimode1[p->start_gui]);
1302 	cfgfile_write_bool (f, _T("use_debugger"), p->start_debugger);
1303 
1304 	cfgfile_write_rom (f, &p->path_rom, p->romfile, _T("kickstart_rom_file"));
1305 	cfgfile_write_rom (f, &p->path_rom, p->romextfile, _T("kickstart_ext_rom_file"));
1306 	if (p->romextfile2addr) {
1307 		cfgfile_write (f, _T("kickstart_ext_rom_file2_address"), _T("%x"), p->romextfile2addr);
1308 		cfgfile_write_rom (f, &p->path_rom, p->romextfile2, _T("kickstart_ext_rom_file2"));
1309 	}
1310 	if (p->romident[0])
1311 		cfgfile_dwrite_str (f, _T("kickstart_rom"), p->romident);
1312 	if (p->romextident[0])
1313 		cfgfile_write_str (f, _T("kickstart_ext_rom="), p->romextident);
1314 
1315 	for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) {
1316 		cfgfile_write_board_rom(f, &p->path_rom, &p->expansionboard[i]);
1317 	}
1318 
1319 	cfgfile_write_path (f, &p->path_rom, _T("flash_file"), p->flashfile);
1320 	cfgfile_write_path (f, &p->path_rom, _T("cart_file"), p->cartfile);
1321 	cfgfile_write_path (f, &p->path_rom, _T("rtc_file"), p->rtcfile);
1322 	if (p->cartident[0])
1323 		cfgfile_write_str (f, _T("cart"), p->cartident);
1324 	cfgfile_dwrite_path (f, &p->path_rom, _T("picassoiv_rom_file"), p->picassoivromfile);
1325 
1326 	cfgfile_write_bool (f, _T("kickshifter"), p->kickshifter);
1327 	cfgfile_write_bool (f, _T("ks_write_enabled"), p->rom_readwrite);
1328 
1329 	cfgfile_write (f, _T("floppy_volume"), _T("%d"), p->dfxclickvolume_disk[0]);
1330 	p->nr_floppies = 4;
1331 	for (i = 0; i < 4; i++) {
1332 		_stprintf (tmp, _T("floppy%d"), i);
1333 		cfgfile_write_path (f, &p->path_floppy, tmp, p->floppyslots[i].df);
1334 		_stprintf (tmp, _T("floppy%dwp"), i);
1335 		cfgfile_dwrite_bool (f, tmp, p->floppyslots[i].forcedwriteprotect);
1336 		_stprintf (tmp, _T("floppy%dtype"), i);
1337 		cfgfile_dwrite (f, tmp, _T("%d"), p->floppyslots[i].dfxtype);
1338 		_stprintf (tmp, _T("floppy%dsound"), i);
1339 		cfgfile_dwrite (f, tmp, _T("%d"), p->floppyslots[i].dfxclick);
1340 		if (p->floppyslots[i].dfxclick < 0 && p->floppyslots[i].dfxclickexternal[0]) {
1341 			_stprintf (tmp, _T("floppy%dsoundext"), i);
1342 			cfgfile_dwrite (f, tmp, p->floppyslots[i].dfxclickexternal);
1343 		}
1344 		if (p->floppyslots[i].dfxclick) {
1345 			_stprintf (tmp, _T("floppy%dsoundvolume_disk"), i);
1346 			cfgfile_write (f, tmp, _T("%d"), p->dfxclickvolume_disk[i]);
1347 			_stprintf (tmp, _T("floppy%dsoundvolume_empty"), i);
1348 			cfgfile_write (f, tmp, _T("%d"), p->dfxclickvolume_empty[i]);
1349 		}
1350 		if (p->floppyslots[i].dfxtype < 0 && p->nr_floppies > i)
1351 			p->nr_floppies = i;
1352 	}
1353 	for (i = 0; i < MAX_SPARE_DRIVES; i++) {
1354 		if (p->dfxlist[i][0]) {
1355 			_stprintf (tmp, _T("diskimage%d"), i);
1356 			cfgfile_dwrite_path (f, &p->path_floppy, tmp, p->dfxlist[i]);
1357 		}
1358 	}
1359 
1360 	for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
1361 		if (p->cdslots[i].name[0] || p->cdslots[i].inuse) {
1362 			TCHAR tmp2[MAX_DPATH];
1363 			_stprintf (tmp, _T("cdimage%d"), i);
1364 			TCHAR *s = cfgfile_put_multipath (&p->path_cd, p->cdslots[i].name);
1365 			_tcscpy (tmp2, s);
1366 			xfree (s);
1367 			if (p->cdslots[i].type != SCSI_UNIT_DEFAULT || _tcschr (p->cdslots[i].name, ',') || p->cdslots[i].delayed) {
1368 				_tcscat (tmp2, _T(","));
1369 				if (p->cdslots[i].delayed) {
1370 					_tcscat (tmp2, _T("delay"));
1371 					_tcscat (tmp2, _T(":"));
1372 				}
1373 				if (p->cdslots[i].type != SCSI_UNIT_DEFAULT) {
1374 					_tcscat (tmp2, cdmodes[p->cdslots[i].type + 1]);
1375 				}
1376 			}
1377 			cfgfile_write_str (f, tmp, tmp2);
1378 		}
1379 	}
1380 
1381 	for (i = 0; i < MAX_LUA_STATES; i++) {
1382 		if (p->luafiles[i][0]) {
1383 			cfgfile_write_str (f, _T("lua"), p->luafiles[i]);
1384 		}
1385 	}
1386 
1387 	if (p->statefile[0])
1388 		cfgfile_write_str (f, _T("statefile"), p->statefile);
1389 	if (p->quitstatefile[0])
1390 		cfgfile_write_str (f, _T("statefile_quit"), p->quitstatefile);
1391 
1392 	cfgfile_write (f, _T("nr_floppies"), _T("%d"), p->nr_floppies);
1393 	cfgfile_dwrite_bool (f, _T("floppy_write_protect"), p->floppy_read_only);
1394 	cfgfile_write (f, _T("floppy_speed"), _T("%d"), p->floppy_speed);
1395 	cfgfile_dwrite (f, _T("floppy_channel_mask"), _T("0x%x"), p->dfxclickchannelmask);
1396 	cfgfile_write (f, _T("cd_speed"), _T("%d"), p->cd_speed);
1397 	cfgfile_write_bool (f, _T("parallel_on_demand"), p->parallel_demand);
1398 	cfgfile_write_bool (f, _T("serial_on_demand"), p->serial_demand);
1399 	cfgfile_write_bool (f, _T("serial_hardware_ctsrts"), p->serial_hwctsrts);
1400 	cfgfile_write_bool (f, _T("serial_direct"), p->serial_direct);
1401 	cfgfile_dwrite (f, _T("serial_stopbits"), _T("%d"), p->serial_stopbits);
1402 	cfgfile_dwrite_str(f, _T("serial_translate"), serialcrlf[p->serial_crlf]);
1403 	cfgfile_write_str (f, _T("scsi"), scsimode[p->scsi]);
1404 	cfgfile_write_bool (f, _T("uaeserial"), p->uaeserial);
1405 	cfgfile_write_bool (f, _T("sana2"), p->sana2);
1406 
1407 	cfgfile_write_str (f, _T("sound_output"), soundmode1[p->produce_sound]);
1408 	cfgfile_write_str (f, _T("sound_channels"), stereomode[p->sound_stereo]);
1409 	cfgfile_write (f, _T("sound_stereo_separation"), _T("%d"), p->sound_stereo_separation);
1410 	cfgfile_write (f, _T("sound_stereo_mixing_delay"), _T("%d"), p->sound_mixed_stereo_delay >= 0 ? p->sound_mixed_stereo_delay : 0);
1411 	cfgfile_write (f, _T("sound_max_buff"), _T("%d"), p->sound_maxbsiz);
1412 	cfgfile_write (f, _T("sound_frequency"), _T("%d"), p->sound_freq);
1413 	cfgfile_write_str (f, _T("sound_interpol"), interpolmode[p->sound_interpol]);
1414 	cfgfile_write_str (f, _T("sound_filter"), soundfiltermode1[p->sound_filter]);
1415 	cfgfile_write_str (f, _T("sound_filter_type"), soundfiltermode2[p->sound_filter_type]);
1416 	cfgfile_write (f, _T("sound_volume"), _T("%d"), p->sound_volume_master);
1417 	cfgfile_write (f, _T("sound_volume_paula"), _T("%d"), p->sound_volume_paula);
1418 	if (p->sound_volume_cd >= 0)
1419 		cfgfile_write (f, _T("sound_volume_cd"), _T("%d"), p->sound_volume_cd);
1420 	if (p->sound_volume_board >= 0)
1421 		cfgfile_write (f, _T("sound_volume_ahi"), _T("%d"), p->sound_volume_board);
1422 	cfgfile_write_bool (f, _T("sound_auto"), p->sound_auto);
1423 	cfgfile_write_bool (f, _T("sound_cdaudio"), p->sound_cdaudio);
1424 	cfgfile_write_bool (f, _T("sound_stereo_swap_paula"), p->sound_stereo_swap_paula);
1425 	cfgfile_write_bool (f, _T("sound_stereo_swap_ahi"), p->sound_stereo_swap_ahi);
1426 	cfgfile_dwrite (f, _T("sampler_frequency"), _T("%d"), p->sampler_freq);
1427 	cfgfile_dwrite (f, _T("sampler_buffer"), _T("%d"), p->sampler_buffer);
1428 	cfgfile_dwrite_bool (f, _T("sampler_stereo"), p->sampler_stereo);
1429 
1430 	cfgfile_write_str (f, _T("comp_trustbyte"), compmode[p->comptrustbyte]);
1431 	cfgfile_write_str (f, _T("comp_trustword"), compmode[p->comptrustword]);
1432 	cfgfile_write_str (f, _T("comp_trustlong"), compmode[p->comptrustlong]);
1433 	cfgfile_write_str (f, _T("comp_trustnaddr"), compmode[p->comptrustnaddr]);
1434 	cfgfile_write_bool (f, _T("comp_nf"), p->compnf);
1435 	cfgfile_write_bool (f, _T("comp_constjump"), p->comp_constjump);
1436 	cfgfile_write_str (f, _T("comp_flushmode"), flushmode[p->comp_hardflush]);
1437 #ifdef USE_JIT_FPU
1438 	cfgfile_write_bool (f, _T("compfpu"), p->compfpu);
1439 #endif
1440 	cfgfile_write (f, _T("cachesize"), _T("%d"), p->cachesize);
1441 
1442 	for (i = 0; i < MAX_JPORTS; i++) {
1443 		struct jport *jp = &p->jports[i];
1444 		int v = jp->id;
1445 		TCHAR tmp1[MAX_DPATH], tmp2[MAX_DPATH];
1446 		if (v == JPORT_NONE) {
1447 			_tcscpy (tmp2, _T("none"));
1448 		} else if (v < JSEM_CUSTOM) {
1449 			_stprintf(tmp2, _T("kbd%d"), v + 1);
1450 		} else if (v < JSEM_JOYS) {
1451 			_stprintf(tmp2, _T("custom%d"), v - JSEM_CUSTOM);
1452 		} else if (v < JSEM_MICE) {
1453 			_stprintf (tmp2, _T("joy%d"), v - JSEM_JOYS);
1454 		} else {
1455 			_tcscpy (tmp2, _T("mouse"));
1456 			if (v - JSEM_MICE > 0)
1457 				_stprintf (tmp2, _T("mouse%d"), v - JSEM_MICE);
1458 		}
1459 		if (i < 2 || jp->id >= 0) {
1460 			_stprintf (tmp1, _T("joyport%d"), i);
1461 			cfgfile_write (f, tmp1, tmp2);
1462 			_stprintf (tmp1, _T("joyport%dautofire"), i);
1463 			cfgfile_write (f, tmp1, joyaf[jp->autofire]);
1464 			if (i < 2 && jp->mode > 0) {
1465 				_stprintf (tmp1, _T("joyport%dmode"), i);
1466 				cfgfile_write (f, tmp1, joyportmodes[jp->mode]);
1467 			}
1468 			if (jp->name[0]) {
1469 				_stprintf (tmp1, _T("joyportfriendlyname%d"), i);
1470 				cfgfile_write (f, tmp1, jp->name);
1471 			}
1472 			if (jp->configname[0]) {
1473 				_stprintf (tmp1, _T("joyportname%d"), i);
1474 				cfgfile_write (f, tmp1, jp->configname);
1475 			}
1476 			if (jp->nokeyboardoverride) {
1477 				_stprintf (tmp1, _T("joyport%dkeyboardoverride"), i);
1478 				cfgfile_write_bool (f, tmp1, !jp->nokeyboardoverride);
1479 			}
1480 		}
1481 	}
1482 	for (i = 0; i < MAX_JPORTS_CUSTOM; i++) {
1483 		struct jport_custom *jp = &p->jports_custom[i];
1484 		if (jp->custom[0]) {
1485 			TCHAR tmp1[MAX_DPATH];
1486 			_stprintf(tmp1, _T("joyportcustom%d"), i);
1487 			cfgfile_write(f, tmp1, jp->custom);
1488 		}
1489 	}
1490 
1491 	if (p->dongle) {
1492 		if (p->dongle + 1 >= sizeof (dongles) / sizeof (TCHAR*))
1493 			cfgfile_write (f, _T("dongle"), _T("%d"), p->dongle);
1494 		else
1495 			cfgfile_write_str (f, _T("dongle"), dongles[p->dongle]);
1496 	}
1497 
1498 	cfgfile_write_bool (f, _T("bsdsocket_emu"), p->socket_emu);
1499 	if (p->a2065name[0])
1500 		cfgfile_write_str (f, _T("a2065"), p->a2065name);
1501 	if (p->ne2000pciname[0])
1502 		cfgfile_write_str(f, _T("ne2000_pci"), p->ne2000pciname);
1503 
1504 #ifdef WITH_SLIRP
1505 #ifdef FSUAE
1506 	cfgfile_dwrite_str(f, _T("slirp_implementation"), slirp_implementations[p->slirp_implementation]);
1507 #endif
1508 	tmp[0] = 0;
1509 	for (i = 0; i < MAX_SLIRP_REDIRS; i++) {
1510 		struct slirp_redir *sr = &p->slirp_redirs[i];
1511 		if (sr->proto && !sr->srcport) {
1512 			TCHAR *p = tmp + _tcslen (tmp);
1513 			if (p > tmp)
1514 				*p++ = ',';
1515 			_stprintf (p, _T("%d"), sr->dstport);
1516 		}
1517 	}
1518 	if (tmp[0])
1519 		cfgfile_write_str (f, _T("slirp_ports"), tmp);
1520 	for (i = 0; i < MAX_SLIRP_REDIRS; i++) {
1521 		struct slirp_redir *sr = &p->slirp_redirs[i];
1522 		if (sr->proto && sr->srcport) {
1523 			uae_u32 v = htonl (sr->addr);
1524 			if (v) {
1525 				_stprintf (tmp, _T("%s:%d:%d:%d.%d.%d.%d"),
1526 					sr->proto == 1 ? _T("tcp") : _T("udp"),
1527 					sr->dstport, sr->srcport,
1528 					(v >> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
1529 			} else {
1530 				_stprintf (tmp, _T("%s:%d:%d"),
1531 					sr->proto == 1 ? _T("tcp") : _T("udp"),
1532 					sr->dstport, sr->srcport);
1533 			}
1534 			cfgfile_write_str (f, _T("slirp_redir"), tmp);
1535 		}
1536 	}
1537 #endif /* WITH_SLIRP */
1538 
1539 	cfgfile_write_bool (f, _T("synchronize_clock"), p->tod_hack);
1540 	cfgfile_write (f, _T("maprom"), _T("0x%x"), p->maprom);
1541 	cfgfile_dwrite_str (f, _T("boot_rom_uae"), uaebootrom[p->boot_rom]);
1542 	cfgfile_dwrite_str (f, _T("parallel_matrix_emulation"), epsonprinter[p->parallel_matrix_emulation]);
1543 	cfgfile_write_bool (f, _T("parallel_postscript_emulation"), p->parallel_postscript_emulation);
1544 	cfgfile_write_bool (f, _T("parallel_postscript_detection"), p->parallel_postscript_detection);
1545 	cfgfile_write_str (f, _T("ghostscript_parameters"), p->ghostscript_parameters);
1546 	cfgfile_write (f, _T("parallel_autoflush"), _T("%d"), p->parallel_autoflush_time);
1547 	cfgfile_dwrite (f, _T("uae_hide"), _T("%d"), p->uae_hide);
1548 	cfgfile_dwrite_bool (f, _T("uae_hide_autoconfig"), p->uae_hide_autoconfig);
1549 	cfgfile_dwrite_bool (f, _T("magic_mouse"), p->input_magic_mouse);
1550 	cfgfile_dwrite_str (f, _T("magic_mousecursor"), magiccursors[p->input_magic_mouse_cursor]);
1551 	cfgfile_dwrite_str (f, _T("absolute_mouse"), abspointers[p->input_tablet]);
1552 	cfgfile_dwrite_bool (f, _T("tablet_library"), p->tablet_library);
1553 	cfgfile_dwrite_bool (f, _T("clipboard_sharing"), p->clipboard_sharing);
1554 	cfgfile_dwrite_bool(f, _T("native_code"), p->native_code);
1555 
1556 	cfgfile_write (f, _T("gfx_display"), _T("%d"), p->gfx_apmode[APMODE_NATIVE].gfx_display);
1557 	cfgfile_write_str (f, _T("gfx_display_friendlyname"), target_get_display_name (p->gfx_apmode[APMODE_NATIVE].gfx_display, true));
1558 	cfgfile_write_str (f, _T("gfx_display_name"), target_get_display_name (p->gfx_apmode[APMODE_NATIVE].gfx_display, false));
1559 	cfgfile_write (f, _T("gfx_display_rtg"), _T("%d"), p->gfx_apmode[APMODE_RTG].gfx_display);
1560 	cfgfile_write_str (f, _T("gfx_display_friendlyname_rtg"), target_get_display_name (p->gfx_apmode[APMODE_RTG].gfx_display, true));
1561 	cfgfile_write_str (f, _T("gfx_display_name_rtg"), target_get_display_name (p->gfx_apmode[APMODE_RTG].gfx_display, false));
1562 
1563 	cfgfile_write (f, _T("gfx_framerate"), _T("%d"), p->gfx_framerate);
1564 	write_resolution (f, _T("gfx_width"), _T("gfx_height"), &p->gfx_size_win); /* compatibility with old versions */
1565 	cfgfile_write (f, _T("gfx_top_windowed"), _T("%d"), p->gfx_size_win.x);
1566 	cfgfile_write (f, _T("gfx_left_windowed"), _T("%d"), p->gfx_size_win.y);
1567 	write_resolution (f, _T("gfx_width_windowed"), _T("gfx_height_windowed"), &p->gfx_size_win);
1568 	write_resolution (f, _T("gfx_width_fullscreen"), _T("gfx_height_fullscreen"), &p->gfx_size_fs);
1569 	cfgfile_write (f, _T("gfx_refreshrate"), _T("%d"), p->gfx_apmode[0].gfx_refreshrate);
1570 	cfgfile_dwrite (f, _T("gfx_refreshrate_rtg"), _T("%d"), p->gfx_apmode[1].gfx_refreshrate);
1571 	cfgfile_write (f, _T("gfx_autoresolution"), _T("%d"), p->gfx_autoresolution);
1572 	cfgfile_dwrite (f, _T("gfx_autoresolution_delay"), _T("%d"), p->gfx_autoresolution_delay);
1573 	cfgfile_dwrite (f, _T("gfx_autoresolution_min_vertical"), vertmode[p->gfx_autoresolution_minv + 1]);
1574 	cfgfile_dwrite (f, _T("gfx_autoresolution_min_horizontal"), horizmode[p->gfx_autoresolution_minh + 1]);
1575 	cfgfile_write_bool (f, _T("gfx_autoresolution_vga"), p->gfx_autoresolution_vga);
1576 
1577 	cfgfile_write (f, _T("gfx_backbuffers"), _T("%d"), p->gfx_apmode[0].gfx_backbuffers);
1578 	cfgfile_write (f, _T("gfx_backbuffers_rtg"), _T("%d"), p->gfx_apmode[1].gfx_backbuffers);
1579 	if (p->gfx_apmode[APMODE_NATIVE].gfx_interlaced)
1580 		cfgfile_write_bool (f, _T("gfx_interlace"), p->gfx_apmode[APMODE_NATIVE].gfx_interlaced);
1581 	cfgfile_write_str (f, _T("gfx_vsync"), vsyncmodes[p->gfx_apmode[0].gfx_vsync]);
1582 	cfgfile_write_str (f, _T("gfx_vsyncmode"), vsyncmodes2[p->gfx_apmode[0].gfx_vsyncmode]);
1583 	cfgfile_write_str (f, _T("gfx_vsync_picasso"), vsyncmodes[p->gfx_apmode[1].gfx_vsync]);
1584 	cfgfile_write_str (f, _T("gfx_vsyncmode_picasso"), vsyncmodes2[p->gfx_apmode[1].gfx_vsyncmode]);
1585 	cfgfile_write_bool (f, _T("gfx_lores"), p->gfx_resolution == 0);
1586 	cfgfile_write_str (f, _T("gfx_resolution"), lorestype1[p->gfx_resolution]);
1587 	cfgfile_write_str (f, _T("gfx_lores_mode"), loresmode[p->gfx_lores_mode]);
1588 	cfgfile_write_bool (f, _T("gfx_flickerfixer"), p->gfx_scandoubler);
1589 	cfgfile_write_str (f, _T("gfx_linemode"), p->gfx_vresolution > 0 ? linemode[p->gfx_iscanlines * 4 + p->gfx_pscanlines + 1] : linemode[0]);
1590 	cfgfile_write_str (f, _T("gfx_fullscreen_amiga"), fullmodes[p->gfx_apmode[0].gfx_fullscreen]);
1591 	cfgfile_write_str (f, _T("gfx_fullscreen_picasso"), fullmodes[p->gfx_apmode[1].gfx_fullscreen]);
1592 	cfgfile_write_str (f, _T("gfx_center_horizontal"), centermode1[p->gfx_xcenter]);
1593 	cfgfile_write_str (f, _T("gfx_center_vertical"), centermode1[p->gfx_ycenter]);
1594 	cfgfile_write_str (f, _T("gfx_colour_mode"), colormode1[p->color_mode]);
1595 	cfgfile_write_bool (f, _T("gfx_blacker_than_black"), p->gfx_blackerthanblack);
1596 	cfgfile_dwrite_bool (f, _T("gfx_black_frame_insertion"), p->lightboost_strobo);
1597 	cfgfile_write_str (f, _T("gfx_api"), filterapi[p->gfx_api]);
1598 	cfgfile_dwrite (f, _T("gfx_horizontal_tweak"), _T("%d"), p->gfx_extrawidth);
1599 
1600 #ifdef GFXFILTER
1601 	for (int j = 0; j < 2; j++) {
1602 		struct gfx_filterdata *gf = &p->gf[j];
1603 		const TCHAR *ext = j == 0 ? NULL : _T("_rtg");
1604 		for (int i = 0; i <MAX_FILTERSHADERS; i++) {
1605 			if (gf->gfx_filtershader[i][0])
1606 				cfgfile_write_ext (f, _T("gfx_filter_pre"), ext, _T("D3D:%s"), gf->gfx_filtershader[i]);
1607 			if (gf->gfx_filtermask[i][0])
1608 				cfgfile_write_str (f, _T("gfx_filtermask_pre"), ext, gf->gfx_filtermask[i]);
1609 		}
1610 		for (int i = 0; i < MAX_FILTERSHADERS; i++) {
1611 			if (gf->gfx_filtershader[i + MAX_FILTERSHADERS][0])
1612 				cfgfile_write_ext (f, _T("gfx_filter_post"), ext, _T("D3D:%s"), gf->gfx_filtershader[i + MAX_FILTERSHADERS]);
1613 			if (gf->gfx_filtermask[i + MAX_FILTERSHADERS][0])
1614 				cfgfile_write_str (f, _T("gfx_filtermask_post"), ext, gf->gfx_filtermask[i + MAX_FILTERSHADERS]);
1615 		}
1616 		cfgfile_dwrite_str (f, _T("gfx_filter_mask"), ext, gf->gfx_filtermask[2 * MAX_FILTERSHADERS]);
1617 		{
1618 			bool d3dfound = false;
1619 			if (gf->gfx_filtershader[2 * MAX_FILTERSHADERS][0] && p->gfx_api) {
1620 				cfgfile_dwrite_ext (f, _T("gfx_filter"), ext, _T("D3D:%s"), gf->gfx_filtershader[2 * MAX_FILTERSHADERS]);
1621 				d3dfound = true;
1622 			}
1623 			if (!d3dfound) {
1624 				if (gf->gfx_filter > 0) {
1625 					int i = 0;
1626 					struct uae_filter *uf;
1627 					while (uaefilters[i].name) {
1628 						uf = &uaefilters[i];
1629 						if (uf->type == gf->gfx_filter) {
1630 							cfgfile_dwrite_str (f, _T("gfx_filter"), ext, uf->cfgname);
1631 						}
1632 						i++;
1633 					}
1634 				} else {
1635 					cfgfile_dwrite_ext (f, _T("gfx_filter"), ext, _T("no"));
1636 				}
1637 			}
1638 		}
1639 		cfgfile_dwrite_str (f, _T("gfx_filter_mode"), ext, filtermode2[gf->gfx_filter_filtermode]);
1640 		cfgfile_dwrite_ext (f, _T("gfx_filter_vert_zoomf"), ext, _T("%f"), gf->gfx_filter_vert_zoom);
1641 		cfgfile_dwrite_ext (f, _T("gfx_filter_horiz_zoomf"), ext, _T("%f"), gf->gfx_filter_horiz_zoom);
1642 		cfgfile_dwrite_ext (f, _T("gfx_filter_vert_zoom_multf"), ext, _T("%f"), gf->gfx_filter_vert_zoom_mult);
1643 		cfgfile_dwrite_ext (f, _T("gfx_filter_horiz_zoom_multf"), ext, _T("%f"), gf->gfx_filter_horiz_zoom_mult);
1644 		cfgfile_dwrite_ext (f, _T("gfx_filter_vert_offsetf"), ext, _T("%f"), gf->gfx_filter_vert_offset);
1645 		cfgfile_dwrite_ext (f, _T("gfx_filter_horiz_offsetf"), ext, _T("%f"), gf->gfx_filter_horiz_offset);
1646 
1647 		cfgfile_dwrite_ext (f, _T("gfx_filter_left_border"), ext, _T("%d"), gf->gfx_filter_left_border);
1648 		cfgfile_dwrite_ext (f, _T("gfx_filter_right_border"), ext, _T("%d"), gf->gfx_filter_right_border);
1649 		cfgfile_dwrite_ext (f, _T("gfx_filter_top_border"), ext, _T("%d"), gf->gfx_filter_top_border);
1650 		cfgfile_dwrite_ext (f, _T("gfx_filter_bottom_border"), ext, _T("%d"), gf->gfx_filter_bottom_border);
1651 
1652 		cfgfile_dwrite_ext (f, _T("gfx_filter_scanlines"), ext, _T("%d"), gf->gfx_filter_scanlines);
1653 		cfgfile_dwrite_ext (f, _T("gfx_filter_scanlinelevel"), ext, _T("%d"), gf->gfx_filter_scanlinelevel);
1654 		cfgfile_dwrite_ext (f, _T("gfx_filter_scanlineratio"), ext, _T("%d"), gf->gfx_filter_scanlineratio);
1655 
1656 		cfgfile_dwrite_ext (f, _T("gfx_filter_luminance"), ext, _T("%d"), gf->gfx_filter_luminance);
1657 		cfgfile_dwrite_ext (f, _T("gfx_filter_contrast"), ext, _T("%d"), gf->gfx_filter_contrast);
1658 		cfgfile_dwrite_ext (f, _T("gfx_filter_saturation"), ext, _T("%d"), gf->gfx_filter_saturation);
1659 		cfgfile_dwrite_ext (f, _T("gfx_filter_gamma"), ext, _T("%d"), gf->gfx_filter_gamma);
1660 		cfgfile_dwrite_ext (f, _T("gfx_filter_gamma_r"), ext, _T("%d"), gf->gfx_filter_gamma_ch[0]);
1661 		cfgfile_dwrite_ext (f, _T("gfx_filter_gamma_g"), ext, _T("%d"), gf->gfx_filter_gamma_ch[1]);
1662 		cfgfile_dwrite_ext (f, _T("gfx_filter_gamma_b"), ext, _T("%d"), gf->gfx_filter_gamma_ch[2]);
1663 
1664 		cfgfile_dwrite_ext (f, _T("gfx_filter_blur"), ext, _T("%d"), gf->gfx_filter_blur);
1665 		cfgfile_dwrite_ext (f, _T("gfx_filter_noise"), ext, _T("%d"), gf->gfx_filter_noise);
1666 		cfgfile_dwrite_bool (f, _T("gfx_filter_bilinear"), ext, gf->gfx_filter_bilinear != 0);
1667 
1668 		cfgfile_dwrite_ext (f, _T("gfx_filter_keep_autoscale_aspect"), ext, _T("%d"), gf->gfx_filter_keep_autoscale_aspect);
1669 		cfgfile_dwrite_str (f, _T("gfx_filter_keep_aspect"), ext, aspects[gf->gfx_filter_keep_aspect]);
1670 		cfgfile_dwrite_str(f, _T("gfx_filter_autoscale"), ext, ext == NULL ? autoscale[gf->gfx_filter_autoscale] : autoscale_rtg[gf->gfx_filter_autoscale]);
1671 		cfgfile_dwrite_str (f, _T("gfx_filter_autoscale_limit"), ext, autoscalelimit[gf->gfx_filter_integerscalelimit]);
1672 		cfgfile_dwrite_ext (f, _T("gfx_filter_aspect_ratio"), ext, _T("%d:%d"),
1673 			gf->gfx_filter_aspect >= 0 ? (gf->gfx_filter_aspect / ASPECTMULT) : -1,
1674 			gf->gfx_filter_aspect >= 0 ? (gf->gfx_filter_aspect & (ASPECTMULT - 1)) : -1);
1675 		if (gf->gfx_filteroverlay[0]) {
1676 			cfgfile_dwrite_ext(f, _T("gfx_filter_overlay"), ext, _T("%s%s"),
1677 				gf->gfx_filteroverlay, _tcschr (gf->gfx_filteroverlay, ',') ? _T(",") : _T(""));
1678 		}
1679 	}
1680 	cfgfile_dwrite (f, _T("gfx_luminance"), _T("%d"), p->gfx_luminance);
1681 	cfgfile_dwrite (f, _T("gfx_contrast"), _T("%d"), p->gfx_contrast);
1682 	cfgfile_dwrite (f, _T("gfx_gamma"), _T("%d"), p->gfx_gamma);
1683 	cfgfile_dwrite (f, _T("gfx_gamma_r"), _T("%d"), p->gfx_gamma_ch[0]);
1684 	cfgfile_dwrite (f, _T("gfx_gamma_g"), _T("%d"), p->gfx_gamma_ch[1]);
1685 	cfgfile_dwrite (f, _T("gfx_gamma_b"), _T("%d"), p->gfx_gamma_ch[2]);
1686 
1687 	cfgfile_dwrite (f, _T("gfx_center_horizontal_position"), _T("%d"), p->gfx_xcenter_pos);
1688 	cfgfile_dwrite (f, _T("gfx_center_vertical_position"), _T("%d"), p->gfx_ycenter_pos);
1689 	cfgfile_dwrite (f, _T("gfx_center_horizontal_size"), _T("%d"), p->gfx_xcenter_size);
1690 	cfgfile_dwrite (f, _T("gfx_center_vertical_size"), _T("%d"), p->gfx_ycenter_size);
1691 
1692 	cfgfile_dwrite (f, _T("rtg_vert_zoom_multf"), _T("%.f"), p->rtg_vert_zoom_mult);
1693 	cfgfile_dwrite (f, _T("rtg_horiz_zoom_multf"), _T("%.f"), p->rtg_horiz_zoom_mult);
1694 
1695 #endif
1696 
1697 	cfgfile_write_bool (f, _T("immediate_blits"), p->immediate_blits);
1698 	cfgfile_dwrite_str (f, _T("waiting_blits"), waitblits[p->waiting_blits]);
1699 	cfgfile_write_bool (f, _T("ntsc"), p->ntscmode);
1700 	cfgfile_write_bool (f, _T("genlock"), p->genlock);
1701 	cfgfile_dwrite_str(f, _T("genlockmode"), genlockmodes[p->genlock_image]);
1702 	cfgfile_dwrite_str(f, _T("genlock_image"), p->genlock_image_file);
1703 	cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix);
1704 	cfgfile_dwrite_str(f, _T("monitoremu"), specialmonitors[p->monitoremu]);
1705 
1706 	cfgfile_dwrite_bool (f, _T("show_leds"), !!(p->leds_on_screen & STATUSLINE_CHIPSET));
1707 	cfgfile_dwrite_bool (f, _T("show_leds_rtg"), !!(p->leds_on_screen & STATUSLINE_RTG));
1708 	write_leds(f, _T("show_leds_enabled"), p->leds_on_screen_mask[0]);
1709 	write_leds(f, _T("show_leds_enabled_rtg"), p->leds_on_screen_mask[1]);
1710 	cfgfile_dwrite_bool(f, _T("show_refresh_indicator"), p->refresh_indicator);
1711 
1712 	if (p->osd_pos.y || p->osd_pos.x) {
1713 		cfgfile_dwrite (f, _T("osd_position"), _T("%.1f%s:%.1f%s"),
1714 			p->osd_pos.x >= 20000 ? (p->osd_pos.x - 30000) / 10.0 : (float)p->osd_pos.x, p->osd_pos.x >= 20000 ? _T("%") : _T(""),
1715 			p->osd_pos.y >= 20000 ? (p->osd_pos.y - 30000) / 10.0 : (float)p->osd_pos.y, p->osd_pos.y >= 20000 ? _T("%") : _T(""));
1716 	}
1717 	cfgfile_dwrite (f, _T("keyboard_leds"), _T("numlock:%s,capslock:%s,scrolllock:%s"),
1718 		kbleds[p->keyboard_leds[0]], kbleds[p->keyboard_leds[1]], kbleds[p->keyboard_leds[2]]);
1719 	if (p->chipset_mask & CSMASK_AGA)
1720 		cfgfile_write (f, _T("chipset"),_T("aga"));
1721 	else if ((p->chipset_mask & CSMASK_ECS_AGNUS) && (p->chipset_mask & CSMASK_ECS_DENISE))
1722 		cfgfile_write (f, _T("chipset"),_T("ecs"));
1723 	else if (p->chipset_mask & CSMASK_ECS_AGNUS)
1724 		cfgfile_write (f, _T("chipset"),_T("ecs_agnus"));
1725 	else if (p->chipset_mask & CSMASK_ECS_DENISE)
1726 		cfgfile_write (f, _T("chipset"),_T("ecs_denise"));
1727 	else
1728 		cfgfile_write (f, _T("chipset"), _T("ocs"));
1729 	if (p->chipset_refreshrate > 0)
1730 		cfgfile_write (f, _T("chipset_refreshrate"), _T("%f"), p->chipset_refreshrate);
1731 
1732 	for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
1733 		if (p->cr[i].rate <= 0)
1734 			continue;
1735 		struct chipset_refresh *cr = &p->cr[i];
1736 		cr->index = i;
1737 		_stprintf (tmp, _T("%f"), cr->rate);
1738 		TCHAR *s = tmp + _tcslen (tmp);
1739 		if (cr->label[0] > 0 && i < MAX_CHIPSET_REFRESH)
1740 			s += _stprintf (s, _T(",t=%s"), cr->label);
1741 		if (cr->horiz > 0)
1742 			s += _stprintf (s, _T(",h=%d"), cr->horiz);
1743 		if (cr->vert > 0)
1744 			s += _stprintf (s, _T(",v=%d"), cr->vert);
1745 		if (cr->locked)
1746 			_tcscat (s, _T(",locked"));
1747 		if (cr->ntsc > 0)
1748 			_tcscat (s, _T(",ntsc"));
1749 		else if (cr->ntsc == 0)
1750 			_tcscat (s, _T(",pal"));
1751 		if (cr->lace > 0)
1752 			_tcscat (s, _T(",lace"));
1753 		else if (cr->lace == 0)
1754 			_tcscat (s, _T(",nlace"));
1755 		if (cr->framelength > 0)
1756 			_tcscat (s, _T(",lof"));
1757 		else if (cr->framelength == 0)
1758 			_tcscat (s, _T(",shf"));
1759 		if (cr->vsync > 0)
1760 			_tcscat (s, _T(",vsync"));
1761 		else if (cr->vsync == 0)
1762 			_tcscat (s, _T(",nvsync"));
1763 		if (cr->rtg)
1764 			_tcscat (s, _T(",rtg"));
1765 		if (cr->commands[0]) {
1766 			_tcscat (s, _T(","));
1767 			_tcscat (s, cr->commands);
1768 			for (int j = 0; j < _tcslen (s); j++) {
1769 				if (s[j] == '\n')
1770 					s[j] = ',';
1771 			}
1772 			s[_tcslen (s) - 1] = 0;
1773 		}
1774 		if (i == CHIPSET_REFRESH_PAL)
1775 			cfgfile_dwrite (f, _T("displaydata_pal"), tmp);
1776 		else if (i == CHIPSET_REFRESH_NTSC)
1777 			cfgfile_dwrite (f, _T("displaydata_ntsc"), tmp);
1778 		else
1779 			cfgfile_dwrite (f, _T("displaydata"), tmp);
1780 	}
1781 
1782 	cfgfile_write_str (f, _T("collision_level"), collmode[p->collision_level]);
1783 
1784 	cfgfile_write_str(f, _T("chipset_compatible"), cscompa[p->cs_compatible]);
1785 	cfgfile_dwrite_str (f, _T("ciaatod"), ciaatodmode[p->cs_ciaatod]);
1786 	cfgfile_dwrite_str (f, _T("rtc"), rtctype[p->cs_rtc]);
1787 	//cfgfile_dwrite (f, _T("chipset_rtc_adjust"), _T("%d"), p->cs_rtc_adjust);
1788 	cfgfile_dwrite_bool (f, _T("ksmirror_e0"), p->cs_ksmirror_e0);
1789 	cfgfile_dwrite_bool (f, _T("ksmirror_a8"), p->cs_ksmirror_a8);
1790 	cfgfile_dwrite_bool (f, _T("cd32cd"), p->cs_cd32cd);
1791 	cfgfile_dwrite_bool (f, _T("cd32c2p"), p->cs_cd32c2p);
1792 	cfgfile_dwrite_bool(f, _T("cd32nvram"), p->cs_cd32nvram);
1793 	cfgfile_dwrite (f, _T("cd32nvram_size"), _T("%d"), p->cs_cd32nvram_size / 1024);
1794 	cfgfile_dwrite_bool(f, _T("cd32fmv"), p->cs_cd32fmv);
1795 	cfgfile_dwrite_bool(f, _T("cdtvcd"), p->cs_cdtvcd);
1796 	cfgfile_dwrite_bool(f, _T("cdtv-cr"), p->cs_cdtvcr);
1797 	cfgfile_dwrite_bool (f, _T("cdtvram"), p->cs_cdtvram);
1798 	cfgfile_dwrite (f, _T("cdtvramcard"), _T("%d"), p->cs_cdtvcard);
1799 	cfgfile_dwrite_str (f, _T("ide"), p->cs_ide == IDE_A600A1200 ? _T("a600/a1200") : (p->cs_ide == IDE_A4000 ? _T("a4000") : _T("none")));
1800 	cfgfile_dwrite_bool (f, _T("a1000ram"), p->cs_a1000ram);
1801 	cfgfile_dwrite (f, _T("fatgary"), _T("%d"), p->cs_fatgaryrev);
1802 	cfgfile_dwrite (f, _T("ramsey"), _T("%d"), p->cs_ramseyrev);
1803 	cfgfile_dwrite_bool (f, _T("pcmcia"), p->cs_pcmcia);
1804 	cfgfile_dwrite_bool (f, _T("scsi_cdtv"), p->cs_cdtvscsi);
1805 	cfgfile_dwrite_bool (f, _T("scsi_a3000"), p->cs_mbdmac == 1);
1806 	cfgfile_dwrite_bool (f, _T("scsi_a4000t"), p->cs_mbdmac == 2);
1807 	cfgfile_dwrite_bool (f, _T("bogomem_fast"), p->cs_slowmemisfast);
1808 	cfgfile_dwrite_bool (f, _T("resetwarning"), p->cs_resetwarning);
1809 	cfgfile_dwrite_bool (f, _T("denise_noehb"), p->cs_denisenoehb);
1810 	cfgfile_dwrite_bool (f, _T("agnus_bltbusybug"), p->cs_agnusbltbusybug);
1811 	cfgfile_dwrite_bool (f, _T("ics_agnus"), p->cs_dipagnus);
1812 	cfgfile_dwrite_bool (f, _T("cia_todbug"), p->cs_ciatodbug);
1813 	cfgfile_dwrite_bool (f, _T("z3_autoconfig"), p->cs_z3autoconfig);
1814 	cfgfile_dwrite_bool (f, _T("1mchipjumper"), p->cs_1mchipjumper);
1815 	cfgfile_dwrite (f, _T("chipset_hacks"), _T("0x%x"), p->cs_hacks);
1816 
1817 	cfgfile_dwrite_str (f, _T("z3mapping"), z3mapping[p->z3_mapping_mode]);
1818 	cfgfile_dwrite_bool (f, _T("fastmem_autoconfig"), p->fastmem_autoconfig);
1819 	if (p->fastmem_size < 0x100000 && p->fastmem_size)
1820 		cfgfile_write (f, _T("fastmem_size_k"), _T("%d"), p->fastmem_size / 1024);
1821 	else
1822 		cfgfile_write (f, _T("fastmem_size"), _T("%d"), p->fastmem_size / 0x100000);
1823 	if (p->fastmem2_size < 0x100000 && p->fastmem2_size)
1824 		cfgfile_dwrite (f, _T("fastmem2_size_k"), _T("%d"), p->fastmem2_size / 1024);
1825 	else
1826 		cfgfile_dwrite (f, _T("fastmem2_size"), _T("%d"), p->fastmem2_size / 0x100000);
1827 	cfgfile_write (f, _T("mem25bit_size"), _T("%d"), p->mem25bit_size / 0x100000);
1828 	cfgfile_write (f, _T("a3000mem_size"), _T("%d"), p->mbresmem_low_size / 0x100000);
1829 	cfgfile_write (f, _T("mbresmem_size"), _T("%d"), p->mbresmem_high_size / 0x100000);
1830 	cfgfile_write (f, _T("z3mem_size"), _T("%d"), p->z3fastmem_size / 0x100000);
1831 	cfgfile_dwrite (f, _T("z3mem2_size"), _T("%d"), p->z3fastmem2_size / 0x100000);
1832 	cfgfile_write (f, _T("z3mem_start"), _T("0x%x"), p->z3autoconfig_start);
1833 	cfgfile_write(f, _T("bogomem_size"), _T("%d"), p->bogomem_size / 0x40000);
1834 	if (p->cpuboard_type) {
1835 		const struct cpuboardtype *cbt = &cpuboards[p->cpuboard_type];
1836 		const struct cpuboardsubtype *cbst = &cbt->subtypes[p->cpuboard_subtype];
1837 		const struct expansionboardsettings *cbs = cbst->settings;
1838 		cfgfile_dwrite_str(f, _T("cpuboard_type"), cbst->configname);
1839 		if (cbs && p->cpuboard_settings) {
1840 			tmp[0] = 0;
1841 			cfgfile_write_rom_settings(cbs, tmp, p->cpuboard_settings);
1842 			cfgfile_dwrite_str(f, _T("cpuboard_settings"), tmp);
1843 		}
1844 	} else {
1845 		cfgfile_dwrite_str(f, _T("cpuboard_type"), _T("none"));
1846 	}
1847 	cfgfile_dwrite(f, _T("cpuboardmem1_size"), _T("%d"), p->cpuboardmem1_size / 0x100000);
1848 	cfgfile_dwrite(f, _T("cpuboardmem2_size"), _T("%d"), p->cpuboardmem2_size / 0x100000);
1849 	cfgfile_write(f, _T("gfxcard_size"), _T("%d"), p->rtgmem_size / 0x100000);
1850 	cfgfile_write_str(f, _T("gfxcard_type"), gfxboard_get_configname(p->rtgmem_type));
1851 	cfgfile_write_bool(f, _T("gfxcard_hardware_vblank"), p->rtg_hardwareinterrupt);
1852 	cfgfile_write_bool (f, _T("gfxcard_hardware_sprite"), p->rtg_hardwaresprite);
1853 	cfgfile_write (f, _T("chipmem_size"), _T("%d"), p->chipmem_size == 0x20000 ? -1 : (p->chipmem_size == 0x40000 ? 0 : p->chipmem_size / 0x80000));
1854 	cfgfile_dwrite (f, _T("megachipmem_size"), _T("%d"), p->z3chipmem_size / 0x100000);
1855 	// do not save aros rom special space
1856 	if (!(p->custom_memory_sizes[0] == 512 * 1024 && p->custom_memory_sizes[1] == 512 * 1024 && p->custom_memory_addrs[0] == 0xa80000 && p->custom_memory_addrs[1] == 0xb00000)) {
1857 		if (p->custom_memory_sizes[0])
1858 			cfgfile_write (f, _T("addmem1"), _T("0x%x,0x%x"), p->custom_memory_addrs[0], p->custom_memory_sizes[0]);
1859 		if (p->custom_memory_sizes[1])
1860 			cfgfile_write (f, _T("addmem2"), _T("0x%x,0x%x"), p->custom_memory_addrs[1], p->custom_memory_sizes[1]);
1861 	}
1862 
1863 	if (p->m68k_speed > 0) {
1864 		cfgfile_write (f, _T("finegrain_cpu_speed"), _T("%d"), p->m68k_speed);
1865 	} else {
1866 		cfgfile_write_str (f, _T("cpu_speed"), p->m68k_speed < 0 ? _T("max") : _T("real"));
1867 	}
1868 	cfgfile_write (f, _T("cpu_throttle"), _T("%.1f"), p->m68k_speed_throttle);
1869 	cfgfile_dwrite(f, _T("cpu_x86_throttle"), _T("%.1f"), p->x86_speed_throttle);
1870 
1871 	/* do not reorder start */
1872 	write_compatibility_cpu(f, p);
1873 	cfgfile_write (f, _T("cpu_model"), _T("%d"), p->cpu_model);
1874 	if (p->fpu_model)
1875 		cfgfile_write (f, _T("fpu_model"), _T("%d"), p->fpu_model);
1876 	if (p->mmu_model)
1877 		cfgfile_write (f, _T("mmu_model"), _T("%d"), p->mmu_model);
1878 	if (p->ppc_mode) {
1879 		cfgfile_write_str(f, _T("ppc_model"), p->ppc_model[0] ? p->ppc_model : (p->ppc_mode == 1 ? _T("automatic") : _T("manual")));
1880 		cfgfile_write_str(f, _T("ppc_cpu_idle"), ppc_cpu_idle[p->ppc_cpu_idle]);
1881 	}
1882 	cfgfile_write_bool (f, _T("cpu_compatible"), p->cpu_compatible);
1883 	cfgfile_write_bool (f, _T("cpu_24bit_addressing"), p->address_space_24);
1884 	/* do not reorder end */
1885 	cfgfile_dwrite_bool(f, _T("cpu_reset_pause"), p->reset_delay);
1886 	cfgfile_dwrite_bool(f, _T("cpu_threaded"), p->cpu_thread);
1887 	if (p->ppc_mode)
1888 		cfgfile_write_str(f, _T("ppc_implementation"), ppc_implementations[p->ppc_implementation]);
1889 
1890 	if (p->cpu_cycle_exact) {
1891 		if (p->cpu_frequency)
1892 			cfgfile_write (f, _T("cpu_frequency"), _T("%d"), p->cpu_frequency);
1893 		if (p->cpu_clock_multiplier) {
1894 			if (p->cpu_clock_multiplier >= 256)
1895 				cfgfile_write (f, _T("cpu_multiplier"), _T("%d"), p->cpu_clock_multiplier >> 8);
1896 		}
1897 	}
1898 
1899 	cfgfile_write_bool (f, _T("cpu_cycle_exact"), p->cpu_cycle_exact);
1900 	// must be after cpu_cycle_exact
1901 	cfgfile_write_bool (f, _T("cpu_memory_cycle_exact"), p->cpu_memory_cycle_exact);
1902 	cfgfile_write_bool (f, _T("blitter_cycle_exact"), p->blitter_cycle_exact);
1903 	// must be after cpu_cycle_exact, cpu_memory_cycle_exact and blitter_cycle_exact
1904 	if (p->cpu_cycle_exact && p->blitter_cycle_exact)
1905 		cfgfile_write_str (f, _T("cycle_exact"), cycleexact[2]);
1906 	else if (p->cpu_memory_cycle_exact && p->blitter_cycle_exact)
1907 		cfgfile_write_str (f, _T("cycle_exact"), cycleexact[1]);
1908 	else
1909 		cfgfile_write_str (f, _T("cycle_exact"), cycleexact[0]);
1910 
1911 	cfgfile_dwrite_bool (f, _T("fpu_no_unimplemented"), p->fpu_no_unimplemented);
1912 	cfgfile_dwrite_bool (f, _T("cpu_no_unimplemented"), p->int_no_unimplemented);
1913 	cfgfile_write_bool (f, _T("fpu_strict"), p->fpu_strict);
1914 	cfgfile_dwrite_bool (f, _T("fpu_softfloat"), p->fpu_softfloat);
1915 
1916 	cfgfile_write_bool (f, _T("rtg_nocustom"), p->picasso96_nocustom);
1917 	cfgfile_write (f, _T("rtg_modes"), _T("0x%x"), p->picasso96_modeflags);
1918 
1919 	cfgfile_write_bool (f, _T("log_illegal_mem"), p->illegal_mem);
1920 	if (p->catweasel >= 100)
1921 		cfgfile_dwrite (f, _T("catweasel"), _T("0x%x"), p->catweasel);
1922 	else
1923 		cfgfile_dwrite (f, _T("catweasel"), _T("%d"), p->catweasel);
1924 	cfgfile_write_bool(f, _T("toccata"), p->sound_toccata);
1925 	if (p->sound_toccata_mixer)
1926 		cfgfile_write_bool(f, _T("toccata_mixer"), p->sound_toccata_mixer);
1927 	cfgfile_write_bool(f, _T("es1370_pci"), p->sound_es1370);
1928 	cfgfile_write_bool(f, _T("fm801_pci"), p->sound_fm801);
1929 
1930 	cfgfile_write_str (f, _T("kbd_lang"), (p->keyboard_lang == KBD_LANG_DE ? _T("de")
1931 		: p->keyboard_lang == KBD_LANG_DK ? _T("dk")
1932 		: p->keyboard_lang == KBD_LANG_ES ? _T("es")
1933 		: p->keyboard_lang == KBD_LANG_US ? _T("us")
1934 		: p->keyboard_lang == KBD_LANG_SE ? _T("se")
1935 		: p->keyboard_lang == KBD_LANG_FR ? _T("fr")
1936 		: p->keyboard_lang == KBD_LANG_IT ? _T("it")
1937 		: _T("FOO")));
1938 
1939 	cfgfile_dwrite (f, _T("state_replay_rate"), _T("%d"), p->statecapturerate);
1940 	cfgfile_dwrite (f, _T("state_replay_buffers"), _T("%d"), p->statecapturebuffersize);
1941 	cfgfile_dwrite_bool (f, _T("state_replay_autoplay"), p->inprec_autoplay);
1942 	cfgfile_dwrite_bool (f, _T("warp"), p->turbo_emulation);
1943 	cfgfile_dwrite (f, _T("warp_limit"), _T("%d"), p->turbo_emulation_limit);
1944 
1945 #ifdef FILESYS
1946 	write_filesys_config (p, f);
1947 	if (p->filesys_no_uaefsdb)
1948 		cfgfile_write_bool (f, _T("filesys_no_fsdb"), p->filesys_no_uaefsdb);
1949 	cfgfile_dwrite (f, _T("filesys_max_size"), _T("%d"), p->filesys_limit);
1950 	cfgfile_dwrite (f, _T("filesys_max_name_length"), _T("%d"), p->filesys_max_name);
1951 	cfgfile_dwrite (f, _T("filesys_max_file_size"), _T("%d"), p->filesys_max_file_size);
1952 	cfgfile_dwrite_bool (f, _T("filesys_inject_icons"), p->filesys_inject_icons);
1953 	cfgfile_dwrite_str (f, _T("filesys_inject_icons_drawer"), p->filesys_inject_icons_drawer);
1954 	cfgfile_dwrite_str (f, _T("filesys_inject_icons_project"), p->filesys_inject_icons_project);
1955 	cfgfile_dwrite_str (f, _T("filesys_inject_icons_tool"), p->filesys_inject_icons_tool);
1956 	cfgfile_dwrite_str (f, _T("scsidev_mode"), uaescsidevmodes[p->uaescsidevmode]);
1957 #endif
1958 
1959 	cfgfile_dwrite(f, _T("uaeboard_mode"),  _T("%d"), p->uaeboard);
1960 
1961 	write_inputdevice_config (p, f);
1962 }
1963 
cfgfile_yesno(const TCHAR * option,const TCHAR * value,const TCHAR * name,int * location,bool numbercheck)1964 static int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, bool numbercheck)
1965 {
1966 	if (name != NULL && _tcscmp (option, name) != 0)
1967 		return 0;
1968 	if (strcasecmp (value, _T("yes")) == 0 || strcasecmp (value, _T("y")) == 0
1969 		|| strcasecmp (value, _T("true")) == 0 || strcasecmp (value, _T("t")) == 0
1970 		|| (numbercheck && strcasecmp (value, _T("1")) == 0))
1971 		*location = 1;
1972 	else if (strcasecmp (value, _T("no")) == 0 || strcasecmp (value, _T("n")) == 0
1973 		|| strcasecmp (value, _T("false")) == 0 || strcasecmp (value, _T("f")) == 0
1974 		|| (numbercheck && strcasecmp (value, _T("0")) == 0))
1975 		*location = 0;
1976 	else {
1977 		cfgfile_warning(_T("Option '%s' requires a value of either 'true' or 'false' (was '%s').\n"), option, value);
1978 		return -1;
1979 	}
1980 	return 1;
1981 }
1982 
cfgfile_yesno(const TCHAR * option,const TCHAR * value,const TCHAR * name,int * location)1983 static int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location)
1984 {
1985 	return cfgfile_yesno (option, value, name, location, true);
1986 }
1987 
cfgfile_yesno(const TCHAR * option,const TCHAR * value,const TCHAR * name,bool * location,bool numbercheck)1988 static int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, bool *location, bool numbercheck)
1989 {
1990 	int val;
1991 	int ret = cfgfile_yesno (option, value, name, &val, numbercheck);
1992 	if (ret == 0)
1993 		return 0;
1994 	if (ret < 0)
1995 		*location = false;
1996 	else
1997 		*location = val != 0;
1998 	return 1;
1999 }
2000 
cfgfile_yesno(const TCHAR * option,const TCHAR * value,const TCHAR * name,bool * location)2001 int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, bool *location)
2002 {
2003 	return cfgfile_yesno (option, value, name, location, true);
2004 }
2005 
cfgfile_doubleval(const TCHAR * option,const TCHAR * value,const TCHAR * name,double * location)2006 static int cfgfile_doubleval (const TCHAR *option, const TCHAR *value, const TCHAR *name, double *location)
2007 {
2008 	TCHAR *endptr;
2009 	if (name != NULL && _tcscmp (option, name) != 0)
2010 		return 0;
2011 	*location = _tcstod (value, &endptr);
2012 	return 1;
2013 }
2014 
cfgfile_floatval(const TCHAR * option,const TCHAR * value,const TCHAR * name,const TCHAR * nameext,float * location)2015 static int cfgfile_floatval (const TCHAR *option, const TCHAR *value, const TCHAR *name, const TCHAR *nameext, float *location)
2016 {
2017 	TCHAR *endptr;
2018 	if (name == NULL)
2019 		return 0;
2020 	if (nameext) {
2021 		TCHAR tmp[MAX_DPATH];
2022 		_tcscpy (tmp, name);
2023 		_tcscat (tmp, nameext);
2024 		if (_tcscmp (tmp, option) != 0)
2025 			return 0;
2026 	} else {
2027 		if (_tcscmp (option, name) != 0)
2028 			return 0;
2029 	}
2030 	*location = (float)_tcstod (value, &endptr);
2031 	return 1;
2032 }
2033 
cfgfile_floatval(const TCHAR * option,const TCHAR * value,const TCHAR * name,float * location)2034 static int cfgfile_floatval (const TCHAR *option, const TCHAR *value, const TCHAR *name, float *location)
2035 {
2036 	return cfgfile_floatval (option, value, name, NULL, location);
2037 }
2038 
cfgfile_intval(const TCHAR * option,const TCHAR * value,const TCHAR * name,const TCHAR * nameext,unsigned int * location,int scale)2039 static int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, const TCHAR *nameext, unsigned int *location, int scale)
2040 {
2041 	int base = 10;
2042 	TCHAR *endptr;
2043 	TCHAR tmp[MAX_DPATH];
2044 
2045 	if (name == NULL)
2046 		return 0;
2047 	if (nameext) {
2048 		_tcscpy (tmp, name);
2049 		_tcscat (tmp, nameext);
2050 		if (_tcscmp (tmp, option) != 0)
2051 			return 0;
2052 	} else {
2053 		if (_tcscmp (option, name) != 0)
2054 			return 0;
2055 	}
2056 	/* I guess octal isn't popular enough to worry about here...  */
2057 	if (value[0] == '0' && _totupper (value[1]) == 'X')
2058 		value += 2, base = 16;
2059 	*location = _tcstol (value, &endptr, base) * scale;
2060 
2061 	if (*endptr != '\0' || *value == '\0') {
2062 		if (strcasecmp (value, _T("false")) == 0 || strcasecmp (value, _T("no")) == 0) {
2063 			*location = 0;
2064 			return 1;
2065 		}
2066 		if (strcasecmp (value, _T("true")) == 0 || strcasecmp (value, _T("yes")) == 0) {
2067 			*location = 1;
2068 			return 1;
2069 		}
2070 		cfgfile_warning(_T("Option '%s' requires a numeric argument but got '%s'\n"), nameext ? tmp : option, value);
2071 		return -1;
2072 	}
2073 	return 1;
2074 }
cfgfile_intval(const TCHAR * option,const TCHAR * value,const TCHAR * name,unsigned int * location,int scale)2075 static int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, unsigned int *location, int scale)
2076 {
2077 	return cfgfile_intval (option, value, name, NULL, location, scale);
2078 }
cfgfile_intval(const TCHAR * option,const TCHAR * value,const TCHAR * name,int * location,int scale)2079 int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, int scale)
2080 {
2081 	unsigned int v = 0;
2082 	int r = cfgfile_intval (option, value, name, NULL, &v, scale);
2083 	if (!r)
2084 		return 0;
2085 	*location = (int)v;
2086 	return r;
2087 }
cfgfile_intval(const TCHAR * option,const TCHAR * value,const TCHAR * name,const TCHAR * nameext,int * location,int scale)2088 static int cfgfile_intval (const TCHAR *option, const TCHAR *value, const TCHAR *name, const TCHAR *nameext, int *location, int scale)
2089 {
2090 	unsigned int v = 0;
2091 	int r = cfgfile_intval (option, value, name, nameext, &v, scale);
2092 	if (!r)
2093 		return 0;
2094 	*location = (int)v;
2095 	return r;
2096 }
2097 
cfgfile_strval(const TCHAR * option,const TCHAR * value,const TCHAR * name,const TCHAR * nameext,int * location,const TCHAR * table[],int more)2098 static int cfgfile_strval (const TCHAR *option, const TCHAR *value, const TCHAR *name, const TCHAR *nameext, int *location, const TCHAR *table[], int more)
2099 {
2100 	int val;
2101 	TCHAR tmp[MAX_DPATH];
2102 	if (name == NULL)
2103 		return 0;
2104 	if (nameext) {
2105 		_tcscpy (tmp, name);
2106 		_tcscat (tmp, nameext);
2107 		if (_tcscmp (tmp, option) != 0)
2108 			return 0;
2109 	} else {
2110 		if (_tcscmp (option, name) != 0)
2111 			return 0;
2112 	}
2113 	val = match_string (table, value);
2114 	if (val == -1) {
2115 		if (more)
2116 			return 0;
2117 		if (!strcasecmp (value, _T("yes")) || !strcasecmp (value, _T("true"))) {
2118 			val = 1;
2119 		} else if  (!strcasecmp (value, _T("no")) || !strcasecmp (value, _T("false"))) {
2120 			val = 0;
2121 		} else {
2122 			cfgfile_warning(_T("Unknown value ('%s') for option '%s'.\n"), value, nameext ? tmp : option);
2123 			return -1;
2124 		}
2125 	}
2126 	*location = val;
2127 	return 1;
2128 }
cfgfile_strval(const TCHAR * option,const TCHAR * value,const TCHAR * name,int * location,const TCHAR * table[],int more)2129 int cfgfile_strval (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, const TCHAR *table[], int more)
2130 {
2131 	return cfgfile_strval (option, value, name, NULL, location, table, more);
2132 }
2133 
cfgfile_strboolval(const TCHAR * option,const TCHAR * value,const TCHAR * name,bool * location,const TCHAR * table[],int more)2134 static int cfgfile_strboolval (const TCHAR *option, const TCHAR *value, const TCHAR *name, bool *location, const TCHAR *table[], int more)
2135 {
2136 	int locationint;
2137 	if (!cfgfile_strval (option, value, name, &locationint, table, more))
2138 		return 0;
2139 	*location = locationint != 0;
2140 	return 1;
2141 }
2142 
cfgfile_string(const TCHAR * option,const TCHAR * value,const TCHAR * name,TCHAR * location,int maxsz)2143 int cfgfile_string (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz)
2144 {
2145 	if (_tcscmp (option, name) != 0)
2146 		return 0;
2147 	_tcsncpy (location, value, maxsz - 1);
2148 	location[maxsz - 1] = '\0';
2149 	return 1;
2150 }
2151 
cfgfile_string(const TCHAR * option,const TCHAR * value,const TCHAR * name,const TCHAR * nameext,TCHAR * location,int maxsz)2152 static int cfgfile_string (const TCHAR *option, const TCHAR *value, const TCHAR *name, const TCHAR *nameext, TCHAR *location, int maxsz)
2153 {
2154 	if (nameext) {
2155 		TCHAR tmp[MAX_DPATH];
2156 		_tcscpy (tmp, name);
2157 		_tcscat (tmp, nameext);
2158 		if (_tcscmp (tmp, option) != 0)
2159 			return 0;
2160 	} else {
2161 		if (_tcscmp (option, name) != 0)
2162 			return 0;
2163 	}
2164 	_tcsncpy (location, value, maxsz - 1);
2165 	location[maxsz - 1] = '\0';
2166 	return 1;
2167 }
2168 
2169 
cfgfile_path(const TCHAR * option,const TCHAR * value,const TCHAR * name,TCHAR * location,int maxsz,struct multipath * mp)2170 static int cfgfile_path (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz, struct multipath *mp)
2171 {
2172 	if (!cfgfile_string (option, value, name, location, maxsz))
2173 		return 0;
2174 	TCHAR *s = target_expand_environment (location);
2175 	_tcsncpy (location, s, maxsz - 1);
2176 	location[maxsz - 1] = 0;
2177 	if (mp) {
2178 		for (int i = 0; i < MAX_PATHS; i++) {
2179 			if (mp->path[i][0] && _tcscmp (mp->path[i], _T(".\\")) != 0 && _tcscmp (mp->path[i], _T("./")) != 0 && (location[0] != '/' && location[0] != '\\' && !_tcschr(location, ':'))) {
2180 				TCHAR np[MAX_DPATH];
2181 				_tcscpy (np, mp->path[i]);
2182 				fixtrailing (np);
2183 				_tcscat (np, s);
2184 				fullpath (np, sizeof np / sizeof (TCHAR));
2185 				if (zfile_exists (np)) {
2186 					_tcsncpy (location, np, maxsz - 1);
2187 					location[maxsz - 1] = 0;
2188 					break;
2189 				}
2190 			}
2191 		}
2192 	}
2193 	xfree (s);
2194 	return 1;
2195 }
2196 
cfgfile_path(const TCHAR * option,const TCHAR * value,const TCHAR * name,TCHAR * location,int maxsz)2197 static int cfgfile_path (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz)
2198 {
2199 	return cfgfile_path (option, value, name, location, maxsz, NULL);
2200 }
2201 
cfgfile_multipath(const TCHAR * option,const TCHAR * value,const TCHAR * name,struct multipath * mp)2202 static int cfgfile_multipath (const TCHAR *option, const TCHAR *value, const TCHAR *name, struct multipath *mp)
2203 {
2204 	TCHAR tmploc[MAX_DPATH];
2205 	if (!cfgfile_string (option, value, name, tmploc, 256))
2206 		return 0;
2207 	for (int i = 0; i < MAX_PATHS; i++) {
2208 		if (mp->path[i][0] == 0 || (i == 0 && (!_tcscmp (mp->path[i], _T(".\\")) || !_tcscmp (mp->path[i], _T("./"))))) {
2209 			TCHAR *s = target_expand_environment (tmploc);
2210 			_tcsncpy (mp->path[i], s, 256 - 1);
2211 			mp->path[i][256 - 1] = 0;
2212 			fixtrailing (mp->path[i]);
2213 			xfree (s);
2214 			return 1;
2215 		}
2216 	}
2217 	return 1;
2218 }
2219 
cfgfile_rom(const TCHAR * option,const TCHAR * value,const TCHAR * name,TCHAR * location,int maxsz)2220 static int cfgfile_rom (const TCHAR *option, const TCHAR *value, const TCHAR *name, TCHAR *location, int maxsz)
2221 {
2222 	TCHAR id[MAX_DPATH];
2223 	if (!cfgfile_string (option, value, name, id, sizeof id / sizeof (TCHAR)))
2224 		return 0;
2225 	TCHAR *p = _tcschr (id, ',');
2226 	if (p) {
2227 		TCHAR *endptr, tmp;
2228 		*p = 0;
2229 		tmp = id[4];
2230 		id[4] = 0;
2231 		uae_u32 crc32 = _tcstol (id, &endptr, 16) << 16;
2232 		id[4] = tmp;
2233 		crc32 |= _tcstol (id + 4, &endptr, 16);
2234 		struct romdata *rd = getromdatabycrc (crc32, true);
2235 		if (rd) {
2236 			struct romdata *rd2 = getromdatabyid (rd->id);
2237 			if (rd->group == 0 && rd2 == rd) {
2238 				if (zfile_exists (location))
2239 					return 1;
2240 			}
2241 			if (rd->group && rd2)
2242 				rd = rd2;
2243 			struct romlist *rl = getromlistbyromdata (rd);
2244 			if (rl) {
2245 				write_log (_T("%s: %s -> %s\n"), name, location, rl->path);
2246 				_tcsncpy (location, rl->path, maxsz);
2247 			}
2248 		}
2249 	}
2250 	return 1;
2251 }
2252 
getintval(TCHAR ** p,int * result,int delim)2253 static int getintval (TCHAR **p, int *result, int delim)
2254 {
2255 	TCHAR *value = *p;
2256 	int base = 10;
2257 	TCHAR *endptr;
2258 	TCHAR *p2 = _tcschr (*p, delim);
2259 
2260 	if (p2 == 0)
2261 		return 0;
2262 
2263 	*p2++ = '\0';
2264 
2265 	if (value[0] == '0' && _totupper (value[1]) == 'X')
2266 		value += 2, base = 16;
2267 	*result = _tcstol (value, &endptr, base);
2268 	*p = p2;
2269 
2270 	if (*endptr != '\0' || *value == '\0')
2271 		return 0;
2272 
2273 	return 1;
2274 }
2275 
getintval2(TCHAR ** p,int * result,int delim,bool last)2276 static int getintval2 (TCHAR **p, int *result, int delim, bool last)
2277 {
2278 	TCHAR *value = *p;
2279 	int base = 10;
2280 	TCHAR *endptr;
2281 	TCHAR *p2;
2282 
2283 	p2 = _tcschr (*p, delim);
2284 	if (p2 == 0) {
2285 		if (last) {
2286 			if (delim != '.')
2287 				p2 = _tcschr (*p, ',');
2288 			if (p2 == 0) {
2289 				p2 = *p;
2290 				while(*p2)
2291 					p2++;
2292 				if (p2 == *p)
2293 					return 0;
2294 			}
2295 		} else {
2296 			return 0;
2297 		}
2298 	}
2299 	if (!_istdigit(**p) && **p != '-' && **p != '+')
2300 		return 0;
2301 
2302 	if (*p2 != 0)
2303 		*p2++ = '\0';
2304 
2305 	if (value[0] == '0' && _totupper (value[1]) == 'X')
2306 		value += 2, base = 16;
2307 	*result = _tcstol (value, &endptr, base);
2308 	*p = p2;
2309 
2310 	if (*endptr != '\0' || *value == '\0') {
2311 		*p = 0;
2312 		return 0;
2313 	}
2314 
2315 	return 1;
2316 }
2317 
cfgfile_option_select(TCHAR * s,const TCHAR * option,const TCHAR * select)2318 static int cfgfile_option_select(TCHAR *s, const TCHAR *option, const TCHAR *select)
2319 {
2320 	TCHAR buf[MAX_DPATH];
2321 	if (!s)
2322 		return -1;
2323 	_tcscpy(buf, s);
2324 	_tcscat(buf, _T(","));
2325 	TCHAR *p = buf;
2326 	for (;;) {
2327 		TCHAR *tmpp = _tcschr (p, ',');
2328 		if (tmpp == NULL)
2329 			return -1;
2330 		*tmpp++ = 0;
2331 		TCHAR *tmpp2 = _tcschr(p, '=');
2332 		if (!tmpp2)
2333 			return -1;
2334 		*tmpp2++ = 0;
2335 		if (!strcasecmp(p, option)) {
2336 			int idx = 0;
2337 			while (select[0]) {
2338 				if (!strcasecmp(select, tmpp2))
2339 					return idx;
2340 				idx++;
2341 				select += _tcslen(select) + 1;
2342 			}
2343 		}
2344 		p = tmpp;
2345 	}
2346 }
2347 
cfgfile_option_bool(TCHAR * s,const TCHAR * option)2348 static int cfgfile_option_bool(TCHAR *s, const TCHAR *option)
2349 {
2350 	TCHAR buf[MAX_DPATH];
2351 	if (!s)
2352 		return -1;
2353 	_tcscpy(buf, s);
2354 	_tcscat(buf, _T(","));
2355 	TCHAR *p = buf;
2356 	for (;;) {
2357 		TCHAR *tmpp = _tcschr (p, ',');
2358 		if (tmpp == NULL)
2359 			return -1;
2360 		*tmpp++ = 0;
2361 		TCHAR *tmpp2 = _tcschr(p, '=');
2362 		if (tmpp2)
2363 			*tmpp2++ = 0;
2364 		if (!strcasecmp(p, option)) {
2365 			if (!tmpp2)
2366 				return 0;
2367 			TCHAR *tmpp3 = _tcschr (tmpp2, ',');
2368 			if (tmpp3)
2369 				*tmpp3 = 0;
2370 			if (tmpp2 && !strcasecmp(tmpp2, _T("true")))
2371 				return 1;
2372 			if (tmpp2 && !strcasecmp(tmpp2, _T("false")))
2373 				return 0;
2374 			return 1;
2375 		}
2376 		p = tmpp;
2377 	}
2378 }
set_chipset_mask(struct uae_prefs * p,int val)2379 static void set_chipset_mask (struct uae_prefs *p, int val)
2380 {
2381 	p->chipset_mask = (val == 0 ? 0
2382 		: val == 1 ? CSMASK_ECS_AGNUS
2383 		: val == 2 ? CSMASK_ECS_DENISE
2384 		: val == 3 ? CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS
2385 		: CSMASK_AGA | CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS);
2386 }
2387 
cfgfile_parse_host(struct uae_prefs * p,TCHAR * option,TCHAR * value)2388 static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
2389 {
2390 	int i, v;
2391 	bool vb;
2392 	TCHAR *section = 0;
2393 	TCHAR *tmpp;
2394 	TCHAR tmpbuf[CONFIG_BLEN];
2395 
2396 	if (_tcsncmp (option, _T("input."), 6) == 0) {
2397 		read_inputdevice_config (p, option, value);
2398 		return 1;
2399 	}
2400 
2401 	for (tmpp = option; *tmpp != '\0'; tmpp++)
2402 		if (_istupper (*tmpp))
2403 			*tmpp = _totlower (*tmpp);
2404 	tmpp = _tcschr (option, '.');
2405 	if (tmpp) {
2406 		section = option;
2407 		option = tmpp + 1;
2408 		*tmpp = '\0';
2409 		if (_tcscmp (section, TARGET_NAME) == 0) {
2410 			/* We special case the various path options here.  */
2411 			if (cfgfile_multipath (option, value, _T("rom_path"), &p->path_rom)
2412 				|| cfgfile_multipath (option, value, _T("floppy_path"), &p->path_floppy)
2413 				|| cfgfile_multipath (option, value, _T("cd_path"), &p->path_cd)
2414 				|| cfgfile_multipath (option, value, _T("hardfile_path"), &p->path_hardfile))
2415 				return 1;
2416 			return target_parse_option (p, option, value);
2417 		}
2418 		return 0;
2419 	}
2420 
2421 	for (i = 0; i < MAX_SPARE_DRIVES; i++) {
2422 		_stprintf (tmpbuf, _T("diskimage%d"), i);
2423 		if (cfgfile_path (option, value, tmpbuf, p->dfxlist[i], sizeof p->dfxlist[i] / sizeof (TCHAR), &p->path_floppy)) {
2424 #if 0
2425 			if (i < 4 && !p->df[i][0])
2426 				_tcscpy (p->df[i], p->dfxlist[i]);
2427 #endif
2428 			return 1;
2429 		}
2430 	}
2431 
2432 	for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
2433 		TCHAR tmp[20];
2434 		_stprintf (tmp, _T("cdimage%d"), i);
2435 		if (!_tcsicmp (option, tmp)) {
2436 			if (!_tcsicmp (value, _T("autodetect"))) {
2437 				p->cdslots[i].type = SCSI_UNIT_DEFAULT;
2438 				p->cdslots[i].inuse = true;
2439 				p->cdslots[i].name[0] = 0;
2440 			} else {
2441 				p->cdslots[i].delayed = false;
2442 				TCHAR *next = _tcsrchr (value, ',');
2443 				int type = SCSI_UNIT_DEFAULT;
2444 				int mode = 0;
2445 				int unitnum = 0;
2446 				for (;;) {
2447 					if (!next)
2448 						break;
2449 					*next++ = 0;
2450 					TCHAR *next2 = _tcschr (next, ':');
2451 					if (next2)
2452 						*next2++ = 0;
2453 					if (!_tcsicmp (next, _T("delay"))) {
2454 						p->cdslots[i].delayed = true;
2455 						next = next2;
2456 						if (!next)
2457 							break;
2458 						next2 = _tcschr (next, ':');
2459 						if (next2)
2460 							*next2++ = 0;
2461 					}
2462 					type = match_string (cdmodes, next);
2463 					if (type < 0)
2464 						type = SCSI_UNIT_DEFAULT;
2465 					else
2466 						type--;
2467 					next = next2;
2468 					if (!next)
2469 						break;
2470 					next2 = _tcschr (next, ':');
2471 					if (next2)
2472 						*next2++ = 0;
2473 					mode = match_string (cdconmodes, next);
2474 					if (mode < 0)
2475 						mode = 0;
2476 					next = next2;
2477 					if (!next)
2478 						break;
2479 					next2 = _tcschr (next, ':');
2480 					if (next2)
2481 						*next2++ = 0;
2482 					cfgfile_intval (option, next, tmp, &unitnum, 1);
2483 				}
2484 				if (_tcslen (value) > 0) {
2485 					TCHAR *s = cfgfile_get_multipath (&p->path_cd, NULL, value, false);
2486 					_tcsncpy (p->cdslots[i].name, s, sizeof p->cdslots[i].name / sizeof (TCHAR));
2487 					xfree (s);
2488 				}
2489 				p->cdslots[i].name[sizeof p->cdslots[i].name - 1] = 0;
2490 				p->cdslots[i].inuse = true;
2491 				p->cdslots[i].type = type;
2492 			}
2493 			// disable all following units
2494 			i++;
2495 			while (i < MAX_TOTAL_SCSI_DEVICES) {
2496 				p->cdslots[i].type = SCSI_UNIT_DISABLED;
2497 				i++;
2498 			}
2499 			return 1;
2500 		}
2501 	}
2502 
2503 	if (!_tcsicmp (option, _T("lua"))) {
2504 		for (i = 0; i < MAX_LUA_STATES; i++) {
2505 			if (!p->luafiles[i][0]) {
2506 				_tcscpy (p->luafiles[i], value);
2507 				break;
2508 			}
2509 		}
2510 		return 1;
2511 	}
2512 
2513 	if (cfgfile_strval (option, value, _T("gfx_autoresolution_min_vertical"), &p->gfx_autoresolution_minv, vertmode, 0)) {
2514 		p->gfx_autoresolution_minv--;
2515 		return 1;
2516 	}
2517 	if (cfgfile_strval (option, value, _T("gfx_autoresolution_min_horizontal"), &p->gfx_autoresolution_minh, horizmode, 0)) {
2518 		p->gfx_autoresolution_minh--;
2519 		return 1;
2520 	}
2521 	if (!_tcsicmp (option, _T("gfx_autoresolution"))) {
2522 		p->gfx_autoresolution = 0;
2523 		cfgfile_intval (option, value, _T("gfx_autoresolution"), &p->gfx_autoresolution, 1);
2524 		if (!p->gfx_autoresolution) {
2525 			v = cfgfile_yesno (option, value, _T("gfx_autoresolution"), &vb);
2526 			if (v > 0)
2527 				p->gfx_autoresolution = vb ? 10 : 0;
2528 		}
2529 		return 1;
2530 	}
2531 
2532 	if (cfgfile_intval (option, value, _T("sound_frequency"), &p->sound_freq, 1)
2533 		|| cfgfile_intval (option, value, _T("sound_max_buff"), &p->sound_maxbsiz, 1)
2534 		|| cfgfile_intval (option, value, _T("state_replay_rate"), &p->statecapturerate, 1)
2535 		|| cfgfile_intval (option, value, _T("state_replay_buffers"), &p->statecapturebuffersize, 1)
2536 		|| cfgfile_yesno (option, value, _T("state_replay_autoplay"), &p->inprec_autoplay)
2537 		|| cfgfile_intval (option, value, _T("sound_frequency"), &p->sound_freq, 1)
2538 		|| cfgfile_intval (option, value, _T("sound_volume"), &p->sound_volume_master, 1)
2539 		|| cfgfile_intval (option, value, _T("sound_volume_paula"), &p->sound_volume_paula, 1)
2540 		|| cfgfile_intval (option, value, _T("sound_volume_cd"), &p->sound_volume_cd, 1)
2541 		|| cfgfile_intval (option, value, _T("sound_volume_ahi"), &p->sound_volume_board, 1)
2542 		|| cfgfile_intval (option, value, _T("sound_stereo_separation"), &p->sound_stereo_separation, 1)
2543 		|| cfgfile_intval (option, value, _T("sound_stereo_mixing_delay"), &p->sound_mixed_stereo_delay, 1)
2544 		|| cfgfile_intval (option, value, _T("sampler_frequency"), &p->sampler_freq, 1)
2545 		|| cfgfile_intval (option, value, _T("sampler_buffer"), &p->sampler_buffer, 1)
2546 		|| cfgfile_intval (option, value, _T("warp_limit"), &p->turbo_emulation_limit, 1)
2547 
2548 		|| cfgfile_intval (option, value, _T("gfx_framerate"), &p->gfx_framerate, 1)
2549 		|| cfgfile_intval (option, value, _T("gfx_top_windowed"), &p->gfx_size_win.x, 1)
2550 		|| cfgfile_intval (option, value, _T("gfx_left_windowed"), &p->gfx_size_win.y, 1)
2551 		|| cfgfile_intval (option, value, _T("gfx_refreshrate"), &p->gfx_apmode[APMODE_NATIVE].gfx_refreshrate, 1)
2552 		|| cfgfile_intval (option, value, _T("gfx_refreshrate_rtg"), &p->gfx_apmode[APMODE_RTG].gfx_refreshrate, 1)
2553 		|| cfgfile_intval (option, value, _T("gfx_autoresolution_delay"), &p->gfx_autoresolution_delay, 1)
2554 		|| cfgfile_intval (option, value, _T("gfx_backbuffers"), &p->gfx_apmode[APMODE_NATIVE].gfx_backbuffers, 1)
2555 		|| cfgfile_intval (option, value, _T("gfx_backbuffers_rtg"), &p->gfx_apmode[APMODE_RTG].gfx_backbuffers, 1)
2556 		|| cfgfile_yesno (option, value, _T("gfx_interlace"), &p->gfx_apmode[APMODE_NATIVE].gfx_interlaced)
2557 		|| cfgfile_yesno (option, value, _T("gfx_interlace_rtg"), &p->gfx_apmode[APMODE_RTG].gfx_interlaced)
2558 
2559 		|| cfgfile_intval (option, value, _T("gfx_center_horizontal_position"), &p->gfx_xcenter_pos, 1)
2560 		|| cfgfile_intval (option, value, _T("gfx_center_vertical_position"), &p->gfx_ycenter_pos, 1)
2561 		|| cfgfile_intval (option, value, _T("gfx_center_horizontal_size"), &p->gfx_xcenter_size, 1)
2562 		|| cfgfile_intval (option, value, _T("gfx_center_vertical_size"), &p->gfx_ycenter_size, 1)
2563 
2564 		|| cfgfile_intval (option, value, _T("filesys_max_size"), &p->filesys_limit, 1)
2565 		|| cfgfile_intval (option, value, _T("filesys_max_name_length"), &p->filesys_max_name, 1)
2566 		|| cfgfile_intval (option, value, _T("filesys_max_file_size"), &p->filesys_max_file_size, 1)
2567 		|| cfgfile_yesno (option, value, _T("filesys_inject_icons"), &p->filesys_inject_icons)
2568 		|| cfgfile_string (option, value, _T("filesys_inject_icons_drawer"), p->filesys_inject_icons_drawer, sizeof p->filesys_inject_icons_drawer / sizeof (TCHAR))
2569 		|| cfgfile_string (option, value, _T("filesys_inject_icons_project"), p->filesys_inject_icons_project, sizeof p->filesys_inject_icons_project / sizeof (TCHAR))
2570 		|| cfgfile_string (option, value, _T("filesys_inject_icons_tool"), p->filesys_inject_icons_tool, sizeof p->filesys_inject_icons_tool / sizeof (TCHAR))
2571 
2572 		|| cfgfile_intval (option, value, _T("gfx_luminance"), &p->gfx_luminance, 1)
2573 		|| cfgfile_intval (option, value, _T("gfx_contrast"), &p->gfx_contrast, 1)
2574 		|| cfgfile_intval (option, value, _T("gfx_gamma"), &p->gfx_gamma, 1)
2575 		|| cfgfile_intval (option, value, _T("gfx_gamma_r"), &p->gfx_gamma_ch[0], 1)
2576 		|| cfgfile_intval (option, value, _T("gfx_gamma_g"), &p->gfx_gamma_ch[1], 1)
2577 		|| cfgfile_intval (option, value, _T("gfx_gamma_b"), &p->gfx_gamma_ch[2], 1)
2578 		|| cfgfile_floatval (option, value, _T("rtg_vert_zoom_multf"), &p->rtg_vert_zoom_mult)
2579 		|| cfgfile_floatval (option, value, _T("rtg_horiz_zoom_multf"), &p->rtg_horiz_zoom_mult)
2580 		|| cfgfile_intval (option, value, _T("gfx_horizontal_tweak"), &p->gfx_extrawidth, 1)
2581 
2582 		|| cfgfile_intval (option, value, _T("floppy0sound"), &p->floppyslots[0].dfxclick, 1)
2583 		|| cfgfile_intval (option, value, _T("floppy1sound"), &p->floppyslots[1].dfxclick, 1)
2584 		|| cfgfile_intval (option, value, _T("floppy2sound"), &p->floppyslots[2].dfxclick, 1)
2585 		|| cfgfile_intval (option, value, _T("floppy3sound"), &p->floppyslots[3].dfxclick, 1)
2586 		|| cfgfile_intval (option, value, _T("floppy0soundvolume_disk"), &p->dfxclickvolume_disk[0], 1)
2587 		|| cfgfile_intval (option, value, _T("floppy1soundvolume_disk"), &p->dfxclickvolume_disk[1], 1)
2588 		|| cfgfile_intval (option, value, _T("floppy2soundvolume_disk"), &p->dfxclickvolume_disk[2], 1)
2589 		|| cfgfile_intval (option, value, _T("floppy3soundvolume_disk"), &p->dfxclickvolume_disk[3], 1)
2590 		|| cfgfile_intval (option, value, _T("floppy0soundvolume_empty"), &p->dfxclickvolume_empty[0], 1)
2591 		|| cfgfile_intval (option, value, _T("floppy1soundvolume_empty"), &p->dfxclickvolume_empty[1], 1)
2592 		|| cfgfile_intval (option, value, _T("floppy2soundvolume_empty"), &p->dfxclickvolume_empty[2], 1)
2593 		|| cfgfile_intval (option, value, _T("floppy3soundvolume_empty"), &p->dfxclickvolume_empty[3], 1)
2594 		|| cfgfile_intval (option, value, _T("floppy_channel_mask"), &p->dfxclickchannelmask, 1))
2595 		return 1;
2596 
2597 	if (cfgfile_path (option, value, _T("floppy0soundext"), p->floppyslots[0].dfxclickexternal, sizeof p->floppyslots[0].dfxclickexternal / sizeof (TCHAR))
2598 		|| cfgfile_path (option, value, _T("floppy1soundext"), p->floppyslots[1].dfxclickexternal, sizeof p->floppyslots[1].dfxclickexternal / sizeof (TCHAR))
2599 		|| cfgfile_path (option, value, _T("floppy2soundext"), p->floppyslots[2].dfxclickexternal, sizeof p->floppyslots[2].dfxclickexternal / sizeof (TCHAR))
2600 		|| cfgfile_path (option, value, _T("floppy3soundext"), p->floppyslots[3].dfxclickexternal, sizeof p->floppyslots[3].dfxclickexternal / sizeof (TCHAR))
2601 		|| cfgfile_string (option, value, _T("config_window_title"), p->config_window_title, sizeof p->config_window_title / sizeof (TCHAR))
2602 		|| cfgfile_string (option, value, _T("config_info"), p->info, sizeof p->info / sizeof (TCHAR))
2603 		|| cfgfile_string (option, value, _T("config_description"), p->description, sizeof p->description / sizeof (TCHAR)))
2604 		return 1;
2605 
2606 	if (cfgfile_yesno(option, value, _T("use_debugger"), &p->start_debugger)
2607 		|| cfgfile_yesno(option, value, _T("floppy0wp"), &p->floppyslots[0].forcedwriteprotect)
2608 		|| cfgfile_yesno(option, value, _T("floppy1wp"), &p->floppyslots[1].forcedwriteprotect)
2609 		|| cfgfile_yesno(option, value, _T("floppy2wp"), &p->floppyslots[2].forcedwriteprotect)
2610 		|| cfgfile_yesno(option, value, _T("floppy3wp"), &p->floppyslots[3].forcedwriteprotect)
2611 		|| cfgfile_yesno(option, value, _T("sampler_stereo"), &p->sampler_stereo)
2612 		|| cfgfile_yesno(option, value, _T("sound_auto"), &p->sound_auto)
2613 		|| cfgfile_yesno(option, value, _T("sound_cdaudio"), &p->sound_cdaudio)
2614 		|| cfgfile_yesno(option, value, _T("sound_stereo_swap_paula"), &p->sound_stereo_swap_paula)
2615 		|| cfgfile_yesno(option, value, _T("sound_stereo_swap_ahi"), &p->sound_stereo_swap_ahi)
2616 		|| cfgfile_yesno(option, value, _T("log_illegal_mem"), &p->illegal_mem)
2617 		|| cfgfile_yesno(option, value, _T("filesys_no_fsdb"), &p->filesys_no_uaefsdb)
2618 		|| cfgfile_yesno(option, value, _T("gfx_blacker_than_black"), &p->gfx_blackerthanblack)
2619 		|| cfgfile_yesno(option, value, _T("gfx_black_frame_insertion"), &p->lightboost_strobo)
2620 		|| cfgfile_yesno(option, value, _T("gfx_flickerfixer"), &p->gfx_scandoubler)
2621 		|| cfgfile_yesno(option, value, _T("gfx_autoresolution_vga"), &p->gfx_autoresolution_vga)
2622 		|| cfgfile_yesno(option, value, _T("show_refresh_indicator"), &p->refresh_indicator)
2623 		|| cfgfile_yesno(option, value, _T("magic_mouse"), &p->input_magic_mouse)
2624 		|| cfgfile_yesno(option, value, _T("warp"), &p->turbo_emulation)
2625 		|| cfgfile_yesno(option, value, _T("headless"), &p->headless)
2626 		|| cfgfile_yesno(option, value, _T("clipboard_sharing"), &p->clipboard_sharing)
2627 		|| cfgfile_yesno(option, value, _T("native_code"), &p->native_code)
2628 		|| cfgfile_yesno(option, value, _T("tablet_library"), &p->tablet_library)
2629 		|| cfgfile_yesno(option, value, _T("bsdsocket_emu"), &p->socket_emu))
2630 		return 1;
2631 
2632 	if (cfgfile_strval (option, value, _T("sound_output"), &p->produce_sound, soundmode1, 1)
2633 		|| cfgfile_strval (option, value, _T("sound_output"), &p->produce_sound, soundmode2, 0)
2634 		|| cfgfile_strval (option, value, _T("sound_interpol"), &p->sound_interpol, interpolmode, 0)
2635 		|| cfgfile_strval (option, value, _T("sound_filter"), &p->sound_filter, soundfiltermode1, 0)
2636 		|| cfgfile_strval (option, value, _T("sound_filter_type"), &p->sound_filter_type, soundfiltermode2, 0)
2637 		|| cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode1, 1)
2638 		|| cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode2, 1)
2639 		|| cfgfile_strboolval (option, value, _T("use_gui"), &p->start_gui, guimode3, 0)
2640 		|| cfgfile_strval (option, value, _T("gfx_resolution"), &p->gfx_resolution, lorestype1, 0)
2641 		|| cfgfile_strval (option, value, _T("gfx_lores"), &p->gfx_resolution, lorestype2, 0)
2642 		|| cfgfile_strval (option, value, _T("gfx_lores_mode"), &p->gfx_lores_mode, loresmode, 0)
2643 		|| cfgfile_strval (option, value, _T("gfx_fullscreen_amiga"), &p->gfx_apmode[APMODE_NATIVE].gfx_fullscreen, fullmodes, 0)
2644 		|| cfgfile_strval (option, value, _T("gfx_fullscreen_picasso"), &p->gfx_apmode[APMODE_RTG].gfx_fullscreen, fullmodes, 0)
2645 		|| cfgfile_strval (option, value, _T("gfx_center_horizontal"), &p->gfx_xcenter, centermode1, 1)
2646 		|| cfgfile_strval (option, value, _T("gfx_center_vertical"), &p->gfx_ycenter, centermode1, 1)
2647 		|| cfgfile_strval (option, value, _T("gfx_center_horizontal"), &p->gfx_xcenter, centermode2, 0)
2648 		|| cfgfile_strval (option, value, _T("gfx_center_vertical"), &p->gfx_ycenter, centermode2, 0)
2649 		|| cfgfile_strval (option, value, _T("gfx_colour_mode"), &p->color_mode, colormode1, 1)
2650 		|| cfgfile_strval (option, value, _T("gfx_colour_mode"), &p->color_mode, colormode2, 0)
2651 		|| cfgfile_strval (option, value, _T("gfx_color_mode"), &p->color_mode, colormode1, 1)
2652 		|| cfgfile_strval (option, value, _T("gfx_color_mode"), &p->color_mode, colormode2, 0)
2653 		|| cfgfile_strval (option, value, _T("gfx_max_horizontal"), &p->gfx_max_horizontal, maxhoriz, 0)
2654 		|| cfgfile_strval (option, value, _T("gfx_max_vertical"), &p->gfx_max_vertical, maxvert, 0)
2655 		|| cfgfile_strval (option, value, _T("gfx_api"), &p->gfx_api, filterapi, 0)
2656 		|| cfgfile_strval (option, value, _T("magic_mousecursor"), &p->input_magic_mouse_cursor, magiccursors, 0)
2657 		|| cfgfile_strval (option, value, _T("absolute_mouse"), &p->input_tablet, abspointers, 0))
2658 		return 1;
2659 
2660 #ifdef GFXFILTER
2661 	for (int j = 0; j < 2; j++) {
2662 		struct gfx_filterdata *gf = &p->gf[j];
2663 		const TCHAR *ext = j == 0 ? NULL : _T("_rtg");
2664 		if (cfgfile_strval (option, value, _T("gfx_filter_autoscale"), ext, &gf->gfx_filter_autoscale, j == 0 ? autoscale : autoscale_rtg, 0)
2665 			|| cfgfile_strval (option, value, _T("gfx_filter_keep_aspect"), ext, &gf->gfx_filter_keep_aspect, aspects, 0)
2666 			|| cfgfile_strval (option, value, _T("gfx_filter_autoscale_limit"), ext, &gf->gfx_filter_integerscalelimit, autoscalelimit, 0))
2667 			return 1;
2668 
2669 		if (cfgfile_floatval (option, value, _T("gfx_filter_vert_zoomf"), ext, &gf->gfx_filter_vert_zoom)
2670 			|| cfgfile_floatval (option, value, _T("gfx_filter_horiz_zoomf"), ext, &gf->gfx_filter_horiz_zoom)
2671 			|| cfgfile_floatval (option, value, _T("gfx_filter_vert_zoom_multf"), ext, &gf->gfx_filter_vert_zoom_mult)
2672 			|| cfgfile_floatval (option, value, _T("gfx_filter_horiz_zoom_multf"), ext, &gf->gfx_filter_horiz_zoom_mult)
2673 			|| cfgfile_floatval (option, value, _T("gfx_filter_vert_offsetf"), ext, &gf->gfx_filter_vert_offset)
2674 			|| cfgfile_floatval (option, value, _T("gfx_filter_horiz_offsetf"), ext, &gf->gfx_filter_horiz_offset)
2675 			|| cfgfile_intval (option, value, _T("gfx_filter_left_border"), ext, &gf->gfx_filter_left_border, 1)
2676 			|| cfgfile_intval (option, value, _T("gfx_filter_right_border"), ext, &gf->gfx_filter_right_border, 1)
2677 			|| cfgfile_intval (option, value, _T("gfx_filter_top_border"), ext, &gf->gfx_filter_top_border, 1)
2678 			|| cfgfile_intval (option, value, _T("gfx_filter_bottom_border"), ext, &gf->gfx_filter_bottom_border, 1)
2679 			|| cfgfile_intval (option, value, _T("gfx_filter_scanlines"), ext, &gf->gfx_filter_scanlines, 1)
2680 			|| cfgfile_intval (option, value, _T("gfx_filter_scanlinelevel"), ext, &gf->gfx_filter_scanlinelevel, 1)
2681 			|| cfgfile_intval (option, value, _T("gfx_filter_scanlineratio"), ext, &gf->gfx_filter_scanlineratio, 1)
2682 			|| cfgfile_intval (option, value, _T("gfx_filter_luminance"), ext, &gf->gfx_filter_luminance, 1)
2683 			|| cfgfile_intval (option, value, _T("gfx_filter_contrast"), ext, &gf->gfx_filter_contrast, 1)
2684 			|| cfgfile_intval (option, value, _T("gfx_filter_saturation"), ext, &gf->gfx_filter_saturation, 1)
2685 			|| cfgfile_intval (option, value, _T("gfx_filter_gamma"), ext, &gf->gfx_filter_gamma, 1)
2686 			|| cfgfile_intval (option, value, _T("gfx_filter_gamma_r"), ext, &gf->gfx_filter_gamma_ch[0], 1)
2687 			|| cfgfile_intval (option, value, _T("gfx_filter_gamma_g"), ext, &gf->gfx_filter_gamma_ch[1], 1)
2688 			|| cfgfile_intval (option, value, _T("gfx_filter_gamma_b"), ext, &gf->gfx_filter_gamma_ch[2], 1)
2689 			|| cfgfile_intval (option, value, _T("gfx_filter_blur"), ext, &gf->gfx_filter_blur, 1)
2690 			|| cfgfile_intval (option, value, _T("gfx_filter_noise"), ext, &gf->gfx_filter_noise, 1)
2691 			|| cfgfile_intval (option, value, _T("gfx_filter_bilinear"), ext, &gf->gfx_filter_bilinear, 1)
2692 			|| cfgfile_intval (option, value, _T("gfx_filter_keep_autoscale_aspect"), ext, &gf->gfx_filter_keep_autoscale_aspect, 1)
2693 			|| cfgfile_string (option, value, _T("gfx_filter_mask"), ext, gf->gfx_filtermask[2 * MAX_FILTERSHADERS], sizeof gf->gfx_filtermask[2 * MAX_FILTERSHADERS] / sizeof (TCHAR)))
2694 			return 1;
2695 	}
2696 #endif
2697 
2698 	if (cfgfile_intval (option, value, _T("floppy_volume"), &v, 1)) {
2699 		for (int i = 0; i < 4; i++) {
2700 			p->dfxclickvolume_disk[i] = v;
2701 			p->dfxclickvolume_empty[i] = v;
2702 		}
2703 		return 1;
2704 	}
2705 
2706 	if (_tcscmp (option, _T("gfx_width_windowed")) == 0) {
2707 		if (!_tcscmp (value, _T("native"))) {
2708 			p->gfx_size_win.width = 0;
2709 			p->gfx_size_win.height = 0;
2710 		} else {
2711 			cfgfile_intval (option, value, _T("gfx_width_windowed"), &p->gfx_size_win.width, 1);
2712 		}
2713 		return 1;
2714 	}
2715 	if (_tcscmp (option, _T("gfx_height_windowed")) == 0) {
2716 		if (!_tcscmp (value, _T("native"))) {
2717 			p->gfx_size_win.width = 0;
2718 			p->gfx_size_win.height = 0;
2719 		} else {
2720 			cfgfile_intval (option, value, _T("gfx_height_windowed"), &p->gfx_size_win.height, 1);
2721 		}
2722 		return 1;
2723 	}
2724 	if (_tcscmp (option, _T("gfx_width_fullscreen")) == 0) {
2725 		if (!_tcscmp (value, _T("native"))) {
2726 			p->gfx_size_fs.width = 0;
2727 			p->gfx_size_fs.height = 0;
2728 			p->gfx_size_fs.special = WH_NATIVE;
2729 		} else {
2730 			cfgfile_intval (option, value, _T("gfx_width_fullscreen"), &p->gfx_size_fs.width, 1);
2731 			p->gfx_size_fs.special = 0;
2732 		}
2733 		return 1;
2734 	}
2735 	if (_tcscmp (option, _T("gfx_height_fullscreen")) == 0) {
2736 		if (!_tcscmp (value, _T("native"))) {
2737 			p->gfx_size_fs.width = 0;
2738 			p->gfx_size_fs.height = 0;
2739 			p->gfx_size_fs.special = WH_NATIVE;
2740 		} else {
2741 			cfgfile_intval (option, value, _T("gfx_height_fullscreen"), &p->gfx_size_fs.height, 1);
2742 			p->gfx_size_fs.special = 0;
2743 		}
2744 		return 1;
2745 	}
2746 
2747 	if (cfgfile_intval (option, value, _T("gfx_display"), &p->gfx_apmode[APMODE_NATIVE].gfx_display, 1)) {
2748 		p->gfx_apmode[APMODE_RTG].gfx_display = p->gfx_apmode[APMODE_NATIVE].gfx_display;
2749 		return 1;
2750 	}
2751 	if (cfgfile_intval (option, value, _T("gfx_display_rtg"), &p->gfx_apmode[APMODE_RTG].gfx_display, 1)) {
2752 		return 1;
2753 	}
2754 	if (_tcscmp (option, _T("gfx_display_friendlyname")) == 0 || _tcscmp (option, _T("gfx_display_name")) == 0) {
2755 		TCHAR tmp[MAX_DPATH];
2756 		if (cfgfile_string (option, value, _T("gfx_display_friendlyname"), tmp, sizeof tmp / sizeof (TCHAR))) {
2757 			int num = target_get_display (tmp);
2758 			if (num >= 0)
2759 				p->gfx_apmode[APMODE_RTG].gfx_display = p->gfx_apmode[APMODE_NATIVE].gfx_display = num;
2760 		}
2761 		if (cfgfile_string (option, value, _T("gfx_display_name"), tmp, sizeof tmp / sizeof (TCHAR))) {
2762 			int num = target_get_display (tmp);
2763 			if (num >= 0)
2764 				p->gfx_apmode[APMODE_RTG].gfx_display = p->gfx_apmode[APMODE_NATIVE].gfx_display = num;
2765 		}
2766 		return 1;
2767 	}
2768 	if (_tcscmp (option, _T("gfx_display_friendlyname_rtg")) == 0 || _tcscmp (option, _T("gfx_display_name_rtg")) == 0) {
2769 		TCHAR tmp[MAX_DPATH];
2770 		if (cfgfile_string (option, value, _T("gfx_display_friendlyname_rtg"), tmp, sizeof tmp / sizeof (TCHAR))) {
2771 			int num = target_get_display (tmp);
2772 			if (num >= 0)
2773 				p->gfx_apmode[APMODE_RTG].gfx_display = num;
2774 		}
2775 		if (cfgfile_string (option, value, _T("gfx_display_name_rtg"), tmp, sizeof tmp / sizeof (TCHAR))) {
2776 			int num = target_get_display (tmp);
2777 			if (num >= 0)
2778 				p->gfx_apmode[APMODE_RTG].gfx_display = num;
2779 		}
2780 		return 1;
2781 	}
2782 
2783 	if (_tcscmp (option, _T("gfx_linemode")) == 0) {
2784 		int v;
2785 		p->gfx_vresolution = VRES_DOUBLE;
2786 		p->gfx_pscanlines = 0;
2787 		p->gfx_iscanlines = 0;
2788 		if (cfgfile_strval(option, value, _T("gfx_linemode"), &v, linemode, 0)) {
2789 			p->gfx_vresolution = VRES_NONDOUBLE;
2790 			if (v > 0) {
2791 				p->gfx_iscanlines = (v - 1) / 4;
2792 				p->gfx_pscanlines = (v - 1) % 4;
2793 				p->gfx_vresolution = VRES_DOUBLE;
2794 			}
2795 		}
2796 		return 1;
2797 	}
2798 	if (_tcscmp (option, _T("gfx_vsync")) == 0) {
2799 		if (cfgfile_strval (option, value, _T("gfx_vsync"), &p->gfx_apmode[APMODE_NATIVE].gfx_vsync, vsyncmodes, 0) >= 0)
2800 			return 1;
2801 		return cfgfile_yesno (option, value, _T("gfx_vsync"), &p->gfx_apmode[APMODE_NATIVE].gfx_vsync);
2802 	}
2803 	if (_tcscmp (option, _T("gfx_vsync_picasso")) == 0) {
2804 		if (cfgfile_strval (option, value, _T("gfx_vsync_picasso"), &p->gfx_apmode[APMODE_RTG].gfx_vsync, vsyncmodes, 0) >= 0)
2805 			return 1;
2806 		return cfgfile_yesno (option, value, _T("gfx_vsync_picasso"), &p->gfx_apmode[APMODE_RTG].gfx_vsync);
2807 	}
2808 	if (cfgfile_strval (option, value, _T("gfx_vsyncmode"), &p->gfx_apmode[APMODE_NATIVE].gfx_vsyncmode, vsyncmodes2, 0))
2809 		return 1;
2810 	if (cfgfile_strval (option, value, _T("gfx_vsyncmode_picasso"), &p->gfx_apmode[APMODE_RTG].gfx_vsyncmode, vsyncmodes2, 0))
2811 		return 1;
2812 
2813 	if (cfgfile_yesno (option, value, _T("show_leds"), &vb)) {
2814 		if (vb)
2815 			p->leds_on_screen |= STATUSLINE_CHIPSET;
2816 		else
2817 			p->leds_on_screen &= ~STATUSLINE_CHIPSET;
2818 		return 1;
2819 	}
2820 	if (cfgfile_yesno (option, value, _T("show_leds_rtg"), &vb)) {
2821 		if (vb)
2822 			p->leds_on_screen |= STATUSLINE_RTG;
2823 		else
2824 			p->leds_on_screen &= ~STATUSLINE_RTG;
2825 		return 1;
2826 	}
2827 	if (_tcscmp (option, _T("show_leds_enabled")) == 0 || _tcscmp (option, _T("show_leds_enabled_rtg")) == 0) {
2828 		TCHAR tmp[MAX_DPATH];
2829 		int idx = _tcscmp (option, _T("show_leds_enabled")) == 0 ? 0 : 1;
2830 		p->leds_on_screen_mask[idx] = 0;
2831 		_tcscpy (tmp, value);
2832 		_tcscat (tmp, _T(","));
2833 		TCHAR *s = tmp;
2834 		for (;;) {
2835 			TCHAR *s2 = s;
2836 			TCHAR *s3 = _tcschr (s, ':');
2837 			s = _tcschr (s, ',');
2838 			if (!s)
2839 				break;
2840 			if (s3 && s3 < s)
2841 				s = s3;
2842 			*s = 0;
2843 			for (int i = 0; leds[i]; i++) {
2844 				if (!_tcsicmp (s2, leds[i])) {
2845 					p->leds_on_screen_mask[idx] |= 1 << i;
2846 				}
2847 			}
2848 			s++;
2849 		}
2850 		return 1;
2851 	}
2852 
2853 	if (!_tcscmp (option, _T("osd_position"))) {
2854 		TCHAR *s = value;
2855 		p->osd_pos.x = 0;
2856 		p->osd_pos.y = 0;
2857 		while (s) {
2858 			if (!_tcschr (s, ':'))
2859 				break;
2860 			p->osd_pos.x =  (int)(_tstof (s) * 10.0);
2861 			s = _tcschr (s, ':');
2862 			if (!s)
2863 				break;
2864 			if (s[-1] == '%')
2865 				p->osd_pos.x += 30000;
2866 			s++;
2867 			p->osd_pos.y = (int)(_tstof (s) * 10.0);
2868 			s += _tcslen (s);
2869 			if (s[-1] == '%')
2870 				p->osd_pos.y += 30000;
2871 			break;
2872 		}
2873 		return 1;
2874 	}
2875 
2876 #ifdef GFXFILTER
2877 	for (int j = 0; j < 2; j++) {
2878 		struct gfx_filterdata *gf = &p->gf[j];
2879 		if ((j == 0 && _tcscmp (option, _T("gfx_filter_overlay")) == 0) || (j == 1 && _tcscmp (option, _T("gfx_filter_overlay_rtg")) == 0)) {
2880 			TCHAR *s = _tcschr (value, ',');
2881 			gf->gfx_filteroverlay_overscan = 0;
2882 			gf->gfx_filteroverlay_pos.x = 0;
2883 			gf->gfx_filteroverlay_pos.y = 0;
2884 			gf->gfx_filteroverlay_pos.width = 0;
2885 			gf->gfx_filteroverlay_pos.height = 0;
2886 			if (s)
2887 				*s = 0;
2888 			while (s) {
2889 				*s++ = 0;
2890 				gf->gfx_filteroverlay_overscan = _tstol (s);
2891 				s = _tcschr (s, ':');
2892 				if (!s)
2893 					break;
2894 				break;
2895 			}
2896 			_tcsncpy (gf->gfx_filteroverlay, value, sizeof gf->gfx_filteroverlay / sizeof (TCHAR) - 1);
2897 			gf->gfx_filteroverlay[sizeof gf->gfx_filteroverlay / sizeof (TCHAR) - 1] = 0;
2898 			return 1;
2899 		}
2900 
2901 		if ((j == 0 && (_tcscmp (option, _T("gfx_filtermask_pre")) == 0 || _tcscmp (option, _T("gfx_filtermask_post")) == 0)) ||
2902 			(j == 1 && (_tcscmp (option, _T("gfx_filtermask_pre_rtg")) == 0 || _tcscmp (option, _T("gfx_filtermask_post_rtg")) == 0))) {
2903 			if (_tcscmp (option, _T("gfx_filtermask_pre")) == 0 || _tcscmp (option, _T("gfx_filtermask_pre_rtg")) == 0) {
2904 				for (int i = 0; i < MAX_FILTERSHADERS; i++) {
2905 					if (gf->gfx_filtermask[i][0] == 0) {
2906 						_tcscpy (gf->gfx_filtermask[i], value);
2907 						break;
2908 					}
2909 				}
2910 			} else {
2911 				for (int i = 0; i < MAX_FILTERSHADERS; i++) {
2912 					if (gf->gfx_filtermask[i + MAX_FILTERSHADERS][0] == 0) {
2913 						_tcscpy (gf->gfx_filtermask[i + MAX_FILTERSHADERS], value);
2914 						break;
2915 					}
2916 				}
2917 			}
2918 			return 1;
2919 		}
2920 
2921 		if ((j == 0 && (_tcscmp (option, _T("gfx_filter_pre")) == 0 || _tcscmp (option, _T("gfx_filter_post")) == 0)) ||
2922 			(j == 1 && (_tcscmp (option, _T("gfx_filter_pre_rtg")) == 0 || _tcscmp (option, _T("gfx_filter_post_rtg")) == 0))) {
2923 			TCHAR *s = _tcschr (value, ':');
2924 			if (s) {
2925 				*s++ = 0;
2926 				if (!_tcscmp (value, _T("D3D"))) {
2927 					p->gfx_api = 1;
2928 					if (_tcscmp (option, _T("gfx_filter_pre")) == 0 || _tcscmp (option, _T("gfx_filter_pre_rtg")) == 0) {
2929 						for (int i = 0; i < MAX_FILTERSHADERS; i++) {
2930 							if (gf->gfx_filtershader[i][0] == 0) {
2931 								_tcscpy (gf->gfx_filtershader[i], s);
2932 								break;
2933 							}
2934 						}
2935 					} else {
2936 						for (int i = 0; i < MAX_FILTERSHADERS; i++) {
2937 							if (gf->gfx_filtershader[i + MAX_FILTERSHADERS][0] == 0) {
2938 								_tcscpy (gf->gfx_filtershader[i + MAX_FILTERSHADERS], s);
2939 								break;
2940 							}
2941 						}
2942 					}
2943 				}
2944 			}
2945 			return 1;
2946 		}
2947 
2948 		if ((j == 0 && _tcscmp (option, _T("gfx_filter")) == 0) || (j == 1 && _tcscmp (option, _T("gfx_filter_rtg")) == 0)) {
2949 			TCHAR *s = _tcschr (value, ':');
2950 			gf->gfx_filter = 0;
2951 			if (s) {
2952 				*s++ = 0;
2953 				if (!_tcscmp (value, _T("D3D"))) {
2954 					p->gfx_api = 1;
2955 					_tcscpy (gf->gfx_filtershader[2 * MAX_FILTERSHADERS], s);
2956 					for (int i = 0; i < 2 * MAX_FILTERSHADERS; i++) {
2957 						if (!_tcsicmp (gf->gfx_filtershader[i], s)) {
2958 							gf->gfx_filtershader[i][0] = 0;
2959 							gf->gfx_filtermask[i][0] = 0;
2960 						}
2961 					}
2962 				}
2963 			}
2964 			if (!_tcscmp (value, _T("direct3d"))) {
2965 				p->gfx_api = 1; // forwards compatibiity
2966 			} else {
2967 				int i = 0;
2968 				while(uaefilters[i].name) {
2969 					if (!_tcscmp (uaefilters[i].cfgname, value)) {
2970 						gf->gfx_filter = uaefilters[i].type;
2971 						break;
2972 					}
2973 					i++;
2974 				}
2975 			}
2976 			return 1;
2977 		}
2978 		if (j == 0 && _tcscmp (option, _T("gfx_filter_mode")) == 0) {
2979 			cfgfile_strval (option, value, _T("gfx_filter_mode"), &gf->gfx_filter_filtermode, filtermode2, 0);
2980 			return 1;
2981 		}
2982 		if (j == 1 && _tcscmp (option, _T("gfx_filter_mode_rtg")) == 0) {
2983 			cfgfile_strval (option, value, _T("gfx_filter_mode_rtg"), &gf->gfx_filter_filtermode, filtermode2, 0);
2984 			return 1;
2985 		}
2986 
2987 		if ((j == 0 && cfgfile_string (option, value, _T("gfx_filter_aspect_ratio"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) ||
2988 			(j == 1 && cfgfile_string (option, value, _T("gfx_filter_aspect_ratio_rtg"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR)))) {
2989 			int v1, v2;
2990 			TCHAR *s;
2991 
2992 			gf->gfx_filter_aspect = -1;
2993 			v1 = _tstol (tmpbuf);
2994 			s = _tcschr (tmpbuf, ':');
2995 			if (s) {
2996 				v2 = _tstol (s + 1);
2997 				if (v1 < 0 || v2 < 0)
2998 					gf->gfx_filter_aspect = -1;
2999 				else if (v1 == 0 || v2 == 0)
3000 					gf->gfx_filter_aspect = 0;
3001 				else
3002 					gf->gfx_filter_aspect = v1 * ASPECTMULT + v2;
3003 			}
3004 			return 1;
3005 		}
3006 	}
3007 #endif
3008 
3009 	if (_tcscmp (option, _T("gfx_width")) == 0 || _tcscmp (option, _T("gfx_height")) == 0) {
3010 		cfgfile_intval (option, value, _T("gfx_width"), &p->gfx_size_win.width, 1);
3011 		cfgfile_intval (option, value, _T("gfx_height"), &p->gfx_size_win.height, 1);
3012 		p->gfx_size_fs.width = p->gfx_size_win.width;
3013 		p->gfx_size_fs.height = p->gfx_size_win.height;
3014 		return 1;
3015 	}
3016 
3017 	if (_tcscmp (option, _T("gfx_fullscreen_multi")) == 0 || _tcscmp (option, _T("gfx_windowed_multi")) == 0) {
3018 		TCHAR tmp[256], *tmpp, *tmpp2;
3019 		struct wh *wh = p->gfx_size_win_xtra;
3020 		if (_tcscmp (option, _T("gfx_fullscreen_multi")) == 0)
3021 			wh = p->gfx_size_fs_xtra;
3022 		_stprintf (tmp, _T(",%s,"), value);
3023 		tmpp2 = tmp;
3024 		for (i = 0; i < 4; i++) {
3025 			tmpp = _tcschr (tmpp2, ',');
3026 			tmpp++;
3027 			wh[i].width = _tstol (tmpp);
3028 			while (*tmpp != ',' && *tmpp != 'x' && *tmpp != '*')
3029 				tmpp++;
3030 			wh[i].height = _tstol (tmpp + 1);
3031 			tmpp2 = tmpp;
3032 		}
3033 		return 1;
3034 	}
3035 
3036 	if (cfgfile_string(option, value, _T("joyportcustom0"), p->jports_custom[0].custom, sizeof p->jports_custom[0].custom / sizeof(TCHAR)))
3037 		return 1;
3038 	if (cfgfile_string(option, value, _T("joyportcustom1"), p->jports_custom[1].custom, sizeof p->jports_custom[1].custom / sizeof(TCHAR)))
3039 		return 1;
3040 	if (cfgfile_string(option, value, _T("joyportcustom2"), p->jports_custom[2].custom, sizeof p->jports_custom[2].custom / sizeof(TCHAR)))
3041 		return 1;
3042 	if (cfgfile_string(option, value, _T("joyportcustom3"), p->jports_custom[3].custom, sizeof p->jports_custom[3].custom / sizeof(TCHAR)))
3043 		return 1;
3044 	if (cfgfile_string(option, value, _T("joyportcustom4"), p->jports_custom[4].custom, sizeof p->jports_custom[4].custom / sizeof(TCHAR)))
3045 		return 1;
3046 	if (cfgfile_string(option, value, _T("joyportcustom5"), p->jports_custom[5].custom, sizeof p->jports_custom[5].custom / sizeof(TCHAR)))
3047 		return 1;
3048 
3049 	if (_tcscmp (option, _T("joyportfriendlyname0")) == 0 || _tcscmp (option, _T("joyportfriendlyname1")) == 0) {
3050 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyportfriendlyname0")) == 0 ? 0 : 1, -1, 2);
3051 		return 1;
3052 	}
3053 	if (_tcscmp (option, _T("joyportfriendlyname2")) == 0 || _tcscmp (option, _T("joyportfriendlyname3")) == 0) {
3054 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyportfriendlyname2")) == 0 ? 2 : 3, -1, 2);
3055 		return 1;
3056 	}
3057 	if (_tcscmp (option, _T("joyportname0")) == 0 || _tcscmp (option, _T("joyportname1")) == 0) {
3058 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyportname0")) == 0 ? 0 : 1, -1, 1);
3059 		return 1;
3060 	}
3061 	if (_tcscmp (option, _T("joyportname2")) == 0 || _tcscmp (option, _T("joyportname3")) == 0) {
3062 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyportname2")) == 0 ? 2 : 3, -1, 1);
3063 		return 1;
3064 	}
3065 	if (_tcscmp (option, _T("joyport0")) == 0 || _tcscmp (option, _T("joyport1")) == 0) {
3066 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyport0")) == 0 ? 0 : 1, -1, 0);
3067 		return 1;
3068 	}
3069 	if (_tcscmp (option, _T("joyport2")) == 0 || _tcscmp (option, _T("joyport3")) == 0) {
3070 		inputdevice_joyport_config_store(p, value, _tcscmp (option, _T("joyport2")) == 0 ? 2 : 3, -1, 0);
3071 		return 1;
3072 	}
3073 	if (cfgfile_strval (option, value, _T("joyport0mode"), &p->jports[0].mode, joyportmodes, 0))
3074 		return 1;
3075 	if (cfgfile_strval (option, value, _T("joyport1mode"), &p->jports[1].mode, joyportmodes, 0))
3076 		return 1;
3077 	if (cfgfile_strval (option, value, _T("joyport2mode"), &p->jports[2].mode, joyportmodes, 0))
3078 		return 1;
3079 	if (cfgfile_strval (option, value, _T("joyport3mode"), &p->jports[3].mode, joyportmodes, 0))
3080 		return 1;
3081 	if (cfgfile_strval (option, value, _T("joyport0autofire"), &p->jports[0].autofire, joyaf, 0))
3082 		return 1;
3083 	if (cfgfile_strval (option, value, _T("joyport1autofire"), &p->jports[1].autofire, joyaf, 0))
3084 		return 1;
3085 	if (cfgfile_strval (option, value, _T("joyport2autofire"), &p->jports[2].autofire, joyaf, 0))
3086 		return 1;
3087 	if (cfgfile_strval (option, value, _T("joyport3autofire"), &p->jports[3].autofire, joyaf, 0))
3088 		return 1;
3089 
3090 	if (cfgfile_yesno (option, value, _T("joyport0keyboardoverride"), &vb)) {
3091 		p->jports[0].nokeyboardoverride = !vb;
3092 		return 1;
3093 	}
3094 	if (cfgfile_yesno (option, value, _T("joyport1keyboardoverride"), &vb)) {
3095 		p->jports[1].nokeyboardoverride = !vb;
3096 		return 1;
3097 	}
3098 	if (cfgfile_yesno (option, value, _T("joyport2keyboardoverride"), &vb)) {
3099 		p->jports[2].nokeyboardoverride = !vb;
3100 		return 1;
3101 	}
3102 	if (cfgfile_yesno (option, value, _T("joyport3keyboardoverride"), &vb)) {
3103 		p->jports[3].nokeyboardoverride = !vb;
3104 		return 1;
3105 	}
3106 
3107 #ifdef SAVESTATE
3108 
3109 	if (cfgfile_path (option, value, _T("statefile_quit"), p->quitstatefile, sizeof p->quitstatefile / sizeof (TCHAR)))
3110 		return 1;
3111 
3112 	if (cfgfile_string (option, value, _T("statefile_name"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
3113 		fetch_statefilepath (savestate_fname, sizeof savestate_fname / sizeof (TCHAR));
3114 		_tcscat (savestate_fname, tmpbuf);
3115 		if (_tcslen (savestate_fname) >= 4 && _tcsicmp (savestate_fname + _tcslen (savestate_fname) - 4, _T(".uss")))
3116 			_tcscat (savestate_fname, _T(".uss"));
3117 		return 1;
3118 	}
3119 
3120 	if (cfgfile_path (option, value, _T("statefile"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
3121 		_tcscpy (p->statefile, tmpbuf);
3122 		_tcscpy (savestate_fname, tmpbuf);
3123 		if (zfile_exists (savestate_fname)) {
3124 			savestate_state = STATE_DORESTORE;
3125 		} else {
3126 			int ok = 0;
3127 #ifdef FSUAE
3128             // code above seems broken, checks dir but removes file
3129             // simple fix: force ok (but leave WIN32 version as it
3130             // is, in case it is supposed to work like this
3131             ok = 1;
3132 #else
3133 			if (savestate_fname[0]) {
3134 				for (;;) {
3135 					TCHAR *p;
3136 					if (my_existsdir (savestate_fname)) {
3137 						ok = 1;
3138 						break;
3139 					}
3140 					p = _tcsrchr (savestate_fname, '\\');
3141 					if (!p)
3142 						p = _tcsrchr (savestate_fname, '/');
3143 					if (!p)
3144 						break;
3145 					*p = 0;
3146 				}
3147 			}
3148 #endif
3149 			if (!ok) {
3150 				TCHAR tmp[MAX_DPATH];
3151 				fetch_statefilepath (tmp, sizeof tmp / sizeof (TCHAR));
3152 				_tcscat (tmp, savestate_fname);
3153 				if (zfile_exists (tmp)) {
3154 					_tcscpy (savestate_fname, tmp);
3155 					savestate_state = STATE_DORESTORE;
3156 				} else {
3157 					savestate_fname[0] = 0;
3158 				}
3159 			}
3160 		}
3161 		return 1;
3162 	}
3163 
3164 #endif /* SAVESTATE */
3165 
3166 	if (cfgfile_strval (option, value, _T("sound_channels"), &p->sound_stereo, stereomode, 1)) {
3167 		if (p->sound_stereo == SND_NONE) { /* "mixed stereo" compatibility hack */
3168 			p->sound_stereo = SND_STEREO;
3169 			p->sound_mixed_stereo_delay = 5;
3170 			p->sound_stereo_separation = 7;
3171 		}
3172 		return 1;
3173 	}
3174 
3175 	if (_tcscmp (option, _T("kbd_lang")) == 0) {
3176 		KbdLang l;
3177 		if ((l = KBD_LANG_DE, strcasecmp (value, _T("de")) == 0)
3178 			|| (l = KBD_LANG_DK, strcasecmp (value, _T("dk")) == 0)
3179 			|| (l = KBD_LANG_SE, strcasecmp (value, _T("se")) == 0)
3180 			|| (l = KBD_LANG_US, strcasecmp (value, _T("us")) == 0)
3181 			|| (l = KBD_LANG_FR, strcasecmp (value, _T("fr")) == 0)
3182 			|| (l = KBD_LANG_IT, strcasecmp (value, _T("it")) == 0)
3183 			|| (l = KBD_LANG_ES, strcasecmp (value, _T("es")) == 0))
3184 			p->keyboard_lang = l;
3185 		else
3186 			cfgfile_warning(_T("Unknown keyboard language\n"));
3187 		return 1;
3188 	}
3189 
3190 	if (cfgfile_string (option, value, _T("config_version"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) {
3191 		TCHAR *tmpp2;
3192 		tmpp = _tcschr (value, '.');
3193 		if (tmpp) {
3194 			*tmpp++ = 0;
3195 			tmpp2 = tmpp;
3196 			p->config_version = _tstol (tmpbuf) << 16;
3197 			tmpp = _tcschr (tmpp, '.');
3198 			if (tmpp) {
3199 				*tmpp++ = 0;
3200 				p->config_version |= _tstol (tmpp2) << 8;
3201 				p->config_version |= _tstol (tmpp);
3202 			}
3203 		}
3204 		return 1;
3205 	}
3206 
3207 	if (cfgfile_string (option, value, _T("keyboard_leds"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) {
3208 		TCHAR *tmpp2 = tmpbuf;
3209 		int i, num;
3210 		p->keyboard_leds[0] = p->keyboard_leds[1] = p->keyboard_leds[2] = 0;
3211 		p->keyboard_leds_in_use = 0;
3212 		_tcscat (tmpbuf, _T(","));
3213 		for (i = 0; i < 3; i++) {
3214 			tmpp = _tcschr (tmpp2, ':');
3215 			if (!tmpp)
3216 				break;
3217 			*tmpp++= 0;
3218 			num = -1;
3219 			if (!strcasecmp (tmpp2, _T("numlock")))
3220 				num = 0;
3221 			if (!strcasecmp (tmpp2, _T("capslock")))
3222 				num = 1;
3223 			if (!strcasecmp (tmpp2, _T("scrolllock")))
3224 				num = 2;
3225 			tmpp2 = tmpp;
3226 			tmpp = _tcschr (tmpp2, ',');
3227 			if (!tmpp)
3228 				break;
3229 			*tmpp++= 0;
3230 			if (num >= 0) {
3231 				p->keyboard_leds[num] = match_string (kbleds, tmpp2);
3232 				if (p->keyboard_leds[num])
3233 					p->keyboard_leds_in_use = 1;
3234 			}
3235 			tmpp2 = tmpp;
3236 		}
3237 		return 1;
3238 	}
3239 
3240 	if (_tcscmp (option, _T("displaydata")) == 0 || _tcscmp (option, _T("displaydata_pal")) == 0 || _tcscmp (option, _T("displaydata_ntsc")) == 0) {
3241 		_tcsncpy (tmpbuf, value, sizeof tmpbuf / sizeof (TCHAR) - 1);
3242 		tmpbuf[sizeof tmpbuf / sizeof (TCHAR) - 1] = '\0';
3243 
3244 		int vert = -1, horiz = -1, lace = -1, ntsc = -1, framelength = -1, vsync = -1;
3245 		bool locked = false;
3246 		bool rtg = false;
3247 		double rate = -1;
3248 		TCHAR cmd[MAX_DPATH], label[16] = { 0 };
3249 		TCHAR *tmpp = tmpbuf;
3250 		TCHAR *end = tmpbuf + _tcslen (tmpbuf);
3251 		cmd[0] = 0;
3252 		for (;;) {
3253 			TCHAR *next = _tcschr (tmpp, ',');
3254 			TCHAR *equals = _tcschr (tmpp, '=');
3255 
3256 			if (!next)
3257 				next = end;
3258 			if (equals == NULL || equals > next)
3259 				equals = NULL;
3260 			else
3261 				equals++;
3262 			*next = 0;
3263 
3264 			if (rate < 0)
3265 				rate = _tstof (tmpp);
3266 			else if (!_tcsnicmp (tmpp, _T("v="), 2))
3267 				vert = _tstol (equals);
3268 			else if (!_tcsnicmp (tmpp, _T("h="), 2))
3269 				horiz = _tstol (equals);
3270 			else if (!_tcsnicmp (tmpp, _T("t="), 2))
3271 				_tcsncpy (label, equals, sizeof label / sizeof (TCHAR) - 1);
3272 			else if (equals) {
3273 				if (_tcslen (cmd) + _tcslen (tmpp) + 2 < sizeof (cmd) / sizeof (TCHAR)) {
3274 					_tcscat (cmd, tmpp);
3275 					_tcscat (cmd, _T("\n"));
3276 				}
3277 			}
3278 			if (!_tcsnicmp (tmpp, _T("locked"), 4))
3279 				locked = true;
3280 			if (!_tcsnicmp (tmpp, _T("nlace"), 5))
3281 				lace = 0;
3282 			if (!_tcsnicmp (tmpp, _T("lace"), 4))
3283 				lace = 1;
3284 			if (!_tcsnicmp (tmpp, _T("nvsync"), 5))
3285 				vsync = 0;
3286 			if (!_tcsnicmp (tmpp, _T("vsync"), 4))
3287 				vsync = 1;
3288 			if (!_tcsnicmp (tmpp, _T("ntsc"), 4))
3289 				ntsc = 1;
3290 			if (!_tcsnicmp (tmpp, _T("pal"), 3))
3291 				ntsc = 0;
3292 			if (!_tcsnicmp (tmpp, _T("lof"), 3))
3293 				framelength = 1;
3294 			if (!_tcsnicmp (tmpp, _T("shf"), 3))
3295 				framelength = 0;
3296 			if (!_tcsnicmp (tmpp, _T("rtg"), 3))
3297 				rtg = true;
3298 			tmpp = next;
3299 			if (tmpp >= end)
3300 				break;
3301 			tmpp++;
3302 		}
3303 		if (rate > 0) {
3304 			for (int i = 0; i < MAX_CHIPSET_REFRESH; i++) {
3305 				if (_tcscmp (option, _T("displaydata_pal")) == 0) {
3306 					i = CHIPSET_REFRESH_PAL;
3307 					p->cr[i].rate = -1;
3308 					_tcscpy (label, _T("PAL"));
3309 				} else if (_tcscmp (option, _T("displaydata_ntsc")) == 0) {
3310 					i = CHIPSET_REFRESH_NTSC;
3311 					p->cr[i].rate = -1;
3312 					_tcscpy (label, _T("NTSC"));
3313 				}
3314 				if (p->cr[i].rate <= 0) {
3315 					p->cr[i].horiz = horiz;
3316 					p->cr[i].vert = vert;
3317 					p->cr[i].lace = lace;
3318 					p->cr[i].ntsc = ntsc;
3319 					p->cr[i].vsync = vsync;
3320 					p->cr[i].locked = locked;
3321 					p->cr[i].rtg = rtg;
3322 					p->cr[i].framelength = framelength;
3323 					p->cr[i].rate = rate;
3324 					_tcscpy (p->cr[i].commands, cmd);
3325 					_tcscpy (p->cr[i].label, label);
3326 					break;
3327 				}
3328 			}
3329 		}
3330 		return 1;
3331 	}
3332 
3333 #ifdef WITH_SLIRP
3334 #ifdef FSUAE
3335 	if (cfgfile_strval(option, value, _T("slirp_implementation"), &p->slirp_implementation, slirp_implementations, 0))
3336 		return 1;
3337 #endif
3338 	if (cfgfile_string (option, value, _T("slirp_ports"), tmpbuf, sizeof (tmpbuf) / sizeof (TCHAR))) {
3339 		TCHAR *tmpp2 = tmpbuf;
3340 		_tcscat (tmpbuf, _T(","));
3341 		for (;;) {
3342 			tmpp = _tcschr (tmpp2, ',');
3343 			if (!tmpp)
3344 				break;
3345 			*tmpp++= 0;
3346 			for (i = 0; i < MAX_SLIRP_REDIRS; i++) {
3347 				struct slirp_redir *sr = &p->slirp_redirs[i];
3348 				if (sr->proto == 0) {
3349 					sr->dstport = _tstol (tmpp2);
3350 					sr->proto = 1;
3351 					break;
3352 				}
3353 			}
3354 			tmpp2 = tmpp;
3355 		}
3356 		return 1;
3357 	}
3358 	if (cfgfile_string (option, value, _T("slirp_redir"), tmpbuf, sizeof (tmpbuf) / sizeof(TCHAR))) {
3359 		TCHAR *tmpp2 = tmpbuf;
3360 		_tcscat (tmpbuf, _T(":"));
3361 		for (i = 0; i < MAX_SLIRP_REDIRS; i++) {
3362 			struct slirp_redir *sr = &p->slirp_redirs[i];
3363 			if (sr->proto == 0) {
3364 				char *s;
3365 				tmpp = _tcschr (tmpp2, ':');
3366 				if (!tmpp)
3367 					break;
3368 				*tmpp++= 0;
3369 				if (!_tcsicmp (tmpp2, _T("tcp")))
3370 					sr->proto = 1;
3371 				else if (!_tcsicmp (tmpp2, _T("udp")))
3372 					sr->proto = 2;
3373 				else
3374 					break;
3375 				tmpp2 = tmpp;
3376 				tmpp = _tcschr (tmpp2, ':');
3377 				if (!tmpp) {
3378 					sr->proto = 0;
3379 					break;
3380 				}
3381 				*tmpp++= 0;
3382 				sr->dstport = _tstol (tmpp2);
3383 				tmpp2 = tmpp;
3384 				tmpp = _tcschr (tmpp2, ':');
3385 				if (!tmpp) {
3386 					sr->proto = 0;
3387 					break;
3388 				}
3389 				*tmpp++= 0;
3390 				sr->srcport = _tstol (tmpp2);
3391 				tmpp2 = tmpp;
3392 				tmpp = _tcschr (tmpp2, ':');
3393 				if (!tmpp)
3394 					break;
3395 				*tmpp++= 0;
3396 				s = ua (tmpp2);
3397 				sr->addr = inet_addr (s);
3398 				xfree (s);
3399 			}
3400 		}
3401 		return 1;
3402 	}
3403 #endif
3404 
3405 	return 0;
3406 }
3407 
decode_rom_ident(TCHAR * romfile,int maxlen,const TCHAR * ident,int romflags)3408 static void decode_rom_ident (TCHAR *romfile, int maxlen, const TCHAR *ident, int romflags)
3409 {
3410 	const TCHAR *p;
3411 	int ver, rev, subver, subrev, round, i;
3412 	TCHAR model[64], *modelp;
3413 	struct romlist **rl;
3414 	TCHAR *romtxt;
3415 
3416 	if (!ident[0])
3417 		return;
3418 	romtxt = xmalloc (TCHAR, 10000);
3419 	romtxt[0] = 0;
3420 	for (round = 0; round < 2; round++) {
3421 		ver = rev = subver = subrev = -1;
3422 		modelp = NULL;
3423 		memset (model, 0, sizeof model);
3424 		p = ident;
3425 		while (*p) {
3426 			TCHAR c = *p++;
3427 			int *pp1 = NULL, *pp2 = NULL;
3428 			if (_totupper (c) == 'V' && _istdigit (*p)) {
3429 				pp1 = &ver;
3430 				pp2 = &rev;
3431 			} else if (_totupper (c) == 'R' && _istdigit (*p)) {
3432 				pp1 = &subver;
3433 				pp2 = &subrev;
3434 			} else if (!_istdigit (c) && c != ' ') {
3435 				_tcsncpy (model, p - 1, (sizeof model) / sizeof (TCHAR) - 1);
3436 				p += _tcslen (model);
3437 				modelp = model;
3438 			}
3439 			if (pp1) {
3440 				*pp1 = _tstol (p);
3441 				while (*p != 0 && *p != '.' && *p != ' ')
3442 					p++;
3443 				if (*p == '.') {
3444 					p++;
3445 					if (pp2)
3446 						*pp2 = _tstol (p);
3447 				}
3448 			}
3449 			if (*p == 0 || *p == ';') {
3450 				rl = getromlistbyident (ver, rev, subver, subrev, modelp, romflags, round > 0);
3451 				if (rl) {
3452 					for (i = 0; rl[i]; i++) {
3453 						if (round) {
3454 							TCHAR romname[MAX_DPATH];
3455 							getromname(rl[i]->rd, romname);
3456 							_tcscat (romtxt, romname);
3457 							_tcscat (romtxt, _T("\n"));
3458 						} else {
3459 							_tcsncpy (romfile, rl[i]->path, maxlen);
3460 							goto end;
3461 						}
3462 					}
3463 					xfree (rl);
3464 				}
3465 			}
3466 		}
3467 	}
3468 end:
3469 	if (round && romtxt[0]) {
3470 		notify_user_parms (NUMSG_ROMNEED, romtxt, romtxt);
3471 	}
3472 	xfree (romtxt);
3473 }
3474 
getuci(struct uae_prefs * p)3475 static struct uaedev_config_data *getuci (struct uae_prefs *p)
3476 {
3477 	if (p->mountitems < MOUNT_CONFIG_SIZE)
3478 		return &p->mountconfig[p->mountitems++];
3479 	return NULL;
3480 }
3481 
add_filesys_config(struct uae_prefs * p,int index,struct uaedev_config_info * ci)3482 struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info *ci)
3483 {
3484 	struct uaedev_config_data *uci;
3485 	int i;
3486 
3487 	if (index < 0 && (ci->type == UAEDEV_DIR || ci->type == UAEDEV_HDF) && ci->devname && _tcslen (ci->devname) > 0) {
3488 		for (i = 0; i < p->mountitems; i++) {
3489 			if (p->mountconfig[i].ci.devname && !_tcscmp (p->mountconfig[i].ci.devname, ci->devname))
3490 				return NULL;
3491 		}
3492 	}
3493 	for (;;) {
3494 		if (ci->type == UAEDEV_CD) {
3495 			if (ci->controller_type >= HD_CONTROLLER_TYPE_IDE_FIRST && ci->controller_type <= HD_CONTROLLER_TYPE_IDE_LAST)
3496 				break;
3497 			if (ci->controller_type >= HD_CONTROLLER_TYPE_SCSI_FIRST && ci->controller_type <= HD_CONTROLLER_TYPE_SCSI_LAST)
3498 				break;
3499 		} else if (ci->type == UAEDEV_TAPE) {
3500 			if (ci->controller_type == HD_CONTROLLER_TYPE_UAE)
3501 				break;
3502 			if (ci->controller_type >= HD_CONTROLLER_TYPE_SCSI_FIRST && ci->controller_type <= HD_CONTROLLER_TYPE_SCSI_LAST)
3503 				break;
3504 		} else {
3505 			break;
3506 		}
3507 		return NULL;
3508 	}
3509 
3510 	if (index < 0) {
3511 		if (ci->controller_type != HD_CONTROLLER_TYPE_UAE) {
3512 			int ctrl = ci->controller_type;
3513 			int ctrlunit = ci->controller_type_unit;
3514 			int cunit = ci->controller_unit;
3515 			for (;;) {
3516 				for (i = 0; i < p->mountitems; i++) {
3517 					if (p->mountconfig[i].ci.controller_type == ctrl && p->mountconfig[i].ci.controller_type_unit == ctrlunit && p->mountconfig[i].ci.controller_unit == cunit) {
3518 						cunit++;
3519 						if (ctrl >= HD_CONTROLLER_TYPE_IDE_FIRST && ctrl <= HD_CONTROLLER_TYPE_IDE_LAST && cunit == 4)
3520 							return NULL;
3521 						if (ctrl >= HD_CONTROLLER_TYPE_SCSI_FIRST && ctrl <= HD_CONTROLLER_TYPE_SCSI_LAST && cunit >= 7)
3522 							return NULL;
3523 					}
3524 				}
3525 				if (i == p->mountitems) {
3526 					ci->controller_unit = cunit;
3527 					break;
3528 				}
3529 			}
3530 		}
3531 		if (ci->type == UAEDEV_CD) {
3532 			for (i = 0; i < p->mountitems; i++) {
3533 				if (p->mountconfig[i].ci.type == ci->type)
3534 					return NULL;
3535 			}
3536 		}
3537 		uci = getuci (p);
3538 		uci->configoffset = -1;
3539 		uci->unitnum = -1;
3540 	} else {
3541 		uci = &p->mountconfig[index];
3542 	}
3543 	if (!uci)
3544 		return NULL;
3545 
3546 	memcpy (&uci->ci, ci, sizeof (struct uaedev_config_info));
3547 	validatedevicename (uci->ci.devname, NULL);
3548 	validatevolumename (uci->ci.volname, NULL);
3549 	if (!uci->ci.devname[0] && ci->type != UAEDEV_CD && ci->type != UAEDEV_TAPE) {
3550 		TCHAR base[32];
3551 		TCHAR base2[32];
3552 		int num = 0;
3553 		if (uci->ci.rootdir[0] == 0 && ci->type == UAEDEV_DIR)
3554 			_tcscpy (base, _T("RDH"));
3555 		else
3556 			_tcscpy (base, _T("DH"));
3557 		_tcscpy (base2, base);
3558 		for (i = 0; i < p->mountitems; i++) {
3559 			_stprintf (base2, _T("%s%d"), base, num);
3560 			if (!_tcsicmp(base2, p->mountconfig[i].ci.devname)) {
3561 				num++;
3562 				i = -1;
3563 				continue;
3564 			}
3565 		}
3566 		_tcscpy (uci->ci.devname, base2);
3567 		validatedevicename (uci->ci.devname, NULL);
3568 	}
3569 	if (ci->type == UAEDEV_DIR) {
3570 		TCHAR *s = filesys_createvolname (uci->ci.volname, uci->ci.rootdir, NULL, _T("Harddrive"));
3571 		_tcscpy (uci->ci.volname, s);
3572 		xfree (s);
3573 	}
3574 	return uci;
3575 }
3576 
parse_addmem(struct uae_prefs * p,TCHAR * buf,int num)3577 static void parse_addmem (struct uae_prefs *p, TCHAR *buf, int num)
3578 {
3579 	int size = 0, addr = 0;
3580 
3581 	if (!getintval2 (&buf, &addr, ',', false))
3582 		return;
3583 	if (!getintval2 (&buf, &size, 0, true))
3584 		return;
3585 	if (addr & 0xffff)
3586 		return;
3587 	if ((size & 0xffff) || (size & 0xffff0000) == 0)
3588 		return;
3589 	p->custom_memory_addrs[num] = addr;
3590 	p->custom_memory_sizes[num] = size;
3591 }
3592 
get_filesys_controller(const TCHAR * hdc,int * type,int * typenum,int * num)3593 static void get_filesys_controller (const TCHAR *hdc, int *type, int *typenum, int *num)
3594 {
3595 #ifdef FSUAE
3596 	write_log("get_filesys_controller %s\n", hdc);
3597 #endif
3598 	int hdcv = HD_CONTROLLER_TYPE_UAE;
3599 	int hdunit = 0;
3600 	int idx = 0;
3601 	if(_tcslen (hdc) >= 4 && !_tcsncmp (hdc, _T("ide"), 3)) {
3602 		hdcv = HD_CONTROLLER_TYPE_IDE_AUTO;
3603 		hdunit = hdc[3] - '0';
3604 		if (hdunit < 0 || hdunit >= 4)
3605 			hdunit = 0;
3606 	} else if(_tcslen (hdc) >= 5 && !_tcsncmp (hdc, _T("scsi"), 4)) {
3607 		hdcv = HD_CONTROLLER_TYPE_SCSI_AUTO;
3608 #ifdef FSUAE
3609 	write_log(" - HD_CONTROLLER_TYPE_SCSI_AUTO\n");
3610 #endif
3611 		hdunit = hdc[4] - '0';
3612 		if (hdunit < 0 || hdunit >= 8 + 2)
3613 			hdunit = 0;
3614 	}
3615 	if (hdcv > HD_CONTROLLER_TYPE_UAE) {
3616 		bool found = false;
3617 		const TCHAR *ext = _tcsrchr (hdc, '_');
3618 		if (ext) {
3619 			ext++;
3620 			int len = _tcslen(ext);
3621 			if (len > 2 && ext[len - 2] == '-' && ext[len - 1] >= '2' && ext[len - 1] <= '9') {
3622 				idx = ext[len - 1] - '1';
3623 				len -= 2;
3624 			}
3625 			for (int i = 0; hdcontrollers[i]; i++) {
3626 				const TCHAR *ext2 = _tcsrchr(hdcontrollers[i], '_');
3627 				if (ext2) {
3628 					ext2++;
3629 					if (_tcslen(ext2) == len && !_tcsnicmp(ext, ext2, len) && hdc[0] == hdcontrollers[i][0]) {
3630 						if (hdcv == HD_CONTROLLER_TYPE_IDE_AUTO) {
3631 							hdcv = i;
3632 						} else {
3633 							hdcv = i + HD_CONTROLLER_EXPANSION_MAX;
3634 						}
3635 #ifdef FSUAE
3636 						write_log(" - found\n");
3637 #endif
3638 						found = true;
3639 						break;
3640 					}
3641 				}
3642 			}
3643 			if (!found) {
3644 				for (int i = 0; expansionroms[i].name; i++) {
3645 					const struct expansionromtype *ert = &expansionroms[i];
3646 					if (_tcslen(ert->name) == len && !_tcsnicmp(ext, ert->name, len)) {
3647 						if (hdcv == HD_CONTROLLER_TYPE_IDE_AUTO) {
3648 							hdcv = HD_CONTROLLER_TYPE_IDE_EXPANSION_FIRST + i;
3649 						} else {
3650 							hdcv = HD_CONTROLLER_TYPE_SCSI_EXPANSION_FIRST + i;
3651 						}
3652 #ifdef FSUAE
3653 						write_log(" - ert->name=%s ext=%s len=%d\n", ert->name, ext, len);
3654 #endif
3655 						break;
3656 					}
3657 				}
3658 
3659 			}
3660 		}
3661 	} else if (_tcslen (hdc) >= 6 && !_tcsncmp (hdc, _T("scsram"), 6)) {
3662 		hdcv = HD_CONTROLLER_TYPE_PCMCIA_SRAM;
3663 		hdunit = 0;
3664 	} else if (_tcslen (hdc) >= 5 && !_tcsncmp (hdc, _T("scide"), 6)) {
3665 		hdcv = HD_CONTROLLER_TYPE_PCMCIA_IDE;
3666 		hdunit = 0;
3667 	}
3668 	if (idx >= MAX_DUPLICATE_EXPANSION_BOARDS)
3669 		idx = MAX_DUPLICATE_EXPANSION_BOARDS - 1;
3670 	*type = hdcv;
3671 	*typenum = idx;
3672 	*num = hdunit;
3673 }
3674 
parse_geo(const TCHAR * tname,struct uaedev_config_info * uci,struct hardfiledata * hfd,bool empty)3675 static bool parse_geo (const TCHAR *tname, struct uaedev_config_info *uci, struct hardfiledata *hfd, bool empty)
3676 {
3677 	struct zfile *f;
3678 	int found;
3679 	TCHAR buf[200];
3680 
3681 	f = zfile_fopen (tname, _T("r"));
3682 	if (!f)
3683 		return false;
3684 	found = hfd == NULL && !empty ? 2 : 0;
3685 	if (found)
3686 		write_log (_T("Geometry file '%s' detected\n"), tname);
3687 	while (zfile_fgets (buf, sizeof buf / sizeof (TCHAR), f)) {
3688 		int v;
3689 		TCHAR *sep;
3690 
3691 		my_trim (buf);
3692 		if (_tcslen (buf) == 0)
3693 			continue;
3694 		if (buf[0] == '[' && buf[_tcslen (buf) - 1] == ']') {
3695 			if (found > 1) {
3696 				zfile_fclose (f);
3697 				return true;
3698 			}
3699 			found = 0;
3700 			buf[_tcslen (buf) - 1] = 0;
3701 			my_trim (buf + 1);
3702 			if (!_tcsicmp (buf + 1, _T("empty"))) {
3703 				if (empty)
3704 					found = 1;
3705 			} else if (!_tcsicmp (buf + 1, _T("default"))) {
3706 				if (!empty)
3707 					found = 1;
3708 			} else if (hfd) {
3709 				uae_u64 size = _tstoi64 (buf + 1);
3710 				if (size == hfd->virtsize)
3711 					found = 2;
3712 			}
3713 			if (found)
3714 				write_log (_T("Geometry file '%s', entry '%s' detected\n"), tname, buf + 1);
3715 			continue;
3716 		}
3717 		if (!found)
3718 			continue;
3719 
3720 		sep =  _tcschr (buf, '=');
3721 		if (!sep)
3722 			continue;
3723 		sep[0] = 0;
3724 
3725 		TCHAR *key = my_strdup_trim (buf);
3726 		TCHAR *val = my_strdup_trim (sep + 1);
3727 		if (val[0] == '0' && _totupper (val[1]) == 'X') {
3728 			TCHAR *endptr;
3729 			v = _tcstol (val, &endptr, 16);
3730 		} else {
3731 			v = _tstol (val);
3732 		}
3733 		if (!_tcsicmp (key, _T("surfaces")))
3734 			uci->surfaces = v;
3735 		if (!_tcsicmp (key, _T("sectorspertrack")) || !_tcsicmp (key, _T("blockspertrack")))
3736 			uci->sectors = v;
3737 		if (!_tcsicmp (key, _T("sectorsperblock")))
3738 			uci->sectorsperblock = v;
3739 		if (!_tcsicmp (key, _T("reserved")))
3740 			uci->reserved = v;
3741 		if (!_tcsicmp (key, _T("lowcyl")))
3742 			uci->lowcyl = v;
3743 		if (!_tcsicmp (key, _T("highcyl")) || !_tcsicmp (key, _T("cyl")))
3744 			uci->highcyl = v;
3745 		if (!_tcsicmp (key, _T("blocksize")) || !_tcsicmp (key, _T("sectorsize")))
3746 			uci->blocksize = v;
3747 		if (!_tcsicmp (key, _T("buffers")))
3748 			uci->buffers = v;
3749 		if (!_tcsicmp (key, _T("maxtransfer")))
3750 			uci->maxtransfer = v;
3751 		if (!_tcsicmp (key, _T("interleave")))
3752 			uci->interleave = v;
3753 		if (!_tcsicmp (key, _T("dostype")))
3754 			uci->dostype = v;
3755 		if (!_tcsicmp (key, _T("bufmemtype")))
3756 			uci->bufmemtype = v;
3757 		if (!_tcsicmp (key, _T("stacksize")))
3758 			uci->stacksize = v;
3759 		if (!_tcsicmp (key, _T("mask")))
3760 			uci->mask = v;
3761 		if (!_tcsicmp (key, _T("unit")))
3762 			uci->unit = v;
3763 		if (!_tcsicmp (key, _T("controller")))
3764 			get_filesys_controller (val, &uci->controller_type, &uci->controller_type_unit, &uci->controller_unit);
3765 		if (!_tcsicmp (key, _T("flags")))
3766 			uci->flags = v;
3767 		if (!_tcsicmp (key, _T("priority")))
3768 			uci->priority = v;
3769 		if (!_tcsicmp (key, _T("forceload")))
3770 			uci->forceload = v;
3771 		if (!_tcsicmp (key, _T("bootpri"))) {
3772 			if (v < -129)
3773 				v = -129;
3774 			if (v > 127)
3775 				v = 127;
3776 			uci->bootpri = v;
3777 		}
3778 		if (!_tcsicmp (key, _T("filesystem")))
3779 			_tcscpy (uci->filesys, val);
3780 		if (!_tcsicmp (key, _T("device")))
3781 			_tcscpy (uci->devname, val);
3782 		xfree (val);
3783 		xfree (key);
3784 	}
3785 	zfile_fclose (f);
3786 	return false;
3787 }
get_hd_geometry(struct uaedev_config_info * uci)3788 bool get_hd_geometry (struct uaedev_config_info *uci)
3789 {
3790 	TCHAR tname[MAX_DPATH];
3791 
3792 	fetch_configurationpath (tname, sizeof tname / sizeof (TCHAR));
3793 	_tcscat (tname, _T("default.geo"));
3794 	if (zfile_exists (tname)) {
3795 		struct hardfiledata hfd;
3796 		memset (&hfd, 0, sizeof hfd);
3797 		hfd.ci.readonly = true;
3798 		hfd.ci.blocksize = 512;
3799 		if (hdf_open (&hfd, uci->rootdir) > 0) {
3800 			parse_geo (tname, uci, &hfd, false);
3801 			hdf_close (&hfd);
3802 		} else {
3803 			parse_geo (tname, uci, NULL, true);
3804 		}
3805 	}
3806 	if (uci->rootdir[0]) {
3807 		_tcscpy (tname, uci->rootdir);
3808 		_tcscat (tname, _T(".geo"));
3809 		return parse_geo (tname, uci, NULL, false);
3810 	}
3811 	return false;
3812 }
3813 
cfgfile_parse_partial_newfilesys(struct uae_prefs * p,int nr,int type,const TCHAR * value,int unit,bool uaehfentry)3814 static int cfgfile_parse_partial_newfilesys (struct uae_prefs *p, int nr, int type, const TCHAR *value, int unit, bool uaehfentry)
3815 {
3816 	TCHAR *tmpp;
3817 	TCHAR *name = NULL, *path = NULL;
3818 
3819 	// read only harddrive name
3820 	if (!uaehfentry)
3821 		return 0;
3822 	if (type != 1)
3823 		return 0;
3824 	tmpp = getnextentry (&value, ',');
3825 	if (!tmpp)
3826 		return 0;
3827 	xfree (tmpp);
3828 	tmpp = getnextentry (&value, ':');
3829 	if (!tmpp)
3830 		return 0;
3831 	xfree (tmpp);
3832 	name = getnextentry (&value, ':');
3833 	if (name && _tcslen (name) > 0) {
3834 		path = getnextentry (&value, ',');
3835 		if (path && _tcslen (path) > 0) {
3836 			for (int i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
3837 				struct uaedev_config_info *uci = &p->mountconfig[i].ci;
3838 				if (_tcsicmp (uci->rootdir, name) == 0) {
3839 					_tcscat (uci->rootdir, _T(":"));
3840 					_tcscat (uci->rootdir, path);
3841 				}
3842 			}
3843 		}
3844 	}
3845 	xfree (path);
3846 	xfree (name);
3847 	return 1;
3848 }
3849 
cfgfile_parse_newfilesys(struct uae_prefs * p,int nr,int type,TCHAR * value,int unit,bool uaehfentry)3850 static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHAR *value, int unit, bool uaehfentry)
3851 {
3852 	struct uaedev_config_info uci;
3853 	TCHAR *tmpp = _tcschr (value, ','), *tmpp2;
3854 	TCHAR *str = NULL;
3855 	TCHAR devname[MAX_DPATH], volname[MAX_DPATH];
3856 
3857 	devname[0] = volname[0] = 0;
3858 	uci_set_defaults (&uci, false);
3859 
3860 	config_newfilesystem = 1;
3861 	if (tmpp == 0)
3862 		goto invalid_fs;
3863 
3864 	*tmpp++ = '\0';
3865 	if (strcasecmp (value, _T("ro")) == 0)
3866 		uci.readonly = true;
3867 	else if (strcasecmp (value, _T("rw")) == 0)
3868 		uci.readonly = false;
3869 	else
3870 		goto invalid_fs;
3871 
3872 	value = tmpp;
3873 	if (type == 0) {
3874 		uci.type = UAEDEV_DIR;
3875 		tmpp = _tcschr (value, ':');
3876 		if (tmpp == 0)
3877 			goto empty_fs;
3878 		*tmpp++ = 0;
3879 		_tcscpy (devname, value);
3880 		tmpp2 = tmpp;
3881 		tmpp = _tcschr (tmpp, ':');
3882 		if (tmpp == 0)
3883 			goto empty_fs;
3884 		*tmpp++ = 0;
3885 		_tcscpy (volname, tmpp2);
3886 		tmpp2 = tmpp;
3887 		tmpp = _tcschr (tmpp, ',');
3888 		if (tmpp == 0)
3889 			goto empty_fs;
3890 		*tmpp++ = 0;
3891 		_tcscpy (uci.rootdir, tmpp2);
3892 		_tcscpy (uci.volname, volname);
3893 		_tcscpy (uci.devname, devname);
3894 		if (! getintval (&tmpp, &uci.bootpri, 0))
3895 			goto empty_fs;
3896 	} else if (type == 1 || ((type == 2 || type == 3) && uaehfentry)) {
3897 		tmpp = _tcschr (value, ':');
3898 		if (tmpp == 0)
3899 			goto invalid_fs;
3900 		*tmpp++ = '\0';
3901 		_tcscpy (devname, value);
3902 		tmpp2 = tmpp;
3903 		tmpp = _tcschr (tmpp, ',');
3904 		if (tmpp == 0)
3905 			goto invalid_fs;
3906 		*tmpp++ = 0;
3907 		_tcscpy (uci.rootdir, tmpp2);
3908 		if (uci.rootdir[0] != ':')
3909 			get_hd_geometry (&uci);
3910 		_tcscpy (uci.devname, devname);
3911 		if (! getintval (&tmpp, &uci.sectors, ',')
3912 			|| ! getintval (&tmpp, &uci.surfaces, ',')
3913 			|| ! getintval (&tmpp, &uci.reserved, ',')
3914 			|| ! getintval (&tmpp, &uci.blocksize, ','))
3915 			goto invalid_fs;
3916 		if (getintval2 (&tmpp, &uci.bootpri, ',', false)) {
3917 			tmpp2 = tmpp;
3918 			tmpp = _tcschr (tmpp, ',');
3919 			if (tmpp != 0) {
3920 				*tmpp++ = 0;
3921 				_tcscpy (uci.filesys, tmpp2);
3922 				TCHAR *tmpp2 = _tcschr (tmpp, ',');
3923 				if (tmpp2)
3924 					*tmpp2++ = 0;
3925 				get_filesys_controller (tmpp, &uci.controller_type, &uci.controller_type_unit, &uci.controller_unit);
3926 				if (tmpp2) {
3927 					if (getintval2 (&tmpp2, &uci.highcyl, ',', false)) {
3928 						getintval (&tmpp2, &uci.pcyls, '/');
3929 						getintval (&tmpp2, &uci.pheads, '/');
3930 						getintval2 (&tmpp2, &uci.psecs, '/', true);
3931 						if (uci.pheads && uci.psecs) {
3932 							uci.physical_geometry = true;
3933 						} else {
3934 							uci.pheads = uci.psecs = uci.pcyls = 0;
3935 							uci.physical_geometry = false;
3936 						}
3937 					}
3938 				}
3939 				uci.controller_media_type = 0;
3940 				uci.unit_feature_level = 1;
3941 
3942 				if (cfgfile_option_find(tmpp2, _T("CF")))
3943 					uci.controller_media_type = 1;
3944 				else if (cfgfile_option_find(tmpp2, _T("HD")))
3945 					uci.controller_media_type = 0;
3946 
3947 				TCHAR *pflags;
3948 				if ((pflags = cfgfile_option_get(tmpp2, _T("flags")))) {
3949 					getintval(&pflags, &uci.unit_special_flags, 0);
3950 				}
3951 
3952 				if (cfgfile_option_find(tmpp2, _T("SCSI2")))
3953 					uci.unit_feature_level = HD_LEVEL_SCSI_2;
3954 				else if (cfgfile_option_find(tmpp2, _T("SCSI1")))
3955 					uci.unit_feature_level = HD_LEVEL_SCSI_1;
3956 				else if (cfgfile_option_find(tmpp2, _T("SASIE")))
3957 					uci.unit_feature_level = HD_LEVEL_SASI_ENHANCED;
3958 				else if (cfgfile_option_find(tmpp2, _T("SASI")))
3959 					uci.unit_feature_level = HD_LEVEL_SASI;
3960 				else if (cfgfile_option_find(tmpp2, _T("SASI_CHS")))
3961 					uci.unit_feature_level = HD_LEVEL_SASI_CHS;
3962 				else if (cfgfile_option_find(tmpp2, _T("ATA2+S")))
3963 					uci.unit_feature_level = HD_LEVEL_ATA_2S;
3964 				else if (cfgfile_option_find(tmpp2, _T("ATA2+")))
3965 					uci.unit_feature_level = HD_LEVEL_ATA_2;
3966 				else if (cfgfile_option_find(tmpp2, _T("ATA1")))
3967 					uci.unit_feature_level = HD_LEVEL_ATA_1;
3968 			}
3969 		}
3970 		if (type == 2) {
3971 			uci.device_emu_unit = unit;
3972 			uci.blocksize = 2048;
3973 			uci.readonly = true;
3974 			uci.type = UAEDEV_CD;
3975 		} else if (type == 3) {
3976 			uci.device_emu_unit = unit;
3977 			uci.blocksize = 512;
3978 			uci.type = UAEDEV_TAPE;
3979 		} else {
3980 			uci.type = UAEDEV_HDF;
3981 		}
3982 	} else {
3983 		goto invalid_fs;
3984 	}
3985 empty_fs:
3986 	if (uci.rootdir[0]) {
3987 		if (_tcslen (uci.rootdir) > 3 && uci.rootdir[0] == 'H' && uci.rootdir[1] == 'D' && uci.rootdir[2] == '_') {
3988 			memmove (uci.rootdir, uci.rootdir + 2, (_tcslen (uci.rootdir + 2) + 1) * sizeof (TCHAR));
3989 			uci.rootdir[0] = ':';
3990 		}
3991 		str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, false);
3992 		_tcscpy (uci.rootdir, str);
3993 	}
3994 #ifdef FILESYS
3995 	add_filesys_config (p, nr, &uci);
3996 #endif
3997 	xfree (str);
3998 	return 1;
3999 
4000 invalid_fs:
4001 	cfgfile_warning(_T("Invalid filesystem/hardfile/cd specification.\n"));
4002 	return 1;
4003 }
4004 
cfgfile_parse_filesys(struct uae_prefs * p,const TCHAR * option,TCHAR * value)4005 static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHAR *value)
4006 {
4007 	int i;
4008 
4009 	for (i = 0; i < MAX_FILESYSTEM_UNITS; i++) {
4010 		TCHAR tmp[100];
4011 		_stprintf (tmp, _T("uaehf%d"), i);
4012 		if (_tcscmp (option, tmp) == 0) {
4013 			for (;;) {
4014 				int  type = -1;
4015 				int unit = -1;
4016 				TCHAR *tmpp = _tcschr (value, ',');
4017 				if (tmpp == NULL)
4018 					return 1;
4019 				*tmpp++ = 0;
4020 				if (_tcsicmp (value, _T("hdf")) == 0) {
4021 					type = 1;
4022 					cfgfile_parse_partial_newfilesys (p, -1, type, tmpp, unit, true);
4023 					return 1;
4024 				} else if (_tcsnicmp (value, _T("cd"), 2) == 0 && (value[2] == 0 || value[3] == 0)) {
4025 					unit = 0;
4026 					if (value[2] > 0)
4027 						unit = value[2] - '0';
4028 					if (unit >= 0 && unit <= MAX_TOTAL_SCSI_DEVICES) {
4029 						type = 2;
4030 					}
4031 				} else if (_tcsnicmp (value, _T("tape"), 4) == 0 && (value[4] == 0 || value[5] == 0)) {
4032 					unit = 0;
4033 					if (value[4] > 0)
4034 						unit = value[4] - '0';
4035 					if (unit >= 0 && unit <= MAX_TOTAL_SCSI_DEVICES) {
4036 						type = 3;
4037 					}
4038 				} else if (_tcsicmp (value, _T("dir")) != 0) {
4039 					type = 0;
4040 					return 1;  /* ignore for now */
4041 				}
4042 				if (type >= 0)
4043 					cfgfile_parse_newfilesys (p, -1, type, tmpp, unit, true);
4044 				return 1;
4045 			}
4046 			return 1;
4047 		} else if (!_tcsncmp (option, tmp, _tcslen (tmp)) && option[_tcslen (tmp)] == '_') {
4048 			struct uaedev_config_info *uci = &currprefs.mountconfig[i].ci;
4049 			if (uci->devname) {
4050 				const TCHAR *s = &option[_tcslen (tmp) + 1];
4051 				if (!_tcscmp (s, _T("bootpri"))) {
4052 					getintval (&value, &uci->bootpri, 0);
4053 				} else if (!_tcscmp (s, _T("read-only"))) {
4054 					cfgfile_yesno (NULL, value, NULL, &uci->readonly);
4055 				} else if (!_tcscmp (s, _T("volumename"))) {
4056 					_tcscpy (uci->volname, value);
4057 				} else if (!_tcscmp (s, _T("devicename"))) {
4058 					_tcscpy (uci->devname, value);
4059 				} else if (!_tcscmp (s, _T("root"))) {
4060 					_tcscpy (uci->rootdir, value);
4061 				} else if (!_tcscmp (s, _T("filesys"))) {
4062 					_tcscpy (uci->filesys, value);
4063 				} else if (!_tcscmp (s, _T("controller"))) {
4064 					get_filesys_controller (value, &uci->controller_type, &uci->controller_type_unit, &uci->controller_unit);
4065 				}
4066 			}
4067 		}
4068 	}
4069 
4070 	if (_tcscmp (option, _T("filesystem")) == 0
4071 		|| _tcscmp (option, _T("hardfile")) == 0)
4072 	{
4073 		struct uaedev_config_info uci;
4074 		TCHAR *tmpp = _tcschr (value, ',');
4075 		TCHAR *str;
4076 		bool hdf;
4077 
4078 		uci_set_defaults (&uci, false);
4079 
4080 		if (config_newfilesystem)
4081 			return 1;
4082 
4083 		if (tmpp == 0)
4084 			goto invalid_fs;
4085 
4086 		*tmpp++ = '\0';
4087 		if (_tcscmp (value, _T("1")) == 0 || strcasecmp (value, _T("ro")) == 0
4088 			|| strcasecmp (value, _T("readonly")) == 0
4089 			|| strcasecmp (value, _T("read-only")) == 0)
4090 			uci.readonly = true;
4091 		else if (_tcscmp (value, _T("0")) == 0 || strcasecmp (value, _T("rw")) == 0
4092 			|| strcasecmp (value, _T("readwrite")) == 0
4093 			|| strcasecmp (value, _T("read-write")) == 0)
4094 			uci.readonly = false;
4095 		else
4096 			goto invalid_fs;
4097 
4098 		value = tmpp;
4099 		if (_tcscmp (option, _T("filesystem")) == 0) {
4100 			hdf = false;
4101 			tmpp = _tcschr (value, ':');
4102 			if (tmpp == 0)
4103 				goto invalid_fs;
4104 			*tmpp++ = '\0';
4105 			_tcscpy (uci.volname, value);
4106 			_tcscpy (uci.rootdir, tmpp);
4107 		} else {
4108 			hdf = true;
4109 			if (! getintval (&value, &uci.sectors, ',')
4110 				|| ! getintval (&value, &uci.surfaces, ',')
4111 				|| ! getintval (&value, &uci.reserved, ',')
4112 				|| ! getintval (&value, &uci.blocksize, ','))
4113 				goto invalid_fs;
4114 			_tcscpy (uci.rootdir, value);
4115 		}
4116 		str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, true);
4117 #ifdef FILESYS
4118 		uci.type = hdf ? UAEDEV_HDF : UAEDEV_DIR;
4119 		add_filesys_config (p, -1, &uci);
4120 #endif
4121 		xfree (str);
4122 		return 1;
4123 invalid_fs:
4124 		cfgfile_warning(_T("Invalid filesystem/hardfile specification.\n"));
4125 		return 1;
4126 
4127 	}
4128 
4129 	if (_tcscmp (option, _T("filesystem2")) == 0)
4130 		return cfgfile_parse_newfilesys (p, -1, 0, value, -1, false);
4131 	if (_tcscmp (option, _T("hardfile2")) == 0)
4132 		return cfgfile_parse_newfilesys (p, -1, 1, value, -1, false);
4133 	if (_tcscmp (option, _T("filesystem_extra")) == 0) {
4134 		int idx = 0;
4135 		TCHAR *s = value;
4136 		_tcscat(s, _T(","));
4137 		struct uaedev_config_info *ci = NULL;
4138 		for (;;) {
4139 			TCHAR *tmpp = _tcschr (s, ',');
4140 			if (tmpp == NULL)
4141 				return 1;
4142 			*tmpp++ = 0;
4143 			if (idx == 0) {
4144 				for (i = 0; i < p->mountitems; i++) {
4145 					if (p->mountconfig[i].ci.devname && !_tcscmp (p->mountconfig[i].ci.devname, s)) {
4146 						ci = &p->mountconfig[i].ci;
4147 						break;
4148 					}
4149 				}
4150 				if (!ci || ci->type != UAEDEV_DIR)
4151 					return 1;
4152 			} else {
4153 				bool b = true;
4154 				TCHAR *tmpp2 = _tcschr(s, '=');
4155 				if (tmpp2) {
4156 					*tmpp2++ = 0;
4157 					if (!strcasecmp(tmpp2, _T("false")))
4158 						b = false;
4159 				}
4160 				if (!strcasecmp(s, _T("inject_icons"))) {
4161 					ci->inject_icons = b;
4162 				}
4163 			}
4164 			idx++;
4165 			s = tmpp;
4166 		}
4167 	}
4168 
4169 	return 0;
4170 }
4171 
cfgfile_board_enabled(struct uae_prefs * p,int romtype,int devnum)4172 bool cfgfile_board_enabled(struct uae_prefs *p, int romtype, int devnum)
4173 {
4174 	int idx;
4175 	if (romtype == ROMTYPE_CPUBOARD && currprefs.cpuboard_type)
4176 		return true;
4177 	struct boardromconfig *brc = get_device_rom(p, romtype, devnum, &idx);
4178 	if (!brc)
4179 		return false;
4180 	return brc->roms[idx].romfile[0] != 0;
4181 }
4182 
cfgfile_read_board_rom(struct uae_prefs * p,const TCHAR * option,const TCHAR * value,struct multipath * mp)4183 static bool cfgfile_read_board_rom(struct uae_prefs *p, const TCHAR *option, const TCHAR *value, struct multipath *mp)
4184 {
4185 	TCHAR buf[256], buf2[MAX_DPATH], buf3[MAX_DPATH];
4186 	bool dummy;
4187 	int val;
4188 	const struct expansionromtype *ert;
4189 
4190 	for (int i = 0; expansionroms[i].name; i++) {
4191 		struct boardromconfig *brc;
4192 		int idx;
4193 		ert = &expansionroms[i];
4194 
4195 		for (int j = 0; j < MAX_DUPLICATE_EXPANSION_BOARDS; j++) {
4196 			TCHAR name[256];
4197 
4198 			if (j == 0)
4199 				_tcscpy(name, ert->name);
4200 			else
4201 				_stprintf(name, _T("%s-%d"), ert->name, j + 1);
4202 
4203 			_stprintf(buf, _T("scsi_%s"), name);
4204 			if (cfgfile_yesno(option, value, buf, &dummy)) {
4205 				return true;
4206 			}
4207 
4208 			_stprintf(buf, _T("%s_rom_file"), name);
4209 			if (cfgfile_path(option, value, buf, buf2, MAX_DPATH / sizeof (TCHAR), mp)) {
4210 				if (buf2[0]) {
4211 					brc = get_device_rom_new(p, ert->romtype, j, &idx);
4212 					_tcscpy(brc->roms[idx].romfile, buf2);
4213 				}
4214 				return true;
4215 			}
4216 
4217 			_stprintf(buf, _T("%s_rom_file_id"), name);
4218 			buf2[0] = 0;
4219 			if (cfgfile_rom (option, value, buf, buf2, MAX_DPATH / sizeof (TCHAR))) {
4220 				if (buf2[0]) {
4221 					brc = get_device_rom_new(p, ert->romtype, j, &idx);
4222 					_tcscpy(brc->roms[idx].romfile, buf2);
4223 				}
4224 				return true;
4225 			}
4226 
4227 			_stprintf(buf, _T("%s_rom"), name);
4228 			if (cfgfile_string (option, value, buf, buf2, sizeof buf2 / sizeof (TCHAR))) {
4229 				if (buf2[0]) {
4230 					decode_rom_ident (buf3, sizeof(buf3) / sizeof (TCHAR), buf2, ert->romtype);
4231 					if (buf3[0]) {
4232 						brc = get_device_rom_new(p, ert->romtype, j, &idx);
4233 						_tcscpy(brc->roms[idx].romident, buf3);
4234 					}
4235 				}
4236 				return true;
4237 			}
4238 
4239 			_stprintf(buf, _T("%s_rom_options"), name);
4240 			if (cfgfile_string (option, value, buf, buf2, sizeof buf2 / sizeof (TCHAR))) {
4241 				brc = get_device_rom(p, ert->romtype, j, &idx);
4242 				if (brc) {
4243 					if (cfgfile_option_bool(buf2, _T("autoboot_disabled")) == 1) {
4244 						brc->roms[idx].autoboot_disabled = true;
4245 					}
4246 					if (ert->settings) {
4247 						brc->roms[idx].device_settings = cfgfile_read_rom_settings(ert->settings, buf2);
4248 					}
4249 					if (ert->id_jumper) {
4250 						TCHAR *p = cfgfile_option_get(buf2, _T("id"));
4251 						if (p) {
4252 							brc->roms[idx].device_id = _tstol(p);
4253 						}
4254 					}
4255 					if (ert->subtypes) {
4256 						const struct expansionsubromtype *srt = ert->subtypes;
4257 						TCHAR tmp[MAX_DPATH], *p;
4258 						p = tmp;
4259 						*p = 0;
4260 						while (srt->name) {
4261 							_tcscpy(p, srt->configname);
4262 							p += _tcslen(p) + 1;
4263 							p[0] = 0;
4264 							srt++;
4265 						}
4266 						int v = cfgfile_option_select(buf2, _T("subtype"), tmp);
4267 						if (v >= 0)
4268 							brc->roms[idx].subtype = v;
4269 					}
4270 				}
4271 				return true;
4272 			}
4273 		}
4274 
4275 		_stprintf(buf, _T("%s_mem_size"), ert->name);
4276 		if (cfgfile_intval (option, value, buf, &val, 0x40000)) {
4277 			if (val) {
4278 				brc = get_device_rom_new(p, ert->romtype, 0, &idx);
4279 				brc->roms[idx].board_ram_size = val;
4280 			}
4281 			return true;
4282 		}
4283 	}
4284 	return false;
4285 }
4286 
cfgfile_parse_hardware(struct uae_prefs * p,const TCHAR * option,TCHAR * value)4287 static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCHAR *value)
4288 {
4289 	int tmpval, dummyint, i;
4290 	bool dummybool;
4291 	TCHAR tmpbuf[CONFIG_BLEN];
4292 
4293 	if (cfgfile_yesno (option, value, _T("cpu_cycle_exact"), &p->cpu_cycle_exact)) {
4294 		/* we don't want cycle-exact in 68020/40+JIT modes */
4295 		if (p->cpu_model >= 68020 && p->cachesize > 0)
4296 			p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 0;
4297 		p->cpu_memory_cycle_exact = p->cpu_cycle_exact;
4298 		return 1;
4299 	}
4300 	if (cfgfile_yesno (option, value, _T("blitter_cycle_exact"), &p->blitter_cycle_exact)) {
4301 		if (p->cpu_model >= 68020 && p->cachesize > 0)
4302 			p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 0;
4303 		return 1;
4304 	}
4305 	if (cfgfile_yesno (option, value, _T("cpu_memory_cycle_exact"), &p->cpu_memory_cycle_exact)) {
4306 		if (!p->cpu_memory_cycle_exact)
4307 			p->blitter_cycle_exact = p->cpu_cycle_exact = false;
4308 		return 1;
4309 	}
4310 	if (cfgfile_strval (option, value, _T("cycle_exact"), &tmpval, cycleexact, 0)) {
4311 		if (tmpval > 0) {
4312 			p->blitter_cycle_exact = true;
4313 			p->cpu_cycle_exact = tmpval > 1;
4314 			p->cpu_memory_cycle_exact = true;
4315 		} else {
4316 			p->blitter_cycle_exact = false;
4317 			p->cpu_cycle_exact = false;
4318 			p->cpu_memory_cycle_exact = false;
4319 		}
4320 		if (p->cpu_model >= 68020 && p->cachesize > 0)
4321 			p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = false;
4322 		// if old version and CE and fastest possible: set to approximate
4323 		if (p->cpu_cycle_exact && p->config_version < ((2 << 16) | (8 << 8) | (2 << 0)) && p->m68k_speed < 0)
4324 			p->m68k_speed = 0;
4325 		return 1;
4326 	}
4327 
4328 	if (cfgfile_string (option, value, _T("cpu_multiplier"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4329 		p->cpu_clock_multiplier = (int)(_tstof (tmpbuf) * 256.0);
4330 		return 1;
4331 	}
4332 
4333 
4334 	if (cfgfile_yesno (option, value, _T("scsi_a3000"), &dummybool)) {
4335 		if (dummybool)
4336 			p->cs_mbdmac = 1;
4337 		return 1;
4338 	}
4339 	if (cfgfile_yesno (option, value, _T("scsi_a4000t"), &dummybool)) {
4340 		if (dummybool)
4341 			p->cs_mbdmac = 2;
4342 		return 1;
4343 	}
4344 
4345 	if (cfgfile_string(option, value, _T("a2065"), p->a2065name, sizeof p->a2065name / sizeof(TCHAR)))
4346 		return 1;
4347 	if (cfgfile_string(option, value, _T("ne2000_pci"), p->ne2000pciname, sizeof p->ne2000pciname / sizeof(TCHAR)))
4348 		return 1;
4349 
4350 	if (cfgfile_yesno (option, value, _T("immediate_blits"), &p->immediate_blits)
4351 		|| cfgfile_yesno (option, value, _T("fpu_no_unimplemented"), &p->fpu_no_unimplemented)
4352 		|| cfgfile_yesno (option, value, _T("cpu_no_unimplemented"), &p->int_no_unimplemented)
4353 		|| cfgfile_yesno (option, value, _T("cd32cd"), &p->cs_cd32cd)
4354 		|| cfgfile_yesno (option, value, _T("cd32c2p"), &p->cs_cd32c2p)
4355 		|| cfgfile_yesno(option, value, _T("cd32nvram"), &p->cs_cd32nvram)
4356 		|| cfgfile_yesno(option, value, _T("cd32fmv"), &p->cs_cd32fmv)
4357 		|| cfgfile_yesno(option, value, _T("cdtvcd"), &p->cs_cdtvcd)
4358 		|| cfgfile_yesno(option, value, _T("cdtv-cr"), &p->cs_cdtvcr)
4359 		|| cfgfile_yesno (option, value, _T("cdtvram"), &p->cs_cdtvram)
4360 		|| cfgfile_yesno (option, value, _T("a1000ram"), &p->cs_a1000ram)
4361 		|| cfgfile_yesno (option, value, _T("pcmcia"), &p->cs_pcmcia)
4362 		|| cfgfile_yesno (option, value, _T("scsi_cdtv"), &p->cs_cdtvscsi)
4363 		|| cfgfile_yesno (option, value, _T("cia_overlay"), &p->cs_ciaoverlay)
4364 		|| cfgfile_yesno (option, value, _T("bogomem_fast"), &p->cs_slowmemisfast)
4365 		|| cfgfile_yesno (option, value, _T("ksmirror_e0"), &p->cs_ksmirror_e0)
4366 		|| cfgfile_yesno (option, value, _T("ksmirror_a8"), &p->cs_ksmirror_a8)
4367 		|| cfgfile_yesno (option, value, _T("resetwarning"), &p->cs_resetwarning)
4368 		|| cfgfile_yesno (option, value, _T("cia_todbug"), &p->cs_ciatodbug)
4369 		|| cfgfile_yesno (option, value, _T("denise_noehb"), &p->cs_denisenoehb)
4370 		|| cfgfile_yesno (option, value, _T("ics_agnus"), &p->cs_dipagnus)
4371 		|| cfgfile_yesno (option, value, _T("z3_autoconfig"), &p->cs_z3autoconfig)
4372 		|| cfgfile_yesno (option, value, _T("1mchipjumper"), &p->cs_1mchipjumper)
4373 		|| cfgfile_yesno (option, value, _T("agnus_bltbusybug"), &p->cs_agnusbltbusybug)
4374 		|| cfgfile_yesno (option, value, _T("fastmem_autoconfig"), &p->fastmem_autoconfig)
4375 		|| cfgfile_yesno (option, value, _T("gfxcard_hardware_vblank"), &p->rtg_hardwareinterrupt)
4376 		|| cfgfile_yesno (option, value, _T("gfxcard_hardware_sprite"), &p->rtg_hardwaresprite)
4377 		|| cfgfile_yesno (option, value, _T("synchronize_clock"), &p->tod_hack)
4378 
4379 		|| cfgfile_yesno (option, value, _T("kickshifter"), &p->kickshifter)
4380 		|| cfgfile_yesno (option, value, _T("ks_write_enabled"), &p->rom_readwrite)
4381 		|| cfgfile_yesno (option, value, _T("ntsc"), &p->ntscmode)
4382 		|| cfgfile_yesno (option, value, _T("sana2"), &p->sana2)
4383 		|| cfgfile_yesno (option, value, _T("genlock"), &p->genlock)
4384 		|| cfgfile_yesno(option, value, _T("cpu_compatible"), &p->cpu_compatible)
4385 		|| cfgfile_yesno(option, value, _T("cpu_threaded"), &p->cpu_thread)
4386 		|| cfgfile_yesno(option, value, _T("cpu_24bit_addressing"), &p->address_space_24)
4387 		|| cfgfile_yesno(option, value, _T("cpu_reset_pause"), &p->reset_delay)
4388 		|| cfgfile_yesno(option, value, _T("parallel_on_demand"), &p->parallel_demand)
4389 		|| cfgfile_yesno (option, value, _T("parallel_postscript_emulation"), &p->parallel_postscript_emulation)
4390 		|| cfgfile_yesno (option, value, _T("parallel_postscript_detection"), &p->parallel_postscript_detection)
4391 		|| cfgfile_yesno (option, value, _T("serial_on_demand"), &p->serial_demand)
4392 		|| cfgfile_yesno (option, value, _T("serial_hardware_ctsrts"), &p->serial_hwctsrts)
4393 		|| cfgfile_yesno (option, value, _T("serial_direct"), &p->serial_direct)
4394 		|| cfgfile_yesno (option, value, _T("fpu_strict"), &p->fpu_strict)
4395 		|| cfgfile_yesno (option, value, _T("fpu_softfloat"), &p->fpu_softfloat)
4396 		|| cfgfile_yesno (option, value, _T("comp_nf"), &p->compnf)
4397 		|| cfgfile_yesno (option, value, _T("comp_constjump"), &p->comp_constjump)
4398 #ifdef USE_JIT_FPU
4399 		|| cfgfile_yesno (option, value, _T("compfpu"), &p->compfpu)
4400 #endif
4401 		|| cfgfile_yesno (option, value, _T("rtg_nocustom"), &p->picasso96_nocustom)
4402 		|| cfgfile_yesno (option, value, _T("floppy_write_protect"), &p->floppy_read_only)
4403 		|| cfgfile_yesno (option, value, _T("uae_hide_autoconfig"), &p->uae_hide_autoconfig)
4404 		|| cfgfile_yesno(option, value, _T("toccata"), &p->sound_toccata)
4405 		|| cfgfile_yesno(option, value, _T("es1370_pci"), &p->sound_es1370)
4406 		|| cfgfile_yesno(option, value, _T("fm801_pci"), &p->sound_fm801)
4407 		|| cfgfile_yesno (option, value, _T("toccata_mixer"), &p->sound_toccata_mixer)
4408 		|| cfgfile_yesno (option, value, _T("uaeserial"), &p->uaeserial))
4409 		return 1;
4410 
4411 #ifdef FSUAE // NL
4412 	if (!g_fs_uae_jit_compiler) {
4413 		if (cfgfile_intval(option, value, _T("cachesize"), &p->cachesize, 1)) {
4414 			/* If FS-UAE wasn't started with JIT support initially, we cannot
4415 			 * enable it at a later time, since 32-bit memory may not be
4416 			 * configured. */
4417 			if (p->cachesize) {
4418 				error_log(_T("uae_cachesize set without jit_compiler"));
4419 				p->cachesize = 0;
4420 				return 1;
4421 			}
4422 		}
4423 	}
4424 #endif
4425 
4426 	if (cfgfile_intval (option, value, _T("cachesize"), &p->cachesize, 1)
4427 		|| cfgfile_intval (option, value, _T("cd32nvram_size"), &p->cs_cd32nvram_size, 1024)
4428 		|| cfgfile_intval (option, value, _T("chipset_hacks"), &p->cs_hacks, 1)
4429 		|| cfgfile_intval (option, value, _T("serial_stopbits"), &p->serial_stopbits, 1)
4430 		|| cfgfile_intval (option, value, _T("cpu060_revision"), &p->cpu060_revision, 1)
4431 		|| cfgfile_intval (option, value, _T("fpu_revision"), &p->fpu_revision, 1)
4432 		|| cfgfile_intval (option, value, _T("cdtvramcard"), &p->cs_cdtvcard, 1)
4433 		|| cfgfile_intval (option, value, _T("fatgary"), &p->cs_fatgaryrev, 1)
4434 		|| cfgfile_intval (option, value, _T("ramsey"), &p->cs_ramseyrev, 1)
4435 		|| cfgfile_doubleval (option, value, _T("chipset_refreshrate"), &p->chipset_refreshrate)
4436 		|| cfgfile_intval(option, value, _T("cpuboardmem1_size"), &p->cpuboardmem1_size, 0x100000)
4437 		|| cfgfile_intval(option, value, _T("cpuboardmem2_size"), &p->cpuboardmem2_size, 0x100000)
4438 		|| cfgfile_intval(option, value, _T("fastmem_size"), &p->fastmem_size, 0x100000)
4439 		|| cfgfile_intval(option, value, _T("fastmem_size_k"), &p->fastmem_size, 1024)
4440 		|| cfgfile_intval (option, value, _T("fastmem2_size"), &p->fastmem2_size, 0x100000)
4441 		|| cfgfile_intval (option, value, _T("fastmem2_size_k"), &p->fastmem2_size, 1024)
4442 		|| cfgfile_intval (option, value, _T("mem25bit_size"), &p->mem25bit_size, 0x100000)
4443 		|| cfgfile_intval (option, value, _T("a3000mem_size"), &p->mbresmem_low_size, 0x100000)
4444 		|| cfgfile_intval (option, value, _T("mbresmem_size"), &p->mbresmem_high_size, 0x100000)
4445 		|| cfgfile_intval (option, value, _T("z3mem_size"), &p->z3fastmem_size, 0x100000)
4446 		|| cfgfile_intval (option, value, _T("z3mem2_size"), &p->z3fastmem2_size, 0x100000)
4447 		|| cfgfile_intval (option, value, _T("megachipmem_size"), &p->z3chipmem_size, 0x100000)
4448 		|| cfgfile_intval (option, value, _T("z3mem_start"), &p->z3autoconfig_start, 1)
4449 		|| cfgfile_intval (option, value, _T("bogomem_size"), &p->bogomem_size, 0x40000)
4450 		|| cfgfile_intval (option, value, _T("gfxcard_size"), &p->rtgmem_size, 0x100000)
4451 		|| cfgfile_intval(option, value, _T("rtg_modes"), &p->picasso96_modeflags, 1)
4452 		|| cfgfile_intval (option, value, _T("floppy_speed"), &p->floppy_speed, 1)
4453 		|| cfgfile_intval (option, value, _T("cd_speed"), &p->cd_speed, 1)
4454 		|| cfgfile_intval (option, value, _T("floppy_write_length"), &p->floppy_write_length, 1)
4455 		|| cfgfile_intval (option, value, _T("floppy_random_bits_min"), &p->floppy_random_bits_min, 1)
4456 		|| cfgfile_intval (option, value, _T("floppy_random_bits_max"), &p->floppy_random_bits_max, 1)
4457 		|| cfgfile_intval (option, value, _T("nr_floppies"), &p->nr_floppies, 1)
4458 		|| cfgfile_intval (option, value, _T("floppy0type"), &p->floppyslots[0].dfxtype, 1)
4459 		|| cfgfile_intval (option, value, _T("floppy1type"), &p->floppyslots[1].dfxtype, 1)
4460 		|| cfgfile_intval (option, value, _T("floppy2type"), &p->floppyslots[2].dfxtype, 1)
4461 		|| cfgfile_intval (option, value, _T("floppy3type"), &p->floppyslots[3].dfxtype, 1)
4462 		|| cfgfile_intval (option, value, _T("maprom"), &p->maprom, 1)
4463 		|| cfgfile_intval (option, value, _T("parallel_autoflush"), &p->parallel_autoflush_time, 1)
4464 		|| cfgfile_intval (option, value, _T("uae_hide"), &p->uae_hide, 1)
4465 		|| cfgfile_intval (option, value, _T("cpu_frequency"), &p->cpu_frequency, 1)
4466 		|| cfgfile_intval(option, value, _T("kickstart_ext_rom_file2addr"), &p->romextfile2addr, 1)
4467 		|| cfgfile_intval(option, value, _T("genlock_mix"), &p->genlock_mix, 1)
4468 		|| cfgfile_intval(option, value, _T("uaeboard_mode"), &p->uaeboard, 1)
4469 		|| cfgfile_intval (option, value, _T("catweasel"), &p->catweasel, 1))
4470 		return 1;
4471 
4472 	if (cfgfile_strval (option, value, _T("comp_trustbyte"), &p->comptrustbyte, compmode, 0)
4473 		|| cfgfile_strval (option, value, _T("rtc"), &p->cs_rtc, rtctype, 0)
4474 		|| cfgfile_strval (option, value, _T("ciaatod"), &p->cs_ciaatod, ciaatodmode, 0)
4475 		|| cfgfile_strval (option, value, _T("ide"), &p->cs_ide, idemode, 0)
4476 		|| cfgfile_strval (option, value, _T("scsi"), &p->scsi, scsimode, 0)
4477 		|| cfgfile_strval (option, value, _T("comp_trustword"), &p->comptrustword, compmode, 0)
4478 		|| cfgfile_strval (option, value, _T("comp_trustlong"), &p->comptrustlong, compmode, 0)
4479 		|| cfgfile_strval (option, value, _T("comp_trustnaddr"), &p->comptrustnaddr, compmode, 0)
4480 		|| cfgfile_strval (option, value, _T("collision_level"), &p->collision_level, collmode, 0)
4481 		|| cfgfile_strval (option, value, _T("parallel_matrix_emulation"), &p->parallel_matrix_emulation, epsonprinter, 0)
4482 		|| cfgfile_strval(option, value, _T("monitoremu"), &p->monitoremu, specialmonitors, 0)
4483 		|| cfgfile_strval(option, value, _T("genlockmode"), &p->genlock_image, genlockmodes, 0)
4484 		|| cfgfile_strval (option, value, _T("waiting_blits"), &p->waiting_blits, waitblits, 0)
4485 		|| cfgfile_strval (option, value, _T("floppy_auto_extended_adf"), &p->floppy_auto_ext2, autoext2, 0)
4486 		|| cfgfile_strval (option, value,  _T("z3mapping"), &p->z3_mapping_mode, z3mapping, 0)
4487 		|| cfgfile_strval (option, value,  _T("scsidev_mode"), &p->uaescsidevmode, uaescsidevmodes, 0)
4488 		|| cfgfile_strval (option, value,  _T("boot_rom_uae"), &p->boot_rom, uaebootrom, 0)
4489 		|| cfgfile_strval (option, value,  _T("serial_translate"), &p->serial_crlf, serialcrlf, 0)
4490 		|| cfgfile_strboolval (option, value, _T("comp_flushmode"), &p->comp_hardflush, flushmode, 0))
4491 		return 1;
4492 
4493 	if (cfgfile_path (option, value, _T("kickstart_rom_file"), p->romfile, sizeof p->romfile / sizeof (TCHAR), &p->path_rom)
4494 		|| cfgfile_path (option, value, _T("kickstart_ext_rom_file"), p->romextfile, sizeof p->romextfile / sizeof (TCHAR), &p->path_rom)
4495 		|| cfgfile_path (option, value, _T("kickstart_ext_rom_file2"), p->romextfile2, sizeof p->romextfile2 / sizeof (TCHAR), &p->path_rom)
4496 		|| cfgfile_rom(option, value, _T("kickstart_rom_file_id"), p->romfile, sizeof p->romfile / sizeof(TCHAR))
4497 		|| cfgfile_rom (option, value, _T("kickstart_ext_rom_file_id"), p->romextfile, sizeof p->romextfile / sizeof (TCHAR))
4498 		|| cfgfile_path (option, value, _T("flash_file"), p->flashfile, sizeof p->flashfile / sizeof (TCHAR), &p->path_rom)
4499 		|| cfgfile_path (option, value, _T("cart_file"), p->cartfile, sizeof p->cartfile / sizeof (TCHAR), &p->path_rom)
4500 		|| cfgfile_path (option, value, _T("rtc_file"), p->rtcfile, sizeof p->rtcfile / sizeof (TCHAR), &p->path_rom)
4501 		|| cfgfile_path(option, value, _T("picassoiv_rom_file"), p->picassoivromfile, sizeof p->picassoivromfile / sizeof(TCHAR), &p->path_rom)
4502 		|| cfgfile_string(option, value, _T("genlock_image"), p->genlock_image_file, sizeof p->genlock_image_file / sizeof(TCHAR))
4503 		|| cfgfile_string(option, value, _T ("pci_devices"), p->pci_devices, sizeof p->pci_devices / sizeof(TCHAR))
4504 		|| cfgfile_string (option, value, _T("ghostscript_parameters"), p->ghostscript_parameters, sizeof p->ghostscript_parameters / sizeof (TCHAR)))
4505 		return 1;
4506 
4507 	if (cfgfile_string(option, value, _T("gfxcard_type"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
4508 		p->rtgmem_type = 0;
4509 		i = 0;
4510 		for (;;) {
4511 			const TCHAR *t = gfxboard_get_configname(i);
4512 			if (!t)
4513 				break;
4514 			if (!_tcsicmp(t, tmpbuf)) {
4515 				p->rtgmem_type = i;
4516 				break;
4517 			}
4518 			i++;
4519 		}
4520 		return 1;
4521 	}
4522 
4523 
4524 	if (cfgfile_string(option, value, _T("cpuboard_type"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
4525 		p->cpuboard_type = 0;
4526 		p->cpuboard_subtype = 0;
4527 		for (i = 0; cpuboards[i].name && !p->cpuboard_type; i++) {
4528 			const struct cpuboardtype *cbt = &cpuboards[i];
4529 			if (cbt->subtypes) {
4530 				for (int j = 0; cbt->subtypes[j].name; j++) {
4531 					if (!_tcsicmp(cbt->subtypes[j].configname, tmpbuf)) {
4532 						p->cpuboard_type = i;
4533 						p->cpuboard_subtype = j;
4534 					}
4535 				}
4536 			}
4537 		}
4538 		return 1;
4539 	}
4540 	if (cfgfile_string(option, value, _T("cpuboard_settings"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
4541 		p->cpuboard_settings = 0;
4542 		const struct cpuboardsubtype *cbst = &cpuboards[p->cpuboard_type].subtypes[p->cpuboard_subtype];
4543 		if (cbst->settings) {
4544 			const struct expansionboardsettings *cbs = cbst->settings;
4545 			for(i = 0; cbs[i].name; i++) {
4546 				if (cfgfile_option_find(tmpbuf, cbs[i].configname)) {
4547 					p->cpuboard_settings |= 1 << (i + cbs[i].bitshift);
4548 					break;
4549 				}
4550 			}
4551 		}
4552 		return 1;
4553 	}
4554 
4555 	if (cfgfile_strval (option, value, _T("chipset_compatible"), &p->cs_compatible, cscompa, 0)) {
4556 		built_in_chipset_prefs (p);
4557 		return 1;
4558 	}
4559 
4560 	if (cfgfile_strval (option, value, _T("cart_internal"), &p->cart_internal, cartsmode, 0)) {
4561 		if (p->cart_internal) {
4562 			struct romdata *rd = getromdatabyid (63);
4563 			if (rd)
4564 				_stprintf (p->cartfile, _T(":%s"), rd->configname);
4565 		}
4566 		return 1;
4567 	}
4568 	if (cfgfile_string (option, value, _T("kickstart_rom"), p->romident, sizeof p->romident / sizeof (TCHAR))) {
4569 		decode_rom_ident (p->romfile, sizeof p->romfile / sizeof (TCHAR), p->romident, ROMTYPE_ALL_KICK);
4570 		return 1;
4571 	}
4572 	if (cfgfile_string (option, value, _T("kickstart_ext_rom"), p->romextident, sizeof p->romextident / sizeof (TCHAR))) {
4573 		decode_rom_ident (p->romextfile, sizeof p->romextfile / sizeof (TCHAR), p->romextident, ROMTYPE_ALL_EXT);
4574 		return 1;
4575 	}
4576 
4577 	if (cfgfile_string (option, value, _T("cart"), p->cartident, sizeof p->cartident / sizeof (TCHAR))) {
4578 		decode_rom_ident (p->cartfile, sizeof p->cartfile / sizeof (TCHAR), p->cartident, ROMTYPE_ALL_CART);
4579 #ifdef FSUAE
4580 		write_log("Cartridge file: %s\n", p->cartfile);
4581 #endif
4582 		return 1;
4583 	}
4584 
4585 	if (cfgfile_read_board_rom(p, option, value, &p->path_rom))
4586 		return 1;
4587 
4588 	for (i = 0; i < 4; i++) {
4589 		_stprintf (tmpbuf, _T("floppy%d"), i);
4590 		if (cfgfile_path (option, value, tmpbuf, p->floppyslots[i].df, sizeof p->floppyslots[i].df / sizeof (TCHAR), &p->path_floppy))
4591 			return 1;
4592 	}
4593 
4594 	if (cfgfile_intval (option, value, _T("chipmem_size"), &dummyint, 1)) {
4595 		if (dummyint < 0)
4596 			p->chipmem_size = 0x20000; /* 128k, prototype support */
4597 		else if (dummyint == 0)
4598 			p->chipmem_size = 0x40000; /* 256k */
4599 		else
4600 			p->chipmem_size = dummyint * 0x80000;
4601 		return 1;
4602 	}
4603 
4604 	if (cfgfile_string (option, value, _T("addmem1"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4605 		parse_addmem (p, tmpbuf, 0);
4606 		return 1;
4607 	}
4608 	if (cfgfile_string (option, value, _T("addmem2"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4609 		parse_addmem (p, tmpbuf, 1);
4610 		return 1;
4611 	}
4612 
4613 	if (cfgfile_strval (option, value, _T("chipset"), &tmpval, csmode, 0)) {
4614 		set_chipset_mask (p, tmpval);
4615 		return 1;
4616 	}
4617 
4618 	if (cfgfile_string (option, value, _T("mmu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4619 		p->mmu_model = _tstol (tmpbuf);
4620 		return 1;
4621 	}
4622 
4623 	if (cfgfile_string (option, value, _T("fpu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4624 		p->fpu_model = _tstol (tmpbuf);
4625 		return 1;
4626 	}
4627 
4628 	if (cfgfile_string (option, value, _T("cpu_model"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4629 		p->cpu_model = _tstol (tmpbuf);
4630 		p->fpu_model = 0;
4631 		return 1;
4632 	}
4633 
4634 	if (cfgfile_strval(option, value, _T("ppc_implementation"), &p->ppc_implementation, ppc_implementations, 0))
4635 		return 1;
4636 	if (cfgfile_string(option, value, _T("ppc_model"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
4637 		p->ppc_mode = 0;
4638 		p->ppc_model[0] = 0;
4639 		if (!_tcsicmp(tmpbuf, _T("automatic"))) {
4640 			p->ppc_mode = 1;
4641 		} else if (!_tcsicmp(tmpbuf, _T("manual"))) {
4642 			p->ppc_mode = 2;
4643 		} else {
4644 			if (tmpbuf[0] && _tcslen(tmpbuf) < sizeof(p->ppc_model) / sizeof(TCHAR)) {
4645 				_tcscpy(p->ppc_model, tmpbuf);
4646 				p->ppc_mode = 2;
4647 			}
4648 		}
4649 		return 1;
4650 	}
4651 	if (cfgfile_strval(option, value, _T("ppc_cpu_idle"), &p->ppc_cpu_idle, ppc_cpu_idle, 0))
4652 		return 1;
4653 
4654 	/* old-style CPU configuration */
4655 	if (cfgfile_string (option, value, _T("cpu_type"), tmpbuf, sizeof tmpbuf / sizeof (TCHAR))) {
4656 		// 68000/010 32-bit addressing was not available until 2.8.2
4657 		bool force24bit = p->config_version <= ((2 << 16) | (8 << 8) | (1 << 0));
4658 		p->fpu_model = 0;
4659 		p->address_space_24 = 0;
4660 		p->cpu_model = 680000;
4661 		if (!_tcscmp (tmpbuf, _T("68000"))) {
4662 			p->cpu_model = 68000;
4663 			if (force24bit)
4664 				p->address_space_24 = 1;
4665 		} else if (!_tcscmp (tmpbuf, _T("68010"))) {
4666 			p->cpu_model = 68010;
4667 			if (force24bit)
4668 				p->address_space_24 = 1;
4669 		} else if (!_tcscmp (tmpbuf, _T("68ec020"))) {
4670 			p->cpu_model = 68020;
4671 		} else if (!_tcscmp (tmpbuf, _T("68020"))) {
4672 			p->cpu_model = 68020;
4673 		} else if (!_tcscmp (tmpbuf, _T("68ec020/68881"))) {
4674 			p->cpu_model = 68020;
4675 			p->fpu_model = 68881;
4676 			p->address_space_24 = 1;
4677 		} else if (!_tcscmp (tmpbuf, _T("68020/68881"))) {
4678 			p->cpu_model = 68020;
4679 			p->fpu_model = 68881;
4680 		} else if (!_tcscmp (tmpbuf, _T("68040"))) {
4681 			p->cpu_model = 68040;
4682 			p->fpu_model = 68040;
4683 		} else if (!_tcscmp (tmpbuf, _T("68060"))) {
4684 			p->cpu_model = 68060;
4685 			p->fpu_model = 68060;
4686 		}
4687 		return 1;
4688 	}
4689 
4690 	/* Broken earlier versions used to write this out as a string.  */
4691 	if (cfgfile_strval (option, value, _T("finegraincpu_speed"), &p->m68k_speed, speedmode, 1)) {
4692 		p->m68k_speed--;
4693 		return 1;
4694 	}
4695 
4696 	if (cfgfile_strval (option, value, _T("cpu_speed"), &p->m68k_speed, speedmode, 1)) {
4697 		p->m68k_speed--;
4698 		return 1;
4699 	}
4700 	if (cfgfile_intval (option, value, _T("cpu_speed"), &p->m68k_speed, 1)) {
4701 		p->m68k_speed *= CYCLE_UNIT;
4702 		return 1;
4703 	}
4704 	if (cfgfile_doubleval(option, value, _T("cpu_throttle"), &p->m68k_speed_throttle)) {
4705 		return 1;
4706 	}
4707 	if (cfgfile_doubleval(option, value, _T("cpu_x86_throttle"), &p->x86_speed_throttle)) {
4708 		return 1;
4709 	}
4710 	if (cfgfile_intval (option, value, _T("finegrain_cpu_speed"), &p->m68k_speed, 1)) {
4711 		if (OFFICIAL_CYCLE_UNIT > CYCLE_UNIT) {
4712 			int factor = OFFICIAL_CYCLE_UNIT / CYCLE_UNIT;
4713 			p->m68k_speed = (p->m68k_speed + factor - 1) / factor;
4714 		}
4715 		if (strcasecmp (value, _T("max")) == 0)
4716 			p->m68k_speed = -1;
4717 		return 1;
4718 	}
4719 
4720 	if (cfgfile_intval (option, value, _T("dongle"), &p->dongle, 1)) {
4721 		if (p->dongle == 0)
4722 			cfgfile_strval (option, value, _T("dongle"), &p->dongle, dongles, 0);
4723 		return 1;
4724 	}
4725 
4726 	if (strcasecmp (option, _T("quickstart")) == 0) {
4727 		int model = 0;
4728 		TCHAR *tmpp = _tcschr (value, ',');
4729 		if (tmpp) {
4730 			*tmpp++ = 0;
4731 			TCHAR *tmpp2 = _tcschr (value, ',');
4732 			if (tmpp2)
4733 				*tmpp2 = 0;
4734 			cfgfile_strval (option, value, option, &model, qsmodes,  0);
4735 			if (model >= 0) {
4736 				int config = _tstol (tmpp);
4737 				built_in_prefs (p, model, config, 0, 0);
4738 			}
4739 		}
4740 		return 1;
4741 	}
4742 
4743 	if (cfgfile_parse_filesys (p, option, value))
4744 		return 1;
4745 
4746 	return 0;
4747 }
4748 
4749 
4750 static bool createconfigstore (struct uae_prefs*);
4751 static int getconfigstoreline (const TCHAR *option, TCHAR *value);
4752 
calcformula(struct uae_prefs * prefs,TCHAR * in)4753 static void calcformula (struct uae_prefs *prefs, TCHAR *in)
4754 {
4755 	TCHAR out[MAX_DPATH], configvalue[CONFIG_BLEN];
4756 	TCHAR *p = out;
4757 	double val;
4758 	int cnt1, cnt2;
4759 	static bool updatestore;
4760 
4761 	if (_tcslen (in) < 2 || in[0] != '[' || in[_tcslen (in) - 1] != ']')
4762 		return;
4763 	if (!configstore || updatestore)
4764 		createconfigstore (prefs);
4765 	updatestore = false;
4766 	if (!configstore)
4767 		return;
4768 	cnt1 = cnt2 = 0;
4769 	for (int i = 1; i < _tcslen (in) - 1; i++) {
4770 		TCHAR c = _totupper (in[i]);
4771 		if (c >= 'A' && c <='Z') {
4772 			TCHAR *start = &in[i];
4773 			while (_istalnum (c) || c == '_' || c == '.') {
4774 				i++;
4775 				c = in[i];
4776 			}
4777 			TCHAR store = in[i];
4778 			in[i] = 0;
4779 			//write_log (_T("'%s'\n"), start);
4780 			if (!getconfigstoreline (start, configvalue))
4781 				return;
4782 			_tcscpy (p, configvalue);
4783 			p += _tcslen (p);
4784 			in[i] = store;
4785 			i--;
4786 			cnt1++;
4787 		} else {
4788 			cnt2++;
4789 			*p ++= c;
4790 		}
4791 	}
4792 	*p = 0;
4793 	if (cnt1 == 0 && cnt2 == 0)
4794 		return;
4795 	/* single config entry only? */
4796 	if (cnt1 == 1 && cnt2 == 0) {
4797 		_tcscpy (in, out);
4798 		updatestore = true;
4799 		return;
4800 	}
4801 	if (calc (out, &val)) {
4802 		if (val - (int)val != 0.0f)
4803 			_stprintf (in, _T("%f"), val);
4804 		else
4805 			_stprintf (in, _T("%d"), (int)val);
4806 		updatestore = true;
4807 		return;
4808 	}
4809 }
4810 
cfgfile_parse_option(struct uae_prefs * p,const TCHAR * option,TCHAR * value,int type)4811 int cfgfile_parse_option (struct uae_prefs *p, const TCHAR *option, TCHAR *value, int type)
4812 {
4813 	calcformula (p, value);
4814 
4815 	if (!_tcscmp (option, _T("debug"))) {
4816 		write_log (_T("CONFIG DEBUG: '%s'\n"), value);
4817 		return 1;
4818 	}
4819 	if (!_tcscmp (option, _T("config_hardware")))
4820 		return 1;
4821 	if (!_tcscmp (option, _T("config_host")))
4822 		return 1;
4823 	if (cfgfile_path (option, value, _T("config_all_path"), p->config_all_path, sizeof p->config_all_path / sizeof(TCHAR)))
4824 		return 1;
4825 	if (cfgfile_path (option, value, _T("config_hardware_path"), p->config_hardware_path, sizeof p->config_hardware_path / sizeof (TCHAR)))
4826 		return 1;
4827 	if (cfgfile_path (option, value, _T("config_host_path"), p->config_host_path, sizeof p->config_host_path / sizeof(TCHAR)))
4828 		return 1;
4829 	if (type == 0 || (type & CONFIG_TYPE_HARDWARE)) {
4830 		if (cfgfile_parse_hardware (p, option, value))
4831 			return 1;
4832 	}
4833 	if (type == 0 || (type & CONFIG_TYPE_HOST)) {
4834 		// cfgfile_parse_host may modify the option (convert to lowercase).
4835 		TCHAR* writable_option = my_strdup(option);
4836 		if (cfgfile_parse_host (p, writable_option, value)) {
4837 			free(writable_option);
4838 			return 1;
4839 		}
4840 		free(writable_option);
4841 	}
4842 	if (type > 0 && (type & (CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST)) != (CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST))
4843 		return 1;
4844 	return 0;
4845 }
4846 
isutf8ext(TCHAR * s)4847 static int isutf8ext (TCHAR *s)
4848 {
4849 	if (_tcslen (s) > _tcslen (UTF8NAME) && !_tcscmp (s + _tcslen (s) - _tcslen (UTF8NAME), UTF8NAME)) {
4850 		s[_tcslen (s) - _tcslen (UTF8NAME)] = 0;
4851 		return 1;
4852 	}
4853 	return 0;
4854 }
4855 
cfgfile_separate_linea(const TCHAR * filename,char * line,TCHAR * line1b,TCHAR * line2b)4856 static int cfgfile_separate_linea (const TCHAR *filename, char *line, TCHAR *line1b, TCHAR *line2b)
4857 {
4858 	char *line1, *line2;
4859 	int i;
4860 
4861 	line1 = line;
4862 	line1 += strspn (line1, "\t \r\n");
4863 	if (*line1 == ';')
4864 		return 0;
4865 	line2 = strchr (line, '=');
4866 	if (! line2) {
4867 		TCHAR *s = au (line1);
4868 		cfgfile_warning(_T("CFGFILE: '%s', linea was incomplete with only %s\n"), filename, s);
4869 		xfree (s);
4870 		return 0;
4871 	}
4872 	*line2++ = '\0';
4873 
4874 	/* Get rid of whitespace.  */
4875 	i = strlen (line2);
4876 	while (i > 0 && (line2[i - 1] == '\t' || line2[i - 1] == ' '
4877 		|| line2[i - 1] == '\r' || line2[i - 1] == '\n'))
4878 		line2[--i] = '\0';
4879 	line2 += strspn (line2, "\t \r\n");
4880 
4881 	i = strlen (line);
4882 	while (i > 0 && (line[i - 1] == '\t' || line[i - 1] == ' '
4883 		|| line[i - 1] == '\r' || line[i - 1] == '\n'))
4884 		line[--i] = '\0';
4885 	line += strspn (line, "\t \r\n");
4886 	au_copy (line1b, MAX_DPATH, line);
4887 	if (isutf8ext (line1b)) {
4888 		if (line2[0]) {
4889 			TCHAR *s = utf8u (line2);
4890 			_tcscpy (line2b, s);
4891 			xfree (s);
4892 		}
4893 	} else {
4894 		au_copy (line2b, MAX_DPATH, line2);
4895 	}
4896 	return 1;
4897 }
4898 
cfgfile_separate_line(TCHAR * line,TCHAR * line1b,TCHAR * line2b)4899 static int cfgfile_separate_line (TCHAR *line, TCHAR *line1b, TCHAR *line2b)
4900 {
4901 	TCHAR *line1, *line2;
4902 	int i;
4903 
4904 	line1 = line;
4905 	line1 += _tcsspn (line1, _T("\t \r\n"));
4906 	if (*line1 == ';')
4907 		return 0;
4908 	line2 = _tcschr (line, '=');
4909 	if (! line2) {
4910 		cfgfile_warning(_T("CFGFILE: line was incomplete with only %s\n"), line1);
4911 		return 0;
4912 	}
4913 	*line2++ = '\0';
4914 
4915 	/* Get rid of whitespace.  */
4916 	i = _tcslen (line2);
4917 	while (i > 0 && (line2[i - 1] == '\t' || line2[i - 1] == ' '
4918 		|| line2[i - 1] == '\r' || line2[i - 1] == '\n'))
4919 		line2[--i] = '\0';
4920 	line2 += _tcsspn (line2, _T("\t \r\n"));
4921 	_tcscpy (line2b, line2);
4922 	i = _tcslen (line);
4923 	while (i > 0 && (line[i - 1] == '\t' || line[i - 1] == ' '
4924 		|| line[i - 1] == '\r' || line[i - 1] == '\n'))
4925 		line[--i] = '\0';
4926 	line += _tcsspn (line, _T("\t \r\n"));
4927 	_tcscpy (line1b, line);
4928 
4929 	if (line2b[0] == '"' || line2b[0] == '\"') {
4930 		TCHAR c = line2b[0];
4931 		int i = 0;
4932 		memmove (line2b, line2b + 1, (_tcslen (line2b) + 1) * sizeof (TCHAR));
4933 		while (line2b[i] != 0 && line2b[i] != c)
4934 			i++;
4935 		line2b[i] = 0;
4936 	}
4937 
4938 	if (isutf8ext (line1b))
4939 		return 0;
4940 	return 1;
4941 }
4942 
isobsolete(TCHAR * s)4943 static int isobsolete (TCHAR *s)
4944 {
4945 	int i = 0;
4946 	while (obsolete[i]) {
4947 		if (!strcasecmp (s, obsolete[i])) {
4948 			cfgfile_warning_obsolete(_T("obsolete config entry '%s'\n"), s);
4949 			return 1;
4950 		}
4951 		i++;
4952 	}
4953 	if (_tcslen (s) > 2 && !_tcsncmp (s, _T("w."), 2))
4954 		return 1;
4955 	if (_tcslen (s) >= 10 && !_tcsncmp (s, _T("gfx_opengl"), 10)) {
4956 		cfgfile_warning_obsolete(_T("obsolete config entry '%s\n"), s);
4957 		return 1;
4958 	}
4959 	if (_tcslen (s) >= 6 && !_tcsncmp (s, _T("gfx_3d"), 6)) {
4960 		cfgfile_warning_obsolete(_T("obsolete config entry '%s\n"), s);
4961 		return 1;
4962 	}
4963 	return 0;
4964 }
4965 
cfgfile_parse_separated_line(struct uae_prefs * p,TCHAR * line1b,TCHAR * line2b,int type)4966 static void cfgfile_parse_separated_line (struct uae_prefs *p, TCHAR *line1b, TCHAR *line2b, int type)
4967 {
4968 	TCHAR line3b[CONFIG_BLEN], line4b[CONFIG_BLEN];
4969 	struct strlist *sl;
4970 	int ret;
4971 
4972 	_tcscpy (line3b, line1b);
4973 	_tcscpy (line4b, line2b);
4974 	ret = cfgfile_parse_option (p, line1b, line2b, type);
4975 	if (!isobsolete (line3b)) {
4976 		for (sl = p->all_lines; sl; sl = sl->next) {
4977 			if (sl->option && !strcasecmp (line1b, sl->option)) break;
4978 		}
4979 		if (!sl) {
4980 			struct strlist *u = xcalloc (struct strlist, 1);
4981 			u->option = my_strdup (line3b);
4982 			u->value = my_strdup (line4b);
4983 			u->next = p->all_lines;
4984 			p->all_lines = u;
4985 			if (!ret) {
4986 				u->unknown = 1;
4987 				cfgfile_warning(_T("unknown config entry: '%s=%s'\n"), u->option, u->value);
4988 			}
4989 		}
4990 	}
4991 }
4992 
cfgfile_parse_lines(struct uae_prefs * p,const TCHAR * lines,int type)4993 void cfgfile_parse_lines (struct uae_prefs *p, const TCHAR *lines, int type)
4994 {
4995 	TCHAR *buf = my_strdup (lines);
4996 	TCHAR *t = buf;
4997 	for (;;) {
4998 		if (_tcslen (t) == 0)
4999 			break;
5000 		TCHAR *t2 = _tcschr (t, '\n');
5001 		if (t2)
5002 			*t2 = 0;
5003 		cfgfile_parse_line (p, t, type);
5004 		if (!t2)
5005 			break;
5006 		t = t2 + 1;
5007 	}
5008 	xfree (buf);
5009 }
5010 
cfgfile_parse_line(struct uae_prefs * p,TCHAR * line,int type)5011 void cfgfile_parse_line (struct uae_prefs *p, TCHAR *line, int type)
5012 {
5013 	TCHAR line1b[CONFIG_BLEN], line2b[CONFIG_BLEN];
5014 
5015 	if (!cfgfile_separate_line (line, line1b, line2b))
5016 		return;
5017 	cfgfile_parse_separated_line (p, line1b, line2b, type);
5018 }
5019 
subst(TCHAR * p,TCHAR * f,int n)5020 static void subst (TCHAR *p, TCHAR *f, int n)
5021 {
5022 	if (_tcslen(p) == 0 || _tcslen(f) == 0)
5023 		return;
5024 	TCHAR *str = cfgfile_subst_path (UNEXPANDED, p, f);
5025 	_tcsncpy (f, str, n - 1);
5026 	f[n - 1] = '\0';
5027 	free (str);
5028 }
5029 
getconfigstoreline(const TCHAR * option,TCHAR * value)5030 static int getconfigstoreline (const TCHAR *option, TCHAR *value)
5031 {
5032 	TCHAR tmp[CONFIG_BLEN * 2], tmp2[CONFIG_BLEN * 2];
5033 
5034 	if (!configstore)
5035 		return 0;
5036 	zfile_fseek (configstore, 0, SEEK_SET);
5037 	for (;;) {
5038 		if (!zfile_fgets (tmp, sizeof tmp / sizeof (TCHAR), configstore))
5039 			return 0;
5040 		if (!cfgfile_separate_line (tmp, tmp2, value))
5041 			continue;
5042 		if (!_tcsicmp (option, tmp2))
5043 			return 1;
5044 	}
5045 }
5046 
createconfigstore(struct uae_prefs * p)5047 static bool createconfigstore (struct uae_prefs *p)
5048 {
5049 	uae_u8 zeros[4] = { 0 };
5050 	zfile_fclose (configstore);
5051 	configstore = zfile_fopen_empty (NULL, _T("configstore"), 50000);
5052 	if (!configstore)
5053 		return false;
5054 	zfile_fseek (configstore, 0, SEEK_SET);
5055 	uaeconfig++;
5056 	cfgfile_save_options (configstore, p, 0);
5057 	uaeconfig--;
5058 	zfile_fwrite (zeros, 1, sizeof zeros, configstore);
5059 	zfile_fseek (configstore, 0, SEEK_SET);
5060 	return true;
5061 }
5062 
cfg_fgets(char * line,int max,struct zfile * fh)5063 static char *cfg_fgets (char *line, int max, struct zfile *fh)
5064 {
5065 #ifdef SINGLEFILE
5066 	extern TCHAR singlefile_config[];
5067 	static TCHAR *sfile_ptr;
5068 	TCHAR *p;
5069 #endif
5070 
5071 	if (fh)
5072 		return zfile_fgetsa (line, max, fh);
5073 #ifdef SINGLEFILE
5074 	if (sfile_ptr == 0) {
5075 		sfile_ptr = singlefile_config;
5076 		if (*sfile_ptr) {
5077 			write_log (_T("singlefile config found\n"));
5078 			while (*sfile_ptr++);
5079 		}
5080 	}
5081 	if (*sfile_ptr == 0) {
5082 		sfile_ptr = singlefile_config;
5083 		return 0;
5084 	}
5085 	p = sfile_ptr;
5086 	while (*p != 13 && *p != 10 && *p != 0) p++;
5087 	memset (line, 0, max);
5088 	memcpy (line, sfile_ptr, (p - sfile_ptr) * sizeof (TCHAR));
5089 	sfile_ptr = p + 1;
5090 	if (*sfile_ptr == 13)
5091 		sfile_ptr++;
5092 	if (*sfile_ptr == 10)
5093 		sfile_ptr++;
5094 	return line;
5095 #endif
5096 	return 0;
5097 }
5098 
cfgfile_load_2(struct uae_prefs * p,const TCHAR * filename,bool real,int * type)5099 static int cfgfile_load_2 (struct uae_prefs *p, const TCHAR *filename, bool real, int *type)
5100 {
5101 	int i;
5102 	struct zfile *fh;
5103 	char linea[CONFIG_BLEN];
5104 	TCHAR line[CONFIG_BLEN], line1b[CONFIG_BLEN], line2b[CONFIG_BLEN];
5105 	struct strlist *sl;
5106 	bool type1 = false, type2 = false;
5107 	int askedtype = 0;
5108 
5109 	if (type) {
5110 		askedtype = *type;
5111 		*type = 0;
5112 	}
5113 	if (real) {
5114 		p->config_version = 0;
5115 		config_newfilesystem = 0;
5116 		inputdevice_config_load_start(p);
5117 		//reset_inputdevice_config (p);
5118 	}
5119 
5120 	fh = zfile_fopen (filename, _T("r"), ZFD_NORMAL);
5121 #ifndef	SINGLEFILE
5122 	if (! fh)
5123 		return 0;
5124 #endif
5125 
5126 	while (cfg_fgets (linea, sizeof (linea), fh) != 0) {
5127 		trimwsa (linea);
5128 		if (strlen (linea) > 0) {
5129 			if (linea[0] == '#' || linea[0] == ';') {
5130 				struct strlist *u = xcalloc (struct strlist, 1);
5131 				u->option = NULL;
5132 				TCHAR *com = au (linea);
5133 				u->value = my_strdup (com);
5134 				xfree (com);
5135 				u->unknown = 1;
5136 				u->next = p->all_lines;
5137 				p->all_lines = u;
5138 				continue;
5139 			}
5140 			if (!cfgfile_separate_linea (filename, linea, line1b, line2b))
5141 				continue;
5142 			type1 = type2 = 0;
5143 			if (cfgfile_yesno (line1b, line2b, _T("config_hardware"), &type1) ||
5144 				cfgfile_yesno (line1b, line2b, _T("config_host"), &type2)) {
5145 					if (type1 && type)
5146 						*type |= CONFIG_TYPE_HARDWARE;
5147 					if (type2 && type)
5148 						*type |= CONFIG_TYPE_HOST;
5149 					continue;
5150 			}
5151 			if (real) {
5152 				cfgfile_parse_separated_line (p, line1b, line2b, askedtype);
5153 			} else {
5154 				cfgfile_string (line1b, line2b, _T("config_description"), p->description, sizeof p->description / sizeof (TCHAR));
5155 				cfgfile_path (line1b, line2b, _T("config_hardware_path"), p->config_hardware_path, sizeof p->config_hardware_path / sizeof (TCHAR));
5156 				cfgfile_path (line1b, line2b, _T("config_host_path"), p->config_host_path, sizeof p->config_host_path / sizeof(TCHAR));
5157 				cfgfile_path (line1b, line2b, _T("config_all_path"), p->config_all_path, sizeof p->config_all_path / sizeof(TCHAR));
5158 				cfgfile_string (line1b, line2b, _T("config_window_title"), p->config_window_title, sizeof p->config_window_title / sizeof (TCHAR));
5159 			}
5160 		}
5161 	}
5162 
5163 	if (type && *type == 0)
5164 		*type = CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST;
5165 	zfile_fclose (fh);
5166 
5167 	if (!real)
5168 		return 1;
5169 
5170 	for (sl = temp_lines; sl; sl = sl->next) {
5171 		_stprintf (line, _T("%s=%s"), sl->option, sl->value);
5172 		cfgfile_parse_line (p, line, 0);
5173 	}
5174 
5175 	for (i = 0; i < 4; i++)
5176 		subst (p->path_floppy.path[0], p->floppyslots[i].df, sizeof p->floppyslots[i].df / sizeof (TCHAR));
5177 	subst (p->path_rom.path[0], p->romfile, sizeof p->romfile / sizeof (TCHAR));
5178 	subst (p->path_rom.path[0], p->romextfile, sizeof p->romextfile / sizeof (TCHAR));
5179 	subst (p->path_rom.path[0], p->romextfile2, sizeof p->romextfile2 / sizeof (TCHAR));
5180 
5181 	for (i = 0; i < MAX_EXPANSION_BOARDS; i++) {
5182 		for (int j = 0; j < MAX_BOARD_ROMS; j++) {
5183 			subst(p->path_rom.path[0], p->expansionboard[i].roms[j].romfile, MAX_DPATH / sizeof(TCHAR));
5184 		}
5185 	}
5186 
5187 	return 1;
5188 }
5189 
cfgfile_load(struct uae_prefs * p,const TCHAR * filename,int * type,int ignorelink,int userconfig)5190 int cfgfile_load (struct uae_prefs *p, const TCHAR *filename, int *type, int ignorelink, int userconfig)
5191 {
5192 	int v;
5193 	TCHAR tmp[MAX_DPATH];
5194 	int type2;
5195 	static int recursive;
5196 
5197 	if (recursive > 1)
5198 		return 0;
5199 	recursive++;
5200 	write_log (_T("load config '%s':%d\n"), filename, type ? *type : -1);
5201 	v = cfgfile_load_2 (p, filename, 1, type);
5202 	if (!v) {
5203 		cfgfile_warning(_T("cfgfile_load_2 failed\n"));
5204 		goto end;
5205 	}
5206 	if (userconfig)
5207 		target_addtorecent (filename, 0);
5208 	if (!ignorelink) {
5209 		if (p->config_all_path[0]) {
5210 			fetch_configurationpath(tmp, sizeof(tmp) / sizeof(TCHAR));
5211 			_tcsncat(tmp, p->config_all_path, sizeof(tmp) / sizeof(TCHAR) - _tcslen(tmp) - 1);
5212 			type2 = CONFIG_TYPE_HOST | CONFIG_TYPE_HARDWARE;
5213 			cfgfile_load(p, tmp, &type2, 1, 0);
5214 		}
5215 		if (p->config_hardware_path[0]) {
5216 			fetch_configurationpath (tmp, sizeof (tmp) / sizeof (TCHAR));
5217 			_tcsncat (tmp, p->config_hardware_path, sizeof (tmp) / sizeof (TCHAR) - _tcslen(tmp) - 1);
5218 			type2 = CONFIG_TYPE_HARDWARE;
5219 			cfgfile_load (p, tmp, &type2, 1, 0);
5220 		}
5221 		if (p->config_host_path[0]) {
5222 			fetch_configurationpath (tmp, sizeof (tmp) / sizeof (TCHAR));
5223 			_tcsncat (tmp, p->config_host_path, sizeof (tmp) / sizeof (TCHAR) - _tcslen(tmp) - 1);
5224 			type2 = CONFIG_TYPE_HOST;
5225 			cfgfile_load (p, tmp, &type2, 1, 0);
5226 		}
5227 	}
5228 end:
5229 	recursive--;
5230 	fixup_prefs (p);
5231 	return v;
5232 }
5233 
cfgfile_backup(const TCHAR * path)5234 void cfgfile_backup (const TCHAR *path)
5235 {
5236 	TCHAR dpath[MAX_DPATH];
5237 
5238 	fetch_configurationpath (dpath, sizeof (dpath) / sizeof (TCHAR));
5239 	_tcscat (dpath, _T("configuration.backup"));
5240 	bool hidden = my_isfilehidden (dpath);
5241 	my_unlink (dpath);
5242 	my_rename (path, dpath);
5243 	if (hidden)
5244 		my_setfilehidden (dpath, hidden);
5245 }
5246 
cfgfile_save(struct uae_prefs * p,const TCHAR * filename,int type)5247 int cfgfile_save (struct uae_prefs *p, const TCHAR *filename, int type)
5248 {
5249 	struct zfile *fh;
5250 
5251 #ifdef FSUAE
5252 	// don't back up config file
5253 #else
5254 	cfgfile_backup (filename);
5255 #endif
5256 	fh = zfile_fopen (filename, unicode_config ? _T("w, ccs=UTF-8") : _T("w"), ZFD_NORMAL);
5257 	if (! fh)
5258 		return 0;
5259 
5260 	if (!type)
5261 		type = CONFIG_TYPE_HARDWARE | CONFIG_TYPE_HOST;
5262 	cfgfile_save_options (fh, p, type);
5263 	zfile_fclose (fh);
5264 	return 1;
5265 }
5266 
cfgfile_get_description(const TCHAR * filename,TCHAR * description,TCHAR * hostlink,TCHAR * hardwarelink,int * type)5267 int cfgfile_get_description (const TCHAR *filename, TCHAR *description, TCHAR *hostlink, TCHAR *hardwarelink, int *type)
5268 {
5269 	int result = 0;
5270 	struct uae_prefs *p = xmalloc (struct uae_prefs, 1);
5271 
5272 	p->description[0] = 0;
5273 	p->config_host_path[0] = 0;
5274 	p->config_hardware_path[0] = 0;
5275 	if (cfgfile_load_2 (p, filename, 0, type)) {
5276 		result = 1;
5277 		if (description)
5278 			_tcscpy (description, p->description);
5279 		if (hostlink)
5280 			_tcscpy (hostlink, p->config_host_path);
5281 		if (hardwarelink)
5282 			_tcscpy (hardwarelink, p->config_hardware_path);
5283 	}
5284 	xfree (p);
5285 	return result;
5286 }
5287 
cfgfile_configuration_change(int v)5288 int cfgfile_configuration_change (int v)
5289 {
5290 	static int mode;
5291 	if (v >= 0)
5292 		mode = v;
5293 	return mode;
5294 }
5295 
cfgfile_show_usage(void)5296 void cfgfile_show_usage (void)
5297 {
5298 	int i;
5299 	write_log (_T("UAE Configuration Help:\n") \
5300 		_T("=======================\n"));
5301 	for (i = 0; i < sizeof opttable / sizeof *opttable; i++)
5302 		write_log (_T("%s: %s\n"), opttable[i].config_label, opttable[i].config_help);
5303 }
5304 
5305 /* This implements the old commandline option parsing. I've re-added this
5306 because the new way of doing things is painful for me (it requires me
5307 to type a couple hundred characters when invoking UAE).  The following
5308 is far less annoying to use.  */
parse_gfx_specs(struct uae_prefs * p,const TCHAR * spec)5309 static void parse_gfx_specs (struct uae_prefs *p, const TCHAR *spec)
5310 {
5311 	TCHAR *x0 = my_strdup (spec);
5312 	TCHAR *x1, *x2;
5313 
5314 	x1 = _tcschr (x0, ':');
5315 	if (x1 == 0)
5316 		goto argh;
5317 	x2 = _tcschr (x1+1, ':');
5318 	if (x2 == 0)
5319 		goto argh;
5320 	*x1++ = 0; *x2++ = 0;
5321 
5322 	p->gfx_size_win.width = p->gfx_size_fs.width = _tstoi (x0);
5323 	p->gfx_size_win.height = p->gfx_size_fs.height = _tstoi (x1);
5324 	p->gfx_resolution = _tcschr (x2, 'l') != 0 ? 1 : 0;
5325 	p->gfx_xcenter = _tcschr (x2, 'x') != 0 ? 1 : _tcschr (x2, 'X') != 0 ? 2 : 0;
5326 	p->gfx_ycenter = _tcschr (x2, 'y') != 0 ? 1 : _tcschr (x2, 'Y') != 0 ? 2 : 0;
5327 	p->gfx_vresolution = _tcschr (x2, 'd') != 0 ? VRES_DOUBLE : VRES_NONDOUBLE;
5328 	p->gfx_pscanlines = _tcschr (x2, 'D') != 0;
5329 	if (p->gfx_pscanlines)
5330 		p->gfx_vresolution = VRES_DOUBLE;
5331 	p->gfx_apmode[0].gfx_fullscreen = _tcschr (x2, 'a') != 0;
5332 	p->gfx_apmode[1].gfx_fullscreen = _tcschr (x2, 'p') != 0;
5333 
5334 	free (x0);
5335 	return;
5336 
5337 argh:
5338 	write_log (_T("Bad display mode specification.\n"));
5339 	write_log (_T("The format to use is: \"width:height:modifiers\"\n"));
5340 	write_log (_T("Type \"uae -h\" for detailed help.\n"));
5341 	free (x0);
5342 }
5343 
parse_sound_spec(struct uae_prefs * p,const TCHAR * spec)5344 static void parse_sound_spec (struct uae_prefs *p, const TCHAR *spec)
5345 {
5346 	TCHAR *x0 = my_strdup (spec);
5347 	TCHAR *x1, *x2 = NULL, *x3 = NULL, *x4 = NULL, *x5 = NULL;
5348 
5349 	x1 = _tcschr (x0, ':');
5350 	if (x1 != NULL) {
5351 		*x1++ = '\0';
5352 		x2 = _tcschr (x1 + 1, ':');
5353 		if (x2 != NULL) {
5354 			*x2++ = '\0';
5355 			x3 = _tcschr (x2 + 1, ':');
5356 			if (x3 != NULL) {
5357 				*x3++ = '\0';
5358 				x4 = _tcschr (x3 + 1, ':');
5359 				if (x4 != NULL) {
5360 					*x4++ = '\0';
5361 					x5 = _tcschr (x4 + 1, ':');
5362 				}
5363 			}
5364 		}
5365 	}
5366 	p->produce_sound = _tstoi (x0);
5367 	if (x1) {
5368 		p->sound_stereo_separation = 0;
5369 		if (*x1 == 'S') {
5370 			p->sound_stereo = SND_STEREO;
5371 			p->sound_stereo_separation = 7;
5372 		} else if (*x1 == 's')
5373 			p->sound_stereo = SND_STEREO;
5374 		else
5375 			p->sound_stereo = SND_MONO;
5376 	}
5377 	if (x3)
5378 		p->sound_freq = _tstoi (x3);
5379 	if (x4)
5380 		p->sound_maxbsiz = _tstoi (x4);
5381 	free (x0);
5382 }
5383 
5384 
parse_joy_spec(struct uae_prefs * p,const TCHAR * spec)5385 static void parse_joy_spec (struct uae_prefs *p, const TCHAR *spec)
5386 {
5387 	int v0 = 2, v1 = 0;
5388 	if (_tcslen(spec) != 2)
5389 		goto bad;
5390 
5391 	switch (spec[0]) {
5392 	case '0': v0 = JSEM_JOYS; break;
5393 	case '1': v0 = JSEM_JOYS + 1; break;
5394 	case 'M': case 'm': v0 = JSEM_MICE; break;
5395 	case 'A': case 'a': v0 = JSEM_KBDLAYOUT; break;
5396 	case 'B': case 'b': v0 = JSEM_KBDLAYOUT + 1; break;
5397 	case 'C': case 'c': v0 = JSEM_KBDLAYOUT + 2; break;
5398 	default: goto bad;
5399 	}
5400 
5401 	switch (spec[1]) {
5402 	case '0': v1 = JSEM_JOYS; break;
5403 	case '1': v1 = JSEM_JOYS + 1; break;
5404 	case 'M': case 'm': v1 = JSEM_MICE; break;
5405 	case 'A': case 'a': v1 = JSEM_KBDLAYOUT; break;
5406 	case 'B': case 'b': v1 = JSEM_KBDLAYOUT + 1; break;
5407 	case 'C': case 'c': v1 = JSEM_KBDLAYOUT + 2; break;
5408 	default: goto bad;
5409 	}
5410 	if (v0 == v1)
5411 		goto bad;
5412 	/* Let's scare Pascal programmers */
5413 	if (0)
5414 bad:
5415 	write_log (_T("Bad joystick mode specification. Use -J xy, where x and y\n")
5416 		_T("can be 0 for joystick 0, 1 for joystick 1, M for mouse, and\n")
5417 		_T("a, b or c for different keyboard settings.\n"));
5418 
5419 	p->jports[0].id = v0;
5420 	p->jports[1].id = v1;
5421 }
5422 
parse_filesys_spec(struct uae_prefs * p,bool readonly,const TCHAR * spec)5423 static void parse_filesys_spec (struct uae_prefs *p, bool readonly, const TCHAR *spec)
5424 {
5425 	struct uaedev_config_info uci;
5426 	TCHAR buf[256];
5427 	TCHAR *s2;
5428 
5429 	uci_set_defaults (&uci, false);
5430 	_tcsncpy (buf, spec, 255); buf[255] = 0;
5431 	s2 = _tcschr (buf, ':');
5432 	if (s2) {
5433 		*s2++ = '\0';
5434 #ifdef __DOS__
5435 		{
5436 			TCHAR *tmp;
5437 
5438 			while ((tmp = _tcschr (s2, '\\')))
5439 				*tmp = '/';
5440 		}
5441 #endif
5442 #ifdef FILESYS
5443 		_tcscpy (uci.volname, buf);
5444 		_tcscpy (uci.rootdir, s2);
5445 		uci.readonly = readonly;
5446 		uci.type = UAEDEV_DIR;
5447 		add_filesys_config (p, -1, &uci);
5448 #endif
5449 	} else {
5450 		write_log (_T("Usage: [-m | -M] VOLNAME:mount_point\n"));
5451 	}
5452 }
5453 
parse_hardfile_spec(struct uae_prefs * p,const TCHAR * spec)5454 static void parse_hardfile_spec (struct uae_prefs *p, const TCHAR *spec)
5455 {
5456 	struct uaedev_config_info uci;
5457 	TCHAR *x0 = my_strdup (spec);
5458 	TCHAR *x1, *x2, *x3, *x4;
5459 
5460 	uci_set_defaults (&uci, false);
5461 	x1 = _tcschr (x0, ':');
5462 	if (x1 == NULL)
5463 		goto argh;
5464 	*x1++ = '\0';
5465 	x2 = _tcschr (x1 + 1, ':');
5466 	if (x2 == NULL)
5467 		goto argh;
5468 	*x2++ = '\0';
5469 	x3 = _tcschr (x2 + 1, ':');
5470 	if (x3 == NULL)
5471 		goto argh;
5472 	*x3++ = '\0';
5473 	x4 = _tcschr (x3 + 1, ':');
5474 	if (x4 == NULL)
5475 		goto argh;
5476 	*x4++ = '\0';
5477 #ifdef FILESYS
5478 	_tcscpy (uci.rootdir, x4);
5479 	//add_filesys_config (p, -1, NULL, NULL, x4, 0, 0, _tstoi (x0), _tstoi (x1), _tstoi (x2), _tstoi (x3), 0, 0, 0, 0, 0, 0, 0);
5480 #endif
5481 	free (x0);
5482 	return;
5483 
5484 argh:
5485 	free (x0);
5486 	cfgfile_warning(_T("Bad hardfile parameter specified\n"));
5487 	return;
5488 }
5489 
parse_cpu_specs(struct uae_prefs * p,const TCHAR * spec)5490 static void parse_cpu_specs (struct uae_prefs *p, const TCHAR *spec)
5491 {
5492 	if (*spec < '0' || *spec > '4') {
5493 		cfgfile_warning(_T("CPU parameter string must begin with '0', '1', '2', '3' or '4'.\n"));
5494 		return;
5495 	}
5496 
5497 	p->cpu_model = (*spec++) * 10 + 68000;
5498 	p->address_space_24 = p->cpu_model < 68020;
5499 	p->cpu_compatible = 0;
5500 	while (*spec != '\0') {
5501 		switch (*spec) {
5502 		case 'a':
5503 			if (p->cpu_model < 68020)
5504 				cfgfile_warning(_T("In 68000/68010 emulation, the address space is always 24 bit.\n"));
5505 			else if (p->cpu_model >= 68040)
5506 				cfgfile_warning(_T("In 68040/060 emulation, the address space is always 32 bit.\n"));
5507 			else
5508 				p->address_space_24 = 1;
5509 			break;
5510 		case 'c':
5511 			if (p->cpu_model != 68000)
5512 				cfgfile_warning(_T("The more compatible CPU emulation is only available for 68000\n")
5513 				_T("emulation, not for 68010 upwards.\n"));
5514 			else
5515 				p->cpu_compatible = 1;
5516 			break;
5517 		default:
5518 			cfgfile_warning(_T("Bad CPU parameter specified.\n"));
5519 			break;
5520 		}
5521 		spec++;
5522 	}
5523 }
5524 
cmdpath(TCHAR * dst,const TCHAR * src,int maxsz)5525 static void cmdpath (TCHAR *dst, const TCHAR *src, int maxsz)
5526 {
5527 	TCHAR *s = target_expand_environment (src);
5528 	_tcsncpy (dst, s, maxsz);
5529 	dst[maxsz] = 0;
5530 	xfree (s);
5531 }
5532 
5533 /* Returns the number of args used up (0 or 1).  */
parse_cmdline_option(struct uae_prefs * p,TCHAR c,const TCHAR * arg)5534 int parse_cmdline_option (struct uae_prefs *p, TCHAR c, const TCHAR *arg)
5535 {
5536 	struct strlist *u = xcalloc (struct strlist, 1);
5537 	const TCHAR arg_required[] = _T("0123rKpImWSAJwNCZUFcblOdHRv");
5538 
5539 	if (_tcschr (arg_required, c) && ! arg) {
5540 		write_log (_T("Missing argument for option `-%c'!\n"), c);
5541 		return 0;
5542 	}
5543 
5544 	u->option = xmalloc (TCHAR, 2);
5545 	u->option[0] = c;
5546 	u->option[1] = 0;
5547 	u->value = my_strdup (arg);
5548 	u->next = p->all_lines;
5549 	p->all_lines = u;
5550 
5551 	switch (c) {
5552 	case 'h': usage (); exit (0);
5553 
5554 	case '0': cmdpath (p->floppyslots[0].df, arg, 255); break;
5555 	case '1': cmdpath (p->floppyslots[1].df, arg, 255); break;
5556 	case '2': cmdpath (p->floppyslots[2].df, arg, 255); break;
5557 	case '3': cmdpath (p->floppyslots[3].df, arg, 255); break;
5558 	case 'r': cmdpath (p->romfile, arg, 255); break;
5559 	case 'K': cmdpath (p->romextfile, arg, 255); break;
5560 	case 'p': _tcsncpy (p->prtname, arg, 255); p->prtname[255] = 0; break;
5561 		/*     case 'I': _tcsncpy (p->sername, arg, 255); p->sername[255] = 0; currprefs.use_serial = 1; break; */
5562 	case 'm': case 'M': parse_filesys_spec (p, c == 'M', arg); break;
5563 	case 'W': parse_hardfile_spec (p, arg); break;
5564 	case 'S': parse_sound_spec (p, arg); break;
5565 	case 'R': p->gfx_framerate = _tstoi (arg); break;
5566 	case 'i': p->illegal_mem = 1; break;
5567 	case 'J': parse_joy_spec (p, arg); break;
5568 
5569 	case 'w': p->m68k_speed = _tstoi (arg); break;
5570 
5571 		/* case 'g': p->use_gfxlib = 1; break; */
5572 	case 'G': p->start_gui = 0; break;
5573 	case 'D': p->start_debugger = 1; break;
5574 
5575 	case 'n':
5576 		if (_tcschr (arg, 'i') != 0)
5577 			p->immediate_blits = 1;
5578 		break;
5579 
5580 	case 'v':
5581 		set_chipset_mask (p, _tstoi (arg));
5582 		break;
5583 
5584 	case 'C':
5585 		parse_cpu_specs (p, arg);
5586 		break;
5587 
5588 	case 'Z':
5589 		p->z3fastmem_size = _tstoi (arg) * 0x100000;
5590 		break;
5591 
5592 	case 'U':
5593 		p->rtgmem_size = _tstoi (arg) * 0x100000;
5594 		break;
5595 
5596 	case 'F':
5597 		p->fastmem_size = _tstoi (arg) * 0x100000;
5598 		break;
5599 
5600 	case 'b':
5601 		p->bogomem_size = _tstoi (arg) * 0x40000;
5602 		break;
5603 
5604 	case 'c':
5605 		p->chipmem_size = _tstoi (arg) * 0x80000;
5606 		break;
5607 
5608 	case 'l':
5609 		if (0 == strcasecmp(arg, _T("de")))
5610 			p->keyboard_lang = KBD_LANG_DE;
5611 		else if (0 == strcasecmp(arg, _T("dk")))
5612 			p->keyboard_lang = KBD_LANG_DK;
5613 		else if (0 == strcasecmp(arg, _T("us")))
5614 			p->keyboard_lang = KBD_LANG_US;
5615 		else if (0 == strcasecmp(arg, _T("se")))
5616 			p->keyboard_lang = KBD_LANG_SE;
5617 		else if (0 == strcasecmp(arg, _T("fr")))
5618 			p->keyboard_lang = KBD_LANG_FR;
5619 		else if (0 == strcasecmp(arg, _T("it")))
5620 			p->keyboard_lang = KBD_LANG_IT;
5621 		else if (0 == strcasecmp(arg, _T("es")))
5622 			p->keyboard_lang = KBD_LANG_ES;
5623 		break;
5624 
5625 	case 'O': parse_gfx_specs (p, arg); break;
5626 	case 'd':
5627 		if (_tcschr (arg, 'S') != NULL || _tcschr (arg, 's')) {
5628 			write_log (_T("  Serial on demand.\n"));
5629 			p->serial_demand = 1;
5630 		}
5631 		if (_tcschr (arg, 'P') != NULL || _tcschr (arg, 'p')) {
5632 			write_log (_T("  Parallel on demand.\n"));
5633 			p->parallel_demand = 1;
5634 		}
5635 
5636 		break;
5637 
5638 	case 'H':
5639 		p->color_mode = _tstoi (arg);
5640 		if (p->color_mode < 0) {
5641 			write_log (_T("Bad color mode selected. Using default.\n"));
5642 			p->color_mode = 0;
5643 		}
5644 		break;
5645 	default:
5646 		write_log (_T("Unknown option `-%c'!\n"), c);
5647 		break;
5648 	}
5649 	return !! _tcschr (arg_required, c);
5650 }
5651 
cfgfile_addcfgparam(TCHAR * line)5652 void cfgfile_addcfgparam (TCHAR *line)
5653 {
5654 	struct strlist *u;
5655 	TCHAR line1b[CONFIG_BLEN], line2b[CONFIG_BLEN];
5656 
5657 	if (!line) {
5658 		struct strlist **ps = &temp_lines;
5659 		while (*ps) {
5660 			struct strlist *s = *ps;
5661 			*ps = s->next;
5662 			xfree (s->value);
5663 			xfree (s->option);
5664 			xfree (s);
5665 		}
5666 		temp_lines = 0;
5667 		return;
5668 	}
5669 	if (!cfgfile_separate_line (line, line1b, line2b))
5670 		return;
5671 	u = xcalloc (struct strlist, 1);
5672 	u->option = my_strdup (line1b);
5673 	u->value = my_strdup (line2b);
5674 	u->next = temp_lines;
5675 	temp_lines = u;
5676 }
5677 
5678 #if 0
5679 static int cfgfile_handle_custom_event (TCHAR *custom, int mode)
5680 {
5681 	TCHAR option[CONFIG_BLEN], value[CONFIG_BLEN];
5682 	TCHAR option2[CONFIG_BLEN], value2[CONFIG_BLEN];
5683 	TCHAR *tmp, *p, *nextp;
5684 	struct zfile *configstore = NULL;
5685 	int cnt = 0, cnt_ok = 0;
5686 
5687 	if (!mode) {
5688 		TCHAR zero = 0;
5689 		configstore = zfile_fopen_empty ("configstore", 50000);
5690 		cfgfile_save_options (configstore, &currprefs, 0);
5691 		cfg_write (&zero, configstore);
5692 	}
5693 
5694 	nextp = NULL;
5695 	tmp = p = xcalloc (TCHAR, _tcslen (custom) + 2);
5696 	_tcscpy (tmp, custom);
5697 	while (p && *p) {
5698 		if (*p == '\"') {
5699 			TCHAR *p2;
5700 			p++;
5701 			p2 = p;
5702 			while (*p2 != '\"' && *p2 != 0)
5703 				p2++;
5704 			if (*p2 == '\"') {
5705 				*p2++ = 0;
5706 				nextp = p2 + 1;
5707 				if (*nextp == ' ')
5708 					nextp++;
5709 			}
5710 		}
5711 		if (cfgfile_separate_line (p, option, value)) {
5712 			cnt++;
5713 			if (mode) {
5714 				cfgfile_parse_option (&changed_prefs, option, value, 0);
5715 			} else {
5716 				zfile_fseek (configstore, 0, SEEK_SET);
5717 				for (;;) {
5718 					if (!getconfigstoreline (configstore, option2, value2))
5719 						break;
5720 					if (!_tcscmpi (option, option2) && !_tcscmpi (value, value2)) {
5721 						cnt_ok++;
5722 						break;
5723 					}
5724 				}
5725 			}
5726 		}
5727 		p = nextp;
5728 	}
5729 	xfree (tmp);
5730 	zfile_fclose (configstore);
5731 	if (cnt > 0 && cnt == cnt_ok)
5732 		return 1;
5733 	return 0;
5734 }
5735 #endif
5736 
cmdlineparser(const TCHAR * s,TCHAR * outp[],int max)5737 int cmdlineparser (const TCHAR *s, TCHAR *outp[], int max)
5738 {
5739 	int j, cnt = 0;
5740 	int slash = 0;
5741 	int quote = 0;
5742 	TCHAR tmp1[MAX_DPATH];
5743 	const TCHAR *prev;
5744 	int doout;
5745 
5746 	doout = 0;
5747 	prev = s;
5748 	j = 0;
5749 	outp[0] = 0;
5750 	while (cnt < max) {
5751 		TCHAR c = *s++;
5752 		if (!c)
5753 			break;
5754 		if (c < 32)
5755 			continue;
5756 		if (c == '\\')
5757 			slash = 1;
5758 		if (!slash && c == '"') {
5759 			if (quote) {
5760 				quote = 0;
5761 				doout = 1;
5762 			} else {
5763 				quote = 1;
5764 				j = -1;
5765 			}
5766 		}
5767 		if (!quote && c == ' ')
5768 			doout = 1;
5769 		if (!doout) {
5770 			if (j >= 0) {
5771 				tmp1[j] = c;
5772 				tmp1[j + 1] = 0;
5773 			}
5774 			j++;
5775 		}
5776 		if (doout) {
5777 			if (_tcslen (tmp1) > 0) {
5778 				outp[cnt++] = my_strdup (tmp1);
5779 				outp[cnt] = 0;
5780 			}
5781 			tmp1[0] = 0;
5782 			doout = 0;
5783 			j = 0;
5784 		}
5785 		slash = 0;
5786 	}
5787 	if (j > 0 && cnt < max) {
5788 		outp[cnt++] = my_strdup (tmp1);
5789 		outp[cnt] = 0;
5790 	}
5791 	return cnt;
5792 }
5793 
5794 #define UAELIB_MAX_PARSE 100
5795 
cfgfile_parse_uaelib_option(struct uae_prefs * p,TCHAR * option,TCHAR * value,int type)5796 static bool cfgfile_parse_uaelib_option (struct uae_prefs *p, TCHAR *option, TCHAR *value, int type)
5797 {
5798 	return false;
5799 }
5800 
cfgfile_searchconfig(const TCHAR * in,int index,TCHAR * out,int outsize)5801 int cfgfile_searchconfig(const TCHAR *in, int index, TCHAR *out, int outsize)
5802 {
5803 	TCHAR tmp[CONFIG_BLEN];
5804 	int j = 0;
5805 	int inlen = _tcslen (in);
5806 	int joker = 0;
5807 	uae_u32 err = 0;
5808 	bool configsearchfound = false;
5809 
5810 	if (in[inlen - 1] == '*') {
5811 		joker = 1;
5812 		inlen--;
5813 	}
5814 	*out = 0;
5815 
5816 	if (!configstore)
5817 		createconfigstore(&currprefs);
5818 	if (!configstore)
5819 		return 20;
5820 
5821 	if (index < 0)
5822 		zfile_fseek(configstore, 0, SEEK_SET);
5823 
5824 	for (;;) {
5825 		uae_u8 b = 0;
5826 
5827 		if (zfile_fread (&b, 1, 1, configstore) != 1) {
5828 			err = 10;
5829 			if (configsearchfound)
5830 				err = 0;
5831 			goto end;
5832 		}
5833 		if (j >= sizeof (tmp) / sizeof (TCHAR) - 1)
5834 			j = sizeof (tmp) / sizeof (TCHAR) - 1;
5835 		if (b == 0) {
5836 			err = 10;
5837 			if (configsearchfound)
5838 				err = 0;
5839 			goto end;
5840 		}
5841 		if (b == '\n') {
5842 			if (!_tcsncmp (tmp, in, inlen) && ((inlen > 0 && _tcslen (tmp) > inlen && tmp[inlen] == '=') || (joker))) {
5843 				TCHAR *p;
5844 				if (joker)
5845 					p = tmp - 1;
5846 				else
5847 					p = _tcschr (tmp, '=');
5848 				if (p) {
5849 					for (int i = 0; out && i < outsize - 1; i++) {
5850 						TCHAR b = *++p;
5851 						out[i] = b;
5852 						out[i + 1] = 0;
5853 						if (!b)
5854 							break;
5855 					}
5856 				}
5857 				err = 0xffffffff;
5858 				configsearchfound = true;
5859 				goto end;
5860 			}
5861 			j = 0;
5862 		} else {
5863 			tmp[j++] = b;
5864 			tmp[j] = 0;
5865 		}
5866 	}
5867 end:
5868 	return err;
5869 }
5870 
cfgfile_modify(uae_u32 index,const TCHAR * parms,uae_u32 size,TCHAR * out,uae_u32 outsize)5871 uae_u32 cfgfile_modify (uae_u32 index, const TCHAR *parms, uae_u32 size, TCHAR *out, uae_u32 outsize)
5872 {
5873 	TCHAR *p;
5874 	TCHAR *argc[UAELIB_MAX_PARSE];
5875 	int argv, i;
5876 	uae_u32 err;
5877 	static TCHAR *configsearch;
5878 
5879 #ifdef FSUAE // NL
5880 	write_log("*** cfgfile_modify *** %s\n", parms);
5881 #endif
5882 
5883 	*out = 0;
5884 	err = 0;
5885 	argv = 0;
5886 	p = 0;
5887 	if (index != 0xffffffff) {
5888 		if (!configstore) {
5889 			err = 20;
5890 			goto end;
5891 		}
5892 		if (configsearch) {
5893 			err = cfgfile_searchconfig(configsearch, index,  out, outsize);
5894 			goto end;
5895 		}
5896 		err = 0xffffffff;
5897 		for (i = 0; out && i < outsize - 1; i++) {
5898 			uae_u8 b = 0;
5899 			if (zfile_fread (&b, 1, 1, configstore) != 1)
5900 				err = 0;
5901 			if (b == 0)
5902 				err = 0;
5903 			if (b == '\n')
5904 				b = 0;
5905 			out[i] = b;
5906 			out[i + 1] = 0;
5907 			if (!b)
5908 				break;
5909 		}
5910 		goto end;
5911 	}
5912 
5913 	if (size > 10000)
5914 		return 10;
5915 	argv = cmdlineparser (parms, argc, UAELIB_MAX_PARSE);
5916 
5917 	if (argv <= 1 && index == 0xffffffff) {
5918 		createconfigstore (&currprefs);
5919 		xfree (configsearch);
5920 		configsearch = NULL;
5921 		if (!configstore) {
5922 			err = 20;
5923 			goto end;
5924 		}
5925 		if (argv > 0 && _tcslen (argc[0]) > 0)
5926 			configsearch = my_strdup (argc[0]);
5927 		err = 0xffffffff;
5928 		goto end;
5929 	}
5930 
5931 	for (i = 0; i < argv; i++) {
5932 		if (i + 2 <= argv) {
5933 			if (!_tcsicmp (argc[i], _T("dbg"))) {
5934 				debug_parser (argc[i + 1], out, outsize);
5935 			} else if (!inputdevice_uaelib (argc[i], argc[i + 1])) {
5936 				if (!cfgfile_parse_uaelib_option (&changed_prefs, argc[i], argc[i + 1], 0)) {
5937 					if (!cfgfile_parse_option (&changed_prefs, argc[i], argc[i + 1], 0)) {
5938 						err = 5;
5939 						break;
5940 					}
5941 				}
5942 			}
5943 			set_config_changed ();
5944 			set_special(SPCFLAG_MODE_CHANGE);
5945 			i++;
5946 		}
5947 	}
5948 end:
5949 	for (i = 0; i < argv; i++)
5950 		xfree (argc[i]);
5951 	xfree (p);
5952 	return err;
5953 }
5954 
cfgfile_uaelib_modify(uae_u32 index,uae_u32 parms,uae_u32 size,uae_u32 out,uae_u32 outsize)5955 uae_u32 cfgfile_uaelib_modify (uae_u32 index, uae_u32 parms, uae_u32 size, uae_u32 out, uae_u32 outsize)
5956 {
5957 	uae_char *p, *parms_p = NULL, *parms_out = NULL;
5958 	int i, ret;
5959 	TCHAR *out_p = NULL, *parms_in = NULL;
5960 
5961 	if (out)
5962 		put_byte (out, 0);
5963 	if (size == 0) {
5964 		while (get_byte (parms + size) != 0)
5965 			size++;
5966 	}
5967 	parms_p = xmalloc (uae_char, size + 1);
5968 	if (!parms_p) {
5969 		ret = 10;
5970 		goto end;
5971 	}
5972 	if (out) {
5973 		out_p = xmalloc (TCHAR, outsize + 1);
5974 		if (!out_p) {
5975 			ret = 10;
5976 			goto end;
5977 		}
5978 		out_p[0] = 0;
5979 	}
5980 	p = parms_p;
5981 	for (i = 0; i < size; i++) {
5982 		p[i] = get_byte (parms + i);
5983 		if (p[i] == 10 || p[i] == 13 || p[i] == 0)
5984 			break;
5985 	}
5986 	p[i] = 0;
5987 	parms_in = au (parms_p);
5988 	ret = cfgfile_modify (index, parms_in, size, out_p, outsize);
5989 	xfree (parms_in);
5990 	if (out) {
5991 		parms_out = ua (out_p);
5992 		p = parms_out;
5993 		for (i = 0; i < outsize - 1; i++) {
5994 			uae_u8 b = *p++;
5995 			put_byte (out + i, b);
5996 			put_byte (out + i + 1, 0);
5997 			if (!b)
5998 				break;
5999 		}
6000 	}
6001 	xfree (parms_out);
6002 end:
6003 	xfree (out_p);
6004 	xfree (parms_p);
6005 	return ret;
6006 }
6007 
cfgfile_read_config_value(const TCHAR * option)6008 static const TCHAR *cfgfile_read_config_value (const TCHAR *option)
6009 {
6010 	struct strlist *sl;
6011 	for (sl = currprefs.all_lines; sl; sl = sl->next) {
6012 		if (sl->option && !strcasecmp (sl->option, option))
6013 			return sl->value;
6014 	}
6015 	return NULL;
6016 }
6017 
cfgfile_uaelib(int mode,uae_u32 name,uae_u32 dst,uae_u32 maxlen)6018 uae_u32 cfgfile_uaelib (int mode, uae_u32 name, uae_u32 dst, uae_u32 maxlen)
6019 {
6020 	TCHAR tmp[CONFIG_BLEN];
6021 	int i;
6022 
6023 	if (mode)
6024 		return 0;
6025 
6026 	for (i = 0; i < sizeof (tmp) / sizeof (TCHAR); i++) {
6027 		tmp[i] = get_byte (name + i);
6028 		if (tmp[i] == 0)
6029 			break;
6030 	}
6031 	tmp[sizeof(tmp) / sizeof (TCHAR) - 1] = 0;
6032 	if (tmp[0] == 0)
6033 		return 0;
6034 	const TCHAR *value = cfgfile_read_config_value (tmp);
6035 	if (value) {
6036 		char *s = ua (value);
6037 		for (i = 0; i < maxlen; i++) {
6038 			put_byte (dst + i, s[i]);
6039 			if (s[i] == 0)
6040 				break;
6041 		}
6042 		xfree (s);
6043 		return dst;
6044 	}
6045 	return 0;
6046 }
6047 
restore_configuration(uae_u8 * src)6048 uae_u8 *restore_configuration (uae_u8 *src)
6049 {
6050 	TCHAR *s = au ((char*)src);
6051 	//write_log (s);
6052 	xfree (s);
6053 	src += strlen ((char*)src) + 1;
6054 	return src;
6055 }
6056 
save_configuration(int * len,bool fullconfig)6057 uae_u8 *save_configuration (int *len, bool fullconfig)
6058 {
6059 	int tmpsize = 100000;
6060 	uae_u8 *dstbak, *dst, *p;
6061 	int index = -1;
6062 
6063 	dstbak = dst = xcalloc (uae_u8, tmpsize);
6064 	p = dst;
6065 	for (;;) {
6066 		TCHAR tmpout[1000];
6067 		int ret;
6068 		tmpout[0] = 0;
6069 		ret = cfgfile_modify (index, _T("*"), 1, tmpout, sizeof (tmpout) / sizeof (TCHAR));
6070 		index++;
6071 		if (_tcslen (tmpout) > 0) {
6072 			char *out;
6073 			if (!fullconfig && !_tcsncmp (tmpout, _T("input."), 6))
6074 				continue;
6075 			//write_log (_T("'%s'\n"), tmpout);
6076 			out = uutf8 (tmpout);
6077 			strcpy ((char*)p, out);
6078 			xfree (out);
6079 			strcat ((char*)p, "\n");
6080 			p += strlen ((char*)p);
6081 			if (p - dstbak >= tmpsize - sizeof (tmpout))
6082 				break;
6083 		}
6084 		if (ret >= 0)
6085 			break;
6086 	}
6087 	*len = p - dstbak + 1;
6088 	return dstbak;
6089 }
6090 
6091 #ifdef UAE_MINI
default_prefs_mini(struct uae_prefs * p,int type)6092 static void default_prefs_mini (struct uae_prefs *p, int type)
6093 {
6094 	_tcscpy (p->description, _T("UAE default A500 configuration"));
6095 
6096 	p->nr_floppies = 1;
6097 	p->floppyslots[0].dfxtype = DRV_35_DD;
6098 	p->floppyslots[1].dfxtype = DRV_NONE;
6099 	p->cpu_model = 68000;
6100 	p->address_space_24 = 1;
6101 	p->chipmem_size = 0x00080000;
6102 	p->bogomem_size = 0x00080000;
6103 }
6104 #endif
6105 
6106 #include "sounddep/sound.h"
6107 
default_prefs(struct uae_prefs * p,int type)6108 void default_prefs (struct uae_prefs *p, int type)
6109 {
6110 	int i;
6111 	int roms[] = { 6, 7, 8, 9, 10, 14, 5, 4, 3, 2, 1, -1 };
6112 	TCHAR zero = 0;
6113 	struct zfile *f;
6114 
6115 	reset_inputdevice_config (p);
6116 	memset (p, 0, sizeof (*p));
6117 	_tcscpy (p->description, _T("UAE default configuration"));
6118 	p->config_hardware_path[0] = 0;
6119 	p->config_host_path[0] = 0;
6120 
6121 	p->gfx_scandoubler = false;
6122 	p->start_gui = true;
6123 	p->start_debugger = false;
6124 
6125 	p->all_lines = 0;
6126 	/* Note to porters: please don't change any of these options! UAE is supposed
6127 	* to behave identically on all platforms if possible.
6128 	* (TW says: maybe it is time to update default config..) */
6129 	p->illegal_mem = 0;
6130 	p->use_serial = 0;
6131 	p->serial_demand = 0;
6132 	p->serial_hwctsrts = 1;
6133 	p->serial_stopbits = 0;
6134 	p->parallel_demand = 0;
6135 	p->parallel_matrix_emulation = 0;
6136 	p->parallel_postscript_emulation = 0;
6137 	p->parallel_postscript_detection = 0;
6138 	p->parallel_autoflush_time = 5;
6139 	p->ghostscript_parameters[0] = 0;
6140 	p->uae_hide = 0;
6141 	p->uae_hide_autoconfig = false;
6142 	p->z3_mapping_mode = Z3MAPPING_AUTO;
6143 
6144 	p->mountitems = 0;
6145 	for (i = 0; i < MOUNT_CONFIG_SIZE; i++) {
6146 		p->mountconfig[i].configoffset = -1;
6147 		p->mountconfig[i].unitnum = -1;
6148 	}
6149 
6150 	memset (&p->jports[0], 0, sizeof (struct jport));
6151 	memset (&p->jports[1], 0, sizeof (struct jport));
6152 	memset (&p->jports[2], 0, sizeof (struct jport));
6153 	memset (&p->jports[3], 0, sizeof (struct jport));
6154 	p->jports[0].id = JSEM_MICE;
6155 	p->jports[1].id = JSEM_KBDLAYOUT;
6156 	p->jports[2].id = -1;
6157 	p->jports[3].id = -1;
6158 	p->keyboard_lang = KBD_LANG_US;
6159 
6160 	p->produce_sound = 3;
6161 	p->sound_stereo = SND_STEREO;
6162 	p->sound_stereo_separation = 7;
6163 	p->sound_mixed_stereo_delay = 0;
6164 	p->sound_freq = DEFAULT_SOUND_FREQ;
6165 	p->sound_maxbsiz = DEFAULT_SOUND_MAXB;
6166 	p->sound_interpol = 1;
6167 	p->sound_filter = FILTER_SOUND_EMUL;
6168 	p->sound_filter_type = 0;
6169 	p->sound_auto = 1;
6170 	p->sound_cdaudio = false;
6171 	p->sampler_stereo = false;
6172 	p->sampler_buffer = 0;
6173 	p->sampler_freq = 0;
6174 
6175 	p->comptrustbyte = 0;
6176 	p->comptrustword = 0;
6177 	p->comptrustlong = 0;
6178 	p->comptrustnaddr= 0;
6179 	p->compnf = 1;
6180 	p->comp_hardflush = 0;
6181 	p->comp_constjump = 1;
6182 #ifdef USE_JIT_FPU
6183 	p->compfpu = 1;
6184 #else
6185 	p->compfpu = 0;
6186 #endif
6187 	p->cachesize = 0;
6188 
6189 	p->gfx_framerate = 1;
6190 	p->gfx_autoframerate = 50;
6191 	p->gfx_size_fs.width = 800;
6192 	p->gfx_size_fs.height = 600;
6193 	p->gfx_size_win.width = 720;
6194 	p->gfx_size_win.height = 568;
6195 	for (i = 0; i < 4; i++) {
6196 		p->gfx_size_fs_xtra[i].width = 0;
6197 		p->gfx_size_fs_xtra[i].height = 0;
6198 		p->gfx_size_win_xtra[i].width = 0;
6199 		p->gfx_size_win_xtra[i].height = 0;
6200 	}
6201 	p->gfx_resolution = RES_HIRES;
6202 	p->gfx_vresolution = VRES_DOUBLE;
6203 	p->gfx_iscanlines = 1;
6204 	p->gfx_apmode[0].gfx_fullscreen = GFX_WINDOW;
6205 	p->gfx_apmode[1].gfx_fullscreen = GFX_WINDOW;
6206 	p->gfx_xcenter = 0; p->gfx_ycenter = 0;
6207 	p->gfx_xcenter_pos = -1;
6208 	p->gfx_ycenter_pos = -1;
6209 	p->gfx_xcenter_size = -1;
6210 	p->gfx_ycenter_size = -1;
6211 	p->gfx_max_horizontal = RES_HIRES;
6212 	p->gfx_max_vertical = VRES_DOUBLE;
6213 	p->gfx_autoresolution_minv = 0;
6214 	p->gfx_autoresolution_minh = 0;
6215 	p->color_mode = 2;
6216 	p->gfx_blackerthanblack = 0;
6217 	p->gfx_autoresolution_vga = true;
6218 	p->gfx_apmode[0].gfx_backbuffers = 2;
6219 	p->gfx_apmode[1].gfx_backbuffers = 1;
6220 
6221 	p->immediate_blits = 0;
6222 	p->waiting_blits = 0;
6223 	p->collision_level = 2;
6224 	p->leds_on_screen = 0;
6225 	p->leds_on_screen_mask[0] = p->leds_on_screen_mask[1] = (1 << LED_MAX) - 1;
6226 	p->keyboard_leds_in_use = 0;
6227 	p->keyboard_leds[0] = p->keyboard_leds[1] = p->keyboard_leds[2] = 0;
6228 	p->scsi = 0;
6229 	p->uaeserial = 0;
6230 	p->cpu_idle = 0;
6231 	p->turbo_emulation = 0;
6232 	p->turbo_emulation_limit = 0;
6233 	p->headless = 0;
6234 	p->catweasel = 0;
6235 	p->tod_hack = 0;
6236 	p->maprom = 0;
6237 	p->boot_rom = 0;
6238 	p->filesys_no_uaefsdb = 0;
6239 	p->filesys_custom_uaefsdb = 1;
6240 	p->picasso96_nocustom = 1;
6241 	p->cart_internal = 1;
6242 	p->sana2 = 0;
6243 	p->clipboard_sharing = false;
6244 	p->native_code = false;
6245 
6246 	p->cs_compatible = 1;
6247 	p->cs_rtc = 2;
6248 	p->cs_df0idhw = 1;
6249 	p->cs_a1000ram = 0;
6250 	p->cs_fatgaryrev = -1;
6251 	p->cs_ramseyrev = -1;
6252 	p->cs_agnusrev = -1;
6253 	p->cs_deniserev = -1;
6254 	p->cs_mbdmac = 0;
6255 	p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = p->cs_cd32fmv = false;
6256 	p->cs_cd32nvram_size = 1024;
6257 	p->cs_cdtvcd = p->cs_cdtvram = false;
6258 	p->cs_cdtvcard = 0;
6259 	p->cs_pcmcia = 0;
6260 	p->cs_ksmirror_e0 = 1;
6261 	p->cs_ksmirror_a8 = 0;
6262 	p->cs_ciaoverlay = 1;
6263 	p->cs_ciaatod = 0;
6264 	p->cs_df0idhw = 1;
6265 	p->cs_slowmemisfast = 0;
6266 	p->cs_resetwarning = 1;
6267 	p->cs_ciatodbug = false;
6268 
6269 	for (int i = APMODE_NATIVE; i <= APMODE_RTG; i++) {
6270 		struct gfx_filterdata *f = &p->gf[i];
6271 		f->gfx_filter = 0;
6272 		f->gfx_filter_scanlineratio = (1 << 4) | 1;
6273 		for (int j = 0; j <= 2 * MAX_FILTERSHADERS; j++) {
6274 			f->gfx_filtershader[i][0] = 0;
6275 			f->gfx_filtermask[i][0] = 0;
6276 		}
6277 		f->gfx_filter_horiz_zoom_mult = 1.0;
6278 		f->gfx_filter_vert_zoom_mult = 1.0;
6279 		f->gfx_filter_bilinear = 0;
6280 		f->gfx_filter_filtermode = 0;
6281 		f->gfx_filter_keep_aspect = 0;
6282 		f->gfx_filter_autoscale = AUTOSCALE_STATIC_AUTO;
6283 		f->gfx_filter_keep_autoscale_aspect = false;
6284 		f->gfx_filteroverlay_overscan = 0;
6285 	}
6286 
6287 	p->rtg_horiz_zoom_mult = 1.0;
6288 	p->rtg_vert_zoom_mult = 1.0;
6289 
6290 	_tcscpy (p->floppyslots[0].df, _T("df0.adf"));
6291 	_tcscpy (p->floppyslots[1].df, _T("df1.adf"));
6292 	_tcscpy (p->floppyslots[2].df, _T("df2.adf"));
6293 	_tcscpy (p->floppyslots[3].df, _T("df3.adf"));
6294 
6295 	for (int i = 0; i < MAX_LUA_STATES; i++) {
6296 		p->luafiles[i][0] = 0;
6297 	}
6298 
6299 	configure_rom (p, roms, 0);
6300 	_tcscpy (p->romextfile, _T(""));
6301 	_tcscpy (p->romextfile2, _T(""));
6302 	p->romextfile2addr = 0;
6303 	_tcscpy (p->flashfile, _T(""));
6304 	_tcscpy (p->cartfile, _T(""));
6305 	_tcscpy (p->rtcfile, _T(""));
6306 
6307 	_tcscpy (p->path_rom.path[0], _T("./"));
6308 	_tcscpy (p->path_floppy.path[0], _T("./"));
6309 	_tcscpy (p->path_hardfile.path[0], _T("./"));
6310 
6311 	p->prtname[0] = 0;
6312 	p->sername[0] = 0;
6313 
6314 	p->cpu_thread = false;
6315 
6316 	p->fpu_model = 0;
6317 	p->cpu_model = 68000;
6318 	p->m68k_speed_throttle = 0;
6319 	p->cpu_clock_multiplier = 0;
6320 	p->cpu_frequency = 0;
6321 	p->mmu_model = 0;
6322 	p->cpu060_revision = 6;
6323 	p->fpu_revision = 0;
6324 	p->fpu_no_unimplemented = false;
6325 	p->int_no_unimplemented = false;
6326 	p->fpu_strict = 0;
6327 	p->fpu_softfloat = 0;
6328 	p->m68k_speed = 0;
6329 	p->cpu_compatible = 1;
6330 	p->address_space_24 = 1;
6331 	p->cpu_cycle_exact = 0;
6332 	p->cpu_memory_cycle_exact = 0;
6333 	p->blitter_cycle_exact = 0;
6334 	p->chipset_mask = CSMASK_ECS_AGNUS;
6335 	p->genlock = 0;
6336 	p->genlock_image = 0;
6337 	p->genlock_mix = 0;
6338 	p->ntscmode = 0;
6339 	p->filesys_limit = 0;
6340 	p->filesys_max_name = 107;
6341 	p->filesys_max_file_size = 0x7fffffff;
6342 
6343 	p->fastmem_size = 0x00000000;
6344 	p->fastmem2_size = 0x00000000;
6345 	p->mem25bit_size = 0x00000000;
6346 	p->mbresmem_low_size = 0x00000000;
6347 	p->mbresmem_high_size = 0x00000000;
6348 	p->z3fastmem_size = 0x00000000;
6349 	p->z3fastmem2_size = 0x00000000;
6350 	p->z3autoconfig_start = 0x10000000;
6351 	p->chipmem_size = 0x00080000;
6352 	p->bogomem_size = 0x00080000;
6353 	p->rtgmem_size = 0x00000000;
6354 	p->rtgmem_type = GFXBOARD_UAE_Z3;
6355 	p->custom_memory_addrs[0] = 0;
6356 	p->custom_memory_sizes[0] = 0;
6357 	p->custom_memory_addrs[1] = 0;
6358 	p->custom_memory_sizes[1] = 0;
6359 	p->fastmem_autoconfig = true;
6360 
6361 	p->nr_floppies = 2;
6362 	p->floppy_read_only = false;
6363 	p->floppyslots[0].dfxtype = DRV_35_DD;
6364 	p->floppyslots[1].dfxtype = DRV_35_DD;
6365 	p->floppyslots[2].dfxtype = DRV_NONE;
6366 	p->floppyslots[3].dfxtype = DRV_NONE;
6367 	p->floppy_speed = 100;
6368 	p->floppy_write_length = 0;
6369 	p->floppy_random_bits_min = 1;
6370 	p->floppy_random_bits_max = 3;
6371 	p->dfxclickvolume_disk[0] = 33;
6372 	p->dfxclickvolume_disk[1] = 33;
6373 	p->dfxclickvolume_empty[0] = 33;
6374 	p->dfxclickvolume_empty[1] = 33;
6375 	p->dfxclickchannelmask = 0xffff;
6376 	p->cd_speed = 100;
6377 
6378 	p->statecapturebuffersize = 100;
6379 	p->statecapturerate = 5 * 50;
6380 	p->inprec_autoplay = true;
6381 
6382 #ifdef UAE_MINI
6383 	default_prefs_mini (p, 0);
6384 #endif
6385 
6386 	p->input_tablet = TABLET_OFF;
6387 	p->tablet_library = false;
6388 	p->input_magic_mouse = 0;
6389 	p->input_magic_mouse_cursor = 0;
6390 
6391 	inputdevice_default_prefs (p);
6392 
6393 	blkdev_default_prefs (p);
6394 
6395 	p->cr_selected = -1;
6396 	struct chipset_refresh *cr;
6397 	for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
6398 		cr = &p->cr[i];
6399 		cr->index = i;
6400 		cr->rate = -1;
6401 	}
6402 	cr = &p->cr[CHIPSET_REFRESH_PAL];
6403 	cr->index = CHIPSET_REFRESH_PAL;
6404 	cr->horiz = -1;
6405 	cr->vert = -1;
6406 	cr->lace = -1;
6407 	cr->vsync = - 1;
6408 	cr->framelength = -1;
6409 	cr->rate = 50.0;
6410 	cr->ntsc = 0;
6411 	cr->locked = false;
6412 	_tcscpy (cr->label, _T("PAL"));
6413 	cr = &p->cr[CHIPSET_REFRESH_NTSC];
6414 	cr->index = CHIPSET_REFRESH_NTSC;
6415 	cr->horiz = -1;
6416 	cr->vert = -1;
6417 	cr->lace = -1;
6418 	cr->vsync = - 1;
6419 	cr->framelength = -1;
6420 	cr->rate = 60.0;
6421 	cr->ntsc = 1;
6422 	cr->locked = false;
6423 	_tcscpy (cr->label, _T("NTSC"));
6424 
6425 	savestate_state = 0;
6426 
6427 	target_default_options (p, type);
6428 
6429 	zfile_fclose (default_file);
6430 	default_file = NULL;
6431 	f = zfile_fopen_empty (NULL, _T("configstore"));
6432 	if (f) {
6433 		uaeconfig++;
6434 		cfgfile_save_options (f, p, 0);
6435 		uaeconfig--;
6436 		cfg_write (&zero, f);
6437 		default_file = f;
6438 	}
6439 }
6440 
buildin_default_prefs_68020(struct uae_prefs * p)6441 static void buildin_default_prefs_68020 (struct uae_prefs *p)
6442 {
6443 	p->cpu_model = 68020;
6444 	p->address_space_24 = 1;
6445 	p->cpu_compatible = 1;
6446 	p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE | CSMASK_AGA;
6447 	p->chipmem_size = 0x200000;
6448 	p->bogomem_size = 0;
6449 	p->m68k_speed = -1;
6450 }
6451 
buildin_default_host_prefs(struct uae_prefs * p)6452 static void buildin_default_host_prefs (struct uae_prefs *p)
6453 {
6454 #if 0
6455 	p->sound_filter = FILTER_SOUND_OFF;
6456 	p->sound_stereo = SND_STEREO;
6457 	p->sound_stereo_separation = 7;
6458 	p->sound_mixed_stereo = 0;
6459 #endif
6460 }
6461 
buildin_default_prefs(struct uae_prefs * p)6462 static void buildin_default_prefs (struct uae_prefs *p)
6463 {
6464 	buildin_default_host_prefs (p);
6465 
6466 	p->floppyslots[0].dfxtype = DRV_35_DD;
6467 	if (p->nr_floppies != 1 && p->nr_floppies != 2)
6468 		p->nr_floppies = 2;
6469 	p->floppyslots[1].dfxtype = p->nr_floppies >= 2 ? DRV_35_DD : DRV_NONE;
6470 	p->floppyslots[2].dfxtype = DRV_NONE;
6471 	p->floppyslots[3].dfxtype = DRV_NONE;
6472 	p->floppy_speed = 100;
6473 
6474 	p->fpu_model = 0;
6475 	p->cpu_model = 68000;
6476 	p->cpu_clock_multiplier = 0;
6477 	p->cpu_frequency = 0;
6478 	p->cpu060_revision = 1;
6479 	p->fpu_revision = -1;
6480 	p->m68k_speed = 0;
6481 	p->cpu_compatible = 1;
6482 	p->address_space_24 = 1;
6483 	p->cpu_cycle_exact = 0;
6484 	p->cpu_memory_cycle_exact = 0;
6485 	p->blitter_cycle_exact = 0;
6486 	p->chipset_mask = CSMASK_ECS_AGNUS;
6487 	p->immediate_blits = 0;
6488 	p->waiting_blits = 0;
6489 	p->collision_level = 2;
6490 	if (p->produce_sound < 1)
6491 		p->produce_sound = 1;
6492 	p->scsi = 0;
6493 	p->uaeserial = 0;
6494 	p->cpu_idle = 0;
6495 	p->turbo_emulation = 0;
6496 	p->turbo_emulation_limit = 0;
6497 	p->catweasel = 0;
6498 	p->tod_hack = 0;
6499 	p->maprom = 0;
6500 	p->cachesize = 0;
6501 	p->socket_emu = 0;
6502 	p->sound_volume_master = 0;
6503 	p->sound_volume_paula = 0;
6504 	p->sound_volume_cd = 0;
6505 	p->clipboard_sharing = false;
6506 	p->ppc_mode = 0;
6507 
6508 	p->chipmem_size = 0x00080000;
6509 	p->bogomem_size = 0x00080000;
6510 	p->fastmem_size = 0x00000000;
6511 	p->mem25bit_size = 0x00000000;
6512 	p->mbresmem_low_size = 0x00000000;
6513 	p->mbresmem_high_size = 0x00000000;
6514 	p->z3fastmem_size = 0x00000000;
6515 	p->z3fastmem2_size = 0x00000000;
6516 	p->z3chipmem_size = 0x00000000;
6517 	p->rtgmem_size = 0x00000000;
6518 	p->rtgmem_type = GFXBOARD_UAE_Z3;
6519 
6520 	p->cs_rtc = 0;
6521 	p->cs_a1000ram = false;
6522 	p->cs_fatgaryrev = -1;
6523 	p->cs_ramseyrev = -1;
6524 	p->cs_agnusrev = -1;
6525 	p->cs_deniserev = -1;
6526 	p->cs_mbdmac = 0;
6527 	p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = p->cs_cd32fmv = false;
6528 	p->cs_cdtvcd = p->cs_cdtvram = p->cs_cdtvcard = false;
6529 	p->cs_ide = 0;
6530 	p->cs_pcmcia = 0;
6531 	p->cs_ksmirror_e0 = 1;
6532 	p->cs_ksmirror_a8 = 0;
6533 	p->cs_ciaoverlay = 1;
6534 	p->cs_ciaatod = 0;
6535 	p->cs_df0idhw = 1;
6536 	p->cs_resetwarning = 0;
6537 	p->cs_ciatodbug = false;
6538 	p->cs_1mchipjumper = false;
6539 
6540 	_tcscpy (p->romextfile, _T(""));
6541 	_tcscpy (p->romextfile2, _T(""));
6542 	set_device_rom(p, NULL, ROMTYPE_CPUBOARD, 0);
6543 
6544 	p->prtname[0] = 0;
6545 	p->sername[0] = 0;
6546 
6547 	p->mountitems = 0;
6548 
6549 	target_default_options (p, 1);
6550 }
6551 
set_68020_compa(struct uae_prefs * p,int compa,int cd32)6552 static void set_68020_compa (struct uae_prefs *p, int compa, int cd32)
6553 {
6554 	switch (compa)
6555 	{
6556 	case 0:
6557 		p->blitter_cycle_exact = 1;
6558 		p->m68k_speed = 0;
6559 		if (p->cpu_model == 68020 && p->cachesize == 0) {
6560 			p->cpu_cycle_exact = 1;
6561 			p->cpu_memory_cycle_exact = 1;
6562 			p->cpu_clock_multiplier = 4 << 8;
6563 		}
6564 	break;
6565 	case 1:
6566 		p->cpu_compatible = true;
6567 		p->m68k_speed = 0;
6568 		break;
6569 	case 2:
6570 		p->cpu_compatible = 0;
6571 		p->m68k_speed = -1;
6572 		p->address_space_24 = 0;
6573 		break;
6574 	case 3:
6575 		p->cpu_compatible = 0;
6576 		p->address_space_24 = 0;
6577 		p->cachesize = MAX_JIT_CACHE;
6578 		break;
6579 	}
6580 }
6581 
6582 /* 0: cycle-exact
6583 * 1: more compatible
6584 * 2: no more compatible, no 100% sound
6585 * 3: no more compatible, waiting blits, no 100% sound
6586 */
6587 
set_68000_compa(struct uae_prefs * p,int compa)6588 static void set_68000_compa (struct uae_prefs *p, int compa)
6589 {
6590 	p->cpu_clock_multiplier = 2 << 8;
6591 	switch (compa)
6592 	{
6593 	case 0:
6594 		p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 1;
6595 		break;
6596 	case 1:
6597 		break;
6598 	case 2:
6599 		p->cpu_compatible = 0;
6600 		break;
6601 	case 3:
6602 		p->produce_sound = 2;
6603 		p->cpu_compatible = 0;
6604 		break;
6605 	}
6606 }
6607 
bip_a3000(struct uae_prefs * p,int config,int compa,int romcheck)6608 static int bip_a3000 (struct uae_prefs *p, int config, int compa, int romcheck)
6609 {
6610 	int roms[2];
6611 
6612 	if (config == 2)
6613 		roms[0] = 61;
6614 	else if (config == 1)
6615 		roms[0] = 71;
6616 	else
6617 		roms[0] = 59;
6618 	roms[1] = -1;
6619 	p->bogomem_size = 0;
6620 	p->chipmem_size = 0x200000;
6621 	p->cpu_model = 68030;
6622 	p->fpu_model = 68882;
6623 	p->fpu_no_unimplemented = true;
6624 	if (compa == 0)
6625 		p->mmu_model = 68030;
6626 	else
6627 		p->cachesize = MAX_JIT_CACHE;
6628 	p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6629 	p->cpu_compatible = p->address_space_24 = 0;
6630 	p->m68k_speed = -1;
6631 	p->immediate_blits = 0;
6632 	p->produce_sound = 2;
6633 	p->floppyslots[0].dfxtype = DRV_35_HD;
6634 	p->floppy_speed = 0;
6635 	p->cpu_idle = 150;
6636 	p->cs_compatible = CP_A3000;
6637 	p->mbresmem_low_size = 8 * 1024 * 1024;
6638 	built_in_chipset_prefs (p);
6639 	p->cs_ciaatod = p->ntscmode ? 2 : 1;
6640 	return configure_rom (p, roms, romcheck);
6641 }
bip_a4000(struct uae_prefs * p,int config,int compa,int romcheck)6642 static int bip_a4000 (struct uae_prefs *p, int config, int compa, int romcheck)
6643 {
6644 	int roms[8];
6645 
6646 	roms[0] = 16;
6647 	roms[1] = 31;
6648 	roms[2] = 13;
6649 	roms[3] = 12;
6650 	roms[4] = -1;
6651 
6652 	p->bogomem_size = 0;
6653 	p->chipmem_size = 0x200000;
6654 	p->mbresmem_low_size = 8 * 1024 * 1024;
6655 	p->cpu_model = 68030;
6656 	p->fpu_model = 68882;
6657 	switch (config)
6658 	{
6659 		case 1:
6660 		p->cpu_model = 68040;
6661 		p->fpu_model = 68040;
6662 		break;
6663 		case 2:
6664 		p->cpu_model = 68060;
6665 		p->fpu_model = 68060;
6666 		p->ppc_mode = 1;
6667 		cpuboard_setboard(p, BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_PPC);
6668 		p->cpuboardmem1_size = 128 * 1024 * 1024;
6669 		int roms_ppc[] = { 98, -1 };
6670 		configure_rom(p, roms_ppc, romcheck);
6671 		break;
6672 	}
6673 	p->chipset_mask = CSMASK_AGA | CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6674 	p->cpu_compatible = p->address_space_24 = 0;
6675 	p->m68k_speed = -1;
6676 	p->immediate_blits = 0;
6677 	p->produce_sound = 2;
6678 	p->cachesize = MAX_JIT_CACHE;
6679 	p->floppyslots[0].dfxtype = DRV_35_HD;
6680 	p->floppyslots[1].dfxtype = DRV_35_HD;
6681 	p->floppy_speed = 0;
6682 	p->cpu_idle = 150;
6683 	p->cs_compatible = CP_A4000;
6684 	built_in_chipset_prefs (p);
6685 	p->cs_ciaatod = p->ntscmode ? 2 : 1;
6686 	return configure_rom (p, roms, romcheck);
6687 }
bip_a4000t(struct uae_prefs * p,int config,int compa,int romcheck)6688 static int bip_a4000t (struct uae_prefs *p, int config, int compa, int romcheck)
6689 {
6690 
6691 	int roms[8];
6692 
6693 	roms[0] = 16;
6694 	roms[1] = 31;
6695 	roms[2] = 13;
6696 	roms[3] = -1;
6697 
6698 	p->bogomem_size = 0;
6699 	p->chipmem_size = 0x200000;
6700 	p->mbresmem_low_size = 8 * 1024 * 1024;
6701 	p->cpu_model = 68030;
6702 	p->fpu_model = 68882;
6703 	if (config > 0) {
6704 		p->cpu_model = 68040;
6705 		p->fpu_model = 68040;
6706 	}
6707 	p->chipset_mask = CSMASK_AGA | CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6708 	p->cpu_compatible = p->address_space_24 = 0;
6709 	p->m68k_speed = -1;
6710 	p->immediate_blits = 0;
6711 	p->produce_sound = 2;
6712 	p->cachesize = MAX_JIT_CACHE;
6713 	p->floppyslots[0].dfxtype = DRV_35_HD;
6714 	p->floppyslots[1].dfxtype = DRV_35_HD;
6715 	p->floppy_speed = 0;
6716 	p->cpu_idle = 150;
6717 	p->cs_compatible = CP_A4000T;
6718 	built_in_chipset_prefs (p);
6719 	p->cs_ciaatod = p->ntscmode ? 2 : 1;
6720 	return configure_rom (p, roms, romcheck);
6721 }
6722 
bip_velvet(struct uae_prefs * p,int config,int compa,int romcheck)6723 static void bip_velvet(struct uae_prefs *p, int config, int compa, int romcheck)
6724 {
6725 	p->chipset_mask = 0;
6726 	p->bogomem_size = 0;
6727 	p->sound_filter = FILTER_SOUND_ON;
6728 	set_68000_compa (p, compa);
6729 	p->floppyslots[1].dfxtype = DRV_NONE;
6730 	p->cs_compatible = CP_VELVET;
6731 	p->cs_slowmemisfast = 1;
6732 	p->cs_dipagnus = 1;
6733 	p->cs_agnusbltbusybug = 1;
6734 	built_in_chipset_prefs (p);
6735 	p->cs_denisenoehb = 1;
6736 	p->cs_cia6526 = 1;
6737 	p->chipmem_size = 0x40000;
6738 }
6739 
bip_a1000(struct uae_prefs * p,int config,int compa,int romcheck)6740 static int bip_a1000 (struct uae_prefs *p, int config, int compa, int romcheck)
6741 {
6742 	int roms[2];
6743 
6744 #ifdef FSUAE
6745 	roms[0] = 5;
6746 #else
6747 	roms[0] = 24;
6748 #endif
6749 	roms[1] = -1;
6750 	p->chipset_mask = 0;
6751 	p->bogomem_size = 0;
6752 	p->sound_filter = FILTER_SOUND_ON;
6753 	set_68000_compa (p, compa);
6754 	p->floppyslots[1].dfxtype = DRV_NONE;
6755 	p->cs_compatible = CP_A1000;
6756 	p->cs_slowmemisfast = 1;
6757 	p->cs_dipagnus = 1;
6758 	p->cs_agnusbltbusybug = 1;
6759 	built_in_chipset_prefs (p);
6760 	if (config > 0)
6761 		p->cs_denisenoehb = 1;
6762 	if (config > 1)
6763 		p->chipmem_size = 0x40000;
6764 	if (config > 2) {
6765 		roms[0] = 125;
6766 		roms[1] = -1;
6767 		bip_velvet(p, config, compa, romcheck);
6768 	}
6769 	return configure_rom (p, roms, romcheck);
6770 }
6771 
bip_cdtvcr(struct uae_prefs * p,int config,int compa,int romcheck)6772 static int bip_cdtvcr (struct uae_prefs *p, int config, int compa, int romcheck)
6773 {
6774 	int roms[4];
6775 
6776 	p->bogomem_size = 0;
6777 	p->chipmem_size = 0x100000;
6778 	p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6779 	p->cs_cdtvcd = p->cs_cdtvram = true;
6780 	p->cs_cdtvcr = true;
6781 	p->cs_rtc = 1;
6782 	p->nr_floppies = 0;
6783 	p->floppyslots[0].dfxtype = DRV_NONE;
6784 	if (config > 0)
6785 		p->floppyslots[0].dfxtype = DRV_35_DD;
6786 	p->floppyslots[1].dfxtype = DRV_NONE;
6787 	set_68000_compa (p, compa);
6788 	p->cs_compatible = CP_CDTVCR;
6789 	built_in_chipset_prefs (p);
6790 	fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR));
6791 	_tcscat (p->flashfile, _T("cdtv-cr.nvr"));
6792 	roms[0] = 9;
6793 	roms[1] = 10;
6794 	roms[2] = -1;
6795 	if (!configure_rom (p, roms, romcheck))
6796 		return 0;
6797 	roms[0] = 108;
6798 	roms[1] = 107;
6799 	roms[2] = -1;
6800 	if (!configure_rom (p, roms, romcheck))
6801 		return 0;
6802 	return 1;
6803 }
6804 
bip_cdtv(struct uae_prefs * p,int config,int compa,int romcheck)6805 static int bip_cdtv (struct uae_prefs *p, int config, int compa, int romcheck)
6806 {
6807 	int roms[4];
6808 
6809 	if (config >= 2)
6810 		return bip_cdtvcr(p, config - 2, compa, romcheck);
6811 
6812 	p->bogomem_size = 0;
6813 	p->chipmem_size = 0x100000;
6814 	p->chipset_mask = CSMASK_ECS_AGNUS;
6815 	p->cs_cdtvcd = p->cs_cdtvram = 1;
6816 	if (config > 0)
6817 		p->cs_cdtvcard = 64;
6818 	p->cs_rtc = 1;
6819 	p->nr_floppies = 0;
6820 	p->floppyslots[0].dfxtype = DRV_NONE;
6821 	if (config > 0)
6822 		p->floppyslots[0].dfxtype = DRV_35_DD;
6823 	p->floppyslots[1].dfxtype = DRV_NONE;
6824 	set_68000_compa (p, compa);
6825 	p->cs_compatible = CP_CDTV;
6826 	built_in_chipset_prefs (p);
6827 	fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR));
6828 	_tcscat (p->flashfile, _T("cdtv.nvr"));
6829 	roms[0] = 6;
6830 	roms[1] = 32;
6831 	roms[2] = -1;
6832 	if (!configure_rom (p, roms, romcheck))
6833 		return 0;
6834 	roms[0] = 20;
6835 	roms[1] = 21;
6836 	roms[2] = 22;
6837 	roms[3] = -1;
6838 	if (!configure_rom (p, roms, romcheck))
6839 		return 0;
6840 	return 1;
6841 }
6842 
bip_cd32(struct uae_prefs * p,int config,int compa,int romcheck)6843 static int bip_cd32 (struct uae_prefs *p, int config, int compa, int romcheck)
6844 {
6845 	int roms[3];
6846 
6847 	buildin_default_prefs_68020 (p);
6848 	p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = true;
6849 	p->nr_floppies = 0;
6850 	p->floppyslots[0].dfxtype = DRV_NONE;
6851 	p->floppyslots[1].dfxtype = DRV_NONE;
6852 	set_68020_compa (p, compa, 1);
6853 	p->cs_compatible = CP_CD32;
6854 	built_in_chipset_prefs (p);
6855 	fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR));
6856 	_tcscat (p->flashfile, _T("cd32.nvr"));
6857 	roms[0] = 64;
6858 	roms[1] = -1;
6859 	if (!configure_rom (p, roms, 0)) {
6860 		roms[0] = 18;
6861 		roms[1] = -1;
6862 		if (!configure_rom (p, roms, romcheck))
6863 			return 0;
6864 		roms[0] = 19;
6865 		if (!configure_rom (p, roms, romcheck))
6866 			return 0;
6867 	}
6868 	if (config > 0) {
6869 		p->cs_cd32fmv = true;
6870 		roms[0] = 74;
6871 		roms[1] = 23;
6872 		roms[2] = -1;
6873 		if (!configure_rom (p, roms, romcheck))
6874 			return 0;
6875 	}
6876 	return 1;
6877 }
6878 
bip_a1200(struct uae_prefs * p,int config,int compa,int romcheck)6879 static int bip_a1200 (struct uae_prefs *p, int config, int compa, int romcheck)
6880 {
6881 	int roms[4];
6882 	int roms_bliz[2];
6883 
6884 	buildin_default_prefs_68020 (p);
6885 	roms[0] = 11;
6886 	roms[1] = 15;
6887 	roms[2] = 31;
6888 	roms[3] = -1;
6889 #ifdef FSUAE
6890 	roms[1] = -1;
6891 #endif
6892 	roms_bliz[0] = -1;
6893 	roms_bliz[1] = -1;
6894 	p->cs_rtc = 0;
6895 	p->cs_compatible = CP_A1200;
6896 	built_in_chipset_prefs (p);
6897 	switch (config)
6898 	{
6899 		case 1:
6900 		p->fastmem_size = 0x400000;
6901 		p->cs_rtc = 1;
6902 		break;
6903 		case 2:
6904 		cpuboard_setboard(p, BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230IV);
6905 		p->cpuboardmem1_size = 32 * 1024 * 1024;
6906 		p->cpu_model = 68030;
6907 		p->cs_rtc = 1;
6908 		roms_bliz[0] = 89;
6909 		configure_rom(p, roms_bliz, romcheck);
6910 		break;
6911 		case 3:
6912 		cpuboard_setboard(p, BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1260);
6913 		p->cpuboardmem1_size = 32 * 1024 * 1024;
6914 		p->cpu_model = 68040;
6915 		p->fpu_model = 68040;
6916 		p->cs_rtc = 1;
6917 		roms_bliz[0] = 90;
6918 		configure_rom(p, roms_bliz, romcheck);
6919 		break;
6920 		case 4:
6921 		cpuboard_setboard(p, BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1260);
6922 		p->cpuboardmem1_size = 32 * 1024 * 1024;
6923 		p->cpu_model = 68060;
6924 		p->fpu_model = 68060;
6925 		p->cs_rtc = 1;
6926 		roms_bliz[0] = 90;
6927 		configure_rom(p, roms_bliz, romcheck);
6928 		break;
6929 		case 5:
6930 		cpuboard_setboard(p, BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_PPC);
6931 		p->cpuboardmem1_size = 256 * 1024 * 1024;
6932 		p->cpu_model = 68060;
6933 		p->fpu_model = 68060;
6934 		p->ppc_mode = 1;
6935 		p->cs_rtc = 1;
6936 		roms[0] = 15;
6937 		roms[1] = 11;
6938 		roms[2] = -1;
6939 		roms_bliz[0] = 100;
6940 		configure_rom(p, roms_bliz, romcheck);
6941 		break;
6942 #ifdef FSUAE
6943 		case 6:
6944 		roms[0] = 15;
6945 		roms[3] = -1;
6946 		break;
6947 #endif
6948 	}
6949 	set_68020_compa (p, compa, 0);
6950 	return configure_rom (p, roms, romcheck);
6951 }
6952 
bip_a600(struct uae_prefs * p,int config,int compa,int romcheck)6953 static int bip_a600 (struct uae_prefs *p, int config, int compa, int romcheck)
6954 {
6955 	int roms[4];
6956 
6957 	roms[0] = 10;
6958 	roms[1] = 9;
6959 	roms[2] = 8;
6960 	roms[3] = -1;
6961 	set_68000_compa (p, compa);
6962 	p->cs_compatible = CP_A600;
6963 	built_in_chipset_prefs (p);
6964 	p->bogomem_size = 0;
6965 	p->chipmem_size = 0x100000;
6966 	if (config > 0)
6967 		p->cs_rtc = 1;
6968 	if (config == 1)
6969 		p->chipmem_size = 0x200000;
6970 	if (config == 2)
6971 		p->fastmem_size = 0x400000;
6972 	p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6973 	return configure_rom (p, roms, romcheck);
6974 }
6975 
bip_a500p(struct uae_prefs * p,int config,int compa,int romcheck)6976 static int bip_a500p (struct uae_prefs *p, int config, int compa, int romcheck)
6977 {
6978 	int roms[2];
6979 
6980 	roms[0] = 7;
6981 	roms[1] = -1;
6982 	set_68000_compa (p, compa);
6983 	p->cs_compatible = CP_A500P;
6984 	built_in_chipset_prefs (p);
6985 	p->bogomem_size = 0;
6986 	p->chipmem_size = 0x100000;
6987 	if (config > 0)
6988 		p->cs_rtc = 1;
6989 	if (config == 1)
6990 		p->chipmem_size = 0x200000;
6991 	if (config == 2)
6992 		p->fastmem_size = 0x400000;
6993 	p->chipset_mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
6994 	return configure_rom (p, roms, romcheck);
6995 }
bip_a500(struct uae_prefs * p,int config,int compa,int romcheck)6996 static int bip_a500 (struct uae_prefs *p, int config, int compa, int romcheck)
6997 {
6998 	int roms[4];
6999 
7000 	roms[0] = roms[1] = roms[2] = roms[3] = -1;
7001 	switch (config)
7002 	{
7003 	case 0: // KS 1.3, OCS Agnus, 0.5M Chip + 0.5M Slow
7004 		roms[0] = 6;
7005 		roms[1] = 32;
7006 		p->chipset_mask = 0;
7007 		break;
7008 	case 1: // KS 1.3, ECS Agnus, 0.5M Chip + 0.5M Slow
7009 		roms[0] = 6;
7010 		roms[1] = 32;
7011 		break;
7012 	case 2: // KS 1.3, ECS Agnus, 1.0M Chip
7013 		roms[0] = 6;
7014 		roms[1] = 32;
7015 		p->bogomem_size = 0;
7016 		p->chipmem_size = 0x100000;
7017 		break;
7018 	case 3: // KS 1.3, OCS Agnus, 0.5M Chip
7019 		roms[0] = 6;
7020 		roms[1] = 32;
7021 		p->bogomem_size = 0;
7022 		p->chipset_mask = 0;
7023 		p->cs_rtc = 0;
7024 		p->floppyslots[1].dfxtype = DRV_NONE;
7025 		break;
7026 	case 4: // KS 1.2, OCS Agnus, 0.5M Chip
7027 		roms[0] = 5;
7028 		roms[1] = 4;
7029 		roms[2] = 3;
7030 		p->bogomem_size = 0;
7031 		p->chipset_mask = 0;
7032 		p->cs_rtc = 0;
7033 		p->floppyslots[1].dfxtype = DRV_NONE;
7034 		break;
7035 	case 5: // KS 1.2, OCS Agnus, 0.5M Chip + 0.5M Slow
7036 		roms[0] = 5;
7037 		roms[1] = 4;
7038 		roms[2] = 3;
7039 		p->chipset_mask = 0;
7040 		break;
7041 	}
7042 	set_68000_compa (p, compa);
7043 	p->cs_compatible = CP_A500;
7044 	built_in_chipset_prefs (p);
7045 	return configure_rom (p, roms, romcheck);
7046 }
7047 
bip_super(struct uae_prefs * p,int config,int compa,int romcheck)7048 static int bip_super (struct uae_prefs *p, int config, int compa, int romcheck)
7049 {
7050 	int roms[7];
7051 
7052 	roms[0] = 16;
7053 	roms[1] = 31;
7054 	roms[2] = 15;
7055 	roms[3] = 14;
7056 	roms[4] = 12;
7057 	roms[5] = 11;
7058 	roms[6] = -1;
7059 	p->bogomem_size = 0;
7060 	p->chipmem_size = 0x400000;
7061 	p->z3fastmem_size = 8 * 1024 * 1024;
7062 	p->rtgmem_size = 16 * 1024 * 1024;
7063 	p->cpu_model = 68040;
7064 	p->fpu_model = 68040;
7065 	p->chipset_mask = CSMASK_AGA | CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
7066 	p->cpu_compatible = p->address_space_24 = 0;
7067 	p->m68k_speed = -1;
7068 	p->immediate_blits = 1;
7069 	p->produce_sound = 2;
7070 	p->cachesize = MAX_JIT_CACHE;
7071 	p->floppyslots[0].dfxtype = DRV_35_HD;
7072 	p->floppyslots[1].dfxtype = DRV_35_HD;
7073 	p->floppy_speed = 0;
7074 	p->cpu_idle = 150;
7075 	p->scsi = 1;
7076 	p->uaeserial = 1;
7077 	p->socket_emu = 1;
7078 	p->cart_internal = 0;
7079 	p->picasso96_nocustom = 1;
7080 	p->cs_compatible = 1;
7081 	built_in_chipset_prefs (p);
7082 	p->cs_ide = -1;
7083 	p->cs_ciaatod = p->ntscmode ? 2 : 1;
7084 	//_tcscat(p->flashfile, _T("battclock.nvr"));
7085 	return configure_rom (p, roms, romcheck);
7086 }
7087 
bip_arcadia(struct uae_prefs * p,int config,int compa,int romcheck)7088 static int bip_arcadia (struct uae_prefs *p, int config, int compa, int romcheck)
7089 {
7090 	int roms[4], i;
7091 	struct romlist **rl;
7092 
7093 	p->bogomem_size = 0;
7094 	p->chipset_mask = 0;
7095 	p->cs_rtc = 0;
7096 	p->nr_floppies = 0;
7097 	p->floppyslots[0].dfxtype = DRV_NONE;
7098 	p->floppyslots[1].dfxtype = DRV_NONE;
7099 	set_68000_compa (p, compa);
7100 	p->cs_compatible = CP_A500;
7101 	built_in_chipset_prefs (p);
7102 	fetch_datapath (p->flashfile, sizeof (p->flashfile) / sizeof (TCHAR));
7103 	_tcscat (p->flashfile, _T("arcadia.nvr"));
7104 	roms[0] = 5;
7105 	roms[1] = 4;
7106 	roms[2] = -1;
7107 	if (!configure_rom (p, roms, romcheck))
7108 		return 0;
7109 	roms[0] = 51;
7110 	roms[1] = 49;
7111 	roms[2] = -1;
7112 	if (!configure_rom (p, roms, romcheck))
7113 		return 0;
7114 	rl = getarcadiaroms ();
7115 	for (i = 0; rl[i]; i++) {
7116 		if (config-- == 0) {
7117 			roms[0] = rl[i]->rd->id;
7118 			roms[1] = -1;
7119 			configure_rom (p, roms, 0);
7120 			break;
7121 		}
7122 	}
7123 	xfree (rl);
7124 	return 1;
7125 }
7126 
built_in_prefs(struct uae_prefs * p,int model,int config,int compa,int romcheck)7127 int built_in_prefs (struct uae_prefs *p, int model, int config, int compa, int romcheck)
7128 {
7129 	int v = 0;
7130 
7131 	buildin_default_prefs (p);
7132 	switch (model)
7133 	{
7134 	case 0:
7135 		v = bip_a500 (p, config, compa, romcheck);
7136 		break;
7137 	case 1:
7138 		v = bip_a500p (p, config, compa, romcheck);
7139 		break;
7140 	case 2:
7141 		v = bip_a600 (p, config, compa, romcheck);
7142 		break;
7143 	case 3:
7144 		v = bip_a1000 (p, config, compa, romcheck);
7145 		break;
7146 	case 4:
7147 		v = bip_a1200 (p, config, compa, romcheck);
7148 		break;
7149 	case 5:
7150 		v = bip_a3000 (p, config, compa, romcheck);
7151 		break;
7152 	case 6:
7153 		v = bip_a4000 (p, config, compa, romcheck);
7154 		break;
7155 	case 7:
7156 		v = bip_a4000t (p, config, compa, romcheck);
7157 		break;
7158 	case 8:
7159 		v = bip_cd32 (p, config, compa, romcheck);
7160 		break;
7161 	case 9:
7162 		v = bip_cdtv (p, config, compa, romcheck);
7163 		break;
7164 	case 10:
7165 		v = bip_arcadia (p, config , compa, romcheck);
7166 		break;
7167 	case 11:
7168 		v = bip_super (p, config, compa, romcheck);
7169 		break;
7170 	}
7171 	if ((p->cpu_model >= 68020 || !p->cpu_cycle_exact || !p->cpu_memory_cycle_exact) && !p->immediate_blits)
7172 		p->waiting_blits = 1;
7173 	if (p->sound_filter_type == FILTER_SOUND_TYPE_A500 && (p->chipset_mask & CSMASK_AGA))
7174 		p->sound_filter_type = FILTER_SOUND_TYPE_A1200;
7175 	else if (p->sound_filter_type == FILTER_SOUND_TYPE_A1200 && !(p->chipset_mask & CSMASK_AGA))
7176 		p->sound_filter_type = FILTER_SOUND_TYPE_A500;
7177 	if (p->cpu_model >= 68040)
7178 		p->cs_bytecustomwritebug = true;
7179 	return v;
7180 }
7181 
7182 #ifdef FSUAE
7183 /**
7184  * This function will be called (twice) by fixup_prefs after custom uae_
7185  * options have been applied, and may reset some (chipset) options overriden
7186  * by the user unless also uae_chipset_compatible has been set to -.
7187  */
7188 #endif
built_in_chipset_prefs(struct uae_prefs * p)7189 int built_in_chipset_prefs (struct uae_prefs *p)
7190 {
7191 #ifdef FSUAE
7192 	write_log("built_in_chipset_prefs, ignore = %d\n", !p->cs_compatible);
7193 #endif
7194 	if (!p->cs_compatible)
7195 		return 1;
7196 
7197 	p->cs_a1000ram = 0;
7198 	p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = 0;
7199 	p->cs_cdtvcd = p->cs_cdtvram = p->cs_cdtvscsi = p->cs_cdtvcr = 0;
7200 	p->cs_fatgaryrev = -1;
7201 	p->cs_ide = 0;
7202 	p->cs_ramseyrev = -1;
7203 	p->cs_deniserev = -1;
7204 	p->cs_agnusrev = -1;
7205 	p->cs_denisenoehb = 0;
7206 	p->cs_dipagnus = 0;
7207 	p->cs_agnusbltbusybug = 0;
7208 	p->cs_mbdmac = 0;
7209 	p->cs_pcmcia = 0;
7210 	p->cs_ksmirror_e0 = 1;
7211 	p->cs_ksmirror_a8 = 0;
7212 	p->cs_ciaoverlay = 1;
7213 	p->cs_ciaatod = 0;
7214 #ifdef FSUAE
7215 	/* Allow RTC to be set without disabling cs_compatible */
7216 #else
7217 	p->cs_rtc = 0;
7218 #endif
7219 	p->cs_rtc_adjust_mode = p->cs_rtc_adjust = 0;
7220 	p->cs_df0idhw = 1;
7221 	p->cs_resetwarning = 1;
7222 	p->cs_slowmemisfast = 0;
7223 	p->cs_ciatodbug = false;
7224 	p->cs_z3autoconfig = false;
7225 	p->cs_bytecustomwritebug = false;
7226 
7227 	switch (p->cs_compatible)
7228 	{
7229 	case CP_GENERIC: // generic
7230 		if (p->cpu_model >= 68020) {
7231 			// big box-like
7232 			p->cs_rtc = 2;
7233 			p->cs_fatgaryrev = 0;
7234 			p->cs_ide = -1;
7235 			p->cs_mbdmac = -1;
7236 			p->cs_ramseyrev = 0x0f;
7237 		} else if (p->cpu_compatible) {
7238 			// very A500-like
7239 			p->cs_df0idhw = 0;
7240 			p->cs_resetwarning = 0;
7241 			if (p->bogomem_size || p->chipmem_size > 0x80000 || p->fastmem_size)
7242 				p->cs_rtc = 1;
7243 			p->cs_ciatodbug = true;
7244 		} else {
7245 			// sort of A500-like
7246 			p->cs_ide = -1;
7247 			p->cs_rtc = 1;
7248 		}
7249 		break;
7250 	case CP_CDTV: // CDTV
7251 		p->cs_rtc = 1;
7252 		p->cs_cdtvcd = p->cs_cdtvram = 1;
7253 		p->cs_df0idhw = 1;
7254 		p->cs_ksmirror_e0 = 0;
7255 		break;
7256 	case CP_CDTVCR: // CDTV-CR
7257 		p->cs_rtc = 1;
7258 		p->cs_cdtvcd = p->cs_cdtvram = 1;
7259 		p->cs_cdtvcr = true;
7260 		p->cs_df0idhw = 1;
7261 		p->cs_ksmirror_e0 = 0;
7262 		p->cs_ide = IDE_A600A1200;
7263 		p->cs_pcmcia = 1;
7264 		p->cs_ksmirror_a8 = 1;
7265 		p->cs_ciaoverlay = 0;
7266 		p->cs_resetwarning = 0;
7267 		p->cs_ciatodbug = true;
7268 		break;
7269 	case CP_CD32: // CD32
7270 		p->cs_cd32c2p = p->cs_cd32cd = p->cs_cd32nvram = true;
7271 		p->cs_ksmirror_e0 = 0;
7272 		p->cs_ksmirror_a8 = 1;
7273 		p->cs_ciaoverlay = 0;
7274 		p->cs_resetwarning = 0;
7275 		break;
7276 	case CP_A500: // A500
7277 		p->cs_df0idhw = 0;
7278 		p->cs_resetwarning = 0;
7279 		if (p->bogomem_size || p->chipmem_size > 0x80000 || p->fastmem_size)
7280 			p->cs_rtc = 1;
7281 		p->cs_ciatodbug = true;
7282 		break;
7283 	case CP_A500P: // A500+
7284 		p->cs_rtc = 1;
7285 		p->cs_resetwarning = 0;
7286 		p->cs_ciatodbug = true;
7287 		break;
7288 	case CP_A600: // A600
7289 #ifdef FSUAE
7290 		if (p->chipmem_size > 0x100000 || p->fastmem_size)
7291 			p->cs_rtc = 1;
7292 #endif
7293 		p->cs_ide = IDE_A600A1200;
7294 		p->cs_pcmcia = 1;
7295 		p->cs_ksmirror_a8 = 1;
7296 		p->cs_ciaoverlay = 0;
7297 		p->cs_resetwarning = 0;
7298 		p->cs_ciatodbug = true;
7299 		break;
7300 	case CP_A1000: // A1000
7301 		p->cs_a1000ram = 1;
7302 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
7303 		p->cs_ksmirror_e0 = 0;
7304 		p->cs_agnusbltbusybug = 1;
7305 		p->cs_dipagnus = 1;
7306 		p->cs_ciatodbug = true;
7307 		break;
7308 	case CP_VELVET: // A1000 Prototype
7309 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
7310 		p->cs_ksmirror_e0 = 0;
7311 		p->cs_agnusbltbusybug = 1;
7312 		p->cs_dipagnus = 1;
7313 		p->cs_denisenoehb = 1;
7314 		break;
7315 	case CP_A1200: // A1200
7316 		p->cs_ide = IDE_A600A1200;
7317 		p->cs_pcmcia = 1;
7318 		p->cs_ksmirror_a8 = 1;
7319 		p->cs_ciaoverlay = 0;
7320 		if (p->fastmem_size || p->z3fastmem_size || p->cpuboard_type)
7321 			p->cs_rtc = 1;
7322 		break;
7323 	case CP_A2000: // A2000
7324 		p->cs_rtc = 1;
7325 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
7326 		p->cs_ciatodbug = true;
7327 		break;
7328 	case CP_A3000: // A3000
7329 		p->cs_rtc = 2;
7330 		p->cs_fatgaryrev = 0;
7331 		p->cs_ramseyrev = 0x0d;
7332 		p->cs_mbdmac = 1;
7333 		p->cs_ksmirror_e0 = 0;
7334 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
7335 		p->cs_z3autoconfig = true;
7336 		break;
7337 	case CP_A3000T: // A3000T
7338 		p->cs_rtc = 2;
7339 		p->cs_fatgaryrev = 0;
7340 		p->cs_ramseyrev = 0x0d;
7341 		p->cs_mbdmac = 1;
7342 		p->cs_ksmirror_e0 = 0;
7343 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
7344 		p->cs_z3autoconfig = true;
7345 		break;
7346 	case CP_A4000: // A4000
7347 		p->cs_rtc = 2;
7348 		p->cs_fatgaryrev = 0;
7349 		p->cs_ramseyrev = 0x0f;
7350 		p->cs_ide = IDE_A4000;
7351 		p->cs_mbdmac = 0;
7352 		p->cs_ksmirror_a8 = 0;
7353 		p->cs_ksmirror_e0 = 0;
7354 		p->cs_ciaoverlay = 0;
7355 		p->cs_z3autoconfig = true;
7356 		break;
7357 	case CP_A4000T: // A4000T
7358 		p->cs_rtc = 2;
7359 		p->cs_fatgaryrev = 0;
7360 		p->cs_ramseyrev = 0x0f;
7361 		p->cs_ide = IDE_A4000;
7362 		p->cs_mbdmac = 2;
7363 		p->cs_ksmirror_a8 = 0;
7364 		p->cs_ksmirror_e0 = 0;
7365 		p->cs_ciaoverlay = 0;
7366 		p->cs_z3autoconfig = true;
7367 		break;
7368 	}
7369 	if (p->cpu_model >= 68040)
7370 		p->cs_bytecustomwritebug = true;
7371 	return 1;
7372 }
7373 
built_in_cpuboard_prefs(struct uae_prefs * p)7374 int built_in_cpuboard_prefs(struct uae_prefs *p)
7375 {
7376 	int roms[2], roms2[2];
7377 
7378 	roms[0] = -1;
7379 	roms[1] = -1;
7380 	roms2[0] = -1;
7381 	roms2[1] = -1;
7382 
7383 	switch(cpuboards[p->cpuboard_type].id)
7384 	{
7385 		case BOARD_MACROSYSTEM:
7386 		switch(p->cpuboard_subtype)
7387 		{
7388 			case BOARD_MACROSYSTEM_SUB_WARPENGINE_A4000:
7389 			roms[0] = 93;
7390 			break;
7391 		}
7392 		break;
7393 		case BOARD_BLIZZARD:
7394 		switch(p->cpuboard_subtype)
7395 		{
7396 		case BOARD_BLIZZARD_SUB_1230IV:
7397 			roms[0] = 89;
7398 			break;
7399 		case BOARD_BLIZZARD_SUB_1260:
7400 			roms[0] = 90;
7401 			break;
7402 		case BOARD_BLIZZARD_SUB_2060:
7403 			roms[0] = 92;
7404 			break;
7405 		case BOARD_BLIZZARD_SUB_PPC:
7406 			roms[0] = p->cpu_model == 68040 ? 99 : 100;
7407 			break;
7408 		}
7409 		break;
7410 		case BOARD_CYBERSTORM:
7411 		switch(p->cpuboard_subtype)
7412 		{
7413 		case BOARD_CYBERSTORM_SUB_MK1:
7414 			roms[0] = p->cpu_model == 68040 ? 95 : 101;
7415 			break;
7416 		case BOARD_CYBERSTORM_SUB_MK2:
7417 			roms[0] = 96;
7418 			break;
7419 		case BOARD_CYBERSTORM_SUB_MK3:
7420 			roms[0] = 97;
7421 			break;
7422 		case BOARD_CYBERSTORM_SUB_PPC:
7423 			roms[0] = 98;
7424 			break;
7425 		}
7426 		break;
7427 	}
7428 	if (!configure_rom(p, roms, 0))
7429 		return 0;
7430 	if (!configure_rom(p, roms2, 0))
7431 		return 0;
7432 	return 1;
7433 }
7434 
set_config_changed(void)7435 void set_config_changed (void)
7436 {
7437 	config_changed = 1;
7438 }
7439 
config_check_vsync(void)7440 void config_check_vsync (void)
7441 {
7442 	if (config_changed) {
7443 #ifdef WITH_LUA
7444 		if (config_changed == 1) {
7445 			createconfigstore (&currprefs);
7446 			uae_lua_run_handler ("on_uae_config_changed");
7447 		}
7448 #endif
7449 		config_changed++;
7450 		if (config_changed >= 3)
7451 			config_changed = 0;
7452 	}
7453 }
7454 
is_error_log(void)7455 bool is_error_log (void)
7456 {
7457 	return error_lines != NULL;
7458 }
get_error_log(void)7459 TCHAR *get_error_log (void)
7460 {
7461 	strlist *sl;
7462 	int len = 0;
7463 	for (sl = error_lines; sl; sl = sl->next) {
7464 		len += _tcslen (sl->option) + 1;
7465 	}
7466 	if (!len)
7467 		return NULL;
7468 	TCHAR *s = xcalloc (TCHAR, len + 1);
7469 	for (sl = error_lines; sl; sl = sl->next) {
7470 		_tcscat (s, sl->option);
7471 		_tcscat (s, _T("\n"));
7472 	}
7473 	return s;
7474 }
error_log(const TCHAR * format,...)7475 void error_log (const TCHAR *format, ...)
7476 {
7477 	TCHAR buffer[256], *bufp;
7478 	int bufsize = 256;
7479 	va_list parms;
7480 
7481 	if (format == NULL) {
7482 		struct strlist **ps = &error_lines;
7483 		while (*ps) {
7484 			struct strlist *s = *ps;
7485 			*ps = s->next;
7486 			xfree (s->value);
7487 			xfree (s->option);
7488 			xfree (s);
7489 		}
7490 		return;
7491 	}
7492 
7493 	va_start (parms, format);
7494 	bufp = buffer;
7495 	for (;;) {
7496 		int count = _vsntprintf (bufp, bufsize - 1, format, parms);
7497 		if (count < 0) {
7498 			bufsize *= 10;
7499 			if (bufp != buffer)
7500 				xfree (bufp);
7501 			bufp = xmalloc (TCHAR, bufsize);
7502 			continue;
7503 		}
7504 		break;
7505 	}
7506 	bufp[bufsize - 1] = 0;
7507 	write_log (_T("%s\n"), bufp);
7508 	va_end (parms);
7509 
7510 	strlist *u = xcalloc (struct strlist, 1);
7511 	u->option = my_strdup (bufp);
7512 	u->next = error_lines;
7513 	error_lines = u;
7514 
7515 #ifdef FSUAE // NL
7516 	gui_message("%s", bufp);
7517 #endif
7518 
7519 	if (bufp != buffer)
7520 		xfree (bufp);
7521 }
7522