|
|
1.1 root 1: /*
2: Hatari - screen.c
3:
4: This file is distributed under the GNU Public License, version 2 or at your
5: option any later version. Read the file gpl.txt for details.
6:
7: */
8:
9: const char Screen_fileid[] = "Hatari screen.c : " __DATE__ " " __TIME__;
10:
11: #include <SDL.h>
12: #include <SDL_endian.h>
13:
14: #include "main.h"
15: #include "configuration.h"
16: #include "log.h"
17: #include "m68000.h"
18: #include "paths.h"
19: #include "screen.h"
20: #include "control.h"
21: #include "convert/routines.h"
22: #include "resolution.h"
23: #include "statusbar.h"
24: #include "video.h"
25:
26:
27: /* extern for several purposes */
28: SDL_Surface *sdlscrn = NULL; /* The SDL screen surface */
29: int nScreenZoomX, nScreenZoomY; /* Zooming factors, used for scaling mouse motions */
30: int nBorderPixelsLeft, nBorderPixelsRight; /* Pixels in left and right border */
31: int nBorderPixelsTop, nBorderPixelsBottom; /* Lines in top and bottom border */
32:
33: /* extern for shortcuts and falcon/hostscreen.c */
34: bool bGrabMouse = false; /* Grab the mouse cursor in the window */
35: bool bInFullScreen = false; /* true if in full screen */
36:
37:
38: /* extern for video.c */
39: Uint8 pNEXTScreen[(1120*832)*2];
40: FRAMEBUFFER *pFrameBuffer; /* Pointer into current 'FrameBuffer' */
41:
42: static FRAMEBUFFER FrameBuffers[NUM_FRAMEBUFFERS]; /* Store frame buffer details to tell how to update */
43: static Uint8 *pNEXTScreenCopy; /* Keep track of current and previous ST screen data */
44: static Uint8 *pPCScreenDest; /* Destination PC buffer */
45: static int NEXTScreenEndHorizLine; /* End lines to be converted */
46: static int PCScreenBytesPerLine;
47: static int NEXTScreenWidthBytes;
48: static SDL_Rect NEXTScreenRect; /* screen size without statusbar */
49:
50: static int NEXTScreenLineOffset[910]; /* Offsets for ST screen lines eg, 0,160,320... */
51:
52: static void (*ScreenDrawFunctionsNormal[3])(void); /* Screen draw functions */
53:
54: static bool bScreenContentsChanged; /* true if buffer changed and requires blitting */
55: static bool bScrDoubleY; /* true if double on Y */
56: static int ScrUpdateFlag; /* Bit mask of how to update screen */
57:
58:
59: static bool Screen_DrawFrame(bool bForceFlip);
60:
61:
62: /*-----------------------------------------------------------------------*/
63: /**
64: * Create ST 0x777 / STe 0xfff color format to 16 or 32 bits per pixel
65: * conversion table. Called each time when changed resolution or to/from
66: * fullscreen mode.
67: */
68: static void Screen_SetupRGBTable(void)
69: {
70: }
71:
72: SDL_Color sdlColors[16];
73: Uint32 colors[32];
74:
75: /*-----------------------------------------------------------------------*/
76: /**
77: * Create new palette for display.
78: */
79: static void Screen_CreatePalette(void)
80: {
81:
82: sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 255;
83: sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 160;
84: sdlColors[2].r = sdlColors[2].g = sdlColors[2].b = 80;
85: sdlColors[3].r = sdlColors[3].g = sdlColors[3].b = 0;
86: }
87:
88:
89: /*-----------------------------------------------------------------------*/
90: /**
91: * Create 8-Bit palette for display if needed.
92: */
93: static void Screen_Handle8BitPalettes(void)
94: {
95: }
96:
97:
98: /*-----------------------------------------------------------------------*/
99: /**
100: * Set screen draw functions.
101: */
102: static void Screen_SetDrawFunctions(int nBitCount, bool bDoubleLowRes)
103: {
104: ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
105: }
106:
107:
108: /*-----------------------------------------------------------------------*/
109: /**
110: * Set amount of border pixels
111: */
112: static void Screen_SetBorderPixels(int leftX, int leftY)
113: {
114: }
115:
116: /*-----------------------------------------------------------------------*/
117: /**
118: * store Y offset for each horizontal line in our source ST screen for
119: * reference in the convert functions.
120: */
121: static void Screen_SetSTScreenOffsets(void)
122: {
123: }
124:
125:
126: /*-----------------------------------------------------------------------*/
127: /**
128: * Initialize SDL screen surface / set resolution.
129: */
130: static void Screen_SetResolution(void)
131: {
132: int Width, Height, nZoom, SBarHeight, BitCount, maxW, maxH;
133: Uint32 sdlVideoFlags;
134: bool bDoubleLowRes = false;
135:
136: BitCount = 8;
137:
138: nBorderPixelsTop = nBorderPixelsBottom = 0;
139: nBorderPixelsLeft = nBorderPixelsRight = 0;
140:
141: nScreenZoomX = 1;
142: nScreenZoomY = 1;
143:
144: Width = 1120;
145: Height = 832;
146: nZoom = 1;
147:
148: /* Statusbar height for doubled screen size */
149: SBarHeight = Statusbar_GetHeightForSize(1120, 832);
150: Resolution_GetLimits(&maxW, &maxH, &BitCount);
151:
152:
153: Screen_SetSTScreenOffsets();
154: Height += Statusbar_SetHeight(Width, Height);
155:
156: /* SDL Video attributes: */
157: if (bInFullScreen)
158: {
159: sdlVideoFlags = SDL_HWSURFACE|SDL_FULLSCREEN|SDL_HWPALETTE/*|SDL_DOUBLEBUF*/;
160: /* SDL_DOUBLEBUF helps avoiding tearing and can be faster on suitable HW,
161: * but it doesn't work with partial screen updates done by the ST screen
162: * update code or the Hatari GUI, so double buffering is disabled.
163: */
164: }
165: else
166: {
167: sdlVideoFlags = SDL_SWSURFACE|SDL_HWPALETTE;
168: }
169:
170: /* Check if we really have to change the video mode: */
171: if (!sdlscrn || sdlscrn->w != Width || sdlscrn->h != Height
172: || (BitCount && sdlscrn->format->BitsPerPixel != BitCount)
173: || (sdlscrn->flags&SDL_FULLSCREEN) != (sdlVideoFlags&SDL_FULLSCREEN))
174: {
175: #ifdef _MUDFLAP
176: if (sdlscrn) {
177: __mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS);
178: }
179: #endif
180: if (bInFullScreen)
181: {
182: /* unhide the Hatari WM window for fullscreen */
183: Control_ReparentWindow(Width, Height, bInFullScreen);
184: }
185:
186: /* Set new video mode */
187: //fprintf(stderr,"Requesting video mode %i %i %i\n", Width, Height, BitCount);
188: sdlscrn = SDL_SetVideoMode(Width, Height, BitCount, sdlVideoFlags);
189: //fprintf(stderr,"Got video mode %i %i %i\n", sdlscrn->w, sdlscrn->h, sdlscrn->format->BitsPerPixel);
190:
191: /* By default ConfigureParams.Screen.nForceBpp and therefore
192: * BitCount is zero which means "SDL color depth autodetection".
193: * In this case the SDL_SetVideoMode() call might return
194: * a 24 bpp resolution
195: */
196: if (sdlscrn && sdlscrn->format->BitsPerPixel == 24)
197: {
198: fprintf(stderr, "Unsupported color depth 24, trying 32 bpp instead...\n");
199: sdlscrn = SDL_SetVideoMode(Width, Height, 32, sdlVideoFlags);
200: }
201:
202: /* Exit if we can not open a screen */
203: if (!sdlscrn)
204: {
205: fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
206: SDL_Quit();
207: exit(-2);
208: }
209: #ifdef _MUDFLAP
210: __mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels");
211: #endif
212:
213: if (!bInFullScreen)
214: {
215: /* re-embed the new Hatari SDL window */
216: Control_ReparentWindow(Width, Height, bInFullScreen);
217: }
218:
219: /* Re-init screen palette: */
220: if (sdlscrn->format->BitsPerPixel == 8)
221: Screen_Handle8BitPalettes(); /* Initialize new 8 bit palette */
222: else
223: Screen_SetupRGBTable(); /* Create color convertion table */
224:
225: Statusbar_Init(sdlscrn);
226:
227: /* screen area without the statusbar */
228: NEXTScreenRect.x = 0;
229: NEXTScreenRect.y = 0;
230: NEXTScreenRect.w = sdlscrn->w;
231: NEXTScreenRect.h = sdlscrn->h - Statusbar_GetHeight();
232: }
233:
234: /* Set drawing functions */
235: Screen_SetDrawFunctions(sdlscrn->format->BitsPerPixel, bDoubleLowRes);
236:
237: Screen_SetFullUpdate(); /* Cause full update of screen */
238: }
239:
240:
241: /*-----------------------------------------------------------------------*/
242: /**
243: * Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
244: */
245: void Screen_Init(void)
246: {
247: int i;
248: SDL_Surface *pIconSurf;
249: char sIconFileName[FILENAME_MAX];
250:
251: /* Clear frame buffer structures and set current pointer */
252: memset(FrameBuffers, 0, NUM_FRAMEBUFFERS * sizeof(FRAMEBUFFER));
253:
254: /* Allocate previous screen check workspace. We are going to double-buffer a double-buffered screen. Oh. */
255: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
256: {
257: FrameBuffers[i].pNEXTScreen = malloc(((1024)/8)*768);
258: FrameBuffers[i].pNEXTScreenCopy = malloc(((1024)/8)*768);
259: if (!FrameBuffers[i].pNEXTScreen || !FrameBuffers[i].pNEXTScreenCopy)
260: {
261: fprintf(stderr, "Failed to allocate frame buffer memory.\n");
262: exit(-1);
263: }
264: }
265: pFrameBuffer = &FrameBuffers[0];
266:
267: /* Load and set icon */
268: snprintf(sIconFileName, sizeof(sIconFileName), "%s%cprevious-icon.bmp",
269: Paths_GetDataDir(), PATHSEP);
270: pIconSurf = SDL_LoadBMP(sIconFileName);
271: if (pIconSurf)
272: {
273: SDL_SetColorKey(pIconSurf, SDL_SRCCOLORKEY, SDL_MapRGB(pIconSurf->format, 255, 255, 255));
274: SDL_WM_SetIcon(pIconSurf, NULL);
275: SDL_FreeSurface(pIconSurf);
276: }
277:
278: /* Set initial window resolution */
279: bInFullScreen = ConfigureParams.Screen.bFullScreen;
280: Screen_SetResolution();
281:
282: if (bGrabMouse)
283: SDL_WM_GrabInput(SDL_GRAB_ON);
284:
285: Video_SetScreenRasters(); /* Set rasters ready for first screen */
286:
287: Screen_CreatePalette();
288: /* Configure some SDL stuff: */
289: SDL_ShowCursor(SDL_DISABLE);
290: }
291:
292:
293: /*-----------------------------------------------------------------------*/
294: /**
295: * Free screen bitmap and allocated resources
296: */
297: void Screen_UnInit(void)
298: {
299: int i;
300:
301: /* Free memory used for copies */
302: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
303: {
304: free(FrameBuffers[i].pNEXTScreen);
305: free(FrameBuffers[i].pNEXTScreenCopy);
306: }
307: }
308:
309:
310: /*-----------------------------------------------------------------------*/
311: /**
312: * Reset screen
313: */
314: void Screen_Reset(void)
315: {
316: /* Cause full update */
317: Screen_ModeChanged();
318: }
319:
320:
321: /*-----------------------------------------------------------------------*/
322: /**
323: * Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
324: * next time around
325: */
326: void Screen_SetFullUpdate(void)
327: {
328: int i;
329:
330: /* Update frame buffers */
331: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
332: FrameBuffers[i].bFullUpdate = true;
333: }
334:
335:
336: /*-----------------------------------------------------------------------*/
337: /**
338: * Clear Window display memory
339: */
340: static void Screen_ClearScreen(void)
341: {
342: SDL_FillRect(sdlscrn, &NEXTScreenRect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
343: }
344:
345:
346: /*-----------------------------------------------------------------------*/
347: /**
348: * Return true if (falcon/tt) hostscreen functions need to be used
349: * instead of the (st/ste) functions here.
350: */
351: static bool Screen_UseHostScreen(void)
352: {
353: return false;
354: }
355:
356: /*-----------------------------------------------------------------------*/
357: /**
358: * Force screen redraw. Does the right thing regardless of whether
359: * we're in ST/STe, Falcon or TT mode. Needed when switching modes
360: * while emulation is paused.
361: */
362: static void Screen_Refresh(void)
363: {
364: Screen_DrawFrame(true);
365: }
366:
367:
368: /*-----------------------------------------------------------------------*/
369: /**
370: * Enter Full screen mode
371: */
372: void Screen_EnterFullScreen(void)
373: {
374: bool bWasRunning;
375:
376: if (!bInFullScreen)
377: {
378: /* Hold things... */
379: bWasRunning = Main_PauseEmulation(false);
380: bInFullScreen = true;
381:
382: if (Screen_UseHostScreen())
383: {
384: // HostScreen_toggleFullScreen();
385: }
386: else
387: {
388: Screen_SetResolution();
389: Screen_ClearScreen(); /* Black out screen bitmap as will be invalid when return */
390: }
391:
392: SDL_Delay(20); /* To give monitor time to change to new resolution */
393:
394: if (bWasRunning)
395: {
396: /* And off we go... */
397: Main_UnPauseEmulation();
398: }
399: else
400: {
401: Screen_Refresh();
402: }
403: SDL_WM_GrabInput(SDL_GRAB_ON); /* Grab mouse pointer in fullscreen */
404: }
405: }
406:
407:
408: /*-----------------------------------------------------------------------*/
409: /**
410: * Return from Full screen mode back to a window
411: */
412: void Screen_ReturnFromFullScreen(void)
413: {
414: bool bWasRunning;
415:
416: if (bInFullScreen)
417: {
418: /* Hold things... */
419: bWasRunning = Main_PauseEmulation(false);
420: bInFullScreen = false;
421:
422: if (Screen_UseHostScreen())
423: {
424: // HostScreen_toggleFullScreen();
425: }
426: else
427: {
428: Screen_SetResolution();
429: }
430: SDL_Delay(20); /* To give monitor time to switch resolution */
431:
432: if (bWasRunning)
433: {
434: /* And off we go... */
435: Main_UnPauseEmulation();
436: }
437: else
438: {
439: Screen_Refresh();
440: }
441:
442: if (!bGrabMouse)
443: {
444: /* Un-grab mouse pointer in windowed mode */
445: SDL_WM_GrabInput(SDL_GRAB_OFF);
446: }
447: }
448: }
449:
450:
451: /*-----------------------------------------------------------------------*/
452: /**
453: * Have we changed between low/med/high res?
454: */
455: static void Screen_DidResolutionChange(int new_res)
456: {
457: }
458:
459:
460: /*-----------------------------------------------------------------------*/
461: /**
462: * Force things associated with changing between low/medium/high res.
463: */
464: void Screen_ModeChanged(void)
465: {
466: if (!sdlscrn)
467: {
468: /* screen not yet initialized */
469: return;
470: }
471: /* Set new display mode, if differs from current */
472: Screen_SetResolution();
473: Screen_SetFullUpdate();
474: if (bInFullScreen || bGrabMouse)
475: SDL_WM_GrabInput(SDL_GRAB_ON);
476: else
477: SDL_WM_GrabInput(SDL_GRAB_OFF);
478: }
479:
480:
481: /*-----------------------------------------------------------------------*/
482: /**
483: * Compare current resolution on line with previous, and set 'UpdateLine' accordingly
484: * Return if swap between low/medium resolution
485: */
486: static bool Screen_CompareResolution(int y, int *pUpdateLine, int oldres)
487: {
488: return false;
489: }
490:
491:
492: /*-----------------------------------------------------------------------*/
493: /**
494: * Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
495: */
496: static void Screen_ComparePalette(int y, int *pUpdateLine)
497: {
498: }
499:
500:
501: /*-----------------------------------------------------------------------*/
502: /**
503: * Check for differences in Palette and Resolution from Mask table and update
504: * and store off which lines need updating and create full-screen palette.
505: * (It is very important for these routines to check for colour changes with
506: * the previous screen so only the very minimum parts are updated).
507: * Return new STRes value.
508: */
509: static int Screen_ComparePaletteMask(int res)
510: {
511: return 0;
512: }
513:
514:
515: /*-----------------------------------------------------------------------*/
516: /**
517: * Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
518: * or when going between a Window and full-screen display
519: */
520: static void Screen_SetFullUpdateMask(void)
521: {
522: }
523:
524:
525: /*-----------------------------------------------------------------------*/
526: /**
527: * Set details for ST screen conversion.
528: */
529: static void Screen_SetConvertDetails(void)
530: {
531: }
532:
533:
534: /*-----------------------------------------------------------------------*/
535: /**
536: * Lock full-screen for drawing
537: */
538: static bool Screen_Lock(void)
539: {
540: if (SDL_MUSTLOCK(sdlscrn))
541: {
542: if (SDL_LockSurface(sdlscrn))
543: {
544: Screen_ReturnFromFullScreen(); /* All OK? If not need to jump back to a window */
545: return false;
546: }
547: }
548:
549: return true;
550: }
551:
552: /*-----------------------------------------------------------------------*/
553: /**
554: * UnLock full-screen
555: */
556: static void Screen_UnLock(void)
557: {
558: if ( SDL_MUSTLOCK(sdlscrn) )
559: SDL_UnlockSurface(sdlscrn);
560: }
561:
562:
563: /*-----------------------------------------------------------------------*/
564: /**
565: * Blit our converted ST screen to window/full-screen
566: */
567: static void Screen_Blit(void)
568: {
569: unsigned char *pTmpScreen;
570:
571: {
572: SDL_UpdateRects(sdlscrn, 1, &NEXTScreenRect);
573: }
574:
575: /* Swap copy/raster buffers in screen. */
576: pTmpScreen = pFrameBuffer->pNEXTScreenCopy;
577: pFrameBuffer->pNEXTScreenCopy = pFrameBuffer->pNEXTScreen;
578: pFrameBuffer->pNEXTScreen = pTmpScreen;
579: }
580:
581:
582: /*-----------------------------------------------------------------------*/
583: /**
584: */
585: static bool Screen_DrawFrame(bool bForceFlip)
586: {
587: int new_res;
588: void (*pDrawFunction)(void);
589:
590: /* Lock screen ready for drawing */
591: if (Screen_Lock())
592: {
593:
594: pDrawFunction = ScreenDrawFunctionsNormal[ST_HIGH_RES];
595:
596: if (pDrawFunction)
597: CALL_VAR(pDrawFunction);
598:
599: /* Unlock screen */
600: Screen_UnLock();
601:
602: /* draw statusbar or overlay led(s) after unlock */
603: Statusbar_OverlayBackup(sdlscrn);
604: Statusbar_Update(sdlscrn);
605:
606: Screen_Blit();
607:
608: return bScreenContentsChanged;
609: }
610:
611: return false;
612: }
613:
614:
615: /*-----------------------------------------------------------------------*/
616: /**
617: * Draw ST screen to window/full-screen
618: */
619: bool Screen_Draw(void)
620: {
621: if (!bQuitProgram)
622: {
623: /* And draw (if screen contents changed) */
624: Screen_DrawFrame(false);
625: return true;
626: }
627:
628: return false;
629: }
630:
631:
632: /* -------------- screen conversion routines --------------------------------
633: */
634:
635:
636: /*-----------------------------------------------------------------------*/
637: /**
638: */
639: static int AdjustLinePaletteRemap(int y)
640: {
641: return true;
642: }
643:
644:
645: /*-----------------------------------------------------------------------*/
646: /**
647: */
648: static void Convert_StartFrame(void)
649: {
650: }
651:
652: /* lookup tables and conversion macros */
653: #include "convert/macros.h"
654:
655: /* Conversion routines */
656:
657: #include "convert/high640x8.c" /* HighRes To 640xH x 8-bit color */
658:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.