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

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

unix.superglobalmegacorp.com

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