|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - screen.c
1.1 root 3:
1.1.1.6 root 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:
1.1.1.17 root 7: This code converts a 1/2/4 plane ST format screen to either 8, 16 or 32-bit PC
1.1.1.11 root 8: format. An awful lot of processing is needed to do this conversion - we
1.1.1.6 root 9: cannot simply change palettes on interrupts as it is possible with DOS.
10: The main code processes the palette/resolution mask tables to find exactly
11: which lines need to updating and the conversion routines themselves only
12: update 16-pixel blocks which differ from the previous frame - this gives a
13: large performance increase.
14: Each conversion routine can convert any part of the source ST screen (which
15: includes the overscan border, usually set to colour zero) so they can be used
16: for both window and full-screen mode.
17: Note that in Hi-Resolution we have no overscan and just two colors so we can
1.1.1.17 root 18: optimise things further.
19: In color mode it seems possible to display 47 lines in the bottom border
20: with a second 60/50 Hz switch, but most programs consider there are 45
21: visible lines in the bottom border only, which gives a total of 274 lines
22: for a screen. So not displaying the last two lines fixes garbage that could
23: appear in the last two lines when displaying 47 lines (Digiworld 2 by ICE,
24: Tyranny by DHS).
1.1 root 25: */
1.1.1.15 root 26:
1.1.1.17 root 27: const char Screen_fileid[] = "Hatari screen.c : " __DATE__ " " __TIME__;
1.1 root 28:
29: #include <SDL.h>
1.1.1.11 root 30: #include <SDL_endian.h>
1.1 root 31:
32: #include "main.h"
1.1.1.7 root 33: #include "configuration.h"
1.1 root 34: #include "ikbd.h"
1.1.1.13 root 35: #include "log.h"
1.1 root 36: #include "m68000.h"
1.1.1.13 root 37: #include "paths.h"
1.1 root 38: #include "screen.h"
1.1.1.15 root 39: #include "control.h"
1.1.1.11 root 40: #include "convert/routines.h"
1.1.1.18 root 41: #include "resolution.h"
1.1 root 42: #include "sound.h"
43: #include "spec512.h"
1.1.1.15 root 44: #include "statusbar.h"
1.1 root 45: #include "vdi.h"
46: #include "video.h"
1.1.1.13 root 47: #include "falcon/videl.h"
48: #include "falcon/hostscreen.h"
1.1 root 49:
50:
1.1.1.13 root 51: /* extern for several purposes */
52: SDL_Surface *sdlscrn = NULL; /* The SDL screen surface */
53: int nScreenZoomX, nScreenZoomY; /* Zooming factors, used for scaling mouse motions */
54: int nBorderPixelsLeft, nBorderPixelsRight; /* Pixels in left and right border */
1.1.1.15 root 55: int nBorderPixelsTop, nBorderPixelsBottom; /* Lines in top and bottom border */
1.1.1.13 root 56:
57: /* extern for shortcuts and falcon/hostscreen.c */
1.1.1.17 root 58: bool bGrabMouse = false; /* Grab the mouse cursor in the window */
59: bool bInFullScreen = false; /* true if in full screen */
1.1.1.13 root 60:
61: /* extern for spec512.c */
1.1.1.11 root 62: int STScreenLeftSkipBytes;
63: int STScreenStartHorizLine; /* Start lines to be converted */
64: Uint32 STRGBPalette[16]; /* Palette buffer used in conversion routines */
65: Uint32 ST2RGB[4096]; /* Table to convert ST 0x777 / STe 0xfff palette to PC format RGB551 (2 pixels each entry) */
1.1.1.13 root 66:
67: /* extern for video.c */
1.1.1.11 root 68: Uint8 *pSTScreen;
69: FRAMEBUFFER *pFrameBuffer; /* Pointer into current 'FrameBuffer' */
70:
71: static FRAMEBUFFER FrameBuffers[NUM_FRAMEBUFFERS]; /* Store frame buffer details to tell how to update */
72: static Uint8 *pSTScreenCopy; /* Keep track of current and previous ST screen data */
73: static Uint8 *pPCScreenDest; /* Destination PC buffer */
74: static int STScreenEndHorizLine; /* End lines to be converted */
75: static int PCScreenBytesPerLine;
76: static int STScreenWidthBytes;
1.1.1.15 root 77: static SDL_Rect STScreenRect; /* screen size without statusbar */
1.1 root 78:
1.1.1.11 root 79: static int STScreenLineOffset[NUM_VISIBLE_LINES]; /* Offsets for ST screen lines eg, 0,160,320... */
80: static Uint16 HBLPalette[16], PrevHBLPalette[16]; /* Current palette for line, also copy of first line */
1.1 root 81:
1.1.1.13 root 82: static void (*ScreenDrawFunctionsNormal[3])(void); /* Screen draw functions */
1.1.1.12 root 83: static void (*ScreenDrawFunctionsVDI[3])(void) =
1.1.1.10 root 84: {
1.1.1.13 root 85: ConvertVDIRes_16Colour,
86: ConvertVDIRes_4Colour,
87: ConvertVDIRes_2Colour
1.1.1.10 root 88: };
89:
1.1.1.17 root 90: static bool bScreenContentsChanged; /* true if buffer changed and requires blitting */
91: static bool bScrDoubleY; /* true if double on Y */
1.1.1.11 root 92: static int ScrUpdateFlag; /* Bit mask of how to update screen */
93:
1.1.1.10 root 94:
1.1.1.18 root 95: static bool Screen_DrawFrame(bool bForceFlip);
96:
97:
1.1.1.10 root 98: /*-----------------------------------------------------------------------*/
1.1.1.13 root 99: /**
100: * Create ST 0x777 / STe 0xfff color format to 16 or 32 bits per pixel
101: * conversion table. Called each time when changed resolution or to/from
102: * fullscreen mode.
103: */
1.1.1.10 root 104: static void Screen_SetupRGBTable(void)
105: {
1.1.1.13 root 106: Uint16 STColor;
107: Uint32 RGBColor;
108: int r, g, b;
109: int rr, gg, bb;
110:
111: /* Do Red, Green and Blue for all 16*16*16 = 4096 STe colors */
112: for (r = 0; r < 16; r++)
113: {
114: for (g = 0; g < 16; g++)
115: {
116: for (b = 0; b < 16; b++)
117: {
118: /* STe 0xfff format */
119: STColor = (r<<8) | (g<<4) | (b);
120: rr = ((r & 0x7) << 5) | ((r & 0x8) << 1);
121: gg = ((g & 0x7) << 5) | ((g & 0x8) << 1);
122: bb = ((b & 0x7) << 5) | ((b & 0x8) << 1);
123: RGBColor = SDL_MapRGB(sdlscrn->format, rr, gg, bb);
124: if (sdlscrn->format->BitsPerPixel <= 16)
125: {
126: /* As longs, for speed (write two pixels at once) */
127: ST2RGB[STColor] = (RGBColor<<16) | RGBColor;
128: }
129: else
130: {
131: ST2RGB[STColor] = RGBColor;
132: }
133: }
134: }
135: }
1.1.1.10 root 136: }
137:
1.1.1.13 root 138:
1.1.1.10 root 139: /*-----------------------------------------------------------------------*/
1.1.1.13 root 140: /**
141: * Create new palette for display.
142: */
1.1.1.10 root 143: static void Screen_CreatePalette(void)
144: {
145: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 146: static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
1.1.1.10 root 147: #endif
1.1.1.13 root 148: SDL_Color sdlColors[16];
149: int i, j;
1.1.1.10 root 150:
1.1.1.13 root 151: if (bUseHighRes)
152: {
153: /* Colors for monochrome screen mode emulation */
154: if (HBLPalettes[0])
155: {
156: sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 255;
157: sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 0;
158: }
159: else
160: {
161: sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 0;
162: sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 255;
163: }
164: SDL_SetColors(sdlscrn, sdlColors, 10, 2);
165: /*SDL_SetColors(sdlscrn, sdlColors, 0, 2);*/
166: }
167: else
168: {
169: int r, g, b;
170: /* Colors for STe color screen mode emulation */
171: for (i = 0; i < 16; i++)
172: {
1.1.1.11 root 173: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 174: j = endiantable[i];
1.1.1.11 root 175: #else
1.1.1.13 root 176: j = i;
1.1.1.11 root 177: #endif
1.1.1.13 root 178: /* normalize all to 0x1e0 */
179: r = HBLPalettes[i] >> 3;
180: g = HBLPalettes[i] << 1;
181: b = HBLPalettes[i] << 5;
182: /* move top bit of 0x1e0 to lowest in 0xf0 */
183: sdlColors[j].r = (r & 0xe0) | ((r & 0x100) >> 4);
184: sdlColors[j].g = (g & 0xe0) | ((g & 0x100) >> 4);
185: sdlColors[j].b = (b & 0xe0) | ((b & 0x100) >> 4);
186: }
187: SDL_SetColors(sdlscrn, sdlColors, 10, 16);
188: }
1.1.1.10 root 189: }
190:
191:
192: /*-----------------------------------------------------------------------*/
1.1.1.13 root 193: /**
194: * Create 8-Bit palette for display if needed.
195: */
1.1.1.10 root 196: static void Screen_Handle8BitPalettes(void)
197: {
1.1.1.17 root 198: bool bPaletteChanged = false;
1.1.1.13 root 199: int i;
1.1.1.10 root 200:
1.1.1.13 root 201: /* Do need to check for 8-Bit palette change? Ie, update whole screen */
202: /* VDI screens and monochrome modes are ALL 8-Bit at the moment! */
203: if (sdlscrn->format->BitsPerPixel == 8)
204: {
205: /* If using HiRes palette update with full update flag */
206: if (!bUseHighRes)
207: {
208: /* Check if palette of 16 colours changed from previous frame */
209: for (i = 0; i < 16 && !bPaletteChanged; i++)
210: {
211: /* Check with first line palette (stored in 'Screen_ComparePaletteMask') */
212: if (HBLPalettes[i] != PrevHBLPalette[i])
1.1.1.17 root 213: bPaletteChanged = true;
1.1.1.13 root 214: }
215: }
216:
217: /* Did palette change or do we require a full update? */
218: if (bPaletteChanged || pFrameBuffer->bFullUpdate)
219: {
220: /* Create palette, for Full-Screen of Window */
221: Screen_CreatePalette();
222: /* Make sure update whole screen */
1.1.1.17 root 223: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 224: }
225: }
1.1.1.10 root 226:
1.1.1.13 root 227: /* Copy old palette for 8-Bit compare as this routine writes over it */
228: memcpy(PrevHBLPalette,HBLPalettes, sizeof(Uint16)*16);
1.1.1.10 root 229: }
230:
1.1 root 231:
232: /*-----------------------------------------------------------------------*/
1.1.1.13 root 233: /**
234: * Set screen draw functions.
235: */
1.1.1.18 root 236: static void Screen_SetDrawFunctions(int nBitCount, bool bDoubleLowRes)
1.1.1.10 root 237: {
1.1.1.14 root 238: if (nBitCount == 8)
1.1.1.13 root 239: {
240: /* Low color */
1.1.1.18 root 241: if (bDoubleLowRes)
1.1.1.13 root 242: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x8Bit;
243: else
244: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x8Bit;
245: ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x8Bit;
246: ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
247: }
248: else if (nBitCount <= 16)
249: {
250: /* High color */
1.1.1.18 root 251: if (bDoubleLowRes)
1.1.1.13 root 252: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x16Bit;
253: else
254: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x16Bit;
255: ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x16Bit;
256: ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
257: }
258: else /* Assume 32 bit drawing functions */
259: {
260: /* True color */
1.1.1.18 root 261: if (bDoubleLowRes)
1.1.1.13 root 262: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x32Bit;
263: else
264: ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x32Bit;
265: ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x32Bit;
266: ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
267: }
1.1.1.10 root 268: }
269:
270:
271: /*-----------------------------------------------------------------------*/
1.1.1.13 root 272: /**
1.1.1.18 root 273: * Set amount of border pixels
1.1.1.13 root 274: */
1.1.1.18 root 275: static void Screen_SetBorderPixels(int leftX, int leftY)
1.1.1.7 root 276: {
1.1.1.18 root 277: /* All screen widths need to be aligned to 16-bits.
278: *
279: * TODO: Change VDI_Limit() to generic function and check
280: * the limits when config values are set or changed
281: */
282: nBorderPixelsLeft = VDI_Limit(leftX/2, 16, 0, 48);
283: nBorderPixelsRight = nBorderPixelsLeft;
1.1.1.7 root 284:
1.1.1.18 root 285: /* assertain assumption of code below */
286: assert(OVERSCAN_TOP < MAX_OVERSCAN_BOTTOM);
287:
288: if (leftY > 2*OVERSCAN_TOP)
1.1.1.13 root 289: {
1.1.1.18 root 290: nBorderPixelsTop = OVERSCAN_TOP;
291: if (leftY >= OVERSCAN_TOP + MAX_OVERSCAN_BOTTOM)
292: nBorderPixelsBottom = MAX_OVERSCAN_BOTTOM;
293: else
294: nBorderPixelsBottom = leftY - OVERSCAN_TOP;
1.1.1.13 root 295: }
296: else
297: {
1.1.1.18 root 298: if (leftY > 0)
299: nBorderPixelsTop = nBorderPixelsBottom = leftY/2;
300: else
301: nBorderPixelsTop = nBorderPixelsBottom = 0;
1.1.1.13 root 302: }
1.1.1.18 root 303: }
304:
305: /*-----------------------------------------------------------------------*/
306: /**
307: * store Y offset for each horizontal line in our source ST screen for
308: * reference in the convert functions.
309: */
310: static void Screen_SetSTScreenOffsets(void)
311: {
312: int i;
1.1.1.13 root 313:
1.1.1.18 root 314: /* Store offset to each horizontal line, uses
315: * nBorderPixels* variables.
316: */
1.1.1.13 root 317: for (i = 0; i < NUM_VISIBLE_LINES; i++)
318: {
319: STScreenLineOffset[i] = i * SCREENBYTES_LINE;
320: }
1.1.1.7 root 321: }
322:
1.1.1.8 root 323:
1.1.1.7 root 324: /*-----------------------------------------------------------------------*/
1.1.1.13 root 325: /**
326: * Initialize SDL screen surface / set resolution.
327: */
328: static void Screen_SetResolution(void)
1.1.1.11 root 329: {
1.1.1.18 root 330: int Width, Height, nZoom, SBarHeight, BitCount, maxW, maxH;
331: Uint32 sdlVideoFlags;
332: bool bDoubleLowRes = false;
1.1.1.13 root 333:
334: /* Bits per pixel */
1.1.1.14 root 335: if (STRes == ST_HIGH_RES || bUseVDIRes)
1.1.1.13 root 336: {
337: BitCount = 8;
338: }
339: else
340: {
341: BitCount = ConfigureParams.Screen.nForceBpp;
342: }
343:
1.1.1.18 root 344: nBorderPixelsTop = nBorderPixelsBottom = 0;
345: nBorderPixelsLeft = nBorderPixelsRight = 0;
346:
347: nScreenZoomX = 1;
348: nScreenZoomY = 1;
349:
350: /* Determine which resolution to use */
351: if (bUseVDIRes)
1.1.1.13 root 352: {
1.1.1.18 root 353: Width = VDIWidth;
354: Height = VDIHeight;
1.1.1.13 root 355: }
356: else
357: {
1.1.1.18 root 358: if (STRes == ST_LOW_RES)
359: {
360: Width = 320;
361: Height = 200;
362: nZoom = 1;
363: }
364: else /* else use 640x400, also for med-rez */
365: {
366: Width = 640;
367: Height = 400;
368: nZoom = 2;
369: }
370:
371: /* Statusbar height for doubled screen size */
372: SBarHeight = Statusbar_GetHeightForSize(640, 400);
373:
374: Resolution_GetLimits(&maxW, &maxH, &BitCount);
375:
376: /* Zoom if necessary, factors used for scaling mouse motions */
377: if (STRes == ST_LOW_RES &&
378: 2*Width <= maxW && 2*Height+SBarHeight <= maxH)
379: {
380: nZoom = 2;
381: Width *= 2;
382: Height *= 2;
383: nScreenZoomX = 2;
384: nScreenZoomY = 2;
385: bDoubleLowRes = true;
386: }
387: else if (STRes == ST_MEDIUM_RES)
388: {
389: /* med-rez conversion functions want always
390: * to double vertically, they don't support
391: * skipping that (only leaving doubled lines
392: * black for the TV mode).
393: */
394: nScreenZoomX = 1;
395: nScreenZoomY = 2;
396: }
397:
398: /* Adjust width/height for overscan borders, if mono or VDI we have no overscan */
399: if (ConfigureParams.Screen.bAllowOverscan && !bUseHighRes)
400: {
401: int leftX = maxW - Width;
402: int leftY = maxH - (Height + Statusbar_GetHeightForSize(Width, Height));
403:
404: Screen_SetBorderPixels(leftX/nZoom, leftY/nZoom);
405: Width += (nBorderPixelsRight + nBorderPixelsLeft)*nZoom;
406: Height += (nBorderPixelsTop + nBorderPixelsBottom)*nZoom;
407: }
1.1.1.13 root 408: }
1.1.1.18 root 409:
410: Screen_SetSTScreenOffsets();
411: Height += Statusbar_SetHeight(Width, Height);
1.1.1.13 root 412:
413: /* SDL Video attributes: */
414: if (bInFullScreen)
415: {
416: sdlVideoFlags = SDL_HWSURFACE|SDL_FULLSCREEN|SDL_HWPALETTE/*|SDL_DOUBLEBUF*/;
1.1.1.18 root 417: /* SDL_DOUBLEBUF helps avoiding tearing and can be faster on suitable HW,
418: * but it doesn't work with partial screen updates done by the ST screen
419: * update code or the Hatari GUI, so double buffering is disabled.
420: */
1.1.1.13 root 421: }
422: else
423: {
424: sdlVideoFlags = SDL_SWSURFACE|SDL_HWPALETTE;
425: }
426:
427: /* Check if we really have to change the video mode: */
428: if (!sdlscrn || sdlscrn->w != Width || sdlscrn->h != Height
1.1.1.18 root 429: || (BitCount && sdlscrn->format->BitsPerPixel != BitCount)
1.1.1.13 root 430: || (sdlscrn->flags&SDL_FULLSCREEN) != (sdlVideoFlags&SDL_FULLSCREEN))
431: {
1.1.1.18 root 432: #ifdef _MUDFLAP
433: if (sdlscrn) {
434: __mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS);
435: }
436: #endif
1.1.1.15 root 437: if (bInFullScreen)
438: {
439: /* unhide the Hatari WM window for fullscreen */
440: Control_ReparentWindow(Width, Height, bInFullScreen);
441: }
442:
1.1.1.13 root 443: /* Set new video mode */
444: //fprintf(stderr,"Requesting video mode %i %i %i\n", Width, Height, BitCount);
445: sdlscrn = SDL_SetVideoMode(Width, Height, BitCount, sdlVideoFlags);
446: //fprintf(stderr,"Got video mode %i %i %i\n", sdlscrn->w, sdlscrn->h, sdlscrn->format->BitsPerPixel);
1.1.1.15 root 447:
448: /* By default ConfigureParams.Screen.nForceBpp and therefore
449: * BitCount is zero which means "SDL color depth autodetection".
450: * In this case the SDL_SetVideoMode() call might return
451: * a 24 bpp resolution
452: */
1.1.1.13 root 453: if (sdlscrn && sdlscrn->format->BitsPerPixel == 24)
454: {
455: fprintf(stderr, "Unsupported color depth 24, trying 32 bpp instead...\n");
456: sdlscrn = SDL_SetVideoMode(Width, Height, 32, sdlVideoFlags);
457: }
1.1.1.15 root 458:
1.1.1.13 root 459: /* Exit if we can not open a screen */
460: if (!sdlscrn)
461: {
462: fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
463: SDL_Quit();
464: exit(-2);
465: }
1.1.1.18 root 466: #ifdef _MUDFLAP
467: __mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels");
468: #endif
1.1.1.13 root 469:
1.1.1.15 root 470: if (!bInFullScreen)
471: {
472: /* re-embed the new Hatari SDL window */
473: Control_ReparentWindow(Width, Height, bInFullScreen);
474: }
475:
1.1.1.13 root 476: /* Re-init screen palette: */
1.1.1.14 root 477: if (sdlscrn->format->BitsPerPixel == 8)
1.1.1.13 root 478: Screen_Handle8BitPalettes(); /* Initialize new 8 bit palette */
479: else
480: Screen_SetupRGBTable(); /* Create color convertion table */
481:
1.1.1.15 root 482: Statusbar_Init(sdlscrn);
483:
484: /* screen area without the statusbar */
485: STScreenRect.x = 0;
486: STScreenRect.y = 0;
487: STScreenRect.w = sdlscrn->w;
488: STScreenRect.h = sdlscrn->h - Statusbar_GetHeight();
1.1.1.13 root 489: }
490:
491: /* Set drawing functions */
1.1.1.18 root 492: Screen_SetDrawFunctions(sdlscrn->format->BitsPerPixel, bDoubleLowRes);
1.1.1.13 root 493:
494: Screen_SetFullUpdate(); /* Cause full update of screen */
1.1.1.11 root 495: }
496:
497:
498: /*-----------------------------------------------------------------------*/
1.1.1.13 root 499: /**
500: * Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
501: */
1.1 root 502: void Screen_Init(void)
503: {
1.1.1.13 root 504: int i;
505: SDL_Surface *pIconSurf;
506: char sIconFileName[FILENAME_MAX];
507:
508: /* Clear frame buffer structures and set current pointer */
509: memset(FrameBuffers, 0, NUM_FRAMEBUFFERS * sizeof(FRAMEBUFFER));
510:
511: /* Allocate previous screen check workspace. We are going to double-buffer a double-buffered screen. Oh. */
512: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
513: {
514: FrameBuffers[i].pSTScreen = malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
515: FrameBuffers[i].pSTScreenCopy = malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
516: if (!FrameBuffers[i].pSTScreen || !FrameBuffers[i].pSTScreenCopy)
517: {
518: fprintf(stderr, "Failed to allocate frame buffer memory.\n");
519: exit(-1);
520: }
521: }
522: pFrameBuffer = &FrameBuffers[0];
523:
524: /* Load and set icon */
525: snprintf(sIconFileName, sizeof(sIconFileName), "%s%chatari-icon.bmp",
526: Paths_GetDataDir(), PATHSEP);
527: pIconSurf = SDL_LoadBMP(sIconFileName);
528: if (pIconSurf)
529: {
530: SDL_SetColorKey(pIconSurf, SDL_SRCCOLORKEY, SDL_MapRGB(pIconSurf->format, 255, 255, 255));
531: SDL_WM_SetIcon(pIconSurf, NULL);
532: SDL_FreeSurface(pIconSurf);
533: }
534:
535: /* Set initial window resolution */
536: bInFullScreen = ConfigureParams.Screen.bFullScreen;
537: Screen_SetResolution();
538:
1.1.1.17 root 539: if (bGrabMouse)
540: SDL_WM_GrabInput(SDL_GRAB_ON);
541:
1.1.1.13 root 542: Video_SetScreenRasters(); /* Set rasters ready for first screen */
543:
544: /* Configure some SDL stuff: */
545: SDL_ShowCursor(SDL_DISABLE);
1.1 root 546: }
547:
1.1.1.2 root 548:
1.1 root 549: /*-----------------------------------------------------------------------*/
1.1.1.13 root 550: /**
551: * Free screen bitmap and allocated resources
552: */
1.1 root 553: void Screen_UnInit(void)
554: {
1.1.1.13 root 555: int i;
1.1 root 556:
1.1.1.13 root 557: /* Free memory used for copies */
558: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
559: {
560: free(FrameBuffers[i].pSTScreen);
561: free(FrameBuffers[i].pSTScreenCopy);
562: }
1.1 root 563: }
564:
1.1.1.2 root 565:
1.1 root 566: /*-----------------------------------------------------------------------*/
1.1.1.13 root 567: /**
568: * Reset screen
569: */
1.1 root 570: void Screen_Reset(void)
571: {
1.1.1.13 root 572: /* On re-boot, always correct ST resolution for monitor, eg Colour/Mono */
573: if (bUseVDIRes)
574: {
575: STRes = VDIRes;
576: }
577: else
578: {
579: if (bUseHighRes)
580: {
581: STRes = ST_HIGH_RES;
582: TTRes = TT_HIGH_RES;
583: }
584: else
585: {
586: STRes = ST_LOW_RES;
587: TTRes = TT_MEDIUM_RES;
588: }
589: }
590: /* Cause full update */
591: Screen_ModeChanged();
1.1 root 592: }
593:
594:
595: /*-----------------------------------------------------------------------*/
1.1.1.13 root 596: /**
597: * Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
598: * next time around
599: */
1.1 root 600: void Screen_SetFullUpdate(void)
601: {
1.1.1.13 root 602: int i;
1.1 root 603:
1.1.1.13 root 604: /* Update frame buffers */
605: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
1.1.1.17 root 606: FrameBuffers[i].bFullUpdate = true;
1.1 root 607: }
608:
1.1.1.5 root 609:
1.1 root 610: /*-----------------------------------------------------------------------*/
1.1.1.13 root 611: /**
612: * Clear Window display memory
613: */
1.1.1.11 root 614: static void Screen_ClearScreen(void)
615: {
1.1.1.15 root 616: SDL_FillRect(sdlscrn, &STScreenRect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
1.1.1.11 root 617: }
618:
1.1.1.18 root 619:
620: /*-----------------------------------------------------------------------*/
621: /**
622: * Return true if (falcon/tt) hostscreen functions need to be used
623: * instead of the (st/ste) functions here.
624: */
625: static bool Screen_UseHostScreen(void)
626: {
627: return ((ConfigureParams.System.nMachineType == MACHINE_FALCON
628: || ConfigureParams.System.nMachineType == MACHINE_TT)
629: && !bUseVDIRes);
630: }
631:
632: /*-----------------------------------------------------------------------*/
633: /**
634: * Force screen redraw. Does the right thing regardless of whether
635: * we're in ST/STe, Falcon or TT mode. Needed when switching modes
636: * while emulation is paused.
637: */
638: static void Screen_Refresh(void)
639: {
640: if (!bUseVDIRes)
641: {
642: if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
643: {
644: VIDEL_renderScreen();
645: return;
646: }
647: else if (ConfigureParams.System.nMachineType == MACHINE_TT)
648: {
649: Video_RenderTTScreen();
650: return;
651: }
652: }
653: Screen_DrawFrame(true);
654: }
655:
656:
1.1.1.11 root 657: /*-----------------------------------------------------------------------*/
1.1.1.13 root 658: /**
659: * Enter Full screen mode
660: */
1.1 root 661: void Screen_EnterFullScreen(void)
662: {
1.1.1.18 root 663: bool bWasRunning;
664:
1.1.1.13 root 665: if (!bInFullScreen)
666: {
1.1.1.18 root 667: /* Hold things... */
668: bWasRunning = Main_PauseEmulation(false);
1.1.1.17 root 669: bInFullScreen = true;
1.1.1.2 root 670:
1.1.1.18 root 671: if (Screen_UseHostScreen())
1.1.1.13 root 672: {
673: HostScreen_toggleFullScreen();
674: }
675: else
676: {
677: Screen_SetResolution();
678: Screen_ClearScreen(); /* Black out screen bitmap as will be invalid when return */
679: }
1.1 root 680:
1.1.1.13 root 681: SDL_Delay(20); /* To give monitor time to change to new resolution */
1.1.1.18 root 682:
683: if (bWasRunning)
684: {
685: /* And off we go... */
686: Main_UnPauseEmulation();
687: }
688: else
689: {
690: Screen_Refresh();
691: }
1.1.1.13 root 692: SDL_WM_GrabInput(SDL_GRAB_ON); /* Grab mouse pointer in fullscreen */
693: }
1.1 root 694: }
695:
1.1.1.2 root 696:
1.1 root 697: /*-----------------------------------------------------------------------*/
1.1.1.13 root 698: /**
699: * Return from Full screen mode back to a window
700: */
1.1 root 701: void Screen_ReturnFromFullScreen(void)
702: {
1.1.1.18 root 703: bool bWasRunning;
704:
1.1.1.13 root 705: if (bInFullScreen)
706: {
1.1.1.18 root 707: /* Hold things... */
708: bWasRunning = Main_PauseEmulation(false);
1.1.1.17 root 709: bInFullScreen = false;
1.1.1.13 root 710:
1.1.1.18 root 711: if (Screen_UseHostScreen())
1.1.1.13 root 712: {
713: HostScreen_toggleFullScreen();
714: }
715: else
716: {
717: Screen_SetResolution();
718: }
719: SDL_Delay(20); /* To give monitor time to switch resolution */
1.1.1.18 root 720:
721: if (bWasRunning)
722: {
723: /* And off we go... */
724: Main_UnPauseEmulation();
725: }
726: else
727: {
728: Screen_Refresh();
729: }
1.1.1.17 root 730:
731: if (!bGrabMouse)
1.1.1.18 root 732: {
1.1.1.17 root 733: /* Un-grab mouse pointer in windowed mode */
734: SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1.1.18 root 735: }
1.1.1.13 root 736: }
737: }
1.1.1.2 root 738:
739:
1.1.1.13 root 740: /*-----------------------------------------------------------------------*/
741: /**
742: * Have we changed between low/med/high res?
743: */
744: static void Screen_DidResolutionChange(int new_res)
745: {
746: if (new_res != STRes)
747: {
748: STRes = new_res;
749: Screen_ModeChanged();
750: }
751: else
752: {
753: /* Did change overscan mode? Causes full update */
754: if (pFrameBuffer->OverscanModeCopy != OverscanMode)
1.1.1.17 root 755: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 756: }
1.1 root 757: }
758:
1.1.1.5 root 759:
1.1.1.2 root 760: /*-----------------------------------------------------------------------*/
1.1.1.13 root 761: /**
762: * Force things associated with changing between low/medium/high res.
763: */
764: void Screen_ModeChanged(void)
1.1 root 765: {
1.1.1.13 root 766: if (!sdlscrn)
767: {
768: /* screen not yet initialized */
769: return;
770: }
771: /* Don't run this function if Videl emulation is running! */
772: if (ConfigureParams.System.nMachineType == MACHINE_FALCON && !bUseVDIRes)
773: {
774: VIDEL_ZoomModeChanged();
775: }
776: else if (ConfigureParams.System.nMachineType == MACHINE_TT && !bUseVDIRes)
777: {
778: int width, height, bpp;
779: Video_GetTTRes(&width, &height, &bpp);
780: HostScreen_setWindowSize(width, height, 8);
781: }
1.1.1.17 root 782: else
783: {
784: /* Set new display mode, if differs from current */
785: Screen_SetResolution();
786: Screen_SetFullUpdate();
787: }
788: if (bInFullScreen || bGrabMouse)
789: SDL_WM_GrabInput(SDL_GRAB_ON);
790: else
791: SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1 root 792: }
793:
1.1.1.2 root 794:
795: /*-----------------------------------------------------------------------*/
1.1.1.13 root 796: /**
797: * Compare current resolution on line with previous, and set 'UpdateLine' accordingly
798: * Return if swap between low/medium resolution
799: */
1.1.1.15 root 800: static bool Screen_CompareResolution(int y, int *pUpdateLine, int oldres)
1.1 root 801: {
1.1.1.13 root 802: /* Check if wrote to resolution register */
803: if (HBLPaletteMasks[y]&PALETTEMASK_RESOLUTION) /* See 'Intercept_ShifterMode_WriteByte' */
804: {
805: int newres = (HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT;
806: /* Did resolution change? */
807: if (newres != (int)((pFrameBuffer->HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT))
808: *pUpdateLine |= PALETTEMASK_UPDATERES;
809: else
810: *pUpdateLine &= ~PALETTEMASK_UPDATERES;
811: /* Have used any low/medium res mix? */
812: return (newres != (oldres&ST_MEDIUM_RES_BIT));
813: }
1.1.1.17 root 814: return false;
1.1 root 815: }
816:
1.1.1.7 root 817:
1.1.1.2 root 818: /*-----------------------------------------------------------------------*/
1.1.1.13 root 819: /**
820: * Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
821: */
1.1.1.8 root 822: static void Screen_ComparePalette(int y, int *pUpdateLine)
1.1 root 823: {
1.1.1.17 root 824: bool bPaletteChanged = false;
1.1.1.13 root 825: int i;
1.1 root 826:
1.1.1.13 root 827: /* Did write to palette in this or previous frame? */
828: if (((HBLPaletteMasks[y]|pFrameBuffer->HBLPaletteMasks[y])&PALETTEMASK_PALETTE)!=0)
829: {
830: /* Check and update ones which changed */
831: for (i = 0; i < 16; i++)
832: {
833: if (HBLPaletteMasks[y]&(1<<i)) /* Update changes in ST palette */
834: HBLPalette[i] = HBLPalettes[(y*16)+i];
835: }
836: /* Now check with same palette from previous frame for any differences(may be changing palette back) */
837: for (i = 0; (i < 16) && (!bPaletteChanged); i++)
838: {
839: if (HBLPalette[i]!=pFrameBuffer->HBLPalettes[(y*16)+i])
1.1.1.17 root 840: bPaletteChanged = true;
1.1.1.13 root 841: }
842: if (bPaletteChanged)
843: *pUpdateLine |= PALETTEMASK_UPDATEPAL;
844: else
845: *pUpdateLine &= ~PALETTEMASK_UPDATEPAL;
846: }
1.1 root 847: }
848:
1.1.1.7 root 849:
1.1.1.2 root 850: /*-----------------------------------------------------------------------*/
1.1.1.13 root 851: /**
852: * Check for differences in Palette and Resolution from Mask table and update
853: * and store off which lines need updating and create full-screen palette.
854: * (It is very important for these routines to check for colour changes with
855: * the previous screen so only the very minimum parts are updated).
856: * Return new STRes value.
857: */
858: static int Screen_ComparePaletteMask(int res)
1.1 root 859: {
1.1.1.17 root 860: bool bLowMedMix = false;
1.1.1.13 root 861: int LineUpdate = 0;
862: int y;
863:
864: /* Set for monochrome? */
865: if (bUseHighRes)
866: {
867: OverscanMode = OVERSCANMODE_NONE;
868:
869: /* Just copy mono colours, 0x777 checked also in convert/vdi2.c */
870: if (HBLPalettes[0] & 0x777)
871: {
872: HBLPalettes[0] = 0x777;
873: HBLPalettes[1] = 0x000;
874: }
875: else
876: {
877: HBLPalettes[0] = 0x000;
878: HBLPalettes[1] = 0x777;
879: }
880:
881: /* Colors changed? */
882: if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17 root 883: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 884:
885: /* Set bit to flag 'full update' */
886: if (pFrameBuffer->bFullUpdate)
887: ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
888: else
889: ScrUpdateFlag = 0x00000000;
890: }
891:
892: /* Use VDI resolution? */
893: if (bUseVDIRes)
894: {
895: /* Force to VDI resolution screen, without overscan */
896: res = VDIRes;
897:
898: /* Colors changed? */
899: if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17 root 900: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 901:
902: /* Set bit to flag 'full update' */
903: if (pFrameBuffer->bFullUpdate)
904: ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
905: else
906: ScrUpdateFlag = 0x00000000;
907: }
908: /* Are in Mono? Force to monochrome and no overscan */
909: else if (bUseHighRes)
910: {
911: /* Force to standard hi-resolution screen, without overscan */
912: res = ST_HIGH_RES;
913: }
914: else /* Full colour */
915: {
916: /* Get resolution */
917: //res = (HBLPaletteMasks[0]>>16)&ST_RES_MASK;
918: /* [NP] keep only low/med bit (could be hires in case of overscan on the 1st line) */
919: res = (HBLPaletteMasks[0]>>16)&ST_MEDIUM_RES_BIT;
920:
921: /* Do all lines - first is tagged as full-update */
922: for (y = 0; y < NUM_VISIBLE_LINES; y++)
923: {
924: /* Find any resolution/palette change and update palette/mask buffer */
925: /* ( LineUpdate has top two bits set to say if line needs updating due to palette or resolution change ) */
926: bLowMedMix |= Screen_CompareResolution(y, &LineUpdate, res);
927: Screen_ComparePalette(y,&LineUpdate);
928: HBLPaletteMasks[y] = (HBLPaletteMasks[y]&(~PALETTEMASK_UPDATEMASK)) | LineUpdate;
929: /* Copy palette and mask for next frame */
930: memcpy(&pFrameBuffer->HBLPalettes[y*16],HBLPalette,sizeof(short int)*16);
931: pFrameBuffer->HBLPaletteMasks[y] = HBLPaletteMasks[y];
932: }
933: /* Did mix/have medium resolution? */
934: if (bLowMedMix || (res & ST_MEDIUM_RES_BIT))
935: res = ST_MEDIUM_RES;
936: }
937:
938: return res;
939: }
940:
941:
942: /*-----------------------------------------------------------------------*/
943: /**
944: * Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
945: * or when going between a Window and full-screen display
946: */
1.1.1.8 root 947: static void Screen_SetFullUpdateMask(void)
1.1 root 948: {
1.1.1.13 root 949: int y;
1.1 root 950:
1.1.1.13 root 951: for (y = 0; y < NUM_VISIBLE_LINES; y++)
952: HBLPaletteMasks[y] |= PALETTEMASK_UPDATEFULL;
1.1 root 953: }
954:
1.1.1.7 root 955:
1.1.1.2 root 956: /*-----------------------------------------------------------------------*/
1.1.1.13 root 957: /**
958: * Set details for ST screen conversion.
959: */
1.1.1.10 root 960: static void Screen_SetConvertDetails(void)
1.1 root 961: {
1.1.1.13 root 962: pSTScreen = pFrameBuffer->pSTScreen; /* Source in ST memory */
963: pSTScreenCopy = pFrameBuffer->pSTScreenCopy; /* Previous ST screen */
964: pPCScreenDest = sdlscrn->pixels; /* Destination PC screen */
965:
966: PCScreenBytesPerLine = sdlscrn->pitch; /* Bytes per line */
967: pHBLPalettes = pFrameBuffer->HBLPalettes; /* HBL palettes pointer */
968: /* Not in TV-Mode? Then double up on Y: */
1.1.1.15 root 969: bScrDoubleY = !(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_TV);
1.1.1.13 root 970:
971: if (bUseVDIRes)
972: {
973: /* Select screen draw for standard or VDI display */
974: STScreenLeftSkipBytes = 0;
975: STScreenWidthBytes = VDIWidth * VDIPlanes / 8;
976: STScreenStartHorizLine = 0;
977: STScreenEndHorizLine = VDIHeight;
978: }
979: else
980: {
981: if (ConfigureParams.Screen.bAllowOverscan) /* Use borders? */
982: {
983: /* Always draw to WHOLE screen including ALL borders */
984: STScreenLeftSkipBytes = 0; /* Number of bytes to skip on ST screen for left (border) */
985:
986: if (bUseHighRes)
987: {
988: pFrameBuffer->OverscanModeCopy = OverscanMode = OVERSCANMODE_NONE;
1.1.1.15 root 989: STScreenStartHorizLine = 0;
1.1.1.13 root 990: STScreenEndHorizLine = 400;
991: }
992: else
993: {
994: STScreenWidthBytes = SCREENBYTES_LINE; /* Number of horizontal bytes in our ST screen */
1.1.1.15 root 995: STScreenStartHorizLine = OVERSCAN_TOP - nBorderPixelsTop;
996: STScreenEndHorizLine = OVERSCAN_TOP + 200 + nBorderPixelsBottom;
1.1.1.13 root 997: }
998: }
999: else
1000: {
1001: /* Only draw main area and centre on Y */
1002: STScreenLeftSkipBytes = SCREENBYTES_LEFT;
1003: STScreenWidthBytes = SCREENBYTES_MIDDLE;
1004: STScreenStartHorizLine = OVERSCAN_TOP;
1005: STScreenEndHorizLine = OVERSCAN_TOP + (bUseHighRes ? 400 : 200);
1006: }
1007: }
1.1 root 1008: }
1009:
1.1.1.2 root 1010:
1011: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1012: /**
1013: * Lock full-screen for drawing
1014: */
1.1.1.15 root 1015: static bool Screen_Lock(void)
1.1 root 1016: {
1.1.1.13 root 1017: if (SDL_MUSTLOCK(sdlscrn))
1018: {
1019: if (SDL_LockSurface(sdlscrn))
1020: {
1021: Screen_ReturnFromFullScreen(); /* All OK? If not need to jump back to a window */
1.1.1.17 root 1022: return false;
1.1.1.13 root 1023: }
1024: }
1.1.1.2 root 1025:
1.1.1.17 root 1026: return true;
1.1 root 1027: }
1028:
1.1.1.2 root 1029: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1030: /**
1031: * UnLock full-screen
1032: */
1.1.1.8 root 1033: static void Screen_UnLock(void)
1.1 root 1034: {
1.1.1.13 root 1035: if ( SDL_MUSTLOCK(sdlscrn) )
1036: SDL_UnlockSurface(sdlscrn);
1.1 root 1037: }
1038:
1.1.1.2 root 1039:
1040: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1041: /**
1042: * Blit our converted ST screen to window/full-screen
1043: */
1.1.1.15 root 1044: static void Screen_Blit(void)
1.1 root 1045: {
1.1.1.13 root 1046: unsigned char *pTmpScreen;
1047:
1.1.1.18 root 1048: #if 0 /* double buffering cannot be used with partial screen updates */
1049: # if NUM_FRAMEBUFFERS > 1
1050: if (bInFullScreen && (sdlscrn->flags & SDL_DOUBLEBUF))
1.1.1.13 root 1051: {
1052: /* Swap screen */
1.1.1.18 root 1053: if (pFrameBuffer==&FrameBuffers[0])
1054: pFrameBuffer = &FrameBuffers[1];
1055: else
1056: pFrameBuffer = &FrameBuffers[0];
1.1.1.15 root 1057: SDL_Flip(sdlscrn);
1.1.1.13 root 1058: }
1059: else
1.1.1.18 root 1060: # endif
1061: #endif
1.1.1.13 root 1062: {
1.1.1.15 root 1063: SDL_UpdateRects(sdlscrn, 1, &STScreenRect);
1.1.1.13 root 1064: }
1065:
1066: /* Swap copy/raster buffers in screen. */
1067: pTmpScreen = pFrameBuffer->pSTScreenCopy;
1068: pFrameBuffer->pSTScreenCopy = pFrameBuffer->pSTScreen;
1069: pFrameBuffer->pSTScreen = pTmpScreen;
1.1 root 1070: }
1071:
1.1.1.3 root 1072:
1.1.1.2 root 1073: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1074: /**
1075: * Draw ST screen to window/full-screen framebuffer
1.1.1.15 root 1076: * @param bForceFlip Force screen update, even if contents did not change
1.1.1.17 root 1077: * @return true if screen contents changed
1.1.1.13 root 1078: */
1.1.1.15 root 1079: static bool Screen_DrawFrame(bool bForceFlip)
1.1 root 1080: {
1.1.1.13 root 1081: int new_res;
1082: void (*pDrawFunction)(void);
1.1.1.17 root 1083: static bool bPrevFrameWasSpec512 = false;
1.1.1.13 root 1084:
1085: /* Scan palette/resolution masks for each line and build up palette/difference tables */
1086: new_res = Screen_ComparePaletteMask(STRes);
1087: /* Do require palette? Check if changed and update */
1088: Screen_Handle8BitPalettes();
1089: /* Did we change resolution this frame - allocate new screen if did so */
1090: Screen_DidResolutionChange(new_res);
1091: /* Is need full-update, tag as such */
1092: if (pFrameBuffer->bFullUpdate)
1093: Screen_SetFullUpdateMask();
1094:
1.1.1.15 root 1095: /* restore area potentially left under overlay led
1096: * and saved by Statusbar_OverlayBackup()
1097: */
1098: Statusbar_OverlayRestore(sdlscrn);
1099:
1.1.1.13 root 1100: /* Lock screen ready for drawing */
1101: if (Screen_Lock())
1102: {
1.1.1.17 root 1103: bScreenContentsChanged = false; /* Did change (ie needs blit?) */
1.1.1.15 root 1104:
1.1.1.13 root 1105: /* Set details */
1106: Screen_SetConvertDetails();
1.1.1.15 root 1107:
1.1.1.13 root 1108: /* Clear screen on full update to clear out borders and also interleaved lines */
1109: if (pFrameBuffer->bFullUpdate && !bUseVDIRes)
1110: Screen_ClearScreen();
1.1.1.15 root 1111:
1.1.1.13 root 1112: /* Call drawing for full-screen */
1113: if (bUseVDIRes)
1114: {
1115: pDrawFunction = ScreenDrawFunctionsVDI[VDIRes];
1116: }
1117: else
1118: {
1119: pDrawFunction = ScreenDrawFunctionsNormal[STRes];
1120: /* Check if is Spec512 image */
1121: if (Spec512_IsImage())
1122: {
1.1.1.17 root 1123: bPrevFrameWasSpec512 = true;
1.1.1.13 root 1124: /* What mode were we in? Keep to 320xH or 640xH */
1125: if (pDrawFunction==ConvertLowRes_320x16Bit)
1.1.1.19! root 1126: pDrawFunction = ConvertLowRes_320x16Bit_Spec;
1.1.1.13 root 1127: else if (pDrawFunction==ConvertLowRes_640x16Bit)
1.1.1.19! root 1128: pDrawFunction = ConvertLowRes_640x16Bit_Spec;
1.1.1.13 root 1129: else if (pDrawFunction==ConvertLowRes_320x32Bit)
1.1.1.19! root 1130: pDrawFunction = ConvertLowRes_320x32Bit_Spec;
1.1.1.13 root 1131: else if (pDrawFunction==ConvertLowRes_640x32Bit)
1.1.1.19! root 1132: pDrawFunction = ConvertLowRes_640x32Bit_Spec;
! 1133: else if (pDrawFunction==ConvertMediumRes_640x32Bit)
! 1134: pDrawFunction = ConvertMediumRes_640x32Bit_Spec;
! 1135: else if (pDrawFunction==ConvertMediumRes_640x16Bit)
! 1136: pDrawFunction = ConvertMediumRes_640x16Bit_Spec;
1.1.1.13 root 1137: }
1138: else if (bPrevFrameWasSpec512)
1139: {
1140: /* If we switch back from Spec512 mode to normal
1141: * screen rendering, we have to make sure to do
1142: * a full update of the screen. */
1143: Screen_SetFullUpdateMask();
1.1.1.17 root 1144: bPrevFrameWasSpec512 = false;
1.1.1.13 root 1145: }
1146: }
1147:
1148: if (pDrawFunction)
1.1.1.15 root 1149: CALL_VAR(pDrawFunction);
1150:
1151: /* Unlock screen */
1152: Screen_UnLock();
1.1.1.13 root 1153:
1.1.1.15 root 1154: /* draw statusbar or overlay led(s) after unlock */
1155: Statusbar_OverlayBackup(sdlscrn);
1156: Statusbar_Update(sdlscrn);
1157:
1.1.1.13 root 1158: /* Clear flags, remember type of overscan as if change need screen full update */
1.1.1.17 root 1159: pFrameBuffer->bFullUpdate = false;
1.1.1.13 root 1160: pFrameBuffer->OverscanModeCopy = OverscanMode;
1161:
1162: /* And show to user */
1163: if (bScreenContentsChanged || bForceFlip)
1.1.1.15 root 1164: {
1165: Screen_Blit();
1166: }
1.1.1.13 root 1167:
1.1.1.15 root 1168: return bScreenContentsChanged;
1.1.1.13 root 1169: }
1.1.1.15 root 1170:
1171: return false;
1.1 root 1172: }
1173:
1.1.1.9 root 1174:
1.1.1.2 root 1175: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1176: /**
1177: * Draw ST screen to window/full-screen
1178: */
1.1.1.15 root 1179: bool Screen_Draw(void)
1.1 root 1180: {
1.1.1.13 root 1181: if (!bQuitProgram && VideoBase)
1182: {
1183: /* And draw (if screen contents changed) */
1.1.1.15 root 1184: return Screen_DrawFrame(false);
1.1.1.13 root 1185: }
1.1.1.15 root 1186:
1187: return false;
1.1 root 1188: }
1.1.1.11 root 1189:
1190:
1191: /* -------------- screen conversion routines --------------------------------
1192: Screen conversion routines. We have a number of routines to convert ST screen
1193: to PC format. We split these into Low, Medium and High each with 8/16-bit
1194: versions. To gain extra speed, as almost half of the processing time can be
1195: spent in these routines, we check for any changes from the previously
1196: displayed frame. AdjustLinePaletteRemap() sets a flag to tell the routines
1197: if we need to totally update a line (ie full update, or palette/res change)
1198: or if we just can do a difference check.
1199: We convert each screen 16 pixels at a time by use of a couple of look-up
1200: tables. These tables convert from 2-plane format to bbp and then we can add
1201: two of these together to get 4-planes. This keeps the tables small and thus
1202: improves speed. We then look these bbp values up as an RGB/Index value to
1203: copy to the screen.
1204: */
1205:
1206:
1.1.1.13 root 1207: /*-----------------------------------------------------------------------*/
1208: /**
1.1.1.11 root 1209: * Update the STRGBPalette[] array with current colours for this raster line.
1210: *
1211: * Return 'ScrUpdateFlag', 0x80000000=Full update, 0x40000000=Update
1212: * as palette changed
1213: */
1214: static int AdjustLinePaletteRemap(int y)
1215: {
1216: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 1217: static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
1.1.1.11 root 1218: #endif
1.1.1.13 root 1219: Uint16 *actHBLPal;
1220: int i;
1.1.1.11 root 1221:
1.1.1.13 root 1222: /* Copy palette and convert to RGB in display format */
1223: actHBLPal = pHBLPalettes + (y<<4); /* offset in palette */
1224: for (i=0; i<16; i++)
1225: {
1.1.1.11 root 1226: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 1227: STRGBPalette[endiantable[i]] = ST2RGB[*actHBLPal++];
1.1.1.11 root 1228: #else
1.1.1.13 root 1229: STRGBPalette[i] = ST2RGB[*actHBLPal++];
1.1.1.11 root 1230: #endif
1.1.1.13 root 1231: }
1232: ScrUpdateFlag = HBLPaletteMasks[y];
1233: return ScrUpdateFlag;
1.1.1.11 root 1234: }
1235:
1236:
1.1.1.13 root 1237: /*-----------------------------------------------------------------------*/
1238: /**
1.1.1.11 root 1239: * Run updates to palette(STRGBPalette[]) until get to screen line
1240: * we are to convert from
1241: */
1242: static void Convert_StartFrame(void)
1243: {
1.1.1.13 root 1244: int y = 0;
1245: /* Get #lines before conversion starts */
1246: int lines = STScreenStartHorizLine;
1247: while (lines--)
1248: AdjustLinePaletteRemap(y++); /* Update palette */
1.1.1.11 root 1249: }
1250:
1251: /* lookup tables and conversion macros */
1252: #include "convert/macros.h"
1253:
1254: /* Conversion routines */
1.1.1.13 root 1255:
1.1.1.19! root 1256: #include "convert/low320x8.c" /* LowRes To 320xH x 8-bit color */
! 1257: #include "convert/low640x8.c" /* LowRes To 640xH x 8-bit color */
! 1258: #include "convert/med640x8.c" /* MediumRes To 640xH x 8-bit color */
! 1259: #include "convert/high640x8.c" /* HighRes To 640xH x 8-bit color */
! 1260:
! 1261: #include "convert/low320x16.c" /* LowRes To 320xH x 16-bit color */
! 1262: #include "convert/low640x16.c" /* LowRes To 640xH x 16-bit color */
! 1263: #include "convert/med640x16.c" /* MediumRes To 640xH x 16-bit color */
! 1264: #include "convert/low320x16_spec.c" /* LowRes Spectrum 512 To 320xH x 16-bit color */
! 1265: #include "convert/low640x16_spec.c" /* LowRes Spectrum 512 To 640xH x 16-bit color */
! 1266: #include "convert/med640x16_spec.c" /* MediumRes Spectrum 512 To 640xH x 16-bit color */
! 1267:
! 1268: #include "convert/low320x32.c" /* LowRes To 320xH x 32-bit color */
! 1269: #include "convert/low640x32.c" /* LowRes To 640xH x 32-bit color */
! 1270: #include "convert/med640x32.c" /* MediumRes To 640xH x 32-bit color */
! 1271: #include "convert/low320x32_spec.c" /* LowRes Spectrum 512 To 320xH x 32-bit color */
! 1272: #include "convert/low640x32_spec.c" /* LowRes Spectrum 512 To 640xH x 32-bit color */
! 1273: #include "convert/med640x32_spec.c" /* MediumRes Spectrum 512 To 640xH x 32-bit color */
! 1274:
! 1275: #include "convert/vdi16.c" /* VDI x 16 color */
! 1276: #include "convert/vdi4.c" /* VDI x 4 color */
! 1277: #include "convert/vdi2.c" /* VDI x 2 color */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.