|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.