/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 23473 byte(s)
0.4.3
1 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
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 * $Id: main.c,v 1.284 2006/09/19 10:50:08 debug Exp $
29 */
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 #include "debugger.h"
41 #include "device.h"
42 #include "diskimage.h"
43 #include "emul.h"
44 #include "machine.h"
45 #include "misc.h"
46 #include "settings.h"
47 #include "timer.h"
48
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 struct settings *global_settings;
57
58 int extra_argc;
59 char **extra_argv;
60 char *progname;
61
62 int skip_srandom_call = 0;
63
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 printf(" " VERSION);
200 #endif
201 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
202 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 printf(" or %s [general options] @configfile\n", progname);
208 #ifdef UNSTABLE_DEVEL
209 printf(" or %s [userland, other, and general options] file "
210 "[args ...]\n", progname);
211 #endif
212
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 printf(" b specifies that this is the boot"
232 " device\n");
233 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 " file)\n");
241 printf(" s SCSI\n");
242 printf(" t tape\n");
243 printf(" 0-7 force a specific ID\n");
244 printf(" -G port listen to gdb remote connections on this port\n");
245 printf(" -I hz set the main cpu frequency to hz (not used by "
246 "all combinations\n of machines and guest OSes)");
247 printf(" -i display each instruction as it is executed\n");
248 printf(" -J disable dyntrans instruction combinations\n");
249 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 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 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 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 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 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 "(default is on when\n using configuration files or"
293 " when X11 is used, off otherwise)\n");
294 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 #ifdef UNSTABLE_DEVEL
303 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 #endif
307
308 printf("\nGeneral options:\n");
309 printf(" -c cmd add cmd as a command to run before starting "
310 "the simulation\n");
311 printf(" -D skip the srandom call at startup\n");
312 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 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
330 "Examples:\n"
331 " 0xbfc00000:rom.bin for a raw ROM image\n"
332 " 0xbfc00000:0x100:rom.bin for an image with "
333 "0x100 bytes header\n"
334 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
335 "start with pc=0xbfc00884\n");
336 }
337
338
339 /*
340 * get_cmd_args():
341 *
342 * Reads command line arguments.
343 */
344 int get_cmd_args(int argc, char *argv[], struct emul *emul,
345 char ***diskimagesp, int *n_diskimagesp)
346 {
347 int ch, res, using_switch_d = 0, using_switch_Z = 0;
348 int using_switch_e = 0, using_switch_E = 0;
349 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 char *opts =
355 "C:c:Dd:E:e:G:HhI:iJj:KM:Nn:Oo:p:QqRrSs:tU"
356 #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 switch (ch) {
367 case 'C':
368 m->cpu_name = strdup(optarg);
369 msopts = 1;
370 break;
371 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 case 'D':
383 skip_srandom_call = 1;
384 break;
385 case 'd':
386 /* 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 using_switch_d = 1;
396 msopts = 1;
397 break;
398 case 'E':
399 if (using_switch_E ++ > 0) {
400 fprintf(stderr, "-E already used.\n");
401 exit(1);
402 }
403 type = optarg;
404 msopts = 1;
405 break;
406 case 'e':
407 if (using_switch_e ++ > 0) {
408 fprintf(stderr, "-e already used.\n");
409 exit(1);
410 }
411 subtype = optarg;
412 msopts = 1;
413 break;
414 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 /* Note: implicit -V */
422 single_step = ENTER_SINGLE_STEPPING;
423 msopts = 1;
424 break;
425 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 m->allow_instruction_combinations = 0;
441 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 case 's':
513 machine_statistics_init(m, optarg);
514 msopts = 1;
515 break;
516 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 single_step = ENTER_SINGLE_STEPPING;
535 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 /* FALL-THROUGH */
546 case 'x':
547 console_allow_slaves(1);
548 break;
549 case 'Y':
550 m->x11_scaledown = atoi(optarg);
551 if (m->x11_scaledown < -1) {
552 m->x11_scaleup = - m->x11_scaledown;
553 m->x11_scaledown = 1;
554 }
555 if (m->x11_scaledown < 1) {
556 fprintf(stderr, "Invalid scaledown value.\n");
557 exit(1);
558 }
559 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 fprintf(stderr, "Run %s -h for help on command "
586 "line options.\n", progname);
587 exit(1);
588 }
589 }
590
591 if (type != NULL || subtype != NULL) {
592 if (type == NULL)
593 type = "";
594 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 /* -i and -r are pretty verbose: */
617
618 if (m->instruction_trace && !verbose) {
619 fprintf(stderr, "Implicitly %sturning on -v, because"
620 " of -i\n", quiet_mode? "turning off -q and " : "");
621 verbose = 1;
622 quiet_mode = 0;
623 }
624
625 if (m->register_dump && !verbose) {
626 fprintf(stderr, "Implicitly %sturning on -v, because"
627 " of -r\n", quiet_mode? "turning off -q and " : "");
628 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 * file. If no kernel is supplied, but a diskimage is being used,
638 * then try to boot from disk.
639 */
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 /* 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 struct emul **emuls;
704 char **diskimages = NULL;
705 int n_diskimages = 0;
706 int n_emuls;
707 int i;
708
709
710 progname = argv[0];
711
712
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 global_settings = settings_new();
720
721 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 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 console_init();
742 cpu_init();
743 device_init();
744 machine_init();
745 timer_init();
746 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 settings_add(global_settings, "emul[0]", 1,
762 SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
763
764 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
765
766 if (!skip_srandom_call) {
767 struct timeval tv;
768 gettimeofday(&tv, NULL);
769 srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
770 }
771
772 /* Print startup message: */
773 debug("GXemul");
774 #ifdef VERSION
775 debug(" " VERSION);
776 #endif
777 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
778 debug("Read the source code and/or documentation for "
779 "other Copyright messages.\n\n");
780
781 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
782 n_emuls --;
783 } else {
784 for (i=0; i<n_diskimages; i++)
785 diskimage_add(emuls[0]->machines[0], diskimages[i]);
786 }
787
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 char tmpstr[50];
809 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
826 /* 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 emuls[n_emuls - 1] =
834 emul_create_from_configfile(s);
835
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 }
841 }
842
843 if (n_emuls == 0) {
844 fprintf(stderr, "No emulations defined. Maybe you forgot to "
845 "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 "to boot an emulated DECstation 5000/200 with a disk "
848 "image.\n", progname);
849 exit(1);
850 }
851
852 device_set_exit_on_error(0);
853 console_warn_if_slaves_are_needed(1);
854
855
856 /* Run all emulations: */
857 emul_run(emuls, n_emuls);
858
859
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 settings_destroy(global_settings);
871
872 return 0;
873 }
874

  ViewVC Help
Powered by ViewVC 1.1.26