Annotation of hatari/src/screen.c, revision 1.1.1.26

1.1       root        1: /*
1.1.1.6   root        2:   Hatari - screen.c
1.1       root        3: 
1.1.1.21  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.1.6   root        6: 
1.1.1.17  root        7:   This code converts a 1/2/4 plane ST format screen to either 8, 16 or 32-bit PC
1.1.1.11  root        8:   format. An awful lot of processing is needed to do this conversion - we
1.1.1.6   root        9:   cannot simply change palettes on  interrupts as it is possible with DOS.
                     10:   The main code processes the palette/resolution mask tables to find exactly
                     11:   which lines need to updating and the conversion routines themselves only
                     12:   update 16-pixel blocks which differ from the previous frame - this gives a
                     13:   large performance increase.
                     14:   Each conversion routine can convert any part of the source ST screen (which
                     15:   includes the overscan border, usually set to colour zero) so they can be used
                     16:   for both window and full-screen mode.
                     17:   Note that in Hi-Resolution we have no overscan and just two colors so we can
1.1.1.17  root       18:   optimise things further.
                     19:   In color mode it seems possible to display 47 lines in the bottom border
                     20:   with a second 60/50 Hz switch, but most programs consider there are 45
                     21:   visible lines in the bottom border only, which gives a total of 274 lines
                     22:   for a screen. So not displaying the last two lines fixes garbage that could
                     23:   appear in the last two lines when displaying 47 lines (Digiworld 2 by ICE,
                     24:   Tyranny by DHS).
1.1       root       25: */
1.1.1.15  root       26: 
1.1.1.17  root       27: const char Screen_fileid[] = "Hatari screen.c : " __DATE__ " " __TIME__;
1.1       root       28: 
                     29: #include <SDL.h>
1.1.1.11  root       30: #include <SDL_endian.h>
1.1.1.24  root       31: #include <assert.h>
1.1       root       32: 
                     33: #include "main.h"
1.1.1.7   root       34: #include "configuration.h"
1.1.1.23  root       35: #include "avi_record.h"
1.1.1.13  root       36: #include "log.h"
                     37: #include "paths.h"
1.1.1.23  root       38: #include "options.h"
1.1       root       39: #include "screen.h"
1.1.1.24  root       40: #include "screenConvert.h"
1.1.1.15  root       41: #include "control.h"
1.1.1.11  root       42: #include "convert/routines.h"
1.1.1.18  root       43: #include "resolution.h"
1.1       root       44: #include "spec512.h"
1.1.1.15  root       45: #include "statusbar.h"
1.1       root       46: #include "vdi.h"
                     47: #include "video.h"
1.1.1.13  root       48: #include "falcon/videl.h"
1.1       root       49: 
1.1.1.22  root       50: #define DEBUG 0
                     51: 
                     52: #if DEBUG
                     53: # define DEBUGPRINT(x) printf x
                     54: #else
                     55: # define DEBUGPRINT(x)
                     56: #endif
1.1       root       57: 
1.1.1.13  root       58: /* extern for several purposes */
                     59: SDL_Surface *sdlscrn = NULL;                /* The SDL screen surface */
                     60: int nScreenZoomX, nScreenZoomY;             /* Zooming factors, used for scaling mouse motions */
                     61: int nBorderPixelsLeft, nBorderPixelsRight;  /* Pixels in left and right border */
1.1.1.23  root       62: static int nBorderPixelsTop, nBorderPixelsBottom;  /* Lines in top and bottom border */
1.1.1.13  root       63: 
1.1.1.24  root       64: /* extern for shortcuts etc. */
1.1.1.17  root       65: bool bGrabMouse = false;      /* Grab the mouse cursor in the window */
                     66: bool bInFullScreen = false;   /* true if in full screen */
1.1.1.13  root       67: 
                     68: /* extern for spec512.c */
1.1.1.11  root       69: int STScreenLeftSkipBytes;
                     70: int STScreenStartHorizLine;   /* Start lines to be converted */
                     71: Uint32 STRGBPalette[16];      /* Palette buffer used in conversion routines */
                     72: Uint32 ST2RGB[4096];          /* Table to convert ST 0x777 / STe 0xfff palette to PC format RGB551 (2 pixels each entry) */
1.1.1.13  root       73: 
                     74: /* extern for video.c */
1.1.1.11  root       75: Uint8 *pSTScreen;
                     76: FRAMEBUFFER *pFrameBuffer;    /* Pointer into current 'FrameBuffer' */
                     77: 
                     78: static FRAMEBUFFER FrameBuffers[NUM_FRAMEBUFFERS]; /* Store frame buffer details to tell how to update */
                     79: static Uint8 *pSTScreenCopy;                       /* Keep track of current and previous ST screen data */
                     80: static Uint8 *pPCScreenDest;                       /* Destination PC buffer */
                     81: static int STScreenEndHorizLine;                   /* End lines to be converted */
                     82: static int PCScreenBytesPerLine;
                     83: static int STScreenWidthBytes;
1.1.1.20  root       84: static int PCScreenOffsetX;                        /* how many pixels to skip from left when drawing */
                     85: static int PCScreenOffsetY;                        /* how many pixels to skip from top when drawing */
1.1.1.15  root       86: static SDL_Rect STScreenRect;                      /* screen size without statusbar */
1.1       root       87: 
1.1.1.11  root       88: static int STScreenLineOffset[NUM_VISIBLE_LINES];  /* Offsets for ST screen lines eg, 0,160,320... */
                     89: static Uint16 HBLPalette[16], PrevHBLPalette[16];  /* Current palette for line, also copy of first line */
1.1       root       90: 
1.1.1.13  root       91: static void (*ScreenDrawFunctionsNormal[3])(void); /* Screen draw functions */
1.1.1.10  root       92: 
1.1.1.17  root       93: static bool bScreenContentsChanged;     /* true if buffer changed and requires blitting */
                     94: static bool bScrDoubleY;                /* true if double on Y */
1.1.1.11  root       95: static int ScrUpdateFlag;               /* Bit mask of how to update screen */
1.1.1.25  root       96: static bool bRGBTableInSync;            /* Is RGB table up to date? */
1.1.1.11  root       97: 
1.1.1.24  root       98: /* These are used for the generic screen conversion functions */
                     99: static int genconv_width_req, genconv_height_req, genconv_bpp;
                    100: static bool genconv_do_update;          /* HW surface is available -> the SDL need not to update the surface after ->pixel access */
                    101: 
1.1.1.10  root      102: 
1.1.1.18  root      103: static bool Screen_DrawFrame(bool bForceFlip);
                    104: 
1.1.1.23  root      105: #if WITH_SDL2
                    106: 
                    107: SDL_Window *sdlWindow;
                    108: static SDL_Renderer *sdlRenderer;
                    109: static SDL_Texture *sdlTexture;
1.1.1.26! root      110: static bool bUseSdlRenderer;            /* true when using SDL2 renderer */
1.1.1.23  root      111: 
                    112: void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects)
                    113: {
1.1.1.26! root      114:        if (bUseSdlRenderer)
1.1.1.25  root      115:        {
                    116:                SDL_UpdateTexture(sdlTexture, NULL, screen->pixels, screen->pitch);
                    117:                SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
                    118:                SDL_RenderPresent(sdlRenderer);
                    119:        }
                    120:        else
                    121:        {
                    122:                SDL_UpdateWindowSurfaceRects(sdlWindow, rects, numrects);
                    123:        }
1.1.1.23  root      124: }
                    125: 
                    126: void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h)
                    127: {
1.1.1.25  root      128:        SDL_Rect rect;
                    129: 
                    130:        if (w == 0 && h == 0) {
                    131:                x = y = 0;
                    132:                w = screen->w;
                    133:                h = screen->h;
                    134:        }
                    135: 
                    136:        rect.x = x; rect.y = y;
                    137:        rect.w = w; rect.h = h;
1.1.1.23  root      138:        SDL_UpdateRects(screen, 1, &rect);
                    139: }
                    140: 
1.1.1.26! root      141: #endif /* WITH_SDL2 */
1.1.1.18  root      142: 
1.1.1.10  root      143: /*-----------------------------------------------------------------------*/
1.1.1.13  root      144: /**
                    145:  * Create ST 0x777 / STe 0xfff color format to 16 or 32 bits per pixel
                    146:  * conversion table. Called each time when changed resolution or to/from
                    147:  * fullscreen mode.
                    148:  */
1.1.1.10  root      149: static void Screen_SetupRGBTable(void)
                    150: {
1.1.1.13  root      151:        Uint16 STColor;
                    152:        Uint32 RGBColor;
                    153:        int r, g, b;
                    154:        int rr, gg, bb;
                    155: 
                    156:        /* Do Red, Green and Blue for all 16*16*16 = 4096 STe colors */
                    157:        for (r = 0; r < 16; r++)
                    158:        {
                    159:                for (g = 0; g < 16; g++)
                    160:                {
                    161:                        for (b = 0; b < 16; b++)
                    162:                        {
                    163:                                /* STe 0xfff format */
                    164:                                STColor = (r<<8) | (g<<4) | (b);
1.1.1.20  root      165:                                rr = ((r & 0x7) << 1) | ((r & 0x8) >> 3);
                    166:                                rr |= rr << 4;
                    167:                                gg = ((g & 0x7) << 1) | ((g & 0x8) >> 3);
                    168:                                gg |= gg << 4;
                    169:                                bb = ((b & 0x7) << 1) | ((b & 0x8) >> 3);
                    170:                                bb |= bb << 4;
1.1.1.13  root      171:                                RGBColor = SDL_MapRGB(sdlscrn->format, rr, gg, bb);
                    172:                                if (sdlscrn->format->BitsPerPixel <= 16)
                    173:                                {
                    174:                                        /* As longs, for speed (write two pixels at once) */
                    175:                                        ST2RGB[STColor] = (RGBColor<<16) | RGBColor;
                    176:                                }
                    177:                                else
                    178:                                {
                    179:                                        ST2RGB[STColor] = RGBColor;
                    180:                                }
                    181:                        }
                    182:                }
                    183:        }
1.1.1.10  root      184: }
                    185: 
