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