Annotation of hatari/src/screen.c, revision 1.1.1.12

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.12! root       22: const char Screen_rcsid[] = "Hatari $Id: screen.c,v 1.50 2006/06/26 23:03:09 thothy Exp $";
1.1       root       23: 
                     24: #include <SDL.h>
1.1.1.11  root       25: #include <SDL_endian.h>
1.1       root       26: 
                     27: #include "main.h"
1.1.1.7   root       28: #include "configuration.h"
1.1       root       29: #include "ikbd.h"
                     30: #include "m68000.h"
                     31: #include "misc.h"
                     32: #include "printer.h"
                     33: #include "screen.h"
1.1.1.11  root       34: #include "convert/routines.h"
1.1       root       35: #include "screenSnapShot.h"
                     36: #include "sound.h"
                     37: #include "spec512.h"
                     38: #include "vdi.h"
                     39: #include "video.h"
                     40: 
                     41: 
1.1.1.11  root       42: BOOL bGrabMouse = FALSE;      /* Grab the mouse cursor in the window */
                     43: BOOL bInFullScreen=FALSE;     /* TRUE if in full screen */
                     44: int STScreenLeftSkipBytes;
                     45: int STScreenStartHorizLine;   /* Start lines to be converted */
                     46: int STRes=ST_LOW_RES;         /* current resolution */
                     47: int PrevSTRes=ST_LOW_RES;     /* previous ST resolution */
                     48: Uint32 STRGBPalette[16];      /* Palette buffer used in conversion routines */
                     49: Uint32 ST2RGB[4096];          /* Table to convert ST 0x777 / STe 0xfff palette to PC format RGB551 (2 pixels each entry) */
1.1.1.12! root       50: SDL_Surface *sdlscrn = NULL;  /* The SDL screen surface */
1.1.1.11  root       51: Uint8 *pSTScreen;
                     52: FRAMEBUFFER *pFrameBuffer;    /* Pointer into current 'FrameBuffer' */
                     53: 
                     54: static FRAMEBUFFER FrameBuffers[NUM_FRAMEBUFFERS]; /* Store frame buffer details to tell how to update */
                     55: static Uint8 *pSTScreenCopy;                       /* Keep track of current and previous ST screen data */
                     56: static Uint8 *pPCScreenDest;                       /* Destination PC buffer */
                     57: static int STScreenEndHorizLine;                   /* End lines to be converted */
                     58: static int PCScreenBytesPerLine;
                     59: static int STScreenWidthBytes;
1.1       root       60: 
1.1.1.11  root       61: static int STScreenLineOffset[NUM_VISIBLE_LINES];  /* Offsets for ST screen lines eg, 0,160,320... */
                     62: static Uint16 HBLPalette[16], PrevHBLPalette[16];  /* Current palette for line, also copy of first line */
1.1       root       63: 
1.1.1.12! root       64: static void (*ScreenDrawFunctionsNormal[4])(void); /* Screen draw functions */
        !            65: static void (*ScreenDrawFunctionsVDI[3])(void) =
1.1.1.10  root       66: {
                     67:   ConvertVDIRes_16Colour,
                     68:   ConvertVDIRes_4Colour,
                     69:   ConvertVDIRes_2Colour
                     70: };
                     71: 
1.1.1.11  root       72: static BOOL bScreenContentsChanged;     /* TRUE if buffer changed and requires blitting */
                     73: static BOOL bScrDoubleY;                /* TRUE if double on Y */
                     74: static int ScrUpdateFlag;               /* Bit mask of how to update screen */
                     75: 
1.1.1.10  root       76: 
                     77: /*-----------------------------------------------------------------------*/
                     78: /*
1.1.1.12! root       79:   Create ST 0x777 / STe 0xfff color format to 16-bits per pixel conversion
        !            80:   table. Called each time when changed resolution or to/from fullscreen mode.
1.1.1.10  root       81: */
                     82: static void Screen_SetupRGBTable(void)
                     83: {
1.1.1.11  root       84:   Uint16 STColour, RGBColour;
1.1.1.12! root       85:   int r, g, b;
        !            86:   int rr, gg, bb;
1.1.1.10  root       87: 
1.1.1.12! root       88:   /* Do Red, Green and Blue for all 16*16*16 = 4096 STe colors */
        !            89:   for(r=0; r < 16; r++)
1.1.1.11  root       90:   {
                     91:       for(g=0; g < 16; g++)
1.1.1.10  root       92:       {
1.1.1.11  root       93:         for(b=0; b < 16; b++)
                     94:         {
                     95:           /* STe 0xfff format */
                     96:           STColour = (r<<8) | (g<<4) | (b);
                     97:           rr = ((r & 0x7) << 5) | ((r & 0x8) << 1);
                     98:           gg = ((g & 0x7) << 5) | ((g & 0x8) << 1);
                     99:           bb = ((b & 0x7) << 5) | ((b & 0x8) << 1);
                    100:           RGBColour = SDL_MapRGB(sdlscrn->format, rr, gg, bb);
                    101:           /* As longs, for speed (write two pixels at once) */
                    102:           ST2RGB[STColour] = (RGBColour<<16) | RGBColour;
                    103:         }
1.1.1.10  root      104:       }
                    105:   }
                    106: }
                    107: 
                    108: /*-----------------------------------------------------------------------*/
                    109: /*
                    110:   Create new palette for display.
                    111: */
                    112: static void Screen_CreatePalette(void)
                    113: {
                    114: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    115:   static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
                    116: #endif
                    117:   SDL_Color sdlColors[16];
                    118:   int i, j;
                    119: 
                    120:   if (bUseHighRes)
                    121:   {
                    122:     /* Colors for monochrome screen mode emulation */
                    123:     if (HBLPalettes[0])
                    124:     {
                    125:       sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 255;
                    126:       sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 0;
                    127:     }
                    128:     else
                    129:     {
                    130:       sdlColors[0].r = sdlColors[0].g = sdlColors[0].b = 0;
                    131:       sdlColors[1].r = sdlColors[1].g = sdlColors[1].b = 255;
                    132:     }
                    133:     SDL_SetColors(sdlscrn, sdlColors, 10, 2);
                    134:     /*SDL_SetColors(sdlscrn, sdlColors, 0, 2);*/
                    135:   }
                    136:   else
                    137:   {
1.1.1.11  root      138:       int r, g, b;
                    139:       /* Colors for STe color screen mode emulation */
                    140:       for (i=0; i<16; i++)
                    141:       {
                    142: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    143:         j = endiantable[i];
                    144: #else
                    145:         j = i;
                    146: #endif
                    147:         /* normalize all to 0x1e0 */
                    148:         r = HBLPalettes[i] >> 3;
                    149:         g = HBLPalettes[i] << 1;
                    150:         b = HBLPalettes[i] << 5;
                    151:         /* move top bit of 0x1e0 to lowest in 0xf0 */
                    152:         sdlColors[j].r = (r & 0xe0) | ((r & 0x100) >> 4);
                    153:         sdlColors[j].g = (g & 0xe0) | ((g & 0x100) >> 4);
                    154:         sdlColors[j].b = (b & 0xe0) | ((b & 0x100) >> 4);
                    155:       }
                    156:       SDL_SetColors(sdlscrn, sdlColors, 10, 16);
1.1.1.10  root      157:   }
                    158: }
                    159: 
                    160: 
                    161: /*-----------------------------------------------------------------------*/
                    162: /*
                    163:   Create 8-Bit palette for display if needed.
                    164: */
                    165: static void Screen_Handle8BitPalettes(void)
                    166: {
                    167:   BOOL bPaletteChanged=FALSE;
                    168:   int i;
                    169: 
                    170:   /* Do need to check for 8-Bit palette change? Ie, update whole screen */
                    171:   /* VDI screens and monochrome modes are ALL 8-Bit at the moment! */
                    172:   if (sdlscrn->format->BitsPerPixel == 8)
                    173:   {
                    174:     /* If using HiRes palette update with full update flag */
                    175:     if (!bUseHighRes)
                    176:     {
                    177:       /* Check if palette of 16 colours changed from previous frame */
                    178:       for (i=0; i<16 && !bPaletteChanged; i++)
                    179:       {
                    180:         /* Check with first line palette(stored in 'Screen_ComparePaletteMask') */
                    181:         if (HBLPalettes[i] != PrevHBLPalette[i])
                    182:           bPaletteChanged = TRUE;
                    183:       }
                    184:     }
                    185: 
                    186:     /* Did palette change or do we require a full update? */
                    187:     if (bPaletteChanged || pFrameBuffer->bFullUpdate)
                    188:     {
                    189:       /* Create palette, for Full-Screen of Window */
                    190:       Screen_CreatePalette();
                    191:       /* Make sure update whole screen */
                    192:       pFrameBuffer->bFullUpdate = TRUE;
                    193:     }
                    194:   }
                    195: 
                    196:   /* Copy old palette for 8-Bit compare as this routine writes over it */
1.1.1.11  root      197:   memcpy(PrevHBLPalette,HBLPalettes, sizeof(Uint16)*16);
1.1.1.10  root      198: }
                    199: 