1.1.1.13  root      186: 
                    187: /**
1.1.1.24  root      188:  * Convert 640x400 monochrome screen
1.1.1.13  root      189:  */
1.1.1.24  root      190: static void Screen_ConvertHighRes(void)
1.1.1.10  root      191: {
1.1.1.24  root      192:        int linewidth = 640 / 16;
1.1.1.10  root      193: 
1.1.1.24  root      194:        Screen_GenConvert(pSTScreen, 640, 400, 1, linewidth, 0, 0, 0, 0, 0);
                    195:        bScreenContentsChanged = true;
1.1.1.10  root      196: }
                    197: 
1.1.1.13  root      198: /**
                    199:  * Set screen draw functions.
                    200:  */
1.1.1.18  root      201: static void Screen_SetDrawFunctions(int nBitCount, bool bDoubleLowRes)
1.1.1.10  root      202: {
1.1.1.24  root      203:        if (nBitCount <= 16)
1.1.1.13  root      204:        {
                    205:                /* High color */
1.1.1.18  root      206:                if (bDoubleLowRes)
1.1.1.13  root      207:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x16Bit;
                    208:                else
                    209:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x16Bit;
                    210:                ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x16Bit;
                    211:        }
                    212:        else /* Assume 32 bit drawing functions */
                    213:        {
                    214:                /* True color */
1.1.1.18  root      215:                if (bDoubleLowRes)
1.1.1.13  root      216:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x32Bit;
                    217:                else
                    218:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x32Bit;
                    219:                ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x32Bit;
                    220:        }
1.1.1.10  root      221: }
                    222: 
                    223: 
                    224: /*-----------------------------------------------------------------------*/
1.1.1.13  root      225: /**
1.1.1.18  root      226:  * Set amount of border pixels
1.1.1.13  root      227:  */
1.1.1.18  root      228: static void Screen_SetBorderPixels(int leftX, int leftY)
1.1.1.7   root      229: {
1.1.1.23  root      230:        /* All screen widths need to be aligned to 16-bits */
                    231:        nBorderPixelsLeft = Opt_ValueAlignMinMax(leftX/2, 16, 0, 48);
1.1.1.18  root      232:        nBorderPixelsRight = nBorderPixelsLeft;
1.1.1.7   root      233: 
1.1.1.18  root      234:        /* assertain assumption of code below */
                    235:        assert(OVERSCAN_TOP < MAX_OVERSCAN_BOTTOM);
                    236:        
                    237:        if (leftY > 2*OVERSCAN_TOP)
1.1.1.13  root      238:        {
1.1.1.18  root      239:                nBorderPixelsTop = OVERSCAN_TOP;
                    240:                if (leftY >= OVERSCAN_TOP + MAX_OVERSCAN_BOTTOM)
                    241:                        nBorderPixelsBottom = MAX_OVERSCAN_BOTTOM;
                    242:                else
                    243:                        nBorderPixelsBottom = leftY - OVERSCAN_TOP;
1.1.1.13  root      244:        }
                    245:        else
                    246:        {
1.1.1.18  root      247:                if (leftY > 0)
                    248:                        nBorderPixelsTop = nBorderPixelsBottom = leftY/2;
                    249:                else
                    250:                        nBorderPixelsTop = nBorderPixelsBottom = 0;
1.1.1.13  root      251:        }
1.1.1.18  root      252: }
                    253: 
                    254: /*-----------------------------------------------------------------------*/
                    255: /**
                    256:  * store Y offset for each horizontal line in our source ST screen for
                    257:  * reference in the convert functions.
                    258:  */
                    259: static void Screen_SetSTScreenOffsets(void)
                    260: {
                    261:        int i;
1.1.1.13  root      262: 
1.1.1.18  root      263:        /* Store offset to each horizontal line, uses
                    264:         * nBorderPixels* variables.
                    265:         */
1.1.1.13  root      266:        for (i = 0; i < NUM_VISIBLE_LINES; i++)
                    267:        {
                    268:                STScreenLineOffset[i] = i * SCREENBYTES_LINE;
                    269:        }
1.1.1.7   root      270: }
                    271: 
1.1.1.24  root      272: /**
                    273:  * Return true if Falcon/TT/VDI generic screen convert functions
                    274:  * need to be used instead of the ST/STE functions.
                    275:  */
                    276: static bool Screen_UseGenConvScreen(void)
                    277: {
                    278:        return Config_IsMachineFalcon() || Config_IsMachineTT()
                    279:                || bUseHighRes || bUseVDIRes;
                    280: }
                    281: 
                    282: static bool Screen_WantToKeepResolution(void)
                    283: {
                    284: #if WITH_SDL2
                    285:        return ConfigureParams.Screen.bKeepResolution;
                    286: #else
                    287:        if (Screen_UseGenConvScreen())
                    288:                return ConfigureParams.Screen.bKeepResolution;
                    289:        else
                    290:                return ConfigureParams.Screen.bKeepResolutionST;
                    291: #endif
                    292: }
                    293: 
1.1.1.23  root      294: #if WITH_SDL2
                    295: static void Screen_FreeSDL2Resources(void)
                    296: {
                    297:        if (sdlTexture)
                    298:        {
                    299:                SDL_DestroyTexture(sdlTexture);
                    300:                sdlTexture = NULL;
                    301:        }
                    302:        if (sdlscrn)
                    303:        {
1.1.1.26! root      304:                if (bUseSdlRenderer)
1.1.1.25  root      305:                        SDL_FreeSurface(sdlscrn);
1.1.1.23  root      306:                sdlscrn = NULL;
                    307:        }
                    308:        if (sdlRenderer)
                    309:        {
                    310:                SDL_DestroyRenderer(sdlRenderer);
                    311:                sdlRenderer = NULL;
                    312:        }
                    313: }
                    314: #endif
                    315: 
                    316: /**
                    317:  * Change the SDL video mode.
                    318:  * @return true if mode has been changed, false if change was not necessary
                    319:  */
                    320: bool Screen_SetSDLVideoSize(int width, int height, int bitdepth, bool bForceChange)
                    321: {
                    322:        Uint32 sdlVideoFlags;
1.1.1.26! root      323:        char *psSdlVideoDriver;
        !           324:        bool bUseDummyMode;
1.1.1.23  root      325: #if WITH_SDL2
                    326:        static int nPrevRenderScaleQuality = 0;
                    327:        static bool bPrevUseVsync = false;
1.1.1.24  root      328:        static bool bPrevInFullScreen;
                    329:        int win_width, win_height;
1.1.1.23  root      330: 
                    331:        if (bitdepth == 0 || bitdepth == 24)
                    332:                bitdepth = 32;
                    333: #endif
                    334:        /* Check if we really have to change the video mode: */
                    335:        if (sdlscrn != NULL && sdlscrn->w == width && sdlscrn->h == height
                    336:            && sdlscrn->format->BitsPerPixel == bitdepth && !bForceChange)
                    337:                return false;
                    338: 
1.1.1.26! root      339:        psSdlVideoDriver = SDL_getenv("SDL_VIDEODRIVER");
        !           340:        bUseDummyMode = psSdlVideoDriver && !strcmp(psSdlVideoDriver, "dummy");
        !           341:        if (bUseDummyMode)
        !           342:        {
        !           343:                ConfigureParams.Screen.DisableVideo = true;
        !           344:        }
        !           345: 
1.1.1.23  root      346: #ifdef _MUDFLAP
                    347:        if (sdlscrn)
                    348:        {
                    349:                __mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS);
                    350:        }
                    351: #endif
                    352:        if (bInFullScreen)
                    353:        {
                    354:                /* unhide the Hatari WM window for fullscreen */
                    355:                Control_ReparentWindow(width, height, bInFullScreen);
                    356:        }
                    357: 
                    358: #if WITH_SDL2
1.1.1.26! root      359:        bUseSdlRenderer = ConfigureParams.Screen.bUseSdlRenderer && !bUseDummyMode;
1.1.1.23  root      360: 
                    361:        /* SDL Video attributes: */
1.1.1.24  root      362:        win_width = width;
                    363:        win_height = height;
1.1.1.23  root      364:        if (bInFullScreen)
                    365:        {
1.1.1.24  root      366:                sdlVideoFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_INPUT_GRABBED;
                    367:                if (ConfigureParams.Screen.bKeepResolution)
                    368:                        sdlVideoFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
                    369:                else
                    370:                        sdlVideoFlags |= SDL_WINDOW_FULLSCREEN;
1.1.1.23  root      371:        }
                    372:        else
                    373:        {
1.1.1.24  root      374:                int deskw, deskh;
1.1.1.25  root      375:                if (getenv("PARENT_WIN_ID") != NULL)    /* Embedded window? */
                    376:                        sdlVideoFlags = SDL_WINDOW_BORDERLESS;
1.1.1.26! root      377:                else if (ConfigureParams.Screen.bResizable && bUseSdlRenderer)
1.1.1.25  root      378:                        sdlVideoFlags = SDL_WINDOW_RESIZABLE;
                    379:                else
                    380:                        sdlVideoFlags = 0;
1.1.1.24  root      381:                /* Make sure that window is not bigger than current desktop */
                    382:                Resolution_GetDesktopSize(&deskw, &deskh);
                    383:                if (win_width > deskw)
                    384:                        win_width = deskw;
                    385:                if (win_height > deskh)
                    386:                        win_height = deskh;
1.1.1.23  root      387:        }
                    388: 
                    389:        Screen_FreeSDL2Resources();
1.1.1.25  root      390:        if (sdlWindow &&
                    391:            ((bInFullScreen && !ConfigureParams.Screen.bKeepResolution) ||
                    392:             (bPrevInFullScreen != bInFullScreen) ||
                    393:             bForceChange
                    394:            ))
1.1.1.24  root      395:        {
                    396:                SDL_DestroyWindow(sdlWindow);
                    397:                sdlWindow = NULL;
                    398:        }
                    399:        bPrevInFullScreen = bInFullScreen;
