Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

swimp_rhap.m (12234B)


      1 #import <AppKit/AppKit.h>
      2 #import <Interceptor/NSDirectScreen.h>
      3 #import <AppKit/NSColor.h>
      4 #include "../ref_soft/r_local.h"
      5 
      6 @interface QuakeView : NSView
      7 @end
      8 
      9 NSWindow	*vid_window_i;
     10 QuakeView	*vid_view_i;
     11 NSDirectScreen *vid_screen;
     12 byte		*vid_buffer;		// real framebuffer
     13 int			vid_rowbytes;		// framebuffer rowbytes
     14 
     15 unsigned	*buffernative;		// 24 bit off-screen back buffer for window
     16 unsigned	swimp_palette[256];
     17 
     18 typedef enum {
     19     rhap_shutdown,
     20     rhap_windowed,
     21     rhap_fullscreen
     22 } rhapMode_t;
     23 
     24 rhapMode_t	rhap_mode;
     25 
     26 /*
     27 =======================================================================
     28 
     29 FULLSCREEN
     30 
     31 =======================================================================
     32 */
     33 
     34 /*
     35 ** InitFullscreen
     36 */
     37 rserr_t InitFullscreen (int width, int height)
     38 {
     39     NSDictionary *mode, *bestMode;
     40     int			modeWidth, bestWidth;
     41     int			modeHeight, bestHeight;
     42 	NSArray		*modes;
     43     int			i;
     44 	NSString	*string;
     45 
     46     
     47     vid_screen = [[NSDirectScreen alloc] initWithScreen:[NSScreen mainScreen]];
     48 
     49     // search for an apropriate mode
     50     modes = [vid_screen availableDisplayModes];
     51     bestMode = NULL;
     52     bestWidth = 99999;
     53     bestHeight = 99999;
     54    	for (i=0 ; i<[modes count] ; i++) {
     55         mode = [modes objectAtIndex: i];
     56         string = [mode objectForKey: @"NSDirectScreenPixelEncoding"];
     57         if ( ![string isEqualToString: @"PPPPPPPP"] )
     58             continue;	// only look at paletted modes
     59         modeWidth = [[mode objectForKey: @"NSDirectScreenWidth"] intValue];
     60         modeHeight = [[mode objectForKey: @"NSDirectScreenHeight"] intValue];
     61         if (modeWidth < width || modeHeight < height)
     62             continue;
     63         if (modeWidth < bestWidth) {
     64             bestWidth = modeWidth;
     65             bestHeight = modeHeight;
     66             bestMode = mode;
     67         }
     68     } 
     69 
     70     // if there wasn't any paletted mode of that res or greater, fail
     71     if (!bestMode)
     72         return rserr_invalid_fullscreen;
     73 
     74 	ri.Con_Printf (PRINT_ALL, "SheildDisplay\n");
     75     [vid_screen shieldDisplay];
     76 
     77     // hide the cursor in all fullscreen modes
     78     [NSCursor hide];
     79     
     80     vid_window_i = [vid_screen shieldingWindow];
     81 
     82     ri.Con_Printf (PRINT_ALL, "switchToDisplayMode\n");
     83     [vid_screen switchToDisplayMode:bestMode];
     84 //    [vid_screen fadeDisplayOutToColor:[NSColor blackColor]];
     85 //    [vid_screen fadeDisplayInFromColor:[NSColor blackColor]];
     86 
     87 	vid_buffer = [vid_screen data];
     88 	vid_rowbytes = [vid_screen bytesPerRow];
     89 
     90     return rserr_ok;
     91 }
     92 
     93 void ShutdownFullscreen (void)
     94 {
     95 	[vid_screen dealloc];
     96 	[NSCursor unhide];
     97 }
     98 
     99 void SetPaletteFullscreen (const unsigned char *palette) {
    100 #if 0
    101     byte	*p;
    102     int		i;
    103 	NSDirectPalette		*pal;
    104 
    105     pal = [NSDirectPalette init];
    106     for (i=0 ; i<256 ; i++)
    107         [pal setRed: palette[0]*(1.0/255)
    108               green:  palette[1]*(1.0/255)
    109                blue:  palette[2]*(1.0/255)
    110             atIndex: i];
    111 	[vid_screen setPalette: pal];
    112     [pal release];
    113 #endif
    114 }
    115 
    116 
    117 
    118 void BlitFullscreen (void)
    119 {
    120 	int		i, j;
    121 	int		w;
    122 	int		*dest, *source;
    123 
    124 	w = vid.width>>2;
    125 
    126     source = (int *)vid.buffer;		// off-screen buffer
    127     dest = (int *)vid_buffer;		// directly on screen
    128     for (j=0 ; j<vid.height ; j++
    129          , source += (vid.rowbytes>>2), dest += (vid_rowbytes>>2)  ) {
    130         for (i=0 ; i<w ; i++ ) {
    131             dest[i] = source[i];            
    132         }
    133  	}
    134 }
    135 
    136 /*
    137 =======================================================================
    138 
    139 WINDOWED
    140 
    141 =======================================================================
    142 */
    143 
    144 /*
    145 ** InitWindowed
    146 */
    147 rserr_t InitWindowed (int width, int height)
    148 {
    149     rserr_t retval = rserr_ok;
    150     NSRect	content;
    151     cvar_t	*vid_xpos;
    152     cvar_t	*vid_ypos;
    153 
    154     //
    155     // open a window
    156     //
    157     vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
    158     vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
    159 
    160     content = NSMakeRect (vid_xpos->value,vid_ypos->value, width, height);
    161     vid_window_i = [[NSWindow alloc]
    162                 initWithContentRect:	content
    163                             styleMask:	NSTitledWindowMask
    164                             backing:	NSBackingStoreRetained
    165                             defer:	NO
    166     ];
    167 
    168 //    [vid_window_i addToEventMask: NS_FLAGSCHANGEDMASK];
    169     [vid_window_i setTitle: @"Quake2"];
    170 
    171     buffernative = malloc(width * height * 4);
    172 
    173     return retval;
    174 }
    175 
    176 void ShutdownWindowed (void)
    177 {
    178     if (vid_window_i)
    179     {
    180         [vid_window_i release];
    181         vid_window_i = NULL;
    182     }
    183     if (buffernative)
    184     {
    185         free (buffernative);
    186         buffernative = NULL;
    187     }
    188 }
    189 
    190 void SetPaletteWindowed (const unsigned char *palette) {
    191     byte	*p;
    192     int		i;
    193 
    194     p = (byte *)swimp_palette;
    195     for (i=0 ; i<256 ; i++, p+=4, palette+=4)
    196     {
    197         p[0] = palette[0];
    198        	p[1] = palette[1];
    199         p[2] = palette[2];
    200         p[3] = 0xff;
    201     }
    202 }
    203 
    204 
    205 void BlitWindowed (void)
    206 {
    207     int		i, c;
    208     int		bps, spp, bpp, bpr;
    209     unsigned char	*planes[5];
    210     NSRect			bounds;
    211 
    212     if (!vid_view_i)
    213         return;
    214 
    215     // translate to 24 bit color
    216     c = vid.width*vid.height;
    217     for (i=0 ; i<c ; i++)
    218         buffernative[i] = swimp_palette[vid.buffer[i]];
    219 
    220      bps = 8;
    221      spp = 3;
    222      bpp = 32;
    223      bpr = vid.width * 4;
    224      planes[0] = (unsigned char *)buffernative;
    225 
    226     bounds = [vid_view_i bounds];
    227 
    228     [vid_view_i lockFocus];
    229 
    230     NSDrawBitmap(
    231                 bounds,
    232                 vid.width,
    233                 vid.height,
    234                 bps,
    235                 spp,
    236                 bpp,
    237                 bpr,
    238                 NO,
    239                 NO,
    240                  @"NSDeviceRGBColorSpace",
    241                 planes
    242                 );
    243 
    244     [vid_view_i unlockFocus];
    245 	PSWait ();
    246 }
    247 
    248 
    249 //======================================================================
    250 
    251 /*
    252 ** RW_IMP.C
    253 **
    254 ** This file contains ALL Win32 specific stuff having to do with the
    255 ** software refresh.  When a port is being made the following functions
    256 ** must be implemented by the port:
    257 **
    258 ** SWimp_EndFrame
    259 ** SWimp_Init
    260 ** SWimp_SetPalette
    261 ** SWimp_Shutdown
    262 */
    263 
    264 
    265 /*
    266 ** SWimp_Init
    267 **
    268 ** This routine is responsible for initializing the implementation
    269 ** specific stuff in a software rendering subsystem.
    270 */
    271 int SWimp_Init( void *hInstance, void *wndProc )
    272 {
    273     if (!NSApp)
    274     {
    275         [NSApplication sharedApplication];
    276         [NSApp finishLaunching];
    277     }
    278 
    279     return true;
    280 }
    281 
    282 
    283 /*
    284 ** SWimp_SetMode
    285 */
    286 rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen)
    287 {
    288     const char 	*win_fs[] = { "W", "FS" };
    289     NSRect		content;
    290 	rserr_t		ret;
    291     
    292     // free resources in use
    293     SWimp_Shutdown ();
    294 
    295     ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
    296 
    297     if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
    298     {
    299         ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
    300         return rserr_invalid_mode;
    301     }
    302 
    303     ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
    304 
    305     vid.buffer = malloc(*pwidth * *pheight);
    306 	vid.rowbytes = *pwidth;
    307 
    308     if (fullscreen) {
    309         rhap_mode = rhap_fullscreen;
    310         ret = InitFullscreen (*pwidth, *pheight);        
    311     } else {
    312         rhap_mode = rhap_windowed;
    313         ret = InitWindowed (*pwidth, *pheight);
    314     }
    315 
    316     if (ret != rserr_ok) {
    317         SWimp_Shutdown ();
    318         return ret;       
    319     }
    320     
    321     /*
    322      ** the view is identical in windowed and fullscreen modes
    323      */
    324     content.origin.x = content.origin.y = 0;
    325     content.size.width = *pwidth;
    326     content.size.height = *pheight;
    327     vid_view_i = [[QuakeView alloc] initWithFrame: content];
    328     [vid_window_i setContentView: vid_view_i];
    329     [vid_window_i makeFirstResponder: vid_view_i];
    330     [vid_window_i setDelegate: vid_view_i];
    331 
    332     [NSApp activateIgnoringOtherApps: YES];
    333     [vid_window_i makeKeyAndOrderFront: nil];
    334     [vid_window_i display];
    335 
    336 	return ret;
    337 }
    338 
    339 /*
    340 ** SWimp_Shutdown
    341 **
    342 ** System specific graphics subsystem shutdown routine
    343 */
    344 void SWimp_Shutdown( void )
    345 {
    346     if (rhap_mode == rhap_windowed)
    347         ShutdownWindowed ();
    348     else if (rhap_mode == rhap_fullscreen)
    349         ShutdownFullscreen ();
    350 
    351     rhap_mode = rhap_shutdown;
    352 
    353     if (vid.buffer)
    354     {
    355         free (vid.buffer);
    356         vid.buffer = NULL;
    357     }
    358 }
    359 
    360 
    361 /*
    362 ** SWimp_SetPalette
    363 **
    364 ** System specific palette setting routine.  A NULL palette means
    365 ** to use the existing palette.  The palette is expected to be in
    366 ** a padded 4-byte xRGB format.
    367 */
    368 void SWimp_SetPalette( const unsigned char *palette )
    369 {
    370     if (rhap_mode == rhap_windowed)
    371         SetPaletteWindowed (palette);
    372     else if (rhap_mode == rhap_fullscreen)
    373         SetPaletteFullscreen (palette);
    374 }
    375 
    376 
    377 /*
    378 ** SWimp_EndFrame
    379 **
    380 ** This does an implementation specific copy from the backbuffer to the
    381 ** front buffer.  In the Win32 case it uses BitBlt or BltFast depending
    382 ** on whether we're using DIB sections/GDI or DDRAW.
    383 */
    384 void SWimp_EndFrame (void)
    385 {
    386     if (rhap_mode == rhap_windowed)
    387         BlitWindowed ();
    388     else if (rhap_mode == rhap_fullscreen)
    389         BlitFullscreen ();
    390 }
    391 
    392 
    393 /*
    394 ** SWimp_AppActivate
    395 */
    396 void SWimp_AppActivate( qboolean active )
    397 {
    398 }
    399 
    400 
    401 /*
    402  ==========================================================================
    403 
    404  NEXTSTEP VIEW CLASS
    405 
    406  ==========================================================================
    407  */
    408 #include "../client/keys.h"
    409 
    410 void IN_ActivateMouse (void);
    411 void IN_DeactivateMouse (void);
    412 
    413 @implementation QuakeView
    414 
    415 -(BOOL) acceptsFirstResponder
    416 {
    417     return YES;
    418 }
    419 
    420 - (void)windowDidMove: (NSNotification *)note
    421 {
    422     NSRect	r;
    423 
    424     r = [vid_window_i frame];
    425     ri.Cmd_ExecuteText (EXEC_NOW, va("vid_xpos %i", (int)r.origin.x+1));
    426     ri.Cmd_ExecuteText (EXEC_NOW, va("vid_ypos %i", (int)r.origin.y+1));
    427 }
    428 
    429 - (void)becomeKeyWindow
    430 {
    431     IN_ActivateMouse ();
    432 }
    433 
    434 - (void)resignKeyWindow
    435 {
    436     IN_DeactivateMouse ();
    437 }
    438 
    439 
    440 typedef struct
    441 {
    442     int		source, dest;
    443 } keymap_t;
    444 
    445 keymap_t keymaps[] =
    446 {
    447     {0xf703, K_RIGHTARROW},
    448 	{0xf702, K_LEFTARROW},
    449 	{0xf700, K_UPARROW},
    450 	{0xf701, K_DOWNARROW},
    451 
    452 	{0xf704, K_F1},
    453 	{0xf705, K_F2},
    454 	{0xf706, K_F3},
    455 	{0xf707, K_F4},
    456 	{0xf708, K_F5},
    457 	{0xf709, K_F6},
    458 	{0xf70a, K_F7},
    459 	{0xf70b, K_F8},
    460 	{0xf70c, K_F9},
    461 	{0xf70d, K_F10},
    462 	{0xf70e, K_F11},
    463 	{0xf70f, K_F12},
    464 
    465     {-1,-1}
    466 };
    467 
    468 keymap_t flagmaps[] =
    469 {
    470     {NSShiftKeyMask, K_SHIFT},
    471     {NSControlKeyMask, K_CTRL},
    472     {NSAlternateKeyMask, K_ALT},
    473     {NSCommandKeyMask, K_ALT},
    474 
    475     {-1,-1}
    476 };
    477 
    478 - (void)mouseDown:(NSEvent *)theEvent
    479 {
    480     Key_Event (K_MOUSE1, true, 0);
    481 }
    482 - (void)mouseUp:(NSEvent *)theEvent
    483 {
    484     Key_Event (K_MOUSE1, false, 0);
    485 }
    486 - (void)rightMouseDown:(NSEvent *)theEvent
    487 {
    488     Key_Event (K_MOUSE2, true, 0);
    489 }
    490 - (void)rightMouseUp:(NSEvent *)theEvent
    491 {
    492     Key_Event (K_MOUSE2, false, 0);
    493 }
    494 
    495 
    496 /*
    497  ===================
    498  keyboard methods
    499  ===================
    500  */
    501 - (void)keyDown:(NSEvent *)theEvent
    502 {
    503     int	ch;
    504     keymap_t	*km;
    505 
    506 //    PSobscurecursor ();
    507 
    508     ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
    509 // check for non-ascii first
    510    for (km=keymaps;km->source!=-1;km++)
    511        if (ch == km->source)
    512        {
    513            Key_Event (km->dest, true, 0);
    514            return;
    515        }
    516 
    517     if (ch >= 'A' && ch <= 'Z')
    518         ch += 'a' - 'A';
    519     if (ch>=256)
    520         return;
    521 
    522     Key_Event (ch, true, 0);
    523 }
    524 
    525 - (void)flagsChanged:(NSEvent *)theEvent
    526 {
    527     static int	oldflags;
    528     int		newflags;
    529     int		delta;
    530     keymap_t	*km;
    531     int		i;
    532 
    533 //    PSobscurecursor ();
    534     newflags = [theEvent modifierFlags];
    535     delta = newflags ^ oldflags;
    536     for (i=0 ; i<32 ; i++)
    537     {
    538         if ( !(delta & (1<<i)))
    539             continue;
    540         // changed
    541         for (km=flagmaps;km->source!=-1;km++)
    542             if ( (1<<i) == km->source)
    543             {
    544                 if (newflags & (1<<i))
    545                     Key_Event (km->dest, true, 0);
    546                 else
    547                     Key_Event (km->dest, false, 0);
    548             }
    549 
    550     }
    551 
    552         oldflags = newflags;
    553 }
    554 
    555 
    556 - (void)keyUp:(NSEvent *)theEvent
    557 {
    558     int	ch;
    559     keymap_t	*km;
    560 
    561     ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
    562 
    563 	// check for non-ascii first
    564    for (km=keymaps;km->source!=-1;km++)
    565       if (ch == km->source)
    566       {
    567           Key_Event (km->dest, false, 0);
    568           return;
    569       }
    570 
    571     if (ch >= 'A' && ch <= 'Z')
    572         ch += 'a' - 'A';
    573     if (ch>=256)
    574         return;
    575     Key_Event (ch, false, 0);
    576 }
    577 
    578 @end
    579 
    580