Annotation of frontvm/hardware/screen.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - screen.c
                      3: 
                      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
                      8:   format. An awful lost of processing is needed to do this conversion - we
                      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.
                     21: */
                     22: 
                     23: #include <SDL.h>
                     24: 
                     25: #include "main.h"
                     26: #include "configuration.h"
                     27: #include "m68000.h"
                     28: #include "memAlloc.h"
                     29: #include "misc.h"
                     30: #include "screen.h"
                     31: #include "screenConvert.h"
                     32: #include "video.h"
                     33: #include "scalebit.h"
                     34: 
                     35: int len_main_palette;
                     36: unsigned short MainPalette[256];
                     37: unsigned short CtrlPalette[16];
                     38: 
                     39: SCREENDRAW ScreenDraw;                   /* Set up with details of drawing functions  */
                     40: unsigned char *pScreenBitmap=NULL;                /* Screen pixels in PC RGB format, allocated with 'CreateDIBSection' */
                     41: unsigned char *pPCScreenDest;                     /* Destination PC buffer */
                     42: int STScreenStartHorizLine,STScreenEndHorizLine;  /* Start/End lines to be converted */
                     43: int PCScreenBytesPerLine, STScreenWidthBytes, STScreenLeftSkipBytes;
                     44: BOOL bInFullScreen=FALSE;                         /* TRUE if in full screen */
                     45: BOOL bFullScreenHold = FALSE;                     /* TRUE if hold display while full screen */
                     46: BOOL bScreenContentsChanged;                      /* TRUE if buffer changed and requires blitting */
                     47: BOOL bTooSlowSoSkipAFlip = FALSE;
                     48: int nDroppedFrames=0;                             /* Number of dropped frames during emulation run */
                     49: int prevChosenDisplayMode = -1;
                     50: 
                     51: int STScreenLineOffset[SCREEN_HEIGHT_HBL];        /* Offsets for ST screen lines eg, 0,160,320... */
                     52: unsigned long MainRGBPalette[256];
                     53: unsigned long CtrlRGBPalette[16];
                     54: 
                     55: SDL_Surface *sdlscrn;                             /* The SDL screen surface */
                     56: BOOL bGrabMouse = FALSE;                          /* Grab the mouse cursor in the window */
                     57: 
                     58: 
                     59: /*-----------------------------------------------------------------------*/
                     60: /*
                     61:   Set window size
                     62: */
                     63: void Screen_SetWindowRes()
                     64: {
                     65:   prevChosenDisplayMode = ConfigureParams.Screen.ChosenDisplayMode;
                     66:   switch (ConfigureParams.Screen.ChosenDisplayMode) {
                     67:          case DISPLAYMODE_HICOL_1X:
                     68:                sdlscrn=SDL_SetVideoMode(320, 200, 16, SDL_DOUBLEBUF | SDL_ANYFORMAT);
                     69:                break;
                     70:          default:
                     71:                sdlscrn=SDL_SetVideoMode(640, 400, 16, SDL_DOUBLEBUF | SDL_ANYFORMAT);
                     72:                break;
                     73:   }
                     74:   if ((sdlscrn == NULL) || (sdlscrn->format->BytesPerPixel < 2))
                     75:   {
                     76:     fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                     77:     SDL_Quit();
                     78:     exit(-2);
                     79:   }
                     80:   pScreenBitmap=sdlscrn->pixels;
                     81: 
                     82:   if(!bGrabMouse)
                     83:   {
                     84:     SDL_WM_GrabInput(SDL_GRAB_OFF);  /* Un-grab mouse pointer in windowed mode */
                     85:   }
                     86:   Screen_SetDrawModes();        /* Set draw modes(store which modes to use!) */
                     87: }
                     88: 
                     89: /*-----------------------------------------------------------------------*/
                     90: /*
                     91:   Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
                     92: */
                     93: void Screen_Init(void)
                     94: {
                     95:   Screen_SetWindowRes();
                     96: 
                     97:   Screen_SetScreenLineOffsets();                  /* Store offset to each horizontal line */
                     98: 
                     99:   /* Configure some SDL stuff: */
                    100:   SDL_WM_SetCaption(PROG_NAME, "Frontier");
                    101:   SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
                    102:   SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
                    103:   SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
                    104:   SDL_ShowCursor(SDL_DISABLE);
                    105: }
                    106: 
                    107: 
                    108: /*-----------------------------------------------------------------------*/
                    109: /*
                    110:   Free screen bitmap and allocated resources
                    111: */
                    112: void Screen_UnInit(void)
                    113: {
                    114: }
                    115: 
                    116: 
                    117: /*-----------------------------------------------------------------------*/
                    118: /*
                    119:   Reset screen
                    120: */
                    121: void Screen_Reset(void)
                    122: {
                    123: }
                    124: 
                    125: /*-----------------------------------------------------------------------*/
                    126: /*
                    127:   Store Y offset for each horizontal line in our source ST screen for each reference in assembler(no multiply)
                    128: */
                    129: void Screen_SetScreenLineOffsets(void)
                    130: {
                    131:   int i;
                    132: 
                    133:   for(i=0; i<SCREEN_HEIGHT_HBL; i++)
                    134:     STScreenLineOffset[i] = i * SCREENBYTES_LINE;
                    135: }
                    136: 
                    137: 
                    138: /*-----------------------------------------------------------------------*/
                    139: 
                    140: /*-----------------------------------------------------------------------*/
                    141: /*
                    142:   Enter Full screen mode
                    143: */
                    144: 
                    145: static SDL_Surface *set_new_sdl_fsmode() {
                    146:   SDL_Surface *newsdlscrn;
                    147: 
                    148:     newsdlscrn = SDL_SetVideoMode(sdlscrn->w, sdlscrn->h,
                    149:                ScreenDraw.BitDepth, SDL_DOUBLEBUF | SDL_ANYFORMAT | SDL_FULLSCREEN);
                    150:   return newsdlscrn;
                    151: }
                    152: 
                    153: void Screen_EnterFullScreen(void)
                    154: {
                    155:   SDL_Surface *newsdlscrn;
                    156: 
                    157:   if (!bInFullScreen)
                    158:   {
                    159:     Main_PauseEmulation();        /* Hold things... */
                    160:     SDL_Delay(20);                /* To give sound time to clear! */
                    161: 
                    162:     newsdlscrn = set_new_sdl_fsmode();
                    163:     Screen_SetDrawModes();        /* Set draw modes(store which modes to use!) */
                    164: 
                    165:     if( newsdlscrn==NULL )
                    166:     {
                    167:       fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
                    168:     }
                    169:     else
                    170:     {
                    171:       sdlscrn = newsdlscrn;
                    172:       pScreenBitmap = newsdlscrn->pixels;
                    173:       bInFullScreen = TRUE;
                    174: 
                    175:       Screen_ClearScreen();         /* Black out screen bitmap as will be invalid when return */
                    176:     }
                    177:     Main_UnPauseEmulation();        /* And off we go... */
                    178: 
                    179:     SDL_WM_GrabInput(SDL_GRAB_ON);  /* Grab mouse pointer in fullscreen */
                    180:   }
                    181: }
                    182: 
                    183: 
                    184: /*-----------------------------------------------------------------------*/
                    185: /*
                    186:   Return from Full screen mode back to a window
                    187: */
                    188: void Screen_ReturnFromFullScreen(void)
                    189: {
                    190:   if (bInFullScreen)
                    191:   {
                    192:     Main_PauseEmulation();        /* Hold things... */
                    193:     SDL_Delay(20);                /* To give sound time to clear! */
                    194: 
                    195:     bInFullScreen = FALSE;
                    196: 
                    197:     Screen_SetWindowRes();
                    198:     Screen_SetDrawModes();
                    199: 
                    200:     Main_UnPauseEmulation();          /* And off we go... */
                    201:   }
                    202: }
                    203: 
                    204: 
                    205: /*-----------------------------------------------------------------------*/
                    206: /*
                    207:   Clear Window display memory
                    208: */
                    209: void Screen_ClearScreen(void)
                    210: {
                    211:   SDL_FillRect(sdlscrn,NULL, SDL_MapRGB(sdlscrn->format, 0, 0, 0) );
                    212: }
                    213: 
                    214: /*-----------------------------------------------------------------------*/
                    215: /*
                    216: */
                    217: void Screen_SetDrawModes(void)
                    218: {
                    219:   /* Clear out */
                    220:   Memory_Clear(&ScreenDraw,sizeof(SCREENDRAW));
                    221: 
                    222:   ScreenDraw.pDrawFunction = screendrawfuncs[sdlscrn->format->BytesPerPixel][ConfigureParams.Screen.ChosenDisplayMode];
                    223:   /* Assign full-screen draw modes from chosen option under dialog */
                    224:   switch (ConfigureParams.Screen.ChosenDisplayMode) {
                    225: 
                    226:        case DISPLAYMODE_HICOL_1X:
                    227:                ScreenDraw.Width = 320;
                    228:                ScreenDraw.Height = 200;
                    229:                ScreenDraw.BitDepth = sdlscrn->format->BitsPerPixel;
                    230:                ScreenDraw.VertPixelsPerLine = 1;
                    231:                ScreenDraw.PCStartHorizLine = 0;
                    232:                ScreenDraw.MouseScale = 1;
                    233:                break;
                    234:        case DISPLAYMODE_HICOL_2X:
                    235:        default:
                    236:                ScreenDraw.Width = 640;
                    237:                ScreenDraw.Height = 480;
                    238:                ScreenDraw.BitDepth = sdlscrn->format->BitsPerPixel;
                    239:                ScreenDraw.VertPixelsPerLine = 2;
                    240:                ScreenDraw.PCStartHorizLine = 0;
                    241:                ScreenDraw.MouseScale = 2;
                    242:                break;
                    243:   }
                    244: }
                    245: 
                    246: 
                    247: /*-----------------------------------------------------------------------*/
                    248: /*
                    249:   Set details for ST screen conversion(Window version)
                    250: */
                    251: void Screen_SetWindowConvertDetails(void)
                    252: {
                    253:   pPCScreenDest = pScreenBitmap;                /* Destination PC screen */
                    254: 
                    255:   STScreenStartHorizLine = 0;                   /* Full height */
                    256: 
                    257:     /* Always draw to WHOLE screen including ALL borders */
                    258:     STScreenLeftSkipBytes = 0;                  /* Number of bytes to skip on ST screen for left(border) */
                    259:     STScreenWidthBytes = SCREENBYTES_LINE;      /* Number of horizontal bytes in our ST screen */
                    260: 
                    261:     STScreenEndHorizLine = SCREEN_HEIGHT_HBL;
                    262: 
                    263:       PCScreenBytesPerLine = sdlscrn->pitch;
                    264: }
                    265: 
                    266: /*-----------------------------------------------------------------------*/
                    267: /*
                    268:   Set details for ST screen conversion (Full-Screen version)
                    269: */
                    270: void Screen_SetFullScreenConvertDetails(void)
                    271: {
                    272:   /* Only draw what can fit into full-screen and centre on Y */
                    273:   STScreenLeftSkipBytes = 0;
                    274:   STScreenWidthBytes = SCREENBYTES_LINE;
                    275: 
                    276:   STScreenStartHorizLine = 0;
                    277:   STScreenEndHorizLine = SCREEN_HEIGHT_HBL;
                    278: 
                    279:   PCScreenBytesPerLine = sdlscrn->pitch;
                    280:   pPCScreenDest = (unsigned char *)sdlscrn->pixels;  /* Destination PC screen */
                    281:   /* And offset on X */
                    282:  // pPCScreenDest += ScreenDraw.PCStartXOffset;
                    283:   //pPCScreenDest += ScreenDraw.PCStartHorizLine * PCScreenBytesPerLine;
                    284: 
                    285:   /* Is non-interlaced? May need to double up on Y */
                    286:     bScrDoubleY = TRUE;
                    287: }
                    288: 
                    289: 
                    290: /*-----------------------------------------------------------------------*/
                    291: /*
                    292:   Lock full-screen for drawing
                    293: */
                    294: BOOL Screen_Lock(void)
                    295: {
                    296:   if(SDL_MUSTLOCK(sdlscrn))
                    297:   {
                    298:     if(SDL_LockSurface(sdlscrn))
                    299:     {
                    300:       Screen_ReturnFromFullScreen();   /* All OK? If not need to jump back to a window */
                    301:       return(FALSE);
                    302:     }
                    303:   }
                    304: 
                    305:   return(TRUE);
                    306: }
                    307: 
                    308: /*-----------------------------------------------------------------------*/
                    309: /*
                    310:   UnLock full-screen
                    311: */
                    312: void Screen_UnLock(void)
                    313: {
                    314:   if( SDL_MUSTLOCK(sdlscrn) )
                    315:     SDL_UnlockSurface(sdlscrn);
                    316: }
                    317: 
                    318: 
                    319: /*-----------------------------------------------------------------------*/
                    320: /*
                    321:   Draw ST screen to window/full-screen framebuffer
                    322: */
                    323: void Screen_DrawFrame(BOOL bForceFlip)
                    324: {
                    325:   void *pDrawFunction;
                    326: 
                    327:   if ((!ConfigureParams.Screen.bFullScreen) &&
                    328:       (prevChosenDisplayMode != ConfigureParams.Screen.ChosenDisplayMode))
                    329:          Screen_SetWindowRes ();
                    330: 
                    331:   //if (!bScreenContentsChanged) return;
                    332:   if (bTooSlowSoSkipAFlip) {
                    333:          bTooSlowSoSkipAFlip = FALSE;
                    334:          return;
                    335:   }
                    336:   
                    337:   /* Lock screen ready for drawing */
                    338:   if (Screen_Lock()) {
                    339:     bScreenContentsChanged = FALSE;
                    340:     /* Set details */
                    341:     if (bInFullScreen) 
                    342:            Screen_SetFullScreenConvertDetails();
                    343:     else
                    344:            Screen_SetWindowConvertDetails();
                    345:     /* Call drawing for full-screen */
                    346:       pDrawFunction = ScreenDraw.pDrawFunction;
                    347:     
                    348:     /* build RGB palettes */
                    349:     BuildRGBPalette (MainRGBPalette, MainPalette, len_main_palette);
                    350:     BuildRGBPalette (CtrlRGBPalette, CtrlPalette, 16);
                    351:       
                    352:     if (pDrawFunction)
                    353:       CALL_VAR(pDrawFunction)
                    354: 
                    355:     /* Unlock screen */
                    356:     Screen_UnLock();
                    357: 
                    358:     SDL_Flip(sdlscrn);
                    359:   }
                    360: }
                    361: 
                    362: /*-----------------------------------------------------------------------*/
                    363: /*
                    364:   Draw ST screen to window/full-screen
                    365:   This is now called from the 68k program's vblank handler,
                    366:   since we need the vblank to update palettes appropriately
                    367:   before drawing the screen (for frontier)
                    368: */
                    369: void Screen_Draw(unsigned long _dummy)
                    370: {
                    371:   /* Are we holding screen? Ie let user choose options while in full-screen mode using GDI */
                    372:   if (bInFullScreen && bFullScreenHold)
                    373:   {
                    374:     return;
                    375:   }
                    376: 
                    377:   if (!bQuitProgram)
                    378:   {
                    379:     if(VideoBase)
                    380:     {
                    381:       Screen_DrawFrame(FALSE);
                    382:     }
                    383:   }
                    384: 
                    385: }

unix.superglobalmegacorp.com

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