1.1       root      200: 
                    201: /*-----------------------------------------------------------------------*/
                    202: /*
1.1.1.10  root      203:   Set screen draw functions.
1.1.1.7   root      204: */
1.1.1.10  root      205: static void Screen_SetDrawFunctions(void)
                    206: {
                    207:   switch (ConfigureParams.Screen.ChosenDisplayMode)
                    208:   {
                    209:     case DISPLAYMODE_LOWCOL_LOWRES:     /* low color, low resolution */
                    210:       ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x8Bit;
                    211:       ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x8Bit;
                    212:       ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    213:       ScreenDrawFunctionsNormal[ST_LOWMEDIUM_MIX_RES] = ConvertMediumRes_640x8Bit;
                    214:       break;
                    215:     case DISPLAYMODE_LOWCOL_HIGHRES:    /* low color, zoomed resolution */
                    216:       ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x8Bit;
                    217:       ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x8Bit;
                    218:       ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    219:       ScreenDrawFunctionsNormal[ST_LOWMEDIUM_MIX_RES] = ConvertMediumRes_640x8Bit;
                    220:       break;
                    221:     case DISPLAYMODE_HICOL_LOWRES:      /* high color, low resolution */
                    222:       ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_320x16Bit;
                    223:       ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x16Bit;
                    224:       ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    225:       ScreenDrawFunctionsNormal[ST_LOWMEDIUM_MIX_RES] = ConvertMediumRes_640x16Bit;
                    226:       break;
                    227:     case DISPLAYMODE_HICOL_HIGHRES:     /* high color, zoomed resolution */
                    228:       ScreenDrawFunctionsNormal[ST_LOW_RES] = ConvertLowRes_640x16Bit;
                    229:       ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = ConvertMediumRes_640x16Bit;
                    230:       ScreenDrawFunctionsNormal[ST_HIGH_RES] = ConvertHighRes_640x8Bit;
                    231:       ScreenDrawFunctionsNormal[ST_LOWMEDIUM_MIX_RES] = ConvertMediumRes_640x16Bit;
                    232:       break;
                    233:     default:
                    234:       fprintf(stderr, "Illegal display mode: %i\n", ConfigureParams.Screen.ChosenDisplayMode);
                    235:       ScreenDrawFunctionsNormal[ST_LOW_RES] = NULL;
                    236:       ScreenDrawFunctionsNormal[ST_MEDIUM_RES] = NULL;
                    237:       ScreenDrawFunctionsNormal[ST_HIGH_RES] = NULL;
                    238:       ScreenDrawFunctionsNormal[ST_LOWMEDIUM_MIX_RES] = NULL;
                    239:       break;
                    240:   }
                    241: }
                    242: 
                    243: 
                    244: /*-----------------------------------------------------------------------*/
                    245: /*
                    246:   Initialize SDL screen surface / set resolution.
                    247: */
                    248: static void Screen_SetResolution(void)
