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