1.1.1.23  root      400: 
                    401:        /* Set SDL2 video hints */
                    402:        if (nPrevRenderScaleQuality != ConfigureParams.Screen.nRenderScaleQuality)
                    403:        {
                    404:                char hint[2] = { '0' + ConfigureParams.Screen.nRenderScaleQuality, 0 };
                    405:                SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, hint, SDL_HINT_OVERRIDE);
                    406:                nPrevRenderScaleQuality = ConfigureParams.Screen.nRenderScaleQuality;
                    407:        }
                    408:        if (bPrevUseVsync != ConfigureParams.Screen.bUseVsync)
                    409:        {
                    410:                char hint[2] = { '0' + ConfigureParams.Screen.bUseVsync, 0 };
                    411:                SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC, hint, SDL_HINT_OVERRIDE);
                    412:                bPrevUseVsync = ConfigureParams.Screen.bUseVsync;
                    413:        }
                    414: 
1.1.1.25  root      415: #ifdef SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4             /* requires sdl >= 2.0.4 */
                    416:        /* Disable closing Hatari with alt+F4 under Windows as alt+F4 can be used by some emulated programs */
                    417:        SDL_SetHintWithPriority(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1", SDL_HINT_OVERRIDE);
                    418: #endif
                    419: 
1.1.1.23  root      420:        /* Set new video mode */
                    421:        DEBUGPRINT(("SDL screen request: %d x %d @ %d (%s)\n", width, height,
                    422:                bitdepth, bInFullScreen?"fullscreen":"windowed"));
                    423: 
1.1.1.24  root      424:        if (sdlWindow)
                    425:        {
                    426:                if ((SDL_GetWindowFlags(sdlWindow) & SDL_WINDOW_MAXIMIZED) == 0)
                    427:                        SDL_SetWindowSize(sdlWindow, win_width, win_height);
                    428:        }
                    429:        else
                    430:        {
                    431:                sdlWindow = SDL_CreateWindow("Hatari", SDL_WINDOWPOS_UNDEFINED,
                    432:                                             SDL_WINDOWPOS_UNDEFINED,
                    433:                                             win_width, win_height, sdlVideoFlags);
                    434:        }
1.1.1.25  root      435:        if (!sdlWindow)
1.1.1.23  root      436:        {
1.1.1.26! root      437:                fprintf(stderr, "ERROR: Failed to create %dx%d window!\n",
1.1.1.25  root      438:                        win_width, win_height);
1.1.1.23  root      439:                exit(-1);
                    440:        }
1.1.1.26! root      441:        if (bUseSdlRenderer)
1.1.1.23  root      442:        {
                    443:                int rm, bm, gm, pfmt;
1.1.1.24  root      444: 
1.1.1.25  root      445:                sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
                    446:                if (!sdlRenderer)
                    447:                {
1.1.1.26! root      448:                        fprintf(stderr, "ERROR: Failed to create %dx%d renderer!\n",
1.1.1.25  root      449:                                win_width, win_height);
                    450:                        exit(1);
                    451:                }
                    452: 
1.1.1.24  root      453:                if (bInFullScreen)
                    454:                        SDL_RenderSetLogicalSize(sdlRenderer, width, height);
                    455: 
1.1.1.23  root      456:                if (bitdepth == 16)
                    457:                {
                    458:                        rm = 0xF800;
                    459:                        gm = 0x07E0;
                    460:                        bm = 0x001F;
                    461:                        pfmt = SDL_PIXELFORMAT_RGB565;
                    462:                }
                    463:                else
                    464:                {
                    465:                        rm = 0x00FF0000;
                    466:                        gm = 0x0000FF00;
                    467:                        bm = 0x000000FF;
                    468:                        pfmt = SDL_PIXELFORMAT_RGB888;
                    469:                }
                    470:                sdlscrn = SDL_CreateRGBSurface(0, width, height, bitdepth,
                    471:                                               rm, gm, bm, 0);
                    472:                sdlTexture = SDL_CreateTexture(sdlRenderer, pfmt,
                    473:                                               SDL_TEXTUREACCESS_STREAMING,
                    474:                                               width, height);
                    475:                if (!sdlTexture)
                    476:                {
1.1.1.26! root      477:                        fprintf(stderr, "ERROR: Failed to create %dx%d@%d texture!\n",
1.1.1.25  root      478:                               width, height, bitdepth);
1.1.1.23  root      479:                        exit(-3);
                    480:                }
                    481:        }
1.1.1.25  root      482:        else
                    483:        {
                    484:                sdlscrn = SDL_GetWindowSurface(sdlWindow);
                    485:        }
1.1.1.23  root      486: 
1.1.1.26! root      487: #else  /* !WITH_SDL2 */
1.1.1.23  root      488: 
                    489:        /* SDL Video attributes: */
                    490:        if (bInFullScreen)
                    491:        {
                    492:                sdlVideoFlags  = SDL_HWSURFACE|SDL_FULLSCREEN/*|SDL_DOUBLEBUF*/;
                    493:                /* SDL_DOUBLEBUF helps avoiding tearing and can be faster on suitable HW,
                    494:                 * but it doesn't work with partial screen updates done by the ST screen
                    495:                 * update code or the Hatari GUI, so double buffering is disabled. */
                    496:        }
                    497:        else
                    498:        {
                    499:                sdlVideoFlags  = SDL_SWSURFACE;
                    500:        }
                    501: 
                    502:        /* Set new video mode */
1.1.1.24  root      503:        DEBUGPRINT(("SDL screen request: %d x %d @ %d (%s)\n", width, height, bitdepth,
                    504:                    bInFullScreen?"fullscreen":"windowed"));
1.1.1.23  root      505:        sdlscrn = SDL_SetVideoMode(width, height, bitdepth, sdlVideoFlags);
                    506: 
                    507:        /* By default ConfigureParams.Screen.nForceBpp and therefore
                    508:         * BitCount is zero which means "SDL color depth autodetection".
                    509:         * In this case the SDL_SetVideoMode() call might return
                    510:         * a 24 bpp resolution
                    511:         */
                    512:        if (sdlscrn && sdlscrn->format->BitsPerPixel == 24)
                    513:        {
1.1.1.26! root      514:                Log_Printf(LOG_WARN, "Unsupported color depth 24, trying 32 bpp instead...\n");
1.1.1.23  root      515:                sdlscrn = SDL_SetVideoMode(width, height, 32, sdlVideoFlags);
                    516:        }
                    517: 
1.1.1.26! root      518: #endif /* !WITH_SDL2 */
1.1.1.23  root      519: 
                    520:        /* Exit if we can not open a screen */
                    521:        if (!sdlscrn)
                    522:        {
1.1.1.26! root      523:                fprintf(stderr, "ERROR: Could not set video mode:\n %s\n", SDL_GetError() );
1.1.1.23  root      524:                SDL_Quit();
                    525:                exit(-2);
                    526:        }
                    527: 
                    528:        DEBUGPRINT(("SDL screen granted: %d x %d @ %d\n", sdlscrn->w, sdlscrn->h,
                    529:                    sdlscrn->format->BitsPerPixel));
                    530: 
                    531: #ifdef _MUDFLAP
                    532:        __mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels");
                    533: #endif
                    534: 
                    535:        if (!bInFullScreen)
                    536:        {
                    537:                /* re-embed the new Hatari SDL window */
                    538:                Control_ReparentWindow(width, height, bInFullScreen);
                    539:        }
                    540: 
1.1.1.25  root      541:        Avi_SetSurface(sdlscrn);
                    542: 
                    543:        bRGBTableInSync = false;
                    544: 
1.1.1.23  root      545:        return true;
                    546: }