1.1.1.7   root      249: {
                    250:   int Width, Height, BitCount;
1.1.1.10  root      251:   unsigned int sdlVideoFlags;
1.1.1.7   root      252: 
1.1.1.10  root      253:   /* Determine which resolution to use */
1.1.1.9   root      254:   if (bUseVDIRes)
                    255:   {
1.1.1.7   root      256:     Width = VDIWidth;
                    257:     Height = VDIHeight;
1.1.1.9   root      258:   }
                    259:   else
                    260:   {
1.1.1.10  root      261:     if (STRes == ST_LOW_RES &&
                    262:         (ConfigureParams.Screen.ChosenDisplayMode == DISPLAYMODE_LOWCOL_LOWRES
                    263:          || ConfigureParams.Screen.ChosenDisplayMode == DISPLAYMODE_HICOL_LOWRES))
1.1.1.9   root      264:     {
1.1.1.10  root      265:       Width = 320;
                    266:       Height = 200;
                    267:     }
                    268:     else    /* else use 640x400 */
                    269:     {
                    270:       Width = 640;
                    271:       Height = 400;
1.1.1.9   root      272:     }
1.1.1.7   root      273: 
1.1.1.10  root      274:     /* Adjust width/height for overscan borders, if mono or VDI we have no overscan */
                    275:     if (ConfigureParams.Screen.bAllowOverscan && !bUseHighRes)
                    276:     {
                    277:       int nZoom = ((Width == 640) ? 2 : 1);
                    278:       /* Add in overscan borders (if 640x200 bitmap is double on Y) */
                    279:       Width += (OVERSCAN_LEFT+OVERSCAN_RIGHT) * nZoom;
                    280:       Height += (OVERSCAN_TOP+OVERSCAN_BOTTOM) * nZoom;
                    281:     }
1.1.1.7   root      282:   }
                    283: 
                    284:   /* Bits per pixel */
1.1.1.9   root      285:   if (ConfigureParams.Screen.ChosenDisplayMode == DISPLAYMODE_LOWCOL_LOWRES
                    286:       || ConfigureParams.Screen.ChosenDisplayMode == DISPLAYMODE_LOWCOL_HIGHRES
                    287:       || STRes == ST_HIGH_RES || bUseVDIRes)
1.1.1.7   root      288:   {
                    289:     BitCount = 8;
                    290:   }
                    291:   else
                    292:   {
                    293:     BitCount = 16;
                    294:   }
                    295: 
1.1.1.10  root      296:   /* SDL Video attributes: */
                    297:   if (bInFullScreen)
1.1.1.7   root      298:   {
1.1.1.10  root      299:     sdlVideoFlags  = SDL_HWSURFACE|SDL_FULLSCREEN|SDL_HWPALETTE/*|SDL_DOUBLEBUF*/;
                    300:     /* SDL_DOUBLEBUF is a good idea, but the GUI doesn't work with double buffered
                    301:      * screens yet, so double buffering is currently disabled. */
1.1.1.7   root      302:   }
                    303:   else
                    304:   {
1.1.1.10  root      305:     sdlVideoFlags  = SDL_SWSURFACE|SDL_HWPALETTE;
1.1.1.7   root      306:   }
                    307: 
1.1.1.12! root      308:   /* Check if we really have to change the video mode: */
        !           309:   if (sdlscrn && sdlscrn->w == Width && sdlscrn->h == Height
        !           310:       && sdlscrn->format->BitsPerPixel == BitCount
        !           311:       && (sdlscrn->flags&SDL_FULLSCREEN) == (sdlVideoFlags&SDL_FULLSCREEN))
        !           312:   {
        !           313:     return;
        !           314:   }
        !           315: 
1.1.1.10  root      316:   sdlscrn = SDL_SetVideoMode(Width, Height, BitCount, sdlVideoFlags);
                    317:   if (!sdlscrn)
1.1.1.7   root      318:   {
1.1.1.10  root      319:     fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    320:     SDL_Quit();
                    321:     exit(-2);
1.1.1.7   root      322:   }
1.1.1.10  root      323: 
                    324:   /* Re-init screen palette: */
                    325:   if (BitCount == 8)
                    326:     Screen_Handle8BitPalettes();    /* Initialize new 8 bit palette */
                    327:   else
                    328:     Screen_SetupRGBTable();         /* Create color convertion table */
                    329: 
                    330:   if (!bGrabMouse)
                    331:     SDL_WM_GrabInput(SDL_GRAB_OFF); /* Un-grab mouse pointer in windowed mode */
                    332: 
                    333:   Screen_SetDrawFunctions();        /* Set draw functions */
                    334:   Screen_SetFullUpdate();           /* Cause full update of screen */
1.1.1.7   root      335: }
                    336: 
1.1.1.8   root      337: 
1.1.1.7   root      338: /*-----------------------------------------------------------------------*/
                    339: /*
1.1.1.11  root      340:   Store Y offset for each horizontal line in our source ST screen for each reference in assembler(no multiply)
                    341: */
                    342: static void Screen_SetScreenLineOffsets(void)
                    343: {
                    344:   int i;
                    345: 
                    346:   for(i=0; i<NUM_VISIBLE_LINES; i++)
                    347:     STScreenLineOffset[i] = i * SCREENBYTES_LINE;
                    348: }
                    349: 
                    350: 
                    351: /*-----------------------------------------------------------------------*/
                    352: /*
1.1       root      353:   Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
                    354: */
                    355: void Screen_Init(void)
                    356: {
                    357:   int i;
                    358: 
                    359:   /* Clear frame buffer structures and set current pointer */
1.1.1.10  root      360:   memset(FrameBuffers, 0, NUM_FRAMEBUFFERS * sizeof(FRAMEBUFFER));
1.1       root      361: 
                    362:   /* Allocate previous screen check workspace. We are going to double-buffer a double-buffered screen. Oh. */
1.1.1.5   root      363:   for(i=0; i<NUM_FRAMEBUFFERS; i++)
                    364:   {
1.1.1.10  root      365:     FrameBuffers[i].pSTScreen = (unsigned char *)malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
                    366:     FrameBuffers[i].pSTScreenCopy = (unsigned char *)malloc(((MAX_VDI_WIDTH*MAX_VDI_PLANES)/8)*MAX_VDI_HEIGHT);
                    367:     if (!FrameBuffers[i].pSTScreen || !FrameBuffers[i].pSTScreenCopy)
                    368:     {
                    369:       fprintf(stderr, "Failed to allocate frame buffer memory.\n");
                    370:       exit(-1);
                    371:     }
1.1       root      372:   }
                    373:   pFrameBuffer = &FrameBuffers[0];
                    374: 
1.1.1.10  root      375:   Screen_SetResolution();
1.1       root      376: 
                    377:   Video_SetScreenRasters();                       /* Set rasters ready for first screen */
                    378: 
                    379:   Screen_SetScreenLineOffsets();                  /* Store offset to each horizontal line */
                    380: 
1.1.1.2   root      381:   /* Configure some SDL stuff: */
1.1       root      382:   SDL_WM_SetCaption(PROG_NAME, "Hatari");
                    383:   SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
                    384:   SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
                    385:   SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
1.1.1.4   root      386:   SDL_ShowCursor(SDL_DISABLE);
1.1       root      387: }
                    388: 
