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

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