1.1.1.8   root      547: 
1.1.1.24  root      548: 
1.1.1.13  root      549: /**
1.1.1.24  root      550:  * Initialize ST/STE screen resolution.
1.1.1.13  root      551:  */
1.1.1.24  root      552: static void Screen_SetSTResolution(bool bForceChange)
1.1.1.11  root      553: {
1.1.1.18  root      554:        int Width, Height, nZoom, SBarHeight, BitCount, maxW, maxH;
                    555:        bool bDoubleLowRes = false;
1.1.1.13  root      556: 
                    557:        /* Bits per pixel */
1.1.1.24  root      558:        BitCount = ConfigureParams.Screen.nForceBpp;
1.1.1.13  root      559: 
1.1.1.18  root      560:        nBorderPixelsTop = nBorderPixelsBottom = 0;
                    561:        nBorderPixelsLeft = nBorderPixelsRight = 0;
                    562: 
                    563:        nScreenZoomX = 1;
                    564:        nScreenZoomY = 1;
                    565: 
1.1.1.24  root      566:        if (STRes == ST_LOW_RES)
1.1.1.13  root      567:        {
1.1.1.24  root      568:                Width = 320;
                    569:                Height = 200;
                    570:                nZoom = 1;
1.1.1.13  root      571:        }
1.1.1.24  root      572:        else    /* else use 640x400, also for med-rez */
1.1.1.13  root      573:        {
1.1.1.24  root      574:                Width = 640;
                    575:                Height = 400;
                    576:                nZoom = 2;
                    577:        }
1.1.1.18  root      578: 
1.1.1.24  root      579:        /* Statusbar height for doubled screen size */
                    580:        SBarHeight = Statusbar_GetHeightForSize(640, 400);
1.1.1.18  root      581: 
1.1.1.24  root      582:        Resolution_GetLimits(&maxW, &maxH, &BitCount, Screen_WantToKeepResolution());
                    583: 
                    584:        /* Zoom if necessary, factors used for scaling mouse motions */
                    585:        if (STRes == ST_LOW_RES &&
                    586:            2*Width <= maxW && 2*Height+SBarHeight <= maxH)
                    587:        {
                    588:                nZoom = 2;
                    589:                Width *= 2;
                    590:                Height *= 2;
                    591:                nScreenZoomX = 2;
                    592:                nScreenZoomY = 2;
                    593:                bDoubleLowRes = true;
                    594:        }
                    595:        else if (STRes == ST_MEDIUM_RES)
                    596:        {
                    597:                /* med-rez conversion functions want always
                    598:                 * to double vertically, they don't support
                    599:                 * skipping that (only leaving doubled lines
                    600:                 * black for the TV mode).
                    601:                 */
                    602:                nScreenZoomX = 1;
                    603:                nScreenZoomY = 2;
                    604:        }
                    605: 
                    606:        /* Adjust width/height for overscan borders, if mono or VDI we have no overscan */
                    607:        if (ConfigureParams.Screen.bAllowOverscan && !bUseHighRes)
                    608:        {
                    609:                int leftX = maxW - Width;
                    610:                int leftY = maxH - (Height + Statusbar_GetHeightForSize(Width, Height));
                    611: 
                    612:                Screen_SetBorderPixels(leftX/nZoom, leftY/nZoom);
                    613:                DEBUGPRINT(("resolution limit:\n\t%d x %d\nlimited resolution:\n\t", maxW, maxH));
                    614:                DEBUGPRINT(("%d * (%d + %d + %d) x (%d + %d + %d)\n", nZoom,
                    615:                            nBorderPixelsLeft, Width/nZoom, nBorderPixelsRight,
                    616:                            nBorderPixelsTop, Height/nZoom, nBorderPixelsBottom));
                    617:                Width += (nBorderPixelsRight + nBorderPixelsLeft)*nZoom;
                    618:                Height += (nBorderPixelsTop + nBorderPixelsBottom)*nZoom;
                    619:                DEBUGPRINT(("\t= %d x %d (+ statusbar)\n", Width, Height));
1.1.1.13  root      620:        }
1.1.1.23  root      621: 
1.1.1.18  root      622:        Screen_SetSTScreenOffsets();  
                    623:        Height += Statusbar_SetHeight(Width, Height);
1.1.1.13  root      624: 
1.1.1.20  root      625:        PCScreenOffsetX = PCScreenOffsetY = 0;
                    626: 
1.1.1.23  root      627:        /* Video attributes: */
1.1.1.24  root      628: #if !WITH_SDL2
1.1.1.23  root      629:        if (bInFullScreen && ConfigureParams.Screen.bKeepResolutionST)
1.1.1.13  root      630:        {
1.1.1.23  root      631:                /* use desktop resolution */
                    632:                Resolution_GetDesktopSize(&maxW, &maxH);
                    633:                SBarHeight = Statusbar_GetHeightForSize(maxW, maxH);
                    634:                /* re-calculate statusbar height for this resolution */
                    635:                Statusbar_SetHeight(maxW, maxH-SBarHeight);
                    636:                /* center Atari screen to resolution */
                    637:                PCScreenOffsetY = (maxH - Height)/2;
                    638:                PCScreenOffsetX = (maxW - Width)/2;
                    639:                /* and select desktop resolution */
                    640:                Height = maxH;
                    641:                Width = maxW;
1.1.1.13  root      642:        }
1.1.1.24  root      643: #endif
1.1.1.13  root      644: 
1.1.1.23  root      645:        if (Screen_SetSDLVideoSize(Width, Height, BitCount, bForceChange))
1.1.1.13  root      646:        {
1.1.1.15  root      647:                Statusbar_Init(sdlscrn);
1.1.1.23  root      648: 
1.1.1.15  root      649:                /* screen area without the statusbar */
                    650:                STScreenRect.x = 0;
                    651:                STScreenRect.y = 0;
                    652:                STScreenRect.w = sdlscrn->w;
                    653:                STScreenRect.h = sdlscrn->h - Statusbar_GetHeight();
1.1.1.13  root      654:        }
                    655: 
1.1.1.25  root      656:        if (!bRGBTableInSync)
                    657:        {
                    658:                Screen_SetupRGBTable();   /* Create color conversion table */
                    659:                bRGBTableInSync = true;
                    660:        }
                    661: 
1.1.1.13  root      662:        /* Set drawing functions */
1.1.1.18  root      663:        Screen_SetDrawFunctions(sdlscrn->format->BitsPerPixel, bDoubleLowRes);
1.1.1.13  root      664: 
                    665:        Screen_SetFullUpdate();           /* Cause full update of screen */
1.1.1.11  root      666: }
                    667: 
                    668: 
1.1.1.24  root      669: /**
                    670:  * Change resolution, according to the machine and display type
                    671:  * that we're currently emulating.
                    672:  */
                    673: static void Screen_ChangeResolution(bool bForceChange)
                    674: {
                    675:        int hbpp = ConfigureParams.Screen.nForceBpp;
                    676: 
                    677:        if (bUseVDIRes)
                    678:        {
                    679:                Screen_SetGenConvSize(VDIWidth, VDIHeight, hbpp, bForceChange);
                    680:        }
                    681:        else if (Config_IsMachineFalcon())
                    682:        {
1.1.1.25  root      683:                Videl_ScreenModeChanged(bForceChange);
1.1.1.24  root      684:        }
                    685:        else if (Config_IsMachineTT())
                    686:        {
                    687:                int width, height, bpp;
                    688:                Video_GetTTRes(&width, &height, &bpp);
                    689:                Screen_SetGenConvSize(width, height, hbpp, bForceChange);
                    690:        }
                    691:        else if (bUseHighRes)
                    692:        {
                    693:                Screen_SetGenConvSize(640, 400, hbpp, bForceChange);
                    694:        }
                    695:        else
                    696:        {
                    697:                Screen_SetSTResolution(bForceChange);
                    698:        }
                    699: 
                    700:        if (bInFullScreen || bGrabMouse)
                    701:                SDL_WM_GrabInput(SDL_GRAB_ON);
                    702:        else
                    703:                SDL_WM_GrabInput(SDL_GRAB_OFF);
                    704: }
                    705: 
                    706: 
                    707: /**
                    708:  * Change the resolution - but only if it was already initialized before
                    709:  */
                    710: void Screen_ModeChanged(bool bForceChange)
                    711: {
                    712:        if (sdlscrn)    /* Do it only if we're already up and running */
                    713:        {
                    714:                Screen_ChangeResolution(bForceChange);
                    715:        }
                    716: }
                    717: 
                    718: 
1.1.1.11  root      719: /*-----------------------------------------------------------------------*/
1.1.1.13  root      720: /**
                    721:  * Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
                    722:  */
1.1       root      723: void Screen_Init(void)
                    724: {
1.1.1.13  root      725:        int i;
                    726:        SDL_Surface *pIconSurf;
                    727:        char sIconFileName[FILENAME_MAX];
                    728: 
                    729:        /* Clear frame buffer structures and set current pointer */
                    730:        memset(FrameBuffers, 0, NUM_FRAMEBUFFERS * sizeof(FRAMEBUFFER));
                    731: 
                    732:        /* Allocate previous screen check workspace. We are going to double-buffer a double-buffered screen. Oh. */
                    733:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
                    734:        {
1.1.1.21  root      735:                FrameBuffers[i].pSTScreen = malloc(MAX_VDI_BYTES);
                    736:                FrameBuffers[i].pSTScreenCopy = malloc(MAX_VDI_BYTES);
1.1.1.13  root      737:                if (!FrameBuffers[i].pSTScreen || !FrameBuffers[i].pSTScreenCopy)
                    738:                {
1.1.1.26! root      739:                        fprintf(stderr, "ERROR: Failed to allocate frame buffer memory.\n");
1.1.1.13  root      740:                        exit(-1);
                    741:                }
                    742:        }
                    743:        pFrameBuffer = &FrameBuffers[0];
                    744: 
1.1.1.25  root      745:        /* Set initial window resolution */
                    746:        bInFullScreen = ConfigureParams.Screen.bFullScreen;
                    747:        Screen_ChangeResolution(false);
                    748:        ScreenDrawFunctionsNormal[ST_HIGH_RES] = Screen_ConvertHighRes;
                    749: 
                    750:        Video_SetScreenRasters();                       /* Set rasters ready for first screen */
                    751: 
1.1.1.13  root      752:        /* Load and set icon */
                    753:        snprintf(sIconFileName, sizeof(sIconFileName), "%s%chatari-icon.bmp",
                    754:                 Paths_GetDataDir(), PATHSEP);
                    755:        pIconSurf = SDL_LoadBMP(sIconFileName);
                    756:        if (pIconSurf)
                    757:        {
1.1.1.23  root      758: #if WITH_SDL2
                    759:                SDL_SetColorKey(pIconSurf, SDL_TRUE, SDL_MapRGB(pIconSurf->format, 255, 255, 255));
                    760:                SDL_SetWindowIcon(sdlWindow, pIconSurf);
                    761: #else
1.1.1.13  root      762:                SDL_SetColorKey(pIconSurf, SDL_SRCCOLORKEY, SDL_MapRGB(pIconSurf->format, 255, 255, 255));
                    763:                SDL_WM_SetIcon(pIconSurf, NULL);
1.1.1.23  root      764: #endif
1.1.1.13  root      765:                SDL_FreeSurface(pIconSurf);
                    766:        }
                    767: 
                    768:        /* Configure some SDL stuff: */
                    769:        SDL_ShowCursor(SDL_DISABLE);
1.1       root      770: }
                    771: 
1.1.1.2   root      772: 
1.1       root      773: /*-----------------------------------------------------------------------*/
1.1.1.13  root      774: /**
                    775:  * Free screen bitmap and allocated resources
                    776:  */
1.1       root      777: void Screen_UnInit(void)
                    778: {
1.1.1.13  root      779:        int i;
1.1       root      780: 
1.1.1.13  root      781:        /* Free memory used for copies */
                    782:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
                    783:        {
                    784:                free(FrameBuffers[i].pSTScreen);
                    785:                free(FrameBuffers[i].pSTScreenCopy);
                    786:        }
1.1.1.23  root      787: 
                    788: #if WITH_SDL2
                    789:        Screen_FreeSDL2Resources();
1.1.1.24  root      790:        if (sdlWindow)
                    791:        {
                    792:                SDL_DestroyWindow(sdlWindow);
                    793:                sdlWindow = NULL;
                    794:        }
1.1.1.23  root      795: #endif
1.1       root      796: }
                    797: 
