1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * Main program
5  *
6  * Copyright 1995 Ed Hanway
7  * Copyright 1995, 1996, 1997 Bernd Schmidt
8  * Copyright 2006-2007 Richard Drummond
9  * Copyright 2010 Mustafa Tufan
10  */
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 #include <assert.h>
14 #include <wchar.h>
15 
16 #include "cfgfile.h"
17 #include "threaddep/thread.h"
18 #include "uae.h"
19 #include "gensound.h"
20 #include "audio.h"
21 #include "sounddep/sound.h"
22 #include "events.h"
23 #include "memory_uae.h"
24 #include "custom.h"
25 #include "serial.h"
26 #include "newcpu.h"
27 #include "disk.h"
28 #include "debug.h"
29 #include "xwin.h"
30 #include "inputdevice.h"
31 #include "keybuf.h"
32 #include "gui.h"
33 #include "autoconf.h"
34 #include "traps.h"
35 #include "osemu.h"
36 #include "picasso96.h"
37 #include "bsdsocket.h"
38 #include "uaeexe.h"
39 #include "native2amiga.h"
40 #include "scsidev.h"
41 #include "uaeserial.h"
42 #include "akiko.h"
43 #include "cdtv.h"
44 #include "savestate.h"
45 #include "filesys.h"
46 #include "parallel.h"
47 #include "a2091.h"
48 #include "a2065.h"
49 #include "ncr_scsi.h"
50 #include "scsi.h"
51 #include "sana2.h"
52 #include "blkdev.h"
53 #include "gfxfilter.h"
54 #include "uaeresource.h"
55 #include "dongle.h"
56 #include "sampler.h"
57 #include "consolehook.h"
58 #include "gayle.h"
59 #include "misc.h"
60 #include "keyboard.h"
61 #ifdef RETROPLATFORM
62 #include "rp.h"
63 #endif
64 #ifdef USE_SDL
65 #include "SDL.h"
66 #endif
67 
68 /* internal prototypes */
69 uae_u32 uaerand (void);
70 uae_u32 uaesrand (uae_u32 seed);
71 uae_u32 uaerandgetseed (void);
72 void my_trim (TCHAR *s);
73 TCHAR *my_strdup_trim (const TCHAR *s);
74 
75 /* internal members */
76 long int version = 256 * 65536L * UAEMAJOR + 65536L * UAEMINOR + UAESUBREV;
77 
78 struct uae_prefs currprefs, changed_prefs;
79 int config_changed;
80 
81 int pissoff_value = 15000 * CYCLE_UNIT;
82 int pause_emulation;
83 char start_path_data[MAX_DPATH];
84 bool no_gui = 0, quit_to_gui = 0;
85 bool cloanto_rom = 0;
86 bool kickstart_rom = 1;
87 bool console_emulation = 0;
88 
89 struct gui_info gui_data;
90 
91 TCHAR warning_buffer[256];
92 
93 TCHAR optionsfile[256];
94 
95 static unsigned long randseed;
96 static unsigned long oldhcounter;
97 
98 #ifndef _WIN32
99 // Prototype in sysdeps.h
GetLastError(void)100 DWORD GetLastError(void)
101 {
102 	return errno;
103 }
104 #endif
105 
hr(void)106 static void hr (void)
107 {
108 	write_log (_T("------------------------------------------------------------------------------------\n"));
109 }
110 
show_version(void)111 static void show_version (void)
112 {
113 	write_log (_T("P-UAE %d.%d.%d\n"), UAEMAJOR, UAEMINOR, UAESUBREV);
114 	write_log (_T("Git Commit: %s\n"), PACKAGE_COMMIT);
115 	write_log (_T("Build date: " __DATE__ " " __TIME__ "\n"));
116 }
117 
show_version_full(void)118 static void show_version_full (void)
119 {
120 	hr ();
121 	show_version ();
122 	hr ();
123 	write_log (_T("Copyright 1995-2002 Bernd Schmidt\n"));
124 	write_log (_T("          1999-2013 Toni Wilen\n"));
125 	write_log (_T("          2003-2007 Richard Drummond\n"));
126 	write_log (_T("          2006-2013 Mustafa 'GnoStiC' Tufan\n\n"));
127 	write_log (_T("See the source for a full list of contributors.\n"));
128 	write_log (_T("This is free software; see the file COPYING for copying conditions.  There is NO\n"));
129 	write_log (_T("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
130 	hr ();
131 }
132 
uaesrand(uae_u32 seed)133 uae_u32 uaesrand (uae_u32 seed)
134 {
135 	oldhcounter = -1;
136 	randseed = seed;
137 	//randseed = 0x12345678;
138 	//write_log (_T("seed=%08x\n"), randseed);
139 	return randseed;
140 }
141 
uaerand(void)142 uae_u32 uaerand (void)
143 {
144 	if (oldhcounter != hsync_counter) {
145 		srand (hsync_counter ^ randseed);
146 		oldhcounter = hsync_counter;
147 	}
148 	uae_u32 r = rand ();
149 	//write_log (_T("rand=%08x\n"), r);
150 	return r;
151 }
152 
uaerandgetseed(void)153 uae_u32 uaerandgetseed (void)
154 {
155 	return randseed;
156 }
157 
my_trim(TCHAR * s)158  void my_trim (TCHAR *s)
159 {
160 	int len;
161 	while (_tcscspn (s, _T("\t \r\n")) == 0)
162 		memmove (s, s + 1, (_tcslen (s + 1) + 1) * sizeof (TCHAR));
163 	len = _tcslen (s);
164 	while (len > 0 && _tcscspn (s + len - 1, _T("\t \r\n")) == 0)
165 		s[--len] = '\0';
166 }
167 
my_strdup_trim(const TCHAR * s)168 TCHAR *my_strdup_trim (const TCHAR *s)
169 {
170 	TCHAR *out;
171 	int len;
172 
173 	while (_tcscspn (s, _T("\t \r\n")) == 0)
174 		s++;
175 	len = _tcslen (s);
176 	while (len > 0 && _tcscspn (s + len - 1, _T("\t \r\n")) == 0)
177 		len--;
178 	out = xmalloc (TCHAR, len + 1);
179 	memcpy (out, s, len * sizeof (TCHAR));
180 	out[len] = 0;
181 	return out;
182 }
183 
discard_prefs(struct uae_prefs * p,int type)184 void discard_prefs (struct uae_prefs *p, int type)
185 {
186 	struct strlist **ps = &p->all_lines;
187 	while (*ps) {
188 		struct strlist *s = *ps;
189 		*ps = s->next;
190 		xfree (s->value);
191 		xfree (s->option);
192 		xfree (s);
193 	}
194 #ifdef FILESYS
195 	filesys_cleanup ();
196 #endif
197 }
198 
fixup_prefs_dim2(struct wh * wh)199 static void fixup_prefs_dim2 (struct wh *wh)
200 {
201 	if (wh->width < 160)
202 		wh->width = 160;
203 	if (wh->height < 128)
204 		wh->height = 128;
205 	if (wh->width > MAX_UAE_WIDTH)
206 		wh->width = MAX_UAE_WIDTH;
207 	if (wh->height > MAX_UAE_HEIGHT)
208 		wh->height = MAX_UAE_HEIGHT;
209 }
210 
fixup_prefs_dimensions(struct uae_prefs * prefs)211 void fixup_prefs_dimensions (struct uae_prefs *prefs)
212 {
213 	fixup_prefs_dim2 (&prefs->gfx_size_fs);
214 	fixup_prefs_dim2 (&prefs->gfx_size_win);
215 	if (prefs->gfx_apmode[1].gfx_vsync)
216 		prefs->gfx_apmode[1].gfx_vsyncmode = 1;
217 
218 	for (int i = 0; i < 2; i++) {
219 		struct apmode *ap = &prefs->gfx_apmode[i];
220 		ap->gfx_vflip = 0;
221 		ap->gfx_strobo = false;
222 		if (ap->gfx_vsync) {
223 			if (ap->gfx_vsyncmode) {
224 				// low latency vsync: no flip only if no-buffer
225 				if (ap->gfx_backbuffers >= 1)
226 					ap->gfx_vflip = 1;
227 				if (!i && ap->gfx_backbuffers == 2)
228 					ap->gfx_vflip = 1;
229 				ap->gfx_strobo = prefs->lightboost_strobo;
230 			} else {
231 				// legacy vsync: always wait for flip
232 				ap->gfx_vflip = -1;
233 				if (prefs->gfx_api && ap->gfx_backbuffers < 1)
234 					ap->gfx_backbuffers = 1;
235 				if (ap->gfx_vflip)
236 					ap->gfx_strobo = prefs->lightboost_strobo;;
237 			}
238 		} else {
239 			// no vsync: wait if triple bufferirng
240 			if (ap->gfx_backbuffers >= 2)
241 				ap->gfx_vflip = -1;
242 		}
243 	}
244 
245 	if (prefs->gfx_filter == 0 && ((prefs->gfx_filter_autoscale && !prefs->gfx_api) || (prefs->gfx_apmode[0].gfx_vsyncmode)))
246 		prefs->gfx_filter = 1;
247 	if (prefs->gfx_filter == 0 && prefs->monitoremu)
248 		prefs->gfx_filter = 1;
249 }
250 
fixup_cpu(struct uae_prefs * p)251 void fixup_cpu (struct uae_prefs *p)
252 {
253 	if (p->cpu_frequency == 1000000)
254 		p->cpu_frequency = 0;
255 	switch (p->cpu_model)
256 	{
257 	case 68000:
258 		p->address_space_24 = 1;
259 		if (p->cpu_compatible || p->cpu_cycle_exact)
260 			p->fpu_model = 0;
261 		break;
262 	case 68010:
263 		p->address_space_24 = 1;
264 		if (p->cpu_compatible || p->cpu_cycle_exact)
265 			p->fpu_model = 0;
266 		break;
267 	case 68020:
268 		break;
269 	case 68030:
270 		p->address_space_24 = 0;
271 		break;
272 	case 68040:
273 		p->address_space_24 = 0;
274 		if (p->fpu_model)
275 			p->fpu_model = 68040;
276 		break;
277 	case 68060:
278 		p->address_space_24 = 0;
279 		if (p->fpu_model)
280 			p->fpu_model = 68060;
281 		break;
282 	}
283 
284 	if (p->cpu_model >= 68040 && p->cachesize && p->cpu_compatible)
285 		p->cpu_compatible = false;
286 
287 	if (p->cpu_model < 68030 || p->cachesize)
288 		p->mmu_model = 0;
289 
290 	if (p->cachesize && p->cpu_cycle_exact)
291 		p->cachesize = 0;
292 
293 	if (p->cpu_cycle_exact && p->m68k_speed < 0)
294 		p->m68k_speed = 0;
295 
296 	if (p->immediate_blits && p->blitter_cycle_exact)
297 		p->immediate_blits = false;
298 	if (p->immediate_blits && p->waiting_blits)
299 		p->waiting_blits = 0;
300 }
301 
302 
303 
fixup_prefs(struct uae_prefs * p)304 void fixup_prefs (struct uae_prefs *p)
305 {
306 /** FIXME:
307   * There must be a way to a) have a sane max_z3fastmem value
308   * without NATMEM being used and b) a way to use fastmem and
309   * rtg mem without crashing 64bit linux systems.
310 **/
311 #ifndef NATMEM_OFFSET
312 	max_z3fastmem = 0;
313 #endif // NATMEM_OFFSET
314 
315 	int err = 0;
316 
317 	built_in_chipset_prefs (p);
318 	fixup_cpu (p);
319 
320 	if (((p->chipmem_size & (p->chipmem_size - 1)) != 0 && p->chipmem_size != 0x180000)
321 		|| p->chipmem_size < 0x20000
322 		|| p->chipmem_size > 0x800000)
323 	{
324 		write_log (_T("Unsupported chipmem size %x!\n"), p->chipmem_size);
325 		p->chipmem_size = 0x200000;
326 		err = 1;
327 	}
328 	if ((p->fastmem_size & (p->fastmem_size - 1)) != 0
329 		|| (p->fastmem_size != 0 && (p->fastmem_size < 0x100000 || p->fastmem_size > 0x800000)))
330 	{
331 		write_log (_T("Unsupported fastmem size %x!\n"), p->fastmem_size);
332 		err = 1;
333 	}
334 	if ((p->rtgmem_size & (p->rtgmem_size - 1)) != 0
335 		|| (p->rtgmem_size != 0 && (p->rtgmem_size < 0x100000 || p->rtgmem_size > max_z3fastmem)))
336 	{
337 		write_log (_T("Unsupported graphics card memory size %x (%x)!\n"), p->rtgmem_size, max_z3fastmem);
338 		if (p->rtgmem_size > max_z3fastmem)
339 			p->rtgmem_size = max_z3fastmem;
340 		else
341 			p->rtgmem_size = 0;
342 		err = 1;
343 	}
344 
345 	if ((p->z3fastmem_size & (p->z3fastmem_size - 1)) != 0
346 		|| (p->z3fastmem_size != 0 && (p->z3fastmem_size < 0x100000 || p->z3fastmem_size > max_z3fastmem)))
347 	{
348 		write_log (_T("Unsupported Zorro III fastmem size %x (%x)!\n"), p->z3fastmem_size, max_z3fastmem);
349 		if (p->z3fastmem_size > max_z3fastmem)
350 			p->z3fastmem_size = max_z3fastmem;
351 		else
352 			p->z3fastmem_size = 0;
353 		err = 1;
354 	}
355 	if ((p->z3fastmem2_size & (p->z3fastmem2_size - 1)) != 0
356 		|| (p->z3fastmem2_size != 0 && (p->z3fastmem2_size < 0x100000 || p->z3fastmem2_size > max_z3fastmem)))
357 	{
358 		write_log (_T("Unsupported Zorro III fastmem size %x (%x)!\n"), p->z3fastmem2_size, max_z3fastmem);
359 		if (p->z3fastmem2_size > max_z3fastmem)
360 			p->z3fastmem2_size = max_z3fastmem;
361 		else
362 			p->z3fastmem2_size = 0;
363 		err = 1;
364 	}
365 	p->z3fastmem_start &= ~0xffff;
366 	if (p->z3fastmem_start < 0x1000000)
367 		p->z3fastmem_start = 0x1000000;
368 	if ((p->z3chipmem_size & (p->z3chipmem_size - 1)) != 0
369 		|| (p->z3chipmem_size != 0 && (p->z3chipmem_size < 0x100000 || p->z3chipmem_size > max_z3fastmem)))
370 	{
371 		write_log (_T("Unsupported Zorro III fake chipmem size %x (%x)!\n"), p->z3chipmem_size, max_z3fastmem);
372 		if (p->z3chipmem_size > max_z3fastmem)
373 			p->z3chipmem_size = max_z3fastmem;
374 		else
375 			p->z3chipmem_size = 0;
376 		err = 1;
377 	}
378 
379 	if (p->address_space_24 && (p->z3fastmem_size != 0 || p->z3fastmem2_size != 0 || p->z3chipmem_size != 0)) {
380 		p->z3fastmem_size = p->z3fastmem2_size = p->z3chipmem_size = 0;
381 		write_log (_T("Can't use a graphics card or 32-bit memory when using a 24 bit\naddress space.\n"));
382 	}
383 	if (p->bogomem_size != 0 && p->bogomem_size != 0x80000 && p->bogomem_size != 0x100000 && p->bogomem_size != 0x180000 && p->bogomem_size != 0x1c0000) {
384 		p->bogomem_size = 0;
385 		write_log (_T("Unsupported bogomem size!\n"));
386 		err = 1;
387 	}
388 	if (p->bogomem_size > 0x180000 && (p->cs_fatgaryrev >= 0 || p->cs_ide || p->cs_ramseyrev >= 0)) {
389 		p->bogomem_size = 0x180000;
390 		write_log (_T("Possible Gayle bogomem conflict fixed\n"));
391 	}
392 	if (p->chipmem_size > 0x200000 && p->fastmem_size != 0) {
393 		write_log (_T("You can't use fastmem and more than 2MB chip at the same time!\n"));
394 		p->fastmem_size = 0;
395 		err = 1;
396 	}
397 	if (p->mbresmem_low_size > 0x04000000 || (p->mbresmem_low_size & 0xfffff)) {
398 		p->mbresmem_low_size = 0;
399 		write_log (_T("Unsupported A3000 MB RAM size\n"));
400 	}
401 	if (p->mbresmem_high_size > 0x04000000 || (p->mbresmem_high_size & 0xfffff)) {
402 		p->mbresmem_high_size = 0;
403 		write_log (_T("Unsupported Motherboard RAM size\n"));
404 	}
405 
406 	if (p->address_space_24 && p->rtgmem_size)
407 		p->rtgmem_type = 0;
408 	if (!p->rtgmem_type && (p->chipmem_size > 2 * 1024 * 1024 || getz2size (p) > 8 * 1024 * 1024 || getz2size (p) < 0)) {
409 		p->rtgmem_size = 0;
410 		write_log (_T("Too large Z2 RTG memory size\n"));
411 	}
412 
413 
414 #if 0
415 	if (p->m68k_speed < -1 || p->m68k_speed > 20) {
416 		write_log (_T("Bad value for -w parameter: must be -1, 0, or within 1..20.\n"));
417 		p->m68k_speed = 4;
418 		err = 1;
419 	}
420 #endif
421 
422 	if (p->produce_sound < 0 || p->produce_sound > 3) {
423 		write_log (_T("Bad value for -S parameter: enable value must be within 0..3\n"));
424 		p->produce_sound = 0;
425 		err = 1;
426 	}
427 #ifdef JIT
428 	if (p->comptrustbyte < 0 || p->comptrustbyte > 3) {
429 		write_log (_T("Bad value for comptrustbyte parameter: value must be within 0..2\n"));
430 		p->comptrustbyte = 1;
431 		err = 1;
432 	}
433 	if (p->comptrustword < 0 || p->comptrustword > 3) {
434 		write_log (_T("Bad value for comptrustword parameter: value must be within 0..2\n"));
435 		p->comptrustword = 1;
436 		err = 1;
437 	}
438 	if (p->comptrustlong < 0 || p->comptrustlong > 3) {
439 		write_log (_T("Bad value for comptrustlong parameter: value must be within 0..2\n"));
440 		p->comptrustlong = 1;
441 		err = 1;
442 	}
443 	if (p->comptrustnaddr < 0 || p->comptrustnaddr > 3) {
444 		write_log (_T("Bad value for comptrustnaddr parameter: value must be within 0..2\n"));
445 		p->comptrustnaddr = 1;
446 		err = 1;
447 	}
448 	if (p->cachesize < 0 || p->cachesize > 16384) {
449 		write_log (_T("Bad value for cachesize parameter: value must be within 0..16384\n"));
450 		p->cachesize = 0;
451 		err = 1;
452 	}
453 #endif
454 	if (p->z3fastmem_size > 0 && (p->address_space_24 || p->cpu_model < 68020)) {
455 		write_log (_T("Z3 fast memory can't be used with a 68000/68010 emulation. It\n"));
456 		write_log (_T("requires a 68020 emulation. Turning off Z3 fast memory.\n"));
457 		p->z3fastmem_size = 0;
458 		err = 1;
459 	}
460 	if (p->rtgmem_size > 0 && p->rtgmem_type && (p->cpu_model < 68020 || p->address_space_24)) {
461 		write_log (_T("RTG can't be used with a 68000/68010 or 68EC020 emulation. It\n"));
462 		write_log (_T("requires a 68020 emulation. Turning off RTG.\n"));
463 		p->rtgmem_size = 0;
464 		err = 1;
465 	}
466 #if !defined (BSDSOCKET)
467 	if (p->socket_emu) {
468 		write_log (_T("Compile-time option of BSDSOCKET_SUPPORTED was not enabled.  You can't use bsd-socket emulation.\n"));
469 		p->socket_emu = 0;
470 		err = 1;
471 	}
472 #endif
473 
474 	if (p->nr_floppies < 0 || p->nr_floppies > 4) {
475 		write_log (_T("Invalid number of floppies.  Using 4.\n"));
476 		p->nr_floppies = 4;
477 		p->floppyslots[0].dfxtype = 0;
478 		p->floppyslots[1].dfxtype = 0;
479 		p->floppyslots[2].dfxtype = 0;
480 		p->floppyslots[3].dfxtype = 0;
481 		err = 1;
482 	}
483 	if (p->floppy_speed > 0 && p->floppy_speed < 10) {
484 		p->floppy_speed = 100;
485 	}
486 	if (p->input_mouse_speed < 1 || p->input_mouse_speed > 1000) {
487 		p->input_mouse_speed = 100;
488 	}
489 	if (p->collision_level < 0 || p->collision_level > 3) {
490 		write_log (_T("Invalid collision support level.  Using 1.\n"));
491 		p->collision_level = 1;
492 		err = 1;
493 	}
494 	if (p->parallel_postscript_emulation)
495 		p->parallel_postscript_detection = 1;
496 	if (p->cs_compatible == 1) {
497 		p->cs_fatgaryrev = p->cs_ramseyrev = p->cs_mbdmac = -1;
498 		p->cs_ide = 0;
499 		if (p->cpu_model >= 68020) {
500 			p->cs_fatgaryrev = 0;
501 			p->cs_ide = -1;
502 			p->cs_ramseyrev = 0x0f;
503 			p->cs_mbdmac = 0;
504 		}
505 	} else if (p->cs_compatible == 0) {
506 		if (p->cs_ide == IDE_A4000) {
507 			if (p->cs_fatgaryrev < 0)
508 				p->cs_fatgaryrev = 0;
509 			if (p->cs_ramseyrev < 0)
510 				p->cs_ramseyrev = 0x0f;
511 		}
512 	}
513 	/* Can't fit genlock and A2024 or Graffiti at the same time,
514 	 * also Graffiti uses genlock audio bit as an enable signal
515 	 */
516 	if (p->genlock && p->monitoremu)
517 		p->genlock = false;
518 
519 
520 	fixup_prefs_dimensions (p);
521 
522 #if !defined (JIT)
523 	p->cachesize = 0;
524 #endif
525 #ifdef CPU_68000_ONLY
526 	p->cpu_model = 68000;
527 	p->fpu_model = 0;
528 #endif
529 #ifndef CPUEMU_0
530 	p->cpu_compatible = 1;
531 	p->address_space_24 = 1;
532 #endif
533 #if !defined (CPUEMU_11) && !defined (CPUEMU_12)
534 	p->cpu_compatible = 0;
535 	p->address_space_24 = 0;
536 #endif
537 #if !defined (CPUEMU_12)
538 	p->cpu_cycle_exact = p->blitter_cycle_exact = 0;
539 #endif
540 #ifndef AGA
541 	p->chipset_mask &= ~CSMASK_AGA;
542 #endif
543 #ifndef AUTOCONFIG
544 	p->z3fastmem_size = 0;
545 	p->fastmem_size = 0;
546 	p->rtgmem_size = 0;
547 #endif
548 #if !defined (BSDSOCKET)
549 	p->socket_emu = 0;
550 #endif
551 #if !defined (SCSIEMU)
552 	p->scsi = 0;
553 #endif
554 #if !defined (SANA2)
555 	p->sana2 = 0;
556 #endif
557 #if !defined (UAESERIAL)
558 	p->uaeserial = 0;
559 #endif
560 #if defined (CPUEMU_12)
561 	if (p->cpu_cycle_exact) {
562 		p->gfx_framerate = 1;
563 #ifdef JIT
564 		p->cachesize = 0;
565 #endif
566 		p->m68k_speed = 0;
567 	}
568 #endif
569 	if (p->maprom && !p->address_space_24)
570 		p->maprom = 0x0f000000;
571 	if ((p->maprom & 0xff000000) && p->address_space_24)
572 		p->maprom = 0x00e00000;
573 	if (p->tod_hack && p->cs_ciaatod == 0)
574 		p->cs_ciaatod = p->ntscmode ? 2 : 1;
575 
576 	built_in_chipset_prefs (p);
577 #ifdef SCSIEMU
578 	blkdev_fix_prefs (p);
579 #endif
580 	target_fixup_options (p);
581 }
582 
583 int quit_program = 0;
584 static int restart_program;
585 static TCHAR restart_config[MAX_DPATH];
586 static int default_config;
587 
uae_reset(int hardreset,int keyboardreset)588 void uae_reset (int hardreset, int keyboardreset)
589 {
590 	if (debug_dma) {
591 		record_dma_reset ();
592 		record_dma_reset ();
593 	}
594 	currprefs.quitstatefile[0] = changed_prefs.quitstatefile[0] = 0;
595 
596 	if (quit_program == 0) {
597 		quit_program = -UAE_RESET;
598 		if (keyboardreset)
599 			quit_program = -UAE_RESET_KEYBOARD;
600 		if (hardreset)
601 			quit_program = -UAE_RESET_HARD;
602 	}
603 
604 }
605 
uae_quit(void)606 void uae_quit (void)
607 {
608 	deactivate_debugger ();
609 	if (quit_program != -UAE_QUIT)
610 		quit_program = -UAE_QUIT;
611 	target_quit ();
612 }
613 
614 /* 0 = normal, 1 = nogui, -1 = disable nogui */
uae_restart(int opengui,const TCHAR * cfgfile)615 void uae_restart (int opengui, const TCHAR *cfgfile)
616 {
617 	uae_quit ();
618 	restart_program = opengui > 0 ? 1 : (opengui == 0 ? 2 : 3);
619 	restart_config[0] = 0;
620 	default_config = 0;
621 	if (cfgfile)
622 		_tcscpy (restart_config, cfgfile);
623 	target_restart ();
624 }
625 
626 #ifndef DONT_PARSE_CMDLINE
627 
usage(void)628 void usage (void)
629 {
630 }
parse_cmdline_2(int argc,TCHAR ** argv)631 static void parse_cmdline_2 (int argc, TCHAR **argv)
632 {
633 	int i;
634 
635 	cfgfile_addcfgparam (0);
636 	for (i = 1; i < argc; i++) {
637 		if (_tcsncmp (argv[i], _T("-cfgparam="), 10) == 0) {
638 			cfgfile_addcfgparam (argv[i] + 10);
639 		} else if (_tcscmp (argv[i], _T("-cfgparam")) == 0) {
640 			if (i + 1 == argc)
641 				write_log (_T("Missing argument for '-cfgparam' option.\n"));
642 			else
643 				cfgfile_addcfgparam (argv[++i]);
644 		}
645 	}
646 }
647 
diskswapper_cb(struct zfile * f,void * vrsd)648 static int diskswapper_cb (struct zfile *f, void *vrsd)
649 {
650 	int *num = (int*)vrsd;
651 	if (*num >= MAX_SPARE_DRIVES)
652 		return 1;
653 	if (zfile_gettype (f) ==  ZFILE_DISKIMAGE) {
654 		_tcsncpy (currprefs.dfxlist[*num], zfile_getname (f), 255);
655 		(*num)++;
656 	}
657 	return 0;
658 }
659 
parse_diskswapper(const TCHAR * s)660 static void parse_diskswapper (const TCHAR *s)
661 {
662 	TCHAR *tmp = my_strdup (s);
663 	TCHAR *delim = _T(",");
664 	TCHAR *p1, *p2;
665 	int num = 0;
666 
667 	p1 = tmp;
668 	for (;;) {
669 		p2 = _tcstok (p1, delim);
670 		if (!p2)
671 			break;
672 		p1 = NULL;
673 		if (num >= MAX_SPARE_DRIVES)
674 			break;
675 		if (!zfile_zopen (p2, diskswapper_cb, &num)) {
676 			_tcsncpy (currprefs.dfxlist[num], p2, 255);
677 			num++;
678 		}
679 	}
680 	xfree (tmp);
681 }
682 
parsetext(const TCHAR * s)683 static TCHAR *parsetext (const TCHAR *s)
684 {
685 	if (*s == '"' || *s == '\'') {
686 		TCHAR *d;
687 		TCHAR c = *s++;
688 		int i;
689 		d = my_strdup (s);
690 		for (i = 0; i < (int)_tcslen (d); i++) {
691 			if (d[i] == c) {
692 				d[i] = 0;
693 				break;
694 			}
695 		}
696 		return d;
697 	} else {
698 		return my_strdup (s);
699 	}
700 }
parsetextpath(const TCHAR * s)701 static TCHAR *parsetextpath (const TCHAR *s)
702 {
703 	TCHAR *s3 = parsetext (s);
704 	//TCHAR *s3 = target_expand_environment (s2);
705 	//xfree (s2);
706 	return s3;
707 }
708 
parse_cmdline(int argc,TCHAR ** argv)709 static void parse_cmdline (int argc, TCHAR **argv)
710 {
711 	int i;
712 
713 	for (i = 1; i < argc; i++) {
714 		if (!_tcsncmp (argv[i], _T("-diskswapper="), 13)) {
715 			TCHAR *txt = parsetextpath (argv[i] + 13);
716 			parse_diskswapper (txt);
717 			xfree (txt);
718 		} else if (_tcsncmp (argv[i], _T("-cfgparam="), 10) == 0) {
719 			;
720 		} else if (_tcscmp (argv[i], _T("-cfgparam")) == 0) {
721 			if (i + 1 < argc)
722 				i++;
723 		} else if (_tcsncmp (argv[i], _T("-config="), 8) == 0) {
724 			TCHAR *txt = parsetextpath (argv[i] + 8);
725 			currprefs.mountitems = 0;
726 			target_cfgfile_load (&currprefs, txt, -1, 0);
727 			xfree (txt);
728 		} else if (_tcsncmp (argv[i], _T("-statefile="), 11) == 0) {
729 #ifdef SAVESTATE
730 			TCHAR *txt = parsetextpath (argv[i] + 11);
731 			savestate_state = STATE_DORESTORE;
732 			_tcscpy (savestate_fname, txt);
733 			xfree (txt);
734 #else
735 			write_log (_T("Option -statefile ignored:\n"));
736 			write_log (_T("-> puae has been configured with --disable-save-state\n"));
737 #endif // SAVESTATE
738 		} else if (_tcscmp (argv[i], _T("-f")) == 0) {
739 			/* Check for new-style "-f xxx" argument, where xxx is config-file */
740 			if (i + 1 == argc) {
741 				write_log (_T("Missing argument for '-f' option.\n"));
742 			} else {
743 				TCHAR *txt = parsetextpath (argv[++i]);
744 				currprefs.mountitems = 0;
745 				target_cfgfile_load (&currprefs, txt, -1, 0);
746 				xfree (txt);
747 			}
748 		} else if (_tcscmp (argv[i], _T("-s")) == 0) {
749 			if (i + 1 == argc)
750 				write_log (_T("Missing argument for '-s' option.\n"));
751 			else
752 				cfgfile_parse_line (&currprefs, argv[++i], 0);
753 		} else if (_tcscmp (argv[i], _T("-h")) == 0 || _tcscmp (argv[i], _T("-help")) == 0) {
754 			usage ();
755 			exit (0);
756 		} else if (_tcsncmp (argv[i], _T("-cdimage="), 9) == 0) {
757 			TCHAR *txt = parsetextpath (argv[i] + 9);
758 			TCHAR *txt2 = xmalloc(TCHAR, _tcslen(txt) + 2);
759 			_tcscpy(txt2, txt);
760 			if (_tcsrchr(txt2, ',') != NULL)
761 				_tcscat(txt2, _T(","));
762 			cfgfile_parse_option (&currprefs, _T("cdimage0"), txt2, 0);
763 			xfree(txt2);
764 			xfree (txt);
765 		} else {
766 			if (argv[i][0] == '-' && argv[i][1] != '\0') {
767 				const TCHAR *arg = argv[i] + 2;
768 				int extra_arg = *arg == '\0';
769 				if (extra_arg)
770 					arg = i + 1 < argc ? argv[i + 1] : 0;
771 				if (parse_cmdline_option (&currprefs, argv[i][1], arg) && extra_arg)
772 					i++;
773 			}
774 		}
775 	}
776 }
777 #endif
778 
779 #ifdef __LIBRETRO__
780 #undef OPTIONS_IN_HOME
781 #endif
782 
parse_cmdline_and_init_file(int argc,TCHAR ** argv)783 static void parse_cmdline_and_init_file (int argc, TCHAR **argv)
784 {
785 
786 	_tcscpy (optionsfile, _T(""));
787 
788 #ifdef OPTIONS_IN_HOME
789 	{
790 		TCHAR *home = getenv ("HOME");
791 		if (home != NULL && strlen (home) < 240)
792 		{
793 			_tcscpy (optionsfile, home);
794 			_tcscat (optionsfile, _T("/"));
795 		}
796 	}
797 #endif
798 
799 #ifdef __LIBRETRO__
800 #ifdef ANDROID
801 _tcscpy (optionsfile, "/mnt/sdcard/euae");
802 _tcscat (optionsfile, _T("/"));
803 #else
804 _tcscpy (optionsfile, ".");
805 _tcscat (optionsfile, _T("/"));
806 #endif
807 #endif
808 	parse_cmdline_2 (argc, argv);
809 
810 	_tcscat (optionsfile, restart_config);
811 
812 
813 	if (argc > 1 && ! target_cfgfile_load (&currprefs, argv[1], 0, default_config)) {
814 		write_log (_T("failed to load config '%s'\n"), optionsfile);
815 #ifdef OPTIONS_IN_HOME
816 		/* sam: if not found in $HOME then look in current directory */
817 		_tcscpy (optionsfile, restart_config);
818 		target_cfgfile_load (&currprefs, optionsfile, 0, default_config);
819 #endif
820 	}
821 	fixup_prefs (&currprefs);
822 
823 	parse_cmdline (argc, argv);
824 //	fixup_prefs (&currprefs); //fixup after cmdline
825 }
826 
reset_all_systems(void)827 void reset_all_systems (void)
828 {
829 	init_eventtab ();
830 
831 #ifdef PICASSO96
832 	picasso_reset ();
833 #endif
834 #ifdef SCSIEMU
835 	scsi_reset ();
836 	scsidev_reset ();
837 	scsidev_start_threads ();
838 #endif
839 #ifdef A2065
840 	a2065_reset ();
841 #endif
842 #ifdef SANA2
843 	netdev_reset ();
844 	netdev_start_threads ();
845 #endif
846 #ifdef FILESYS
847 	filesys_prepare_reset ();
848 	filesys_reset ();
849 #endif
850 #ifdef NATMEM_OFFSET
851 	init_shm ();
852 #endif
853 	memory_reset ();
854 #if defined (BSDSOCKET)
855 	bsdlib_reset ();
856 #endif
857 #ifdef FILESYS
858 	filesys_start_threads ();
859 	hardfile_reset ();
860 #endif
861 #ifdef UAESERIAL
862 	uaeserialdev_reset ();
863 	uaeserialdev_start_threads ();
864 #endif
865 #if defined (PARALLEL_PORT)
866 	initparallel ();
867 #endif
868 	native2amiga_reset ();
869 	dongle_reset ();
870 #ifdef SAMPLER
871 	sampler_init ();
872 #endif
873 }
874 
875 #ifdef __LIBRETRO__
876 //RETRO FIXME
get_current_config_name()877 const char* get_current_config_name() {
878 	if (restart_config[0] == 0) {
879 		return optionsfile;
880 	} else {
881 		return restart_config;
882 	}
883 }
884 #endif
885 
886 /* Okay, this stuff looks strange, but it is here to encourage people who
887 * port UAE to re-use as much of this code as possible. Functions that you
888 * should be using are do_start_program () and do_leave_program (), as well
889 * as real_main (). Some OSes don't call main () (which is braindamaged IMHO,
890 * but unfortunately very common), so you need to call real_main () from
891 * whatever entry point you have. You may want to write your own versions
892 * of start_program () and leave_program () if you need to do anything special.
893 * Add #ifdefs around these as appropriate.
894 */
895 extern unsigned int pause_uae;
do_start_program(void)896 void do_start_program (void)
897 {
898 	if (quit_program == -UAE_QUIT)
899 		return;
900 #ifdef JIT
901 	if (!canbang && candirect < 0)
902 		candirect = 0;
903 	if (canbang && candirect < 0)
904 		candirect = 1;
905 #endif
906 	/* Do a reset on startup. Whether this is elegant is debatable. */
907 	inputdevice_updateconfig (&changed_prefs, &currprefs);
908 	if (quit_program >= 0)
909 		quit_program = UAE_RESET;
910 
911 	{
912 		m68k_go (1);
913 	}
914 }
915 
do_leave_program(void)916 void do_leave_program (void)
917 {
918 #ifdef SAMPLER
919 	sampler_free ();
920 #endif
921 	graphics_leave ();
922 	inputdevice_close ();
923 	DISK_free ();
924 	close_sound ();
925 	dump_counts ();
926 #ifdef SERIAL_PORT
927 	serial_exit ();
928 #endif
929 #ifdef CDTV
930 	cdtv_free ();
931 #endif
932 #ifdef A2091
933 	a2091_free ();
934 #endif
935 #ifdef NCR
936 	ncr_free ();
937 #endif
938 #ifdef CD32
939 	akiko_free ();
940 #endif
941 	if (! no_gui)
942 		gui_exit ();
943 #ifdef USE_SDL
944 	SDL_Quit ();
945 #endif
946 #ifdef AUTOCONFIG
947 	expansion_cleanup ();
948 #endif
949 #ifdef FILESYS
950 	filesys_cleanup ();
951 #endif
952 #ifdef BSDSOCKET
953 	bsdlib_reset ();
954 #endif
955 #ifdef SCSIEMU
956 #ifdef GAYLE
957 	gayle_free ();
958 #endif
959 	device_func_reset ();
960 #endif
961 	savestate_free ();
962 	memory_cleanup ();
963 #ifdef NATMEM_OFFSET
964 	free_shm ();
965 #endif
966 	cfgfile_addcfgparam (0);
967 	machdep_free ();
968 }
969 
start_program(void)970 void start_program (void)
971 {
972 	gui_display (-1);
973 	do_start_program ();
974 }
975 
leave_program(void)976 void leave_program (void)
977 {
978 	do_leave_program ();
979 }
980 
981 
virtualdevice_init(void)982 void virtualdevice_init (void)
983 {
984 #ifdef AUTOCONFIG
985 	/* Install resident module to get 8MB chipmem, if requested */
986 	rtarea_setup ();
987 #endif
988 #ifdef FILESYS
989 	rtarea_init ();
990 	uaeres_install ();
991 	hardfile_install ();
992 #endif
993 #ifdef SCSIEMU
994 	scsi_reset ();
995 	scsidev_install ();
996 #endif
997 #ifdef SANA2
998 	netdev_install ();
999 #endif
1000 #ifdef UAESERIAL
1001 	uaeserialdev_install ();
1002 #endif
1003 #ifdef AUTOCONFIG
1004 	expansion_init ();
1005 	emulib_install ();
1006 	uaeexe_install ();
1007 #endif
1008 #ifdef FILESYS
1009 	filesys_install ();
1010 #endif
1011 #if defined (BSDSOCKET)
1012 	bsdlib_install ();
1013 #endif
1014 }
1015 
real_main2(int argc,TCHAR ** argv)1016 static int real_main2 (int argc, TCHAR **argv)
1017 {
1018 #ifdef USE_SDL
1019 	int result = (SDL_Init (SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) == 0);
1020 	if (result)
1021 		atexit (SDL_Quit);
1022 #endif
1023 	config_changed = 1;
1024 	if (restart_config[0]) {
1025 		default_prefs (&currprefs, 0);
1026 		fixup_prefs (&currprefs);
1027 	}
1028 
1029 	if (! graphics_setup ()) {
1030 		write_log (_T("Graphics Setup Failed\n"));
1031 		exit (1);
1032 	}
1033 
1034 	if (restart_config[0])
1035 		parse_cmdline_and_init_file (argc, argv);
1036 	else
1037 		currprefs = changed_prefs;
1038 
1039 //	uae_inithrtimer ();
1040 
1041 	if (!machdep_init ()) {
1042 		write_log (_T("Machine Init Failed.\n"));
1043 		restart_program = 0;
1044 		return -1;
1045 	}
1046 
1047 	if (console_emulation) {
1048 		consolehook_config (&currprefs);
1049 		fixup_prefs (&currprefs);
1050 	}
1051 
1052 	if (! setup_sound ()) {
1053 		write_log (_T("Sound driver unavailable: Sound output disabled\n"));
1054 		currprefs.produce_sound = 0;
1055 	}
1056 	inputdevice_init ();
1057 
1058 	changed_prefs = currprefs;
1059 	no_gui = ! currprefs.start_gui;
1060 
1061 	if (restart_program == 2)
1062 		no_gui = 1;
1063 	else if (restart_program == 3)
1064 		no_gui = 0;
1065 
1066 	restart_program = 0;
1067 	if (! no_gui && currprefs.start_gui) {
1068 		int err = gui_init ();
1069 		currprefs = changed_prefs;
1070 		config_changed = 1;
1071 
1072 		if (err == -1) {
1073 			write_log (_T("Failed to initialize the GUI\n"));
1074 			return -1;
1075 		} else if (err == -2) {
1076 			return 1;
1077 		}
1078 	}
1079 
1080 	memset (&gui_data, 0, sizeof gui_data);
1081 	gui_data.cd = -1;
1082 	gui_data.hd = -1;
1083 	gui_data.net = -1;
1084 	gui_data.md = (currprefs.cs_cd32nvram || currprefs.cs_cdtvram) ? 0 : -1;
1085 
1086 #ifdef NATMEM_OFFSET
1087 	init_shm ();
1088 #endif
1089 
1090 #ifdef PICASSO96
1091 	picasso_reset ();
1092 #endif
1093 
1094 	fixup_prefs (&currprefs);
1095 
1096 #ifdef RETROPLATFORM
1097 	rp_fixup_options (&currprefs);
1098 #endif
1099 
1100 	changed_prefs = currprefs;
1101 	target_run ();
1102 	/* force sound settings change */
1103 	currprefs.produce_sound = 0;
1104 
1105 	savestate_init ();
1106 	keybuf_init (); /* Must come after init_joystick */
1107 
1108 	memory_hardreset (2);
1109 	memory_reset ();
1110 
1111 #ifdef AUTOCONFIG
1112 	native2amiga_install ();
1113 #endif
1114 
1115 	custom_init (); /* Must come after memory_init */
1116 
1117 #ifdef SERIAL_PORT
1118 	serial_init ();
1119 #endif
1120 
1121 	DISK_init ();
1122 
1123 	reset_frame_rate_hack ();
1124 	init_m68k (); /* must come after reset_frame_rate_hack (); */
1125 
1126 	gui_update ();
1127 
1128 	if (graphics_init ()) {
1129 
1130 #ifdef DEBUGGER
1131 		setup_brkhandler ();
1132 		if (currprefs.start_debugger && debuggable ())
1133 			activate_debugger ();
1134 #endif
1135 
1136 		if (!init_audio ()) {
1137 			if (sound_available && currprefs.produce_sound > 1) {
1138 				write_log (_T("Sound driver unavailable: Sound output disabled\n"));
1139 			}
1140 			currprefs.produce_sound = 0;
1141 		}
1142 		start_program ();
1143 	}
1144 
1145 	return 0;
1146 }
1147 
real_main(int argc,TCHAR ** argv)1148 void real_main (int argc, TCHAR **argv)
1149 {
1150 	show_version_full ();
1151 	restart_program = 1;
1152 
1153 	fetch_configurationpath (restart_config, sizeof (restart_config) / sizeof (TCHAR));
1154 
1155 	if(argc>1) {
1156 		_tcscat (restart_config, argv[1]);
1157 	} else  _tcscat (restart_config, OPTIONSFILENAME);
1158 	default_config = 1;
1159 
1160 #ifdef NATMEM_OFFSET
1161 	preinit_shm ();
1162 #endif
1163 
1164 	write_log (_T("Enumerating display devices.. \n"));
1165 #ifndef __LIBRETRO__
1166 	enumeratedisplays ();
1167 #endif
1168 	write_log (_T("Sorting devices and modes..\n"));
1169 #ifndef __LIBRETRO__
1170 	sortdisplays ();
1171 #endif
1172 //	write_log (_T("Display buffer mode = %d\n"), ddforceram);
1173 //	enumerate_sound_devices ();
1174 	write_log (_T("done\n"));
1175 
1176 	keyboard_settrans ();
1177 #ifdef CATWEASEL
1178 	catweasel_init ();
1179 #endif
1180 #ifdef PARALLEL_PORT
1181 	paraport_mask = paraport_init ();
1182 #endif
1183 	while (restart_program) {
1184 		int ret;
1185 		changed_prefs = currprefs;
1186 		ret = real_main2 (argc, argv);
1187 		if (ret == 0 && quit_to_gui)
1188 			restart_program = 1;
1189 		leave_program ();
1190 		quit_program = 0;
1191 	}
1192 	zfile_exit ();
1193 }
1194 
1195 #ifndef NO_MAIN_IN_MAIN_C
1196 #ifdef __LIBRETRO__
umain(int argc,TCHAR ** argv)1197 int umain (int argc, TCHAR **argv)
1198 #else
1199 int main (int argc, TCHAR **argv)
1200 #endif
1201 {
1202 	real_main (argc, argv);
1203 	return 0;
1204 }
1205 #endif
1206 
1207 #ifdef SINGLEFILE
1208 uae_u8 singlefile_config[50000] = { "_CONFIG_STARTS_HERE" };
1209 uae_u8 singlefile_data[1500000] = { "_DATA_STARTS_HERE" };
1210 #endif
1211