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

1.1       root        1: /*
1.1.1.6   root        2:   Hatari - screen.c
1.1       root        3: 
1.1.1.6   root        4:   This file is distributed under the GNU Public License, version 2 or at your
                      5:   option any later version. Read the file gpl.txt for details.
                      6: 
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       root       31: 
                     32: #include "main.h"
1.1.1.7   root       33: #include "configuration.h"
1.1       root       34: #include "ikbd.h"
1.1.1.13  root       35: #include "log.h"
1.1       root       36: #include "m68000.h"
1.1.1.13  root       37: #include "paths.h"
1.1       root       38: #include "screen.h"
1.1.1.15  root       39: #include "control.h"
1.1.1.11  root       40: #include "convert/routines.h"
1.1       root       41: #include "sound.h"
                     42: #include "spec512.h"
1.1.1.15  root       43: #include "statusbar.h"
1.1       root       44: #include "vdi.h"
                     45: #include "video.h"
1.1.1.13  root       46: #include "falcon/videl.h"
                     47: #include "falcon/hostscreen.h"
1.1       root       48: 
                     49: 
1.1.1.13  root       50: /* extern for several purposes */
                     51: SDL_Surface *sdlscrn = NULL;                /* The SDL screen surface */
                     52: int nScreenZoomX, nScreenZoomY;             /* Zooming factors, used for scaling mouse motions */
                     53: int nBorderPixelsLeft, nBorderPixelsRight;  /* Pixels in left and right border */
1.1.1.15  root       54: int nBorderPixelsTop, nBorderPixelsBottom;  /* Lines in top and bottom border */
1.1.1.13  root       55: 
                     56: /* extern for shortcuts and falcon/hostscreen.c */
1.1.1.17! root       57: bool bGrabMouse = false;      /* Grab the mouse cursor in the window */
        !            58: bool bInFullScreen = false;   /* true if in full screen */
1.1.1.13  root       59: 
                     60: /* extern for spec512.c */
1.1.1.11  root       61: int STScreenLeftSkipBytes;
                     62: int STScreenStartHorizLine;   /* Start lines to be converted */
                     63: Uint32 STRGBPalette[16];      /* Palette buffer used in conversion routines */
                     64: Uint32 ST2RGB[4096];          /* Table to convert ST 0x777 / STe 0xfff palette to PC format RGB551 (2 pixels each entry) */
1.1.1.13  root       65: 
                     66: /* extern for video.c */
1.1.1.11  root       67: Uint8 *pSTScreen;
                     68: FRAMEBUFFER *pFrameBuffer;    /* Pointer into current 'FrameBuffer' */
                     69: 
                     70: static FRAMEBUFFER FrameBuffers[NUM_FRAMEBUFFERS]; /* Store frame buffer details to tell how to update */
                     71: static Uint8 *pSTScreenCopy;                       /* Keep track of current and previous ST screen data */
                     72: static Uint8 *pPCScreenDest;                       /* Destination PC buffer */
                     73: static int STScreenEndHorizLine;                   /* End lines to be converted */
                     74: static int PCScreenBytesPerLine;
                     75: static int STScreenWidthBytes;
1.1.1.15  root       76: static SDL_Rect STScreenRect;                      /* screen size without statusbar */
1.1       root       77: 
1.1.1.11  root       78: static int STScreenLineOffset[NUM_VISIBLE_LINES];  /* Offsets for ST screen lines eg, 0,160,320... */
                     79: static Uint16 HBLPalette[16], PrevHBLPalette[16];  /* Current palette for line, also copy of first line */
1.1       root       80: 
1.1.1.13  root       81: static void (*ScreenDrawFunctionsNormal[3])(void); /* Screen draw functions */
1.1.1.12  root       82: static void (*ScreenDrawFunctionsVDI[3])(void) =
1.1.1.10  root       83: {
1.1.1.13  root       84:        ConvertVDIRes_16Colour,
                     85:        ConvertVDIRes_4Colour,
                     86:        ConvertVDIRes_2Colour
1.1.1.10  root       87: };
                     88: 
1.1.1.17! root       89: static bool bScreenContentsChanged;     /* true if buffer changed and requires blitting */
        !            90: static bool bScrDoubleY;                /* true if double on Y */
1.1.1.11  root       91: static int ScrUpdateFlag;               /* Bit mask of how to update screen */
                     92: 
1.1.1.10  root       93: 
                     94: /*-----------------------------------------------------------------------*/
1.1.1.13  root       95: /**
                     96:  * Create ST 0x777 / STe 0xfff color format to 16 or 32 bits per pixel
                     97:  * conversion table. Called each time when changed resolution or to/from
                     98:  * fullscreen mode.
                     99:  */
1.1.1.10  root      100: static void Screen_SetupRGBTable(void)
                    101: {
1.1.1.13  root      102:        Uint16 STColor;
                    103:        Uint32 RGBColor;
                    104:        int r, g, b;
                    105:        int rr, gg, bb;
                    106: 
                    107:        /* Do Red, Green and Blue for all 16*16*16 = 4096 STe colors */
                    108:        for (r = 0; r < 16; r++)
                    109:        {
                    110:                for (g = 0; g < 16; g++)
                    111:                {
                    112:                        for (b = 0; b < 16; b++)
                    113:                        {
                    114:                                /* STe 0xfff format */
                    115:                                STColor = (r<<8) | (g<<4) | (b);
                    116:                                rr = ((r & 0x7) << 5) | ((r & 0x8) << 1);
                    117:                                gg = ((g & 0x7) << 5) | ((g & 0x8) << 1);
                    118:                                bb = ((b & 0x7) << 5) | ((b & 0x8) << 1);
                    119:                                RGBColor = SDL_MapRGB(sdlscrn->format, rr, gg, bb);
                    120:                                if (sdlscrn->format->BitsPerPixel <= 16)
                    121:                                {
                    122:                                        /* As longs, for speed (write two pixels at once) */
                    123:                                        ST2RGB[STColor] = (RGBColor<<16) | RGBColor;
                    124:                                }
                    125:                                else
                    126:                                {
                    127:                                        ST2RGB[STColor] = RGBColor;
                    128:                                }
                    129:                        }
                    130:                }
                    131:        }
1.1.1.10  root      132: }
                    133: 
1.1.1.13  root      134: 
1.1.1.10  root      135: /*-----------------------------------------------------------------------*/
1.1.1.13  root      136: /**
                    137:  * Create new palette for display.
                    138:  */
