Annotation of hatari/src/statusbar.c, revision 1.1.1.8

1.1       root        1: /*
                      2:   Hatari - statusbar.c
                      3: 
1.1.1.8 ! root        4:   This file is distributed under the GNU General Public License, version 2
        !             5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   Code to draw statusbar area, floppy leds etc.
1.1.1.3   root        8: 
1.1       root        9:   Use like this:
                     10:   - Before screen surface is (re-)created Statusbar_SetHeight()
                     11:     has to be called with the new screen height. Add the returned
                     12:     value to screen height (zero means no statusbar).  After this,
                     13:     Statusbar_GetHeight() can be used to retrieve the statusbar size
                     14:   - After screen surface is (re-)created, call Statusbar_Init()
                     15:     to re-initialize / re-draw the statusbar
                     16:   - Call Statusbar_SetFloppyLed() to set floppy drive led ON/OFF,
                     17:     or call Statusbar_EnableHDLed() to enabled HD led for a while
                     18:   - Whenever screen is redrawn, call Statusbar_Update() to draw the
                     19:     updated information to the statusbar (outside of screen locking)
                     20:   - If screen redraws may be partial, Statusbar_OverlayRestore()
                     21:     needs to be called before locking the screen for drawing and
                     22:     Statusbar_OverlayBackup() needs to be called after screen unlocking,
                     23:     but before calling Statusbar_Update().  These are needed for
                     24:     hiding the overlay drive led when drive leds are turned OFF.
                     25:   - If other information shown by Statusbar (TOS version etc) changes,
                     26:     call Statusbar_UpdateInfo()
                     27: 
                     28:   TODO:
                     29:   - re-calculate colors on each update to make sure they're
                     30:     correct in Falcon & TT 8-bit palette modes?
                     31:   - call Statusbar_AddMessage() from log.c?
                     32: */
1.1.1.3   root       33: const char Statusbar_fileid[] = "Hatari statusbar.c : " __DATE__ " " __TIME__;
1.1       root       34: 
                     35: #include <assert.h>
                     36: #include "main.h"
                     37: #include "configuration.h"
                     38: #include "screenSnapShot.h"
                     39: #include "sdlgui.h"
                     40: #include "statusbar.h"
                     41: #include "tos.h"
1.1.1.5   root       42: #include "screen.h"
1.1       root       43: #include "video.h"
                     44: #include "wavFormat.h"
                     45: #include "ymFormat.h"
1.1.1.4   root       46: #include "avi_record.h"
1.1       root       47: 
                     48: #define DEBUG 0
                     49: #if DEBUG
1.1.1.7   root       50: #include <execinfo.h>
                     51: # define DEBUGPRINT(x) printf x
1.1       root       52: #else
                     53: #define DEBUGPRINT(x)
                     54: #endif
                     55: 
                     56: #define MAX_DRIVE_LEDS (DRIVE_LED_HD + 1)
                     57: 
                     58: /* whether drive leds should be ON and their previous shown state */
                     59: static struct {
1.1.1.8 ! root       60:        drive_led_t state;
        !            61:        drive_led_t oldstate;
1.1       root       62:        Uint32 expire;  /* when to disable led, valid only if >0 && state=TRUE */
                     63:        int offset;     /* led x-pos on screen */
                     64: } Led[MAX_DRIVE_LEDS];
                     65: 
1.1.1.8 ! root       66: 
1.1       root       67: /* drive leds size & y-pos */
                     68: static SDL_Rect LedRect;
                     69: 
                     70: /* overlay led size & pos */
                     71: static SDL_Rect OverlayLedRect;
                     72: 
                     73: /* screen contents left under overlay led */
                     74: static SDL_Surface *OverlayUnderside;
                     75: 
                     76: static enum {
                     77:        OVERLAY_NONE,
                     78:        OVERLAY_DRAWN,
                     79:        OVERLAY_RESTORED
                     80: } bOverlayState;
                     81: 
                     82: static SDL_Rect RecLedRect;
                     83: static bool bOldRecording;
                     84: 
                     85: /* led colors */
1.1.1.8 ! root       86: static Uint32 LedColor[ MAX_LED_STATE ];
        !            87: static Uint32 RecColorOn, RecColorOff;
