|
|
1.1 root 1: /*
2: Hatari - main.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Main initialization and event handling routines.
8: */
9: const char Main_fileid[] = "Hatari main.c : " __DATE__ " " __TIME__;
10:
11: #include <time.h>
1.1.1.2 root 12: #include <errno.h>
1.1 root 13: #include <SDL.h>
14:
15: #include "main.h"
16: #include "configuration.h"
17: #include "control.h"
18: #include "options.h"
19: #include "dialog.h"
20: #include "ioMem.h"
1.1.1.2 root 21: #include "keymap.h"
1.1 root 22: #include "log.h"
23: #include "m68000.h"
24: #include "memorySnapShot.h"
25: #include "paths.h"
26: #include "reset.h"
1.1.1.2 root 27: #include "resolution.h"
1.1 root 28: #include "screen.h"
1.1.1.4 ! root 29: #include "scsi.h"
1.1 root 30: #include "sdlgui.h"
31: #include "shortcut.h"
32: #include "statusbar.h"
33: #include "nextMemory.h"
34: #include "str.h"
35: #include "video.h"
36: #include "avi_record.h"
37: #include "debugui.h"
1.1.1.2 root 38: #include "clocks_timings.h"
1.1.1.4 ! root 39: #include "file.h"
1.1.1.2 root 40:
1.1 root 41: #include "hatari-glue.h"
42:
1.1.1.2 root 43: #if HAVE_GETTIMEOFDAY
44: #include <sys/time.h>
45: #endif
1.1 root 46:
1.1.1.4 ! root 47: int nFrameSkips;
1.1 root 48:
49: bool bQuitProgram = false; /* Flag to quit program cleanly */
50:
1.1.1.2 root 51: static Uint32 nRunVBLs; /* Whether and how many VBLS to run before exit */
1.1 root 52: static Uint32 nFirstMilliTick; /* Ticks when VBL counting started */
53: static Uint32 nVBLCount; /* Frame count */
54:
55: static bool bEmulationActive = true; /* Run emulation when started */
56: static bool bAccurateDelays; /* Host system has an accurate SDL_Delay()? */
57: static bool bIgnoreNextMouseMotion = false; /* Next mouse motion will be ignored (needed after SDL_WarpMouse) */
58:
59:
60: /*-----------------------------------------------------------------------*/
61: /**
62: * Return current time as millisecond for performance measurements.
63: *
64: * (On Unix only time spent by Hatari itself is counted, on other
65: * platforms less accurate SDL "wall clock".)
66: */
67: #if HAVE_SYS_TIMES_H
68: #include <unistd.h>
69: #include <sys/times.h>
70: static Uint32 Main_GetTicks(void)
71: {
72: static unsigned int ticks_to_msec = 0;
73: struct tms fields;
74: if (!ticks_to_msec)
75: {
76: ticks_to_msec = sysconf(_SC_CLK_TCK);
77: printf("OS clock ticks / second: %d\n", ticks_to_msec);
78: /* Linux has 100Hz virtual clock so no accuracy loss there */
79: ticks_to_msec = 1000UL / ticks_to_msec;
80: }
81: /* return milliseconds (clock ticks) spent in this process
82: */
83: times(&fields);
84: return ticks_to_msec * fields.tms_utime;
85: }
86: #else
87: # warning "times() function missing, using inaccurate SDL_GetTicks() instead."
88: # define Main_GetTicks SDL_GetTicks
89: #endif
90:
91:
1.1.1.2 root 92: //#undef HAVE_GETTIMEOFDAY
93: //#undef HAVE_NANOSLEEP
94:
95: /*-----------------------------------------------------------------------*/
96: /**
97: * Return a time counter in micro seconds.
98: * If gettimeofday is available, we use it directly, else we convert the
99: * return of SDL_GetTicks in micro sec.
100: */
101:
102: static Sint64 Time_GetTicks ( void )
103: {
104: Sint64 ticks_micro;
105:
106: #if HAVE_GETTIMEOFDAY
107: struct timeval now;
108: gettimeofday ( &now , NULL );
109: ticks_micro = (Sint64)now.tv_sec * 1000000 + now.tv_usec;
110: #else
111: ticks_micro = (Sint64)SDL_GetTicks() * 1000; /* milli sec -> micro sec */
112: #endif
113:
114: return ticks_micro;
115: }
116:
117:
118: /*-----------------------------------------------------------------------*/
119: /**
120: * Sleep for a given number of micro seconds.
121: * If nanosleep is available, we use it directly, else we use SDL_Delay
122: * (which is portable, but less accurate as is uses milli-seconds)
123: */
124:
125: static void Time_Delay ( Sint64 ticks_micro )
126: {
127: #if HAVE_NANOSLEEP
128: struct timespec ts;
129: int ret;
130: ts.tv_sec = ticks_micro / 1000000;
131: ts.tv_nsec = (ticks_micro % 1000000) * 1000; /* micro sec -> nano sec */
132: /* wait until all the delay is elapsed, including possible interruptions by signals */
133: do
134: {
135: errno = 0;
136: ret = nanosleep(&ts, &ts);
137: } while ( ret && ( errno == EINTR ) ); /* keep on sleeping if we were interrupted */
138: #else
139: SDL_Delay ( (Uint32)(ticks_micro / 1000) ) ; /* micro sec -> milli sec */
140: #endif
141: }
142:
143:
1.1 root 144: /*-----------------------------------------------------------------------*/
145: /**
146: * Pause emulation, stop sound. 'visualize' should be set true,
147: * unless unpause will be called immediately afterwards.
148: *
149: * @return true if paused now, false if was already paused
150: */
151: bool Main_PauseEmulation(bool visualize)
152: {
153: if ( !bEmulationActive )
154: return false;
155:
1.1.1.2 root 156: // Audio_EnableAudio(false);
1.1 root 157: bEmulationActive = false;
158: if (visualize)
159: {
160: if (nFirstMilliTick)
161: {
162: int interval = Main_GetTicks() - nFirstMilliTick;
163: static float previous;
164: float current;
165:
166: current = (1000.0 * nVBLCount) / interval;
167: printf("SPEED: %.1f VBL/s (%d/%.1fs), diff=%.1f%%\n",
168: current, nVBLCount, interval/1000.0,
1.1.1.2 root 169: previous>0.0 ? 100*(current-previous)/previous : 0.0);
1.1 root 170: nVBLCount = nFirstMilliTick = 0;
171: previous = current;
172: }
173:
174: Statusbar_AddMessage("Emulation paused", 100);
175: /* make sure msg gets shown */
176: Statusbar_Update(sdlscrn);
177:
178: if (bGrabMouse && !bInFullScreen)
179: /* Un-grab mouse pointer in windowed mode */
180: SDL_WM_GrabInput(SDL_GRAB_OFF);
181: }
182: return true;
183: }
184:
185: /*-----------------------------------------------------------------------*/
186: /**
187: * Start/continue emulation
188: *
189: * @return true if continued, false if was already running
190: */
191: bool Main_UnPauseEmulation(void)
192: {
193: if ( bEmulationActive )
194: return false;
195:
1.1.1.2 root 196: // Sound_BufferIndexNeedReset = true;
197: // Audio_EnableAudio(ConfigureParams.Sound.bEnableSound);
1.1 root 198: bEmulationActive = true;
199:
200: /* Cause full screen update (to clear all) */
201: Screen_SetFullUpdate();
202:
203: if (bGrabMouse)
204: /* Grab mouse pointer again */
205: SDL_WM_GrabInput(SDL_GRAB_ON);
206: return true;
207: }
208:
209: /*-----------------------------------------------------------------------*/
210: /**
211: * Optionally ask user whether to quit and set bQuitProgram accordingly
212: */
213: void Main_RequestQuit(void)
214: {
215: if (ConfigureParams.Memory.bAutoSave)
216: {
217: bQuitProgram = true;
218: MemorySnapShot_Capture(ConfigureParams.Memory.szAutoSaveFileName, false);
219: }
220: else if (ConfigureParams.Log.bConfirmQuit)
221: {
222: bQuitProgram = false; /* if set true, dialog exits */
223: bQuitProgram = DlgAlert_Query("All unsaved data will be lost.\nDo you really want to quit?");
224: }
225: else
226: {
227: bQuitProgram = true;
228: }
229:
230: if (bQuitProgram)
231: {
232: /* Assure that CPU core shuts down */
233: M68000_SetSpecial(SPCFLAG_BRK);
234: }
235: }
236:
237: /*-----------------------------------------------------------------------*/
238: /**
1.1.1.2 root 239: * Set how many VBLs Hatari should run, from the moment this function
240: * is called.
241: */
242: void Main_SetRunVBLs(Uint32 vbls)
243: {
244: fprintf(stderr, "Exit after %d VBLs.\n", vbls);
245: nRunVBLs = vbls;
246: nVBLCount = 0;
247: }
248:
249: /*-----------------------------------------------------------------------*/
250: /**
1.1 root 251: * This function waits on each emulated VBL to synchronize the real time
252: * with the emulated ST.
253: * Unfortunately SDL_Delay and other sleep functions like usleep or nanosleep
254: * are very inaccurate on some systems like Linux 2.4 or Mac OS X (they can only
255: * wait for a multiple of 10ms due to the scheduler on these systems), so we have
256: * to "busy wait" there to get an accurate timing.
1.1.1.2 root 257: * All times are expressed as micro seconds, to avoid too much rounding error.
1.1 root 258: */
259: void Main_WaitOnVbl(void)
260: {
1.1.1.2 root 261: Sint64 CurrentTicks;
262: static Sint64 DestTicks = 0;
263: Sint64 FrameDuration_micro;
264: Sint64 nDelay;
1.1 root 265:
266: nVBLCount++;
267: if (nRunVBLs && nVBLCount >= nRunVBLs)
268: {
269: /* show VBLs/s */
270: Main_PauseEmulation(true);
271: exit(0);
272: }
273:
1.1.1.2 root 274: // FrameDuration_micro = (Sint64) ( 1000000.0 / nScreenRefreshRate + 0.5 ); /* round to closest integer */
1.1.1.4 ! root 275: FrameDuration_micro = ClocksTimings_GetVBLDuration_micro ( ConfigureParams.System.nMachineType , 68 );
! 276: // FrameDuration_micro = 1000000/50;
1.1.1.2 root 277: CurrentTicks = Time_GetTicks();
278:
279: if ( DestTicks == 0 ) /* first call, init DestTicks */
280: DestTicks = CurrentTicks + FrameDuration_micro;
281:
282: nDelay = DestTicks - CurrentTicks;
1.1 root 283:
284: /* Do not wait if we are in fast forward mode or if we are totally out of sync */
285: if (ConfigureParams.System.bFastForward == true
1.1.1.2 root 286: || nDelay < -4*FrameDuration_micro)
1.1 root 287: {
288: if (ConfigureParams.System.bFastForward == true)
289: {
290: if (!nFirstMilliTick)
291: nFirstMilliTick = Main_GetTicks();
292: }
1.1.1.4 ! root 293: if (nFrameSkips < ConfigureParams.Screen.nFrameSkips)
! 294: {
! 295: nFrameSkips += 1;
! 296: Log_Printf(LOG_DEBUG, "Increased frameskip to %d\n", nFrameSkips);
! 297: }
1.1.1.2 root 298: /* Only update DestTicks for next VBL */
299: DestTicks = CurrentTicks + FrameDuration_micro;
1.1 root 300: return;
301: }
302: /* If automatic frameskip is enabled and delay's more than twice
303: * the effect of single frameskip, decrease frameskip
304: */
1.1.1.4 ! root 305: if (nFrameSkips > 0
! 306: && ConfigureParams.Screen.nFrameSkips >= AUTO_FRAMESKIP_LIMIT
! 307: && 2*nDelay > FrameDuration_micro/nFrameSkips)
! 308: {
! 309: nFrameSkips -= 1;
! 310: Log_Printf(LOG_DEBUG, "Decreased frameskip to %d\n", nFrameSkips);
! 311: }
1.1 root 312:
313: if (bAccurateDelays)
314: {
315: /* Accurate sleeping is possible -> use SDL_Delay to free the CPU */
1.1.1.2 root 316: if (nDelay > 1000)
317: Time_Delay(nDelay - 1000);
1.1 root 318: }
319: else
320: {
321: /* No accurate SDL_Delay -> only wait if more than 5ms to go... */
1.1.1.2 root 322: if (nDelay > 5000)
323: Time_Delay(nDelay<10000 ? nDelay-1000 : 9000);
1.1 root 324: }
325:
326: /* Now busy-wait for the right tick: */
327: while (nDelay > 0)
328: {
1.1.1.2 root 329: CurrentTicks = Time_GetTicks();
330: nDelay = DestTicks - CurrentTicks;
1.1 root 331: }
332:
1.1.1.2 root 333: //printf ( "tick %lld\n" , CurrentTicks );
334: /* Update DestTicks for next VBL */
335: DestTicks += FrameDuration_micro;
1.1 root 336: }
337:
338:
339: /*-----------------------------------------------------------------------*/
340: /**
341: * Since SDL_Delay and friends are very inaccurate on some systems, we have
342: * to check if we can rely on this delay function.
343: */
344: static void Main_CheckForAccurateDelays(void)
345: {
346: int nStartTicks, nEndTicks;
347:
348: /* Force a task switch now, so we have a longer timeslice afterwards */
349: SDL_Delay(10);
350:
351: nStartTicks = SDL_GetTicks();
352: SDL_Delay(1);
353: nEndTicks = SDL_GetTicks();
354:
355: /* If the delay took longer than 10ms, we are on an inaccurate system! */
356: bAccurateDelays = ((nEndTicks - nStartTicks) < 9);
357:
358: if (bAccurateDelays)
359: Log_Printf(LOG_WARN, "Host system has accurate delays. (%d)\n", nEndTicks - nStartTicks);
360: else
361: Log_Printf(LOG_WARN, "Host system does not have accurate delays. (%d)\n", nEndTicks - nStartTicks);
362: }
363:
364:
365: /* ----------------------------------------------------------------------- */
366: /**
367: * Set mouse pointer to new coordinates and set flag to ignore the mouse event
368: * that is generated by SDL_WarpMouse().
369: */
370: void Main_WarpMouse(int x, int y)
371: {
372: SDL_WarpMouse(x, y); /* Set mouse pointer to new position */
373: bIgnoreNextMouseMotion = true; /* Ignore mouse motion event from SDL_WarpMouse */
374: }
375:
376:
377: /* ----------------------------------------------------------------------- */
378: /**
379: * Handle mouse motion event.
380: */
381: static void Main_HandleMouseMotion(SDL_Event *pEvent)
382: {
383: int dx, dy;
384: static int ax = 0, ay = 0;
385:
386: /* Ignore motion when position has changed right after a reset or TOS
387: * (especially version 4.04) might get confused and play key clicks */
1.1.1.4 ! root 388: if (bIgnoreNextMouseMotion )
1.1 root 389: {
390: bIgnoreNextMouseMotion = false;
391: return;
392: }
393:
394: dx = pEvent->motion.xrel;
395: dy = pEvent->motion.yrel;
396:
397: /* In zoomed low res mode, we divide dx and dy by the zoom factor so that
398: * the ST mouse cursor stays in sync with the host mouse. However, we have
399: * to take care of lowest bit of dx and dy which will get lost when
400: * dividing. So we store these bits in ax and ay and add them to dx and dy
401: * the next time. */
402: if (nScreenZoomX != 1)
403: {
404: dx += ax;
405: ax = dx % nScreenZoomX;
406: dx /= nScreenZoomX;
407: }
408: if (nScreenZoomY != 1)
409: {
410: dy += ay;
411: ay = dy % nScreenZoomY;
412: dy /= nScreenZoomY;
413: }
414:
1.1.1.2 root 415: // KeyboardProcessor.Mouse.dx += dx;
416: // KeyboardProcessor.Mouse.dy += dy;
1.1 root 417: }
418:
419:
420: /* ----------------------------------------------------------------------- */
421: /**
422: * SDL message handler.
423: * Here we process the SDL events (keyboard, mouse, ...) and map it to
424: * Atari IKBD events.
425: */
426: void Main_EventHandler(void)
427: {
428: bool bContinueProcessing;
429: SDL_Event event;
430: int events;
431: int remotepause;
432:
433: do
434: {
435: bContinueProcessing = false;
436:
437: /* check remote process control */
438: remotepause = Control_CheckUpdates();
439:
440: if ( bEmulationActive || remotepause )
441: {
442: events = SDL_PollEvent(&event);
443: }
444: else
445: {
446: ShortCut_ActKey();
447: /* last (shortcut) event activated emulation? */
448: if ( bEmulationActive )
449: break;
450: events = SDL_WaitEvent(&event);
451: }
452: if (!events)
453: {
454: /* no events -> if emulation is active or
455: * user is quitting -> return from function.
456: */
457: continue;
458: }
459: switch (event.type)
460: {
461:
462: case SDL_QUIT:
463: Main_RequestQuit();
464: break;
465:
466: case SDL_MOUSEMOTION: /* Read/Update internal mouse position */
467: Main_HandleMouseMotion(&event);
468: bContinueProcessing = true;
469: break;
470:
471: case SDL_MOUSEBUTTONDOWN:
472: if (event.button.button == SDL_BUTTON_LEFT)
473: {
1.1.1.2 root 474: // if (Keyboard.LButtonDblClk == 0)
475: // Keyboard.bLButtonDown |= BUTTON_MOUSE; /* Set button down flag */
1.1 root 476: }
477: else if (event.button.button == SDL_BUTTON_RIGHT)
478: {
1.1.1.2 root 479: // Keyboard.bRButtonDown |= BUTTON_MOUSE;
1.1 root 480: }
481: else if (event.button.button == SDL_BUTTON_MIDDLE)
482: {
1.1.1.2 root 483: /* Start double-click sequence in emulation time */
484: // Keyboard.LButtonDblClk = 1;
1.1 root 485: }
486: else if (event.button.button == SDL_BUTTON_WHEELDOWN)
487: {
1.1.1.2 root 488: /* Simulate pressing the "cursor down" key */
489: // IKBD_PressSTKey(0x50, true);
1.1 root 490: }
491: else if (event.button.button == SDL_BUTTON_WHEELUP)
492: {
1.1.1.2 root 493: /* Simulate pressing the "cursor up" key */
494: // IKBD_PressSTKey(0x48, true);
1.1 root 495: }
496: break;
497:
498: case SDL_MOUSEBUTTONUP:
499: if (event.button.button == SDL_BUTTON_LEFT)
500: {
1.1.1.2 root 501: // Keyboard.bLButtonDown &= ~BUTTON_MOUSE;
1.1 root 502: }
503: else if (event.button.button == SDL_BUTTON_RIGHT)
504: {
1.1.1.2 root 505: // Keyboard.bRButtonDown &= ~BUTTON_MOUSE;
1.1 root 506: }
507: else if (event.button.button == SDL_BUTTON_WHEELDOWN)
508: {
1.1.1.2 root 509: /* Simulate releasing the "cursor down" key */
510: // IKBD_PressSTKey(0x50, false);
1.1 root 511: }
512: else if (event.button.button == SDL_BUTTON_WHEELUP)
513: {
1.1.1.2 root 514: /* Simulate releasing the "cursor up" key */
515: // IKBD_PressSTKey(0x48, false);
1.1 root 516: }
517: break;
518:
519: case SDL_KEYDOWN:
1.1.1.3 root 520: // fprintf(stderr, "keydwn\n");
521: // Keymap_KeyDown(&event.key.keysym);
522: KeyTranslator(&event.key.keysym);
1.1 root 523: break;
524:
525: case SDL_KEYUP:
1.1.1.3 root 526: // Keymap_KeyUp(&event.key.keysym);
527: KeyRelease(&event.key.keysym);
1.1 root 528: break;
529:
530: default:
531: /* don't let unknown events delay event processing */
532: bContinueProcessing = true;
533: break;
534: }
535: } while (bContinueProcessing || !(bEmulationActive || bQuitProgram));
536: }
537:
538:
539: /*-----------------------------------------------------------------------*/
540: /**
1.1.1.2 root 541: * Set Hatari window title. Use NULL for default
542: */
543: void Main_SetTitle(const char *title)
544: {
545: if (title)
1.1.1.4 ! root 546: SDL_WM_SetCaption(title, "Previous");
1.1.1.2 root 547: else
1.1.1.4 ! root 548: SDL_WM_SetCaption(PROG_NAME, "Previous");
1.1.1.2 root 549: }
550:
551: /*-----------------------------------------------------------------------*/
552: /**
1.1 root 553: * Initialise emulation
554: */
555: static void Main_Init(void)
556: {
557: /* Open debug log file */
558: if (!Log_Init())
559: {
560: fprintf(stderr, "Logging/tracing initialization failed\n");
561: exit(-1);
562: }
563: Log_Printf(LOG_INFO, PROG_NAME ", compiled on: " __DATE__ ", " __TIME__ "\n");
564:
565: /* Init SDL's video subsystem. Note: Audio and joystick subsystems
566: will be initialized later (failures there are not fatal). */
567: if (SDL_Init(SDL_INIT_VIDEO | Opt_GetNoParachuteFlag()) < 0)
568: {
569: fprintf(stderr, "Could not initialize the SDL library:\n %s\n", SDL_GetError() );
570: exit(-1);
571: }
1.1.1.2 root 572: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType );
573: Resolution_Init();
1.1 root 574: SDLGui_Init();
575: Screen_Init();
1.1.1.2 root 576: Main_SetTitle(NULL);
577: // HostScreen_Init();
578: // DSP_Init();
579: // Floppy_Init();
1.1 root 580: M68000_Init(); /* Init CPU emulation */
1.1.1.2 root 581: // Audio_Init();
582: // DmaSnd_Init();
1.1.1.3 root 583: Keymap_Init();
1.1.1.2 root 584:
1.1.1.4 ! root 585:
1.1.1.2 root 586: /* call menu at startup */
1.1.1.4 ! root 587: if (!File_Exists(sConfigFileName) || ConfigureParams.ConfigDialog.bShowConfigDialogAtStartup)
! 588: Dialog_DoProperty();
! 589: else
! 590: Dialog_CheckFiles();
! 591:
1.1.1.2 root 592: if (bQuitProgram)
1.1.1.4 ! root 593: {
! 594: SDL_Quit();
! 595: exit(-2);
! 596: }
! 597:
! 598:
! 599: // const char *err_msg;
! 600: //
! 601: // while ((err_msg=Reset_Cold())!=NULL)
! 602: // {
! 603: // DlgMissing_Rom();
! 604: // if (bQuitProgram) {
! 605: // Main_RequestQuit();
! 606: // break;
! 607: // }
! 608: // }
! 609:
! 610: Reset_Cold();
! 611:
! 612: // if (bQuitProgram) {
! 613: // SDL_Quit();
! 614: // exit(-2);
! 615: // }
1.1 root 616: IoMem_Init();
617:
618: /* done as last, needs CPU & DSP running... */
619: DebugUI_Init();
620: }
621:
622:
623: /*-----------------------------------------------------------------------*/
624: /**
625: * Un-Initialise emulation
626: */
627: static void Main_UnInit(void)
628: {
629: Screen_ReturnFromFullScreen();
1.1.1.4 ! root 630: SCSI_Uninit();
1.1 root 631: IoMem_UnInit();
632: SDLGui_UnInit();
633: Screen_UnInit();
634: Exit680x0();
635:
636: /* SDL uninit: */
637: SDL_Quit();
638:
639: /* Close debug log file */
640: Log_UnInit();
641: }
642:
643:
644: /*-----------------------------------------------------------------------*/
645: /**
646: * Load initial configuration file(s)
647: */
648: static void Main_LoadInitialConfig(void)
649: {
650: char *psGlobalConfig;
651:
652: psGlobalConfig = malloc(FILENAME_MAX);
653: if (psGlobalConfig)
654: {
655: #if defined(__AMIGAOS4__)
656: strncpy(psGlobalConfig, CONFDIR"previous.cfg", FILENAME_MAX);
657: #else
658: snprintf(psGlobalConfig, FILENAME_MAX, CONFDIR"%cprevious.cfg", PATHSEP);
659: #endif
660: /* Try to load the global configuration file */
661: Configuration_Load(psGlobalConfig);
662:
663: free(psGlobalConfig);
664: }
665:
666: /* Now try the users configuration file */
667: Configuration_Load(NULL);
668: }
669:
670: /*-----------------------------------------------------------------------*/
671: /**
672: * Set TOS etc information and initial help message
673: */
674: static void Main_StatusbarSetup(void)
675: {
676: const char *name = NULL;
677: SDLKey key;
678:
679: key = ConfigureParams.Shortcut.withoutModifier[SHORTCUT_OPTIONS];
680: if (!key)
681: key = ConfigureParams.Shortcut.withModifier[SHORTCUT_OPTIONS];
682: if (key)
683: name = SDL_GetKeyName(key);
684: if (name)
685: {
686: char message[24], *keyname;
687: #ifdef _MUDFLAP
688: __mf_register(name, 32, __MF_TYPE_GUESS, "SDL keyname");
689: #endif
690: keyname = Str_ToUpper(strdup(name));
691: snprintf(message, sizeof(message), "Press %s for Options", keyname);
692: free(keyname);
693:
694: Statusbar_AddMessage(message, 6000);
695: }
696: /* update information loaded by Main_Init() */
697: Statusbar_UpdateInfo();
698: }
699:
700: /*-----------------------------------------------------------------------*/
701: /**
702: * Main
703: *
704: * Note: 'argv' cannot be declared const, MinGW would then fail to link.
705: */
706: int main(int argc, char *argv[])
707: {
708: /* Generate random seed */
709: srand(time(NULL));
710:
711: /* Initialize directory strings */
712: Paths_Init(argv[0]);
713:
714: /* Set default configuration values: */
715: Configuration_SetDefault();
716:
717: /* Now load the values from the configuration file */
718: Main_LoadInitialConfig();
719:
720: /* Check for any passed parameters */
1.1.1.2 root 721: if (!Opt_ParseParameters(argc, (const char * const *)argv))
1.1 root 722: {
723: return 1;
724: }
725: /* monitor type option might require "reset" -> true */
726: Configuration_Apply(true);
727:
728: #ifdef WIN32
729: Win_OpenCon();
730: #endif
731:
732: /* Needed on maemo but useful also with normal X11 window managers
733: * for window grouping when you have multiple Hatari SDL windows open
734: */
735: #if HAVE_SETENV
736: setenv("SDL_VIDEO_X11_WMCLASS", "previous", 1);
737: #endif
738:
739: /* Init emulator system */
740: Main_Init();
741:
742: /* Set initial Statusbar information */
743: Main_StatusbarSetup();
744:
745: /* Check if SDL_Delay is accurate */
746: Main_CheckForAccurateDelays();
747:
748:
749: /* Run emulation */
750: Main_UnPauseEmulation();
751: M68000_Start(); /* Start emulation */
752:
1.1.1.4 ! root 753:
1.1 root 754: /* Un-init emulation system */
755: Main_UnInit();
756:
757: return 0;
758: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.