1.1.1.2   root      389: 
1.1       root      390: /*-----------------------------------------------------------------------*/
                    391: /*
                    392:   Free screen bitmap and allocated resources
                    393: */
                    394: void Screen_UnInit(void)
                    395: {
                    396:   int i;
                    397: 
1.1.1.3   root      398:   /* Free memory used for copies */
1.1.1.7   root      399:   for(i=0; i<NUM_FRAMEBUFFERS; i++)
                    400:   {
1.1.1.10  root      401:     free(FrameBuffers[i].pSTScreen);
                    402:     free(FrameBuffers[i].pSTScreenCopy);
1.1       root      403:   }
                    404: }
                    405: 
1.1.1.2   root      406: 
1.1       root      407: /*-----------------------------------------------------------------------*/
                    408: /*
                    409:   Reset screen
                    410: */
                    411: void Screen_Reset(void)
                    412: {
                    413:   /* On re-boot, always correct ST resolution for monitor, eg Colour/Mono */
1.1.1.5   root      414:   if (bUseVDIRes)
                    415:   {
1.1       root      416:     STRes = VDIRes;
                    417:   }
1.1.1.5   root      418:   else
                    419:   {
1.1       root      420:     if (bUseHighRes)
                    421:       STRes = ST_HIGH_RES;
                    422:     else
                    423:       STRes = ST_LOW_RES;
                    424:   }
                    425:   PrevSTRes = -1;
                    426:   /* Cause full update */
                    427:   Screen_SetFullUpdate();
                    428: }
                    429: 
                    430: 
                    431: /*-----------------------------------------------------------------------*/
                    432: /*
1.1.1.5   root      433:   Set flags so screen will be TOTALLY re-drawn (clears whole of full-screen)
                    434:   next time around
1.1       root      435: */
                    436: void Screen_SetFullUpdate(void)
                    437: {
                    438:   int i;
                    439: 
                    440:   /* Update frame buffers */
                    441:   for(i=0; i<NUM_FRAMEBUFFERS; i++)
                    442:     FrameBuffers[i].bFullUpdate = TRUE;
                    443: }
                    444: 
1.1.1.5   root      445: 
1.1       root      446: /*-----------------------------------------------------------------------*/
                    447: /*
1.1.1.11  root      448:   Clear Window display memory
                    449: */
                    450: static void Screen_ClearScreen(void)
                    451: {
                    452:   SDL_FillRect(sdlscrn,NULL, SDL_MapRGB(sdlscrn->format, 0, 0, 0) );
                    453: }
                    454: 
                    455: /*-----------------------------------------------------------------------*/
                    456: /*
1.1       root      457:   Enter Full screen mode
                    458: */
                    459: void Screen_EnterFullScreen(void)
                    460: {
1.1.1.5   root      461:   if (!bInFullScreen)
                    462:   {
1.1       root      463:     Main_PauseEmulation();        /* Hold things... */
1.1.1.2   root      464: 
1.1.1.10  root      465:     bInFullScreen = TRUE;
                    466:     Screen_SetResolution();
1.1       root      467: 
1.1.1.10  root      468:     SDL_Delay(20);                /* To give monitor time to change to new resolution */
                    469:     Screen_ClearScreen();         /* Black out screen bitmap as will be invalid when return */
1.1.1.2   root      470: 
1.1.1.10  root      471:     Main_UnPauseEmulation();      /* And off we go... */
1.1.1.3   root      472: 
1.1.1.4   root      473:     SDL_WM_GrabInput(SDL_GRAB_ON);  /* Grab mouse pointer in fullscreen */
1.1       root      474:   }
                    475: }
                    476: 
1.1.1.2   root      477: 
1.1       root      478: /*-----------------------------------------------------------------------*/
                    479: /*
                    480:   Return from Full screen mode back to a window
                    481: */
                    482: void Screen_ReturnFromFullScreen(void)
                    483: {
1.1.1.7   root      484:   if (bInFullScreen)
                    485:   {
1.1.1.2   root      486:     Main_PauseEmulation();        /* Hold things... */
                    487: 
                    488:     bInFullScreen = FALSE;
1.1.1.10  root      489:     Screen_SetResolution();
1.1.1.2   root      490: 
1.1.1.10  root      491:     SDL_Delay(20);                /* To give monitor time to switch resolution */
1.1.1.2   root      492: 
1.1.1.10  root      493:     Main_UnPauseEmulation();      /* And off we go... */
1.1       root      494:   }
                    495: }
                    496: 
1.1.1.5   root      497: 
1.1.1.2   root      498: /*-----------------------------------------------------------------------*/
1.1       root      499: /*
                    500:   Have we changes beteen low/medium/high res?
                    501: */
                    502: void Screen_DidResolutionChange(void)
                    503: {
1.1.1.2   root      504:   /* Did change res? */
1.1.1.5   root      505:   if (STRes!=PrevSTRes)
                    506:   {
1.1.1.10  root      507:     /* Set new display mode, if differs from current */
                    508:     Screen_SetResolution();
1.1       root      509:     PrevSTRes = STRes;
                    510:   }
                    511: 
1.1.1.2   root      512:   /* Did change overscan mode? Causes full update */
1.1.1.10  root      513:   if (pFrameBuffer->OverscanModeCopy != OverscanMode)
1.1       root      514:     pFrameBuffer->bFullUpdate = TRUE;
                    515: }
                    516: 
1.1.1.2   root      517: 
                    518: /*-----------------------------------------------------------------------*/
1.1       root      519: /*
                    520:   Compare current resolution on line with previous, and set 'UpdateLine' accordingly
                    521:   Also check if swap between low/medium resolution and return in 'bLowMedMix'
                    522: */
1.1.1.8   root      523: static void Screen_CompareResolution(int y, int *pUpdateLine, BOOL *pbLowMedMix)
1.1       root      524: {
                    525:   int Resolution;
                    526: 
1.1.1.2   root      527:   /* Check if wrote to resolution register */
1.1.1.7   root      528:   if (HBLPaletteMasks[y]&PALETTEMASK_RESOLUTION)  /* See 'Intercept_ShifterMode_WriteByte' */
                    529:   {
1.1       root      530:     Resolution = (HBLPaletteMasks[y]>>16)&0x1;
1.1.1.2   root      531:     /* Have used any low/medium res mix? */
1.1       root      532:     if (Resolution!=(STRes&0x1))
                    533:       *pbLowMedMix = TRUE;
1.1.1.2   root      534:     /* Did change resolution */
1.1       root      535:     if (Resolution!=(int)((pFrameBuffer->HBLPaletteMasks[y]>>16)&0x1))
                    536:       *pUpdateLine |= PALETTEMASK_UPDATERES;
                    537:     else
                    538:       *pUpdateLine &= ~PALETTEMASK_UPDATERES;
                    539:   }
                    540: }
                    541: 
