1 /*
2  * main.c - VICE main startup entry.
3  *
4  * Written by
5  *  Ettore Perazzoli <ettore@comm2000.it>
6  *  Teemu Rantanen <tvr@cs.hut.fi>
7  *  Vesa-Matti Puro <vmp@lut.fi>
8  *  Jarkko Sonninen <sonninen@lut.fi>
9  *  Jouko Valta <jopi@stekt.oulu.fi>
10  *  Andre Fachat <a.fachat@physik.tu-chemnitz.de>
11  *  Andreas Boose <viceteam@t-online.de>
12  *
13  * This file is part of VICE, the Versatile Commodore Emulator.
14  * See README for copyright notice.
15  *
16  *  This program is free software; you can redistribute it and/or modify
17  *  it under the terms of the GNU General Public License as published by
18  *  the Free Software Foundation; either version 2 of the License, or
19  *  (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29  *  02111-1307  USA.
30  *
31  */
32 
33 /* #define DEBUG_MAIN */
34 
35 #include "vice.h"
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "archdep.h"
42 #include "cmdline.h"
43 #include "console.h"
44 #include "debug.h"
45 #include "drive.h"
46 #include "fullscreen.h"
47 #include "gfxoutput.h"
48 #include "info.h"
49 #include "init.h"
50 #include "initcmdline.h"
51 #include "lib.h"
52 #include "log.h"
53 #include "machine.h"
54 #include "maincpu.h"
55 #include "main.h"
56 #include "resources.h"
57 #include "sysfile.h"
58 #include "types.h"
59 #include "uiapi.h"
60 #include "version.h"
61 #include "video.h"
62 
63 #ifdef USE_SVN_REVISION
64 #include "svnversion.h"
65 #endif
66 
67 #ifdef DEBUG_MAIN
68 #define DBG(x)  printf x
69 #else
70 #define DBG(x)
71 #endif
72 
73 #ifdef __LIBRETRO__
74 #include "libretro-core.h"
75 #define LOG_HR "--------------------------------------------------------------------------------"
76 #endif
77 
78 #ifdef __OS2__
79 const
80 #endif
81 int console_mode = 0;
82 int video_disabled_mode = 0;
83 static int init_done = 0;
84 
85 
86 /** \brief  Size of buffer used to write core team members' names to log/stdout
87  *
88  * 79 characters + 1 byte for '\0'. Assuming a terminal width of 80 characters,
89  * we can only use 79 when calling log_message() since that function adds a
90  * newline to its ouput.
91  */
92 #define TERM_TMP_SIZE  80
93 
94 /* ------------------------------------------------------------------------- */
95 
96 /* This is the main program entry point.  Call this from `main()'.  */
main_program(int argc,char ** argv)97 int main_program(int argc, char **argv)
98 {
99     int i, n;
100     const char *program_name;
101     int ishelp = 0;
102     char term_tmp[TERM_TMP_SIZE];
103     size_t name_len;
104 
105 
106     lib_init_rand();
107 
108     /* Check for -config and -console before initializing the user interface.
109        -config  => use specified configuration file
110        -console => no user interface
111     */
112     DBG(("main:early cmdline(argc:%d)\n", argc));
113     for (i = 0; i < argc; i++) {
114 #ifndef __OS2__
115         if ((!strcmp(argv[i], "-console")) || (!strcmp(argv[i], "--console"))) {
116             console_mode = 1;
117             video_disabled_mode = 1;
118         } else
119 #endif
120         if ((!strcmp(argv[i], "-config")) || (!strcmp(argv[i], "--config"))) {
121             if ((i + 1) < argc) {
122                 vice_config_file = lib_stralloc(argv[++i]);
123             }
124         } else if ((!strcmp(argv[i], "-help")) ||
125                    (!strcmp(argv[i], "--help")) ||
126                    (!strcmp(argv[i], "-h")) ||
127                    (!strcmp(argv[i], "-?"))) {
128             ishelp = 1;
129         }
130     }
131 
132     DBG(("main:archdep_init(argc:%d)\n", argc));
133     if (archdep_init(&argc, argv) != 0) {
134         archdep_startup_log_error("archdep_init failed.\n");
135         return -1;
136     }
137 #ifndef __LIBRETRO__
138     if (archdep_vice_atexit(main_exit) != 0) {
139         archdep_startup_log_error("archdep_vice_atexit failed.\n");
140         return -1;
141     }
142 #else
143 #if 0
144     if (atexit(vice_main_exit) < 0)
145     {
146        archdep_startup_log_error("atexit failed.\n");
147        return -1;
148     }
149 #endif
150 #endif
151 
152     maincpu_early_init();
153     machine_setup_context();
154     drive_setup_context();
155     machine_early_init();
156 
157     /* Initialize system file locator.  */
158     sysfile_init(machine_name);
159 
160     gfxoutput_early_init(ishelp);
161     if ((init_resources() < 0) || (init_cmdline_options() < 0)) {
162         return -1;
163     }
164 
165     /* Set factory defaults.  */
166     if (resources_set_defaults() < 0) {
167         archdep_startup_log_error("Cannot set defaults.\n");
168         return -1;
169     }
170 
171     /* Initialize the user interface.  `ui_init()' might need to handle the
172        command line somehow, so we call it before parsing the options.
173        (e.g. under X11, the `-display' option is handled independently).  */
174     DBG(("main:ui_init(argc:%d)\n", argc));
175     if (!console_mode && ui_init(&argc, argv) < 0) {
176         archdep_startup_log_error("Cannot initialize the UI.\n");
177         return -1;
178     }
179 
180     if (!ishelp) {
181         /* Load the user's default configuration file.  */
182         if (resources_load(NULL) < 0) {
183             /* The resource file might contain errors, and thus certain
184             resources might have been initialized anyway.  */
185             if (resources_set_defaults() < 0) {
186                 archdep_startup_log_error("Cannot set defaults.\n");
187                 return -1;
188             }
189         }
190     }
191 
192     if (log_init() < 0) {
193         archdep_startup_log_error("Cannot startup logging system.\n");
194     }
195 
196     DBG(("main:initcmdline_check_args(argc:%d)\n", argc));
197     if (initcmdline_check_args(argc, argv) < 0) {
198         return -1;
199     }
200 
201     program_name = archdep_program_name();
202 
203     /* VICE boot sequence.  */
204 #ifdef __LIBRETRO__
205     log_message(LOG_DEFAULT, LOG_HR);
206     log_message(LOG_DEFAULT, "VICE %s", VERSION);
207 #ifdef GIT_VERSION
208     log_message(LOG_DEFAULT, "Git commit:%s", GIT_VERSION);
209 #endif
210     log_message(LOG_DEFAULT, "Build date: " __DATE__ " " __TIME__);
211     log_message(LOG_DEFAULT, "");
212     log_message(LOG_DEFAULT, "Welcome to %s, the free portable %s Emulator.", program_name, machine_name);
213     log_message(LOG_DEFAULT, "");
214     log_message(LOG_DEFAULT, "This is free software with ABSOLUTELY NO WARRANTY.");
215     log_message(LOG_DEFAULT, LOG_HR);
216 #else
217     log_message(LOG_DEFAULT, " ");
218 #ifdef USE_SVN_REVISION
219     log_message(LOG_DEFAULT, "*** VICE Version %s, rev %s ***", VERSION, VICE_SVN_REV_STRING);
220 #else
221     log_message(LOG_DEFAULT, "*** VICE Version %s ***", VERSION);
222 #endif
223     log_message(LOG_DEFAULT, " ");
224     if (machine_class == VICE_MACHINE_VSID) {
225         log_message(LOG_DEFAULT, "Welcome to %s, the free portable SID Player.",
226                     program_name);
227     } else {
228         log_message(LOG_DEFAULT, "Welcome to %s, the free portable %s Emulator.",
229                     program_name, machine_name);
230     }
231     log_message(LOG_DEFAULT, " ");
232 
233     log_message(LOG_DEFAULT, "Current VICE team members:");
234     n = 0; *term_tmp = 0;
235     for (i = 0; core_team[i].name != NULL; i++) {
236         name_len = strlen(core_team[i].name);
237         /* XXX: reject names that will never fit, for now */
238         if ((int)name_len + 3 > TERM_TMP_SIZE) {
239             log_warning(LOG_DEFAULT, "%s:%d: name '%s' too large for buffer",
240                     __FILE__, __LINE__, core_team[i].name);
241             break;  /* this will still write out whatever was in the buffer */
242         }
243 
244         if (n + (int)name_len + 3 > TERM_TMP_SIZE) {    /* +3 for ", \0" */
245             log_message(LOG_DEFAULT, "%s", term_tmp);
246             strcpy(term_tmp, core_team[i].name);
247             n = (int)name_len;
248         } else {
249             strcat(term_tmp, core_team[i].name);
250             n += (int)name_len;
251         }
252         if (core_team[i + 1].name == NULL) {
253             strcat(term_tmp, ".");
254         } else {
255             strcat(term_tmp, ", ");
256             n += 2;
257         }
258     }
259     log_message(LOG_DEFAULT, "%s", term_tmp);
260 
261     log_message(LOG_DEFAULT, " ");
262     log_message(LOG_DEFAULT, "This is free software with ABSOLUTELY NO WARRANTY.");
263     log_message(LOG_DEFAULT, "See the \"About VICE\" command for more info.");
264     log_message(LOG_DEFAULT, " ");
265 #endif
266 
267     /* lib_free(program_name); */
268 
269     /* Complete the GUI initialization (after loading the resources and
270        parsing the command-line) if necessary.  */
271     if (!console_mode && ui_init_finish() < 0) {
272         return -1;
273     }
274 
275     if (!console_mode && video_init() < 0) {
276         return -1;
277     }
278 
279     if (initcmdline_check_psid() < 0) {
280         return -1;
281     }
282 
283     if (init_main() < 0) {
284         return -1;
285     }
286 
287     initcmdline_check_attach();
288 
289     init_done = 1;
290 
291     /* Let's go...  */
292     log_message(LOG_DEFAULT, "Main CPU: starting at ($FFFC).");
293 #ifdef __LIBRETRO__
294     maincpu_mainloop_retro();
295 #else
296     maincpu_mainloop();
297 
298     log_error(LOG_DEFAULT, "perkele!");
299 #endif
300 
301     return 0;
302 }
303