Annotation of previous_trunk/src/fast_screen.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - screen.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at your
                      5:   option any later version. Read the file gpl.txt for details.
                      6: 
                      7:  (SC) Simon Schubiger - most of it rewritten for Previous NeXT emulator
                      8: */
                      9: 
                     10: #include <SDL.h>
                     11: #include <SDL_endian.h>
                     12: #include <SDL_blendmode.h>
                     13: 
                     14: const char Screen_fileid[] = "Previous fast_screen.c : " __DATE__ " " __TIME__;
                     15: 
                     16: #include "main.h"
                     17: #include "configuration.h"
                     18: #include "log.h"
                     19: #include "m68000.h"
                     20: #include "dimension.hpp"
                     21: #include "nd_mem.hpp"
                     22: #include "paths.h"
                     23: #include "screen.h"
                     24: #include "statusbar.h"
                     25: #include "video.h"
                     26: 
                     27: SDL_Window*   sdlWindow;
                     28: SDL_Surface*  sdlscrn = NULL;   /* The SDL screen surface */
                     29: int nScreenZoomX, nScreenZoomY; /* Zooming factors, used for scaling mouse motions */
                     30: 
                     31: /* extern for shortcuts */
                     32: volatile bool bGrabMouse    = false; /* Grab the mouse cursor in the window */
                     33: volatile bool bInFullScreen = false; /* true if in full screen */
                     34: 
                     35: static const int NeXT_SCRN_WIDTH  = 1120;
                     36: static const int NeXT_SCRN_HEIGHT = 832;
                     37: 
                     38: static SDL_Thread*   repaintThread;
                     39: static SDL_Renderer* sdlRenderer;
                     40: static SDL_sem*      initLatch;
                     41: static SDL_atomic_t  blitFB;
                     42: static SDL_atomic_t  blitUI;           /* When value == 1, the repaint thread will blit the sldscrn surface to the screen on the next redraw */
                     43: static bool          doUIblit;
                     44: static SDL_Rect      saveWindowBounds; /* Window bounds before going fullscreen. Used to restore window size & position. */
                     45: static void*         uiBuffer;         /* uiBuffer used for ui texture */
                     46: static void*         uiBufferTmp;      /* Temporary uiBuffer used by repainter */
                     47: static SDL_SpinLock  uiBufferLock;     /* Lock for concurrent access to UI buffer between m68k thread and repainter */
                     48: static Uint32        mask;             /* green screen mask for transparent UI areas */
                     49: static volatile bool doRepaint  = true; /* Repaint thread runs while true */
                     50: static SDL_Rect      statusBar;
                     51: 
                     52: 
                     53: static Uint32 BW2RGB[0x400];
                     54: static Uint32 COL2RGB[0x10000];
                     55: 
                     56: static Uint32 bw2rgb(SDL_PixelFormat* format, int bw) {
                     57:     switch(bw & 3) {
                     58:         case 3:  return SDL_MapRGB(format, 0,   0,   0);
                     59:         case 2:  return SDL_MapRGB(format, 85,  85,  85);
                     60:         case 1:  return SDL_MapRGB(format, 170, 170, 170);
                     61:         case 0:  return SDL_MapRGB(format, 255, 255, 255);
                     62:         default: return 0;
                     63:     }
                     64: }
                     65: 
                     66: static Uint32 col2rgb(SDL_PixelFormat* format, int col) {
                     67:     int r = col & 0xF000; r >>= 12; r |= r << 4;
                     68:     int g = col & 0x0F00; g >>= 8;  g |= g << 4;
                     69:     int b = col & 0x00F0; b >>= 4;  b |= b << 4;
                     70:     return SDL_MapRGB(format, r,   g,   b);
                     71: }
                     72: 
                     73: /*
                     74:  BW format is 2bit per pixel
                     75:  */
                     76: static void blitBW(SDL_Texture* tex) {
                     77:     void* pixels;
                     78:     int   d;
                     79:     int   pitch = (NeXT_SCRN_WIDTH + (ConfigureParams.System.bTurbo ? 0 : 32)) / 4;
                     80:     SDL_LockTexture(tex, NULL, &pixels, &d);
                     81:     Uint32* dst = (Uint32*)pixels;
                     82:     for(int y = 0; y < NeXT_SCRN_HEIGHT; y++) {
                     83:         int src     = y * pitch;
                     84:         for(int x = 0; x < NeXT_SCRN_WIDTH/4; x++, src++) {
                     85:             int idx = NEXTVideo[src] * 4;
                     86:             *dst++  = BW2RGB[idx+0];
                     87:             *dst++  = BW2RGB[idx+1];
                     88:             *dst++  = BW2RGB[idx+2];
                     89:             *dst++  = BW2RGB[idx+3];
                     90:         }
                     91:     }
                     92:     SDL_UnlockTexture(tex);
                     93: }
                     94: 
                     95: /*
                     96:  Color format is 4bit per pixel, big-endian: RGBx
                     97:  */
                     98: static void blitColor(SDL_Texture* tex) {
                     99:     void* pixels;
                    100:     int   d;
                    101:     int pitch = NeXT_SCRN_WIDTH + (ConfigureParams.System.bTurbo ? 0 : 32);
                    102:     SDL_LockTexture(tex, NULL, &pixels, &d);
                    103:     Uint32* dst = (Uint32*)pixels;
                    104:     for(int y = 0; y < NeXT_SCRN_HEIGHT; y++) {
                    105:         Uint16* src = (Uint16*)NEXTColorVideo + (y*pitch);
                    106:         for(int x = 0; x < NeXT_SCRN_WIDTH; x++) {
                    107:             *dst++ = COL2RGB[*src++];
                    108:         }
                    109:     }
                    110:     SDL_UnlockTexture(tex);
                    111: }
                    112: 
                    113: /*
                    114:  Dimension format is 8bit per pixel, big-endian: RRGGBBAA
                    115:  */
                    116: void blitDimension(Uint32* vram, SDL_Texture* tex) {
                    117: #if ND_STEP
                    118:     Uint32* src = &vram[0];
                    119: #else
                    120:     Uint32* src = &vram[16];
                    121: #endif
                    122:     void*   pixels;
                    123:     int     d;
                    124:     Uint32  format;
                    125:     SDL_QueryTexture(tex, &format, &d, &d, &d);
                    126:     SDL_LockTexture(tex, NULL, &pixels, &d);
                    127:     Uint32* dst = (Uint32*)pixels;
                    128:     if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                    129:         /* Add big-endian accelerated blit loops as needed here */
                    130:         switch (format) {
                    131:             default: {
                    132:                 /* fallback to SDL_MapRGB */
                    133:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
                    134:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
                    135:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
                    136:                         Uint32 v = *src++;
                    137:                         *dst++   = SDL_MapRGB(pformat, (v >> 24) & 0xFF, (v>>16) & 0xFF, (v>>8) & 0xFF);
                    138:                     }
                    139:                     src += 32;
                    140:                 }
                    141:                 SDL_FreeFormat(pformat);
                    142:                 break;
                    143:             }
                    144:         }
                    145:     } else {
                    146:         /* Add little-endian accelerated blit loops as needed here */
                    147:         switch (format) {
                    148:             case SDL_PIXELFORMAT_ARGB8888:
                    149:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
                    150:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
                    151:                         // Uint32 LE: AABBGGRR
                    152:                         // Target:    AARRGGBB
                    153:                         Uint32 v = *src++;
                    154:                         *dst++   = (v & 0xFF000000) | ((v<<16) &0x00FF0000) | (v &0x0000FF00) | ((v>>16) &0x000000FF);
                    155:                     }
                    156:                     src += 32;
                    157:                 }
                    158:                 break;
                    159:             default: {
                    160:                 /* fallback to SDL_MapRGB */
                    161:                 SDL_PixelFormat* pformat = SDL_AllocFormat(format);
                    162:                 for(int y = NeXT_SCRN_HEIGHT; --y >= 0;) {
                    163:                     for(int x = NeXT_SCRN_WIDTH; --x >= 0;) {
                    164:                         Uint32 v = SDL_Swap32(*src++);
                    165:                         *dst++   = SDL_MapRGB(pformat, (v >> 24) & 0xFF, (v>>16) & 0xFF, (v>>8) & 0xFF);
                    166:                     }
                    167:                     src += 32;
                    168:                 }
                    169:                 SDL_FreeFormat(pformat);
                    170:                 break;
                    171:             }
                    172:         }
                    173:     }
                    174:     SDL_UnlockTexture(tex);
                    175: }
                    176: 
                    177: /*
                    178:  Blit NeXT framebuffer to texture.
                    179:  */
                    180: static void blitScreen(SDL_Texture* tex) {
                    181:     if (ConfigureParams.Screen.nMonitorType==MONITOR_TYPE_DIMENSION) {
                    182:         Uint32* vram = nd_vram_for_slot(ND_SLOT(ConfigureParams.Screen.nMonitorNum));
                    183:         if(vram)
                    184:             blitDimension(vram, tex);
                    185:         return;
                    186:     }
                    187:     if(ConfigureParams.System.bColor) {
                    188:         blitColor(tex);
                    189:     } else {
                    190:         blitBW(tex);
                    191:     }
                    192: }
                    193: 
                    194: /*
                    195:  Initializes SDL graphics and then enters repaint loop.
                    196:  Loop: Blits the NeXT framebuffer to the fbTexture, blends with the GUI surface and
                    197:  shows it.
                    198:  */
                    199: static int repainter(void* unused) {
                    200:     int width;
                    201:     int height;
                    202: 
                    203:     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_NORMAL);
                    204:     SDL_GetWindowSize(sdlWindow, &width, &height);
                    205:     
                    206:     statusBar.x = 0;
                    207:     statusBar.y = NeXT_SCRN_HEIGHT;
                    208:     statusBar.w = width;
                    209:     statusBar.h = height - NeXT_SCRN_HEIGHT;
                    210:     
                    211:     SDL_Texture*  uiTexture;
                    212:     SDL_Texture*  fbTexture;
                    213:     
                    214:     Uint32 r, g, b, a;
                    215:     
                    216:     sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
                    217:     SDL_RenderSetLogicalSize(sdlRenderer, width, height);
                    218:     
                    219:     uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    220:     SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
                    221:     
                    222:     fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
                    223:     SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
                    224:     
                    225:     Uint32 format;
                    226:     int    d;
                    227:     SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
                    228:     SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
                    229:     mask = g | a;
                    230:     sdlscrn     = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
                    231:     uiBuffer    = malloc(sdlscrn->h * sdlscrn->pitch);
                    232:     uiBufferTmp = malloc(sdlscrn->h * sdlscrn->pitch);
                    233:     // clear UI with mask
                    234:     SDL_FillRect(sdlscrn, NULL, mask);
                    235:     
                    236:     /* Exit if we can not open a screen */
                    237:     if (!sdlscrn) {
                    238:         fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    239:         SDL_Quit();
                    240:         exit(-2);
                    241:     }
                    242:     
                    243:     Statusbar_Init(sdlscrn);
                    244:     
                    245:        if (bGrabMouse) {
                    246:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    247:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    248:     }
                    249: 
                    250:        /* Configure some SDL stuff: */
                    251:        SDL_ShowCursor(SDL_DISABLE);
                    252:     
                    253:     /* Setup lookup tables */
                    254:     SDL_PixelFormat* pformat = SDL_AllocFormat(format);
                    255:     /* initialize BW lookup table */
                    256:     for(int i = 0; i < 0x100; i++) {
                    257:         BW2RGB[i*4+0] = bw2rgb(pformat, i>>6);
                    258:         BW2RGB[i*4+1] = bw2rgb(pformat, i>>4);
                    259:         BW2RGB[i*4+2] = bw2rgb(pformat, i>>2);
                    260:         BW2RGB[i*4+3] = bw2rgb(pformat, i>>0);
                    261:     }
                    262:     /* initialize color lookup table */
                    263:     for(int i = 0; i < 0x10000; i++)
                    264:         COL2RGB[SDL_BYTEORDER == SDL_BIG_ENDIAN ? i : SDL_Swap16(i)] = col2rgb(pformat, i);
                    265:     
                    266:     /* Initialization done -> signal */
                    267:     SDL_SemPost(initLatch);
                    268:     
                    269:     /* Start with framebuffer blit enabled */
                    270:     SDL_AtomicSet(&blitFB, 1);
                    271:     
                    272:     /* Enter repaint loop */
                    273:     while(doRepaint) {
                    274:         bool updateFB = false;
                    275:         bool updateUI = false;
                    276:         
                    277:         if (SDL_AtomicGet(&blitFB)) {
                    278:             // Blit the NeXT framebuffer to textrue
                    279:             blitScreen(fbTexture);
                    280:             updateFB = true;
                    281:         }
                    282:         
                    283:         // Copy UI surface to texture
                    284:         SDL_AtomicLock(&uiBufferLock);
                    285:         if(SDL_AtomicSet(&blitUI, 0)) {
                    286:             // update full UI texture
                    287:             memcpy(uiBufferTmp, uiBuffer, sdlscrn->h * sdlscrn->pitch);
                    288:             updateUI = true;
                    289:         }
                    290:         SDL_AtomicUnlock(&uiBufferLock);
                    291:         
                    292:         if(updateUI) {
                    293:             SDL_UpdateTexture(uiTexture, NULL,       uiBufferTmp, sdlscrn->pitch);
                    294:         }
                    295:         
                    296:         // Update and render UI texture
                    297:         if (updateFB || updateUI) {
                    298:             SDL_RenderClear(sdlRenderer);
                    299:             // Render NeXT framebuffer texture
                    300:             SDL_RenderCopy(sdlRenderer, fbTexture, NULL, NULL);
                    301:             SDL_RenderCopy(sdlRenderer, uiTexture, NULL, NULL);
                    302:             // SDL_RenderPresent sleeps until next VSYNC because of SDL_RENDERER_PRESENTVSYNC in ScreenInit
                    303:             SDL_RenderPresent(sdlRenderer);
                    304:         } else {
                    305:             host_sleep_ms(10);
                    306:         }
                    307:     }
                    308:     return 0;
                    309: }
                    310: 
                    311: /*-----------------------------------------------------------------------*/
                    312: /**
                    313:  * Pause Screen, pauses or resumes drawing of NeXT framebuffer
                    314:  */
                    315: void Screen_Pause(bool pause) {
                    316:     if (pause) {
                    317:         SDL_AtomicSet(&blitFB, 0);
                    318:     } else {
                    319:         SDL_AtomicSet(&blitFB, 1);
                    320:     }
                    321: }
                    322: 
                    323: /*-----------------------------------------------------------------------*/
                    324: /**
                    325:  * Init Screen, creates window and starts repaint thread
                    326:  */
                    327: void Screen_Init(void) {
                    328:     /* Set initial window resolution */
                    329:     bInFullScreen = ConfigureParams.Screen.bFullScreen;
                    330:     nScreenZoomX  = 1;
                    331:     nScreenZoomY  = 1;
                    332: 
                    333:     int width  = NeXT_SCRN_WIDTH;
                    334:     int height = NeXT_SCRN_HEIGHT;
                    335:     
                    336:     /* Statusbar height */
                    337:     height += Statusbar_SetHeight(width, height);
                    338:     
                    339:     /* Set new video mode */
                    340:     SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
                    341:     
                    342:     fprintf(stderr, "SDL screen request: %d x %d (%s)\n", width, height, bInFullScreen ? "fullscreen" : "windowed");
                    343:     
                    344:     int x = SDL_WINDOWPOS_UNDEFINED;
                    345:     if(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_DUAL) {
                    346:         for(int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
                    347:             SDL_Rect r;
                    348:             SDL_GetDisplayBounds(i, &r);
                    349:             if(r.w >= width * 2) {
                    350:                 x = r.x + width + ((r.w - width * 2) / 2);
                    351:                 break;
                    352:             }
                    353:             if(r.x >= 0 && SDL_GetNumVideoDisplays() == 1) x = r.x + 8;
                    354:         }
                    355:     }
                    356:     sdlWindow  = SDL_CreateWindow(PROG_NAME, x, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
                    357:     if (!sdlWindow) {
                    358:         fprintf(stderr,"Failed to create window: %s!\n", SDL_GetError());
                    359:         exit(-1);
                    360:     }
                    361: 
                    362:     initLatch     = SDL_CreateSemaphore(0);
                    363:     repaintThread = SDL_CreateThread(repainter, "[Previous] screen repaint", NULL);
                    364:     SDL_SemWait(initLatch);
                    365: }
                    366: 
                    367: void nd_sdl_destroy(void);
                    368: 
                    369: /*-----------------------------------------------------------------------*/
                    370: /**
                    371:  * Free screen bitmap and allocated resources
                    372:  */
                    373: void Screen_UnInit(void) {
                    374:     doRepaint = false; // stop repaint thread
                    375:     int s;
                    376:     SDL_WaitThread(repaintThread, &s);
                    377:     nd_sdl_destroy();
                    378: }
                    379: 
                    380: /*-----------------------------------------------------------------------*/
                    381: /**
                    382:  * Enter Full screen mode
                    383:  */
                    384: void Screen_EnterFullScreen(void) {
                    385:        bool bWasRunning;
                    386: 
                    387:        if (!bInFullScreen) {
                    388:                /* Hold things... */
                    389:                bWasRunning = Main_PauseEmulation(false);
                    390:                bInFullScreen = true;
                    391: 
                    392:         SDL_GetWindowPosition(sdlWindow, &saveWindowBounds.x, &saveWindowBounds.y);
                    393:         SDL_GetWindowSize(sdlWindow, &saveWindowBounds.w, &saveWindowBounds.h);
                    394:         SDL_SetWindowFullscreen(sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
                    395:                SDL_Delay(20);                  /* To give monitor time to change to new resolution */
                    396:                
                    397:                if (bWasRunning) {
                    398:                        /* And off we go... */
                    399:                        Main_UnPauseEmulation();
                    400:                }
                    401:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    402:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    403:        }
                    404: }
                    405: 
                    406: /*-----------------------------------------------------------------------*/
                    407: /**
                    408:  * Return from Full screen mode back to a window
                    409:  */
                    410: void Screen_ReturnFromFullScreen(void) {
                    411:        bool bWasRunning;
                    412: 
                    413:        if (bInFullScreen) {
                    414:                /* Hold things... */
                    415:                bWasRunning = Main_PauseEmulation(false);
                    416:                bInFullScreen = false;
                    417: 
                    418:         SDL_SetWindowFullscreen(sdlWindow, 0);
                    419:                SDL_Delay(20);                /* To give monitor time to switch resolution */
                    420:         SDL_SetWindowPosition(sdlWindow, saveWindowBounds.x, saveWindowBounds.y);
                    421:         SDL_SetWindowSize(sdlWindow, saveWindowBounds.w, saveWindowBounds.h);
                    422:         
                    423:                if (bWasRunning) {
                    424:                        /* And off we go... */
                    425:                        Main_UnPauseEmulation();
                    426:                }
                    427: 
                    428:                if (!bGrabMouse) {
                    429:                        /* Un-grab mouse pointer in windowed mode */
                    430:                        SDL_SetRelativeMouseMode(SDL_FALSE);
                    431:             SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    432:                }
                    433:        }
                    434: }
                    435: 
                    436: /*-----------------------------------------------------------------------*/
                    437: /**
                    438:  * Force things associated with changing between fullscreen/windowed
                    439:  */
                    440: void Screen_ModeChanged(void) {
                    441:        if (!sdlscrn) {
                    442:                /* screen not yet initialized */
                    443:                return;
                    444:        }
                    445:        if (bInFullScreen || bGrabMouse) {
                    446:                SDL_SetRelativeMouseMode(SDL_TRUE);
                    447:         SDL_SetWindowGrab(sdlWindow, SDL_TRUE);
                    448:        } else {
                    449:                SDL_SetRelativeMouseMode(SDL_FALSE);
                    450:         SDL_SetWindowGrab(sdlWindow, SDL_FALSE);
                    451:     }
                    452: }
                    453: 
                    454: 
                    455: /*-----------------------------------------------------------------------*/
                    456: /**
                    457:  * Draw screen to window/full-screen - (SC) Just status bar updates. Screen redraw is done in repaint thread.
                    458:  */
                    459: 
                    460: static bool shieldStatusBarUpdate;
                    461: 
                    462: static void statusBarUpdate(void) {
                    463:     if(shieldStatusBarUpdate) return;
                    464:     SDL_LockSurface(sdlscrn);
                    465:     SDL_AtomicLock(&uiBufferLock);
                    466:     memcpy(&((Uint8*)uiBuffer)[statusBar.y*sdlscrn->pitch], &((Uint8*)sdlscrn->pixels)[statusBar.y*sdlscrn->pitch], statusBar.h * sdlscrn->pitch);
                    467:     SDL_AtomicSet(&blitUI, 1);
                    468:     SDL_AtomicUnlock(&uiBufferLock);
                    469:     SDL_UnlockSurface(sdlscrn);
                    470: }
                    471: 
                    472: bool Update_StatusBar(void) {
                    473:     shieldStatusBarUpdate = true;
                    474:     Statusbar_OverlayBackup(sdlscrn);
                    475:     Statusbar_Update(sdlscrn);
                    476:     shieldStatusBarUpdate = false;
                    477: 
                    478:     statusBarUpdate();
                    479:     
                    480:     return !bQuitProgram;
                    481: }
                    482: 
                    483: /*
                    484:  Copy UI SDL surface to uiBuffer and replace mask pixels with transparent pixels for
                    485:  UI blending with framebuffer texture.
                    486: */
                    487: static void uiUpdate(void) {
                    488:     SDL_LockSurface(sdlscrn);
                    489:     int     count = sdlscrn->w * sdlscrn->h;
                    490:     Uint32* dst   = (Uint32*)uiBuffer;
                    491:     Uint32* src   = (Uint32*)sdlscrn->pixels;
                    492:     SDL_AtomicLock(&uiBufferLock);
                    493:     // poor man's green-screen - would be nice if SDL had more blending modes...
                    494:     for(int i = count; --i >= 0; src++)
                    495:         *dst++ = *src == mask ? 0 : *src;
                    496:     SDL_AtomicSet(&blitUI, 1);
                    497:     SDL_AtomicUnlock(&uiBufferLock);
                    498:     SDL_UnlockSurface(sdlscrn);
                    499: }
                    500: 
                    501: void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
                    502:     while(numrects--) {
                    503:         if(rects->y < NeXT_SCRN_HEIGHT) {
                    504:             uiUpdate();
                    505:             doUIblit = true;
                    506:         } else {
                    507:             if(doUIblit) {
                    508:                 uiUpdate();
                    509:                 doUIblit = false;
                    510:             } else {
                    511:                 statusBarUpdate();
                    512:             }
                    513:         }
                    514:     }
                    515: }
                    516: 
                    517: void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h) {
                    518:     SDL_Rect rect = { x, y, w, h };
                    519:     SDL_UpdateRects(screen, 1, &rect);
                    520: }

unix.superglobalmegacorp.com

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