/[gxemul]/upstream/0.4.6/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.6/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26