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

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

unix.superglobalmegacorp.com

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