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

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

unix.superglobalmegacorp.com

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