Annotation of frontvm/hardware/screen.c, revision 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.