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

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

unix.superglobalmegacorp.com

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