1.1.1.10  root      139: static void Screen_CreatePalette(void)
                    140: {
                    141: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root      142:        static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
1.1.1.10  root      143: #endif
1.1.1.13  root      144:        SDL_Color sdlColors[16];
                    145:        int i, j;
1.1.1.10  root      146: 
1.1.1.13  root      147:        if (bUseHighRes)
                    148:        {
                    149:                /* Colors for monochrome screen mode emulation */
                    150:                if (HBLPalettes[0])
                    151:                {
                    152:                        sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 255;
                    153:                        sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 0;
                    154:                }
                    155:                else
                    156:                {
                    157:                        sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 0;
                    158:                        sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 255;
                    159:                }
                    160:                SDL_SetColors(sdlscrn, sdlColors, 10, 2);
                    161:                /*SDL_SetColors(sdlscrn, sdlColors, 0, 2);*/
                    162:        }
                    163:        else
                    164:        {
                    165:                int r, g, b;
                    166:                /* Colors for STe color screen mode emulation */
                    167:                for (i = 0; i < 16; i++)
                    168:                {
1.1.1.11  root      169: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root      170:                        j = endiantable[i];
1.1.1.11  root      171: #else
1.1.1.13  root      172:                        j = i;
1.1.1.11  root      173: #endif
1.1.1.13  root      174:                        /* normalize all to 0x1e0 */
                    175:                        r = HBLPalettes[i] >> 3;
                    176:                        g = HBLPalettes[i] << 1;
                    177:                        b = HBLPalettes[i] << 5;
                    178:                        /* move top bit of 0x1e0 to lowest in 0xf0 */
                    179:                        sdlColors[j].r = (r & 0xe0) | ((r & 0x100) >> 4);
                    180:                        sdlColors[j].g = (g & 0xe0) | ((g & 0x100) >> 4);
                    181:                        sdlColors[j].b = (b & 0xe0) | ((b & 0x100) >> 4);
                    182:                }
                    183:                SDL_SetColors(sdlscrn, sdlColors, 10, 16);
                    184:        }
1.1.1.10  root      185: }
                    186: 
                    187: 
                    188: /*-----------------------------------------------------------------------*/
1.1.1.13  root      189: /**
                    190:  * Create 8-Bit palette for display if needed.
                    191:  */
1.1.1.10  root      192: static void Screen_Handle8BitPalettes(void)
                    193: {
1.1.1.17! root      194:        bool bPaletteChanged = false;
1.1.1.13  root      195:        int i;
1.1.1.10  root      196: 
1.1.1.13  root      197:        /* Do need to check for 8-Bit palette change? Ie, update whole screen */
                    198:        /* VDI screens and monochrome modes are ALL 8-Bit at the moment! */
                    199:        if (sdlscrn->format->BitsPerPixel == 8)
                    200:        {
                    201:                /* If using HiRes palette update with full update flag */
                    202:                if (!bUseHighRes)
                    203:                {
                    204:                        /* Check if palette of 16 colours changed from previous frame */
                    205:                        for (i = 0; i < 16 && !bPaletteChanged; i++)
                    206:                        {
                    207:                                /* Check with first line palette (stored in 'Screen_ComparePaletteMask') */
                    208:                                if (HBLPalettes[i] != PrevHBLPalette[i])
1.1.1.17! root      209:                                        bPaletteChanged = true;
1.1.1.13  root      210:                        }
                    211:                }
                    212: 
                    213:                /* Did palette change or do we require a full update? */
                    214:                if (bPaletteChanged || pFrameBuffer->bFullUpdate)
                    215:                {
                    216:                        /* Create palette, for Full-Screen of Window */
                    217:                        Screen_CreatePalette();
                    218:                        /* Make sure update whole screen */
1.1.1.17! root      219:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root      220:                }
                    221:        }
1.1.1.10  root      222: 
1.1.1.13  root      223:        /* Copy old palette for 8-Bit compare as this routine writes over it */
                    224:        memcpy(PrevHBLPalette,HBLPalettes, sizeof(Uint16)*16);
1.1.1.10  root      225: }
                    226: 
1.1       root      227: 
                    228: /*-----------------------------------------------------------------------*/
1.1.1.13  root      229: /**
                    230:  * Set screen draw functions.
                    231:  */
                    232: static void Screen_SetDrawFunctions(int nBitCount)
1.1.1.10  root      233: {
1.1.1.14  root      234:        if (nBitCount == 8)
1.1.1.13  root      235:        {
                    236:                /* Low color */
                    237:                if (ConfigureParams.Screen.bZoomLowRes)
                    238:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x8Bit;
                    239:                else
                    240:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x8Bit;
                    241:                ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x8Bit;
                    242:                ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    243:        }
                    244:        else if (nBitCount <= 16)
                    245:        {
                    246:                /* High color */
                    247:                if (ConfigureParams.Screen.bZoomLowRes)
                    248:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x16Bit;
                    249:                else
                    250:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x16Bit;
                    251:                ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x16Bit;
                    252:                ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    253:        }
                    254:        else /* Assume 32 bit drawing functions */
                    255:        {
                    256:                /* True color */
                    257:                if (ConfigureParams.Screen.bZoomLowRes)
                    258:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x32Bit;
                    259:                else
                    260:                        ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x32Bit;
                    261:                ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x32Bit;
                    262:                ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    263:        }
1.1.1.10  root      264: }
                    265: 
                    266: 
                    267: /*-----------------------------------------------------------------------*/
1.1.1.13  root      268: /**
                    269:  * Set amount of border pixels for windowed and full-screen mode and
                    270:  * store Y offset for each horizontal line in our source ST screen for
                    271:  * reference in tje convert functions.
                    272:  */
                    273: static void Screen_SetSTScreenOffsets(void)
1.1.1.7   root      274: {
1.1.1.13  root      275:        int i;
1.1.1.7   root      276: 
1.1.1.13  root      277:        /* Determine border pixels */
                    278:        if (bInFullScreen)
                    279:        {
1.1.1.15  root      280:                nBorderPixelsTop = ConfigureParams.Screen.nFullScreenBorderPixelsTop;
1.1.1.13  root      281:                nBorderPixelsLeft = ConfigureParams.Screen.nFullScreenBorderPixelsLeft;
                    282:                nBorderPixelsRight = ConfigureParams.Screen.nFullScreenBorderPixelsRight;
                    283:                nBorderPixelsBottom = ConfigureParams.Screen.nFullScreenBorderPixelsBottom;
                    284:        }
                    285:        else
                    286:        {
1.1.1.15  root      287:                nBorderPixelsTop = ConfigureParams.Screen.nWindowBorderPixelsTop;
1.1.1.13  root      288:                nBorderPixelsLeft = ConfigureParams.Screen.nWindowBorderPixelsLeft;
                    289:                nBorderPixelsRight = ConfigureParams.Screen.nWindowBorderPixelsRight;
                    290:                nBorderPixelsBottom = ConfigureParams.Screen.nWindowBorderPixelsBottom;
                    291:        }
1.1.1.15  root      292:        /* All screen widths need to be aligned to 16-bits.
                    293:         * 
                    294:         * TODO: Change VDI_Limit() to generic function and check
                    295:         * the limits when config values are set or changed (after 1.1).
                    296:         */
                    297:        nBorderPixelsTop = VDI_Limit(nBorderPixelsTop, 1, 0, OVERSCAN_TOP);
                    298:        nBorderPixelsLeft = VDI_Limit(nBorderPixelsLeft, 16, 0, 48);
                    299:        nBorderPixelsRight = VDI_Limit(nBorderPixelsRight, 16, 0, 48);
                    300:        nBorderPixelsBottom = VDI_Limit(nBorderPixelsBottom, 1, 0, MAX_OVERSCAN_BOTTOM);
1.1.1.13  root      301: 
                    302:        /* Store offset to each horizontal line */
                    303:        for (i = 0; i < NUM_VISIBLE_LINES; i++)
                    304:        {
                    305:                STScreenLineOffset[i] = i * SCREENBYTES_LINE;
                    306:        }
1.1.1.7   root      307: }
                    308: 
