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

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

unix.superglobalmegacorp.com

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