/[gxemul]/upstream/0.4.3/src/main.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.4.3/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 23473 byte(s)
0.4.3
1 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 32 * $Id: main.c,v 1.284 2006/09/19 10:50:08 debug Exp $
29 dpavlin 2 */
30    
31     #include <stdio.h>
32     #include <stdlib.h>
33     #include <stdarg.h>
34     #include <string.h>
35     #include <time.h>
36     #include <unistd.h>
37    
38     #include "console.h"
39     #include "cpu.h"
40 dpavlin 26 #include "debugger.h"
41 dpavlin 2 #include "device.h"
42     #include "diskimage.h"
43     #include "emul.h"
44     #include "machine.h"
45     #include "misc.h"
46 dpavlin 24 #include "settings.h"
47 dpavlin 32 #include "timer.h"
48 dpavlin 2
49    
50     extern volatile int single_step;
51     extern int force_debugger_at_exit;
52    
53     extern int optind;
54     extern char *optarg;
55    
56 dpavlin 24 struct settings *global_settings;
57    
58 dpavlin 2 int extra_argc;
59     char **extra_argv;
60     char *progname;
61    
62 dpavlin 32 int skip_srandom_call = 0;
63 dpavlin 2
64    
65     /*****************************************************************************
66     *
67     * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
68     * The global variable quiet_mode can be used to suppress the output
69     * of debug(), but not the output of fatal().
70     *
71     *****************************************************************************/
72    
73     int verbose = 0;
74     int quiet_mode = 0;
75    
76     static int debug_indent = 0;
77     static int debug_currently_at_start_of_line = 1;
78    
79    
80     /*
81     * va_debug():
82     *
83     * Used internally by debug() and fatal().
84     */
85     static void va_debug(va_list argp, char *fmt)
86     {
87     char buf[DEBUG_BUFSIZE + 1];
88     char *s;
89     int i;
90    
91     buf[0] = buf[DEBUG_BUFSIZE] = 0;
92     vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
93    
94     s = buf;
95     while (*s) {
96     if (debug_currently_at_start_of_line) {
97     for (i=0; i<debug_indent; i++)
98     printf(" ");
99     }
100    
101     printf("%c", *s);
102    
103     debug_currently_at_start_of_line = 0;
104     if (*s == '\n' || *s == '\r')
105     debug_currently_at_start_of_line = 1;
106     s++;
107     }
108     }
109    
110    
111     /*
112     * debug_indentation():
113     *
114     * Modify the debug indentation.
115     */
116     void debug_indentation(int diff)
117     {
118     debug_indent += diff;
119     if (debug_indent < 0)
120     fprintf(stderr, "WARNING: debug_indent less than 0!\n");
121     }
122    
123    
124     /*
125     * debug():
126     *
127     * Debug output (ignored if quiet_mode is set).
128     */
129     void debug(char *fmt, ...)
130     {
131     va_list argp;
132    
133     if (quiet_mode)
134     return;
135    
136     va_start(argp, fmt);
137     va_debug(argp, fmt);
138     va_end(argp);
139     }
140    
141    
142     /*
143     * fatal():
144     *
145     * Fatal works like debug(), but doesn't care about the quiet_mode
146     * setting.
147     */
148     void fatal(char *fmt, ...)
149     {
150     va_list argp;
151    
152     va_start(argp, fmt);
153     va_debug(argp, fmt);
154     va_end(argp);
155     }
156    
157    
158     /*****************************************************************************/
159    
160    
161     /*
162     * internal_w():
163     *
164     * For internal use by gxemul itself.
165     */
166     void internal_w(char *arg)
167     {
168     if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
169     fprintf(stderr, "-W is for internal use by gxemul,"
170     " not for manual use.\n");
171     exit(1);
172     }
173    
174     arg += 2;
175    
176     switch (arg[0]) {
177     case 'S':
178     console_slave(arg + 1);
179     break;
180     default:
181     fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
182     arg);
183     }
184     }
185    
186    
187     /*****************************************************************************/
188    
189    
190     /*
191     * usage():
192     *
193     * Prints program usage to stdout.
194     */
195     static void usage(int longusage)
196     {
197     printf("GXemul");
198     #ifdef VERSION
199 dpavlin 28 printf(" " VERSION);
200 dpavlin 2 #endif
201 dpavlin 28 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
202 dpavlin 2 printf("Read the source code and/or documentation for "
203     "other Copyright messages.\n");
204    
205     printf("\nusage: %s [machine, other, and general options] [file "
206     "[...]]\n", progname);
207 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
208 dpavlin 24 #ifdef UNSTABLE_DEVEL
209 dpavlin 2 printf(" or %s [userland, other, and general options] file "
210     "[args ...]\n", progname);
211 dpavlin 24 #endif
212 dpavlin 2
213     if (!longusage) {
214     printf("\nRun %s -h for help on command line options.\n",
215     progname);
216     return;
217     }
218    
219     printf("\nMachine selection options:\n");
220     printf(" -E t try to emulate machine type t. (Use -H to get "
221     "a list of types.)\n");
222     printf(" -e st try to emulate machine subtype st. (Use this "
223     "with -E.)\n");
224    
225     printf("\nOther options:\n");
226     printf(" -C x try to emulate a specific CPU. (Use -H to get a "
227     "list of types.)\n");
228     printf(" -d fname add fname as a disk image. You can add \"xxx:\""
229     " as a prefix\n");
230     printf(" where xxx is one or more of the following:\n");
231 dpavlin 6 printf(" b specifies that this is the boot"
232 dpavlin 2 " device\n");
233 dpavlin 6 printf(" c CD-ROM\n");
234     printf(" d DISK\n");
235     printf(" f FLOPPY\n");
236     printf(" gH;S; set geometry to H heads and S"
237     " sectors-per-track\n");
238     printf(" i IDE\n");
239     printf(" r read-only (don't allow changes to the"
240 dpavlin 2 " file)\n");
241 dpavlin 6 printf(" s SCSI\n");
242     printf(" t tape\n");
243     printf(" 0-7 force a specific ID\n");
244 dpavlin 24 printf(" -G port listen to gdb remote connections on this port\n");
245 dpavlin 32 printf(" -I hz set the main cpu frequency to hz (not used by "
246     "all combinations\n of machines and guest OSes)");
247 dpavlin 2 printf(" -i display each instruction as it is executed\n");
248 dpavlin 28 printf(" -J disable dyntrans instruction combinations\n");
249 dpavlin 24 printf(" -j name set the name of the kernel; for DECstation "
250     "emulation, this passes\n the name to the bootloader,"
251     " for example:\n");
252     printf(" -j netbsd (NetBSD/pmax) "
253     "-j bsd (OpenBSD/pmax)\n");
254     printf(" -j vmsprite (Sprite/pmax) "
255     "-j vmunix (Ultrix/RISC)\n");
256     printf(" For other emulation modes, if the boot disk is an"
257     " ISO9660\n filesystem, -j sets the name of the"
258     " kernel to load.\n");
259 dpavlin 2 printf(" -M m emulate m MBs of physical RAM\n");
260     printf(" -N display nr of instructions/second average, at"
261     " regular intervals\n");
262     printf(" -n nr set nr of CPUs (for SMP experiments)\n");
263     printf(" -O force netboot (tftp instead of disk), even when"
264     " a disk image is\n"
265     " present (for DECstation, SGI, and ARC emulation)\n");
266 dpavlin 24 printf(" -o arg set the boot argument, for DEC, ARC, or SGI"
267     " emulation\n");
268     printf(" (default arg for DEC is -a, for ARC/SGI -aN)\n");
269 dpavlin 2 printf(" -p pc add a breakpoint (remember to use the '0x' "
270     "prefix for hex!)\n");
271     printf(" -Q no built-in PROM emulation (use this for "
272     "running ROM images)\n");
273     printf(" -R use random bootstrap cpu, instead of nr 0\n");
274     printf(" -r register dumps before every instruction\n");
275     printf(" -S initialize emulated RAM to random bytes, "
276     "instead of zeroes\n");
277 dpavlin 28 printf(" -s f:name write statistics to file 'name', "
278     "f is one or more of the following:\n");
279     printf(" v virtual program counter\n");
280     printf(" p physical equivalent of program counter\n");
281     printf(" i internal ic->f representation of "
282     "the program counter\n");
283     printf(" and optionally:\n");
284     printf(" d disable statistics gathering at "
285     "startup\n");
286     printf(" o overwrite instead of append\n");
287 dpavlin 2 printf(" -t show function trace tree\n");
288     printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
289     #ifdef WITH_X11
290     printf(" -X use X11\n");
291     printf(" -x open up new xterms for emulated serial ports "
292 dpavlin 22 "(default is on when\n using configuration files or"
293     " when X11 is used, off otherwise)\n");
294 dpavlin 2 printf(" -Y n scale down framebuffer windows by n x n times\n");
295     #endif /* WITH_X11 */
296     printf(" -Z n set nr of graphics cards, for emulating a "
297     "dual-head or tripple-head\n"
298     " environment (only for DECstation emulation)\n");
299     printf(" -z disp add disp as an X11 display to use for "
300     "framebuffers\n");
301    
302 dpavlin 24 #ifdef UNSTABLE_DEVEL
303 dpavlin 2 printf("\nUserland options:\n");
304     printf(" -u emul userland-only (syscall) emulation (use -H to"
305     " get a list of\n available emulation modes)\n");
306 dpavlin 24 #endif
307 dpavlin 2
308     printf("\nGeneral options:\n");
309 dpavlin 22 printf(" -c cmd add cmd as a command to run before starting "
310     "the simulation\n");
311 dpavlin 32 printf(" -D skip the srandom call at startup\n");
312 dpavlin 2 printf(" -H display a list of possible CPU and "
313     "machine types\n");
314     printf(" -h display this help message\n");
315     printf(" -K force the debugger to be entered at the end "
316     "of a simulation\n");
317     printf(" -q quiet mode (don't print startup messages)\n");
318     printf(" -V start up in the single-step debugger, paused\n");
319     printf(" -v verbose debug messages\n");
320     printf("\n");
321     printf("If you are selecting a machine type to emulate directly "
322     "on the command line,\nthen you must specify one or more names"
323     " of files that you wish to load into\n"
324     "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
325     "where syms is the text produced by running 'nm' (or 'nm -S') "
326     "on a binary.\n"
327     "To load a raw binary into memory, add \"address:\" in front "
328     "of the filename,\n"
329 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
330 dpavlin 2 "Examples:\n"
331 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
332     " 0xbfc00000:0x100:rom.bin for an image with "
333 dpavlin 2 "0x100 bytes header\n"
334 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
335 dpavlin 2 "start with pc=0xbfc00884\n");
336     }
337    
338    
339     /*
340     * get_cmd_args():
341     *
342     * Reads command line arguments.
343     */
344 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
345     char ***diskimagesp, int *n_diskimagesp)
346 dpavlin 2 {
347     int ch, res, using_switch_d = 0, using_switch_Z = 0;
348 dpavlin 24 int using_switch_e = 0, using_switch_E = 0;
349 dpavlin 2 char *type = NULL, *subtype = NULL;
350     int n_cpus_set = 0;
351     int msopts = 0; /* Machine-specific options used */
352     struct machine *m = emul_add_machine(emul, "default");
353    
354 dpavlin 24 char *opts =
355 dpavlin 28 "C:c:Dd:E:e:G:HhI:iJj:KM:Nn:Oo:p:QqRrSs:tU"
356 dpavlin 24 #ifdef UNSTABLE_DEVEL
357     "u:"
358     #endif
359     "VvW:"
360     #ifdef WITH_X11
361     "XxY:"
362     #endif
363     "Z:z:";
364    
365     while ((ch = getopt(argc, argv, opts)) != -1) {
366 dpavlin 2 switch (ch) {
367     case 'C':
368     m->cpu_name = strdup(optarg);
369     msopts = 1;
370     break;
371 dpavlin 22 case 'c':
372     emul->n_debugger_cmds ++;
373     emul->debugger_cmds = realloc(emul->debugger_cmds,
374     emul->n_debugger_cmds * sizeof(char *));
375     if (emul->debugger_cmds == NULL) {
376     fatal("out of memory\n");
377     exit(1);
378     }
379     emul->debugger_cmds[emul->n_debugger_cmds-1] =
380     strdup(optarg);
381     break;
382 dpavlin 2 case 'D':
383 dpavlin 32 skip_srandom_call = 1;
384 dpavlin 2 break;
385     case 'd':
386 dpavlin 4 /* diskimage_add() is called further down */
387     (*n_diskimagesp) ++;
388     (*diskimagesp) = realloc(*diskimagesp,
389     sizeof(char *) * (*n_diskimagesp));
390     if (*diskimagesp == NULL) {
391     fprintf(stderr, "out of memory\n");
392     exit(1);
393     }
394     (*diskimagesp)[(*n_diskimagesp) - 1] = strdup(optarg);
395 dpavlin 2 using_switch_d = 1;
396     msopts = 1;
397     break;
398     case 'E':
399 dpavlin 24 if (using_switch_E ++ > 0) {
400     fprintf(stderr, "-E already used.\n");
401     exit(1);
402     }
403 dpavlin 2 type = optarg;
404     msopts = 1;
405     break;
406     case 'e':
407 dpavlin 24 if (using_switch_e ++ > 0) {
408     fprintf(stderr, "-e already used.\n");
409     exit(1);
410     }
411 dpavlin 2 subtype = optarg;
412     msopts = 1;
413     break;
414 dpavlin 24 case 'G':
415     m->gdb.port = atoi(optarg);
416     if (m->gdb.port < 1 || m->gdb.port > 65535) {
417     fprintf(stderr, "Invalid debugger port %i.\n",
418     m->gdb.port);
419     exit(1);
420     }
421 dpavlin 26 /* Note: implicit -V */
422     single_step = ENTER_SINGLE_STEPPING;
423 dpavlin 24 msopts = 1;
424     break;
425 dpavlin 2 case 'H':
426     machine_list_available_types_and_cpus();
427     exit(1);
428     case 'h':
429     usage(1);
430     exit(1);
431     case 'I':
432     m->emulated_hz = atoi(optarg);
433     msopts = 1;
434     break;
435     case 'i':
436     m->instruction_trace = 1;
437     msopts = 1;
438     break;
439     case 'J':
440 dpavlin 28 m->allow_instruction_combinations = 0;
441 dpavlin 2 msopts = 1;
442     break;
443     case 'j':
444     m->boot_kernel_filename = strdup(optarg);
445     if (m->boot_kernel_filename == NULL) {
446     fprintf(stderr, "out of memory\n");
447     exit(1);
448     }
449     msopts = 1;
450     break;
451     case 'K':
452     force_debugger_at_exit = 1;
453     break;
454     case 'M':
455     m->physical_ram_in_mb = atoi(optarg);
456     msopts = 1;
457     break;
458     case 'N':
459     m->show_nr_of_instructions = 1;
460     msopts = 1;
461     break;
462     case 'n':
463     m->ncpus = atoi(optarg);
464     n_cpus_set = 1;
465     msopts = 1;
466     break;
467     case 'O':
468     m->force_netboot = 1;
469     msopts = 1;
470     break;
471     case 'o':
472     m->boot_string_argument = strdup(optarg);
473     if (m->boot_string_argument == NULL) {
474     fprintf(stderr, "out of memory\n");
475     exit(1);
476     }
477     msopts = 1;
478     break;
479     case 'p':
480     if (m->n_breakpoints >= MAX_BREAKPOINTS) {
481     fprintf(stderr, "too many breakpoints\n");
482     exit(1);
483     }
484     m->breakpoint_string[m->n_breakpoints] = strdup(optarg);
485     if (m->breakpoint_string[m->n_breakpoints] == NULL) {
486     fprintf(stderr, "out of memory\n");
487     exit(1);
488     }
489     m->breakpoint_flags[m->n_breakpoints] = 0;
490     m->n_breakpoints ++;
491     msopts = 1;
492     break;
493     case 'Q':
494     m->prom_emulation = 0;
495     msopts = 1;
496     break;
497     case 'q':
498     quiet_mode = 1;
499     break;
500     case 'R':
501     m->use_random_bootstrap_cpu = 1;
502     msopts = 1;
503     break;
504     case 'r':
505     m->register_dump = 1;
506     msopts = 1;
507     break;
508     case 'S':
509     m->random_mem_contents = 1;
510     msopts = 1;
511     break;
512 dpavlin 28 case 's':
513     machine_statistics_init(m, optarg);
514     msopts = 1;
515     break;
516 dpavlin 2 case 't':
517     m->show_trace_tree = 1;
518     msopts = 1;
519     break;
520     case 'U':
521     m->slow_serial_interrupts_hack_for_linux = 1;
522     msopts = 1;
523     break;
524     case 'u':
525     m->userland_emul = strdup(optarg);
526     if (m->userland_emul == NULL) {
527     fprintf(stderr, "out of memory\n");
528     exit(1);
529     }
530     m->machine_type = MACHINE_USERLAND;
531     msopts = 1;
532     break;
533     case 'V':
534 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
535 dpavlin 2 break;
536     case 'v':
537     verbose ++;
538     break;
539     case 'W':
540     internal_w(optarg);
541     exit(0);
542     case 'X':
543     m->use_x11 = 1;
544     msopts = 1;
545 dpavlin 22 /* FALL-THROUGH */
546 dpavlin 2 case 'x':
547     console_allow_slaves(1);
548     break;
549     case 'Y':
550     m->x11_scaledown = atoi(optarg);
551 dpavlin 20 if (m->x11_scaledown < -1) {
552     m->x11_scaleup = - m->x11_scaledown;
553     m->x11_scaledown = 1;
554     }
555 dpavlin 4 if (m->x11_scaledown < 1) {
556     fprintf(stderr, "Invalid scaledown value.\n");
557     exit(1);
558     }
559 dpavlin 2 msopts = 1;
560     break;
561     case 'Z':
562     m->n_gfx_cards = atoi(optarg);
563     using_switch_Z = 1;
564     msopts = 1;
565     break;
566     case 'z':
567     m->x11_n_display_names ++;
568     m->x11_display_names = realloc(
569     m->x11_display_names,
570     m->x11_n_display_names * sizeof(char *));
571     if (m->x11_display_names == NULL) {
572     fprintf(stderr, "out of memory\n");
573     exit(1);
574     }
575     m->x11_display_names[m->x11_n_display_names-1] =
576     strdup(optarg);
577     if (m->x11_display_names
578     [m->x11_n_display_names-1] == NULL) {
579     fprintf(stderr, "out of memory\n");
580     exit(1);
581     }
582     msopts = 1;
583     break;
584     default:
585 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
586     "line options.\n", progname);
587 dpavlin 2 exit(1);
588     }
589     }
590    
591 dpavlin 12 if (type != NULL || subtype != NULL) {
592     if (type == NULL)
593     type = "";
594 dpavlin 2 if (subtype == NULL)
595     subtype = "";
596     res = machine_name_to_type(type, subtype,
597     &m->machine_type, &m->machine_subtype, &m->arch);
598     if (!res)
599     exit(1);
600     }
601    
602     argc -= optind;
603     argv += optind;
604    
605     extra_argc = argc;
606     extra_argv = argv;
607    
608    
609     if (m->machine_type == MACHINE_NONE && msopts) {
610     fprintf(stderr, "Machine specific options used directly on "
611     "the command line, but no machine\nemulation specified?\n");
612     exit(1);
613     }
614    
615    
616 dpavlin 12 /* -i and -r are pretty verbose: */
617 dpavlin 2
618     if (m->instruction_trace && !verbose) {
619 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
620     " of -i\n", quiet_mode? "turning off -q and " : "");
621 dpavlin 2 verbose = 1;
622     quiet_mode = 0;
623     }
624    
625     if (m->register_dump && !verbose) {
626 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
627     " of -r\n", quiet_mode? "turning off -q and " : "");
628 dpavlin 2 verbose = 1;
629     quiet_mode = 0;
630     }
631    
632    
633     /*
634     * Usually, an executable filename must be supplied.
635     *
636     * However, it is possible to boot directly from a harddisk image
637 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
638     * then try to boot from disk.
639 dpavlin 2 */
640     if (extra_argc == 0) {
641     if (using_switch_d) {
642     /* Booting directly from a disk image... */
643     } else {
644     usage(0);
645     fprintf(stderr, "\nNo filename given. Aborting.\n");
646     exit(1);
647     }
648     } else if (m->boot_kernel_filename[0] == '\0') {
649     /*
650     * Default boot_kernel_filename is "", which can be overriden
651     * by the -j command line option. If it is still "" here,
652     * and we're not booting directly from a disk image, then
653     * try to set it to the last part of the last file name
654     * given on the command line. (Last part = the stuff after
655     * the last slash.)
656     */
657     char *s = extra_argv[extra_argc - 1];
658     char *s2;
659    
660     s2 = strrchr(s, '/');
661     if (s2 == NULL)
662     s2 = s;
663     else
664     s2 ++;
665    
666     m->boot_kernel_filename = strdup(s2);
667     if (m->boot_kernel_filename == NULL) {
668     fprintf(stderr, "out of memory\n");
669     exit(1);
670     }
671     }
672    
673     if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
674     fprintf(stderr, "Bad number of gfx cards (-Z).\n");
675     exit(1);
676     }
677    
678     if (!using_switch_Z && !m->use_x11)
679     m->n_gfx_cards = 0;
680    
681     return 0;
682     }
683    
684    
685     /*
686     * main():
687     *
688     * Two kinds of emulations are started from here:
689     *
690     * o) Simple emulations, using command line arguments, compatible with
691     * earlier version of GXemul/mips64emul.
692     *
693     * o) Emulations set up by parsing special config files. (0 or more.)
694     */
695     int main(int argc, char *argv[])
696     {
697 dpavlin 32 /* Setting constants: */
698     const int constant_yes = 1;
699     const int constant_true = 1;
700     const int constant_no = 0;
701     const int constant_false = 0;
702    
703 dpavlin 2 struct emul **emuls;
704 dpavlin 4 char **diskimages = NULL;
705     int n_diskimages = 0;
706 dpavlin 2 int n_emuls;
707     int i;
708    
709 dpavlin 32
710 dpavlin 2 progname = argv[0];
711    
712 dpavlin 32
713     /*
714     * Create the settings object, and add global settings to it:
715     *
716     * Read-only "constants": yes, no, true, false.
717     * Global emulator settings: verbose, single_step, ...
718     */
719 dpavlin 24 global_settings = settings_new();
720    
721 dpavlin 32 settings_add(global_settings, "yes", 0, SETTINGS_TYPE_INT,
722     SETTINGS_FORMAT_YESNO, (void *)&constant_yes);
723     settings_add(global_settings, "no", 0, SETTINGS_TYPE_INT,
724     SETTINGS_FORMAT_YESNO, (void *)&constant_no);
725     settings_add(global_settings, "true", 0, SETTINGS_TYPE_INT,
726     SETTINGS_FORMAT_BOOL, (void *)&constant_true);
727     settings_add(global_settings, "false", 0, SETTINGS_TYPE_INT,
728     SETTINGS_FORMAT_BOOL, (void *)&constant_false);
729    
730 dpavlin 24 settings_add(global_settings, "single_step", 0,
731     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
732     settings_add(global_settings, "force_debugger_at_exit", 1,
733     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
734     (void *)&force_debugger_at_exit);
735     settings_add(global_settings, "verbose", 1,
736     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&verbose);
737     settings_add(global_settings, "quiet_mode", 1,
738     SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&quiet_mode);
739    
740     /* Initialize all emulator subsystems: */
741 dpavlin 2 console_init();
742     cpu_init();
743     device_init();
744     machine_init();
745 dpavlin 32 timer_init();
746 dpavlin 2 useremul_init();
747    
748     emuls = malloc(sizeof(struct emul *));
749     if (emuls == NULL) {
750     fprintf(stderr, "out of memory\n");
751     exit(1);
752     }
753    
754     /* Allocate space for a simple emul setup: */
755     n_emuls = 1;
756     emuls[0] = emul_new(NULL);
757     if (emuls[0] == NULL) {
758     fprintf(stderr, "out of memory\n");
759     exit(1);
760     }
761 dpavlin 32 settings_add(global_settings, "emul[0]", 1,
762     SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
763 dpavlin 2
764 dpavlin 4 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
765 dpavlin 2
766 dpavlin 32 if (!skip_srandom_call) {
767     struct timeval tv;
768     gettimeofday(&tv, NULL);
769     srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
770 dpavlin 2 }
771    
772     /* Print startup message: */
773     debug("GXemul");
774     #ifdef VERSION
775 dpavlin 28 debug(" " VERSION);
776 dpavlin 2 #endif
777 dpavlin 28 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
778 dpavlin 2 debug("Read the source code and/or documentation for "
779     "other Copyright messages.\n\n");
780    
781 dpavlin 32 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
782 dpavlin 2 n_emuls --;
783 dpavlin 32 } else {
784 dpavlin 4 for (i=0; i<n_diskimages; i++)
785     diskimage_add(emuls[0]->machines[0], diskimages[i]);
786     }
787 dpavlin 2
788     /* Simple initialization, from command line arguments: */
789     if (n_emuls > 0) {
790     /* Make sure that there are no configuration files as well: */
791     for (i=1; i<argc; i++)
792     if (argv[i][0] == '@') {
793     fprintf(stderr, "You can either start one "
794     "emulation with one machine directly from "
795     "the command\nline, or start one or more "
796     "emulations using configuration files."
797     " Not both.\n");
798     exit(1);
799     }
800    
801     /* Initialize one emul: */
802     emul_simple_init(emuls[0]);
803     }
804    
805     /* Initialize emulations from config files: */
806     for (i=1; i<argc; i++) {
807     if (argv[i][0] == '@') {
808 dpavlin 32 char tmpstr[50];
809 dpavlin 2 char *s = argv[i] + 1;
810     if (strlen(s) == 0 && i+1 < argc &&
811     argv[i+1][0] != '@') {
812     i++;
813     s = argv[i];
814     }
815     n_emuls ++;
816     emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
817     if (emuls == NULL) {
818     fprintf(stderr, "out of memory\n");
819     exit(1);
820     }
821    
822     /* Always allow slave xterms when using multiple
823     emulations: */
824     console_allow_slaves(1);
825 dpavlin 22
826 dpavlin 32 /* Destroy the temporary emuls[0], since it will
827     be overwritten: */
828     if (n_emuls == 1) {
829     emul_destroy(emuls[0]);
830     settings_remove(global_settings, "emul[0]");
831     }
832    
833 dpavlin 22 emuls[n_emuls - 1] =
834     emul_create_from_configfile(s);
835 dpavlin 32
836     snprintf(tmpstr, sizeof(tmpstr), "emul[%i]", n_emuls-1);
837     settings_add(global_settings, tmpstr, 1,
838     SETTINGS_TYPE_SUBSETTINGS, 0,
839     emuls[n_emuls-1]->settings);
840 dpavlin 2 }
841     }
842    
843     if (n_emuls == 0) {
844 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
845 dpavlin 12 "use -E xx and/or -e yy, to specify\nthe machine type."
846     " For example:\n\n %s -e 3max -d disk.img\n\n"
847 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
848     "image.\n", progname);
849 dpavlin 2 exit(1);
850     }
851    
852     device_set_exit_on_error(0);
853 dpavlin 22 console_warn_if_slaves_are_needed(1);
854 dpavlin 2
855 dpavlin 32
856 dpavlin 2 /* Run all emulations: */
857     emul_run(emuls, n_emuls);
858    
859 dpavlin 32
860     /*
861     * Deinitialize everything:
862     */
863    
864     console_deinit();
865    
866     for (i=0; i<n_emuls; i++)
867     emul_destroy(emuls[i]);
868    
869     settings_remove_all(global_settings);
870 dpavlin 24 settings_destroy(global_settings);
871    
872 dpavlin 2 return 0;
873     }
874    

  ViewVC Help
Powered by ViewVC 1.1.26