1.1.1.2   root      798: 
1.1       root      799: /*-----------------------------------------------------------------------*/
1.1.1.13  root      800: /**
                    801:  * Reset screen
                    802:  */
1.1       root      803: void Screen_Reset(void)
                    804: {
1.1.1.13  root      805:        /* On re-boot, always correct ST resolution for monitor, eg Colour/Mono */
                    806:        if (bUseVDIRes)
                    807:        {
                    808:                STRes = VDIRes;
                    809:        }
                    810:        else
                    811:        {
                    812:                if (bUseHighRes)
                    813:                {
                    814:                        STRes = ST_HIGH_RES;
                    815:                        TTRes = TT_HIGH_RES;
                    816:                }
                    817:                else
                    818:                {
                    819:                        STRes = ST_LOW_RES;
                    820:                        TTRes = TT_MEDIUM_RES;
                    821:                }
                    822:        }
                    823:        /* Cause full update */
1.1.1.23  root      824:        Screen_ModeChanged(false);
1.1       root      825: }
                    826: 
                    827: 
                    828: /*-----------------------------------------------------------------------*/
1.1.1.13  root      829: /**
                    830:  * Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
                    831:  * next time around
                    832:  */
1.1       root      833: void Screen_SetFullUpdate(void)
                    834: {
1.1.1.13  root      835:        int i;
1.1       root      836: 
1.1.1.13  root      837:        /* Update frame buffers */
                    838:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
1.1.1.17  root      839:                FrameBuffers[i].bFullUpdate = true;
1.1       root      840: }
                    841: 
1.1.1.5   root      842: 
1.1       root      843: /*-----------------------------------------------------------------------*/
1.1.1.13  root      844: /**
                    845:  * Clear Window display memory
                    846:  */
