|
|
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.2 ! root 517: fprintf(stderr, "keydwn\n");
1.1 root 518: Keymap_KeyDown(&event.key.keysym);
1.1.1.2 ! root 519: ShortCut_ActKey();
1.1 root 520: break;
521:
522: case SDL_KEYUP:
523: Keymap_KeyUp(&event.key.keysym);
524: break;
525:
526: default:
527: /* don't let unknown events delay event processing */
528: bContinueProcessing = true;
529: break;
530: }
531: } while (bContinueProcessing || !(bEmulationActive || bQuitProgram));
532: }
533:
534:
535: /*-----------------------------------------------------------------------*/
536: /**
1.1.1.2 ! root 537: * Set Hatari window title. Use NULL for default
! 538: */
! 539: void Main_SetTitle(const char *title)
! 540: {
! 541: if (title)
! 542: SDL_WM_SetCaption(title, "Hatari");
! 543: else
! 544: SDL_WM_SetCaption(PROG_NAME, "Hatari");
! 545: }
! 546:
! 547: /*-----------------------------------------------------------------------*/
! 548: /**
1.1 root 549: * Initialise emulation
550: */
551: static void Main_Init(void)
552: {
553: /* Open debug log file */
554: if (!Log_Init())
555: {
556: fprintf(stderr, "Logging/tracing initialization failed\n");
557: exit(-1);
558: }
559: Log_Printf(LOG_INFO, PROG_NAME ", compiled on: " __DATE__ ", " __TIME__ "\n");
560:
561: /* Init SDL's video subsystem. Note: Audio and joystick subsystems
562: will be initialized later (failures there are not fatal). */
563: if (SDL_Init(SDL_INIT_VIDEO | Opt_GetNoParachuteFlag()) < 0)
564: {
565: fprintf(stderr, "Could not initialize the SDL library:\n %s\n", SDL_GetError() );
566: exit(-1);
567: }
1.1.1.2 ! root 568: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType );
! 569: Resolution_Init();
1.1 root 570: SDLGui_Init();
1.1.1.2 ! root 571: // Printer_Init();
! 572: // RS232_Init();
! 573: // Midi_Init();
1.1 root 574: Screen_Init();
1.1.1.2 ! root 575: Main_SetTitle(NULL);
! 576: // HostScreen_Init();
! 577: // DSP_Init();
! 578: // Floppy_Init();
1.1 root 579: M68000_Init(); /* Init CPU emulation */
1.1.1.2 ! root 580: // Audio_Init();
! 581: // DmaSnd_Init();
! 582: // Keymap_Init();
! 583:
! 584: /* Init HD emulation */
! 585: // HDC_Init();
! 586: // Ide_Init();
! 587: // GemDOS_Init();
! 588: // if (ConfigureParams.HardDisk.bUseHardDiskDirectories)
! 589: // {
! 590: /* uses variables set by HDC_Init()! */
! 591: // GemDOS_InitDrives();
! 592: // }
1.1 root 593:
594: if (Reset_Cold()) /* Reset all systems, load TOS image */
595: {
596: /* If loading of the TOS failed, we bring up the GUI to let the
597: * user choose another TOS ROM file. */
1.1.1.2 ! root 598: // Dialog_DoProperty();
1.1 root 599: }
1.1.1.2 ! root 600: /* call menu at startup */
! 601: Dialog_DoProperty();
! 602: if (bQuitProgram)
1.1 root 603: {
604: fprintf(stderr, "Failed to load TOS image!\n");
605: SDL_Quit();
606: exit(-2);
607: }
608:
609: IoMem_Init();
1.1.1.2 ! root 610: // NvRam_Init();
! 611: // Joy_Init();
! 612: // Sound_Init();
1.1 root 613:
614: /* done as last, needs CPU & DSP running... */
615: DebugUI_Init();
616: }
617:
618:
619: /*-----------------------------------------------------------------------*/
620: /**
621: * Un-Initialise emulation
622: */
623: static void Main_UnInit(void)
624: {
625: Screen_ReturnFromFullScreen();
1.1.1.2 ! root 626: // Floppy_UnInit();
! 627: // HDC_UnInit();
! 628: // Midi_UnInit();
! 629: // RS232_UnInit();
! 630: // Printer_UnInit();
1.1 root 631: IoMem_UnInit();
1.1.1.2 ! root 632: // NvRam_UnInit();
! 633: // GemDOS_UnInitDrives();
! 634: // Ide_UnInit();
! 635: // Joy_UnInit();
! 636: // if (Sound_AreWeRecording())
! 637: // Sound_EndRecording();
! 638: // Audio_UnInit();
1.1 root 639: SDLGui_UnInit();
1.1.1.2 ! root 640: // DSP_UnInit();
! 641: // HostScreen_UnInit();
1.1 root 642: Screen_UnInit();
643: Exit680x0();
644:
645: /* SDL uninit: */
646: SDL_Quit();
647:
648: /* Close debug log file */
649: Log_UnInit();
650: }
651:
652:
653: /*-----------------------------------------------------------------------*/
654: /**
655: * Load initial configuration file(s)
656: */
657: static void Main_LoadInitialConfig(void)
658: {
659: char *psGlobalConfig;
660:
661: psGlobalConfig = malloc(FILENAME_MAX);
662: if (psGlobalConfig)
663: {
664: #if defined(__AMIGAOS4__)
665: strncpy(psGlobalConfig, CONFDIR"previous.cfg", FILENAME_MAX);
666: #else
667: snprintf(psGlobalConfig, FILENAME_MAX, CONFDIR"%cprevious.cfg", PATHSEP);
668: #endif
669: /* Try to load the global configuration file */
670: Configuration_Load(psGlobalConfig);
671:
672: free(psGlobalConfig);
673: }
674:
675: /* Now try the users configuration file */
676: Configuration_Load(NULL);
677: }
678:
679: /*-----------------------------------------------------------------------*/
680: /**
681: * Set TOS etc information and initial help message
682: */
683: static void Main_StatusbarSetup(void)
684: {
685: const char *name = NULL;
686: SDLKey key;
687:
688: key = ConfigureParams.Shortcut.withoutModifier[SHORTCUT_OPTIONS];
689: if (!key)
690: key = ConfigureParams.Shortcut.withModifier[SHORTCUT_OPTIONS];
691: if (key)
692: name = SDL_GetKeyName(key);
693: if (name)
694: {
695: char message[24], *keyname;
696: #ifdef _MUDFLAP
697: __mf_register(name, 32, __MF_TYPE_GUESS, "SDL keyname");
698: #endif
699: keyname = Str_ToUpper(strdup(name));
700: snprintf(message, sizeof(message), "Press %s for Options", keyname);
701: free(keyname);
702:
703: Statusbar_AddMessage(message, 6000);
704: }
705: /* update information loaded by Main_Init() */
706: Statusbar_UpdateInfo();
707: }
708:
709: /*-----------------------------------------------------------------------*/
710: /**
711: * Main
712: *
713: * Note: 'argv' cannot be declared const, MinGW would then fail to link.
714: */
715: int main(int argc, char *argv[])
716: {
717: /* Generate random seed */
718: srand(time(NULL));
719:
720: /* Initialize directory strings */
721: Paths_Init(argv[0]);
722:
723: /* Set default configuration values: */
724: Configuration_SetDefault();
725:
726: /* Now load the values from the configuration file */
727: Main_LoadInitialConfig();
728:
729: /* Check for any passed parameters */
1.1.1.2 ! root 730: if (!Opt_ParseParameters(argc, (const char * const *)argv))
1.1 root 731: {
732: return 1;
733: }
734: /* monitor type option might require "reset" -> true */
735: Configuration_Apply(true);
736:
737: #ifdef WIN32
738: Win_OpenCon();
739: #endif
740:
741: /* Needed on maemo but useful also with normal X11 window managers
742: * for window grouping when you have multiple Hatari SDL windows open
743: */
744: #if HAVE_SETENV
745: setenv("SDL_VIDEO_X11_WMCLASS", "previous", 1);
746: #endif
747:
748: /* Init emulator system */
749: Main_Init();
750:
751: /* Set initial Statusbar information */
752: Main_StatusbarSetup();
753:
754: /* Check if SDL_Delay is accurate */
755: Main_CheckForAccurateDelays();
756:
1.1.1.2 ! root 757: // if ( AviRecordOnStartup ) /* Immediatly starts avi recording ? */
! 758: // Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop ,
! 759: // ConfigureParams.Video.AviRecordFps == 0 ?
! 760: // ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) :
! 761: // (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL ,
! 762: // 1 << CLOCKS_TIMINGS_SHIFT_VBL ,
! 763: // ConfigureParams.Video.AviRecordVcodec );
1.1 root 764:
765: /* Run emulation */
766: Main_UnPauseEmulation();
767: M68000_Start(); /* Start emulation */
768:
1.1.1.2 ! root 769: // if (bRecordingAvi)
! 770: // {
! 771: /* cleanly close the avi file */
! 772: // Statusbar_AddMessage("Finishing AVI file...", 100);
! 773: // Statusbar_Update(sdlscrn);
! 774: // Avi_StopRecording();
! 775: // }
1.1 root 776: /* Un-init emulation system */
777: Main_UnInit();
778:
779: return 0;
780: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.