|
|
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_WM_SetCaption(PROG_NAME, "Hatari");
546: SDL_ShowCursor(SDL_DISABLE);
1.1 root 547: }
548:
1.1.1.2 root 549:
1.1 root 550: /*-----------------------------------------------------------------------*/
1.1.1.13 root 551: /**
552: * Free screen bitmap and allocated resources
553: */
1.1 root 554: void Screen_UnInit(void)
555: {
1.1.1.13 root 556: int i;
1.1 root 557:
1.1.1.13 root 558: /* Free memory used for copies */
559: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
560: {
561: free(FrameBuffers[i].pSTScreen);
562: free(FrameBuffers[i].pSTScreenCopy);
563: }
1.1 root 564: }
565:
1.1.1.2 root 566:
1.1 root 567: /*-----------------------------------------------------------------------*/
1.1.1.13 root 568: /**
569: * Reset screen
570: */
1.1 root 571: void Screen_Reset(void)
572: {
1.1.1.13 root 573: /* On re-boot, always correct ST resolution for monitor, eg Colour/Mono */
574: if (bUseVDIRes)
575: {
576: STRes = VDIRes;
577: }
578: else
579: {
580: if (bUseHighRes)
581: {
582: STRes = ST_HIGH_RES;
583: TTRes = TT_HIGH_RES;
584: }
585: else
586: {
587: STRes = ST_LOW_RES;
588: TTRes = TT_MEDIUM_RES;
589: }
590: }
591: /* Cause full update */
592: Screen_ModeChanged();
1.1 root 593: }
594:
595:
596: /*-----------------------------------------------------------------------*/
1.1.1.13 root 597: /**
598: * Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
599: * next time around
600: */
1.1 root 601: void Screen_SetFullUpdate(void)
602: {
1.1.1.13 root 603: int i;
1.1 root 604:
1.1.1.13 root 605: /* Update frame buffers */
606: for (i = 0; i < NUM_FRAMEBUFFERS; i++)
1.1.1.17 root 607: FrameBuffers[i].bFullUpdate = true;
1.1 root 608: }
609:
1.1.1.5 root 610:
1.1 root 611: /*-----------------------------------------------------------------------*/
1.1.1.13 root 612: /**
613: * Clear Window display memory
614: */
1.1.1.11 root 615: static void Screen_ClearScreen(void)
616: {
1.1.1.15 root 617: SDL_FillRect(sdlscrn, &STScreenRect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
1.1.1.11 root 618: }
619:
1.1.1.18! root 620:
! 621: /*-----------------------------------------------------------------------*/
! 622: /**
! 623: * Return true if (falcon/tt) hostscreen functions need to be used
! 624: * instead of the (st/ste) functions here.
! 625: */
! 626: static bool Screen_UseHostScreen(void)
! 627: {
! 628: return ((ConfigureParams.System.nMachineType == MACHINE_FALCON
! 629: || ConfigureParams.System.nMachineType == MACHINE_TT)
! 630: && !bUseVDIRes);
! 631: }
! 632:
! 633: /*-----------------------------------------------------------------------*/
! 634: /**
! 635: * Force screen redraw. Does the right thing regardless of whether
! 636: * we're in ST/STe, Falcon or TT mode. Needed when switching modes
! 637: * while emulation is paused.
! 638: */
! 639: static void Screen_Refresh(void)
! 640: {
! 641: if (!bUseVDIRes)
! 642: {
! 643: if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
! 644: {
! 645: VIDEL_renderScreen();
! 646: return;
! 647: }
! 648: else if (ConfigureParams.System.nMachineType == MACHINE_TT)
! 649: {
! 650: Video_RenderTTScreen();
! 651: return;
! 652: }
! 653: }
! 654: Screen_DrawFrame(true);
! 655: }
! 656:
! 657:
1.1.1.11 root 658: /*-----------------------------------------------------------------------*/
1.1.1.13 root 659: /**
660: * Enter Full screen mode
661: */
1.1 root 662: void Screen_EnterFullScreen(void)
663: {
1.1.1.18! root 664: bool bWasRunning;
! 665:
1.1.1.13 root 666: if (!bInFullScreen)
667: {
1.1.1.18! root 668: /* Hold things... */
! 669: bWasRunning = Main_PauseEmulation(false);
1.1.1.17 root 670: bInFullScreen = true;
1.1.1.2 root 671:
1.1.1.18! root 672: if (Screen_UseHostScreen())
1.1.1.13 root 673: {
674: HostScreen_toggleFullScreen();
675: }
676: else
677: {
678: Screen_SetResolution();
679: Screen_ClearScreen(); /* Black out screen bitmap as will be invalid when return */
680: }
1.1 root 681:
1.1.1.13 root 682: SDL_Delay(20); /* To give monitor time to change to new resolution */
1.1.1.18! root 683:
! 684: if (bWasRunning)
! 685: {
! 686: /* And off we go... */
! 687: Main_UnPauseEmulation();
! 688: }
! 689: else
! 690: {
! 691: Screen_Refresh();
! 692: }
1.1.1.13 root 693: SDL_WM_GrabInput(SDL_GRAB_ON); /* Grab mouse pointer in fullscreen */
694: }
1.1 root 695: }
696:
1.1.1.2 root 697:
1.1 root 698: /*-----------------------------------------------------------------------*/
1.1.1.13 root 699: /**
700: * Return from Full screen mode back to a window
701: */
1.1 root 702: void Screen_ReturnFromFullScreen(void)
703: {
1.1.1.18! root 704: bool bWasRunning;
! 705:
1.1.1.13 root 706: if (bInFullScreen)
707: {
1.1.1.18! root 708: /* Hold things... */
! 709: bWasRunning = Main_PauseEmulation(false);
1.1.1.17 root 710: bInFullScreen = false;
1.1.1.13 root 711:
1.1.1.18! root 712: if (Screen_UseHostScreen())
1.1.1.13 root 713: {
714: HostScreen_toggleFullScreen();
715: }
716: else
717: {
718: Screen_SetResolution();
719: }
720: SDL_Delay(20); /* To give monitor time to switch resolution */
1.1.1.18! root 721:
! 722: if (bWasRunning)
! 723: {
! 724: /* And off we go... */
! 725: Main_UnPauseEmulation();
! 726: }
! 727: else
! 728: {
! 729: Screen_Refresh();
! 730: }
1.1.1.17 root 731:
732: if (!bGrabMouse)
1.1.1.18! root 733: {
1.1.1.17 root 734: /* Un-grab mouse pointer in windowed mode */
735: SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1.1.18! root 736: }
1.1.1.13 root 737: }
738: }
1.1.1.2 root 739:
740:
1.1.1.13 root 741: /*-----------------------------------------------------------------------*/
742: /**
743: * Have we changed between low/med/high res?
744: */
745: static void Screen_DidResolutionChange(int new_res)
746: {
747: if (new_res != STRes)
748: {
749: STRes = new_res;
750: Screen_ModeChanged();
751: }
752: else
753: {
754: /* Did change overscan mode? Causes full update */
755: if (pFrameBuffer->OverscanModeCopy != OverscanMode)
1.1.1.17 root 756: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 757: }
1.1 root 758: }
759:
1.1.1.5 root 760:
1.1.1.2 root 761: /*-----------------------------------------------------------------------*/
1.1.1.13 root 762: /**
763: * Force things associated with changing between low/medium/high res.
764: */
765: void Screen_ModeChanged(void)
1.1 root 766: {
1.1.1.13 root 767: if (!sdlscrn)
768: {
769: /* screen not yet initialized */
770: return;
771: }
772: /* Don't run this function if Videl emulation is running! */
773: if (ConfigureParams.System.nMachineType == MACHINE_FALCON && !bUseVDIRes)
774: {
775: VIDEL_ZoomModeChanged();
776: }
777: else if (ConfigureParams.System.nMachineType == MACHINE_TT && !bUseVDIRes)
778: {
779: int width, height, bpp;
780: Video_GetTTRes(&width, &height, &bpp);
781: HostScreen_setWindowSize(width, height, 8);
782: }
1.1.1.17 root 783: else
784: {
785: /* Set new display mode, if differs from current */
786: Screen_SetResolution();
787: Screen_SetFullUpdate();
788: }
789: if (bInFullScreen || bGrabMouse)
790: SDL_WM_GrabInput(SDL_GRAB_ON);
791: else
792: SDL_WM_GrabInput(SDL_GRAB_OFF);
1.1 root 793: }
794:
1.1.1.2 root 795:
796: /*-----------------------------------------------------------------------*/
1.1.1.13 root 797: /**
798: * Compare current resolution on line with previous, and set 'UpdateLine' accordingly
799: * Return if swap between low/medium resolution
800: */
1.1.1.15 root 801: static bool Screen_CompareResolution(int y, int *pUpdateLine, int oldres)
1.1 root 802: {
1.1.1.13 root 803: /* Check if wrote to resolution register */
804: if (HBLPaletteMasks[y]&PALETTEMASK_RESOLUTION) /* See 'Intercept_ShifterMode_WriteByte' */
805: {
806: int newres = (HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT;
807: /* Did resolution change? */
808: if (newres != (int)((pFrameBuffer->HBLPaletteMasks[y]>>16)&ST_MEDIUM_RES_BIT))
809: *pUpdateLine |= PALETTEMASK_UPDATERES;
810: else
811: *pUpdateLine &= ~PALETTEMASK_UPDATERES;
812: /* Have used any low/medium res mix? */
813: return (newres != (oldres&ST_MEDIUM_RES_BIT));
814: }
1.1.1.17 root 815: return false;
1.1 root 816: }
817:
1.1.1.7 root 818:
1.1.1.2 root 819: /*-----------------------------------------------------------------------*/
1.1.1.13 root 820: /**
821: * Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
822: */
1.1.1.8 root 823: static void Screen_ComparePalette(int y, int *pUpdateLine)
1.1 root 824: {
1.1.1.17 root 825: bool bPaletteChanged = false;
1.1.1.13 root 826: int i;
1.1 root 827:
1.1.1.13 root 828: /* Did write to palette in this or previous frame? */
829: if (((HBLPaletteMasks[y]|pFrameBuffer->HBLPaletteMasks[y])&PALETTEMASK_PALETTE)!=0)
830: {
831: /* Check and update ones which changed */
832: for (i = 0; i < 16; i++)
833: {
834: if (HBLPaletteMasks[y]&(1<<i)) /* Update changes in ST palette */
835: HBLPalette[i] = HBLPalettes[(y*16)+i];
836: }
837: /* Now check with same palette from previous frame for any differences(may be changing palette back) */
838: for (i = 0; (i < 16) && (!bPaletteChanged); i++)
839: {
840: if (HBLPalette[i]!=pFrameBuffer->HBLPalettes[(y*16)+i])
1.1.1.17 root 841: bPaletteChanged = true;
1.1.1.13 root 842: }
843: if (bPaletteChanged)
844: *pUpdateLine |= PALETTEMASK_UPDATEPAL;
845: else
846: *pUpdateLine &= ~PALETTEMASK_UPDATEPAL;
847: }
1.1 root 848: }
849:
1.1.1.7 root 850:
1.1.1.2 root 851: /*-----------------------------------------------------------------------*/
1.1.1.13 root 852: /**
853: * Check for differences in Palette and Resolution from Mask table and update
854: * and store off which lines need updating and create full-screen palette.
855: * (It is very important for these routines to check for colour changes with
856: * the previous screen so only the very minimum parts are updated).
857: * Return new STRes value.
858: */
859: static int Screen_ComparePaletteMask(int res)
1.1 root 860: {
1.1.1.17 root 861: bool bLowMedMix = false;
1.1.1.13 root 862: int LineUpdate = 0;
863: int y;
864:
865: /* Set for monochrome? */
866: if (bUseHighRes)
867: {
868: OverscanMode = OVERSCANMODE_NONE;
869:
870: /* Just copy mono colours, 0x777 checked also in convert/vdi2.c */
871: if (HBLPalettes[0] & 0x777)
872: {
873: HBLPalettes[0] = 0x777;
874: HBLPalettes[1] = 0x000;
875: }
876: else
877: {
878: HBLPalettes[0] = 0x000;
879: HBLPalettes[1] = 0x777;
880: }
881:
882: /* Colors changed? */
883: if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17 root 884: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 885:
886: /* Set bit to flag 'full update' */
887: if (pFrameBuffer->bFullUpdate)
888: ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
889: else
890: ScrUpdateFlag = 0x00000000;
891: }
892:
893: /* Use VDI resolution? */
894: if (bUseVDIRes)
895: {
896: /* Force to VDI resolution screen, without overscan */
897: res = VDIRes;
898:
899: /* Colors changed? */
900: if (HBLPalettes[0] != PrevHBLPalette[0])
1.1.1.17 root 901: pFrameBuffer->bFullUpdate = true;
1.1.1.13 root 902:
903: /* Set bit to flag 'full update' */
904: if (pFrameBuffer->bFullUpdate)
905: ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
906: else
907: ScrUpdateFlag = 0x00000000;
908: }
909: /* Are in Mono? Force to monochrome and no overscan */
910: else if (bUseHighRes)
911: {
912: /* Force to standard hi-resolution screen, without overscan */
913: res = ST_HIGH_RES;
914: }
915: else /* Full colour */
916: {
917: /* Get resolution */
918: //res = (HBLPaletteMasks[0]>>16)&ST_RES_MASK;
919: /* [NP] keep only low/med bit (could be hires in case of overscan on the 1st line) */
920: res = (HBLPaletteMasks[0]>>16)&ST_MEDIUM_RES_BIT;
921:
922: /* Do all lines - first is tagged as full-update */
923: for (y = 0; y < NUM_VISIBLE_LINES; y++)
924: {
925: /* Find any resolution/palette change and update palette/mask buffer */
926: /* ( LineUpdate has top two bits set to say if line needs updating due to palette or resolution change ) */
927: bLowMedMix |= Screen_CompareResolution(y, &LineUpdate, res);
928: Screen_ComparePalette(y,&LineUpdate);
929: HBLPaletteMasks[y] = (HBLPaletteMasks[y]&(~PALETTEMASK_UPDATEMASK)) | LineUpdate;
930: /* Copy palette and mask for next frame */
931: memcpy(&pFrameBuffer->HBLPalettes[y*16],HBLPalette,sizeof(short int)*16);
932: pFrameBuffer->HBLPaletteMasks[y] = HBLPaletteMasks[y];
933: }
934: /* Did mix/have medium resolution? */
935: if (bLowMedMix || (res & ST_MEDIUM_RES_BIT))
936: res = ST_MEDIUM_RES;
937: }
938:
939: return res;
940: }
941:
942:
943: /*-----------------------------------------------------------------------*/
944: /**
945: * Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
946: * or when going between a Window and full-screen display
947: */
1.1.1.8 root 948: static void Screen_SetFullUpdateMask(void)
1.1 root 949: {
1.1.1.13 root 950: int y;
1.1 root 951:
1.1.1.13 root 952: for (y = 0; y < NUM_VISIBLE_LINES; y++)
953: HBLPaletteMasks[y] |= PALETTEMASK_UPDATEFULL;
1.1 root 954: }
955:
1.1.1.7 root 956:
1.1.1.2 root 957: /*-----------------------------------------------------------------------*/
1.1.1.13 root 958: /**
959: * Set details for ST screen conversion.
960: */
1.1.1.10 root 961: static void Screen_SetConvertDetails(void)
1.1 root 962: {
1.1.1.13 root 963: pSTScreen = pFrameBuffer->pSTScreen; /* Source in ST memory */
964: pSTScreenCopy = pFrameBuffer->pSTScreenCopy; /* Previous ST screen */
965: pPCScreenDest = sdlscrn->pixels; /* Destination PC screen */
966:
967: PCScreenBytesPerLine = sdlscrn->pitch; /* Bytes per line */
968: pHBLPalettes = pFrameBuffer->HBLPalettes; /* HBL palettes pointer */
969: /* Not in TV-Mode? Then double up on Y: */
1.1.1.15 root 970: bScrDoubleY = !(ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_TV);
1.1.1.13 root 971:
972: if (bUseVDIRes)
973: {
974: /* Select screen draw for standard or VDI display */
975: STScreenLeftSkipBytes = 0;
976: STScreenWidthBytes = VDIWidth * VDIPlanes / 8;
977: STScreenStartHorizLine = 0;
978: STScreenEndHorizLine = VDIHeight;
979: }
980: else
981: {
982: if (ConfigureParams.Screen.bAllowOverscan) /* Use borders? */
983: {
984: /* Always draw to WHOLE screen including ALL borders */
985: STScreenLeftSkipBytes = 0; /* Number of bytes to skip on ST screen for left (border) */
986:
987: if (bUseHighRes)
988: {
989: pFrameBuffer->OverscanModeCopy = OverscanMode = OVERSCANMODE_NONE;
1.1.1.15 root 990: STScreenStartHorizLine = 0;
1.1.1.13 root 991: STScreenEndHorizLine = 400;
992: }
993: else
994: {
995: STScreenWidthBytes = SCREENBYTES_LINE; /* Number of horizontal bytes in our ST screen */
1.1.1.15 root 996: STScreenStartHorizLine = OVERSCAN_TOP - nBorderPixelsTop;
997: STScreenEndHorizLine = OVERSCAN_TOP + 200 + nBorderPixelsBottom;
1.1.1.13 root 998: }
999: }
1000: else
1001: {
1002: /* Only draw main area and centre on Y */
1003: STScreenLeftSkipBytes = SCREENBYTES_LEFT;
1004: STScreenWidthBytes = SCREENBYTES_MIDDLE;
1005: STScreenStartHorizLine = OVERSCAN_TOP;
1006: STScreenEndHorizLine = OVERSCAN_TOP + (bUseHighRes ? 400 : 200);
1007: }
1008: }
1.1 root 1009: }
1010:
1.1.1.2 root 1011:
1012: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1013: /**
1014: * Lock full-screen for drawing
1015: */
1.1.1.15 root 1016: static bool Screen_Lock(void)
1.1 root 1017: {
1.1.1.13 root 1018: if (SDL_MUSTLOCK(sdlscrn))
1019: {
1020: if (SDL_LockSurface(sdlscrn))
1021: {
1022: Screen_ReturnFromFullScreen(); /* All OK? If not need to jump back to a window */
1.1.1.17 root 1023: return false;
1.1.1.13 root 1024: }
1025: }
1.1.1.2 root 1026:
1.1.1.17 root 1027: return true;
1.1 root 1028: }
1029:
1.1.1.2 root 1030: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1031: /**
1032: * UnLock full-screen
1033: */
1.1.1.8 root 1034: static void Screen_UnLock(void)
1.1 root 1035: {
1.1.1.13 root 1036: if ( SDL_MUSTLOCK(sdlscrn) )
1037: SDL_UnlockSurface(sdlscrn);
1.1 root 1038: }
1039:
1.1.1.2 root 1040:
1041: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1042: /**
1043: * Blit our converted ST screen to window/full-screen
1044: */
1.1.1.15 root 1045: static void Screen_Blit(void)
1.1 root 1046: {
1.1.1.13 root 1047: unsigned char *pTmpScreen;
1048:
1.1.1.18! root 1049: #if 0 /* double buffering cannot be used with partial screen updates */
! 1050: # if NUM_FRAMEBUFFERS > 1
! 1051: if (bInFullScreen && (sdlscrn->flags & SDL_DOUBLEBUF))
1.1.1.13 root 1052: {
1053: /* Swap screen */
1.1.1.18! root 1054: if (pFrameBuffer==&FrameBuffers[0])
! 1055: pFrameBuffer = &FrameBuffers[1];
! 1056: else
! 1057: pFrameBuffer = &FrameBuffers[0];
1.1.1.15 root 1058: SDL_Flip(sdlscrn);
1.1.1.13 root 1059: }
1060: else
1.1.1.18! root 1061: # endif
! 1062: #endif
1.1.1.13 root 1063: {
1.1.1.15 root 1064: SDL_UpdateRects(sdlscrn, 1, &STScreenRect);
1.1.1.13 root 1065: }
1066:
1067: /* Swap copy/raster buffers in screen. */
1068: pTmpScreen = pFrameBuffer->pSTScreenCopy;
1069: pFrameBuffer->pSTScreenCopy = pFrameBuffer->pSTScreen;
1070: pFrameBuffer->pSTScreen = pTmpScreen;
1.1 root 1071: }
1072:
1.1.1.3 root 1073:
1.1.1.2 root 1074: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1075: /**
1076: * Draw ST screen to window/full-screen framebuffer
1.1.1.15 root 1077: * @param bForceFlip Force screen update, even if contents did not change
1.1.1.17 root 1078: * @return true if screen contents changed
1.1.1.13 root 1079: */
1.1.1.15 root 1080: static bool Screen_DrawFrame(bool bForceFlip)
1.1 root 1081: {
1.1.1.13 root 1082: int new_res;
1083: void (*pDrawFunction)(void);
1.1.1.17 root 1084: static bool bPrevFrameWasSpec512 = false;
1.1.1.13 root 1085:
1086: /* Scan palette/resolution masks for each line and build up palette/difference tables */
1087: new_res = Screen_ComparePaletteMask(STRes);
1088: /* Do require palette? Check if changed and update */
1089: Screen_Handle8BitPalettes();
1090: /* Did we change resolution this frame - allocate new screen if did so */
1091: Screen_DidResolutionChange(new_res);
1092: /* Is need full-update, tag as such */
1093: if (pFrameBuffer->bFullUpdate)
1094: Screen_SetFullUpdateMask();
1095:
1.1.1.15 root 1096: /* restore area potentially left under overlay led
1097: * and saved by Statusbar_OverlayBackup()
1098: */
1099: Statusbar_OverlayRestore(sdlscrn);
1100:
1.1.1.13 root 1101: /* Lock screen ready for drawing */
1102: if (Screen_Lock())
1103: {
1.1.1.17 root 1104: bScreenContentsChanged = false; /* Did change (ie needs blit?) */
1.1.1.15 root 1105:
1.1.1.13 root 1106: /* Set details */
1107: Screen_SetConvertDetails();
1.1.1.15 root 1108:
1.1.1.13 root 1109: /* Clear screen on full update to clear out borders and also interleaved lines */
1110: if (pFrameBuffer->bFullUpdate && !bUseVDIRes)
1111: Screen_ClearScreen();
1.1.1.15 root 1112:
1.1.1.13 root 1113: /* Call drawing for full-screen */
1114: if (bUseVDIRes)
1115: {
1116: pDrawFunction = ScreenDrawFunctionsVDI[VDIRes];
1117: }
1118: else
1119: {
1120: pDrawFunction = ScreenDrawFunctionsNormal[STRes];
1121: /* Check if is Spec512 image */
1122: if (Spec512_IsImage())
1123: {
1.1.1.17 root 1124: bPrevFrameWasSpec512 = true;
1.1.1.13 root 1125: /* What mode were we in? Keep to 320xH or 640xH */
1126: if (pDrawFunction==ConvertLowRes_320x16Bit)
1127: pDrawFunction = ConvertSpec512_320x16Bit;
1128: else if (pDrawFunction==ConvertLowRes_640x16Bit)
1129: pDrawFunction = ConvertSpec512_640x16Bit;
1130: else if (pDrawFunction==ConvertLowRes_320x32Bit)
1131: pDrawFunction = ConvertSpec512_320x32Bit;
1132: else if (pDrawFunction==ConvertLowRes_640x32Bit)
1133: pDrawFunction = ConvertSpec512_640x32Bit;
1134: }
1135: else if (bPrevFrameWasSpec512)
1136: {
1137: /* If we switch back from Spec512 mode to normal
1138: * screen rendering, we have to make sure to do
1139: * a full update of the screen. */
1140: Screen_SetFullUpdateMask();
1.1.1.17 root 1141: bPrevFrameWasSpec512 = false;
1.1.1.13 root 1142: }
1143: }
1144:
1145: if (pDrawFunction)
1.1.1.15 root 1146: CALL_VAR(pDrawFunction);
1147:
1148: /* Unlock screen */
1149: Screen_UnLock();
1.1.1.13 root 1150:
1.1.1.15 root 1151: /* draw statusbar or overlay led(s) after unlock */
1152: Statusbar_OverlayBackup(sdlscrn);
1153: Statusbar_Update(sdlscrn);
1154:
1.1.1.13 root 1155: /* Clear flags, remember type of overscan as if change need screen full update */
1.1.1.17 root 1156: pFrameBuffer->bFullUpdate = false;
1.1.1.13 root 1157: pFrameBuffer->OverscanModeCopy = OverscanMode;
1158:
1159: /* And show to user */
1160: if (bScreenContentsChanged || bForceFlip)
1.1.1.15 root 1161: {
1162: Screen_Blit();
1163: }
1.1.1.13 root 1164:
1.1.1.15 root 1165: return bScreenContentsChanged;
1.1.1.13 root 1166: }
1.1.1.15 root 1167:
1168: return false;
1.1 root 1169: }
1170:
1.1.1.9 root 1171:
1.1.1.2 root 1172: /*-----------------------------------------------------------------------*/
1.1.1.13 root 1173: /**
1174: * Draw ST screen to window/full-screen
1175: */
1.1.1.15 root 1176: bool Screen_Draw(void)
1.1 root 1177: {
1.1.1.13 root 1178: if (!bQuitProgram && VideoBase)
1179: {
1180: /* And draw (if screen contents changed) */
1.1.1.15 root 1181: return Screen_DrawFrame(false);
1.1.1.13 root 1182: }
1.1.1.15 root 1183:
1184: return false;
1.1 root 1185: }
1.1.1.11 root 1186:
1187:
1188: /* -------------- screen conversion routines --------------------------------
1189: Screen conversion routines. We have a number of routines to convert ST screen
1190: to PC format. We split these into Low, Medium and High each with 8/16-bit
1191: versions. To gain extra speed, as almost half of the processing time can be
1192: spent in these routines, we check for any changes from the previously
1193: displayed frame. AdjustLinePaletteRemap() sets a flag to tell the routines
1194: if we need to totally update a line (ie full update, or palette/res change)
1195: or if we just can do a difference check.
1196: We convert each screen 16 pixels at a time by use of a couple of look-up
1197: tables. These tables convert from 2-plane format to bbp and then we can add
1198: two of these together to get 4-planes. This keeps the tables small and thus
1199: improves speed. We then look these bbp values up as an RGB/Index value to
1200: copy to the screen.
1201: */
1202:
1203:
1.1.1.13 root 1204: /*-----------------------------------------------------------------------*/
1205: /**
1.1.1.11 root 1206: * Update the STRGBPalette[] array with current colours for this raster line.
1207: *
1208: * Return 'ScrUpdateFlag', 0x80000000=Full update, 0x40000000=Update
1209: * as palette changed
1210: */
1211: static int AdjustLinePaletteRemap(int y)
1212: {
1213: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 1214: 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 1215: #endif
1.1.1.13 root 1216: Uint16 *actHBLPal;
1217: int i;
1.1.1.11 root 1218:
1.1.1.13 root 1219: /* Copy palette and convert to RGB in display format */
1220: actHBLPal = pHBLPalettes + (y<<4); /* offset in palette */
1221: for (i=0; i<16; i++)
1222: {
1.1.1.11 root 1223: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.13 root 1224: STRGBPalette[endiantable[i]] = ST2RGB[*actHBLPal++];
1.1.1.11 root 1225: #else
1.1.1.13 root 1226: STRGBPalette[i] = ST2RGB[*actHBLPal++];
1.1.1.11 root 1227: #endif
1.1.1.13 root 1228: }
1229: ScrUpdateFlag = HBLPaletteMasks[y];
1230: return ScrUpdateFlag;
1.1.1.11 root 1231: }
1232:
1233:
1.1.1.13 root 1234: /*-----------------------------------------------------------------------*/
1235: /**
1.1.1.11 root 1236: * Run updates to palette(STRGBPalette[]) until get to screen line
1237: * we are to convert from
1238: */
1239: static void Convert_StartFrame(void)
1240: {
1.1.1.13 root 1241: int y = 0;
1242: /* Get #lines before conversion starts */
1243: int lines = STScreenStartHorizLine;
1244: while (lines--)
1245: AdjustLinePaletteRemap(y++); /* Update palette */
1.1.1.11 root 1246: }
1247:
1248: /* lookup tables and conversion macros */
1249: #include "convert/macros.h"
1250:
1251: /* Conversion routines */
1.1.1.13 root 1252:
1253: #include "convert/low320x8.c" /* LowRes To 320xH x 8-bit color */
1254: #include "convert/low640x8.c" /* LowRes To 640xH x 8-bit color */
1255: #include "convert/med640x8.c" /* MediumRes To 640xH x 8-bit color */
1256: #include "convert/high640x8.c" /* HighRes To 640xH x 8-bit color */
1257:
1258: #include "convert/low320x16.c" /* LowRes To 320xH x 16-bit color */
1259: #include "convert/low640x16.c" /* LowRes To 640xH x 16-bit color */
1260: #include "convert/med640x16.c" /* MediumRes To 640xH x 16-bit color */
1261: #include "convert/spec320x16.c" /* Spectrum 512 To 320xH x 16-bit color */
1262: #include "convert/spec640x16.c" /* Spectrum 512 To 640xH x 16-bit color */
1263:
1264: #include "convert/low320x32.c" /* LowRes To 320xH x 32-bit color */
1265: #include "convert/low640x32.c" /* LowRes To 640xH x 32-bit color */
1266: #include "convert/med640x32.c" /* MediumRes To 640xH x 32-bit color */
1267: #include "convert/spec320x32.c" /* Spectrum 512 To 320xH x 32-bit color */
1268: #include "convert/spec640x32.c" /* Spectrum 512 To 640xH x 32-bit color */
1269:
1270: #include "convert/vdi16.c" /* VDI x 16 color */
1271: #include "convert/vdi4.c" /* VDI x 4 color */
1272: #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.