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