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