1.1.1.7   root      542: 
1.1.1.2   root      543: /*-----------------------------------------------------------------------*/
1.1       root      544: /*
                    545:   Check to see if palette changes cause screen update and keep 'HBLPalette[]' up-to-date
                    546: */
1.1.1.8   root      547: static void Screen_ComparePalette(int y, int *pUpdateLine)
1.1       root      548: {
                    549:   BOOL bPaletteChanged = FALSE;
                    550:   int i;
                    551: 
1.1.1.2   root      552:   /* Did write to palette in this or previous frame? */
1.1.1.7   root      553:   if (((HBLPaletteMasks[y]|pFrameBuffer->HBLPaletteMasks[y])&PALETTEMASK_PALETTE)!=0)
                    554:   {
1.1.1.2   root      555:     /* Check and update ones which changed */
1.1.1.7   root      556:     for(i=0; i<16; i++)
                    557:     {
1.1.1.2   root      558:       if (HBLPaletteMasks[y]&(1<<i))        /* Update changes in ST palette */
1.1       root      559:         HBLPalette[i] = HBLPalettes[(y*16)+i];
                    560:     }
1.1.1.2   root      561:     /* Now check with same palette from previous frame for any differences(may be changing palette back) */
1.1.1.7   root      562:     for(i=0; (i<16) && (!bPaletteChanged); i++)
                    563:     {
1.1       root      564:       if (HBLPalette[i]!=pFrameBuffer->HBLPalettes[(y*16)+i])
                    565:         bPaletteChanged = TRUE;
                    566:     }
                    567:     if (bPaletteChanged)
                    568:       *pUpdateLine |= PALETTEMASK_UPDATEPAL;
                    569:     else
                    570:       *pUpdateLine &= ~PALETTEMASK_UPDATEPAL;
                    571:   }
                    572: }
                    573: 
1.1.1.7   root      574: 
1.1.1.2   root      575: /*-----------------------------------------------------------------------*/
1.1       root      576: /*
1.1.1.11  root      577:   Check for differences in Palette and Resolution from Mask table and update
                    578:   and store off which lines need updating and create full-screen palette.
                    579:   (It is very important for these routines to check for colour changes with
                    580:   the previous screen so only the very minimum parts are updated)
1.1       root      581: */
1.1.1.8   root      582: static int Screen_ComparePaletteMask(void)
1.1       root      583: {
                    584:   BOOL bLowMedMix=FALSE;
                    585:   int LineUpdate = 0;
                    586:   int y;
                    587: 
                    588:   /* Set for monochrome? */
1.1.1.7   root      589:   if (bUseHighRes)
                    590:   {
1.1       root      591:     OverscanMode = OVERSCANMODE_NONE;
                    592: 
1.1.1.11  root      593:     /* Just copy mono colours, 0x777 checked also in convert/vdi2.c */
                    594:     if (HBLPalettes[0] & 0x777)
1.1.1.7   root      595:     {
1.1.1.11  root      596:       HBLPalettes[0] = 0x777;
                    597:       HBLPalettes[1] = 0x000;
1.1       root      598:     }
1.1.1.7   root      599:     else
                    600:     {
1.1.1.11  root      601:       HBLPalettes[0] = 0x000;
                    602:       HBLPalettes[1] = 0x777;
1.1       root      603:     }
                    604: 
1.1.1.7   root      605:     /* Colors changed? */
                    606:     if (HBLPalettes[0] != PrevHBLPalette[0])
                    607:       pFrameBuffer->bFullUpdate = TRUE;
                    608: 
1.1       root      609:     /* Set bit to flag 'full update' */
                    610:     if (pFrameBuffer->bFullUpdate)
                    611:       ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
                    612:     else
                    613:       ScrUpdateFlag = 0x00000000;
                    614:   }
                    615: 
                    616:   /* Use VDI resolution? */
1.1.1.7   root      617:   if (bUseVDIRes)
                    618:   {
1.1       root      619:     /* Force to VDI resolution screen, without overscan */
                    620:     STRes = VDIRes;
                    621: 
1.1.1.7   root      622:     /* Colors changed? */
1.1       root      623:     if (HBLPalettes[0]!=PrevHBLPalette[0])
                    624:       pFrameBuffer->bFullUpdate = TRUE;
                    625: 
                    626:     /* Set bit to flag 'full update' */
                    627:     if (pFrameBuffer->bFullUpdate)
                    628:       ScrUpdateFlag = PALETTEMASK_UPDATEFULL;
                    629:     else
                    630:       ScrUpdateFlag = 0x00000000;
                    631:   }
                    632:   /* Are in Mono? Force to monochrome and no overscan */
1.1.1.7   root      633:   else if (bUseHighRes)
                    634:   {
1.1       root      635:     /* Force to standard hi-resolution screen, without overscan */
                    636:     STRes = ST_HIGH_RES;
                    637:   }
1.1.1.7   root      638:   else    /* Full colour */
                    639:   {
1.1       root      640:     /* Get resolution */
                    641:     STRes = (HBLPaletteMasks[0]>>16)&0x3;
                    642:     /* Do all lines - first is tagged as full-update */
1.1.1.7   root      643:     for(y=0; y<NUM_VISIBLE_LINES; y++)
                    644:     {
1.1       root      645:       /* Find any resolution/palette change and update palette/mask buffer */
                    646:       /* ( LineUpdate has top two bits set to say if line needs updating due to palette or resolution change ) */
                    647:       Screen_CompareResolution(y,&LineUpdate,&bLowMedMix);
                    648:       Screen_ComparePalette(y,&LineUpdate);
                    649:       HBLPaletteMasks[y] = (HBLPaletteMasks[y]&(~PALETTEMASK_UPDATEMASK)) | LineUpdate;
                    650:       /* Copy palette and mask for next frame */
                    651:       memcpy(&pFrameBuffer->HBLPalettes[y*16],HBLPalette,sizeof(short int)*16);
                    652:       pFrameBuffer->HBLPaletteMasks[y] = HBLPaletteMasks[y];
                    653:     }
                    654:     /* Did mix resolution? */
                    655:     if (bLowMedMix)
                    656:       STRes = ST_LOWMEDIUM_MIX_RES;
                    657:   }
                    658: 
                    659:   return(STRes);
                    660: }
                    661: 