1.1.1.8   root      309: 
1.1.1.7   root      310: /*-----------------------------------------------------------------------*/
1.1.1.13  root      311: /**
                    312:  * Initialize SDL screen surface / set resolution.
                    313:  */
                    314: static void Screen_SetResolution(void)
1.1.1.11  root      315: {
1.1.1.13  root      316:        int Width, Height, BitCount;
                    317:        unsigned int sdlVideoFlags;
                    318: 
                    319:        Screen_SetSTScreenOffsets();  
1.1.1.11  root      320: 
1.1.1.13  root      321:        /* Determine which resolution to use */
                    322:        if (bUseVDIRes)
                    323:        {
                    324:                Width = VDIWidth;
                    325:                Height = VDIHeight;
                    326:        }
                    327:        else
                    328:        {
                    329:                if (STRes == ST_LOW_RES && !ConfigureParams.Screen.bZoomLowRes)
                    330:                {
                    331:                        Width = 320;
                    332:                        Height = 200;
                    333:                }
                    334:                else    /* else use 640x400 */
                    335:                {
                    336:                        Width = 640;
                    337:                        Height = 400;
                    338:                }
                    339: 
                    340:                /* Adjust width/height for overscan borders, if mono or VDI we have no overscan */
                    341:                if (ConfigureParams.Screen.bAllowOverscan && !bUseHighRes)
                    342:                {
                    343:                        int nZoom = ((Width == 640) ? 2 : 1);
                    344:                        /* Add in overscan borders (if 640x200 bitmap is double on Y) */
                    345:                        Width += (nBorderPixelsLeft+nBorderPixelsRight) * nZoom;
1.1.1.15  root      346:                        Height += (nBorderPixelsTop+nBorderPixelsBottom) * nZoom;
1.1.1.13  root      347:                }
                    348:        }
                    349: 
                    350:        /* Bits per pixel */
1.1.1.14  root      351:        if (STRes == ST_HIGH_RES || bUseVDIRes)
1.1.1.13  root      352:        {
                    353:                BitCount = 8;
                    354:        }
                    355:        else
                    356:        {
                    357:                BitCount = ConfigureParams.Screen.nForceBpp;
                    358:        }
                    359: 
                    360:        /* Set zoom factors, used for scaling mouse motions */
                    361:        if (STRes == ST_LOW_RES && ConfigureParams.Screen.bZoomLowRes && !bUseVDIRes)
                    362:        {
                    363:                nScreenZoomX = 2;
                    364:                nScreenZoomY = 2;
                    365:        }
                    366:        else if (STRes == ST_MEDIUM_RES && !bUseVDIRes)
                    367:        {
                    368:                nScreenZoomX = 1;
                    369:                nScreenZoomY = 2;
                    370:        }
                    371:        else
                    372:        {
                    373:                nScreenZoomX = 1;
                    374:                nScreenZoomY = 1;
                    375:        }
                    376: 
                    377:        /* SDL Video attributes: */
                    378:        if (bInFullScreen)
                    379:        {
                    380:                sdlVideoFlags  = SDL_HWSURFACE|SDL_FULLSCREEN|SDL_HWPALETTE/*|SDL_DOUBLEBUF*/;
                    381:                /* SDL_DOUBLEBUF is a good idea, but the GUI doesn't work with double buffered
                    382:                 * screens yet, so double buffering is currently disabled. */
                    383:        }
                    384:        else
                    385:        {
                    386:                sdlVideoFlags  = SDL_SWSURFACE|SDL_HWPALETTE;
                    387:        }
1.1.1.15  root      388:        Height += Statusbar_SetHeight(Width, Height);
1.1.1.13  root      389: 
                    390:        /* Check if we really have to change the video mode: */
                    391:        if (!sdlscrn || sdlscrn->w != Width || sdlscrn->h != Height
                    392:            || sdlscrn->format->BitsPerPixel != BitCount
                    393:            || (sdlscrn->flags&SDL_FULLSCREEN) != (sdlVideoFlags&SDL_FULLSCREEN))
                    394:        {
1.1.1.15  root      395:                if (bInFullScreen)
                    396:                {
                    397:                        /* unhide the Hatari WM window for fullscreen */
                    398:                        Control_ReparentWindow(Width, Height, bInFullScreen);
                    399:                }
                    400:                
1.1.1.13  root      401:                /* Set new video mode */
                    402:                //fprintf(stderr,"Requesting video mode %i %i %i\n", Width, Height, BitCount);
                    403:                sdlscrn = SDL_SetVideoMode(Width, Height, BitCount, sdlVideoFlags);
                    404:                //fprintf(stderr,"Got video mode %i %i %i\n", sdlscrn->w, sdlscrn->h, sdlscrn->format->BitsPerPixel);
1.1.1.15  root      405: 
                    406:                /* By default ConfigureParams.Screen.nForceBpp and therefore
                    407:                 * BitCount is zero which means "SDL color depth autodetection".
                    408:                 * In this case the SDL_SetVideoMode() call might return
                    409:                 * a 24 bpp resolution
                    410:                 */
1.1.1.13  root      411:                if (sdlscrn && sdlscrn->format->BitsPerPixel == 24)
                    412:                {
                    413:                        fprintf(stderr, "Unsupported color depth 24, trying 32 bpp instead...\n");
                    414:                        sdlscrn = SDL_SetVideoMode(Width, Height, 32, sdlVideoFlags);
                    415:                }
1.1.1.15  root      416: 
1.1.1.13  root      417:                /* Exit if we can not open a screen */
                    418:                if (!sdlscrn)
                    419:                {
                    420:                        fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    421:                        SDL_Quit();
                    422:                        exit(-2);
                    423:                }
                    424: 
1.1.1.15  root      425:                if (!bInFullScreen)
                    426:                {
                    427:                        /* re-embed the new Hatari SDL window */
                    428:                        Control_ReparentWindow(Width, Height, bInFullScreen);
                    429:                }
                    430:                
1.1.1.13  root      431:                /* Re-init screen palette: */
1.1.1.14  root      432:                if (sdlscrn->format->BitsPerPixel == 8)
1.1.1.13  root      433:                        Screen_Handle8BitPalettes();    /* Initialize new 8 bit palette */
                    434:                else
                    435:                        Screen_SetupRGBTable();         /* Create color convertion table */
                    436: 
1.1.1.15  root      437:                Statusbar_Init(sdlscrn);
                    438:                
                    439:                /* screen area without the statusbar */
                    440:                STScreenRect.x = 0;
                    441:                STScreenRect.y = 0;
                    442:                STScreenRect.w = sdlscrn->w;
                    443:                STScreenRect.h = sdlscrn->h - Statusbar_GetHeight();
1.1.1.13  root      444:        }
                    445: 
                    446:        /* Set drawing functions */
                    447:        Screen_SetDrawFunctions(sdlscrn->format->BitsPerPixel);
                    448: 
                    449:        Screen_SetFullUpdate();           /* Cause full update of screen */
1.1.1.11  root      450: }
                    451: 
                    452: 
                    453: /*-----------------------------------------------------------------------*/
