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