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

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

unix.superglobalmegacorp.com

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