1.1.1.13  root      454: /**
                    455:  * Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
                    456:  */
1.1       root      457: void Screen_Init(void)
                    458: {
1.1.1.13  root      459:        int i;
                    460:        SDL_Surface *pIconSurf;
                    461:        char sIconFileName[FILENAME_MAX];
                    462: 
                    463:        /* Clear frame buffer structures and set current pointer */
                    464:        memset(FrameBuffers, 0, NUM_FRAMEBUFFERS * sizeof(FRAMEBUFFER));
                    465: 
                    466:        /* Allocate previous screen check workspace. We are going to double-buffer a double-buffered screen. Oh. */
                    467:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
                    468:        {
                    469:                FrameBuffers[i].pSTScreen = malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
                    470:                FrameBuffers[i].pSTScreenCopy = malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
                    471:                if (!FrameBuffers[i].pSTScreen || !FrameBuffers[i].pSTScreenCopy)
                    472:                {
                    473:                        fprintf(stderr, "Failed to allocate frame buffer memory.\n");
                    474:                        exit(-1);
                    475:                }
                    476:        }
                    477:        pFrameBuffer = &FrameBuffers[0];
                    478: 
                    479:        /* Load and set icon */
                    480:        snprintf(sIconFileName, sizeof(sIconFileName), "%s%chatari-icon.bmp",
                    481:                 Paths_GetDataDir(), PATHSEP);
                    482:        pIconSurf = SDL_LoadBMP(sIconFileName);
                    483:        if (pIconSurf)
                    484:        {
                    485:                SDL_SetColorKey(pIconSurf, SDL_SRCCOLORKEY, SDL_MapRGB(pIconSurf->format, 255, 255, 255));
                    486:                SDL_WM_SetIcon(pIconSurf, NULL);
                    487:                SDL_FreeSurface(pIconSurf);
                    488:        }
                    489: 
                    490:        /* Set initial window resolution */
                    491:        bInFullScreen = ConfigureParams.Screen.bFullScreen;
                    492:        Screen_SetResolution();
                    493: 
1.1.1.17! root      494:        if (bGrabMouse)
        !           495:                SDL_WM_GrabInput(SDL_GRAB_ON);
        !           496: 
1.1.1.13  root      497:        Video_SetScreenRasters();                       /* Set rasters ready for first screen */
                    498: 
                    499:        /* Configure some SDL stuff: */
                    500:        SDL_WM_SetCaption(PROG_NAME, "Hatari");
                    501:        SDL_ShowCursor(SDL_DISABLE);
1.1       root      502: }
                    503: 
1.1.1.2   root      504: 
1.1       root      505: /*-----------------------------------------------------------------------*/
1.1.1.13  root      506: /**
                    507:  * Free screen bitmap and allocated resources
                    508:  */
1.1       root      509: void Screen_UnInit(void)
                    510: {
1.1.1.13  root      511:        int i;
1.1       root      512: 
1.1.1.13  root      513:        /* Free memory used for copies */
                    514:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
                    515:        {
                    516:                free(FrameBuffers[i].pSTScreen);
                    517:                free(FrameBuffers[i].pSTScreenCopy);
                    518:        }
1.1       root      519: }
                    520: 
1.1.1.2   root      521: 
1.1       root      522: /*-----------------------------------------------------------------------*/
1.1.1.13  root      523: /**
                    524:  * Reset screen
                    525:  */
1.1       root      526: void Screen_Reset(void)
                    527: {
1.1.1.13  root      528:        /* On re-boot, always correct ST resolution for monitor, eg Colour/Mono */
                    529:        if (bUseVDIRes)
                    530:        {
                    531:                STRes = VDIRes;
                    532:        }
                    533:        else
                    534:        {
                    535:                if (bUseHighRes)
                    536:                {
                    537:                        STRes = ST_HIGH_RES;
                    538:                        TTRes = TT_HIGH_RES;
                    539:                }
                    540:                else
                    541:                {
                    542:                        STRes = ST_LOW_RES;
                    543:                        TTRes = TT_MEDIUM_RES;
                    544:                }
                    545:        }
                    546:        /* Cause full update */
                    547:        Screen_ModeChanged();
1.1       root      548: }
                    549: 
                    550: 
                    551: /*-----------------------------------------------------------------------*/
1.1.1.13  root      552: /**
                    553:  * Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
                    554:  * next time around
                    555:  */
1.1       root      556: void Screen_SetFullUpdate(void)
                    557: {
1.1.1.13  root      558:        int i;
1.1       root      559: 
1.1.1.13  root      560:        /* Update frame buffers */
                    561:        for (i = 0; i < NUM_FRAMEBUFFERS; i++)
1.1.1.17! root      562:                FrameBuffers[i].bFullUpdate = true;
1.1       root      563: }
                    564: 
1.1.1.5   root      565: 
1.1       root      566: /*-----------------------------------------------------------------------*/
1.1.1.13  root      567: /**
                    568:  * Clear Window display memory
                    569:  */