1.1.1.11  root      847: static void Screen_ClearScreen(void)
                    848: {
1.1.1.15  root      849:        SDL_FillRect(sdlscrn, &STScreenRect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
1.1.1.11  root      850: }
                    851: 
1.1.1.18  root      852: 
                    853: /*-----------------------------------------------------------------------*/
                    854: /**
                    855:  * Force screen redraw.  Does the right thing regardless of whether
                    856:  * we're in ST/STe, Falcon or TT mode.  Needed when switching modes
                    857:  * while emulation is paused.
                    858:  */
                    859: static void Screen_Refresh(void)
                    860: {
1.1.1.24  root      861:        if (bUseVDIRes)
1.1.1.18  root      862:        {
1.1.1.24  root      863:                Screen_GenDraw(VideoBase, VDIWidth, VDIHeight, VDIPlanes,
                    864:                               VDIWidth * VDIPlanes / 16, 0, 0, 0, 0);
                    865:        }
                    866:        else if (Config_IsMachineFalcon())
                    867:        {
                    868:                VIDEL_renderScreen();
                    869:        }
                    870:        else if (Config_IsMachineTT())
                    871:        {
                    872:                Video_RenderTTScreen();
                    873:        }
                    874:        else
                    875:        {
                    876:                Screen_DrawFrame(true);
1.1.1.18  root      877:        }
                    878: }
                    879: 
                    880: 
1.1.1.11  root      881: /*-----------------------------------------------------------------------*/
1.1.1.13  root      882: /**
                    883:  * Enter Full screen mode
                    884:  */
1.1       root      885: void Screen_EnterFullScreen(void)
                    886: {
1.1.1.18  root      887:        bool bWasRunning;
                    888: 
1.1.1.13  root      889:        if (!bInFullScreen)
                    890:        {
1.1.1.18  root      891:                /* Hold things... */
                    892:                bWasRunning = Main_PauseEmulation(false);
1.1.1.17  root      893:                bInFullScreen = true;
1.1.1.2   root      894: 
1.1.1.24  root      895:                if (Screen_UseGenConvScreen())
1.1.1.13  root      896:                {
1.1.1.24  root      897:                        Screen_SetGenConvSize(genconv_width_req, genconv_height_req,
                    898:                                              genconv_bpp, true);
                    899:                        /* force screen redraw */
                    900:                        Screen_GenConvUpdate(NULL, true);
1.1.1.13  root      901:                }
                    902:                else
                    903:                {
1.1.1.24  root      904:                        Screen_SetSTResolution(true);
1.1.1.13  root      905:                        Screen_ClearScreen();       /* Black out screen bitmap as will be invalid when return */
                    906:                }
1.1       root      907: 
1.1.1.24  root      908:                if (!Screen_WantToKeepResolution())
                    909:                {
                    910:                        /* Give monitor time to change to new resolution */
                    911:                        SDL_Delay(20);
                    912:                }
                    913: 
1.1.1.18  root      914:                if (bWasRunning)
                    915:                {
                    916:                        /* And off we go... */
                    917:                        Main_UnPauseEmulation();
                    918:                }
                    919:                else
                    920:                {
                    921:                        Screen_Refresh();
                    922:                }
1.1.1.13  root      923:                SDL_WM_GrabInput(SDL_GRAB_ON);  /* Grab mouse pointer in fullscreen */
                    924:        }
1.1       root      925: }
                    926: 
1.1.1.2   root      927: 
1.1       root      928: /*-----------------------------------------------------------------------*/
1.1.1.13  root      929: /**
                    930:  * Return from Full screen mode back to a window
                    931:  */
1.1       root      932: void Screen_ReturnFromFullScreen(void)
                    933: {
1.1.1.18  root      934:        bool bWasRunning;
                    935: 
1.1.1.13  root      936:        if (bInFullScreen)
                    937:        {
1.1.1.18  root      938:                /* Hold things... */
                    939:                bWasRunning = Main_PauseEmulation(false);
1.1.1.17  root      940:                bInFullScreen = false;
1.1.1.13  root      941: 
1.1.1.24  root      942:                if (Screen_UseGenConvScreen())
1.1.1.13  root      943:                {
1.1.1.24  root      944:                        Screen_SetGenConvSize(genconv_width_req, genconv_height_req,
                    945:                                              genconv_bpp, true);
                    946:                        /* force screen redraw */
                    947:                        Screen_GenConvUpdate(NULL, true);
1.1.1.13  root      948:                }
                    949:                else
                    950:                {
1.1.1.24  root      951:                        Screen_SetSTResolution(true);
                    952:                }
                    953: 
                    954:                if (!Screen_WantToKeepResolution())
                    955:                {
                    956:                        /* Give monitor time to switch resolution */
                    957:                        SDL_Delay(20);
1.1.1.13  root      958:                }
1.1.1.18  root      959: 
                    960:                if (bWasRunning)
                    961:                {
                    962:                        /* And off we go... */
                    963:                        Main_UnPauseEmulation();
                    964:                }
                    965:                else
                    966:                {
                    967:                        Screen_Refresh();
                    968:                }
1.1.1.17  root      969: 
                    970:                if (!bGrabMouse)
1.1.1.18  root      971:                {
1.1.1.17  root      972:                        /* Un-grab mouse pointer in windowed mode */
                    973:                        SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1.1.18  root      974:                }
1.1.1.13  root      975:        }
                    976: }
1.1.1.2   root      977: 
                    978: 
1.1.1.13  root      979: /*-----------------------------------------------------------------------*/
                    980: /**
                    981:  * Have we changed between low/med/high res?
                    982:  */
                    983: static void Screen_DidResolutionChange(int new_res)
                    984: {
                    985:        if (new_res != STRes)
                    986:        {
                    987:                STRes = new_res;
1.1.1.23  root      988:                Screen_ModeChanged(false);
1.1.1.13  root      989:        }
                    990:        else
                    991:        {
                    992:                /* Did change overscan mode? Causes full update */
1.1.1.24  root      993:                if (pFrameBuffer->VerticalOverscanCopy != VerticalOverscan)
1.1.1.17  root      994:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root      995:        }
1.1       root      996: }
                    997: 
1.1.1.5   root      998: 
1.1.1.13  root      999: /**
                   1000:  * Compare current resolution on line with previous, and set 'UpdateLine' accordingly
                   1001:  * Return if swap between low/medium resolution
                   1002:  */
1.1.1.15  root     1003: static bool Screen_CompareResolution(int y, int *pUpdateLine, int oldres)
1.1       root     1004: {
1.1.1.13  root     1005:        /* Check if wrote to resolution register */
                   1006:        if (HBLPaletteMasks[y]&PALETTEMASK_RESOLUTION)  /* See 'Intercept_ShifterMode_WriteByte' */
                   1007:        {
                   1008:                int newres = (HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT;
                   1009:                /* Did resolution change? */
                   1010:                if (newres != (int)((pFrameBuffer->HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT))
                   1011:                        *pUpdateLine |= PALETTEMASK_UPDATERES;
                   1012:                else
                   1013:                        *pUpdateLine &= ~PALETTEMASK_UPDATERES;
                   1014:                /* Have used any low/medium res mix? */
                   1015:                return (newres != (oldres&ST_MEDIUM_RES_BIT));
                   1016:        }
1.1.1.17  root     1017:        return false;
1.1       root     1018: }
                   1019: 
1.1.1.7   root     1020: 
1.1.1.2   root     1021: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1022: /**
                   1023:  * Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
                   1024:  */
1.1.1.8   root     1025: static void Screen_ComparePalette(int y, int *pUpdateLine)
1.1       root     1026: {
1.1.1.17  root     1027:        bool bPaletteChanged = false;
1.1.1.13  root     1028:        int i;
1.1       root     1029: 
1.1.1.13  root     1030:        /* Did write to palette in this or previous frame? */
                   1031:        if (((HBLPaletteMasks[y]|pFrameBuffer->HBLPaletteMasks[y])&PALETTEMASK_PALETTE)!=0)
                   1032:        {
                   1033:                /* Check and update ones which changed */
                   1034:                for (i = 0; i < 16; i++)
                   1035:                {
                   1036:                        if (HBLPaletteMasks[y]&(1<<i))        /* Update changes in ST palette */
                   1037:                                HBLPalette[i] = HBLPalettes[(y*16)+i];
                   1038:                }
                   1039:                /* Now check with same palette from previous frame for any differences(may be changing palette back) */
                   1040:                for (i = 0; (i < 16) && (!bPaletteChanged); i++)
                   1041:                {
                   1042:                        if (HBLPalette[i]!=pFrameBuffer->HBLPalettes[(y*16)+i])
1.1.1.17  root     1043:                                bPaletteChanged = true;
1.1.1.13  root     1044:                }
                   1045:                if (bPaletteChanged)
                   1046:                        *pUpdateLine |= PALETTEMASK_UPDATEPAL;
                   1047:                else
                   1048:                        *pUpdateLine &= ~PALETTEMASK_UPDATEPAL;
                   1049:        }
1.1       root     1050: }
                   1051: 
1.1.1.7   root     1052: 
1.1.1.2   root     1053: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1054: /**
                   1055:  * Check for differences in Palette and Resolution from Mask table and update
                   1056:  * and store off which lines need updating and create full-screen palette.
                   1057:  * (It is very important for these routines to check for colour changes with
                   1058:  * the previous screen so only the very minimum parts are updated).
                   1059:  * Return new STRes value.
                   1060:  */
                   1061: static int Screen_ComparePaletteMask(int res)
1.1       root     1062: {
1.1.1.17  root     1063:        bool bLowMedMix = false;
1.1.1.13  root     1064:        int LineUpdate = 0;
                   1065:        int y;
                   1066: 
                   1067:        /* Set for monochrome? */
                   1068:        if (bUseHighRes)
                   1069:        {
1.1.1.24  root     1070:                VerticalOverscan = V_OVERSCAN_NONE;
1.1.1.13  root     1071: 
1.1.1.24  root     1072:                /* Just copy mono colors */
1.1.1.13  root     1073:                if (HBLPalettes[0] & 0x777)
                   1074:                {
                   1075:                        HBLPalettes[0] = 0x777;
                   1076:                        HBLPalettes[1] = 0x000;
                   1077:                }
                   1078:                else
                   1079:                {
                   1080:                        HBLPalettes[0] = 0x000;
                   1081:                        HBLPalettes[1] = 0x777;
                   1082:                }
                   1083: 
                   1084:                /* Colors changed? */
                   1085:                if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17  root     1086:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root     1087: 
                   1088:                /* Set bit to flag 'full update' */
                   1089:                if (pFrameBuffer->bFullUpdate)
                   1090:                        ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
                   1091:                else
                   1092:                        ScrUpdateFlag = 0x00000000;
                   1093: 
                   1094:                /* Force to standard hi-resolution screen, without overscan */
                   1095:                res = ST_HIGH_RES;
                   1096:        }
                   1097:        else    /* Full colour */
                   1098:        {
                   1099:                /* Get resolution */
                   1100:                //res = (HBLPaletteMasks[0]>>16)&ST_RES_MASK;
                   1101:                /* [NP] keep only low/med bit (could be hires in case of overscan on the 1st line) */
                   1102:                res = (HBLPaletteMasks[0]>>16)&ST_MEDIUM_RES_BIT;
                   1103: 
                   1104:                /* Do all lines - first is tagged as full-update */
                   1105:                for (y = 0; y < NUM_VISIBLE_LINES; y++)
                   1106:                {
                   1107:                        /* Find any resolution/palette change and update palette/mask buffer */
                   1108:                        /* ( LineUpdate has top two bits set to say if line needs updating due to palette or resolution change ) */
                   1109:                        bLowMedMix |= Screen_CompareResolution(y, &LineUpdate, res);
                   1110:                        Screen_ComparePalette(y,&LineUpdate);
                   1111:                        HBLPaletteMasks[y] = (HBLPaletteMasks[y]&(~PALETTEMASK_UPDATEMASK)) | LineUpdate;
                   1112:                        /* Copy palette and mask for next frame */
                   1113:                        memcpy(&pFrameBuffer->HBLPalettes[y*16],HBLPalette,sizeof(short int)*16);
                   1114:                        pFrameBuffer->HBLPaletteMasks[y] = HBLPaletteMasks[y];
                   1115:                }
                   1116:                /* Did mix/have medium resolution? */
                   1117:                if (bLowMedMix || (res & ST_MEDIUM_RES_BIT))
                   1118:                        res = ST_MEDIUM_RES;
                   1119:        }
                   1120: 
1.1.1.24  root     1121:        /* Copy old palette for compare */
                   1122:        memcpy(PrevHBLPalette, HBLPalettes, sizeof(Uint16)*16);
                   1123: 
1.1.1.13  root     1124:        return res;
                   1125: }
                   1126: 
                   1127: 
                   1128: /*-----------------------------------------------------------------------*/
                   1129: /**
                   1130:  * Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
                   1131:  * or when going between a Window and full-screen display
                   1132:  */
1.1.1.8   root     1133: static void Screen_SetFullUpdateMask(void)
1.1       root     1134: {
1.1.1.13  root     1135:        int y;
1.1       root     1136: 
1.1.1.13  root     1137:        for (y = 0; y < NUM_VISIBLE_LINES; y++)
                   1138:                HBLPaletteMasks[y] |= PALETTEMASK_UPDATEFULL;
1.1       root     1139: }
                   1140: 
1.1.1.7   root     1141: 
1.1.1.2   root     1142: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1143: /**
                   1144:  * Set details for ST screen conversion.
                   1145:  */
1.1.1.10  root     1146: static void Screen_SetConvertDetails(void)
1.1       root     1147: {
1.1.1.13  root     1148:        pSTScreen = pFrameBuffer->pSTScreen;          /* Source in ST memory */
                   1149:        pSTScreenCopy = pFrameBuffer->pSTScreenCopy;  /* Previous ST screen */
                   1150:        pPCScreenDest = sdlscrn->pixels;              /* Destination PC screen */
                   1151: 
                   1152:        PCScreenBytesPerLine = sdlscrn->pitch;        /* Bytes per line */
1.1.1.20  root     1153: 
                   1154:        /* Center to available framebuffer */
                   1155:        pPCScreenDest += PCScreenOffsetY * PCScreenBytesPerLine + PCScreenOffsetX * (sdlscrn->format->BitsPerPixel/8);
                   1156: 
1.1.1.13  root     1157:        pHBLPalettes = pFrameBuffer->HBLPalettes;     /* HBL palettes pointer */
                   1158:        /* Not in TV-Mode? Then double up on Y: */
1.1.1.15  root     1159:        bScrDoubleY = !(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_TV);
1.1.1.13  root     1160: 
1.1.1.24  root     1161:        if (ConfigureParams.Screen.bAllowOverscan)  /* Use borders? */
1.1.1.13  root     1162:        {
1.1.1.24  root     1163:                /* Always draw to WHOLE screen including ALL borders */
                   1164:                STScreenLeftSkipBytes = 0;              /* Number of bytes to skip on ST screen for left (border) */
1.1.1.13  root     1165: 
1.1.1.24  root     1166:                if (bUseHighRes)
                   1167:                {
                   1168:                                pFrameBuffer->VerticalOverscanCopy = VerticalOverscan = V_OVERSCAN_NONE;
                   1169:                        STScreenStartHorizLine = 0;
                   1170:                        STScreenEndHorizLine = 400;
1.1.1.13  root     1171:                }
                   1172:                else
                   1173:                {
1.1.1.24  root     1174:                        STScreenWidthBytes = SCREENBYTES_LINE;  /* Number of horizontal bytes in our ST screen */
                   1175:                        STScreenStartHorizLine = OVERSCAN_TOP - nBorderPixelsTop;
                   1176:                        STScreenEndHorizLine = OVERSCAN_TOP + 200 + nBorderPixelsBottom;
1.1.1.13  root     1177:                }
                   1178:        }
1.1.1.24  root     1179:        else
                   1180:        {
                   1181:                /* Only draw main area and centre on Y */
                   1182:                STScreenLeftSkipBytes = SCREENBYTES_LEFT;
                   1183:                STScreenWidthBytes = SCREENBYTES_MIDDLE;
                   1184:                STScreenStartHorizLine = OVERSCAN_TOP;
                   1185:                STScreenEndHorizLine = OVERSCAN_TOP + (bUseHighRes ? 400 : 200);
                   1186:        }
1.1       root     1187: }
                   1188: 
1.1.1.2   root     1189: 
                   1190: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1191: /**
                   1192:  * Lock full-screen for drawing
                   1193:  */
1.1.1.24  root     1194: bool Screen_Lock(void)
1.1       root     1195: {
1.1.1.13  root     1196:        if (SDL_MUSTLOCK(sdlscrn))
                   1197:        {
                   1198:                if (SDL_LockSurface(sdlscrn))
                   1199:                {
                   1200:                        Screen_ReturnFromFullScreen();   /* All OK? If not need to jump back to a window */
1.1.1.17  root     1201:                        return false;
1.1.1.13  root     1202:                }
                   1203:        }
1.1.1.2   root     1204: 
1.1.1.17  root     1205:        return true;
1.1       root     1206: }
                   1207: 
1.1.1.2   root     1208: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1209: /**
                   1210:  * UnLock full-screen
                   1211:  */
1.1.1.24  root     1212: void Screen_UnLock(void)
1.1       root     1213: {
1.1.1.13  root     1214:        if ( SDL_MUSTLOCK(sdlscrn) )
                   1215:                SDL_UnlockSurface(sdlscrn);
1.1       root     1216: }
                   1217: 
1.1.1.2   root     1218: 
                   1219: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1220: /**
                   1221:  * Blit our converted ST screen to window/full-screen
                   1222:  */
1.1.1.22  root     1223: static void Screen_Blit(SDL_Rect *sbar_rect)
1.1       root     1224: {
1.1.1.13  root     1225:        unsigned char *pTmpScreen;
                   1226: 
1.1.1.18  root     1227: #if 0  /* double buffering cannot be used with partial screen updates */
                   1228: # if NUM_FRAMEBUFFERS > 1
                   1229:        if (bInFullScreen && (sdlscrn->flags & SDL_DOUBLEBUF))
1.1.1.13  root     1230:        {
                   1231:                /* Swap screen */
1.1.1.18  root     1232:                if (pFrameBuffer==&FrameBuffers[0])
                   1233:                        pFrameBuffer = &FrameBuffers[1];
                   1234:                else
                   1235:                        pFrameBuffer = &FrameBuffers[0];
1.1.1.15  root     1236:                SDL_Flip(sdlscrn);
1.1.1.13  root     1237:        }
                   1238:        else
1.1.1.18  root     1239: # endif
                   1240: #endif
1.1.1.13  root     1241:        {
1.1.1.22  root     1242:                int count = 1;
                   1243:                SDL_Rect rects[2];
                   1244:                rects[0] = STScreenRect;
                   1245:                if (sbar_rect)
                   1246:                {
                   1247:                        rects[1] = *sbar_rect;
                   1248:                        count = 2;
                   1249:                }
                   1250:                SDL_UpdateRects(sdlscrn, count, rects);
1.1.1.13  root     1251:        }
                   1252: 
                   1253:        /* Swap copy/raster buffers in screen. */
                   1254:        pTmpScreen = pFrameBuffer->pSTScreenCopy;
                   1255:        pFrameBuffer->pSTScreenCopy = pFrameBuffer->pSTScreen;
                   1256:        pFrameBuffer->pSTScreen = pTmpScreen;
1.1       root     1257: }
                   1258: 
1.1.1.3   root     1259: 
1.1.1.2   root     1260: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1261: /**
                   1262:  * Draw ST screen to window/full-screen framebuffer
1.1.1.15  root     1263:  * @param  bForceFlip  Force screen update, even if contents did not change
1.1.1.17  root     1264:  * @return  true if screen contents changed
1.1.1.13  root     1265:  */
1.1.1.15  root     1266: static bool Screen_DrawFrame(bool bForceFlip)
1.1       root     1267: {
1.1.1.13  root     1268:        int new_res;
                   1269:        void (*pDrawFunction)(void);
1.1.1.17  root     1270:        static bool bPrevFrameWasSpec512 = false;
1.1.1.22  root     1271:        SDL_Rect *sbar_rect;
1.1.1.13  root     1272: 
1.1.1.24  root     1273:        assert(!bUseVDIRes);
                   1274: 
1.1.1.13  root     1275:        /* Scan palette/resolution masks for each line and build up palette/difference tables */
                   1276:        new_res = Screen_ComparePaletteMask(STRes);
                   1277:        /* Did we change resolution this frame - allocate new screen if did so */
                   1278:        Screen_DidResolutionChange(new_res);
                   1279:        /* Is need full-update, tag as such */
                   1280:        if (pFrameBuffer->bFullUpdate)
                   1281:                Screen_SetFullUpdateMask();
                   1282: 
1.1.1.15  root     1283:        /* restore area potentially left under overlay led
                   1284:         * and saved by Statusbar_OverlayBackup()
                   1285:         */
                   1286:        Statusbar_OverlayRestore(sdlscrn);
1.1.1.22  root     1287: 
                   1288:        /* Lock screen for direct screen surface format writes */
1.1.1.26! root     1289:        if (ConfigureParams.Screen.DisableVideo || !Screen_Lock())
1.1.1.13  root     1290:        {
1.1.1.26! root     1291:                return false;
        !          1292:        }
1.1.1.15  root     1293: 
1.1.1.26! root     1294:        bScreenContentsChanged = false;      /* Did change (ie needs blit?) */
1.1.1.24  root     1295: 
1.1.1.26! root     1296:        /* Set details */
        !          1297:        Screen_SetConvertDetails();
1.1.1.13  root     1298: 
1.1.1.26! root     1299:        /* Clear screen on full update to clear out borders and also interleaved lines */
        !          1300:        if (pFrameBuffer->bFullUpdate)
        !          1301:                Screen_ClearScreen();
1.1.1.13  root     1302: 
1.1.1.26! root     1303:        /* Call drawing for full-screen */
        !          1304:        pDrawFunction = ScreenDrawFunctionsNormal[STRes];
        !          1305:        /* Check if is Spec512 image */
        !          1306:        if (Spec512_IsImage())
        !          1307:        {
        !          1308:                bPrevFrameWasSpec512 = true;
        !          1309:                /* What mode were we in? Keep to 320xH or 640xH */
        !          1310:                if (pDrawFunction==ConvertLowRes_320x16Bit)
        !          1311:                        pDrawFunction = ConvertLowRes_320x16Bit_Spec;
        !          1312:                else if (pDrawFunction==ConvertLowRes_640x16Bit)
        !          1313:                        pDrawFunction = ConvertLowRes_640x16Bit_Spec;
        !          1314:                else if (pDrawFunction==ConvertLowRes_320x32Bit)
        !          1315:                        pDrawFunction = ConvertLowRes_320x32Bit_Spec;
        !          1316:                else if (pDrawFunction==ConvertLowRes_640x32Bit)
        !          1317:                        pDrawFunction = ConvertLowRes_640x32Bit_Spec;
        !          1318:                else if (pDrawFunction==ConvertMediumRes_640x32Bit)
        !          1319:                        pDrawFunction = ConvertMediumRes_640x32Bit_Spec;
        !          1320:                else if (pDrawFunction==ConvertMediumRes_640x16Bit)
        !          1321:                        pDrawFunction = ConvertMediumRes_640x16Bit_Spec;
        !          1322:        }
        !          1323:        else if (bPrevFrameWasSpec512)
        !          1324:        {
        !          1325:                /* If we switch back from Spec512 mode to normal
        !          1326:                 * screen rendering, we have to make sure to do
        !          1327:                 * a full update of the screen. */
        !          1328:                Screen_SetFullUpdateMask();
        !          1329:                bPrevFrameWasSpec512 = false;
1.1.1.13  root     1330:        }
1.1.1.15  root     1331: 
1.1.1.26! root     1332:        if (pDrawFunction)
        !          1333:                CALL_VAR(pDrawFunction);
        !          1334: 
        !          1335:        /* Unlock screen */
        !          1336:        Screen_UnLock();
        !          1337: 
        !          1338:        /* draw overlay led(s) or statusbar after unlock */
        !          1339:        Statusbar_OverlayBackup(sdlscrn);
        !          1340:        sbar_rect = Statusbar_Update(sdlscrn, false);
        !          1341: 
        !          1342:        /* Clear flags, remember type of overscan as if change need screen full update */
        !          1343:        pFrameBuffer->bFullUpdate = false;
        !          1344:        pFrameBuffer->VerticalOverscanCopy = VerticalOverscan;
        !          1345: 
        !          1346:        /* And show to user */
        !          1347:        if (bScreenContentsChanged || bForceFlip || sbar_rect)
        !          1348:        {
        !          1349:                Screen_Blit(sbar_rect);
        !          1350:        }
        !          1351: 
        !          1352:        return bScreenContentsChanged;
1.1       root     1353: }
                   1354: 
1.1.1.9   root     1355: 
1.1.1.2   root     1356: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1357: /**
                   1358:  * Draw ST screen to window/full-screen
                   1359:  */
1.1.1.15  root     1360: bool Screen_Draw(void)
1.1       root     1361: {
1.1.1.25  root     1362:        if (bQuitProgram)
1.1.1.13  root     1363:        {
1.1.1.24  root     1364:                return false;
1.1.1.13  root     1365:        }
1.1.1.15  root     1366: 
1.1.1.24  root     1367:        /* And draw (if screen contents changed) */
                   1368:        return Screen_DrawFrame(false);
                   1369: }
                   1370: 
                   1371: /**
                   1372:  * This is used to set the size of the SDL screen
                   1373:  * when we're using the generic conversion functions.
                   1374:  */
                   1375: void Screen_SetGenConvSize(int width, int height, int bpp, bool bForceChange)
                   1376: {
                   1377:        const bool keep = ConfigureParams.Screen.bKeepResolution;
                   1378:        int screenwidth, screenheight, maxw, maxh;
                   1379:        int scalex, scaley, sbarheight;
                   1380: 
                   1381:        if (bpp == 24)
                   1382:                bpp = 32;
                   1383: 
                   1384:        /* constrain size request to user's desktop size */
                   1385:        Resolution_GetDesktopSize(&maxw, &maxh);
                   1386: #if !WITH_SDL2
                   1387:        scalex = scaley = 1;
                   1388:        while (width > maxw*scalex) {
                   1389:                scalex *= 2;
                   1390:        }
                   1391:        while (height > maxh*scaley) {
                   1392:                scaley *= 2;
                   1393:        }
                   1394:        if (scalex * scaley > 1) {
1.1.1.26! root     1395:                Log_Printf(LOG_WARN, "Too large screen size %dx%d -> divided by %dx%d!\n",
1.1.1.24  root     1396:                        width, height, scalex, scaley);
                   1397:                width /= scalex;
                   1398:                height /= scaley;
                   1399:        }
                   1400: #endif
                   1401: 
                   1402:        Resolution_GetLimits(&maxw, &maxh, &bpp, keep);
                   1403:        nScreenZoomX = nScreenZoomY = 1;
                   1404: 
                   1405:        if (ConfigureParams.Screen.bAspectCorrect) {
                   1406:                /* Falcon (and TT) pixel scaling factors seem to 2^x
                   1407:                 * (quarter/half pixel, interlace/double line), so
                   1408:                 * do aspect correction as 2's exponent.
                   1409:                 */
                   1410:                while (nScreenZoomX*width < height &&
                   1411:                       2*nScreenZoomX*width < maxw) {
                   1412:                        nScreenZoomX *= 2;
                   1413:                }
                   1414:                while (2*nScreenZoomY*height < width &&
                   1415:                       2*nScreenZoomY*height < maxh) {
                   1416:                        nScreenZoomY *= 2;
                   1417:                }
                   1418:                if (nScreenZoomX*nScreenZoomY > 2) {
1.1.1.26! root     1419:                        Log_Printf(LOG_WARN, "Strange screen size %dx%d -> aspect corrected by %dx%d!\n",
1.1.1.24  root     1420:                                width, height, nScreenZoomX, nScreenZoomY);
                   1421:                }
                   1422:        }
                   1423: 
                   1424:        /* then select scale as close to target size as possible
                   1425:         * without having larger size than it
                   1426:         */
                   1427:        scalex = maxw/(nScreenZoomX*width);
                   1428:        scaley = maxh/(nScreenZoomY*height);
                   1429:        if (scalex > 1 && scaley > 1) {
                   1430:                /* keep aspect ratio */
                   1431:                if (scalex < scaley) {
                   1432:                        nScreenZoomX *= scalex;
                   1433:                        nScreenZoomY *= scalex;
                   1434:                } else {
                   1435:                        nScreenZoomX *= scaley;
                   1436:                        nScreenZoomY *= scaley;
                   1437:                }
                   1438:        }
                   1439: 
                   1440:        genconv_width_req = width;
                   1441:        genconv_height_req = height;
                   1442:        width *= nScreenZoomX;
                   1443:        height *= nScreenZoomY;
                   1444: 
                   1445:        /* get statusbar size for this screen size */
                   1446:        sbarheight = Statusbar_GetHeightForSize(width, height);
                   1447:        screenheight = height + sbarheight;
                   1448:        screenwidth = width;
                   1449: 
                   1450: #if !WITH_SDL2
                   1451:        /* get resolution corresponding to these */
                   1452:        Resolution_Search(&screenwidth, &screenheight, &bpp, keep);
                   1453: #endif
                   1454:        /* re-calculate statusbar height for this resolution */
                   1455:        sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight);
                   1456: 
                   1457:        genconv_bpp = bpp;
                   1458:        /* screen area without the statusbar */
                   1459:        STScreenRect.x = STScreenRect.y = 0;
                   1460:        STScreenRect.w = screenwidth;
                   1461:        STScreenRect.h = screenheight - sbarheight;
                   1462: 
                   1463:        if (!Screen_SetSDLVideoSize(screenwidth, screenheight, bpp, bForceChange))
                   1464:        {
                   1465:                /* same host screen size despite Atari resolution change,
                   1466:                 * -> no time consuming host video mode change needed
                   1467:                 */
                   1468:                if (screenwidth > width || screenheight > height+sbarheight) {
                   1469:                        /* Atari screen smaller than host -> clear screen */
                   1470:                        Screen_ClearScreen();
                   1471:                        /* re-calculate variables in case height + statusbar height
                   1472:                         * don't anymore match SDL surface size (there's an assert
                   1473:                         * for that)
                   1474:                         */
                   1475:                        Statusbar_Init(sdlscrn);
                   1476:                }
                   1477: #if WITH_SDL2
                   1478:                genconv_do_update = true;
                   1479: #else
                   1480:                genconv_do_update = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;
                   1481: #endif
                   1482:                return;
                   1483:        }
                   1484: 
                   1485:        // In case surface format changed, remap the native palette
                   1486:        Screen_RemapPalette();
                   1487: 
                   1488:        // redraw statusbar
                   1489:        Statusbar_Init(sdlscrn);
                   1490: 
                   1491:        DEBUGPRINT(("Surface Pitch = %d, width = %d, height = %d\n", sdlscrn->pitch, sdlscrn->w, sdlscrn->h));
                   1492:        DEBUGPRINT(("Must Lock? %s\n", SDL_MUSTLOCK(sdlscrn) ? "YES" : "NO"));
                   1493: 
                   1494: #if WITH_SDL2
                   1495:        genconv_do_update = true;
                   1496: #else
                   1497:        // is the SDL_update needed?
                   1498:        genconv_do_update = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;
                   1499: #endif
                   1500: 
                   1501:        DEBUGPRINT(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x"
                   1502:                        ", tshifts r=%d g=%d b=%d"
                   1503:                        ", tlosses r=%d g=%d b=%d\n",
                   1504:                        sdlscrn->format->BitsPerPixel,
                   1505:                        sdlscrn->format->Rmask, sdlscrn->format->Gmask, sdlscrn->format->Bmask,
                   1506:                        sdlscrn->format->Rshift, sdlscrn->format->Gshift, sdlscrn->format->Bshift,
                   1507:                        sdlscrn->format->Rloss, sdlscrn->format->Gloss, sdlscrn->format->Bloss));
                   1508: 
                   1509:        Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2, false);
                   1510: }
                   1511: 
                   1512: void Screen_GenConvUpdate(SDL_Rect *extra, bool forced)
                   1513: {
                   1514:        SDL_Rect rects[2];
                   1515:        int count = 1;
                   1516: 
1.1.1.25  root     1517:        /* Don't update anything on screen if video output is disabled */
                   1518:        if ( ConfigureParams.Screen.DisableVideo )
                   1519:                return;
                   1520: 
1.1.1.24  root     1521:        if (!forced && !genconv_do_update) // the HW surface is available
                   1522:                return;
                   1523: 
                   1524:        rects[0] = STScreenRect;
                   1525:        if (extra) {
                   1526:                rects[1] = *extra;
                   1527:                count = 2;
                   1528:        }
                   1529:        SDL_UpdateRects(sdlscrn, count, rects);
                   1530: }
                   1531: 
                   1532: Uint32 Screen_GetGenConvWidth(void)
                   1533: {
                   1534:        return STScreenRect.w;
                   1535: }
                   1536: 
                   1537: Uint32 Screen_GetGenConvHeight(void)
                   1538: {
                   1539:        return STScreenRect.h;
1.1       root     1540: }
1.1.1.11  root     1541: 
                   1542: 
                   1543: /* -------------- screen conversion routines --------------------------------
                   1544:   Screen conversion routines. We have a number of routines to convert ST screen
                   1545:   to PC format. We split these into Low, Medium and High each with 8/16-bit
                   1546:   versions. To gain extra speed, as almost half of the processing time can be
                   1547:   spent in these routines, we check for any changes from the previously
                   1548:   displayed frame. AdjustLinePaletteRemap() sets a flag to tell the routines
                   1549:   if we need to totally update a line (ie full update, or palette/res change)
                   1550:   or if we just can do a difference check.
                   1551:   We convert each screen 16 pixels at a time by use of a couple of look-up
                   1552:   tables. These tables convert from 2-plane format to bbp and then we can add
                   1553:   two of these together to get 4-planes. This keeps the tables small and thus
                   1554:   improves speed. We then look these bbp values up as an RGB/Index value to
                   1555:   copy to the screen.
                   1556: */
                   1557: 
                   1558: 
