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