Annotation of hatari/src/screen.c, revision 1.1.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.