|
|
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.