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