Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

vid_next.m (37786B)


      1 // vid_next.m -- NEXTSTEP video driver
      2 
      3 #define	INTERCEPTOR
      4 
      5 #import <appkit/appkit.h>
      6 #import <string.h>
      7 #import "intercep.h"
      8 #include "quakedef.h"
      9 #include "d_local.h"
     10 
     11 int	BASEWIDTH = 320;
     12 int BASEHEIGHT = 200;
     13 
     14 void SetupBitmap (void);
     15 void SetupFramebuffer (void);
     16 void UpdateBitmap (void);
     17 void UpdateFramebuffer (vrect_t *vrect);
     18 void SetVideoEncoding (char *encoding);
     19 void Update8_1 (pixel_t *src, byte *dest, int width,
     20 		int height, int destrowbytes);
     21 void Update16_1 (pixel_t *src, unsigned short *dest, int width,
     22 		int height, int destrowbytes);
     23 void Update32_1 (pixel_t *src, unsigned *dest, int width,
     24 		int height, int destrowbytes);
     25 
     26 
     27 @interface QuakeView : View
     28 @end
     29 
     30 @interface FrameWindow:Window
     31 @end
     32 
     33 unsigned short	d_8to16table[256];	// not used in 8 bpp mode
     34 unsigned	d_8to24table[256];	// not used in 8 bpp mode
     35 
     36 
     37 /*
     38 ==========================================================================
     39 
     40 						API FUNCTIONS
     41 
     42 ==========================================================================
     43 */
     44 
     45 typedef enum {disp_bitmap, disp_framebuffer}	display_t;
     46 
     47 pixel_t		*vid_buffer;
     48 pixel_t		*buffernative;
     49 unsigned	pcolormap[4][256];	// map from quake pixels to native pixels
     50 unsigned	pixbytesnative;
     51 unsigned	rowbytesnative;
     52 int			dither;
     53 
     54 int			drawdirect = 0;
     55 
     56 int			d_con_indirect = 0;
     57 
     58 display_t		vid_display;
     59 
     60 byte			vid_palette[768];	// saved for restarting vid system
     61 
     62 id				vid_window_i;
     63 id				vid_view_i;
     64 #ifdef INTERCEPTOR
     65 NXDirectBitmap	*vid_dbitmap_i;
     66 NXFramebuffer	*vid_framebuffer_i;
     67 #endif
     68 
     69 NXRect   		screenBounds;		// only valid in framebuffer mode
     70 
     71 int				vid_scale;
     72 
     73 char			*vid_encodingstring;
     74 
     75 int				vid_fullscreen;
     76 int				vid_screen;
     77 
     78 int				vid_high_hunk_mark;
     79 
     80 typedef enum
     81 {
     82 	enc_24_rgba,
     83 	enc_24_0rgb,
     84 	enc_24_rgb0,
     85 	enc_12_rgba,
     86 	enc_12_rgb0,
     87 	enc_15_0rgb,
     88 	enc_564,
     89 	enc_8_gray,
     90 	enc_8_rgb
     91 } vid_encoding_t;
     92 
     93 typedef struct
     94 {
     95 	char			*string;
     96 	int				pixelbytes;
     97 	void			(*colormap) (void);
     98 	vid_encoding_t	name;
     99 } vidtype_t;
    100 
    101 vid_encoding_t	vid_encoding;
    102  
    103 void	Table8 (void);
    104 void	Table15 (void);
    105 void	Table12 (void);
    106 void	Table12Swap (void);
    107 void	Table24 (void);
    108 void	Table24Swap (void);
    109 
    110 vidtype_t vid_encodingtable[]=
    111 {
    112 {"RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA",4, Table24Swap, enc_24_rgba},
    113 {"--------RRRRRRRRGGGGGGGGBBBBBBBB",4, Table24, enc_24_0rgb},
    114 {"RRRRRRRRGGGGGGGGBBBBBBBB--------",4, Table24Swap, enc_24_rgb0},
    115 {"RRRRGGGGBBBBAAAA",2, Table12Swap, enc_12_rgba},
    116 {"RRRRGGGGBBBB----",2, Table12, enc_12_rgb0},
    117 {"-RRRRRGGGGGBBBBB",2, Table15, enc_15_0rgb},
    118 {"WWWWWWWW",1, Table8, enc_8_gray},
    119 {"PPPPPPPP",1, Table8, enc_8_rgb},
    120 {NULL,0, 0, 0}
    121 };
    122 
    123 vidtype_t	*vid_type;
    124 void	InitNS8Bit (void);
    125 
    126 /*
    127 ================
    128 D_BeginDirectRect
    129 ================
    130 */
    131 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
    132 {
    133 // direct drawing of the "accessing disk" icon isn't supported under Nextstep
    134 }
    135 
    136 
    137 /*
    138 ================
    139 D_EndDirectRect
    140 ================
    141 */
    142 void D_EndDirectRect (int x, int y, int width, int height)
    143 {
    144 // direct drawing of the "accessing disk" icon isn't supported under Nextstep
    145 }
    146 
    147 
    148 /*
    149 ==============
    150 VID_Restart
    151 
    152 internal call only
    153 ===============
    154 */
    155 void VID_Restart (display_t mode, int scale)
    156 {
    157 	vid_display = mode;
    158 	vid_scale = scale;
    159 
    160 	[NXApp activateSelf:YES];
    161 
    162 	if (vid_display == disp_framebuffer)
    163 		SetupFramebuffer ();
    164 	else
    165 		SetupBitmap ();
    166 
    167 	vid.recalc_refdef = 1;
    168 }
    169 
    170 
    171 /*
    172 =================
    173 VID_Scale_f
    174 
    175 Keybinding command
    176 =================
    177 */
    178 void VID_Scale_f (void)
    179 {
    180 	int		scale;
    181 	
    182 	if (Cmd_Argc () != 2)
    183 		return;
    184 		
    185 	scale = atoi (Cmd_Argv(1));
    186 	if (scale != 1 && scale != 2)
    187 	{
    188 		Con_Printf ("scale must be 1 or 2\n");
    189 		return;
    190 	}
    191 	VID_Shutdown ();
    192 	VID_Restart (vid_display, scale);
    193 }
    194 
    195 /*
    196 =================
    197 VID_Mode_f
    198 
    199 Keybinding command
    200 =================
    201 */
    202 void VID_Mode_f (void)
    203 {
    204 	int		mode;
    205 
    206 	if (Cmd_Argc () != 2)
    207 		return;
    208 
    209 	mode = atoi (Cmd_Argv(1));
    210 
    211 	VID_Shutdown ();
    212 	if (mode == 0)
    213 	{
    214 		drawdirect = 0;
    215 		VID_Restart (disp_bitmap, vid_scale);
    216 	}
    217 	else if (mode == 1)
    218 	{
    219 		drawdirect = 0;
    220 		VID_Restart (disp_framebuffer, vid_scale);
    221 	}
    222 	else
    223 	{
    224 		drawdirect = 1;
    225 		VID_Restart (disp_framebuffer, vid_scale);
    226 	}
    227 }
    228 
    229 /*
    230 =================
    231 VID_Size_f
    232 
    233 Keybinding command
    234 =================
    235 */
    236 void VID_Size_f (void)
    237 {	
    238 	if (Cmd_Argc () != 3)
    239 		return;
    240 
    241 	VID_Shutdown ();
    242 
    243 	BASEWIDTH = atoi (Cmd_Argv(1));
    244 	BASEHEIGHT = atoi (Cmd_Argv(2));
    245 
    246 	VID_Restart (vid_display, vid_scale);
    247 }
    248 
    249 /*
    250 ================
    251 VID_Init
    252 ================
    253 */
    254 void	VID_Init (unsigned char *palette)
    255 {
    256 	InitNS8Bit ();			// fixed palette lookups
    257 	
    258 	Q_memcpy (vid_palette, palette, sizeof(vid_palette));
    259 
    260 	if (COM_CheckParm ("-bitmap"))
    261 		vid_display = disp_bitmap;
    262 	else
    263 		vid_display = disp_framebuffer;
    264 
    265 	if (COM_CheckParm ("-screen2"))
    266 		vid_screen = 1;
    267 	else
    268 		vid_screen = 0;
    269 
    270 	if (COM_CheckParm ("-direct"))
    271 		drawdirect = 1;
    272 	
    273 	Cmd_AddCommand ("vid_scale", VID_Scale_f);
    274 	Cmd_AddCommand ("vid_mode", VID_Mode_f);
    275 	Cmd_AddCommand ("vid_size", VID_Size_f);
    276 
    277 	vid.width = BASEWIDTH;
    278 	vid.height = BASEHEIGHT;
    279 	vid.aspect = 1.0;
    280 	vid.numpages = 1;
    281 	vid.colormap = host_colormap;
    282 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
    283 	vid.maxwarpwidth = WARP_WIDTH;
    284 	vid.maxwarpheight = WARP_HEIGHT;
    285 
    286 	if (COM_CheckParm ("-scale2"))
    287 		vid_scale = 2;
    288 	else
    289 		vid_scale = 1;
    290 		
    291     [Application new];
    292 
    293 	VID_Restart (vid_display, vid_scale);
    294 }
    295 
    296 
    297 /*
    298 ================
    299 VID_Shutdown
    300 ================
    301 */
    302 void VID_Shutdown (void)
    303 {
    304 #ifdef INTERCEPTOR
    305 	if (vid_dbitmap_i)
    306 	{
    307 		[vid_dbitmap_i free];
    308 		vid_dbitmap_i = 0;
    309 	}
    310 	if (vid_framebuffer_i)
    311 	{
    312 		[vid_framebuffer_i free];
    313 		vid_framebuffer_i = 0;
    314 	}
    315 #endif
    316 	[vid_window_i close];
    317 	[vid_window_i free];
    318 }
    319 
    320 
    321 /*
    322 ================
    323 VID_Update
    324 ================
    325 */
    326 void	VID_Update (vrect_t *rects)
    327 {
    328 	if (drawdirect)
    329 		return;
    330 
    331 	while (rects)
    332 	{
    333 		UpdateFramebuffer (rects);
    334 		rects = rects->pnext;
    335 	}
    336 
    337 	if (vid_display == disp_bitmap)
    338 		UpdateBitmap ();
    339 }
    340 
    341 
    342 /*
    343 ================
    344 VID_SetPalette
    345 ================
    346 */
    347 void	VID_SetPalette (unsigned char *palette)
    348 {
    349 	Q_memcpy (vid_palette, palette, sizeof(vid_palette));
    350 	vid_type->colormap ();
    351 }
    352 
    353 
    354 /*
    355 ================
    356 VID_ShiftPalette
    357 ================
    358 */
    359 void    VID_ShiftPalette (unsigned char *palette)
    360 {
    361 
    362 	VID_SetPalette (palette);
    363 }
    364 
    365 
    366 /*
    367 ==========================================================================
    368 
    369 						NS STUFF
    370 
    371 ==========================================================================
    372 */
    373 
    374 
    375 /*
    376 =================
    377 SetVideoEncoding
    378 =================
    379 */
    380 void SetVideoEncoding (char *encoding)
    381 {
    382 	vidtype_t			*type;
    383 
    384 	Sys_Printf ("SetVideoEncoding: %s\n",encoding);
    385 	vid_encodingstring = encoding;
    386 	
    387 	for (type = vid_encodingtable ; type->string ; type++)
    388 	{
    389 		if (strcmp(type->string, encoding) == 0)
    390 		{
    391 			pixbytesnative = type->pixelbytes;
    392 			vid_encoding = type->name;
    393 			type->colormap ();
    394 			vid_type = type;
    395 			return;
    396 		}
    397 	}
    398 	
    399 	Sys_Error ("Unsupported video encoding: %s\n",encoding);
    400 }
    401 
    402 /*
    403 =================
    404 AllocBuffers
    405 =================
    406 */
    407 void AllocBuffers (qboolean withnative)
    408 {
    409 	int		surfcachesize;
    410 	void	*surfcache;
    411 	int		pixels;
    412 	int		pixbytes;
    413 	int		vid_buffersize;
    414 
    415 	if (vid_buffer)
    416 	{
    417 		D_FlushCaches ();
    418 		Hunk_FreeToHighMark (vid_high_hunk_mark);
    419 		vid_high_hunk_mark = 0;
    420 		vid_buffer = NULL;
    421 	}
    422 
    423 	pixels = vid.width * vid.height;
    424 
    425 	pixbytes = 1 +sizeof (*d_pzbuffer);
    426 	if (withnative)
    427 		pixbytes += pixbytesnative;
    428 		
    429 	surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
    430 	vid_buffersize = pixels * pixbytes + surfcachesize;
    431 
    432 	vid_high_hunk_mark = Hunk_HighMark ();
    433 	vid_buffer = Hunk_HighAllocName (vid_buffersize, "video");
    434 	if (!vid_buffer)
    435 		Sys_Error ("Couldn't alloc video buffers");
    436 
    437 	vid.buffer = vid_buffer;
    438 
    439 	d_pzbuffer = (unsigned short *)((byte *)vid_buffer + pixels);
    440 	surfcache = (byte *)d_pzbuffer + pixels * sizeof (*d_pzbuffer);
    441 	if (withnative)
    442 		buffernative = (byte *)surfcache + surfcachesize;
    443 
    444 	D_InitCaches (surfcache, surfcachesize);
    445 }
    446 
    447 /*
    448 =================
    449 SetupFramebuffer
    450 =================
    451 */
    452 void SetupFramebuffer (void)
    453 {
    454 #ifdef INTERCEPTOR
    455     int			windowNum;
    456 	NXRect		cont;
    457 	NXScreen	const *screens;
    458 	int			screencount;
    459 
    460 //
    461 // get the screen list
    462 //
    463 	[NXApp getScreens:&screens count:&screencount];
    464 
    465 //
    466 // create vid_framebuffer_i
    467 //
    468     vid_framebuffer_i = [[NXFramebuffer alloc]
    469 		   initFromScreen:screens[vid_screen].screenNumber andMapIfPossible:YES];
    470     [vid_framebuffer_i screenBounds:&screenBounds];
    471 
    472 	SetVideoEncoding ([vid_framebuffer_i pixelEncoding]);
    473 
    474 	buffernative = [vid_framebuffer_i data];
    475 	rowbytesnative = [vid_framebuffer_i bytesPerRow];
    476 
    477 //
    478 // create window
    479 //
    480 	if (vid_fullscreen)
    481 	{
    482 		vid.height = screenBounds.size.height / vid_scale;
    483 		vid.width = screenBounds.size.width / vid_scale;
    484 		cont.origin.x = 0;
    485 		cont.origin.y = 0;
    486 		cont.size.width = screenBounds.size.width;
    487 		cont.size.height = screenBounds.size.height;
    488 	}
    489 	else
    490 	{
    491 		buffernative = (unsigned char *)buffernative + 8 * rowbytesnative +
    492 				8 * pixbytesnative;
    493 		vid.width = BASEWIDTH;
    494 		vid.height = BASEHEIGHT;
    495 		cont.origin.x = 8;
    496 		cont.origin.y = screenBounds.size.height - (vid.height*vid_scale) - 8;
    497 		cont.size.width = vid.width * vid_scale;
    498 		cont.size.height = vid.height * vid_scale;
    499 	}
    500 
    501     vid_window_i = [[FrameWindow alloc]
    502 		 initContent:		&cont
    503 		 style:				NX_PLAINSTYLE
    504 		 backing:			NX_NONRETAINED
    505 		 buttonMask:		0
    506 		 defer:				NO
    507 		 screen:			screens+vid_screen];
    508     windowNum = [vid_window_i windowNum];
    509     PSsetwindowlevel(40, windowNum);
    510     PSsetautofill(YES, windowNum);
    511     PSgsave();
    512     PSwindowdeviceround(windowNum);
    513     PSsetgray(NX_BLACK);
    514     PSsetexposurecolor();
    515     PSgrestore();
    516 
    517 //
    518 // create view
    519 //
    520 	vid_view_i = [[QuakeView alloc] initFrame: &screenBounds];
    521 	[[vid_window_i setContentView: vid_view_i] free];
    522 	[vid_window_i makeFirstResponder: vid_view_i];
    523 	[vid_window_i setDelegate: vid_view_i];	
    524 	[vid_window_i display];
    525 	[vid_window_i makeKeyAndOrderFront: nil];
    526 	NXPing ();
    527 
    528 	AllocBuffers (false);	// no native buffer
    529 
    530 	if (drawdirect)
    531 	{	// the direct drawing mode to NeXT colorspace
    532 		vid.buffer = buffernative;
    533 		vid.rowbytes = rowbytesnative;
    534 	}
    535 	else
    536 		vid.rowbytes = vid.width;
    537 
    538 	vid.conbuffer = vid.buffer;
    539 	vid.conrowbytes = vid.rowbytes;
    540 	vid.conwidth = vid.width;
    541 	vid.conheight = vid.height;
    542 #endif
    543 }
    544 
    545 /*
    546 =================
    547 SetupBitmap
    548 =================
    549 */
    550 void SetupBitmap (void)
    551 {
    552 	int		depth;
    553 	NXRect	content;
    554 
    555 //
    556 // open a window
    557 //
    558 	NXSetRect (&content, 8,136, vid.width*vid_scale, vid.height*vid_scale);
    559 	vid_window_i = [[Window alloc]
    560 			initContent:	&content
    561 			style:			NX_RESIZEBARSTYLE
    562 			backing:		NX_RETAINED
    563 			buttonMask:		0
    564 			defer:			NO
    565 		];
    566 	[vid_window_i display];
    567 	[vid_window_i makeKeyAndOrderFront: nil];
    568 
    569 	NXPing ();
    570 
    571 	content.origin.x = content.origin.y = 0;
    572 	vid_view_i = [[QuakeView alloc] initFrame: &content];
    573 	[[vid_window_i setContentView: vid_view_i] free];
    574 	[vid_window_i makeFirstResponder: vid_view_i];
    575 	[vid_window_i setDelegate: vid_view_i];
    576 
    577 	[vid_window_i addToEventMask: NX_FLAGSCHANGEDMASK];
    578 
    579 //
    580 // find video info
    581 //
    582     depth = [Window defaultDepthLimit];
    583     switch (depth) {
    584 	case NX_EightBitGrayDepth:
    585 		SetVideoEncoding ("WWWWWWWW");
    586 	    break;
    587 	case NX_TwelveBitRGBDepth:
    588 		SetVideoEncoding ("RRRRGGGGBBBBAAAA");
    589 	    break;
    590 	default:
    591 	case NX_TwentyFourBitRGBDepth:
    592 		SetVideoEncoding ("RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA");
    593 	    break;
    594 //	default:	// 8 bit color shows up as an unknown...
    595 		Sys_Error ("Unsupported window depth");
    596     }
    597 
    598 	[vid_window_i setTitle: "Bitmap Quake Console"];
    599 
    600 //
    601 // allocate memory for the back and translation buffers
    602 //
    603 	vid.rowbytes = vid.width;
    604 	rowbytesnative = vid.width * pixbytesnative;
    605 	
    606 	AllocBuffers (true);
    607 	
    608 	vid.conbuffer = vid.buffer;
    609 	vid.conrowbytes = vid.rowbytes;
    610 	vid.conwidth = vid.width;
    611 	vid.conheight = vid.height;
    612 }
    613 
    614 
    615 /*
    616 =================
    617 UpdateFramebuffer
    618 =================
    619 */
    620 void UpdateFramebuffer (vrect_t *vrect)
    621 {
    622 	byte		*psourcebase;
    623 	byte		*pdestbase;
    624 	int			scale;
    625 	
    626 	psourcebase = vid.buffer + vrect->x + vrect->y * vid.rowbytes;
    627 
    628 	if (vid_display == disp_bitmap)
    629 		scale = 1;		// let NS do the scaling
    630 	else
    631 		scale = vid_scale;
    632 		
    633 	pdestbase = buffernative + scale *
    634 			(vrect->x * pixbytesnative + vrect->y * rowbytesnative);
    635 
    636 //
    637 // translate from ideal to native (except 8 bpp direct) and copy to screen
    638 //
    639 
    640 	if (pixbytesnative == 1)
    641 		Update8_1 (psourcebase, pdestbase, vrect->width, vrect->height,
    642 				rowbytesnative);
    643 	else if (pixbytesnative == 2)
    644 		Update16_1 (psourcebase, (unsigned short *)pdestbase, vrect->width, vrect->height,
    645 				rowbytesnative);
    646 	else
    647 		Update32_1 (psourcebase, (unsigned *)pdestbase, vrect->width, vrect->height,
    648 				rowbytesnative);
    649 }
    650 
    651 
    652 /*
    653 =================
    654 UpdateBitmap
    655 =================
    656 */
    657 void UpdateBitmap (void)
    658 {
    659 	unsigned char	*planes[5];
    660 	NXRect			bounds;
    661 	int				bpp, spp, bps, bpr, colorspace;
    662 
    663 //
    664 // flush the screen with an image call
    665 // 
    666 	if (pixbytesnative == 1)
    667 	{
    668 		bps = 8;
    669 		spp = 1;
    670 		bpp = 8;
    671 		bpr = vid.width;
    672 		colorspace = NX_OneIsWhiteColorSpace;
    673 		planes[0] = vid.buffer;
    674 	}
    675 	else if (pixbytesnative == 2)
    676 	{
    677 		bps = 4;
    678 		spp = 3;
    679 		bpp = 16;
    680 		bpr = vid.width * 2;
    681 		colorspace = NX_RGBColorSpace;
    682 		planes[0] = buffernative;
    683 	}
    684 	else
    685 	{
    686 		bps = 8;
    687 		spp = 3;
    688 		bpp = 32;
    689 		bpr = vid.width * 4;
    690 		colorspace = NX_RGBColorSpace;
    691 		planes[0] = buffernative;
    692 	}
    693 
    694 	[vid_view_i getBounds: &bounds];
    695 	[vid_view_i lockFocus];
    696 
    697 	NXDrawBitmap(
    698 		&bounds,  
    699 		vid.width, 
    700 		vid.height,
    701 		bps,
    702 		spp,
    703 		bpp,
    704 		bpr,
    705 		NO,
    706 		NO,
    707 		colorspace,
    708 		planes
    709 	);
    710 	
    711 	[vid_view_i unlockFocus];
    712     NXPing ();	
    713 }
    714 
    715 
    716 
    717 /*
    718 ==========================================================================
    719 
    720 					TRANSLATION TABLE BUILDING
    721 
    722 ==========================================================================
    723 */
    724 
    725 int	redramp[] = {0, 19, 59, 113, 178, 255, 300};
    726 int greenramp[] = {0, 11, 34,  66, 104, 149, 199, 255, 300};
    727 int blueramp[] = {0, 28, 84, 161, 255, 300};
    728 int greyramp[] = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204,
    729 				   221, 238, 255, 300};
    730 
    731 byte	greytable[256];
    732 byte	redtable[256];
    733 byte	greentable[256];
    734 byte	bluetable[256];
    735 
    736 void FillTable (byte *table, int *ramp, int base)
    737 {
    738 	int		i, j, o;
    739 	
    740 	o = 0;
    741 	for (i=0 ; i<16 && o < 256; i++)
    742 	{
    743 		j = ramp[i];
    744 		for ( ; o<=j ; o++)
    745 			table[o] = base + i;
    746 	}
    747 }
    748 
    749 void	InitNS8Bit (void)
    750 {
    751 	FillTable (greytable, greyramp, 240);
    752 	FillTable (redtable, redramp, 0);
    753 	FillTable (greentable, greenramp, 0);
    754 	FillTable (bluetable, blueramp, 0);
    755 }
    756 
    757 
    758 byte ns8trans[256] =	// FIXME: dynamically calc this so palettes work
    759 {
    760 0,241,242,243,244,244,245,246,247,248,249,250,251,252,253,254,
    761 45,241,241,242,91,91,91,96,96,136,136,136,141,141,141,141,
    762 241,46,242,243,243,97,97,97,245,246,143,143,143,143,148,148,
    763 0,5,45,45,50,50,90,90,95,95,95,95,95,140,140,141,
    764 0,40,40,40,40,80,80,80,80,80,120,120,120,120,120,120,
    765 45,50,50,90,90,95,95,135,135,135,136,141,141,181,181,181,
    766 45,90,91,91,131,131,136,136,136,176,181,181,186,226,231,236,
    767 45,45,91,91,96,96,136,136,137,142,182,182,187,188,188,233,
    768 188,249,248,247,246,137,137,137,244,243,243,91,242,241,241,45,
    769 183,183,183,247,137,137,137,137,137,244,91,91,91,241,241,45,
    770 252,251,188,188,248,248,142,142,142,244,244,243,91,242,241,45,
    771 247,247,246,246,245,245,244,244,243,243,242,242,51,241,241,5,
    772 236,231,231,191,186,185,185,140,140,135,135,95,90,90,45,45,
    773 4,49,49,53,53,93,93,93,93,92,92,92,243,242,46,241,
    774 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,
    775 239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,182
    776 };
    777 
    778 /*
    779 ===================
    780 Table8
    781 ===================
    782 */
    783 void	Table8 (void)
    784 {
    785 	byte	*pal;
    786 	int		r,g,b,v;
    787 	int		i;
    788 	byte	*table;
    789 	
    790 	pal = vid_palette;
    791 	table = (byte *)pcolormap[0];
    792 	
    793 	for (i=0 ; i<256 ; i++)
    794 	{
    795 		r = pal[0];
    796 		g = pal[1];
    797 		b = pal[2];
    798 		pal += 3;
    799 		
    800 // use the grey ramp if all indexes are close
    801 
    802 		if (r-g < 16 && r-g > -16 && r-b < 16 && r-b > -16)
    803 		{
    804 			v = (r+g+b)/3;
    805 			*table++ = greytable[v];
    806 			continue;
    807 		}
    808 		
    809 		r = redtable[r];
    810 		g = greentable[g];
    811 		b = bluetable[b];
    812 		
    813 // otherwise use the color cube
    814 		*table++ = r*(8*5) + g*5 + b;
    815 	}
    816 }
    817 
    818 /*
    819 ===================
    820 Table24
    821 ===================
    822 */
    823 void	Table24 (void)
    824 {
    825 	byte	*pal;
    826 	int		r,g,b,v;
    827 	int		i;
    828 	unsigned	*table;
    829 	
    830 	
    831 //
    832 // 8 8 8 encoding
    833 //
    834 	pal = vid_palette;
    835 	table = (unsigned *)pcolormap[0];
    836 	
    837 	for (i=0 ; i<256 ; i++)
    838 	{
    839 		r = pal[0];
    840 		g = pal[1];
    841 		b = pal[2];
    842 		pal += 3;
    843 		
    844 		v = (r<<16) + (g<<8) + b;
    845 		*table++ = v;
    846 	}
    847 }
    848 
    849 /*
    850 ===================
    851 Table24Swap
    852 ===================
    853 */
    854 void	Table24Swap (void)
    855 {
    856 	byte	*pal;
    857 	int		r,g,b,v;
    858 	int		i;
    859 	unsigned	*table;
    860 
    861 //
    862 // 8 8 8 encoding
    863 //
    864 	pal = vid_palette;
    865 	table = (unsigned *)pcolormap[0];
    866 	
    867 	for (i=0 ; i<256 ; i++)
    868 	{
    869 		r = pal[0];
    870 		g = pal[1];
    871 		b = pal[2];
    872 		pal += 3;
    873 		
    874 		v = (r<<24) + (g<<16) + (b<<8) /*+ 255*/;
    875 		v = NXSwapBigLongToHost (v);
    876 		*table++ = v;
    877 	}
    878 }
    879 
    880 
    881 /*
    882 ===================
    883 Table15
    884 ===================
    885 */
    886 void	Table15 (void)
    887 {
    888 	byte			*pal;
    889 	int				r,g,b,v;
    890 	int				i, k;
    891 	unsigned char	*palette;
    892 	unsigned short	*table;
    893 	int				dadj;
    894 	int		ditheradjust[4] = {(1 << 9) * 3 / 8,
    895 									(1 << 9) * 5 / 8,
    896 									(1 << 9) * 7 / 8,
    897 									(1 << 9) * 1 / 8};
    898 	
    899 	palette = vid_palette;
    900 	table = (unsigned short *)pcolormap;
    901 	
    902 //
    903 // 5 5 5 encoding
    904 //
    905 	for (k=0 ; k<4 ; k++)
    906 	{
    907 		dadj = ditheradjust[k];
    908 
    909 		pal = vid_palette;
    910 
    911 		for (i=0 ; i<256 ; i++)
    912 		{
    913 		// shift 6 bits to get back to 0-255, & 3 more for 5 bit color
    914 		// FIXME: scale intensity levels properly
    915 			r = (pal[0] + dadj) >> 3;
    916 			g = (pal[1] + dadj) >> 3;
    917 			b = (pal[2] + dadj) >> 3;
    918 			pal += 3;
    919 
    920 			v = (r<<10) + (g<<5) + b;
    921 
    922 			*table++ = v;
    923 		}
    924 	}
    925 }
    926 
    927 /*
    928 ===================
    929 Table12
    930 ===================
    931 */
    932 void	Table12 (void)
    933 {
    934 	byte			*pal;
    935 	int				r,g,b,v;
    936 	int				i, k;
    937 	unsigned short	*table;
    938 	int				dadj;
    939 	static int		ditheradjust[4] = {(1 << 9) * 3 / 8,
    940 									   (1 << 9) * 5 / 8,
    941 									   (1 << 9) * 7 / 8,
    942 									   (1 << 9) * 1 / 8};
    943 
    944 	table = (unsigned short *)pcolormap;
    945 		
    946 //
    947 // 4 4 4 encoding
    948 //
    949 	for (k=0 ; k<4 ; k++)
    950 	{
    951 		dadj = ditheradjust[k];
    952 
    953 		pal = vid_palette;
    954 
    955 		for (i=0 ; i<256 ; i++)
    956 		{
    957 		// shift 5 bits to get back to 0-255, & 4 more for 4 bit color
    958 		// FIXME: scale intensity levels properly
    959 			r = (pal[0] + dadj) >> 4;
    960 			g = (pal[1] + dadj) >> 4;
    961 			b = (pal[2] + dadj) >> 4;
    962 			pal += 3;
    963 
    964 			v = ((r<<12) + (g<<8) + (b<<4) /*+ 15*/);
    965 
    966 			*table++ = v;
    967 		}
    968 	}
    969 }
    970 
    971 /*
    972 ===================
    973 Table12Swap
    974 ===================
    975 */
    976 void	Table12Swap (void)
    977 {
    978 	byte			*pal;
    979 	int				r,g,b,v;
    980 	int				i, k;
    981 	unsigned short	*table;
    982 	int				dadj;
    983 	static int		ditheradjust[4] = {(1 << 9) * 3 / 8,
    984 									   (1 << 9) * 5 / 8,
    985 									   (1 << 9) * 7 / 8,
    986 									   (1 << 9) * 1 / 8};
    987 
    988 	table = (unsigned short *)pcolormap;
    989 		
    990 //
    991 // 4 4 4 encoding
    992 //
    993 	for (k=0 ; k<4 ; k++)
    994 	{
    995 		dadj = ditheradjust[k];
    996 
    997 		pal = vid_palette;
    998 
    999 		for (i=0 ; i<256 ; i++)
   1000 		{
   1001 		// shift 5 bits to get back to 0-255, & 4 more for 4 bit color
   1002 		// FIXME: scale intensity levels properly
   1003 			r = (pal[0] + dadj) >> 4;
   1004 			g = (pal[1] + dadj) >> 4;
   1005 			b = (pal[2] + dadj) >> 4;
   1006 			pal += 3;
   1007 
   1008 			v = ((r<<12) + (g<<8) + (b<<4) /*+ 15*/);
   1009 			v = NXSwapBigShortToHost (v);
   1010 
   1011 			*table++ = v;
   1012 		}
   1013 	}
   1014 }
   1015 
   1016 
   1017 /*
   1018 ==========================================================================
   1019 
   1020 					GENERIC IMAGING FUNCTIONS
   1021 
   1022 ==========================================================================
   1023 */
   1024 
   1025 /*
   1026 ===================
   1027 Update8_1
   1028 ===================
   1029 */
   1030 void Update8_1 (pixel_t *src, byte *dest, int width, int height,
   1031 		int destrowbytes)
   1032 {
   1033 	int				x,y;
   1034 	unsigned		rowdelta, srcdelta;
   1035 	unsigned		xcount;
   1036 	byte			*pdest;
   1037 	int				xwidth;
   1038 
   1039 	pdest = dest;
   1040 	
   1041 	xcount = width >> 3;
   1042 	srcdelta = vid.width - width;
   1043 
   1044 	xwidth = width - (xcount << 3);
   1045 	if (xwidth)
   1046 		Sys_Error ("Width not multiple of 8");
   1047 
   1048 	if ((vid_display == disp_framebuffer) && (vid_scale == 2))
   1049 	{
   1050 		int		nextrow = destrowbytes;
   1051 
   1052 	    rowdelta = destrowbytes - (width << 1)  + destrowbytes;
   1053 
   1054 		if (dither)
   1055 		{
   1056 			unsigned short	*psrc;
   1057 
   1058 			psrc = (unsigned short *)src;
   1059 
   1060 			for (y = height ; y ; y--)
   1061 			{
   1062 		    	for (x = xcount ; x ;x--)
   1063 			    {
   1064 					unsigned	temp;
   1065 
   1066 					temp = psrc[0];
   1067 					pdest[0] = ((byte *)pcolormap[0])[temp];
   1068 					pdest[1] = ((byte *)pcolormap[1])[temp];
   1069 					pdest[nextrow] = ((byte *)pcolormap[2])[temp];
   1070 					pdest[nextrow + 1] = ((byte *)pcolormap[3])[temp];
   1071 					temp = psrc[1];
   1072 					pdest[2] = ((byte *)pcolormap[0])[temp];
   1073 					pdest[3] = ((byte *)pcolormap[1])[temp];
   1074 					pdest[nextrow + 2] = ((byte *)pcolormap[2])[temp];
   1075 					pdest[nextrow + 3] = ((byte *)pcolormap[3])[temp];
   1076 					temp = psrc[2];
   1077 					pdest[4] = ((byte *)pcolormap[0])[temp];
   1078 					pdest[5] = ((byte *)pcolormap[1])[temp];
   1079 					pdest[nextrow + 4] = ((byte *)pcolormap[2])[temp];
   1080 					pdest[nextrow + 5] = ((byte *)pcolormap[3])[temp];
   1081 					temp = psrc[3];
   1082 					pdest[6] = ((byte *)pcolormap[0])[temp];
   1083 					pdest[7] = ((byte *)pcolormap[1])[temp];
   1084 					pdest[nextrow + 6] = ((byte *)pcolormap[2])[temp];
   1085 					pdest[nextrow + 7] = ((byte *)pcolormap[3])[temp];
   1086 					temp = psrc[4];
   1087 					pdest[8] = ((byte *)pcolormap[0])[temp];
   1088 					pdest[9] = ((byte *)pcolormap[1])[temp];
   1089 					pdest[nextrow + 8] = ((byte *)pcolormap[2])[temp];
   1090 					pdest[nextrow + 9] = ((byte *)pcolormap[3])[temp];
   1091 					temp = psrc[5];
   1092 					pdest[10] = ((byte *)pcolormap[0])[temp];
   1093 					pdest[11] = ((byte *)pcolormap[1])[temp];
   1094 					pdest[nextrow + 10] = ((byte *)pcolormap[2])[temp];
   1095 					pdest[nextrow + 11] = ((byte *)pcolormap[3])[temp];
   1096 					temp = psrc[6];
   1097 					pdest[12] = ((byte *)pcolormap[0])[temp];
   1098 					pdest[13] = ((byte *)pcolormap[1])[temp];
   1099 					pdest[nextrow + 12] = ((byte *)pcolormap[2])[temp];
   1100 					pdest[nextrow + 13] = ((byte *)pcolormap[3])[temp];
   1101 					temp = psrc[7];
   1102 					pdest[14] = ((byte *)pcolormap[0])[temp];
   1103 					pdest[15] = ((byte *)pcolormap[1])[temp];
   1104 					pdest[nextrow + 14] = ((byte *)pcolormap[2])[temp];
   1105 					pdest[nextrow + 15] = ((byte *)pcolormap[3])[temp];
   1106 					pdest += 16; psrc += 8;
   1107 			    }
   1108 
   1109 				psrc += srcdelta;
   1110 			    pdest += rowdelta;
   1111 			}
   1112 		}
   1113 		else
   1114 		{
   1115 			byte	*psrc;
   1116 
   1117 			psrc = (byte *)src;
   1118 
   1119 			for (y = height ; y ; y--)
   1120 			{
   1121 				for (x = xcount ; x ;x--)
   1122 		    	{
   1123 					pdest[0] = pdest[1] = pdest[nextrow] =
   1124 						pdest[nextrow + 1] = ((byte *)pcolormap[0])[psrc[0]];
   1125 					pdest[2] = pdest[3] = pdest[nextrow + 2] =
   1126 						pdest[nextrow + 3] = ((byte *)pcolormap[0])[psrc[1]];
   1127 					pdest[4] = pdest[5] = pdest[nextrow + 4] =
   1128 						pdest[nextrow + 5] = ((byte *)pcolormap[0])[psrc[2]];
   1129 					pdest[6] = pdest[7] = pdest[nextrow + 6] =
   1130 						pdest[nextrow + 7] = ((byte *)pcolormap[0])[psrc[3]];
   1131 					pdest[8] = pdest[9] = pdest[nextrow + 8] =
   1132 						pdest[nextrow + 9] = ((byte *)pcolormap[0])[psrc[4]];
   1133 					pdest[10] = pdest[11] = pdest[nextrow + 10] =
   1134 						pdest[nextrow + 11] = ((byte *)pcolormap[0])[psrc[5]];
   1135 					pdest[12] = pdest[13] = pdest[nextrow + 12] =
   1136 						pdest[nextrow + 13] = ((byte *)pcolormap[0])[psrc[6]];
   1137 					pdest[14] = pdest[15] = pdest[nextrow + 14] =
   1138 						pdest[nextrow + 15] = ((byte *)pcolormap[0])[psrc[7]];
   1139 					pdest += 16; psrc += 8;
   1140 		    	}
   1141 
   1142 				psrc += srcdelta;
   1143 			    pdest += rowdelta;
   1144 			}
   1145 		}
   1146     }
   1147 	else
   1148 	{
   1149 	    rowdelta = destrowbytes - width;
   1150 
   1151 		if (dither)
   1152 		{
   1153 			unsigned short	*psrc;
   1154 
   1155 			psrc = (unsigned short *)src;
   1156 
   1157 			for (y = height ; y>0 ; y -= 2)
   1158 			{
   1159 		    	for (x = xcount ; x ;x--)
   1160 			    {
   1161 					pdest[0] = ((byte *)pcolormap[0])[psrc[0]];
   1162 					pdest[1] = ((byte *)pcolormap[1])[psrc[1]];
   1163 					pdest[2] = ((byte *)pcolormap[0])[psrc[2]];
   1164 					pdest[3] = ((byte *)pcolormap[1])[psrc[3]];
   1165 					pdest[4] = ((byte *)pcolormap[0])[psrc[4]];
   1166 					pdest[5] = ((byte *)pcolormap[1])[psrc[5]];
   1167 					pdest[6] = ((byte *)pcolormap[0])[psrc[6]];
   1168 					pdest[7] = ((byte *)pcolormap[1])[psrc[7]];
   1169 					pdest += 8; psrc += 8;
   1170 			    }
   1171 
   1172 				psrc += srcdelta;
   1173 			    pdest += rowdelta;
   1174 
   1175 		    	for (x = xcount ; x ;x--)
   1176 			    {
   1177 					pdest[0] = ((byte *)pcolormap[2])[psrc[0]];
   1178 					pdest[1] = ((byte *)pcolormap[3])[psrc[1]];
   1179 					pdest[2] = ((byte *)pcolormap[2])[psrc[2]];
   1180 					pdest[3] = ((byte *)pcolormap[3])[psrc[3]];
   1181 					pdest[4] = ((byte *)pcolormap[2])[psrc[4]];
   1182 					pdest[5] = ((byte *)pcolormap[3])[psrc[5]];
   1183 					pdest[6] = ((byte *)pcolormap[2])[psrc[6]];
   1184 					pdest[7] = ((byte *)pcolormap[3])[psrc[7]];
   1185 					pdest += 8; psrc += 8;
   1186 			    }
   1187 
   1188 				psrc += srcdelta;
   1189 			    pdest += rowdelta;
   1190 			}
   1191 		}
   1192 		else
   1193 		{
   1194 			byte	*psrc;
   1195 
   1196 			psrc = (byte *)src;
   1197 //			srcdelta += width;
   1198 //			rowdelta += width;
   1199 
   1200 			for (y = height ; y ; y--)
   1201 			{
   1202 		    	for (x = xcount ; x ;x--)
   1203 			    {
   1204 					pdest[0] = ((byte *)pcolormap[0])[psrc[0]];
   1205 					pdest[1] = ((byte *)pcolormap[0])[psrc[1]];
   1206 					pdest[2] = ((byte *)pcolormap[0])[psrc[2]];
   1207 					pdest[3] = ((byte *)pcolormap[0])[psrc[3]];
   1208 					pdest[4] = ((byte *)pcolormap[0])[psrc[4]];
   1209 					pdest[5] = ((byte *)pcolormap[0])[psrc[5]];
   1210 					pdest[6] = ((byte *)pcolormap[0])[psrc[6]];
   1211 					pdest[7] = ((byte *)pcolormap[0])[psrc[7]];
   1212 					pdest += 8; psrc += 8;
   1213 			    }
   1214 
   1215 				psrc += srcdelta;
   1216 			    pdest += rowdelta;
   1217 		    }
   1218 		}
   1219     }
   1220 }
   1221 
   1222 
   1223 /*
   1224 ===================
   1225 Update16_1
   1226 ===================
   1227 */
   1228 void Update16_1 (pixel_t *src, unsigned short *dest, int width,
   1229 		int height, int destrowbytes)
   1230 {
   1231 	int				x,y;
   1232 	unsigned		rowdelta, srcdelta;
   1233 	unsigned		xcount;
   1234 	pixel_t			*psrc;
   1235 	unsigned short	*pdest;
   1236 	int				xwidth;
   1237 
   1238 
   1239 	psrc = src;
   1240 	pdest = dest;
   1241 	
   1242 	xcount = width >> 3;
   1243 	srcdelta = vid.width - width;
   1244 
   1245 	xwidth = width - (xcount << 3);
   1246 	if (xwidth)
   1247 		Sys_Error ("Width not multiple of 8");
   1248 
   1249 	if ((vid_display == disp_framebuffer) && (vid_scale == 2))
   1250 	{
   1251 		int		nextrow = destrowbytes >> 1;
   1252 
   1253 	    rowdelta = (destrowbytes - ((width << 1) << 1) + destrowbytes) >> 1;
   1254 
   1255 		if (dither)
   1256 		{
   1257 			for (y = height ; y ; y--)
   1258 			{
   1259 		    	for (x = xcount ; x ;x--)
   1260 			    {
   1261 					unsigned	temp;
   1262 
   1263 					temp = psrc[0];
   1264 					pdest[0] = ((unsigned short *)pcolormap[0])[temp];
   1265 					pdest[1] = ((unsigned short *)pcolormap[1])[temp];
   1266 					pdest[nextrow] = ((unsigned short *)pcolormap[2])[temp];
   1267 					pdest[nextrow + 1] = ((unsigned short *)pcolormap[3])[temp];
   1268 					temp = psrc[1];
   1269 					pdest[2] = ((unsigned short *)pcolormap[0])[temp];
   1270 					pdest[3] = ((unsigned short *)pcolormap[1])[temp];
   1271 					pdest[nextrow + 2] = ((unsigned short *)pcolormap[2])[temp];
   1272 					pdest[nextrow + 3] = ((unsigned short *)pcolormap[3])[temp];
   1273 					temp = psrc[2];
   1274 					pdest[4] = ((unsigned short *)pcolormap[0])[temp];
   1275 					pdest[5] = ((unsigned short *)pcolormap[1])[temp];
   1276 					pdest[nextrow + 4] = ((unsigned short *)pcolormap[2])[temp];
   1277 					pdest[nextrow + 5] = ((unsigned short *)pcolormap[3])[temp];
   1278 					temp = psrc[3];
   1279 					pdest[6] = ((unsigned short *)pcolormap[0])[temp];
   1280 					pdest[7] = ((unsigned short *)pcolormap[1])[temp];
   1281 					pdest[nextrow + 6] = ((unsigned short *)pcolormap[2])[temp];
   1282 					pdest[nextrow + 7] = ((unsigned short *)pcolormap[3])[temp];
   1283 					temp = psrc[4];
   1284 					pdest[8] = ((unsigned short *)pcolormap[0])[temp];
   1285 					pdest[9] = ((unsigned short *)pcolormap[1])[temp];
   1286 					pdest[nextrow + 8] = ((unsigned short *)pcolormap[2])[temp];
   1287 					pdest[nextrow + 9] = ((unsigned short *)pcolormap[3])[temp];
   1288 					temp = psrc[5];
   1289 					pdest[10] = ((unsigned short *)pcolormap[0])[temp];
   1290 					pdest[11] = ((unsigned short *)pcolormap[1])[temp];
   1291 					pdest[nextrow + 10] = ((unsigned short *)pcolormap[2])[temp];
   1292 					pdest[nextrow + 11] = ((unsigned short *)pcolormap[3])[temp];
   1293 					temp = psrc[6];
   1294 					pdest[12] = ((unsigned short *)pcolormap[0])[temp];
   1295 					pdest[13] = ((unsigned short *)pcolormap[1])[temp];
   1296 					pdest[nextrow + 12] = ((unsigned short *)pcolormap[2])[temp];
   1297 					pdest[nextrow + 13] = ((unsigned short *)pcolormap[3])[temp];
   1298 					temp = psrc[7];
   1299 					pdest[14] = ((unsigned short *)pcolormap[0])[temp];
   1300 					pdest[15] = ((unsigned short *)pcolormap[1])[temp];
   1301 					pdest[nextrow + 14] = ((unsigned short *)pcolormap[2])[temp];
   1302 					pdest[nextrow + 15] = ((unsigned short *)pcolormap[3])[temp];
   1303 					pdest += 16; psrc += 8;
   1304 			    }
   1305 
   1306 				psrc += srcdelta;
   1307 			    pdest += rowdelta;
   1308 			}
   1309 		}
   1310 		else
   1311 		{
   1312 			for (y = height ; y ; y--)
   1313 			{
   1314 			for (x = xcount ; x ;x--)
   1315 			    {
   1316 					pdest[0] = pdest[1] = pdest[nextrow] =
   1317 							pdest[nextrow + 1] = pcolormap[0][psrc[0]];
   1318 					pdest[2] = pdest[3] = pdest[nextrow + 2] =
   1319 							pdest[nextrow + 3] = pcolormap[0][psrc[1]];
   1320 					pdest[4] = pdest[5] = pdest[nextrow + 4] =
   1321 							pdest[nextrow + 5] = pcolormap[0][psrc[2]];
   1322 					pdest[6] = pdest[7] = pdest[nextrow + 6] =
   1323 							pdest[nextrow + 7] = pcolormap[0][psrc[3]];
   1324 					pdest[8] = pdest[9] = pdest[nextrow + 8] =
   1325 							pdest[nextrow + 9] = pcolormap[0][psrc[4]];
   1326 					pdest[10] = pdest[11] = pdest[nextrow + 10] =
   1327 							pdest[nextrow + 11] = pcolormap[0][psrc[5]];
   1328 					pdest[12] = pdest[13] = pdest[nextrow + 12] =
   1329 							pdest[nextrow + 13] = pcolormap[0][psrc[6]];
   1330 					pdest[14] = pdest[15] = pdest[nextrow + 14] =
   1331 							pdest[nextrow + 15] = pcolormap[0][psrc[7]];
   1332 					pdest += 16; psrc += 8;
   1333 			    }
   1334 
   1335 				psrc += srcdelta;
   1336 			    pdest += rowdelta;
   1337 			}
   1338     	}
   1339 	}
   1340 	else
   1341 	{
   1342 	    rowdelta = (destrowbytes - (width<<1))>>1;
   1343 
   1344 		if (dither)
   1345 		{
   1346 			for (y = height ; y>0 ; y -= 2)
   1347 			{
   1348 		    	for (x = xcount ; x ;x--)
   1349 			    {
   1350 					pdest[0] = ((unsigned short *)pcolormap[0])[psrc[0]];
   1351 					pdest[1] = ((unsigned short *)pcolormap[1])[psrc[1]];
   1352 					pdest[2] = ((unsigned short *)pcolormap[0])[psrc[2]];
   1353 					pdest[3] = ((unsigned short *)pcolormap[1])[psrc[3]];
   1354 					pdest[4] = ((unsigned short *)pcolormap[0])[psrc[4]];
   1355 					pdest[5] = ((unsigned short *)pcolormap[1])[psrc[5]];
   1356 					pdest[6] = ((unsigned short *)pcolormap[0])[psrc[6]];
   1357 					pdest[7] = ((unsigned short *)pcolormap[1])[psrc[7]];
   1358 					pdest += 8; psrc += 8;
   1359 			    }
   1360 
   1361 				psrc += srcdelta;
   1362 			    pdest += rowdelta;
   1363 
   1364 		    	for (x = xcount ; x ;x--)
   1365 			    {
   1366 					pdest[0] = ((unsigned short *)pcolormap[2])[psrc[0]];
   1367 					pdest[1] = ((unsigned short *)pcolormap[3])[psrc[1]];
   1368 					pdest[2] = ((unsigned short *)pcolormap[2])[psrc[2]];
   1369 					pdest[3] = ((unsigned short *)pcolormap[3])[psrc[3]];
   1370 					pdest[4] = ((unsigned short *)pcolormap[2])[psrc[4]];
   1371 					pdest[5] = ((unsigned short *)pcolormap[3])[psrc[5]];
   1372 					pdest[6] = ((unsigned short *)pcolormap[2])[psrc[6]];
   1373 					pdest[7] = ((unsigned short *)pcolormap[3])[psrc[7]];
   1374 					pdest += 8; psrc += 8;
   1375 			    }
   1376 
   1377 				psrc += srcdelta;
   1378 			    pdest += rowdelta;
   1379 			}
   1380 		}
   1381 		else
   1382 		{
   1383 			for (y = height ; y ; y--)
   1384 			{
   1385 			for (x = xcount ; x ;x--)
   1386 			    {
   1387 					pdest[0] = pcolormap[0][psrc[0]];
   1388 					pdest[1] = pcolormap[0][psrc[1]];
   1389 					pdest[2] = pcolormap[0][psrc[2]];
   1390 					pdest[3] = pcolormap[0][psrc[3]];
   1391 					pdest[4] = pcolormap[0][psrc[4]];
   1392 					pdest[5] = pcolormap[0][psrc[5]];
   1393 					pdest[6] = pcolormap[0][psrc[6]];
   1394 					pdest[7] = pcolormap[0][psrc[7]];
   1395 					pdest += 8; psrc += 8;
   1396 			    }
   1397 
   1398 				psrc += srcdelta;
   1399 			    pdest += rowdelta;
   1400 			}
   1401     	}
   1402 	}
   1403 }
   1404 
   1405 
   1406 /*
   1407 ===================
   1408 Update32_1
   1409 ===================
   1410 */
   1411 void Update32_1 (pixel_t *src, unsigned *dest, int width, int height,
   1412 		int destrowbytes)
   1413 {
   1414 	int				x,y;
   1415 	unsigned		rowdelta, srcdelta;
   1416 	unsigned		xcount;
   1417 	pixel_t			*psrc;
   1418 	unsigned		*pdest;
   1419 	int				xwidth;
   1420 
   1421 	psrc = src;
   1422 	pdest = dest;
   1423 
   1424 	xcount = width >> 3;
   1425 	srcdelta = vid.width - width;
   1426 
   1427 	xwidth = width - (xcount << 3);
   1428 	if (xwidth)
   1429 		Sys_Error ("Width not multiple of 8");
   1430 
   1431 	if ((vid_display == disp_framebuffer) && (vid_scale == 2))
   1432 	{
   1433 		int		nextrow = destrowbytes >> 2;
   1434 
   1435 	    rowdelta = ((destrowbytes - ((width << 1) << 2)) >> 2)  +
   1436 				(destrowbytes >> 2);
   1437 
   1438 		for (y = height ; y ; y--)
   1439 		{
   1440 			for (x = xcount ; x ;x--)
   1441 		    {
   1442 				pdest[0] = pdest[1] = pdest[nextrow] =
   1443 						pdest[nextrow + 1] = pcolormap[0][psrc[0]];
   1444 				pdest[2] = pdest[3] = pdest[nextrow + 2] =
   1445 						pdest[nextrow + 3] = pcolormap[0][psrc[1]];
   1446 				pdest[4] = pdest[5] = pdest[nextrow + 4] =
   1447 						pdest[nextrow + 5] = pcolormap[0][psrc[2]];
   1448 				pdest[6] = pdest[7] = pdest[nextrow + 6] =
   1449 						pdest[nextrow + 7] = pcolormap[0][psrc[3]];
   1450 				pdest[8] = pdest[9] = pdest[nextrow + 8] =
   1451 						pdest[nextrow + 9] = pcolormap[0][psrc[4]];
   1452 				pdest[10] = pdest[11] = pdest[nextrow + 10] =
   1453 						pdest[nextrow + 11] = pcolormap[0][psrc[5]];
   1454 				pdest[12] = pdest[13] = pdest[nextrow + 12] =
   1455 						pdest[nextrow + 13] = pcolormap[0][psrc[6]];
   1456 				pdest[14] = pdest[15] = pdest[nextrow + 14] =
   1457 						pdest[nextrow + 15] = pcolormap[0][psrc[7]];
   1458 				pdest += 16; psrc += 8;
   1459 		    }
   1460 
   1461 			psrc += srcdelta;
   1462 		    pdest += rowdelta;
   1463 		}
   1464     }
   1465 	else
   1466 	{
   1467 	    rowdelta = (destrowbytes - (width<<2))>>2;
   1468 
   1469 		for (y = height ; y ; y--)
   1470 		{
   1471 			for (x = xcount ; x ;x--)
   1472 		    {
   1473 				pdest[0] = pcolormap[0][psrc[0]];
   1474 				pdest[1] = pcolormap[0][psrc[1]];
   1475 				pdest[2] = pcolormap[0][psrc[2]];
   1476 				pdest[3] = pcolormap[0][psrc[3]];
   1477 				pdest[4] = pcolormap[0][psrc[4]];
   1478 				pdest[5] = pcolormap[0][psrc[5]];
   1479 				pdest[6] = pcolormap[0][psrc[6]];
   1480 				pdest[7] = pcolormap[0][psrc[7]];
   1481 				pdest += 8; psrc += 8;
   1482 		    }
   1483 
   1484 			psrc += srcdelta;
   1485 		    pdest += rowdelta;
   1486 		}
   1487 	}
   1488 }
   1489 
   1490 
   1491 /*
   1492 ==========================================================================
   1493 
   1494 						NEXTSTEP VIEW CLASS
   1495 
   1496 ==========================================================================
   1497 */
   1498 
   1499 
   1500 @implementation QuakeView
   1501 
   1502 /*
   1503 =================
   1504 windowDidMove
   1505 
   1506 =================
   1507 */
   1508 - windowDidMove:sender
   1509 {
   1510     NXPoint	aPoint;
   1511     NXRect	winframe;
   1512 
   1513     aPoint.x = aPoint.y = 0;
   1514     [self convertPoint:&aPoint toView:nil];
   1515     [window convertBaseToScreen: &aPoint];
   1516     [window getFrame: &winframe];
   1517 
   1518     if ((int)aPoint.x & 7)
   1519     {
   1520 	[window moveTo:winframe.origin.x - ((int)aPoint.x&7) 
   1521 			:winframe.origin.y];
   1522 	[window getFrame: &winframe];
   1523     }
   1524     return self;
   1525 }
   1526 
   1527 - windowWillResize:sender toSize:(NXSize *)frameSize
   1528 {
   1529 	NXRect		fr, cont;
   1530 	
   1531 	fr.origin.x = fr.origin.y = 0;
   1532 	fr.size = *frameSize;
   1533 	
   1534 	[Window getContentRect:&cont forFrameRect: &fr style:[window style]];
   1535 
   1536 	cont.size.width = (int)cont.size.width & ~15;
   1537 	if (cont.size.width < 128)
   1538 		cont.size.width = 128;
   1539 	cont.size.height = (int)cont.size.height & ~3;
   1540 	if (cont.size.height < 32)
   1541 		cont.size.height = 32;
   1542 
   1543 	[Window getFrameRect:&fr forContentRect: &cont style:[window style]];
   1544 
   1545 	*frameSize = fr.size;
   1546 	
   1547 	return self;
   1548 }
   1549 
   1550 - windowDidResize:sender
   1551 {
   1552 	if (vid_display == disp_framebuffer)
   1553 		Sys_Error ("How the heck are you resizing a framebuffer window?!?");
   1554 
   1555 	vid.width = bounds.size.width/vid_scale;
   1556 	vid.height = bounds.size.height/vid_scale;
   1557 
   1558 //
   1559 // allocate memory for the back and translation buffers
   1560 //
   1561 	vid.rowbytes = vid.width;
   1562 	rowbytesnative = vid.width * pixbytesnative;
   1563 	
   1564 	AllocBuffers (true);
   1565 
   1566 	vid.conbuffer = vid.buffer;
   1567 	vid.conrowbytes = vid.rowbytes;
   1568 	vid.conwidth = vid.width;
   1569 	vid.conheight = vid.height;
   1570 
   1571 	vid.recalc_refdef = 1;
   1572 
   1573 	return self;
   1574 }
   1575 
   1576 -(BOOL) acceptsFirstResponder
   1577 {
   1578     return YES;
   1579 }
   1580 
   1581 
   1582 typedef struct
   1583 {
   1584 	int		source, dest;
   1585 } keymap_t;
   1586 
   1587 keymap_t keymaps[] =
   1588 {
   1589 	{103, K_RIGHTARROW},
   1590 	{102, K_LEFTARROW},
   1591 	{100, K_UPARROW},
   1592 	{101, K_DOWNARROW},
   1593 	{111, K_PAUSE},
   1594 
   1595 	{59, K_F1},
   1596 	{60, K_F2},
   1597 	{61, K_F3},
   1598 	{62, K_F4},
   1599 	{63, K_F5},
   1600 	{64, K_F6},
   1601 	{65, K_F7},
   1602 	{66, K_F8},
   1603 	{67, K_F9},
   1604 	{68, K_F10},
   1605 	{87, K_F11},
   1606 	{88, K_F12},
   1607 	
   1608 	{-1,-1}
   1609 };
   1610 
   1611 keymap_t flagmaps[] =
   1612 {
   1613 	{NX_SHIFTMASK, K_SHIFT},
   1614 	{NX_CONTROLMASK, K_CTRL},
   1615 	{NX_ALTERNATEMASK, K_ALT},
   1616 	{NX_COMMANDMASK, K_ALT},
   1617 	
   1618 	{-1,-1}
   1619 };
   1620 
   1621 /*
   1622 ===================
   1623 keyboard methods
   1624 ===================
   1625 */
   1626 - keyDown:(NXEvent *)theEvent
   1627 {
   1628     int	ch;
   1629 	keymap_t	*km;
   1630 	
   1631 	PSobscurecursor ();
   1632 
   1633 // check for non-ascii first
   1634 	ch = theEvent->data.key.keyCode;
   1635 	for (km=keymaps;km->source!=-1;km++)
   1636 		if (ch == km->source)
   1637 		{
   1638 			Key_Event (km->dest, true);
   1639 			return self;
   1640 		}
   1641 
   1642     ch = theEvent->data.key.charCode;
   1643 	if (ch >= 'A' && ch <= 'Z')
   1644 		ch += 'a' - 'A';
   1645     if (ch>=256)
   1646 		return self;
   1647 		
   1648 	Key_Event (ch, true);
   1649     return self;
   1650 }
   1651 
   1652 - flagsChanged:(NXEvent *)theEvent
   1653 {
   1654 	static int	oldflags;
   1655     int		newflags;
   1656 	int		delta;
   1657 	keymap_t	*km;
   1658 	int		i;
   1659 	
   1660 	PSobscurecursor ();
   1661     newflags = theEvent->flags;
   1662 	delta = newflags ^ oldflags;
   1663 	for (i=0 ; i<32 ; i++)
   1664 	{
   1665 		if ( !(delta & (1<<i)))
   1666 			continue;
   1667 	// changed
   1668 		for (km=flagmaps;km->source!=-1;km++)
   1669 			if ( (1<<i) == km->source)
   1670 			{
   1671 				if (newflags & (1<<i))
   1672 					Key_Event (km->dest, true);
   1673 				else
   1674 					Key_Event (km->dest, false);
   1675 			}
   1676 
   1677 	}
   1678 	
   1679 	oldflags = newflags;
   1680 		
   1681     return self;
   1682 }
   1683 
   1684 
   1685 - keyUp:(NXEvent *)theEvent
   1686 {
   1687     int	ch;
   1688  	keymap_t	*km;
   1689   
   1690  // check for non-ascii first
   1691 	ch = theEvent->data.key.keyCode;
   1692 	for (km=keymaps;km->source!=-1;km++)
   1693 		if (ch == km->source)
   1694 		{
   1695 			Key_Event (km->dest, false);
   1696 			return self;
   1697 		}
   1698 
   1699    ch = theEvent->data.key.charCode;
   1700 	if (ch >= 'A' && ch <= 'Z')
   1701 		ch += 'a' - 'A';
   1702     if (ch>=256)
   1703 		return self;
   1704 	Key_Event (ch, false);
   1705     return self;
   1706 }
   1707 
   1708 
   1709 - tiffShot
   1710 {
   1711 	id			imagerep, image;
   1712 	NXRect		r;
   1713 	NXStream	*stream;
   1714 	int			fd;
   1715 	int    		i; 
   1716 	char		tiffname[80]; 
   1717 	
   1718 	[vid_window_i getFrame: &r];
   1719 	r.origin.x = r.origin.y = 0;
   1720 	image = [[NXImage alloc] initSize: &r.size];
   1721 	imagerep = [[NXCachedImageRep alloc] initFromWindow:vid_window_i rect:&r];
   1722 	
   1723 	[image lockFocus];
   1724 	[imagerep draw];
   1725 	[image unlockFocus];
   1726 	
   1727 // 
   1728 // find a file name to save it to 
   1729 // 
   1730 	strcpy(tiffname,"quake00.tif");
   1731 		
   1732 	for (i=0 ; i<=99 ; i++) 
   1733 	{ 
   1734 		tiffname[5] = i/10 + '0'; 
   1735 		tiffname[6] = i%10 + '0'; 
   1736 		if (Sys_FileTime(tiffname) == -1)
   1737 			break;	// file doesn't exist
   1738 	} 
   1739 	if (i==100) 
   1740 		Sys_Error ("SCR_ScreenShot_f: Couldn't create a tiff"); 
   1741 
   1742 	fd = open (tiffname, O_RDWR|O_CREAT|O_TRUNC, 0666);
   1743 	stream = NXOpenFile (fd, NX_READWRITE);
   1744 	[image writeTIFF: stream];
   1745 	NXClose (stream);
   1746 	close (fd);
   1747 	printf ("wrote %s\n", tiffname);
   1748 
   1749 	[image free];
   1750 	[imagerep free];
   1751 	return self;
   1752 	
   1753 }
   1754 
   1755 - screenShot: sender
   1756 {
   1757 	return [self tiffShot];
   1758 }
   1759 
   1760 - setScaleFullScreen: sender
   1761 {
   1762 	VID_Shutdown ();
   1763 	if (vid_fullscreen)
   1764 	{
   1765 		vid_fullscreen = 0;
   1766 		VID_Restart (vid_display, vid_scale);
   1767 	}
   1768 	else
   1769 	{
   1770 		vid_fullscreen = 1;
   1771 		VID_Restart (vid_display, vid_scale);
   1772 	}
   1773 	return self;
   1774 }
   1775 
   1776 @end
   1777 
   1778 //============================================================================
   1779 
   1780 @implementation FrameWindow
   1781 
   1782 - windowExposed:(NXEvent *)theEvent
   1783 {
   1784 	return self;
   1785 }
   1786 
   1787 @end
   1788 
   1789