1.1.1.3   root      662: 
1.1.1.2   root      663: /*-----------------------------------------------------------------------*/
1.1       root      664: /*
                    665:   Update Palette Mask to show 'full-update' required. This is usually done after a resolution change
                    666:   or when going between a Window and full-screen display
                    667: */
1.1.1.8   root      668: static void Screen_SetFullUpdateMask(void)
1.1       root      669: {
                    670:   int y;
                    671: 
                    672:   for(y=0; y<NUM_VISIBLE_LINES; y++)
                    673:     HBLPaletteMasks[y] |= PALETTEMASK_UPDATEFULL;
                    674: }
                    675: 
1.1.1.7   root      676: 
1.1.1.2   root      677: /*-----------------------------------------------------------------------*/
1.1       root      678: /*
1.1.1.10  root      679:   Set details for ST screen conversion.
1.1       root      680: */
1.1.1.10  root      681: static void Screen_SetConvertDetails(void)
1.1       root      682: {
1.1.1.3   root      683:   pSTScreen = pFrameBuffer->pSTScreen;          /* Source in ST memory */
                    684:   pSTScreenCopy = pFrameBuffer->pSTScreenCopy;  /* Previous ST screen */
1.1.1.8   root      685:   pPCScreenDest = sdlscrn->pixels;              /* Destination PC screen */
1.1.1.3   root      686: 
1.1.1.10  root      687:   PCScreenBytesPerLine = sdlscrn->pitch;        /* Bytes per line */
                    688:   pHBLPalettes = pFrameBuffer->HBLPalettes;     /* HBL palettes pointer */
                    689:   bScrDoubleY = !ConfigureParams.Screen.bInterleavedScreen; /* non-interleaved? => double up on Y */
1.1.1.5   root      690: 
1.1.1.10  root      691:   if (bUseVDIRes)
1.1.1.5   root      692:   {
1.1.1.10  root      693:     /* Select screen draw for standard or VDI display */
                    694:     STScreenLeftSkipBytes = 0;
                    695:     STScreenWidthBytes = VDIWidth * VDIPlanes / 8;
                    696:     STScreenStartHorizLine = 0;
                    697:     STScreenEndHorizLine = VDIHeight;
1.1       root      698:   }
                    699:   else
                    700:   {
1.1.1.10  root      701:     if (ConfigureParams.Screen.bAllowOverscan)  /* Use borders? */
1.1.1.5   root      702:     {
1.1.1.10  root      703:       /* Always draw to WHOLE screen including ALL borders */
                    704:       STScreenLeftSkipBytes = 0;                /* Number of bytes to skip on ST screen for left (border) */
                    705:       STScreenStartHorizLine = 0;               /* Full height */
                    706: 
                    707:       if (ConfigureParams.Screen.bUseHighRes)
                    708:       {
                    709:         pFrameBuffer->OverscanModeCopy = OverscanMode = OVERSCANMODE_NONE;
                    710:         STScreenEndHorizLine = 400;
                    711:       }
                    712:       else
                    713:       {
                    714:         STScreenWidthBytes = SCREENBYTES_LINE;  /* Number of horizontal bytes in our ST screen */
                    715:         STScreenEndHorizLine = NUM_VISIBLE_LINES;
                    716:       }
1.1.1.5   root      717:     }
                    718:     else
                    719:     {
1.1.1.10  root      720:       /* Only draw main area and centre on Y */
                    721:       STScreenLeftSkipBytes = SCREENBYTES_LEFT;
                    722:       STScreenWidthBytes = SCREENBYTES_MIDDLE;
                    723:       STScreenStartHorizLine = OVERSCAN_TOP;
                    724:       STScreenEndHorizLine = OVERSCAN_TOP + (bUseHighRes ? 400 : 200);
1.1       root      725:     }
                    726:   }
                    727: }
                    728: 
1.1.1.2   root      729: 
                    730: /*-----------------------------------------------------------------------*/
1.1       root      731: /*
                    732:   Lock full-screen for drawing
                    733: */
1.1.1.8   root      734: static BOOL Screen_Lock(void)
1.1       root      735: {
1.1.1.7   root      736:   if(SDL_MUSTLOCK(sdlscrn))
                    737:   {
                    738:     if(SDL_LockSurface(sdlscrn))
                    739:     {
1.1.1.2   root      740:       Screen_ReturnFromFullScreen();   /* All OK? If not need to jump back to a window */
1.1       root      741:       return(FALSE);
                    742:     }
                    743:   }
1.1.1.2   root      744: 
1.1       root      745:   return(TRUE);
                    746: }
                    747: 
1.1.1.2   root      748: /*-----------------------------------------------------------------------*/
1.1       root      749: /*
                    750:   UnLock full-screen
                    751: */
1.1.1.8   root      752: static void Screen_UnLock(void)
1.1       root      753: {
1.1.1.2   root      754:   if( SDL_MUSTLOCK(sdlscrn) )
1.1.1.3   root      755:     SDL_UnlockSurface(sdlscrn);
1.1       root      756: }
                    757: 
1.1.1.2   root      758: 
                    759: /*-----------------------------------------------------------------------*/
