|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
1.1.1.3 root 3: *
4: * Main program
5: *
6: * Copyright 1995 Ed Hanway
7: * Copyright 1995, 1996, 1997 Bernd Schmidt
1.1 root 8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12: #include <assert.h>
13:
14: #include "config.h"
15: #include "options.h"
1.1.1.3 root 16: #include "threaddep/penguin.h"
1.1.1.2 root 17: #include "uae.h"
1.1.1.3 root 18: #include "gensound.h"
19: #include "sounddep/sound.h"
1.1.1.2 root 20: #include "events.h"
1.1 root 21: #include "memory.h"
22: #include "custom.h"
23: #include "serial.h"
1.1.1.2 root 24: #include "readcpu.h"
1.1 root 25: #include "newcpu.h"
26: #include "disk.h"
27: #include "debug.h"
28: #include "xwin.h"
1.1.1.3 root 29: #include "joystick.h"
1.1 root 30: #include "keybuf.h"
31: #include "gui.h"
32: #include "zfile.h"
33: #include "autoconf.h"
1.1.1.2 root 34: #include "osemu.h"
1.1.1.3 root 35: #include "osdep/exectasks.h"
1.1 root 36: #include "compiler.h"
1.1.1.3 root 37: #include "picasso96.h"
38: #include "uaeexe.h"
1.1.1.4 root 39: #include "getopt.h"
1.1 root 40:
1.1.1.4 root 41: long int version = 256*65536L*UAEMAJOR + 65536L*UAEMINOR + UAESUBREV;
1.1.1.3 root 42:
43: struct uae_prefs currprefs;
44:
1.1.1.4 root 45: struct uae_prefs changed_prefs;
46:
47: int no_gui = 0, use_debugger = 0, use_gfxlib = 0;
48:
49: int joystickpresent = 0;
50:
51: int cloanto_rom = 0;
52:
53: char warning_buffer[256];
54:
55: char romfile[256] = "kick.rom";
56: char keyfile[256] = "";
57: char prtname[256] = DEFPRTNAME;
58:
59: char optionsfile[256];
60:
61: /* If you want to pipe printer output to a file, put something like
62: * "cat >>printerfile.tmp" above.
63: * The printer support was only tested with the driver "PostScript" on
64: * Amiga side, using apsfilter for linux to print ps-data.
65: *
66: * Under DOS it ought to be -p LPT1: or -p PRN: but you'll need a
67: * PostScript printer or ghostscript -=SR=-
68: */
69:
70: /* People must provide their own name for this */
71: char sername[256] = "";
72:
73: /* Slightly stupid place for this... */
74: /* ncurses.c might use quite a few of those. */
75: char *colormodes[] = { "256 colors", "32768 colors", "65536 colors",
76: "256 colors dithered", "16 colors dithered", "16 million colors",
77: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
78: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
79: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
80: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
81: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
82: };
83:
1.1.1.3 root 84: static void default_currprefs (void)
85: {
1.1.1.4 root 86: /* Note to porters: please don't change any of these options! UAE is supposed
87: * to behave identically on all platforms if possible. */
1.1.1.3 root 88: currprefs.framerate = 1;
89: currprefs.illegal_mem = 0;
90: currprefs.no_xhair = 0;
91: currprefs.use_serial = 0;
92: currprefs.serial_demand = 0;
93: currprefs.parallel_demand = 0;
94: currprefs.automount_uaedev = 1;
95:
96: currprefs.fake_joystick = 2 + (0<<8);
97: currprefs.keyboard_lang = KBD_LANG_US;
98: currprefs.emul_accuracy = 2;
99: currprefs.test_drawing_speed = 0;
100:
101: currprefs.produce_sound = 0;
102: currprefs.stereo = 0;
103: currprefs.sound_bits = DEFAULT_SOUND_BITS;
104: currprefs.sound_freq = DEFAULT_SOUND_FREQ;
105: currprefs.sound_minbsiz = DEFAULT_SOUND_MINB;
106: currprefs.sound_maxbsiz = DEFAULT_SOUND_MAXB;
107:
108: currprefs.gfx_width = 800;
109: currprefs.gfx_height = 600;
110: currprefs.gfx_lores = 0;
111: currprefs.gfx_linedbl = 0;
1.1.1.4 root 112: currprefs.gfx_afullscreen = 0;
113: currprefs.gfx_pfullscreen = 0;
1.1.1.3 root 114: currprefs.gfx_correct_aspect = 0;
115: currprefs.gfx_xcenter = 0;
116: currprefs.gfx_ycenter = 0;
117: currprefs.color_mode = 0;
118:
119: currprefs.use_low_bandwidth = 0;
120: currprefs.use_mitshm = 0;
121:
122: currprefs.immediate_blits = 0;
123: currprefs.blits_32bit_enabled = 0;
124:
125: strcpy (currprefs.df[0], "df0.adf");
126: strcpy (currprefs.df[1], "df1.adf");
127: strcpy (currprefs.df[2], "df2.adf");
128: strcpy (currprefs.df[3], "df3.adf");
129:
130: currprefs.m68k_speed = 4;
131: currprefs.cpu_level = 0;
132: currprefs.cpu_compatible = 0;
133: currprefs.address_space_24 = 1;
1.1 root 134:
1.1.1.4 root 135: currprefs.fastmem_size = 0x00000000;
136: currprefs.a3000mem_size = 0x00000000;
137: currprefs.z3fastmem_size = 0x00000000;
138: currprefs.chipmem_size = 0x00200000;
139: currprefs.bogomem_size = 0x00000000;
140: currprefs.gfxmem_size = 0x00000000;
1.1 root 141:
1.1.1.4 root 142: currprefs.mountinfo = alloc_mountinfo ();
143: }
1.1 root 144:
1.1.1.4 root 145: void fixup_prefs_dimensions (struct uae_prefs *prefs)
146: {
147: if (prefs->gfx_width < 320)
148: prefs->gfx_width = 320;
149: if (prefs->gfx_height < 200)
150: prefs->gfx_height = 200;
151: if (prefs->gfx_height > 300 && ! prefs->gfx_linedbl)
152: prefs->gfx_height = 300;
153: if (prefs->gfx_height > 600)
154: prefs->gfx_height = 600;
1.1 root 155:
1.1.1.4 root 156: prefs->gfx_width += 7; /* X86.S wants multiples of 4 bytes, might be 8 in the future. */
157: prefs->gfx_width &= ~7;
158: }
1.1.1.3 root 159:
1.1.1.4 root 160: static void fix_options (void)
1.1.1.2 root 161: {
1.1.1.3 root 162: int err = 0;
163:
1.1.1.4 root 164: if ((currprefs.chipmem_size & (currprefs.chipmem_size - 1)) != 0
165: || currprefs.chipmem_size < 0x80000
166: || currprefs.chipmem_size > 0x800000)
1.1.1.3 root 167: {
1.1.1.4 root 168: currprefs.chipmem_size = 0x200000;
1.1.1.3 root 169: fprintf (stderr, "Unsupported chipmem size!\n");
170: err = 1;
171: }
1.1.1.4 root 172: if ((currprefs.fastmem_size & (currprefs.fastmem_size - 1)) != 0
173: || (currprefs.fastmem_size != 0 && (currprefs.fastmem_size < 0x100000 || currprefs.fastmem_size > 0x800000)))
1.1.1.3 root 174: {
1.1.1.4 root 175: currprefs.fastmem_size = 0;
1.1.1.3 root 176: fprintf (stderr, "Unsupported fastmem size!\n");
177: err = 1;
178: }
1.1.1.4 root 179: if ((currprefs.gfxmem_size & (currprefs.gfxmem_size - 1)) != 0
180: || (currprefs.gfxmem_size != 0 && (currprefs.gfxmem_size < 0x100000 || currprefs.gfxmem_size > 0x800000)))
1.1.1.3 root 181: {
1.1.1.4 root 182: currprefs.gfxmem_size = 0;
1.1.1.3 root 183: fprintf (stderr, "Unsupported graphics card memory size!\n");
184: err = 1;
185: }
1.1.1.4 root 186: if ((currprefs.z3fastmem_size & (currprefs.z3fastmem_size - 1)) != 0
187: || (currprefs.z3fastmem_size != 0 && (currprefs.z3fastmem_size < 0x100000 || currprefs.z3fastmem_size > 0x4000000)))
1.1.1.3 root 188: {
1.1.1.4 root 189: currprefs.z3fastmem_size = 0;
1.1.1.3 root 190: fprintf (stderr, "Unsupported Zorro III fastmem size!\n");
191: err = 1;
192: }
1.1.1.4 root 193: if (currprefs.address_space_24 && (currprefs.gfxmem_size != 0 || currprefs.z3fastmem_size != 0)) {
194: currprefs.z3fastmem_size = currprefs.gfxmem_size = 0;
1.1.1.3 root 195: fprintf (stderr, "Can't use a graphics card or Zorro III fastmem when using a 24 bit\n"
196: "address space - sorry.\n");
197: }
1.1.1.4 root 198: if ((currprefs.bogomem_size & (currprefs.bogomem_size - 1)) != 0
199: || (currprefs.bogomem_size != 0 && (currprefs.bogomem_size < 0x80000 || currprefs.bogomem_size > 0x100000)))
1.1.1.3 root 200: {
1.1.1.4 root 201: currprefs.bogomem_size = 0;
1.1.1.3 root 202: fprintf (stderr, "Unsupported bogomem size!\n");
203: err = 1;
204: }
205:
1.1.1.4 root 206: if (currprefs.chipmem_size > 0x200000 && currprefs.fastmem_size != 0) {
1.1.1.3 root 207: fprintf (stderr, "You can't use fastmem and more than 2MB chip at the same time!\n");
1.1.1.4 root 208: currprefs.fastmem_size = 0;
1.1.1.3 root 209: err = 1;
210: }
1.1.1.4 root 211: if (currprefs.m68k_speed < -1 || currprefs.m68k_speed > 20) {
212: fprintf (stderr, "Bad value for -w parameter: must be -1, 0, or within 1..20.\n");
1.1.1.3 root 213: currprefs.m68k_speed = 4;
214: err = 1;
215: }
216: if (currprefs.produce_sound < 0 || currprefs.produce_sound > 3) {
217: fprintf (stderr, "Bad value for -S parameter: enable value must be within 0..3\n");
218: currprefs.produce_sound = 0;
219: err = 1;
220: }
1.1.1.4 root 221: if (currprefs.cpu_level < 2 && currprefs.z3fastmem_size > 0) {
1.1.1.3 root 222: fprintf (stderr, "Z3 fast memory can't be used with a 68000/68010 emulation. It\n"
223: "requires a 68020 emulation. Turning off Z3 fast memory.\n");
1.1.1.4 root 224: currprefs.z3fastmem_size = 0;
1.1.1.3 root 225: err = 1;
226: }
1.1.1.4 root 227: if (currprefs.cpu_level < 2 && currprefs.gfxmem_size > 0) {
1.1.1.3 root 228: fprintf (stderr, "Picasso96 can't be used with a 68000/68010 emulation. It\n"
229: "requires a 68020 emulation. Turning off Picasso96.\n");
1.1.1.4 root 230: currprefs.gfxmem_size = 0;
1.1.1.3 root 231: err = 1;
232: }
233:
234: if (err)
235: fprintf (stderr, "Please use \"uae -h\" to get usage information.\n");
236: }
237:
238: int quit_program = 0;
239:
240: void uae_reset (void)
241: {
1.1.1.4 root 242: if (quit_program == 0)
1.1.1.3 root 243: quit_program = -2;
244: }
245:
246: void uae_quit (void)
247: {
248: if (quit_program != -1)
249: quit_program = -1;
1.1.1.2 root 250: }
1.1 root 251:
1.1.1.3 root 252: /*
253: * This function is dangerous, at least if you use different versions of UAE
254: * from time to time (as I do). For example, running the SVGAlib version with
255: * "-o" will discard the keyboard language information...
256: */
1.1.1.4 root 257: void save_options (FILE *f)
1.1.1.3 root 258: {
259: int i;
260: if (use_debugger)
261: fprintf (f, "-D\n");
262: fprintf (f, "-r %s\n", romfile);
263: if (strlen (keyfile) > 0)
264: fprintf (f, "-K %s\n", keyfile);
265: for (i = 0; i < 4; i++)
266: if (strlen (currprefs.df[i]) > 0)
267: fprintf (f, "-%d %s\n", i, currprefs.df[i]);
268:
269: #ifndef UNSUPPORTED_OPTION_p
270: fprintf (f, "-p %s\n", prtname);
271: #endif
272: #ifndef UNSUPPORTED_OPTION_S
273: fprintf (f, "-S %d:%c:%d:%d:%d:%d\n", currprefs.produce_sound,
274: currprefs.stereo ? 's' : 'm',
275: currprefs.sound_bits,
276: currprefs.sound_freq,
277: currprefs.sound_maxbsiz,
278: currprefs.sound_minbsiz);
279: #endif
280: if (currprefs.fake_joystick)
281: fprintf (f, "-J %c%c\n", "01MABC"[currprefs.fake_joystick & 255],
282: "01MABC"[(currprefs.fake_joystick >> 8) & 255]);
283: fprintf (f, "-f %d\n", currprefs.framerate);
284: fprintf (f, "-O %d:%d:", currprefs.gfx_width, currprefs.gfx_height);
285: if (currprefs.gfx_lores)
286: fprintf (f, "l");
287: switch (currprefs.gfx_xcenter) {
288: case 1: fprintf (f, "x"); break;
289: case 2: fprintf (f, "X"); break;
290: default: break;
291: }
292: switch (currprefs.gfx_ycenter) {
293: case 1: fprintf (f, "y"); break;
294: case 2: fprintf (f, "Y"); break;
295: default: break;
296: }
297: if (currprefs.gfx_linedbl)
298: fprintf (f, "d");
299: if (currprefs.gfx_correct_aspect)
300: fprintf (f, "c");
301: fprintf (f, "\n-H %d\n", currprefs.color_mode);
1.1.1.4 root 302: if (currprefs.fastmem_size > 0)
303: fprintf (f, "-F %d\n", currprefs.fastmem_size / 0x100000);
304: if (currprefs.z3fastmem_size > 0)
305: fprintf (f, "-Z %d\n", currprefs.z3fastmem_size / 0x100000);
306: if (currprefs.bogomem_size > 0)
307: fprintf (f, "-s %d\n", currprefs.bogomem_size / 0x40000);
308: if (currprefs.gfxmem_size > 0)
309: fprintf (f, "-U %d\n", currprefs.gfxmem_size / 0x100000);
310: fprintf (f, "-c %d\n", currprefs.chipmem_size / 0x80000);
1.1.1.3 root 311:
312: fprintf (f, "-C %d%s\n", currprefs.cpu_level,
313: (currprefs.cpu_compatible ? "c"
314: : currprefs.address_space_24 && currprefs.cpu_level > 1 ? "a"
315: : ""));
316:
317: if (!currprefs.automount_uaedev)
318: fprintf (f, "-a\n");
319: if (currprefs.use_low_bandwidth)
320: fprintf (f, "-L\n");
321: if (currprefs.use_mitshm)
322: fprintf (f, "-T\n");
323: fprintf (f, "-w %d\n", currprefs.m68k_speed);
324: fprintf (f, "-A %d\n", currprefs.emul_accuracy);
325: /* We don't write "-t" - I can hardly imagine a user who wants that in his
326: * config file. */
1.1.1.4 root 327: write_filesys_config (currprefs.mountinfo, f);
1.1.1.3 root 328: #ifndef UNSUPPORTED_OPTION_l
329: fprintf (f, "-l %s\n", (currprefs.keyboard_lang == KBD_LANG_DE ? "de"
330: : currprefs.keyboard_lang == KBD_LANG_ES ? "es"
331: : currprefs.keyboard_lang == KBD_LANG_US ? "us"
332: : currprefs.keyboard_lang == KBD_LANG_SE ? "se"
333: : currprefs.keyboard_lang == KBD_LANG_FR ? "fr"
334: : currprefs.keyboard_lang == KBD_LANG_IT ? "it"
335: : "FOO"));
336: #endif
337: }
338:
339: struct optiondef {
340: const char *getopt_str;
341: const char *helpstr;
342: };
343:
344:
345: static struct optiondef uaeopts[] = {
346: { "h", " -h : Print help\n" },
347: #ifndef UNSUPPORTED_OPTION_l
348: { "l:", " -l lang : Set keyboard language to lang, where lang is\n"
349: " DE, SE, US, ES, FR or IT\n" },
350: #endif
351: { "m:", " -m VOL:dir : Mount directory called <dir> as AmigaDOS volume VOL:\n" },
352: { "M:", " -M VOL:dir : like -m, but mount read-only\n" },
353: { "W:", " -W specs : Mount a hardfile. The \"specs\" parameter consists of\n"
354: " \"sectors per track:number of surfaces:filename\"\n" },
355: { "s:", " -s n : Emulate n*256 KB slow memory at 0xC00000\n" },
356: { "c:", " -c n : Emulate n*512 KB chip memory at 0x000000\n" },
357: { "F:", " -F n : Emulate n MB fast memory at 0x200000\n" },
358: { "Z:", " -Z n : Emulate n MB Zorro III fast memory\n" },
359: #if defined PICASSO96
360: { "U:", " -U n : Emulate a Picasso96 compatible graphics card with n MB memory\n" },
361: #endif
362: { "w:", " -w n : Set CPU speed to n (default 4)\n" },
363: { "a", " -a : Add no expansion devices (disables fastmem and\n"
364: " harddisk support\n" },
365: { "J:", " -J xy : Specify how to emulate joystick port 0 (x) and 1 (y)\n"
366: " Use 0 for joystick 0, 1 for joystick 1, M for mouse,\n"
367: " a/b/c for various keyboard replacements\n" },
368: { "f:", " -f n : Set the frame rate to 1/n (draw only every nth frame)\n" },
369: #ifndef UNSUPPORTED_OPTION_D
370: { "D", " -D : Start up the built-in debugger\n" },
371: #endif
372: { "i", " -i : Print illegal memory accesses\n" },
373: { "t", " -t : Test drawing speed (makes the emulator very slow)\n" },
374: #ifndef UNSUPPORTED_OPTION_G
375: { "G", " -G : Disable user interface\n" },
376: #endif
377: { "A:", " -A n : Set emulator accuracy to n (0, 1 or 2)\n" },
378: #ifdef USE_EXECLIB
379: { "g", " -g : Turn on gfx-lib replacement (EXPERIMENTAL).\n" },
380: #endif
381: { "C:", " -C parms : Set CPU parameters. '0' for 68000 emulation, '1' for\n"
382: " 68010, '2' for 68020, '3' for 68020/68881. Additionally,\n"
383: " you can specify 'c' for a slow but compatible emulation\n"
384: " and 'a' for a 24 bit address space.\n" },
385: { "n:", " -n parms : Set blitter parameters: 'i' enables immediate blits,\n"
386: " '3' enables 32 bit blits (may crash RISC machines)\n" },
387: { "0:1:2:3:", " -[0123] file : Use file instead of df[0123].adf as disk image\n" },
388: { "r:", " -r file : Use file as ROM image instead of kick.rom\n" },
389: { "K:", " -K file : Use file as ROM key file for encrypted ROMs.\n" },
390: #ifndef UNSUPPORTED_OPTION_S
391: { "S:", " -S spec : Set parameters for sound emulation (see below)\n" },
392: #endif
393: #ifndef UNSUPPORTED_OPTION_p
394: { "p:", " -p prt : Use <prt> for printer output (default " DEFPRTNAME ").\n" },
395: #endif
396: #ifndef UNSUPPORTED_OPTION_I
397: { "I:", " -I device : Use <device> for serial output (e.g. " DEFSERNAME ").\n" },
398: { "d:", " -d [s][p] : Open serial/parallel port on demand only.\n" },
399: #endif
400: #ifdef TARGET_SPECIAL_OPTIONS
401: TARGET_SPECIAL_OPTIONS
402: #endif
403: { "O:", " -O modespec : Define graphics mode (see below)\n" },
404: { "H:", " -H mode : Set the color mode (see below)\n" }
405: };
406:
1.1.1.4 root 407: void usage (void)
1.1 root 408: {
1.1.1.3 root 409: int i;
410:
411: printf ("UAE - The Un*x Amiga emulator\n");
412: printf ("Summary of command-line options (please read the README for more details):\n");
413: for (i = 0; i < sizeof uaeopts / sizeof *uaeopts; i++)
414: printf ("%s", uaeopts[i].helpstr);
415:
416: printf ("\n");
417: printf ("%s",
418: "The format for the \"-S\" sound spec parameter is as follows:\n"
419: " -S enable:stereo:bits:freq:maxbuffer:minbuffer\n"
420: " You do not need to give the full specs, you can terminate after every field.\n"
421: " enable: Either 0 (no sound), 1 (emulated, but not output), 2 (emulated), or\n"
422: " 3 (completely accurate emulation). The suggested value is 2.\n"
423: " stereo: Either 's' (stereo) or 'm' (mono).\n"
424: " bits: Number of bits to use for sound output, usually 8 or 16\n"
425: " freq: Frequency for sound output; usually 44100 or 22050\n"
426: " maxbuffer: Maximum buffer size for sound output\n"
427: " minbuffer: Minimum buffer size for sound output\n"
428: "Larger buffers need less computing power, but the sound will be delayed.\n"
429: "Some of these settings will have no effect on certain ports of UAE.\n");
430: printf ("%s",
431: #ifndef COLOR_MODE_HELP_STRING
1.1 root 432: "Valid color modes: 0 (256 colors); 1 (32768 colors); 2 (65536 colors)\n"
433: " 3 (256 colors, with dithering for better results)\n"
434: " 4 (16 colors, dithered); 5 (16 million colors)\n"
1.1.1.3 root 435: #else
436: COLOR_MODE_HELP_STRING
437: #endif
438: );
439: printf ("%s",
1.1.1.2 root 440: "The format for the modespec parameter of \"-O\" is as follows:\n"
441: " -O width:height:modifiers\n"
442: " \"width\" and \"height\" specify the dimensions of the picture.\n"
443: " \"modifiers\" is a string that contains zero or more of the following\n"
444: " characters:\n"
1.1.1.3 root 445: " l: Treat the display as lores, drawing only every second pixel\n"
1.1.1.2 root 446: " x, y: Center the screen horizontally or vertically.\n"
1.1.1.3 root 447: " d: Doubles the height of the display for better interlace emulation\n"
448: " c: Correct aspect ratio\n"
1.1.1.2 root 449: "UAE may choose to ignore the color mode setting and/or adjust the\n"
1.1.1.3 root 450: "video mode setting to reasonable values.\n");
1.1 root 451: }
452:
1.1.1.2 root 453: static void parse_gfx_specs (char *spec)
454: {
455: char *x0 = my_strdup (spec);
456: char *x1, *x2;
1.1.1.3 root 457:
1.1.1.2 root 458: x1 = strchr (x0, ':');
459: if (x1 == 0)
460: goto argh;
461: x2 = strchr (x1+1, ':');
462: if (x2 == 0)
463: goto argh;
464: *x1++ = 0; *x2++ = 0;
1.1.1.3 root 465:
466: currprefs.gfx_width = atoi (x0);
467: currprefs.gfx_height = atoi (x1);
468: currprefs.gfx_lores = strchr (x2, 'l') != 0;
469: currprefs.gfx_xcenter = strchr (x2, 'x') != 0 ? 1 : strchr (x2, 'X') != 0 ? 2 : 0;
470: currprefs.gfx_ycenter = strchr (x2, 'y') != 0 ? 1 : strchr (x2, 'Y') != 0 ? 2 : 0;
471: currprefs.gfx_linedbl = strchr (x2, 'd') != 0;
1.1.1.5 ! root 472: currprefs.gfx_linedbl += 2 * (strchr (x2, 'D') != 0);
1.1.1.4 root 473: currprefs.gfx_afullscreen = strchr (x2, 'a') != 0;
474: currprefs.gfx_pfullscreen = strchr (x2, 'p') != 0;
1.1.1.3 root 475: currprefs.gfx_correct_aspect = strchr (x2, 'c') != 0;
476:
1.1.1.5 ! root 477: if (currprefs.gfx_linedbl == 3) {
! 478: fprintf (stderr, "You can't use both 'd' and 'D' modifiers in the display mode specification.\n");
! 479: }
! 480:
1.1.1.2 root 481: free (x0);
482: return;
1.1.1.3 root 483:
1.1.1.2 root 484: argh:
485: fprintf (stderr, "Bad display mode specification.\n");
486: fprintf (stderr, "The format to use is: \"width:height:modifiers\"\n");
1.1.1.3 root 487: fprintf (stderr, "Type \"uae -h\" for detailed help.\n");
1.1.1.2 root 488: free (x0);
489: }
490:
1.1.1.3 root 491: static void parse_sound_spec (char *spec)
492: {
493: char *x0 = my_strdup (spec);
494: char *x1, *x2 = NULL, *x3 = NULL, *x4 = NULL, *x5 = NULL;
1.1 root 495:
1.1.1.3 root 496: x1 = strchr (x0, ':');
497: if (x1 != NULL) {
498: *x1++ = '\0';
499: x2 = strchr (x1 + 1, ':');
500: if (x2 != NULL) {
501: *x2++ = '\0';
502: x3 = strchr (x2 + 1, ':');
503: if (x3 != NULL) {
504: *x3++ = '\0';
505: x4 = strchr (x3 + 1, ':');
506: if (x4 != NULL) {
507: *x4++ = '\0';
508: x5 = strchr (x4 + 1, ':');
509: }
510: }
511: }
512: }
513: currprefs.produce_sound = atoi (x0);
514: if (x1) {
515: if (*x1 == 's')
516: currprefs.stereo = 1;
517: else
518: currprefs.stereo = 0;
519: }
520: if (x2)
521: currprefs.sound_bits = atoi (x2);
522: if (x3)
523: currprefs.sound_freq = atoi (x3);
524: if (x4)
525: currprefs.sound_maxbsiz = currprefs.sound_minbsiz = atoi (x4);
526: if (x5)
527: currprefs.sound_minbsiz = atoi (x5);
528: free (x0);
529: return;
530: }
531:
532: const char *gameport_state (int nr)
1.1 root 533: {
1.1.1.3 root 534: if (JSEM_ISJOY0 (nr, currprefs.fake_joystick) && nr_joysticks > 0)
535: return "using joystick #0";
536: else if (JSEM_ISJOY1 (nr, currprefs.fake_joystick) && nr_joysticks > 1)
537: return "using joystick #1";
538: else if (JSEM_ISMOUSE (nr, currprefs.fake_joystick))
539: return "using mouse";
540: else if (JSEM_ISNUMPAD (nr, currprefs.fake_joystick))
541: return "using numeric pad as joystick";
542: else if (JSEM_ISCURSOR (nr, currprefs.fake_joystick))
543: return "using cursor keys as joystick";
544: else if (JSEM_ISSOMEWHEREELSE (nr, currprefs.fake_joystick))
545: return "using T/F/H/B/Alt as joystick";
546:
547: return "not connected";
548: }
549:
1.1.1.4 root 550: int parse_joy_spec (char *spec)
1.1.1.3 root 551: {
552: int v0 = 2, v1 = 0;
553: if (strlen(spec) != 2)
554: goto bad;
555:
556: switch (spec[0]) {
557: case '0': v0 = 0; break;
558: case '1': v0 = 1; break;
559: case 'M': case 'm': v0 = 2; break;
560: case 'A': case 'a': v0 = 3; break;
561: case 'B': case 'b': v0 = 4; break;
562: case 'C': case 'c': v0 = 5; break;
563: default: goto bad;
564: }
565:
566: switch (spec[1]) {
567: case '0': v1 = 0; break;
568: case '1': v1 = 1; break;
569: case 'M': case 'm': v1 = 2; break;
570: case 'A': case 'a': v1 = 3; break;
571: case 'B': case 'b': v1 = 4; break;
572: case 'C': case 'c': v1 = 5; break;
573: default: goto bad;
574: }
575: if (v0 == v1)
576: goto bad;
577: /* Let's scare Pascal programmers */
578: if (0)
579: bad:
580: fprintf (stderr, "Bad joystick mode specification. Use -J xy, where x and y\n"
581: "can be 0 for joystick 0, 1 for joystick 1, M for mouse, and\n"
582: "a, b or c for different keyboard settings.\n");
583:
584: return v0 + (v1 << 8);
585: }
586:
587: static void parse_filesys_spec (int readonly, char *spec)
588: {
589: char buf[256];
590: char *s2;
591:
1.1.1.4 root 592: strncpy (buf, spec, 255); buf[255] = 0;
593: s2 = strchr (buf, ':');
594: if (s2) {
1.1.1.3 root 595: *s2++ = '\0';
596: #ifdef __DOS__
597: {
598: char *tmp;
599:
1.1.1.4 root 600: while ((tmp = strchr (s2, '\\')))
1.1.1.3 root 601: *tmp = '/';
602: }
1.1.1.2 root 603: #endif
1.1.1.4 root 604: s2 = add_filesys_unit (currprefs.mountinfo, buf, s2, readonly, 0, 0, 0);
1.1.1.3 root 605: if (s2)
606: fprintf (stderr, "%s\n", s2);
607: } else {
608: fprintf (stderr, "Usage: [-m | -M] VOLNAME:mount_point\n");
609: }
610: }
611:
612: static void parse_hardfile_spec (char *spec)
613: {
614: char *x0 = my_strdup (spec);
615: char *x1, *x2, *x3;
616:
617: x1 = strchr (x0, ':');
618: if (x1 == NULL)
619: goto argh;
620: *x1++ = '\0';
621: x2 = strchr (x1 + 1, ':');
622: if (x2 == NULL)
623: goto argh;
624: *x2++ = '\0';
625: x3 = strchr (x2 + 1, ':');
626: if (x3 == NULL)
627: goto argh;
628: *x3++ = '\0';
1.1.1.4 root 629: x3 = add_filesys_unit (currprefs.mountinfo, 0, x3, 0, atoi (x0), atoi (x1), atoi (x2));
1.1.1.3 root 630: if (x3)
631: fprintf (stderr, "%s\n", x3);
632:
633: free (x0);
634: return;
635:
636: argh:
637: free (x0);
638: fprintf (stderr, "Bad hardfile parameter specified - type \"uae -h\" for help.\n");
639: return;
640: }
641:
642: static void parse_cpu_specs (char *spec)
643: {
644: if (*spec < '0' || *spec > '3') {
645: fprintf (stderr, "CPU parameter string must begin with '0', '1', '2' or '3'.\n");
646: return;
647: }
648:
649: currprefs.cpu_level = *spec++ - '0';
650: currprefs.address_space_24 = currprefs.cpu_level < 2;
651: currprefs.cpu_compatible = 0;
652: while (*spec != '\0') {
653: switch (*spec) {
654: case 'a':
655: if (currprefs.cpu_level < 2)
656: fprintf (stderr, "In 68000/68010 emulation, the address space is always 24 bit.\n");
657: else
658: currprefs.address_space_24 = 1;
659: break;
660: case 'c':
661: if (currprefs.cpu_level != 0)
662: fprintf (stderr, "The more compatible CPU emulation is only available for 68000\n"
663: "emulation, not for 68010 upwards.\n");
664: else
665: currprefs.cpu_compatible = 1;
666: break;
667: default:
668: fprintf (stderr, "Bad CPU parameter specified - type \"uae -h\" for help.\n");
669: break;
670: }
671: spec++;
672: }
673: }
674:
675: #ifndef DONT_PARSE_CMDLINE
676:
1.1.1.4 root 677: void parse_cmdline (int argc, char **argv)
1.1.1.3 root 678: {
679: int c, i;
680: char getopt_str[256];
681: strcpy (getopt_str, "");
682:
683: for (i = 0; i < sizeof uaeopts / sizeof *uaeopts; i++)
684: strcat (getopt_str, uaeopts[i].getopt_str);
685:
1.1.1.2 root 686: /* Help! We're running out of letters! */
1.1.1.4 root 687: while (((c = getopt (argc, argv, getopt_str)) != EOF))
688: switch (c) {
689: case 'h': usage (); exit (0);
1.1 root 690:
1.1.1.3 root 691: case '0': strncpy (currprefs.df[0], optarg, 255); currprefs.df[0][255] = 0; break;
692: case '1': strncpy (currprefs.df[1], optarg, 255); currprefs.df[1][255] = 0; break;
693: case '2': strncpy (currprefs.df[2], optarg, 255); currprefs.df[2][255] = 0; break;
694: case '3': strncpy (currprefs.df[3], optarg, 255); currprefs.df[3][255] = 0; break;
695: case 'r': strncpy (romfile, optarg, 255); romfile[255] = 0; break;
696: case 'K': strncpy (keyfile, optarg, 255); keyfile[255] = 0; break;
697: case 'p': strncpy (prtname, optarg, 255); prtname[255] = 0; break;
698: case 'I': strncpy (sername, optarg, 255); sername[255] = 0; currprefs.use_serial = 1; break;
699: case 'm': case 'M': parse_filesys_spec (c == 'M', optarg); break;
700: case 'W': parse_hardfile_spec (optarg); break;
701: case 'S': parse_sound_spec (optarg); break;
702: case 'f': currprefs.framerate = atoi (optarg); break;
703: case 'A': currprefs.emul_accuracy = atoi (optarg); break;
704: case 'x': currprefs.no_xhair = 1; break;
705: case 'i': currprefs.illegal_mem = 1; break;
706: case 'J': currprefs.fake_joystick = parse_joy_spec (optarg); break;
707: case 'a': currprefs.automount_uaedev = 0; break;
708:
709: case 't': currprefs.test_drawing_speed = 1; break;
710: case 'L': currprefs.use_low_bandwidth = 1; break;
711: case 'T': currprefs.use_mitshm = 1; break;
712: case 'w': currprefs.m68k_speed = atoi (optarg); break;
1.1 root 713:
714: case 'g': use_gfxlib = 1; break;
715: case 'G': no_gui = 1; break;
1.1.1.3 root 716: case 'D': use_debugger = 1; break;
1.1.1.2 root 717:
718: case 'n':
719: if (strchr (optarg, '3') != 0)
1.1.1.3 root 720: currprefs.blits_32bit_enabled = 1;
1.1.1.2 root 721: if (strchr (optarg, 'i') != 0)
1.1.1.3 root 722: currprefs.immediate_blits = 1;
1.1.1.2 root 723: break;
724:
725: case 'C':
1.1.1.3 root 726: parse_cpu_specs (optarg);
727: break;
728:
729: case 'Z':
1.1.1.4 root 730: currprefs.z3fastmem_size = atoi (optarg) * 0x100000;
1.1.1.3 root 731: break;
732:
733: case 'U':
1.1.1.4 root 734: currprefs.gfxmem_size = atoi (optarg) * 0x100000;
1.1.1.2 root 735: break;
1.1 root 736:
737: case 'F':
1.1.1.4 root 738: currprefs.fastmem_size = atoi (optarg) * 0x100000;
1.1 root 739: break;
740:
741: case 's':
1.1.1.4 root 742: currprefs.bogomem_size = atoi (optarg) * 0x40000;
1.1 root 743: break;
744:
745: case 'c':
1.1.1.4 root 746: currprefs.chipmem_size = atoi (optarg) * 0x80000;
1.1 root 747: break;
748:
749: case 'l':
750: if (0 == strcasecmp(optarg, "de"))
1.1.1.3 root 751: currprefs.keyboard_lang = KBD_LANG_DE;
1.1 root 752: else if (0 == strcasecmp(optarg, "us"))
1.1.1.3 root 753: currprefs.keyboard_lang = KBD_LANG_US;
1.1 root 754: else if (0 == strcasecmp(optarg, "se"))
1.1.1.3 root 755: currprefs.keyboard_lang = KBD_LANG_SE;
1.1 root 756: else if (0 == strcasecmp(optarg, "fr"))
1.1.1.3 root 757: currprefs.keyboard_lang = KBD_LANG_FR;
1.1 root 758: else if (0 == strcasecmp(optarg, "it"))
1.1.1.3 root 759: currprefs.keyboard_lang = KBD_LANG_IT;
1.1.1.2 root 760: else if (0 == strcasecmp(optarg, "es"))
1.1.1.3 root 761: currprefs.keyboard_lang = KBD_LANG_ES;
1.1 root 762: break;
763:
1.1.1.2 root 764: case 'O': parse_gfx_specs (optarg); break;
1.1 root 765: case 'd':
1.1.1.3 root 766: if (strchr (optarg, 'S') != NULL || strchr (optarg, 's')) {
767: write_log (" Serial on demand.\n");
768: currprefs.serial_demand = 1;
769: }
770: if (strchr (optarg, 'P') != NULL || strchr (optarg, 'p')) {
771: write_log (" Parallel on demand.\n");
772: currprefs.parallel_demand = 1;
1.1 root 773: }
1.1.1.3 root 774:
1.1 root 775: break;
776:
777: case 'H':
1.1.1.3 root 778: currprefs.color_mode = atoi (optarg);
779: if (currprefs.color_mode < 0) {
780: fprintf (stderr, "Bad color mode selected. Using default.\n");
781: currprefs.color_mode = 0;
1.1 root 782: }
783: break;
784: }
785: }
786: #endif
787:
1.1.1.4 root 788: static void parse_cmdline_and_init_file (int argc, char **argv)
1.1 root 789: {
790: FILE *f;
1.1.1.3 root 791: char *tmp;
792: int t;
1.1 root 793: char *buffer,*tmpbuf, *token;
1.1.1.4 root 794: int bufsiz;
1.1 root 795: int n_args;
796: char **new_argv;
797: int new_argc;
1.1.1.3 root 798: char *home;
1.1 root 799:
1.1.1.4 root 800: strcpy (optionsfile,"");
1.1 root 801:
1.1.1.3 root 802: #ifdef OPTIONS_IN_HOME
1.1.1.4 root 803: home = getenv ("HOME");
804: if (home != NULL && strlen (home) < 240)
1.1 root 805: {
1.1.1.4 root 806: strcpy (optionsfile, home);
807: strcat (optionsfile, "/");
1.1 root 808: }
809: #endif
810:
1.1.1.4 root 811: strcat (optionsfile, OPTIONSFILENAME);
1.1 root 812:
1.1.1.4 root 813: f = fopen (optionsfile, "rb");
1.1.1.3 root 814: #ifdef OPTIONS_IN_HOME
815: /* sam: if not found in $HOME then look in current directory */
1.1.1.2 root 816: if (f == NULL) {
1.1.1.3 root 817: strcpy (optionsfile, OPTIONSFILENAME);
1.1.1.4 root 818: f = fopen (optionsfile, "rb");
1.1.1.2 root 819: }
820: #endif
821:
1.1 root 822: if (f == NULL) {
1.1.1.4 root 823: parse_cmdline (argc, argv);
1.1 root 824: return;
825: }
1.1.1.4 root 826: fseek (f, 0, SEEK_END);
827: bufsiz = ftell (f);
828: fseek (f, 0, SEEK_SET);
1.1 root 829:
1.1.1.4 root 830: buffer = (char *)malloc (bufsiz+1);
1.1 root 831: buffer[bufsiz] = 0;
1.1.1.3 root 832: if (fread (buffer, 1, bufsiz, f) < bufsiz) {
833: fprintf (stderr, "Error reading configuration file\n");
834: fclose (f);
835: parse_cmdline (argc, argv);
1.1 root 836: return;
837: }
838: fclose(f);
839:
1.1.1.3 root 840: /* Canonicalize the buffer */
841: while ((tmp = strchr (buffer, '\r')))
842: *tmp = ' ';
843: for (;;) {
844: tmp = strchr (buffer, '\n');
845: if (tmp == 0)
846: break;
847: if (tmp[1] == '#') {
848: char *tmp2 = strchr (tmp + 1, '\n');
849: if (tmp2 == 0)
850: *tmp = '\0';
851: else
852: memmove (tmp, tmp2, strlen (tmp2) + 1);
853: } else {
1.1 root 854: *tmp = ' ';
1.1.1.3 root 855: }
856: }
1.1.1.4 root 857: while ((tmp = strchr (buffer, '\t')))
1.1.1.3 root 858: *tmp = ' ';
859:
860: tmp = buffer;
861: while (*tmp == ' ')
862: tmp++;
863: t = strlen (tmp);
864: memmove (buffer, tmp, t + 1);
865:
866: while (t > 0 && buffer[t-1] == ' ')
867: buffer[--t] = '\0';
868: for (;;) {
869: tmp = strstr (buffer, " ");
870: if (tmp == 0)
871: break;
872: memmove (tmp, tmp + 1, strlen (tmp));
1.1 root 873: }
874:
875: tmpbuf = my_strdup (buffer);
876:
877: n_args = 0;
878: if (strtok(tmpbuf, "\n ") != NULL) {
879: do {
880: n_args++;
881: } while (strtok(NULL, "\n ") != NULL);
882: }
883: free (tmpbuf);
884:
885: new_argv = (char **)malloc ((1 + n_args + argc) * sizeof (char **));
886: new_argv[0] = argv[0];
887: new_argc = 1;
888:
889: token = strtok(buffer, "\n ");
890: while (token != NULL) {
891: new_argv[new_argc] = my_strdup (token);
892: new_argc++;
1.1.1.4 root 893: token = strtok (NULL, "\n ");
1.1 root 894: }
895: for (n_args = 1; n_args < argc; n_args++)
896: new_argv[new_argc++] = argv[n_args];
897: new_argv[new_argc] = NULL;
898: parse_cmdline(new_argc, new_argv);
899: }
900:
1.1.1.4 root 901: void write_log_standard (const char *fmt, ...)
902: {
903: va_list ap;
904: va_start (ap, fmt);
905: #ifdef HAVE_VFPRINTF
906: vfprintf (stderr, fmt, ap);
907: #else
908: /* Technique stolen from GCC. */
909: {
910: int x1, x2, x3, x4, x5, x6, x7, x8;
911: x1 = va_arg (ap, int);
912: x2 = va_arg (ap, int);
913: x3 = va_arg (ap, int);
914: x4 = va_arg (ap, int);
915: x5 = va_arg (ap, int);
916: x6 = va_arg (ap, int);
917: x7 = va_arg (ap, int);
918: x8 = va_arg (ap, int);
919: fprintf (stderr, fmt, x1, x2, x3, x4, x5, x6, x7, x8);
920: }
921: #endif
922: }
923:
924: void reset_all_systems (void)
925: {
926: filesys_reset ();
927: filesys_start_threads ();
928: }
929:
1.1.1.2 root 930: /* Okay, this stuff looks strange, but it is here to encourage people who
931: * port UAE to re-use as much of this code as possible. Functions that you
932: * should be using are do_start_program() and do_leave_program(), as well
933: * as real_main(). Some OSes don't call main() (which is braindamaged IMHO,
934: * but unfortunately very common), so you need to call real_main() from
935: * whatever entry point you have. You may want to write your own versions
936: * of start_program() and leave_program() if you need to do anything special.
937: * Add #ifdefs around these as appropriate.
938: */
939:
1.1.1.4 root 940: void do_start_program (void)
1.1.1.2 root 941: {
1.1.1.3 root 942: /* Do a reset on startup. Whether this is elegant is debatable. */
943: quit_program = 2;
1.1.1.4 root 944: m68k_go (1);
1.1.1.2 root 945: }
946:
1.1.1.4 root 947: void do_leave_program (void)
1.1.1.2 root 948: {
1.1.1.4 root 949: graphics_leave ();
950: close_joystick ();
951: close_sound ();
952: dump_counts ();
953: serial_exit ();
954: zfile_exit ();
955: if (! no_gui)
956: gui_exit ();
1.1.1.2 root 957: }
958:
1.1.1.4 root 959: void start_program (void)
1.1.1.2 root 960: {
1.1.1.4 root 961: do_start_program ();
1.1.1.2 root 962: }
963:
1.1.1.4 root 964: void leave_program (void)
1.1.1.2 root 965: {
1.1.1.4 root 966: do_leave_program ();
1.1.1.2 root 967: }
968:
1.1.1.4 root 969: void real_main (int argc, char **argv)
1.1 root 970: {
971: FILE *hf;
972:
1.1.1.3 root 973: default_currprefs ();
974:
1.1.1.4 root 975: if (! graphics_setup ()) {
976: exit (1);
1.1 root 977: }
1.1.1.2 root 978:
1.1 root 979: rtarea_init ();
980: hardfile_install ();
981:
1.1.1.4 root 982: parse_cmdline_and_init_file (argc, argv);
1.1.1.2 root 983:
1.1.1.4 root 984: machdep_init ();
1.1.1.3 root 985:
1.1.1.4 root 986: if (! setup_sound ()) {
1.1.1.3 root 987: fprintf (stderr, "Sound driver unavailable: Sound output disabled\n");
988: currprefs.produce_sound = 0;
1.1 root 989: }
1.1.1.4 root 990: init_joystick ();
1.1 root 991:
1.1.1.4 root 992: if (! no_gui) {
993: int err = gui_init ();
1.1.1.2 root 994: if (err == -1) {
1.1.1.3 root 995: fprintf (stderr, "Failed to initialize the GUI\n");
1.1.1.2 root 996: } else if (err == -2) {
1.1.1.4 root 997: exit (0);
1.1.1.2 root 998: }
1.1 root 999: }
1.1.1.5 ! root 1000: if (sound_available && currprefs.produce_sound > 1 && ! init_sound ()) {
1.1.1.3 root 1001: fprintf (stderr, "Sound driver unavailable: Sound output disabled\n");
1002: currprefs.produce_sound = 0;
1003: }
1.1.1.2 root 1004:
1.1.1.4 root 1005: fix_options ();
1.1.1.3 root 1006: changed_prefs = currprefs;
1007:
1.1.1.2 root 1008: /* Install resident module to get 8MB chipmem, if requested */
1.1.1.4 root 1009: rtarea_setup ();
1.1.1.3 root 1010:
1.1.1.4 root 1011: keybuf_init (); /* Must come after init_joystick */
1.1.1.3 root 1012:
1.1 root 1013: expansion_init ();
1.1.1.4 root 1014: memory_init ();
1015:
1016: filesys_install ();
1017: gfxlib_install ();
1018: emulib_install ();
1019: uaeexe_install ();
1020:
1021: custom_init (); /* Must come after memory_init */
1022: serial_init ();
1023: DISK_init ();
1024:
1025: reset_frame_rate_hack ();
1026: init_m68k(); /* must come after reset_frame_rate_hack (); */
1.1 root 1027:
1.1.1.4 root 1028: compiler_init ();
1029: gui_update ();
1.1.1.2 root 1030:
1.1.1.3 root 1031: if (graphics_init ()) {
1032: setup_brkhandler ();
1033: if (use_debugger && debuggable ())
1034: activate_debugger ();
1035:
1036: start_program ();
1.1 root 1037: }
1.1.1.3 root 1038: leave_program ();
1.1.1.2 root 1039: }
1040:
1.1.1.3 root 1041: #ifndef NO_MAIN_IN_MAIN_C
1.1.1.4 root 1042: int main (int argc, char **argv)
1.1.1.2 root 1043: {
1.1.1.4 root 1044: real_main (argc, argv);
1.1 root 1045: return 0;
1046: }
1.1.1.3 root 1047: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.