1.1       root       88: static Uint32 GrayBg, LedColorBg;
                     89: 
                     90: 
1.1.1.8 ! root       91: #define MAX_MESSAGE_LEN 34
1.1       root       92: typedef struct msg_item {
                     93:        struct msg_item *next;
                     94:        char msg[MAX_MESSAGE_LEN+1];
                     95:        Uint32 timeout; /* msecs, zero=no timeout */
                     96:        Uint32 expire;  /* when to expire message */
                     97:        bool shown;
                     98: } msg_item_t;
                     99: 
                    100: static msg_item_t DefaultMessage;
                    101: static msg_item_t *MessageList = &DefaultMessage;
                    102: static SDL_Rect MessageRect;
                    103: 
1.1.1.4   root      104: /* rect for both frame skip value and fast forward indicator */
1.1       root      105: static SDL_Rect FrameSkipsRect;
                    106: static int nOldFrameSkips;
1.1.1.4   root      107: static int bOldFastForward;
1.1       root      108: 
                    109: 
                    110: /* screen height above statusbar and height of statusbar below screen */
                    111: static int ScreenHeight;
                    112: static int StatusbarHeight;
                    113: 
                    114: 
                    115: /*-----------------------------------------------------------------------*/
                    116: /**
1.1.1.4   root      117:  * Return statusbar height for given width and height
1.1       root      118:  */
1.1.1.4   root      119: int Statusbar_GetHeightForSize(int width, int height)
1.1       root      120: {
                    121:        if (ConfigureParams.Screen.bShowStatusbar) {
                    122:                /* Should check the same thing as SDLGui_SetScreen()
                    123:                 * does to decide the font size.
                    124:                 */
1.1.1.3   root      125:                if (width >= 640 && height >= (400-24)) {
1.1.1.7   root      126:                        DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 24));
1.1.1.4   root      127:                        return 24;
1.1       root      128:                } else {
1.1.1.7   root      129:                        DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 12));
1.1.1.4   root      130:                        return 12;
1.1       root      131:                }
                    132:        }
1.1.1.7   root      133:        DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 0));
1.1.1.4   root      134:        return 0;
                    135: }
                    136: 
                    137: /*-----------------------------------------------------------------------*/
                    138: /**
                    139:  * Set screen height used for statusbar height calculation.
                    140:  *
                    141:  * Return height of statusbar that should be added to the screen
                    142:  * height when screen is (re-)created, or zero if statusbar will
                    143:  * not be shown
                    144:  */
                    145: int Statusbar_SetHeight(int width, int height)
                    146: {
1.1.1.7   root      147: #if DEBUG
                    148:        /* find out from where the set height is called */
                    149:        void *addr[8];
                    150:        int count = backtrace(addr, sizeof(addr)/sizeof(*addr));
                    151:        backtrace_symbols_fd(addr, count, fileno(stderr));
                    152: #endif
1.1.1.4   root      153:        ScreenHeight = height;
                    154:        StatusbarHeight = Statusbar_GetHeightForSize(width, height);
1.1.1.6   root      155:        DEBUGPRINT(("Statusbar_SetHeight(%d, %d) -> %d\n", width, height, StatusbarHeight));
1.1       root      156:        return StatusbarHeight;
                    157: }
                    158: 
                    159: /*-----------------------------------------------------------------------*/
                    160: /**
                    161:  * Return height of statusbar set with Statusbar_SetHeight()
                    162:  */
                    163: int Statusbar_GetHeight(void)
                    164: {
                    165:        return StatusbarHeight;
                    166: }
                    167: 
                    168: 
                    169: /*-----------------------------------------------------------------------*/
                    170: /**
                    171:  * Enable HD drive led, it will be automatically disabled after a while.
                    172:  */
1.1.1.8 ! root      173: void Statusbar_EnableHDLed(drive_led_t state)
1.1       root      174: {
                    175:        /* leds are shown for 1/2 sec after enabling */
                    176:        Led[DRIVE_LED_HD].expire = SDL_GetTicks() + 1000/2;
1.1.1.8 ! root      177:        Led[DRIVE_LED_HD].state = state;
1.1       root      178: }
                    179: 
                    180: /*-----------------------------------------------------------------------*/
                    181: /**
                    182:  * Set given floppy drive led state, anything enabling led with this
                    183:  * needs also to take care of disabling it.
                    184:  */
