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

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

unix.superglobalmegacorp.com

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