Annotation of previous/src/main.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.