1.1.1.11  root      570: static void Screen_ClearScreen(void)
                    571: {
1.1.1.15  root      572:        SDL_FillRect(sdlscrn, &STScreenRect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
1.1.1.11  root      573: }
                    574: 
                    575: /*-----------------------------------------------------------------------*/
1.1.1.13  root      576: /**
                    577:  * Enter Full screen mode
                    578:  */
1.1       root      579: void Screen_EnterFullScreen(void)
                    580: {
1.1.1.13  root      581:        if (!bInFullScreen)
                    582:        {
1.1.1.17! root      583:                Main_PauseEmulation(false);         /* Hold things... */
        !           584:                bInFullScreen = true;
1.1.1.2   root      585: 
1.1.1.13  root      586:                if ((ConfigureParams.System.nMachineType == MACHINE_FALCON
                    587:                     || ConfigureParams.System.nMachineType == MACHINE_TT) && !bUseVDIRes)
                    588:                {
                    589:                        HostScreen_toggleFullScreen();
                    590:                }
                    591:                else
                    592:                {
                    593:                        Screen_SetResolution();
                    594:                        Screen_ClearScreen();       /* Black out screen bitmap as will be invalid when return */
                    595:                }
1.1       root      596: 
1.1.1.13  root      597:                SDL_Delay(20);                  /* To give monitor time to change to new resolution */
                    598:                Main_UnPauseEmulation();        /* And off we go... */
1.1.1.2   root      599: 
1.1.1.13  root      600:                SDL_WM_GrabInput(SDL_GRAB_ON);  /* Grab mouse pointer in fullscreen */
                    601:        }
1.1       root      602: }
                    603: 
1.1.1.2   root      604: 
1.1       root      605: /*-----------------------------------------------------------------------*/
1.1.1.13  root      606: /**
                    607:  * Return from Full screen mode back to a window
                    608:  */
1.1       root      609: void Screen_ReturnFromFullScreen(void)
                    610: {
1.1.1.13  root      611:        if (bInFullScreen)
                    612:        {
1.1.1.17! root      613:                Main_PauseEmulation(false);        /* Hold things... */
        !           614:                bInFullScreen = false;
1.1.1.13  root      615: 
                    616:                if ((ConfigureParams.System.nMachineType == MACHINE_FALCON
                    617:                     || ConfigureParams.System.nMachineType == MACHINE_TT) && !bUseVDIRes)
                    618:                {
                    619:                        HostScreen_toggleFullScreen();
                    620:                }
                    621:                else
                    622:                {
                    623:                        Screen_SetResolution();
                    624:                }
                    625:                SDL_Delay(20);                /* To give monitor time to switch resolution */
                    626:                Main_UnPauseEmulation();      /* And off we go... */
1.1.1.17! root      627: 
        !           628:                if (!bGrabMouse)
        !           629:                        /* Un-grab mouse pointer in windowed mode */
        !           630:                        SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1.1.13  root      631:        }
                    632: }
1.1.1.2   root      633: 
                    634: 
1.1.1.13  root      635: /*-----------------------------------------------------------------------*/
                    636: /**
                    637:  * Have we changed between low/med/high res?
                    638:  */
                    639: static void Screen_DidResolutionChange(int new_res)
                    640: {
                    641:        if (new_res != STRes)
                    642:        {
                    643:                STRes = new_res;
                    644:                Screen_ModeChanged();
                    645:        }
                    646:        else
                    647:        {
                    648:                /* Did change overscan mode? Causes full update */
                    649:                if (pFrameBuffer->OverscanModeCopy != OverscanMode)
1.1.1.17! root      650:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root      651:        }
1.1       root      652: }
                    653: 
1.1.1.5   root      654: 
1.1.1.2   root      655: /*-----------------------------------------------------------------------*/
1.1.1.13  root      656: /**
                    657:  * Force things associated with changing between low/medium/high res.
                    658:  */
                    659: void Screen_ModeChanged(void)
1.1       root      660: {
1.1.1.13  root      661:        if (!sdlscrn)
                    662:        {
                    663:                /* screen not yet initialized */
                    664:                return;
                    665:        }
                    666:        /* Don't run this function if Videl emulation is running! */
                    667:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON && !bUseVDIRes)
                    668:        {
                    669:                VIDEL_ZoomModeChanged();
                    670:        }
                    671:        else if (ConfigureParams.System.nMachineType == MACHINE_TT && !bUseVDIRes)
                    672:        {
                    673:                int width, height, bpp;
                    674:                Video_GetTTRes(&width, &height, &bpp);
                    675:                HostScreen_setWindowSize(width, height, 8);
                    676:        }
1.1.1.17! root      677:        else
        !           678:        {
        !           679:                /* Set new display mode, if differs from current */
        !           680:                Screen_SetResolution();
        !           681:                Screen_SetFullUpdate();
        !           682:        }
        !           683:        if (bInFullScreen || bGrabMouse)
        !           684:                SDL_WM_GrabInput(SDL_GRAB_ON);
        !           685:        else
        !           686:                SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1       root      687: }
                    688: 
1.1.1.2   root      689: 
                    690: /*-----------------------------------------------------------------------*/
1.1.1.13  root      691: /**
                    692:  * Compare current resolution on line with previous, and set 'UpdateLine' accordingly
                    693:  * Return if swap between low/medium resolution
                    694:  */
