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

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