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

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

unix.superglobalmegacorp.com

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