1.1.1.13  root     1559: /*-----------------------------------------------------------------------*/
                   1560: /**
1.1.1.11  root     1561:  * Update the STRGBPalette[] array with current colours for this raster line.
                   1562:  *
                   1563:  * Return 'ScrUpdateFlag', 0x80000000=Full update, 0x40000000=Update
                   1564:  * as palette changed
                   1565:  */
                   1566: static int AdjustLinePaletteRemap(int y)
                   1567: {
                   1568: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root     1569:        static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
1.1.1.11  root     1570: #endif
1.1.1.13  root     1571:        Uint16 *actHBLPal;
                   1572:        int i;
1.1.1.11  root     1573: 
1.1.1.13  root     1574:        /* Copy palette and convert to RGB in display format */
                   1575:        actHBLPal = pHBLPalettes + (y<<4);    /* offset in palette */
                   1576:        for (i=0; i<16; i++)
                   1577:        {
1.1.1.11  root     1578: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root     1579:                STRGBPalette[endiantable[i]] = ST2RGB[*actHBLPal++];
1.1.1.11  root     1580: #else
1.1.1.13  root     1581:                STRGBPalette[i] = ST2RGB[*actHBLPal++];
1.1.1.11  root     1582: #endif
1.1.1.13  root     1583:        }
                   1584:        ScrUpdateFlag = HBLPaletteMasks[y];
                   1585:        return ScrUpdateFlag;
1.1.1.11  root     1586: }
                   1587: 
                   1588: 
