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

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

unix.superglobalmegacorp.com

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