1.1.1.8 ! root      185: void Statusbar_SetFloppyLed(drive_index_t drive, drive_led_t state)
1.1       root      186: {
                    187:        assert(drive == DRIVE_LED_A || drive == DRIVE_LED_B);
                    188:        Led[drive].state = state;
                    189: }
                    190: 
                    191: 
                    192: /*-----------------------------------------------------------------------*/
                    193: /**
                    194:  * Set overlay led size/pos on given screen to internal Rect
                    195:  * and free previous resources.
                    196:  */
                    197: static void Statusbar_OverlayInit(const SDL_Surface *surf)
                    198: {
                    199:        int h;
                    200:        /* led size/pos needs to be re-calculated in case screen changed */
                    201:        h = surf->h / 50;
                    202:        OverlayLedRect.w = 2*h;
                    203:        OverlayLedRect.h = h;
                    204:        OverlayLedRect.x = surf->w - 5*h/2;
                    205:        OverlayLedRect.y = h/2;
                    206:        /* free previous restore surface if it's incompatible */
                    207:        if (OverlayUnderside &&
                    208:            OverlayUnderside->w == OverlayLedRect.w &&
                    209:            OverlayUnderside->h == OverlayLedRect.h &&
                    210:            OverlayUnderside->format->BitsPerPixel == surf->format->BitsPerPixel) {
                    211:                SDL_FreeSurface(OverlayUnderside);
                    212:                OverlayUnderside = NULL;
                    213:        }
                    214:        bOverlayState = OVERLAY_NONE;
                    215: }
                    216: 
                    217: /*-----------------------------------------------------------------------*/
                    218: /**
                    219:  * (re-)initialize statusbar internal variables for given screen surface
                    220:  * (sizes&colors may need to be re-calculated for the new SDL surface)
                    221:  * and draw the statusbar background.
                    222:  */
                    223: void Statusbar_Init(SDL_Surface *surf)
                    224: {
                    225:        msg_item_t *item;
                    226:        SDL_Rect ledbox, sbarbox;
                    227:        int i, fontw, fonth, offset;
                    228:        const char *text[MAX_DRIVE_LEDS] = { "A:", "B:", "HD:" };
                    229: 
1.1.1.6   root      230:        DEBUGPRINT(("Statusbar_Init()\n"));
1.1       root      231:        assert(surf);
                    232: 
                    233:        /* dark green and light green for leds themselves */
1.1.1.8 ! root      234:        LedColor[ LED_STATE_OFF ]       = SDL_MapRGB(surf->format, 0x00, 0x40, 0x00);
        !           235:        LedColor[ LED_STATE_ON ]        = SDL_MapRGB(surf->format, 0x00, 0xc0, 0x00);
        !           236:        LedColor[ LED_STATE_ON_BUSY ]   = SDL_MapRGB(surf->format, 0x00, 0xe0, 0x00);
1.1       root      237:        LedColorBg  = SDL_MapRGB(surf->format, 0x00, 0x00, 0x00);
                    238:        RecColorOff = SDL_MapRGB(surf->format, 0x40, 0x00, 0x00);
                    239:        RecColorOn  = SDL_MapRGB(surf->format, 0xe0, 0x00, 0x00);
                    240:        GrayBg      = SDL_MapRGB(surf->format, 0xc0, 0xc0, 0xc0);
                    241: 
                    242:        /* disable leds */
                    243:        for (i = 0; i < MAX_DRIVE_LEDS; i++) {
1.1.1.8 ! root      244:                Led[i].state = Led[i].oldstate = LED_STATE_OFF;
1.1       root      245:                Led[i].expire = 0;
                    246:        }
                    247:        Statusbar_OverlayInit(surf);
                    248:        
                    249:        /* disable statusbar if it doesn't fit to video mode */
                    250:        if (surf->h < ScreenHeight + StatusbarHeight) {
                    251:                StatusbarHeight = 0;
                    252:        }
                    253:        if (!StatusbarHeight) {
1.1.1.6   root      254:                DEBUGPRINT(("Doesn't fit <- Statusbar_Init()\n"));
1.1       root      255:                return;
                    256:        }
                    257: 
                    258:        /* prepare fonts */
                    259:        SDLGui_Init();
                    260:        SDLGui_SetScreen(surf);
                    261:        SDLGui_GetFontSize(&fontw, &fonth);
                    262: 
                    263:        /* video mode didn't match, need to recalculate sizes */
                    264:        if (surf->h > ScreenHeight + StatusbarHeight) {
                    265:                StatusbarHeight = fonth + 2;
                    266:                /* actually statusbar vertical offset */
                    267:                ScreenHeight = surf->h - StatusbarHeight;
                    268:        } else {
                    269:                assert(fonth+2 < StatusbarHeight);
                    270:        }
                    271: 
                    272:        /* draw statusbar background gray so that text shows */
                    273:        sbarbox.x = 0;
                    274:        sbarbox.y = surf->h - StatusbarHeight;
                    275:        sbarbox.w = surf->w;
                    276:        sbarbox.h = StatusbarHeight;
                    277:        SDL_FillRect(surf, &sbarbox, GrayBg);
                    278: 
                    279:        /* led size */
1.1.1.4   root      280:        LedRect.w = fonth/2;
1.1       root      281:        LedRect.h = fonth - 4;
                    282:        LedRect.y = ScreenHeight + StatusbarHeight/2 - LedRect.h/2;
1.1.1.4   root      283: 
1.1       root      284:        /* black box for the leds */
                    285:        ledbox = LedRect;
                    286:        ledbox.y -= 1;
                    287:        ledbox.w += 2;
                    288:        ledbox.h += 2;
                    289: 
                    290:        offset = fontw;
                    291:        MessageRect.y = LedRect.y - 2;
                    292:        /* draw led texts and boxes + calculate box offsets */
                    293:        for (i = 0; i < MAX_DRIVE_LEDS; i++) {
                    294:                SDLGui_Text(offset, MessageRect.y, text[i]);
                    295:                offset += strlen(text[i]) * fontw;
                    296:                offset += fontw/2;
                    297: 
                    298:                ledbox.x = offset - 1;
                    299:                SDL_FillRect(surf, &ledbox, LedColorBg);
                    300: 
                    301:                LedRect.x = offset;
1.1.1.8 ! root      302:                SDL_FillRect(surf, &LedRect, LedColor[ LED_STATE_OFF ]);
1.1       root      303: 
                    304:                Led[i].offset = offset;
1.1.1.4   root      305:                offset += LedRect.w + fontw;
1.1       root      306:        }
                    307: 
                    308:        /* draw frameskip */
                    309:        FrameSkipsRect.x = offset;
                    310:        FrameSkipsRect.y = MessageRect.y;
                    311:        SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "FS:");
                    312:        FrameSkipsRect.x += 3 * fontw + fontw/2;