1.1.1.13  root     1589: /*-----------------------------------------------------------------------*/
                   1590: /**
1.1.1.11  root     1591:  * Run updates to palette(STRGBPalette[]) until get to screen line
                   1592:  * we are to convert from
                   1593:  */
                   1594: static void Convert_StartFrame(void)
                   1595: {
1.1.1.13  root     1596:        int y = 0;
                   1597:        /* Get #lines before conversion starts */
                   1598:        int lines = STScreenStartHorizLine;
                   1599:        while (lines--)
                   1600:                AdjustLinePaletteRemap(y++);     /* Update palette */
1.1.1.11  root     1601: }
                   1602: 
                   1603: /* lookup tables and conversion macros */
                   1604: #include "convert/macros.h"
                   1605: 
                   1606: /* Conversion routines */
1.1.1.13  root     1607: 
1.1.1.19  root     1608: #include "convert/low320x16.c"         /* LowRes To 320xH x 16-bit color */
                   1609: #include "convert/low640x16.c"         /* LowRes To 640xH x 16-bit color */
                   1610: #include "convert/med640x16.c"         /* MediumRes To 640xH x 16-bit color */
                   1611: #include "convert/low320x16_spec.c"    /* LowRes Spectrum 512 To 320xH x 16-bit color */
                   1612: #include "convert/low640x16_spec.c"    /* LowRes Spectrum 512 To 640xH x 16-bit color */
                   1613: #include "convert/med640x16_spec.c"    /* MediumRes Spectrum 512 To 640xH x 16-bit color */
                   1614: 
                   1615: #include "convert/low320x32.c"         /* LowRes To 320xH x 32-bit color */
                   1616: #include "convert/low640x32.c"         /* LowRes To 640xH x 32-bit color */
                   1617: #include "convert/med640x32.c"         /* MediumRes To 640xH x 32-bit color */
                   1618: #include "convert/low320x32_spec.c"    /* LowRes Spectrum 512 To 320xH x 32-bit color */
                   1619: #include "convert/low640x32_spec.c"    /* LowRes Spectrum 512 To 640xH x 32-bit color */
                   1620: #include "convert/med640x32_spec.c"    /* MediumRes Spectrum 512 To 640xH x 32-bit color */

unix.superglobalmegacorp.com

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