1.1.1.15  root      695: static bool Screen_CompareResolution(int y, int *pUpdateLine, int oldres)
1.1       root      696: {
1.1.1.13  root      697:        /* Check if wrote to resolution register */
                    698:        if (HBLPaletteMasks[y]&PALETTEMASK_RESOLUTION)  /* See 'Intercept_ShifterMode_WriteByte' */
                    699:        {
                    700:                int newres = (HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT;
                    701:                /* Did resolution change? */
                    702:                if (newres != (int)((pFrameBuffer->HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT))
                    703:                        *pUpdateLine |= PALETTEMASK_UPDATERES;
                    704:                else
                    705:                        *pUpdateLine &= ~PALETTEMASK_UPDATERES;
                    706:                /* Have used any low/medium res mix? */
                    707:                return (newres != (oldres&ST_MEDIUM_RES_BIT));
                    708:        }
1.1.1.17! root      709:        return false;
1.1       root      710: }
                    711: 
1.1.1.7   root      712: 
1.1.1.2   root      713: /*-----------------------------------------------------------------------*/
1.1.1.13  root      714: /**
                    715:  * Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
                    716:  */
1.1.1.8   root      717: static void Screen_ComparePalette(int y, int *pUpdateLine)
1.1       root      718: {
1.1.1.17! root      719:        bool bPaletteChanged = false;
1.1.1.13  root      720:        int i;
1.1       root      721: 
1.1.1.13  root      722:        /* Did write to palette in this or previous frame? */
                    723:        if (((HBLPaletteMasks[y]|pFrameBuffer->HBLPaletteMasks[y])&PALETTEMASK_PALETTE)!=0)
                    724:        {
                    725:                /* Check and update ones which changed */
                    726:                for (i = 0; i < 16; i++)
                    727:                {
                    728:                        if (HBLPaletteMasks[y]&(1<<i))        /* Update changes in ST palette */
                    729:                                HBLPalette[i] = HBLPalettes[(y*16)+i];
                    730:                }
                    731:                /* Now check with same palette from previous frame for any differences(may be changing palette back) */
                    732:                for (i = 0; (i < 16) && (!bPaletteChanged); i++)
                    733:                {
                    734:                        if (HBLPalette[i]!=pFrameBuffer->HBLPalettes[(y*16)+i])
1.1.1.17! root      735:                                bPaletteChanged = true;
1.1.1.13  root      736:                }
                    737:                if (bPaletteChanged)
                    738:                        *pUpdateLine |= PALETTEMASK_UPDATEPAL;
                    739:                else
                    740:                        *pUpdateLine &= ~PALETTEMASK_UPDATEPAL;
                    741:        }
1.1       root      742: }
                    743: 
1.1.1.7   root      744: 
1.1.1.2   root      745: /*-----------------------------------------------------------------------*/
1.1.1.13  root      746: /**
                    747:  * Check for differences in Palette and Resolution from Mask table and update
                    748:  * and store off which lines need updating and create full-screen palette.
                    749:  * (It is very important for these routines to check for colour changes with
                    750:  * the previous screen so only the very minimum parts are updated).
                    751:  * Return new STRes value.
                    752:  */
                    753: static int Screen_ComparePaletteMask(int res)
1.1       root      754: {
1.1.1.17! root      755:        bool bLowMedMix = false;
1.1.1.13  root      756:        int LineUpdate = 0;
                    757:        int y;
                    758: 
                    759:        /* Set for monochrome? */
                    760:        if (bUseHighRes)
                    761:        {
                    762:                OverscanMode = OVERSCANMODE_NONE;
                    763: 
                    764:                /* Just copy mono colours, 0x777 checked also in convert/vdi2.c */
                    765:                if (HBLPalettes[0] & 0x777)
                    766:                {
                    767:                        HBLPalettes[0] = 0x777;
                    768:                        HBLPalettes[1] = 0x000;
                    769:                }
                    770:                else
                    771:                {
                    772:                        HBLPalettes[0] = 0x000;
                    773:                        HBLPalettes[1] = 0x777;
                    774:                }
                    775: 
                    776:                /* Colors changed? */
                    777:                if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17! root      778:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root      779: 
                    780:                /* Set bit to flag 'full update' */
                    781:                if (pFrameBuffer->bFullUpdate)
                    782:                        ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
                    783:                else
                    784:                        ScrUpdateFlag = 0x00000000;
                    785:        }
                    786: 
                    787:        /* Use VDI resolution? */
                    788:        if (bUseVDIRes)
                    789:        {
                    790:                /* Force to VDI resolution screen, without overscan */
                    791:                res = VDIRes;
                    792: 
                    793:                /* Colors changed? */
                    794:                if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17! root      795:                        pFrameBuffer->bFullUpdate = true;
1.1.1.13  root      796: 
                    797:                /* Set bit to flag 'full update' */
                    798:                if (pFrameBuffer->bFullUpdate)
                    799:                        ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
                    800:                else
                    801:                        ScrUpdateFlag = 0x00000000;
                    802:        }
                    803:        /* Are in Mono? Force to monochrome and no overscan */
                    804:        else if (bUseHighRes)
                    805:        {
                    806:                /* Force to standard hi-resolution screen, without overscan */
                    807:                res = ST_HIGH_RES;
                    808:        }
                    809:        else    /* Full colour */
                    810:        {
                    811:                /* Get resolution */
                    812:                //res = (HBLPaletteMasks[0]>>16)&ST_RES_MASK;
                    813:                /* [NP] keep only low/med bit (could be hires in case of overscan on the 1st line) */
                    814:                res = (HBLPaletteMasks[0]>>16)&ST_MEDIUM_RES_BIT;
                    815: 
                    816:                /* Do all lines - first is tagged as full-update */
                    817:                for (y = 0; y < NUM_VISIBLE_LINES; y++)
                    818:                {
                    819:                        /* Find any resolution/palette change and update palette/mask buffer */
                    820:                        /* ( LineUpdate has top two bits set to say if line needs updating due to palette or resolution change ) */
                    821:                        bLowMedMix |= Screen_CompareResolution(y, &LineUpdate, res);
                    822:                        Screen_ComparePalette(y,&LineUpdate);
                    823:                        HBLPaletteMasks[y] = (HBLPaletteMasks[y]&(~PALETTEMASK_UPDATEMASK)) | LineUpdate;
                    824:                        /* Copy palette and mask for next frame */
                    825:                        memcpy(&pFrameBuffer->HBLPalettes[y*16],HBLPalette,sizeof(short int)*16);
                    826:                        pFrameBuffer->HBLPaletteMasks[y] = HBLPaletteMasks[y];
                    827:                }
                    828:                /* Did mix/have medium resolution? */
                    829:                if (bLowMedMix || (res & ST_MEDIUM_RES_BIT))
                    830:                        res = ST_MEDIUM_RES;
                    831:        }
                    832: 
                    833:        return res;
                    834: }
                    835: 
                    836: 
                    837: /*-----------------------------------------------------------------------*/
                    838: /**
                    839:  * Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
                    840:  * or when going between a Window and full-screen display
                    841:  */
1.1.1.8   root      842: static void Screen_SetFullUpdateMask(void)
1.1       root      843: {
1.1.1.13  root      844:        int y;
1.1       root      845: 
1.1.1.13  root      846:        for (y = 0; y < NUM_VISIBLE_LINES; y++)
                    847:                HBLPaletteMasks[y] |= PALETTEMASK_UPDATEFULL;
1.1       root      848: }
                    849: 
1.1.1.7   root      850: 
1.1.1.2   root      851: /*-----------------------------------------------------------------------*/
1.1.1.13  root      852: /**
                    853:  * Set details for ST screen conversion.
                    854:  */
1.1.1.10  root      855: static void Screen_SetConvertDetails(void)
1.1       root      856: {
1.1.1.13  root      857:        pSTScreen = pFrameBuffer->pSTScreen;          /* Source in ST memory */
                    858:        pSTScreenCopy = pFrameBuffer->pSTScreenCopy;  /* Previous ST screen */
                    859:        pPCScreenDest = sdlscrn->pixels;              /* Destination PC screen */
                    860: 
                    861:        PCScreenBytesPerLine = sdlscrn->pitch;        /* Bytes per line */
                    862:        pHBLPalettes = pFrameBuffer->HBLPalettes;     /* HBL palettes pointer */
                    863:        /* Not in TV-Mode? Then double up on Y: */
1.1.1.15  root      864:        bScrDoubleY = !(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_TV);
1.1.1.13  root      865: 
                    866:        if (bUseVDIRes)
                    867:        {
                    868:                /* Select screen draw for standard or VDI display */
                    869:                STScreenLeftSkipBytes = 0;
                    870:                STScreenWidthBytes = VDIWidth * VDIPlanes / 8;
                    871:                STScreenStartHorizLine = 0;
                    872:                STScreenEndHorizLine = VDIHeight;
                    873:        }
                    874:        else
                    875:        {
                    876:                if (ConfigureParams.Screen.bAllowOverscan)  /* Use borders? */
                    877:                {
                    878:                        /* Always draw to WHOLE screen including ALL borders */
                    879:                        STScreenLeftSkipBytes = 0;              /* Number of bytes to skip on ST screen for left (border) */
                    880: 
                    881:                        if (bUseHighRes)
                    882:                        {
                    883:                                pFrameBuffer->OverscanModeCopy = OverscanMode = OVERSCANMODE_NONE;
1.1.1.15  root      884:                                STScreenStartHorizLine = 0;
1.1.1.13  root      885:                                STScreenEndHorizLine = 400;
                    886:                        }
                    887:                        else
                    888:                        {
                    889:                                STScreenWidthBytes = SCREENBYTES_LINE;  /* Number of horizontal bytes in our ST screen */
1.1.1.15  root      890:                                STScreenStartHorizLine = OVERSCAN_TOP - nBorderPixelsTop;
                    891:                                STScreenEndHorizLine = OVERSCAN_TOP + 200 + nBorderPixelsBottom;
1.1.1.13  root      892:                        }
                    893:                }
                    894:                else
                    895:                {
                    896:                        /* Only draw main area and centre on Y */
                    897:                        STScreenLeftSkipBytes = SCREENBYTES_LEFT;
                    898:                        STScreenWidthBytes = SCREENBYTES_MIDDLE;
                    899:                        STScreenStartHorizLine = OVERSCAN_TOP;
                    900:                        STScreenEndHorizLine = OVERSCAN_TOP + (bUseHighRes ? 400 : 200);
                    901:                }
                    902:        }
1.1       root      903: }
                    904: 
1.1.1.2   root      905: 
                    906: /*-----------------------------------------------------------------------*/
1.1.1.13  root      907: /**
                    908:  * Lock full-screen for drawing
                    909:  */
1.1.1.15  root      910: static bool Screen_Lock(void)
1.1       root      911: {
1.1.1.13  root      912:        if (SDL_MUSTLOCK(sdlscrn))
                    913:        {
                    914:                if (SDL_LockSurface(sdlscrn))
                    915:                {
                    916:                        Screen_ReturnFromFullScreen();   /* All OK? If not need to jump back to a window */
1.1.1.17! root      917:                        return false;
1.1.1.13  root      918:                }
                    919:        }
1.1.1.2   root      920: 
1.1.1.17! root      921:        return true;
1.1       root      922: }
                    923: 
1.1.1.2   root      924: /*-----------------------------------------------------------------------*/
1.1.1.13  root      925: /**
                    926:  * UnLock full-screen
                    927:  */
1.1.1.8   root      928: static void Screen_UnLock(void)
1.1       root      929: {
1.1.1.13  root      930:        if ( SDL_MUSTLOCK(sdlscrn) )
                    931:                SDL_UnlockSurface(sdlscrn);
1.1       root      932: }
                    933: 
1.1.1.2   root      934: 
                    935: /*-----------------------------------------------------------------------*/
1.1.1.13  root      936: /**
                    937:  * Swap ST Buffers, used for full-screen where have double-buffering
                    938:  */
1.1.1.11  root      939: static void Screen_SwapSTBuffers(void)
                    940: {
                    941: #if NUM_FRAMEBUFFERS > 1
1.1.1.13  root      942:        if (sdlscrn->flags & SDL_DOUBLEBUF)
                    943:        {
                    944:                if (pFrameBuffer==&FrameBuffers[0])
                    945:                        pFrameBuffer = &FrameBuffers[1];
                    946:                else
                    947:                        pFrameBuffer = &FrameBuffers[0];
                    948:        }
1.1.1.11  root      949: #endif
                    950: }
                    951: 
                    952: 
                    953: /*-----------------------------------------------------------------------*/
1.1.1.13  root      954: /**
                    955:  * Blit our converted ST screen to window/full-screen
                    956:  */
1.1.1.15  root      957: static void Screen_Blit(void)
1.1       root      958: {
1.1.1.13  root      959:        unsigned char *pTmpScreen;
                    960: 
                    961:        /* Blit to full screen or window? */
                    962:        if (bInFullScreen)
                    963:        {
                    964:                Screen_SwapSTBuffers();
                    965:                /* Swap screen */
1.1.1.15  root      966:                SDL_Flip(sdlscrn);
1.1.1.13  root      967:        }
                    968:        else
                    969:        {
1.1.1.15  root      970:                SDL_UpdateRects(sdlscrn, 1, &STScreenRect);
1.1.1.13  root      971:        }
                    972: 
                    973:        /* Swap copy/raster buffers in screen. */
                    974:        pTmpScreen = pFrameBuffer->pSTScreenCopy;
                    975:        pFrameBuffer->pSTScreenCopy = pFrameBuffer->pSTScreen;
                    976:        pFrameBuffer->pSTScreen = pTmpScreen;
1.1       root      977: }
                    978: 
1.1.1.3   root      979: 
1.1.1.2   root      980: /*-----------------------------------------------------------------------*/
1.1.1.13  root      981: /**
                    982:  * Draw ST screen to window/full-screen framebuffer
1.1.1.15  root      983:  * @param  bForceFlip  Force screen update, even if contents did not change
1.1.1.17! root      984:  * @return  true if screen contents changed
1.1.1.13  root      985:  */
1.1.1.15  root      986: static bool Screen_DrawFrame(bool bForceFlip)
1.1       root      987: {
1.1.1.13  root      988:        int new_res;
                    989:        void (*pDrawFunction)(void);
1.1.1.17! root      990:        static bool bPrevFrameWasSpec512 = false;
1.1.1.13  root      991: 
                    992:        /* Scan palette/resolution masks for each line and build up palette/difference tables */
                    993:        new_res = Screen_ComparePaletteMask(STRes);
                    994:        /* Do require palette? Check if changed and update */
                    995:        Screen_Handle8BitPalettes();
                    996:        /* Did we change resolution this frame - allocate new screen if did so */
                    997:        Screen_DidResolutionChange(new_res);
                    998:        /* Is need full-update, tag as such */
                    999:        if (pFrameBuffer->bFullUpdate)
                   1000:                Screen_SetFullUpdateMask();
                   1001: 
1.1.1.15  root     1002:        /* restore area potentially left under overlay led
                   1003:         * and saved by Statusbar_OverlayBackup()
                   1004:         */
                   1005:        Statusbar_OverlayRestore(sdlscrn);
                   1006:        
1.1.1.13  root     1007:        /* Lock screen ready for drawing */
                   1008:        if (Screen_Lock())
                   1009:        {
1.1.1.17! root     1010:                bScreenContentsChanged = false;      /* Did change (ie needs blit?) */
1.1.1.15  root     1011: 
1.1.1.13  root     1012:                /* Set details */
                   1013:                Screen_SetConvertDetails();
1.1.1.15  root     1014:                
1.1.1.13  root     1015:                /* Clear screen on full update to clear out borders and also interleaved lines */
                   1016:                if (pFrameBuffer->bFullUpdate && !bUseVDIRes)
                   1017:                        Screen_ClearScreen();
1.1.1.15  root     1018:                
1.1.1.13  root     1019:                /* Call drawing for full-screen */
                   1020:                if (bUseVDIRes)
                   1021:                {
                   1022:                        pDrawFunction = ScreenDrawFunctionsVDI[VDIRes];
                   1023:                }
                   1024:                else
                   1025:                {
                   1026:                        pDrawFunction = ScreenDrawFunctionsNormal[STRes];
                   1027:                        /* Check if is Spec512 image */
                   1028:                        if (Spec512_IsImage())
                   1029:                        {
1.1.1.17! root     1030:                                bPrevFrameWasSpec512 = true;
1.1.1.13  root     1031:                                /* What mode were we in? Keep to 320xH or 640xH */
                   1032:                                if (pDrawFunction==ConvertLowRes_320x16Bit)
                   1033:                                        pDrawFunction = ConvertSpec512_320x16Bit;
                   1034:                                else if (pDrawFunction==ConvertLowRes_640x16Bit)
                   1035:                                        pDrawFunction = ConvertSpec512_640x16Bit;
                   1036:                                else if (pDrawFunction==ConvertLowRes_320x32Bit)
                   1037:                                        pDrawFunction = ConvertSpec512_320x32Bit;
                   1038:                                else if (pDrawFunction==ConvertLowRes_640x32Bit)
                   1039:                                        pDrawFunction = ConvertSpec512_640x32Bit;
                   1040:                        }
                   1041:                        else if (bPrevFrameWasSpec512)
                   1042:                        {
                   1043:                                /* If we switch back from Spec512 mode to normal
                   1044:                                 * screen rendering, we have to make sure to do
                   1045:                                 * a full update of the screen. */
                   1046:                                Screen_SetFullUpdateMask();
1.1.1.17! root     1047:                                bPrevFrameWasSpec512 = false;
1.1.1.13  root     1048:                        }
                   1049:                }
                   1050: 
                   1051:                if (pDrawFunction)
1.1.1.15  root     1052:                        CALL_VAR(pDrawFunction);
                   1053: 
                   1054:                /* Unlock screen */
                   1055:                Screen_UnLock();
1.1.1.13  root     1056: 
1.1.1.15  root     1057:                /* draw statusbar or overlay led(s) after unlock */
                   1058:                Statusbar_OverlayBackup(sdlscrn);
                   1059:                Statusbar_Update(sdlscrn);
                   1060:                
1.1.1.13  root     1061:                /* Clear flags, remember type of overscan as if change need screen full update */
1.1.1.17! root     1062:                pFrameBuffer->bFullUpdate = false;
1.1.1.13  root     1063:                pFrameBuffer->OverscanModeCopy = OverscanMode;
                   1064: 
                   1065:                /* And show to user */
                   1066:                if (bScreenContentsChanged || bForceFlip)
1.1.1.15  root     1067:                {
                   1068:                        Screen_Blit();
                   1069:                }
1.1.1.13  root     1070: 
1.1.1.15  root     1071:                return bScreenContentsChanged;
1.1.1.13  root     1072:        }
1.1.1.15  root     1073: 
                   1074:        return false;
1.1       root     1075: }
                   1076: 
1.1.1.9   root     1077: 
1.1.1.2   root     1078: /*-----------------------------------------------------------------------*/
1.1.1.13  root     1079: /**
                   1080:  * Draw ST screen to window/full-screen
                   1081:  */
1.1.1.15  root     1082: bool Screen_Draw(void)
1.1       root     1083: {
1.1.1.13  root     1084:        if (!bQuitProgram && VideoBase)
                   1085:        {
                   1086:                /* And draw (if screen contents changed) */
1.1.1.15  root     1087:                return Screen_DrawFrame(false);
1.1.1.13  root     1088:        }
1.1.1.15  root     1089: 
                   1090:        return false;
1.1       root     1091: }
1.1.1.11  root     1092: 
                   1093: 
                   1094: /* -------------- screen conversion routines --------------------------------
                   1095:   Screen conversion routines. We have a number of routines to convert ST screen
                   1096:   to PC format. We split these into Low, Medium and High each with 8/16-bit
                   1097:   versions. To gain extra speed, as almost half of the processing time can be
                   1098:   spent in these routines, we check for any changes from the previously
                   1099:   displayed frame. AdjustLinePaletteRemap() sets a flag to tell the routines
                   1100:   if we need to totally update a line (ie full update, or palette/res change)
                   1101:   or if we just can do a difference check.
                   1102:   We convert each screen 16 pixels at a time by use of a couple of look-up
                   1103:   tables. These tables convert from 2-plane format to bbp and then we can add
                   1104:   two of these together to get 4-planes. This keeps the tables small and thus
                   1105:   improves speed. We then look these bbp values up as an RGB/Index value to
                   1106:   copy to the screen.
                   1107: */
                   1108: 
                   1109: 
1.1.1.13  root     1110: /*-----------------------------------------------------------------------*/
                   1111: /**
1.1.1.11  root     1112:  * Update the STRGBPalette[] array with current colours for this raster line.
                   1113:  *
                   1114:  * Return 'ScrUpdateFlag', 0x80000000=Full update, 0x40000000=Update
                   1115:  * as palette changed
                   1116:  */
                   1117: static int AdjustLinePaletteRemap(int y)
                   1118: {
                   1119: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root     1120:        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     1121: #endif
1.1.1.13  root     1122:        Uint16 *actHBLPal;
                   1123:        int i;
1.1.1.11  root     1124: 
1.1.1.13  root     1125:        /* Copy palette and convert to RGB in display format */
                   1126:        actHBLPal = pHBLPalettes + (y<<4);    /* offset in palette */
                   1127:        for (i=0; i<16; i++)
                   1128:        {
1.1.1.11  root     1129: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13  root     1130:                STRGBPalette[endiantable[i]] = ST2RGB[*actHBLPal++];
1.1.1.11  root     1131: #else
1.1.1.13  root     1132:                STRGBPalette[i] = ST2RGB[*actHBLPal++];
1.1.1.11  root     1133: #endif
1.1.1.13  root     1134:        }
                   1135:        ScrUpdateFlag = HBLPaletteMasks[y];
                   1136:        return ScrUpdateFlag;
1.1.1.11  root     1137: }
                   1138: 
                   1139: 
1.1.1.13  root     1140: /*-----------------------------------------------------------------------*/
                   1141: /**
1.1.1.11  root     1142:  * Run updates to palette(STRGBPalette[]) until get to screen line
                   1143:  * we are to convert from
                   1144:  */
                   1145: static void Convert_StartFrame(void)
                   1146: {
1.1.1.13  root     1147:        int y = 0;
                   1148:        /* Get #lines before conversion starts */
                   1149:        int lines = STScreenStartHorizLine;
                   1150:        while (lines--)
                   1151:                AdjustLinePaletteRemap(y++);     /* Update palette */
1.1.1.11  root     1152: }
                   1153: 
                   1154: /* lookup tables and conversion macros */
                   1155: #include "convert/macros.h"
                   1156: 
                   1157: /* Conversion routines */
1.1.1.13  root     1158: 
                   1159: #include "convert/low320x8.c"     /* LowRes To 320xH x 8-bit color */
                   1160: #include "convert/low640x8.c"     /* LowRes To 640xH x 8-bit color */
                   1161: #include "convert/med640x8.c"     /* MediumRes To 640xH x 8-bit color */
                   1162: #include "convert/high640x8.c"    /* HighRes To 640xH x 8-bit color */
                   1163: 
                   1164: #include "convert/low320x16.c"    /* LowRes To 320xH x 16-bit color */
                   1165: #include "convert/low640x16.c"    /* LowRes To 640xH x 16-bit color */
                   1166: #include "convert/med640x16.c"    /* MediumRes To 640xH x 16-bit color */
                   1167: #include "convert/spec320x16.c"   /* Spectrum 512 To 320xH x 16-bit color */
                   1168: #include "convert/spec640x16.c"   /* Spectrum 512 To 640xH x 16-bit color */
                   1169: 
                   1170: #include "convert/low320x32.c"    /* LowRes To 320xH x 32-bit color */
                   1171: #include "convert/low640x32.c"    /* LowRes To 640xH x 32-bit color */
                   1172: #include "convert/med640x32.c"    /* MediumRes To 640xH x 32-bit color */
                   1173: #include "convert/spec320x32.c"   /* Spectrum 512 To 320xH x 32-bit color */
                   1174: #include "convert/spec640x32.c"   /* Spectrum 512 To 640xH x 32-bit color */
                   1175: 
                   1176: #include "convert/vdi16.c"        /* VDI x 16 color */
                   1177: #include "convert/vdi4.c"         /* VDI x 4 color */
                   1178: #include "convert/vdi2.c"         /* VDI x 2 color */

unix.superglobalmegacorp.com

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