r_next.m (14811B)
1 2 #import <AppKit/AppKit.h> 3 #include "../ref_soft/r_local.h" 4 5 /* 6 ==================================================================== 7 8 OPENSTEP specific stuff 9 10 ==================================================================== 11 */ 12 13 @interface QuakeView : NSView 14 @end 15 16 NSWindow *vid_window_i; 17 QuakeView *vid_view_i; 18 19 unsigned *buffernative; 20 21 //=========================================================== 22 23 24 int Draw_SetResolution (void); 25 26 #define TYPE_FULLSCREEN 0 27 #define TYPE_WINDOWED 1 28 #define TYPE_STRETCHED 2 29 30 #define NUM_RESOLUTIONS 7 31 int resolutions[NUM_RESOLUTIONS][2] = { 32 {320,200}, {320,240}, {400,300}, {512,384}, {640,480}, {800,600}, {1024,768} }; 33 34 qboolean available[NUM_RESOLUTIONS][3]; 35 int mode_res = 0, mode_type = TYPE_WINDOWED; 36 37 byte gammatable[256]; // palette is sent through this 38 unsigned current_palette[256]; 39 unsigned gamma_palette[256]; 40 41 int cursor_res, cursor_type; 42 43 cvar_t *vid_x; 44 cvar_t *vid_y; 45 cvar_t *vid_mode; 46 cvar_t *vid_stretched; 47 cvar_t *vid_fullscreen; 48 cvar_t *draw_gamma; 49 50 void Draw_BuildGammaTable (void); 51 52 /* 53 ==================================================================== 54 55 MENU INTERACTION 56 57 ==================================================================== 58 */ 59 60 void FindModes (void) 61 { 62 if (mode_res < 0 || mode_res >= NUM_RESOLUTIONS) 63 mode_res = 0; 64 if (mode_type < 0 || mode_type > 3) 65 mode_type = 1; 66 67 } 68 69 void RM_Print (int x, int y, char *s) 70 { 71 while (*s) 72 { 73 Draw_Char (x, y, (*s)+128); 74 s++; 75 x += 8; 76 } 77 } 78 79 /* 80 ================ 81 Draw_MenuDraw 82 ================ 83 */ 84 void Draw_MenuDraw (void) 85 { 86 int i, j; 87 int y; 88 char string[32]; 89 90 Draw_Pic ( 4, 4, "vidmodes"); 91 92 RM_Print (80, 32, "fullscreen windowed stretched"); 93 RM_Print (80, 40, "---------- -------- ---------"); 94 y = 50; 95 96 // draw background behind selected mode 97 Draw_Fill ( (mode_type+1)*80, y+(mode_res)*10, 40,10, 8); 98 99 // draw available grid 100 for (i=0 ; i<NUM_RESOLUTIONS ; i++, y+= 10) 101 { 102 sprintf (string, "%ix%i", resolutions[i][0], resolutions[i][1]); 103 RM_Print (0, y, string); 104 for (j=0 ; j<3 ; j++) 105 if (available[i][j]) 106 RM_Print ( 80 + j*80, y, "*"); 107 } 108 109 // draw the cursor 110 Draw_Char (80 + cursor_type*80, 50 + cursor_res*10, 128 + 12+((int)(r_newrefdef.time*4)&1)); 111 } 112 113 114 #define K_TAB 9 115 #define K_ENTER 13 116 #define K_ESCAPE 27 117 #define K_SPACE 32 118 119 // normal keys should be passed as lowercased ascii 120 121 #define K_BACKSPACE 127 122 #define K_UPARROW 128 123 #define K_DOWNARROW 129 124 #define K_LEFTARROW 130 125 #define K_RIGHTARROW 131 126 127 /* 128 ================ 129 Draw_MenuKey 130 ================ 131 */ 132 void Draw_MenuKey (int key) 133 { 134 switch (key) 135 { 136 case K_LEFTARROW: 137 cursor_type--; 138 if (cursor_type < 0) 139 cursor_type = 2; 140 break; 141 142 case K_RIGHTARROW: 143 cursor_type++; 144 if (cursor_type > 2) 145 cursor_type = 0; 146 break; 147 148 case K_UPARROW: 149 cursor_res--; 150 if (cursor_res < 0) 151 cursor_res = NUM_RESOLUTIONS-1; 152 break; 153 154 case K_DOWNARROW: 155 cursor_res++; 156 if (cursor_res >= NUM_RESOLUTIONS) 157 cursor_res = 0; 158 break; 159 160 case K_ENTER: 161 ri.Cmd_ExecuteText (EXEC_NOW, va("vid_mode %i", cursor_res)); 162 switch (cursor_type) 163 { 164 case TYPE_FULLSCREEN: 165 ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 1"); 166 ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 0"); 167 break; 168 case TYPE_WINDOWED: 169 ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 0"); 170 ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 0"); 171 break; 172 case TYPE_STRETCHED: 173 ri.Cmd_ExecuteText (EXEC_NOW, "vid_fullscreen 0"); 174 ri.Cmd_ExecuteText (EXEC_NOW, "vid_stretched 1"); 175 break; 176 } 177 178 mode_res = cursor_res; 179 mode_type = cursor_type; 180 Draw_SetResolution (); 181 break; 182 183 default: 184 break; 185 } 186 } 187 188 //=========================================================== 189 190 191 /* 192 ================ 193 Draw_SetResolution 194 195 The vid structure will be filled in on return 196 Also allocates the z buffer and surface cache 197 ================ 198 */ 199 int Draw_SetResolution (void) 200 { 201 NSRect content; 202 203 if (vid_mode->value < 0) 204 ri.Cmd_ExecuteText (EXEC_NOW, "vid_mode 0"); 205 if (vid_mode->value >= NUM_RESOLUTIONS) 206 ri.Cmd_ExecuteText (EXEC_NOW, va("vid_mode %i", NUM_RESOLUTIONS-1)); 207 208 vid_mode->modified = false; 209 vid_fullscreen->modified = false; 210 vid_stretched->modified = false; 211 212 // free nativebuffer 213 if (buffernative) 214 { 215 free (buffernative); 216 buffernative = NULL; 217 } 218 219 // free z buffer 220 if (d_pzbuffer) 221 { 222 free (d_pzbuffer); 223 d_pzbuffer = NULL; 224 } 225 // free surface cache 226 if (sc_base) 227 { 228 D_FlushCaches (); 229 free (sc_base); 230 sc_base = NULL; 231 } 232 233 vid.width = resolutions[(int)(vid_mode->value)][0]; 234 vid.height = resolutions[(int)(vid_mode->value)][1]; 235 236 vid.win_width = vid.width; 237 vid.win_height = vid.height; 238 if (vid_stretched->value) 239 { 240 vid.win_width <<= 1; 241 vid.win_height <<= 1; 242 } 243 244 vid.aspect = 1; 245 vid.buffer = malloc (vid.width*vid.height); 246 vid.rowbytes = vid.width; 247 d_pzbuffer = malloc(vid.width*vid.height*2); 248 buffernative = malloc(vid.width*vid.height*4); 249 250 D_InitCaches (); 251 252 Sys_SetPalette ((byte *)d_8to24table); 253 254 if (vid_view_i) 255 [vid_view_i unlockFocus]; 256 if (vid_window_i) 257 [vid_window_i close]; 258 // 259 // open a window 260 // 261 content = NSMakeRect (vid_x->value,vid_y->value,vid.win_width, vid.win_height); 262 vid_window_i = [[NSWindow alloc] 263 initWithContentRect: content 264 styleMask: NSTitledWindowMask 265 backing: NSBackingStoreRetained 266 defer: NO 267 ]; 268 269 [vid_window_i setDelegate: vid_window_i]; 270 [vid_window_i display]; 271 [NSApp activateIgnoringOtherApps: YES]; 272 [vid_window_i makeKeyAndOrderFront: nil]; 273 274 // NSPing (); 275 276 content.origin.x = content.origin.y = 0; 277 vid_view_i = [[QuakeView alloc] initWithFrame: content]; 278 [vid_window_i setContentView: vid_view_i]; 279 [vid_window_i makeFirstResponder: vid_view_i]; 280 [vid_window_i setDelegate: vid_view_i]; 281 282 // [vid_window_i addToEventMask: NS_FLAGSCHANGEDMASK]; 283 [vid_window_i setTitle: @"Bitmap Quake Console"]; 284 [vid_window_i makeKeyAndOrderFront: nil]; 285 286 // leave focus locked forever 287 [vid_view_i lockFocus]; 288 289 ri.VID_SetSize (vid.width, vid.height); 290 291 return 0; 292 } 293 294 /* 295 @@@@@@@@@@@@@@@@@@@@@ 296 Draw_Init 297 298 @@@@@@@@@@@@@@@@@@@@@ 299 */ 300 int Draw_Init (void *window) 301 { 302 [NSApplication sharedApplication]; 303 [NSApp finishLaunching]; 304 305 ri.Con_Printf (PRINT_ALL, "refresh version: "REF_VERSION"\n"); 306 307 vid_x = ri.Cvar_Get ("vid_x", "0", CVAR_ARCHIVE); 308 vid_y = ri.Cvar_Get ("vid_y", "0", CVAR_ARCHIVE); 309 vid_mode = ri.Cvar_Get ("vid_mode", "0", CVAR_ARCHIVE); 310 vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE); 311 vid_stretched = ri.Cvar_Get ("vid_stretched", "0", CVAR_ARCHIVE); 312 draw_gamma = ri.Cvar_Get ("gamma", "1", CVAR_ARCHIVE); 313 314 Draw_GetPalette (); 315 316 Draw_BuildGammaTable (); 317 318 // get the lighting colormap 319 ri.FS_LoadFile ("gfx/colormap.lmp", (void **)&vid.colormap); 320 if (!vid.colormap) 321 { 322 ri.Con_Printf (PRINT_ALL, "ERROR: Couldn't load gfx/colormap.lmp"); 323 return -1; 324 } 325 326 Draw_SetResolution (); 327 328 R_Init (); 329 330 return 0; 331 } 332 333 334 /* 335 @@@@@@@@@@@@@@@@@@@@@ 336 Draw_Shutdown 337 338 @@@@@@@@@@@@@@@@@@@@@ 339 */ 340 void Draw_Shutdown (void) 341 { 342 R_Shutdown (); 343 } 344 345 346 /* 347 @@@@@@@@@@@@@@@@@@@@@ 348 Draw_BuildGammaTable 349 350 @@@@@@@@@@@@@@@@@@@@@ 351 */ 352 void Draw_BuildGammaTable (void) 353 { 354 int i, inf; 355 float g; 356 357 draw_gamma->modified = false; 358 g = draw_gamma->value; 359 360 if (g == 1.0) 361 { 362 for (i=0 ; i<256 ; i++) 363 gammatable[i] = i; 364 return; 365 } 366 367 for (i=0 ; i<256 ; i++) 368 { 369 inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; 370 if (inf < 0) 371 inf = 0; 372 if (inf > 255) 373 inf = 255; 374 gammatable[i] = inf; 375 } 376 } 377 378 379 /* 380 @@@@@@@@@@@@@@@@@@@@@ 381 Draw_BeginFram 382 383 @@@@@@@@@@@@@@@@@@@@@ 384 */ 385 void Draw_BeginFrame (void) 386 { 387 if (vid_mode->modified || vid_fullscreen->modified 388 || vid_stretched->modified) 389 Draw_SetResolution (); 390 391 if (draw_gamma->modified) 392 { 393 Draw_BuildGammaTable (); 394 Sys_SetPalette ((byte *)current_palette); 395 } 396 397 // MGL_beginDirectAccess(); 398 // vid.buffer = mgldc->surface; 399 // vid.rowbytes = mgldc->mi.bytesPerLine; 400 } 401 402 403 /* 404 @@@@@@@@@@@@@@@@@@@@@ 405 Draw_EndFrame 406 407 @@@@@@@@@@@@@@@@@@@@@ 408 */ 409 void Draw_EndFrame (void) 410 { 411 int i, c; 412 int bps, spp, bpp, bpr; 413 unsigned char *planes[5]; 414 NSRect bounds; 415 416 // translate to 24 bit color 417 c = vid.width*vid.height; 418 for (i=0 ; i<c ; i++) 419 buffernative[i] = gamma_palette[vid.buffer[i]]; 420 421 bps = 8; 422 spp = 3; 423 bpp = 32; 424 bpr = vid.width * 4; 425 planes[0] = (unsigned char *)buffernative; 426 427 bounds = [vid_view_i bounds]; 428 429 NSDrawBitmap( 430 bounds, 431 vid.width, 432 vid.height, 433 bps, 434 spp, 435 bpp, 436 bpr, 437 NO, 438 NO, 439 @"NSDeviceRGBColorSpace", 440 planes 441 ); 442 } 443 444 445 //=============================================================================== 446 447 #define HUNK_MAGIC 0xffaffaff 448 typedef struct 449 { 450 int magic; 451 int length; 452 int pad[6]; 453 } hunkheader_t; 454 455 hunkheader_t *membase; 456 int maxsize; 457 int cursize; 458 459 void *Hunk_Begin (void) 460 { 461 kern_return_t r; 462 463 // reserve a huge chunk of memory, but don't commit any yet 464 maxsize = 16*1024*1024; 465 cursize = 0; 466 membase = NULL; 467 r = vm_allocate(task_self(), (vm_address_t *)&membase, maxsize, 1); 468 if (!membase || r != KERN_SUCCESS) 469 ri.Sys_Error (ERR_FATAL,"vm_allocate failed"); 470 membase->magic = HUNK_MAGIC; 471 membase->length = maxsize; 472 cursize = 32; 473 return (void *)((byte *)membase + cursize); 474 } 475 476 void *Hunk_Alloc (int size) 477 { 478 // round to cacheline 479 size = (size+31)&~31; 480 481 cursize += size; 482 483 if (cursize > maxsize) 484 ri.Sys_Error (ERR_DROP, "Hunk_Alloc overflow"); 485 486 memset ((byte *)membase+cursize-size,0,size); 487 488 return (void *)((byte *)membase+cursize-size); 489 } 490 491 int Hunk_End (void) 492 { 493 kern_return_t r; 494 495 // round to pagesize 496 cursize = (cursize+vm_page_size)&~(vm_page_size-1); 497 membase->length = cursize; 498 r = vm_deallocate(task_self(), 499 (vm_address_t)((byte *)membase + cursize), 500 maxsize - cursize); 501 if ( r != KERN_SUCCESS ) 502 ri.Sys_Error (ERR_DROP, "vm_deallocate failed"); 503 return cursize; 504 } 505 506 void Hunk_Free (void *base) 507 { 508 hunkheader_t *h; 509 kern_return_t r; 510 511 h = ((hunkheader_t *)base) - 1; 512 if (h->magic != HUNK_MAGIC) 513 ri.Sys_Error (ERR_FATAL, "Hunk_Free: bad magic"); 514 515 r = vm_deallocate(task_self(), (vm_address_t)h, h->length); 516 if ( r != KERN_SUCCESS ) 517 ri.Sys_Error (ERR_DROP, "vm_deallocate failed"); 518 } 519 520 521 /* 522 ================ 523 Sys_MakeCodeWriteable 524 ================ 525 */ 526 void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) 527 { 528 } 529 530 531 /* 532 ================ 533 Sys_SetPalette 534 ================ 535 */ 536 void Sys_SetPalette (byte *palette) 537 { 538 byte *p; 539 int i; 540 541 memcpy (current_palette, palette, sizeof(current_palette)); 542 p = (byte *)gamma_palette; 543 // gamma correct and byte swap 544 for (i=0 ; i<256 ; i++, p+=4, palette+=4) 545 { 546 p[0] = gammatable[palette[0]]; 547 p[1] = gammatable[palette[1]]; 548 p[2] = gammatable[palette[2]]; 549 p[3] = 0xff; 550 } 551 552 } 553 554 555 /* 556 ========================================================================== 557 558 NEXTSTEP VIEW CLASS 559 560 ========================================================================== 561 */ 562 #include "../client/keys.h" 563 564 void IN_ActivateMouse (void); 565 void IN_DeactivateMouse (void); 566 567 @implementation QuakeView 568 569 -(BOOL) acceptsFirstResponder 570 { 571 return YES; 572 } 573 574 - (void)windowDidMove: (NSNotification *)note 575 { 576 NSRect r; 577 578 r = [vid_window_i frame]; 579 ri.Cmd_ExecuteText (EXEC_NOW, va("vid_x %i", (int)r.origin.x+1)); 580 ri.Cmd_ExecuteText (EXEC_NOW, va("vid_y %i", (int)r.origin.y+1)); 581 } 582 583 - (void)becomeKeyWindow 584 { 585 IN_ActivateMouse (); 586 } 587 588 - (void)resignKeyWindow 589 { 590 IN_DeactivateMouse (); 591 } 592 593 594 typedef struct 595 { 596 int source, dest; 597 } keymap_t; 598 599 keymap_t keymaps[] = 600 { 601 {103, K_RIGHTARROW}, 602 {102, K_LEFTARROW}, 603 {100, K_UPARROW}, 604 {101, K_DOWNARROW}, 605 606 {59, K_F1}, 607 {60, K_F2}, 608 {61, K_F3}, 609 {62, K_F4}, 610 {63, K_F5}, 611 {64, K_F6}, 612 {65, K_F7}, 613 {66, K_F8}, 614 {67, K_F9}, 615 {68, K_F10}, 616 {87, K_F11}, 617 {88, K_F12}, 618 619 {-1,-1} 620 }; 621 622 keymap_t flagmaps[] = 623 { 624 {NSShiftKeyMask, K_SHIFT}, 625 {NSControlKeyMask, K_CTRL}, 626 {NSAlternateKeyMask, K_ALT}, 627 {NSCommandKeyMask, K_ALT}, 628 629 {-1,-1} 630 }; 631 632 - (void)mouseDown:(NSEvent *)theEvent 633 { 634 Key_Event (K_MOUSE1, true); 635 } 636 - (void)mouseUp:(NSEvent *)theEvent 637 { 638 Key_Event (K_MOUSE1, false); 639 } 640 - (void)rightMouseDown:(NSEvent *)theEvent 641 { 642 Key_Event (K_MOUSE2, true); 643 } 644 - (void)rightMouseUp:(NSEvent *)theEvent 645 { 646 Key_Event (K_MOUSE2, false); 647 } 648 649 650 /* 651 =================== 652 keyboard methods 653 =================== 654 */ 655 - (void)keyDown:(NSEvent *)theEvent 656 { 657 int ch; 658 keymap_t *km; 659 660 // PSobscurecursor (); 661 662 // check for non-ascii first 663 ch = [theEvent keyCode]; 664 for (km=keymaps;km->source!=-1;km++) 665 if (ch == km->source) 666 { 667 Key_Event (km->dest, true); 668 return; 669 } 670 671 ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; 672 if (ch >= 'A' && ch <= 'Z') 673 ch += 'a' - 'A'; 674 if (ch>=256) 675 return; 676 677 Key_Event (ch, true); 678 } 679 680 - (void)flagsChanged:(NSEvent *)theEvent 681 { 682 static int oldflags; 683 int newflags; 684 int delta; 685 keymap_t *km; 686 int i; 687 688 // PSobscurecursor (); 689 newflags = [theEvent modifierFlags]; 690 delta = newflags ^ oldflags; 691 for (i=0 ; i<32 ; i++) 692 { 693 if ( !(delta & (1<<i))) 694 continue; 695 // changed 696 for (km=flagmaps;km->source!=-1;km++) 697 if ( (1<<i) == km->source) 698 { 699 if (newflags & (1<<i)) 700 Key_Event (km->dest, true); 701 else 702 Key_Event (km->dest, false); 703 } 704 705 } 706 707 oldflags = newflags; 708 } 709 710 711 - (void)keyUp:(NSEvent *)theEvent 712 { 713 int ch; 714 keymap_t *km; 715 716 // check for non-ascii first 717 ch = [theEvent keyCode]; 718 for (km=keymaps;km->source!=-1;km++) 719 if (ch == km->source) 720 { 721 Key_Event (km->dest, false); 722 return; 723 } 724 725 ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; 726 if (ch >= 'A' && ch <= 'Z') 727 ch += 'a' - 'A'; 728 if (ch>=256) 729 return; 730 Key_Event (ch, false); 731 } 732 733 @end 734 735