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

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

unix.superglobalmegacorp.com

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