Annotation of hatari/src/main.c, revision 1.1.1.18

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: }

unix.superglobalmegacorp.com

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