1.1.1.4   root      313:        FrameSkipsRect.w = 4 * fontw;
1.1       root      314:        FrameSkipsRect.h = fonth;
1.1.1.4   root      315: 
                    316:        if(ConfigureParams.System.bFastForward) {
                    317:                SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0 >>");
                    318:        } else {
                    319:                SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0");
                    320:        }
                    321: 
1.1       root      322:        nOldFrameSkips = 0;
1.1.1.4   root      323: 
1.1       root      324:        /* intialize messages */
1.1.1.4   root      325:        MessageRect.x = FrameSkipsRect.x + FrameSkipsRect.w + fontw;
1.1       root      326:        MessageRect.w = MAX_MESSAGE_LEN * fontw;
                    327:        MessageRect.h = fonth;
                    328:        for (item = MessageList; item; item = item->next) {
1.1.1.3   root      329:                item->shown = false;
1.1       root      330:        }
                    331: 
                    332:        /* draw recording led box */
                    333:        RecLedRect = LedRect;
                    334:        RecLedRect.x = surf->w - fontw - RecLedRect.w;
                    335:        ledbox.x = RecLedRect.x - 1;
                    336:        SDLGui_Text(ledbox.x - 4*fontw - fontw/2, MessageRect.y, "REC:");
                    337:        SDL_FillRect(surf, &ledbox, LedColorBg);
                    338:        SDL_FillRect(surf, &RecLedRect, RecColorOff);
1.1.1.3   root      339:        bOldRecording = false;
1.1       root      340: 
                    341:        /* and blit statusbar on screen */
                    342:        SDL_UpdateRects(surf, 1, &sbarbox);