1.1       root      760: /*
1.1.1.11  root      761:   Swap ST Buffers, used for full-screen where have double-buffering
                    762: */
                    763: static void Screen_SwapSTBuffers(void)
                    764: {
                    765: #if NUM_FRAMEBUFFERS > 1
                    766:   if (sdlscrn->flags & SDL_DOUBLEBUF)
                    767:   {
                    768:     if (pFrameBuffer==&FrameBuffers[0])
                    769:       pFrameBuffer = &FrameBuffers[1];
                    770:     else
                    771:       pFrameBuffer = &FrameBuffers[0];
                    772:   }
                    773: #endif
                    774: }
                    775: 
                    776: 
                    777: /*-----------------------------------------------------------------------*/
                    778: /*
1.1       root      779:   Blit our converted ST screen to window/full-screen
1.1.1.3   root      780:   Note that our source image includes all borders so if have them disabled simply blit a smaller source rectangle!
1.1       root      781: */
1.1.1.11  root      782: static void Screen_Blit(BOOL bSwapScreen)
1.1       root      783: {
1.1.1.3   root      784:   /* Rectangle areas to Blit according to if overscan is enabled or not (source always includes all borders) */
1.1.1.7   root      785: /*   static SDL_Rect SrcWindowBitmapSizes[] = */
                    786: /*   { */
                    787: /*     { OVERSCAN_LEFT,OVERSCAN_TOP, 320,200 },                /\* ST_LOW_RES *\/ */
                    788: /*     { (OVERSCAN_LEFT<<1),(OVERSCAN_TOP<<1), 640,400 },      /\* ST_MEDIUM_RES *\/ */
                    789: /*     { 0,0, 640,400 },                                       /\* ST_HIGH_RES *\/ */
                    790: /*     { (OVERSCAN_LEFT<<1),(OVERSCAN_BOTTOM<<1), 640,400 },   /\* ST_LOWMEDIUM_MIX_RES *\/ */
                    791: /*   }; */
1.1.1.12! root      792:   static const SDL_Rect SrcWindowBitmapSizes[] =
1.1.1.7   root      793:   {
                    794:     { 0,0, 320,200 },                /* ST_LOW_RES */
                    795:     { 0,0, 640,400 },      /* ST_MEDIUM_RES */
1.1.1.5   root      796:     { 0,0, 640,400 },                                       /* ST_HIGH_RES */
1.1.1.7   root      797:     { 0,0, 640,400 },   /* ST_LOWMEDIUM_MIX_RES */
1.1       root      798:   };
1.1.1.7   root      799: 
1.1.1.12! root      800:   static const SDL_Rect SrcWindowOverscanBitmapSizes[] =
1.1.1.7   root      801:   {
1.1.1.5   root      802:     { 0,0, OVERSCAN_LEFT+320+OVERSCAN_RIGHT,OVERSCAN_TOP+200+OVERSCAN_BOTTOM },
                    803:     { 0,0, (OVERSCAN_LEFT<<1)+640+(OVERSCAN_RIGHT<<1),(OVERSCAN_TOP<<1)+400+(OVERSCAN_BOTTOM<<1) },
                    804:     { 0,0, 640,400 },
                    805:     { 0,0, (OVERSCAN_LEFT<<1)+640+(OVERSCAN_RIGHT<<1),(OVERSCAN_TOP<<1)+400+(OVERSCAN_BOTTOM<<1) },
1.1       root      806:   };
1.1.1.3   root      807: 
1.1.1.10  root      808:   unsigned char *pTmpScreen;
1.1.1.12! root      809:   const SDL_Rect *SrcRect;
1.1       root      810: 
1.1.1.3   root      811:   /* Blit to full screen or window? */
1.1.1.7   root      812:   if (bInFullScreen)
                    813:   {
1.1.1.11  root      814:     Screen_SwapSTBuffers();
1.1.1.3   root      815:     /* Swap screen */
1.1       root      816:     if (bSwapScreen)
1.1.1.3   root      817:       SDL_Flip(sdlscrn);
1.1       root      818:   }
1.1.1.7   root      819:   else
                    820:   {
1.1.1.3   root      821:     /* VDI resolution? */
1.1.1.7   root      822:     if (bUseVDIRes || ConfigureParams.Screen.bUseHighRes)
                    823:     {
1.1.1.3   root      824:       /* Show VDI or mono resolution, no overscan */
                    825:       SDL_UpdateRect(sdlscrn, 0,0,0,0);
1.1       root      826:     }
1.1.1.7   root      827:     else
                    828:     {
                    829:       /* Find rectangle to draw from... */
                    830:       if (ConfigureParams.Screen.bAllowOverscan)
                    831:         SrcRect = &SrcWindowOverscanBitmapSizes[STRes];
                    832:       else
                    833:         SrcRect = &SrcWindowBitmapSizes[STRes];
                    834: 
                    835:       /* Blit image */
                    836:       SDL_UpdateRect(sdlscrn, 0,0,0,0);
1.1.1.10  root      837:       //SDL_UpdateRects(sdlscrn, 1, SrcRect);  /* FIXME */
1.1       root      838:     }
                    839:   }
                    840: 
1.1.1.3   root      841:   /* Swap copy/raster buffers in screen. */
1.1.1.10  root      842:   pTmpScreen = pFrameBuffer->pSTScreenCopy;
1.1       root      843:   pFrameBuffer->pSTScreenCopy = pFrameBuffer->pSTScreen;
1.1.1.10  root      844:   pFrameBuffer->pSTScreen = pTmpScreen;
1.1       root      845: }
                    846: 
1.1.1.3   root      847: 
1.1.1.2   root      848: /*-----------------------------------------------------------------------*/
1.1       root      849: /*
                    850:   Draw ST screen to window/full-screen framebuffer
                    851: */
1.1.1.11  root      852: static void Screen_DrawFrame(BOOL bForceFlip)
1.1       root      853: {
1.1.1.12! root      854:   void (*pDrawFunction)(void);
1.1       root      855: 
1.1.1.2   root      856:   /* Scan palette/resolution masks for each line and build up palette/difference tables */
1.1       root      857:   STRes = Screen_ComparePaletteMask();
1.1.1.2   root      858:   /* Do require palette? Check if changed and update */
1.1       root      859:   Screen_Handle8BitPalettes();
1.1.1.2   root      860:   /* Did we change resolution this frame - allocate new screen if did so */
1.1       root      861:   Screen_DidResolutionChange();
1.1.1.2   root      862:   /* Is need full-update, tag as such */
1.1       root      863:   if (pFrameBuffer->bFullUpdate)
                    864:     Screen_SetFullUpdateMask();
                    865: 
                    866:   /* Lock screen ready for drawing */
1.1.1.10  root      867:   if (Screen_Lock())
                    868:   {
                    869:     bScreenContentsChanged = FALSE;      /* Did change (ie needs blit?) */
1.1.1.7   root      870:     /* Set details */
1.1.1.10  root      871:     Screen_SetConvertDetails();
1.1.1.9   root      872:     /* Clear screen on full update to clear out borders and also interleaved lines */
1.1.1.7   root      873:     if (pFrameBuffer->bFullUpdate && !bUseVDIRes)
                    874:       Screen_ClearScreen();
                    875:     /* Call drawing for full-screen */
1.1.1.10  root      876:     if (bUseVDIRes)
                    877:     {
                    878:       pDrawFunction = ScreenDrawFunctionsVDI[VDIRes];
1.1       root      879:     }
1.1.1.10  root      880:     else
                    881:     {
                    882:       pDrawFunction = ScreenDrawFunctionsNormal[STRes];
1.1.1.7   root      883:       /* Check if is Spec512 image */
1.1.1.10  root      884:       if (Spec512_IsImage())
                    885:       {
                    886:         /* What mode were we in? Keep to 320xH or 640xH */
                    887:         if (pDrawFunction==ConvertLowRes_320x16Bit)
                    888:           pDrawFunction = ConvertSpec512_320x16Bit;
                    889:         else if (pDrawFunction==ConvertLowRes_640x16Bit)
                    890:           pDrawFunction = ConvertSpec512_640x16Bit;
1.1       root      891:       }
                    892:     }
                    893: 
1.1.1.7   root      894:     if (pDrawFunction)
                    895:       CALL_VAR(pDrawFunction)
                    896: 
1.1.1.2   root      897:     /* Unlock screen */
1.1       root      898:     Screen_UnLock();
1.1.1.2   root      899:     /* Clear flags, remember type of overscan as if change need screen full update */
1.1       root      900:     pFrameBuffer->bFullUpdate = FALSE;
                    901:     pFrameBuffer->OverscanModeCopy = OverscanMode;
                    902: 
1.1.1.2   root      903:     /* And show to user */
1.1.1.10  root      904:     if (bScreenContentsChanged || bForceFlip)
1.1       root      905:       Screen_Blit(TRUE);
                    906: 
1.1.1.3   root      907:     /* Grab any animation */
                    908:     if(bRecordingAnimation)
1.1       root      909:       ScreenSnapShot_RecordFrame(bScreenContentsChanged);
                    910:   }
                    911: }
                    912: 
