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

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