1.1.1.6   root      343:        DEBUGPRINT(("Drawn <- Statusbar_Init()\n"));
1.1       root      344: }
                    345: 
                    346: 
                    347: /*-----------------------------------------------------------------------*/
                    348: /**
                    349:  * Qeueue new statusbar message 'msg' to be shown for 'msecs' milliseconds
                    350:  */
                    351: void Statusbar_AddMessage(const char *msg, Uint32 msecs)
                    352: {
                    353:        msg_item_t *item;
                    354: 
                    355:        if (!ConfigureParams.Screen.bShowStatusbar) {
                    356:                /* no sense in queuing messages that aren't shown */
                    357:                return;
                    358:        }
                    359:        item = calloc(1, sizeof(msg_item_t));
                    360:        assert(item);
                    361: 
                    362:        item->next = MessageList;
                    363:        MessageList = item;
                    364: 
                    365:        strncpy(item->msg, msg, MAX_MESSAGE_LEN);
                    366:        item->msg[MAX_MESSAGE_LEN] = '\0';
                    367:        DEBUGPRINT(("Add message: '%s'\n", item->msg));
                    368: 
                    369:        if (msecs) {
                    370:                item->timeout = msecs;
                    371:        } else {
                    372:                /* show items by default for 2.5 secs */
                    373:                item->timeout = 2500;
                    374:        }
1.1.1.3   root      375:        item->shown = false;
1.1       root      376: }
                    377: 
                    378: /*-----------------------------------------------------------------------*/
                    379: /**
                    380:  * Write given 'more' string to 'buffer' and return new end of 'buffer'
                    381:  */
                    382: static char *Statusbar_AddString(char *buffer, const char *more)
                    383: {
                    384:        while(*more) {
                    385:                *buffer++ = *more++;
                    386:        }
                    387:        return buffer;
                    388: }
                    389: 
                    390: /*-----------------------------------------------------------------------*/
                    391: /**
                    392:  * Retrieve/update default statusbar information
                    393:  */
                    394: void Statusbar_UpdateInfo(void)
                    395: {
                    396:        char *end = DefaultMessage.msg;
                    397: 
1.1.1.4   root      398:        /* CPU MHz */
                    399:        if (ConfigureParams.System.nCpuFreq > 9) {
                    400:                *end++ = '0' + ConfigureParams.System.nCpuFreq / 10;
                    401:        }
                    402:        *end++ = '0' + ConfigureParams.System.nCpuFreq % 10;
                    403:        end = Statusbar_AddString(end, "MHz/");
                    404: 
                    405:        /* CPU type */
                    406:        if(ConfigureParams.System.nCpuLevel > 0) {
                    407:                *end++ = '0';
                    408:                *end++ = '0' + ConfigureParams.System.nCpuLevel % 10;
                    409:                *end++ = '0';
                    410:                *end++ = '/';
                    411:        }
                    412: 
1.1       root      413:        /* amount of memory */
                    414:        if (ConfigureParams.Memory.nMemorySize > 9) {
                    415:                *end++ = '1';
                    416:                *end++ = '0' + ConfigureParams.Memory.nMemorySize % 10;
                    417:        } else {
                    418:                if (ConfigureParams.Memory.nMemorySize) {
                    419:                        *end++ = '0' + ConfigureParams.Memory.nMemorySize;
                    420:                } else {
1.1.1.7   root      421:                        end = Statusbar_AddString(end, "0.5");
1.1       root      422:                }
                    423:        }
                    424:        end = Statusbar_AddString(end, "MB ");
1.1.1.4   root      425: 
1.1       root      426:        /* machine type */
                    427:        switch (ConfigureParams.System.nMachineType) {
                    428:        case MACHINE_ST:
                    429:                end = Statusbar_AddString(end, "ST");
                    430:                break;
                    431:        case MACHINE_STE:
                    432:                end = Statusbar_AddString(end, "STE");
                    433:                break;
1.1.1.5   root      434:        case MACHINE_MEGA_STE:
1.1.1.7   root      435:                end = Statusbar_AddString(end, "MegaSTE");
1.1.1.5   root      436:                break;
1.1       root      437:        case MACHINE_TT:
                    438:                end = Statusbar_AddString(end, "TT");
                    439:                break;
                    440:        case MACHINE_FALCON:
                    441:                end = Statusbar_AddString(end, "Falcon");
                    442:                break;
                    443:        default:
                    444:                end = Statusbar_AddString(end, "???");
                    445:                break;
                    446:        }
                    447: 
                    448:        /* TOS type/version */
                    449:        if (bIsEmuTOS) {
                    450:                end = Statusbar_AddString(end, ", EmuTOS");
                    451:        } else {
                    452:                end = Statusbar_AddString(end, ", TOS v");
                    453:                *end++ = '0' + ((TosVersion & 0xf00) >> 8);
                    454:                *end++ = '.';
                    455:                *end++ = '0' + ((TosVersion & 0xf0) >> 4);
                    456:                *end++ = '0' + (TosVersion & 0xf);
                    457:        }
                    458:        *end = '\0';
1.1.1.4   root      459: 
1.1       root      460:        assert(end - DefaultMessage.msg < MAX_MESSAGE_LEN);
                    461:        DEBUGPRINT(("Set default message: '%s'\n", DefaultMessage.msg));
1.1.1.5   root      462:        /* make sure default message gets (re-)drawn when next checked */
1.1.1.3   root      463:        DefaultMessage.shown = false;
1.1       root      464: }
                    465: 
                    466: /*-----------------------------------------------------------------------*/
                    467: /**
                    468:  * Draw 'msg' centered to the message area
                    469:  */
                    470: static void Statusbar_DrawMessage(SDL_Surface *surf, const char *msg)
                    471: {
                    472:        int fontw, fonth, offset;
                    473:        SDL_FillRect(surf, &MessageRect, GrayBg);
                    474:        if (*msg) {
                    475:                SDLGui_GetFontSize(&fontw, &fonth);
                    476:                offset = (MessageRect.w - strlen(msg) * fontw) / 2;
                    477:                SDLGui_Text(MessageRect.x + offset, MessageRect.y, msg);
                    478:        }
                    479:        SDL_UpdateRects(surf, 1, &MessageRect);
                    480:        DEBUGPRINT(("Draw message: '%s'\n", msg));
                    481: }
                    482: 
                    483: /*-----------------------------------------------------------------------*/
                    484: /**
                    485:  * If message's not shown, show it.  If message's timed out,
                    486:  * remove it and show next one.
                    487:  */
                    488: static void Statusbar_ShowMessage(SDL_Surface *surf, Uint32 ticks)
                    489: {
                    490:        msg_item_t *next;
                    491: 
                    492:        if (MessageList->shown) {
                    493:                if (!MessageList->expire) {
1.1.1.5   root      494:                        /* last/default message newer expires */
1.1       root      495:                        return;
                    496:                }
                    497:                if (MessageList->expire > ticks) {
                    498:                        /* not timed out yet */
                    499:                        return;
                    500:                }
                    501:                assert(MessageList->next); /* last message shouldn't end here */
                    502:                next = MessageList->next;
                    503:                free(MessageList);
                    504:                MessageList = next;
                    505:                /* make sure next message gets shown */
1.1.1.3   root      506:                MessageList->shown = false;
1.1       root      507:        }
                    508:        if (!MessageList->shown) {
                    509:                /* not shown yet, show */
                    510:                Statusbar_DrawMessage(surf,  MessageList->msg);
                    511:                if (MessageList->timeout && !MessageList->expire) {
                    512:                        MessageList->expire = ticks + MessageList->timeout;
                    513:                }
1.1.1.3   root      514:                MessageList->shown = true;
1.1       root      515:        }
                    516: }
                    517: 
                    518: 
                    519: /*-----------------------------------------------------------------------*/
                    520: /**
                    521:  * Save the area that will be left under overlay led
                    522:  */
                    523: void Statusbar_OverlayBackup(SDL_Surface *surf)
                    524: {
1.1.1.3   root      525:        if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
                    526:            || !ConfigureParams.Screen.bShowDriveLed) {
1.1       root      527:                /* overlay not used with statusbar */
                    528:                return;
                    529:        }
                    530:        assert(surf);
                    531:        if (!OverlayUnderside) {
                    532:                SDL_Surface *bak;
                    533:                SDL_PixelFormat *fmt = surf->format;
                    534:                bak = SDL_CreateRGBSurface(surf->flags,
                    535:                                           OverlayLedRect.w, OverlayLedRect.h,
                    536:                                           fmt->BitsPerPixel,
                    537:                                           fmt->Rmask, fmt->Gmask, fmt->Bmask,
                    538:                                           fmt->Amask);
                    539:                assert(bak);
                    540:                OverlayUnderside = bak;
                    541:        }
                    542:        SDL_BlitSurface(surf, &OverlayLedRect, OverlayUnderside, NULL);
                    543: }
                    544: 
                    545: /*-----------------------------------------------------------------------*/
                    546: /**
                    547:  * Restore the area left under overlay led
                    548:  */
                    549: void Statusbar_OverlayRestore(SDL_Surface *surf)
                    550: {
1.1.1.3   root      551:        if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
                    552:            || !ConfigureParams.Screen.bShowDriveLed) {
1.1       root      553:                /* overlay not used with statusbar */
                    554:                return;
                    555:        }
                    556:        if (bOverlayState == OVERLAY_DRAWN && OverlayUnderside) {
                    557:                assert(surf);
                    558:                SDL_BlitSurface(OverlayUnderside, NULL, surf, &OverlayLedRect);
                    559:                /* this will make the draw function to update this the screen */
                    560:                bOverlayState = OVERLAY_RESTORED;
                    561:        }
                    562: }
                    563: 
                    564: /*-----------------------------------------------------------------------*/
                    565: /**
                    566:  * Draw overlay led
                    567:  */
                    568: static void Statusbar_OverlayDrawLed(SDL_Surface *surf, Uint32 color)
                    569: {
                    570:        SDL_Rect rect;
                    571:        if (bOverlayState == OVERLAY_DRAWN) {
                    572:                /* some led already drawn */
                    573:                return;
                    574:        }
                    575:        bOverlayState = OVERLAY_DRAWN;
                    576: 
                    577:        /* enabled led with border */
                    578:        rect = OverlayLedRect;
                    579:        rect.x += 1;
                    580:        rect.y += 1;
                    581:        rect.w -= 2;
                    582:        rect.h -= 2;
                    583:        SDL_FillRect(surf, &OverlayLedRect, LedColorBg);
                    584:        SDL_FillRect(surf, &rect, color);
                    585: }
                    586: 
                    587: /*-----------------------------------------------------------------------*/
                    588: /**
                    589:  * Draw overlay led onto screen surface if any drives are enabled.
                    590:  */
                    591: static void Statusbar_OverlayDraw(SDL_Surface *surf)
                    592: {
                    593:        Uint32 currentticks = SDL_GetTicks();
                    594:        int i;
                    595: 
                    596:        assert(surf);
1.1.1.4   root      597:        if (bRecordingYM || bRecordingWav || bRecordingAvi) {
1.1       root      598:                Statusbar_OverlayDrawLed(surf, RecColorOn);
                    599:        }
                    600:        for (i = 0; i < MAX_DRIVE_LEDS; i++) {
                    601:                if (Led[i].state) {
                    602:                        if (Led[i].expire && Led[i].expire < currentticks) {
1.1.1.8 ! root      603:                                Led[i].state = LED_STATE_OFF;
1.1       root      604:                                continue;
                    605:                        }
1.1.1.8 ! root      606:                        Statusbar_OverlayDrawLed(surf, LedColor[ Led[i].state ]);
1.1       root      607:                        break;
                    608:                }
                    609:        }
                    610:        /* possible state transitions:
                    611:         *   NONE -> DRAWN -> RESTORED -> DRAWN -> RESTORED -> NONE
                    612:         * Other than NONE state needs to be updated on screen
                    613:         */
                    614:        switch (bOverlayState) {
                    615:        case OVERLAY_RESTORED:
                    616:                bOverlayState = OVERLAY_NONE;
                    617:        case OVERLAY_DRAWN:
                    618:                SDL_UpdateRects(surf, 1, &OverlayLedRect);
                    619:                DEBUGPRINT(("Overlay LED = %s\n", bOverlayState==OVERLAY_DRAWN?"ON":"OFF"));
                    620:                break;
                    621:        case OVERLAY_NONE:
                    622:                break;
                    623:        }
                    624: }
                    625: 
                    626: 
                    627: /*-----------------------------------------------------------------------*/
                    628: /**
                    629:  * Update statusbar information (leds etc) if/when needed.
                    630:  * 
                    631:  * May not be called when screen is locked (SDL limitation).
                    632:  */
                    633: void Statusbar_Update(SDL_Surface *surf)
                    634: {
                    635:        Uint32 color, currentticks;
                    636:        SDL_Rect rect;
                    637:        int i;
                    638: 
                    639:        if (!(StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)) {
                    640:                /* not enabled (anymore), show overlay led instead? */
                    641:                if (ConfigureParams.Screen.bShowDriveLed) {
                    642:                        Statusbar_OverlayDraw(surf);
                    643:                }
                    644:                return;
                    645:        }
                    646:        assert(surf);
                    647:        /* Statusbar_Init() not called before this? */
1.1.1.6   root      648: #if DEBUG
                    649:        if (surf->h != ScreenHeight + StatusbarHeight) {
                    650:                printf("%d != %d + %d\n", surf->h, ScreenHeight, StatusbarHeight);
                    651:        }
                    652: #endif
1.1       root      653:        assert(surf->h == ScreenHeight + StatusbarHeight);
                    654: 
                    655:        rect = LedRect;
                    656:        currentticks = SDL_GetTicks();
                    657:        for (i = 0; i < MAX_DRIVE_LEDS; i++) {
                    658:                if (Led[i].expire && Led[i].expire < currentticks) {
1.1.1.8 ! root      659:                        Led[i].state = LED_STATE_OFF;
1.1       root      660:                }
                    661:                if (Led[i].state == Led[i].oldstate) {
                    662:                        continue;
                    663:                }
                    664:                Led[i].oldstate = Led[i].state;
1.1.1.8 ! root      665:                color = LedColor[ Led[i].state ];
1.1       root      666:                rect.x = Led[i].offset;
                    667:                SDL_FillRect(surf, &rect, color);
                    668:                SDL_UpdateRects(surf, 1, &rect);
1.1.1.8 ! root      669:                DEBUGPRINT(("LED[%d] = %d\n", i, Led[i].state));
1.1       root      670:        }
1.1.1.4   root      671: 
1.1       root      672:        Statusbar_ShowMessage(surf, currentticks);
                    673: 
1.1.1.4   root      674:        if (nOldFrameSkips != nFrameSkips ||
                    675:            bOldFastForward != ConfigureParams.System.bFastForward) {
                    676:                char fscount[5];
                    677:                int end = 2;
                    678: 
1.1.1.3   root      679:                if (nFrameSkips < 10)
                    680:                        fscount[0] = '0' + nFrameSkips;
                    681:                else
                    682:                        fscount[0] = 'X';
1.1.1.4   root      683:                fscount[1] = ' ';
                    684:                if(ConfigureParams.System.bFastForward) {
                    685:                        fscount[2] = '>';
                    686:                        fscount[3] = '>';
                    687:                        end = 4;
                    688:                }
                    689:                fscount[end] = '\0';
                    690: 
1.1       root      691:                SDL_FillRect(surf, &FrameSkipsRect, GrayBg);
                    692:                SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, fscount);
                    693:                SDL_UpdateRects(surf, 1, &FrameSkipsRect);
                    694:                DEBUGPRINT(("FS = %s\n", fscount));
                    695:                nOldFrameSkips = nFrameSkips;
1.1.1.4   root      696:                bOldFastForward = ConfigureParams.System.bFastForward;
1.1       root      697:        }
                    698: 
1.1.1.4   root      699:        if ((bRecordingYM || bRecordingWav || bRecordingAvi)
1.1       root      700:            != bOldRecording) {
                    701:                bOldRecording = !bOldRecording;
                    702:                if (bOldRecording) {
                    703:                        color = RecColorOn;
                    704:                } else {
                    705:                        color = RecColorOff;
                    706:                }
                    707:                SDL_FillRect(surf, &RecLedRect, color);
                    708:                SDL_UpdateRects(surf, 1, &RecLedRect);
                    709:                DEBUGPRINT(("REC = ON\n"));
                    710:        }
                    711: }

unix.superglobalmegacorp.com

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