1.1.1.9   root      913: 
1.1.1.2   root      914: /*-----------------------------------------------------------------------*/
1.1       root      915: /*
                    916:   Draw ST screen to window/full-screen
                    917: */
                    918: void Screen_Draw(void)
                    919: {
1.1.1.5   root      920:   if (!bQuitProgram)
                    921:   {
                    922:     if(VideoBase)
1.1       root      923:     {
                    924:       /* And draw(if screen contents changed) */
                    925:       Screen_DrawFrame(FALSE);
                    926: 
                    927:       /* And status bar */
1.1.1.4   root      928:       /*StatusBar_UpdateIcons();*/ /* Sorry - no statusbar in Hatari yet */
1.1       root      929:     }
                    930: 
1.1.1.2   root      931:     /* Check printer status */
1.1       root      932:     Printer_CheckIdleStatus();
                    933:   }
                    934: }
1.1.1.11  root      935: 
                    936: 
                    937: /* -------------- screen conversion routines --------------------------------
                    938:   Screen conversion routines. We have a number of routines to convert ST screen
                    939:   to PC format. We split these into Low, Medium and High each with 8/16-bit
                    940:   versions. To gain extra speed, as almost half of the processing time can be
                    941:   spent in these routines, we check for any changes from the previously
                    942:   displayed frame. AdjustLinePaletteRemap() sets a flag to tell the routines
                    943:   if we need to totally update a line (ie full update, or palette/res change)
                    944:   or if we just can do a difference check.
                    945:   We convert each screen 16 pixels at a time by use of a couple of look-up
                    946:   tables. These tables convert from 2-plane format to bbp and then we can add
                    947:   two of these together to get 4-planes. This keeps the tables small and thus
                    948:   improves speed. We then look these bbp values up as an RGB/Index value to
                    949:   copy to the screen.
                    950: */
                    951: 
                    952: 
                    953: /*-----------------------------------------------------------------------
                    954:  * Update the STRGBPalette[] array with current colours for this raster line.
                    955:  *
                    956:  * Return 'ScrUpdateFlag', 0x80000000=Full update, 0x40000000=Update
                    957:  * as palette changed
                    958:  */
                    959: static int AdjustLinePaletteRemap(int y)
                    960: {
                    961: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    962:   static const int endiantable[16] = {0,2,1,3,8,10,9,11,4,6,5,7,12,14,13,15};
                    963: #endif
                    964:   Uint16 *actHBLPal;
                    965:   int i;
                    966: 
                    967:   /* Copy palette and convert to RGB in display format */
                    968:   actHBLPal = pHBLPalettes + (y<<4);    /* offset in palette */
                    969:   for(i=0; i<16; i++)
                    970:    {
                    971: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    972:     STRGBPalette[endiantable[i]] = ST2RGB[*actHBLPal++];
                    973: #else
                    974:     STRGBPalette[i] = ST2RGB[*actHBLPal++];
                    975: #endif
                    976:    }
                    977:   ScrUpdateFlag = HBLPaletteMasks[y];
                    978:   return ScrUpdateFlag;
                    979: }
                    980: 
                    981: 
                    982: /*-----------------------------------------------------------------------
                    983:  * Run updates to palette(STRGBPalette[]) until get to screen line
                    984:  * we are to convert from
                    985:  */
                    986: static void Convert_StartFrame(void)
                    987: {
                    988:   int y = 0;
                    989:   /* Get #lines before conversion starts */
                    990:   int lines = STScreenStartHorizLine;
                    991:   while (lines--)
                    992:     AdjustLinePaletteRemap(y++);     /* Update palette */
                    993: }
                    994: 
                    995: /* lookup tables and conversion macros */
                    996: #include "convert/macros.h"
                    997: 
                    998: /* Conversion routines */
                    999: #include "convert/low320x16.c"    /* LowRes To 320xH x 16-bit colour */
                   1000: #include "convert/low640x16.c"    /* LowRes To 640xH x 16-bit colour */
                   1001: #include "convert/med640x16.c"    /* MediumRes To 640xH x 16-bit colour */
                   1002: #include "convert/low320x8.c"     /* LowRes To 320xH x 8-bit colour */
                   1003: #include "convert/low640x8.c"     /* LowRes To 640xH x 8-bit colour */
                   1004: #include "convert/med640x8.c"     /* MediumRes To 640xH x 8-bit colour */
                   1005: #include "convert/high640x8.c"    /* HighRes To 640xH x 8-bit colour */
                   1006: #include "convert/high640x1.c"    /* HighRes To 640xH x 1-bit colour */
                   1007: #include "convert/spec320x16.c"   /* Spectrum 512 To 320xH x 16-bit colour */
                   1008: #include "convert/spec640x16.c"   /* Spectrum 512 To 640xH x 16-bit colour */
                   1009: 
                   1010: #include "convert/vdi16.c"        /* VDI x 16 colour */
                   1011: #include "convert/vdi4.c"         /* VDI x 4 colour */
                   1012: #include "convert/vdi2.c"         /* VDI x 2 colour */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.