emu: add emu_pause, makes it possible to exit the emu loop
[rofl0r-gnuboy.git] / main.c
blobd92407cd7d3aec00641c1105741383b9bfa73445
1 #undef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <signal.h>
10 #include "input.h"
11 #include "rc.h"
12 #include "sys.h"
13 #include "rckeys.h"
14 #include "emu.h"
15 #include "exports.h"
16 #include "loader.h"
17 #include "mem.h"
19 #include "Version"
22 static char *defaultconfig[] =
24 "bootrom_dmg \"\"",
25 "bootrom_gbc \"\"",
26 "bind esc quit",
27 "bind up +up",
28 "bind down +down",
29 "bind left +left",
30 "bind right +right",
31 "bind d +a",
32 "bind s +b",
33 "bind enter +start",
34 "bind space +select",
35 "bind tab +select",
36 "bind joyup +up",
37 "bind joydown +down",
38 "bind joyleft +left",
39 "bind joyright +right",
40 "bind joy0 +b",
41 "bind joy1 +a",
42 "bind joy2 +select",
43 "bind joy3 +start",
44 "bind 1 \"set saveslot 1\"",
45 "bind 2 \"set saveslot 2\"",
46 "bind 3 \"set saveslot 3\"",
47 "bind 4 \"set saveslot 4\"",
48 "bind 5 \"set saveslot 5\"",
49 "bind 6 \"set saveslot 6\"",
50 "bind 7 \"set saveslot 7\"",
51 "bind 8 \"set saveslot 8\"",
52 "bind 9 \"set saveslot 9\"",
53 "bind 0 \"set saveslot 0\"",
54 "bind ins savestate",
55 "bind del loadstate",
56 "source gnuboy.rc",
57 NULL
61 static void banner()
63 printf("\ngnuboy " VERSION "\n");
66 static void copyright()
68 banner();
69 printf(
70 "Copyright (C) 2000-2001 Laguna and Gilgamesh\n"
71 "Portions contributed by other authors; see CREDITS for details.\n"
72 "\n"
73 "This program is free software; you can redistribute it and/or modify\n"
74 "it under the terms of the GNU General Public License as published by\n"
75 "the Free Software Foundation; either version 2 of the License, or\n"
76 "(at your option) any later version.\n"
77 "\n"
78 "This program is distributed in the hope that it will be useful,\n"
79 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
80 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
81 "GNU General Public License for more details.\n"
82 "\n"
83 "You should have received a copy of the GNU General Public License\n"
84 "along with this program; if not, write to the Free Software\n"
85 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
86 "\n");
89 static void usage(char *name)
91 copyright();
92 printf("Type %s --help for detailed help.\n\n", name);
93 exit(1);
96 static void copying()
98 copyright();
99 exit(0);
102 static void joytest()
104 event_t e;
105 char *ename, *kname;
106 printf("press joystick buttons to see their name mappings\n");
107 joy_init();
108 while(1) {
109 ev_poll(0);
110 if(ev_getevent(&e)) {
111 switch(e.type) {
112 case EV_NONE: ename = "none"; break;
113 case EV_PRESS: ename = "press"; break;
114 case EV_RELEASE: ename = "release"; break;
115 case EV_REPEAT: ename = "repeat"; break;
116 case EV_MOUSE: ename = "mouse"; break;
117 default: ename = "unknown";
119 kname = k_keyname(e.code);
120 printf("%s: %s\n", ename, kname ? kname : "<null>");
121 } else {
122 sys_sleep(300);
125 joy_close();
126 exit(0);
129 static void help(char *name)
131 banner();
132 printf("Usage: %s [options] romfile\n", name);
133 printf("\n"
134 " --source FILE read rc commands from FILE\n"
135 " --bind KEY COMMAND bind KEY to perform COMMAND\n"
136 " --VAR=VALUE set rc variable VAR to VALUE\n"
137 " --VAR set VAR to 1 (turn on boolean options)\n"
138 " --no-VAR set VAR to 0 (turn off boolean options)\n"
139 " --showvars list all available rc variables\n"
140 " --help display this help and exit\n"
141 " --version output version information and exit\n"
142 " --copying show copying permissions\n"
143 " --joytest init joystick and show button names pressed\n"
144 " --rominfo show some info about the rom\n"
145 "");
146 exit(0);
149 static void rominfo(char* fn) {
150 extern int rom_load_simple(char *fn);
151 if(rom_load_simple(fn)) {
152 fprintf(stderr, "rom load failed: %s\n", loader_get_error()?loader_get_error():"");
153 exit(1);
155 printf( "rom name:\t%s\n"
156 "mbc type:\t%s\n"
157 "rom size:\t%u KB\n"
158 "ram size:\t%u KB\n"
159 , rom.name, mbc_to_string(mbc.type), mbc.romsize*16, mbc.ramsize*8);
160 exit(0);
163 static void version(char *name)
165 printf("%s-" VERSION "\n", name);
166 exit(0);
170 void doevents()
172 event_t ev;
173 int st;
175 ev_poll(0);
176 while (ev_getevent(&ev))
178 if (ev.type != EV_PRESS && ev.type != EV_RELEASE)
179 continue;
180 st = (ev.type != EV_RELEASE);
181 rc_dokey(ev.code, st);
188 static void shutdown()
190 joy_close();
191 vid_close();
192 pcm_close();
195 void die(char *fmt, ...)
197 va_list ap;
199 va_start(ap, fmt);
200 vfprintf(stderr, fmt, ap);
201 va_end(ap);
202 exit(1);
205 static int bad_signals[] =
207 /* These are all standard, so no need to #ifdef them... */
208 SIGINT, SIGSEGV, SIGTERM, SIGFPE, SIGABRT, SIGILL,
209 #ifdef SIGQUIT
210 SIGQUIT,
211 #endif
212 #ifdef SIGPIPE
213 SIGPIPE,
214 #endif
218 static void fatalsignal(int s)
220 die("Signal %d\n", s);
223 static void catch_signals()
225 int i;
226 for (i = 0; bad_signals[i]; i++)
227 signal(bad_signals[i], fatalsignal);
232 static char *base(char *s)
234 char *p;
235 p = strrchr(s, '/');
236 if (p) return p+1;
237 return s;
241 int main(int argc, char *argv[])
243 int i, ri = 0, sv = 0;
244 char *opt, *arg, *cmd, *s, *rom = 0;
246 /* Avoid initializing video if we don't have to */
247 for (i = 1; i < argc; i++)
249 if (!strcmp(argv[i], "--help"))
250 help(base(argv[0]));
251 else if (!strcmp(argv[i], "--version"))
252 version(base(argv[0]));
253 else if (!strcmp(argv[i], "--copying"))
254 copying();
255 else if (!strcmp(argv[i], "--bind")) i += 2;
256 else if (!strcmp(argv[i], "--source")) i++;
257 else if (!strcmp(argv[i], "--showvars")) sv = 1;
258 else if (!strcmp(argv[i], "--joytest"))
259 joytest();
260 else if (!strcmp(argv[i], "--rominfo")) ri = 1;
261 else if (argv[i][0] == '-' && argv[i][1] == '-');
262 else if (argv[i][0] == '-' && argv[i][1]);
263 else rom = argv[i];
266 if (!rom && !sv) usage(base(argv[0]));
267 if (ri) rominfo(rom);
269 /* If we have special perms, drop them ASAP! */
270 vid_preinit();
272 init_exports();
274 s = strdup(argv[0]);
275 sys_sanitize(s);
276 sys_initpath(s);
278 for (i = 0; defaultconfig[i]; i++)
279 rc_command(defaultconfig[i]);
281 if (sv) {
282 show_exports();
283 exit(0);
286 cmd = malloc(strlen(rom) + 11);
287 sprintf(cmd, "source %s", rom);
288 s = strchr(cmd, '.');
289 if (s) *s = 0;
290 strcat(cmd, ".rc");
291 rc_command(cmd);
293 for (i = 1; i < argc; i++)
295 if (!strcmp(argv[i], "--bind"))
297 if (i + 2 >= argc) die("missing arguments to bind\n");
298 cmd = malloc(strlen(argv[i+1]) + strlen(argv[i+2]) + 9);
299 sprintf(cmd, "bind %s \"%s\"", argv[i+1], argv[i+2]);
300 rc_command(cmd);
301 free(cmd);
302 i += 2;
304 else if (!strcmp(argv[i], "--source"))
306 if (i + 1 >= argc) die("missing argument to source\n");
307 cmd = malloc(strlen(argv[i+1]) + 6);
308 sprintf(cmd, "source %s", argv[++i]);
309 rc_command(cmd);
310 free(cmd);
312 else if (!strncmp(argv[i], "--no-", 5))
314 opt = strdup(argv[i]+5);
315 while ((s = strchr(opt, '-'))) *s = '_';
316 cmd = malloc(strlen(opt) + 7);
317 sprintf(cmd, "set %s 0", opt);
318 rc_command(cmd);
319 free(cmd);
320 free(opt);
322 else if (argv[i][0] == '-' && argv[i][1] == '-')
324 opt = strdup(argv[i]+2);
325 if ((s = strchr(opt, '=')))
327 *s = 0;
328 arg = s+1;
330 else arg = "1";
331 while ((s = strchr(opt, '-'))) *s = '_';
332 while ((s = strchr(arg, ','))) *s = ' ';
334 cmd = malloc(strlen(opt) + strlen(arg) + 6);
335 sprintf(cmd, "set %s %s", opt, arg);
337 rc_command(cmd);
338 free(cmd);
339 free(opt);
341 /* short options not yet implemented */
342 else if (argv[i][0] == '-' && argv[i][1]);
345 /* FIXME - make interface modules responsible for atexit() */
346 atexit(shutdown);
347 catch_signals();
348 vid_init();
349 joy_init();
350 pcm_init();
352 rom = strdup(rom);
353 sys_sanitize(rom);
355 loader_init(rom);
357 emu_reset();
358 emu_run();
360 /* never reached */
361 return 0;