1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20#include <termios.h> 21#include <sys/ioctl.h> 22#include <sys/stat.h> 23#include <sys/vt.h> 24#include <stdarg.h> 25#include <stdio.h> 26#include <signal.h> 27 28#include <asm/io.h> 29 30#include "vga.h" 31#include "vgakeyboard.h" 32#include "vgamouse.h" 33 34#include "quakedef.h" 35#include "d_local.h" 36 37#define stringify(m) { #m, m } 38 39unsigned short d_8to16table[256]; 40static byte *vid_surfcache; 41static int VID_highhunkmark; 42 43int num_modes; 44vga_modeinfo *modes; 45int current_mode; 46 47int num_shades=32; 48 49struct 50{ 51 char *name; 52 int num; 53} mice[] = 54{ 55 stringify(MOUSE_MICROSOFT), 56 stringify(MOUSE_MOUSESYSTEMS), 57 stringify(MOUSE_MMSERIES), 58 stringify(MOUSE_LOGITECH), 59 stringify(MOUSE_BUSMOUSE), 60 stringify(MOUSE_PS2), 61}; 62 63static unsigned char scantokey[128]; 64static byte vid_current_palette[768]; 65 66int num_mice = sizeof (mice) / sizeof(mice[0]); 67 68int d_con_indirect = 0; 69 70int svgalib_inited=0; 71int UseMouse = 1; 72int UseDisplay = 1; 73int UseKeyboard = 1; 74 75int mouserate = MOUSE_DEFAULTSAMPLERATE; 76 77cvar_t vid_mode = {"vid_mode","5",false}; 78cvar_t vid_redrawfull = {"vid_redrawfull","0",false}; 79cvar_t vid_waitforrefresh = {"vid_waitforrefresh","0",true}; 80 81char *framebuffer_ptr; 82 83cvar_t mouse_button_commands[3] = 84{ 85 {"mouse1","+attack"}, 86 {"mouse2","+strafe"}, 87 {"mouse3","+forward"}, 88}; 89 90int mouse_buttons; 91int mouse_buttonstate; 92int mouse_oldbuttonstate; 93float mouse_x, mouse_y; 94float old_mouse_x, old_mouse_y; 95int mx, my; 96 97cvar_t m_filter = {"m_filter","0"}; 98 99static byte backingbuf[48*24]; 100 101int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; 102byte *VGA_pagebase; 103 104void VGA_UpdatePlanarScreen (void *srcbuffer); 105 106void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) 107{ 108 int i, j, k, plane, reps, repshift, offset, vidpage, off; 109 110 if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return; 111 112 if (vid.aspect > 1.5) 113 { 114 reps = 2; 115 repshift = 1; 116 } else { 117 reps = 1; 118 repshift = 0; 119 } 120 121 vidpage = 0; 122 vga_setpage(0); 123 124 if (VGA_planar) 125 { 126 for (plane=0 ; plane<4 ; plane++) 127 { 128 // select the correct plane for reading and writing 129 outb(0x02, 0x3C4); 130 outb(1 << plane, 0x3C5); 131 outb(4, 0x3CE); 132 outb(plane, 0x3CF); 133 134 for (i=0 ; i<(height << repshift) ; i += reps) 135 { 136 for (k=0 ; k<reps ; k++) 137 { 138 for (j=0 ; j<(width >> 2) ; j++) 139 { 140 backingbuf[(i + k) * 24 + (j << 2) + plane] = 141 vid.direct[(y + i + k) * VGA_rowbytes + 142 (x >> 2) + j]; 143 vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = 144 pbitmap[(i >> repshift) * 24 + 145 (j << 2) + plane]; 146 } 147 } 148 } 149 } 150 } else { 151 for (i=0 ; i<(height << repshift) ; i += reps) 152 { 153 for (j=0 ; j<reps ; j++) 154 { 155 offset = x + ((y << repshift) + i + j) * vid.rowbytes; 156 off = offset % 0x10000; 157 if ((offset / 0x10000) != vidpage) { 158 vidpage=offset / 0x10000; 159 vga_setpage(vidpage); 160 } 161 memcpy (&backingbuf[(i + j) * 24], 162 vid.direct + off, width); 163 memcpy (vid.direct + off, 164 &pbitmap[(i >> repshift)*width], width); 165 } 166 } 167 } 168} 169 170void D_EndDirectRect (int x, int y, int width, int height) 171{ 172 int i, j, k, plane, reps, repshift, offset, vidpage, off; 173 174 if (!svgalib_inited || !vid.direct || !vga_oktowrite()) return; 175 176 if (vid.aspect > 1.5) 177 { 178 reps = 2; 179 repshift = 1; 180 } else { 181 reps = 1; 182 repshift = 0; 183 } 184 185 vidpage = 0; 186 vga_setpage(0); 187 188 if (VGA_planar) 189 { 190 for (plane=0 ; plane<4 ; plane++) 191 { 192 // select the correct plane for writing 193 outb(2, 0x3C4); 194 outb(1 << plane, 0x3C5); 195 outb(4, 0x3CE); 196 outb(plane, 0x3CF); 197 198 for (i=0 ; i<(height << repshift) ; i += reps) 199 { 200 for (k=0 ; k<reps ; k++) 201 { 202 for (j=0 ; j<(width >> 2) ; j++) 203 { 204 vid.direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = 205 backingbuf[(i + k) * 24 + (j << 2) + plane]; 206 } 207 } 208 } 209 } 210 } else { 211 for (i=0 ; i<(height << repshift) ; i += reps) 212 { 213 for (j=0 ; j<reps ; j++) 214 { 215 offset = x + ((y << repshift) + i + j) * vid.rowbytes; 216 off = offset % 0x10000; 217 if ((offset / 0x10000) != vidpage) { 218 vidpage=offset / 0x10000; 219 vga_setpage(vidpage); 220 } 221 memcpy (vid.direct + off, 222 &backingbuf[(i +j)*24], 223 width); 224 } 225 } 226 } 227} 228 229/* 230================= 231VID_Gamma_f 232 233Keybinding command 234================= 235*/ 236void VID_Gamma_f (void) 237{ 238 float gamma, f, inf; 239 unsigned char palette[768]; 240 int i; 241 242 if (Cmd_Argc () == 2) 243 { 244 gamma = Q_atof (Cmd_Argv(1)); 245 246 for (i=0 ; i<768 ; i++) 247 { 248 f = pow ( (host_basepal[i]+1)/256.0 , gamma ); 249 inf = f*255 + 0.5; 250 if (inf < 0) 251 inf = 0; 252 if (inf > 255) 253 inf = 255; 254 palette[i] = inf; 255 } 256 257 VID_SetPalette (palette); 258 259 vid.recalc_refdef = 1; // force a surface cache flush 260 } 261} 262 263void VID_DescribeMode_f (void) 264{ 265 int modenum; 266 267 modenum = Q_atoi (Cmd_Argv(1)); 268 if ((modenum >= num_modes) || (modenum < 0 ) || !modes[modenum].width) 269 Con_Printf("Invalid video mode: %d!\n",modenum); 270 Con_Printf("%d: %d x %d - ",modenum,modes[modenum].width,modes[modenum].height); 271 if (modes[modenum].bytesperpixel == 0) 272 Con_Printf("ModeX\n"); 273 else 274 Con_Printf("%d bpp\n", modes[modenum].bytesperpixel<<3); 275} 276 277void VID_DescribeModes_f (void) 278{ 279 int i; 280 281 for (i=0;i<num_modes;i++) 282 if (modes[i].width) { 283 Con_Printf("%d: %d x %d - ", i, modes[i].width,modes[i].height); 284 if (modes[i].bytesperpixel == 0) 285 Con_Printf("ModeX\n"); 286 else 287 Con_Printf("%d bpp\n", modes[i].bytesperpixel<<3); 288 } 289} 290 291/* 292================ 293VID_NumModes 294================ 295*/ 296int VID_NumModes () 297{ 298 int i,i1=0; 299 300 for (i=0;i<num_modes;i++) 301 i1+=(modes[i].width?1:0); 302 return (i1); 303} 304 305void VID_NumModes_f (void) 306{ 307 Con_Printf("%d modes\n",VID_NumModes()); 308} 309 310void VID_Debug_f (void) 311{ 312 Con_Printf("mode: %d\n",current_mode); 313 Con_Printf("height x width: %d x %d\n",vid.height,vid.width); 314 Con_Printf("bpp: %d\n",modes[current_mode].bytesperpixel*8); 315 Con_Printf("vid.aspect: %f\n",vid.aspect); 316} 317 318 319 320void VID_InitModes(void) 321{ 322 323 int i; 324 325// get complete information on all modes 326 327 num_modes = vga_lastmodenumber()+1; 328 modes = Z_Malloc(num_modes * sizeof(vga_modeinfo)); 329 for (i=0 ; i<num_modes ; i++) 330 { 331 if (vga_hasmode(i)) 332 Q_memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo)); 333 else 334 modes[i].width = 0; // means not available 335 } 336 337// filter for modes i don't support 338 339 for (i=0 ; i<num_modes ; i++) 340 { 341 if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) 342 modes[i].width = 0; 343 } 344 345} 346 347int get_mode(char *name, int width, int height, int depth) 348{ 349 350 int i; 351 int ok, match; 352 353 match = (!!width) + (!!height)*2 + (!!depth)*4; 354 355 if (name) 356 { 357 i = vga_getmodenumber(name); 358 if (!modes[i].width) 359 { 360 Sys_Printf("Mode [%s] not supported\n", name); 361 i = G320x200x256; 362 } 363 } 364 else 365 { 366 for (i=0 ; i<num_modes ; i++) 367 if (modes[i].width) 368 { 369 ok = (modes[i].width == width) 370 + (modes[i].height == height)*2 371 + (modes[i].bytesperpixel == depth/8)*4; 372 if ((ok & match) == ok) 373 break; 374 } 375 if (i==num_modes) 376 { 377 Sys_Printf("Mode %dx%d (%d bits) not supported\n", 378 width, height, depth); 379 i = G320x200x256; 380 } 381 } 382 383 return i; 384 385} 386 387int matchmouse(int mouse, char *name) 388{ 389 int i; 390 for (i=0 ; i<num_mice ; i++) 391 if (!strcmp(mice[i].name, name)) 392 return i; 393 return mouse; 394} 395 396#if 0 397 398void vtswitch(int newconsole) 399{ 400 401 int fd; 402 struct vt_stat x; 403 404// switch consoles and wait until reactivated 405 fd = open("/dev/console", O_RDONLY); 406 ioctl(fd, VT_GETSTATE, &x); 407 ioctl(fd, VT_ACTIVATE, newconsole); 408 ioctl(fd, VT_WAITACTIVE, x.v_active); 409 close(fd); 410 411} 412 413#endif 414 415void keyhandler(int scancode, int state) 416{ 417 418 int sc; 419 420 sc = scancode & 0x7f; 421// Con_Printf("scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":""); 422 Key_Event(scantokey[sc], state == KEY_EVENTPRESS); 423 424} 425 426void VID_Shutdown(void) 427{ 428 429 if (!svgalib_inited) return; 430 431// printf("shutdown graphics called\n"); 432 if (UseKeyboard) 433 keyboard_close(); 434 if (UseDisplay) 435 vga_setmode(TEXT); 436// printf("shutdown graphics finished\n"); 437 438 svgalib_inited = 0; 439 440} 441 442void VID_ShiftPalette(unsigned char *p) 443{ 444 VID_SetPalette(p); 445} 446 447void VID_SetPalette(byte *palette) 448{ 449 450 static int tmppal[256*3]; 451 int *tp; 452 int i; 453 454 if (!svgalib_inited) 455 return; 456 457 memcpy(vid_current_palette, palette, sizeof(vid_current_palette)); 458 459 if (vga_getcolors() == 256) 460 { 461 462 tp = tmppal; 463 for (i=256*3 ; i ; i--) 464 *(tp++) = *(palette++) >> 2; 465 466 if (UseDisplay && vga_oktowrite()) 467 vga_setpalvec(0, 256, tmppal); 468 469 } 470} 471 472int VID_SetMode (int modenum, unsigned char *palette) 473{ 474 int bsize, zsize, tsize; 475 476 if ((modenum >= num_modes) || (modenum < 0) || !modes[modenum].width) 477 { 478 Cvar_SetValue ("vid_mode", (float)current_mode); 479 480 Con_Printf("No such video mode: %d\n",modenum); 481 482 return 0; 483 } 484 485 Cvar_SetValue ("vid_mode", (float)modenum); 486 487 current_mode=modenum; 488 489 vid.width = modes[current_mode].width; 490 vid.height = modes[current_mode].height; 491 492 VGA_width = modes[current_mode].width; 493 VGA_height = modes[current_mode].height; 494 VGA_planar = modes[current_mode].bytesperpixel == 0; 495 VGA_rowbytes = modes[current_mode].linewidth; 496 vid.rowbytes = modes[current_mode].linewidth; 497 if (VGA_planar) { 498 VGA_bufferrowbytes = modes[current_mode].linewidth * 4; 499 vid.rowbytes = modes[current_mode].linewidth*4; 500 } 501 502 vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); 503 vid.colormap = (pixel_t *) host_colormap; 504 vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); 505 vid.conrowbytes = vid.rowbytes; 506 vid.conwidth = vid.width; 507 vid.conheight = vid.height; 508 vid.numpages = 1; 509 510 vid.maxwarpwidth = WARP_WIDTH; 511 vid.maxwarpheight = WARP_HEIGHT; 512 513 // alloc zbuffer and surface cache 514 if (d_pzbuffer) { 515 D_FlushCaches(); 516 Hunk_FreeToHighMark (VID_highhunkmark); 517 d_pzbuffer = NULL; 518 vid_surfcache = NULL; 519 } 520 521 bsize = vid.rowbytes * vid.height; 522 tsize = D_SurfaceCacheForRes (vid.width, vid.height); 523 zsize = vid.width * vid.height * sizeof(*d_pzbuffer); 524 525 VID_highhunkmark = Hunk_HighMark (); 526 527 d_pzbuffer = Hunk_HighAllocName (bsize+tsize+zsize, "video"); 528 529 vid_surfcache = ((byte *)d_pzbuffer) + zsize; 530 531 vid.conbuffer = vid.buffer = (pixel_t *)(((byte *)d_pzbuffer) + zsize + tsize); 532 533 D_InitCaches (vid_surfcache, tsize); 534 535// get goin' 536 537 vga_setmode(current_mode); 538 VID_SetPalette(palette); 539 540 VGA_pagebase = vid.direct = framebuffer_ptr = (char *) vga_getgraphmem(); 541// if (vga_setlinearaddressing()>0) 542// framebuffer_ptr = (char *) vga_getgraphmem(); 543 if (!framebuffer_ptr) 544 Sys_Error("This mode isn't hapnin'\n"); 545 546 vga_setpage(0); 547 548 svgalib_inited=1; 549 550 vid.recalc_refdef = 1; // force a surface cache flush 551 552 return 0; 553} 554 555void VID_Init(unsigned char *palette) 556{ 557 558 int i; 559 int w, h, d; 560 561 if (svgalib_inited) 562 return; 563 564// Cmd_AddCommand ("gamma", VID_Gamma_f); 565 566 if (UseDisplay) 567 { 568 vga_init(); 569 570 VID_InitModes(); 571 572 Cvar_RegisterVariable (&vid_mode); 573 Cvar_RegisterVariable (&vid_redrawfull); 574 Cvar_RegisterVariable (&vid_waitforrefresh); 575 576 Cmd_AddCommand("vid_nummodes", VID_NumModes_f); 577 Cmd_AddCommand("vid_describemode", VID_DescribeMode_f); 578 Cmd_AddCommand("vid_describemodes", VID_DescribeModes_f); 579 Cmd_AddCommand("vid_debug", VID_Debug_f); 580 581 // interpret command-line params 582 583 w = h = d = 0; 584 if (getenv("GSVGAMODE")) 585 current_mode = get_mode(getenv("GSVGAMODE"), w, h, d); 586 else if (COM_CheckParm("-mode")) 587 current_mode = get_mode(com_argv[COM_CheckParm("-mode")+1], w, h, d); 588 else if (COM_CheckParm("-w") || COM_CheckParm("-h") 589 || COM_CheckParm("-d")) 590 { 591 if (COM_CheckParm("-w")) 592 w = Q_atoi(com_argv[COM_CheckParm("-w")+1]); 593 if (COM_CheckParm("-h")) 594 h = Q_atoi(com_argv[COM_CheckParm("-h")+1]); 595 if (COM_CheckParm("-d")) 596 d = Q_atoi(com_argv[COM_CheckParm("-d")+1]); 597 current_mode = get_mode(0, w, h, d); 598 } 599 else 600 current_mode = G320x200x256; 601 602 // set vid parameters 603 VID_SetMode(current_mode, palette); 604 605 VID_SetPalette(palette); 606 607 // we do want to run in the background when switched away 608 vga_runinbackground(1); 609 } 610 611 if (COM_CheckParm("-nokbd")) UseKeyboard = 0; 612 613 if (UseKeyboard) 614 { 615 for (i=0 ; i<128 ; i++) 616 scantokey[i] = ' '; 617 618 scantokey[42] = K_SHIFT; 619 scantokey[54] = K_SHIFT; 620 scantokey[72] = K_UPARROW; 621 scantokey[103] = K_UPARROW; 622 scantokey[80] = K_DOWNARROW; 623 scantokey[108] = K_DOWNARROW; 624 scantokey[75] = K_LEFTARROW; 625 scantokey[105] = K_LEFTARROW; 626 scantokey[77] = K_RIGHTARROW; 627 scantokey[106] = K_RIGHTARROW; 628 scantokey[29] = K_CTRL; 629 scantokey[97] = K_CTRL; 630 scantokey[56] = K_ALT; 631 scantokey[100] = K_ALT; 632// scantokey[58] = JK_CAPS; 633// scantokey[69] = JK_NUM_LOCK; 634 scantokey[71] = K_HOME; 635 scantokey[73] = K_PGUP; 636 scantokey[79] = K_END; 637 scantokey[81] = K_PGDN; 638 scantokey[82] = K_INS; 639 scantokey[83] = K_DEL; 640 scantokey[1 ] = K_ESCAPE; 641 scantokey[28] = K_ENTER; 642 scantokey[15] = K_TAB; 643 scantokey[14] = K_BACKSPACE; 644 scantokey[119] = K_PAUSE; 645 scantokey[57] = ' '; 646 647 scantokey[102] = K_HOME; 648 scantokey[104] = K_PGUP; 649 scantokey[107] = K_END; 650 scantokey[109] = K_PGDN; 651 scantokey[110] = K_INS; 652 scantokey[111] = K_DEL; 653 654 scantokey[2] = '1'; 655 scantokey[3] = '2'; 656 scantokey[4] = '3'; 657 scantokey[5] = '4'; 658 scantokey[6] = '5'; 659 scantokey[7] = '6'; 660 scantokey[8] = '7'; 661 scantokey[9] = '8'; 662 scantokey[10] = '9'; 663 scantokey[11] = '0'; 664 scantokey[12] = '-'; 665 scantokey[13] = '='; 666 scantokey[41] = '`'; 667 scantokey[26] = '['; 668 scantokey[27] = ']'; 669 scantokey[39] = ';'; 670 scantokey[40] = '\''; 671 scantokey[51] = ','; 672 scantokey[52] = '.'; 673 scantokey[53] = '/'; 674 scantokey[43] = '\\'; 675 676 scantokey[59] = K_F1; 677 scantokey[60] = K_F2; 678 scantokey[61] = K_F3; 679 scantokey[62] = K_F4; 680 scantokey[63] = K_F5; 681 scantokey[64] = K_F6; 682 scantokey[65] = K_F7; 683 scantokey[66] = K_F8; 684 scantokey[67] = K_F9; 685 scantokey[68] = K_F10; 686 scantokey[87] = K_F11; 687 scantokey[88] = K_F12; 688 scantokey[30] = 'a'; 689 scantokey[48] = 'b'; 690 scantokey[46] = 'c'; 691 scantokey[32] = 'd'; 692 scantokey[18] = 'e'; 693 scantokey[33] = 'f'; 694 scantokey[34] = 'g'; 695 scantokey[35] = 'h'; 696 scantokey[23] = 'i'; 697 scantokey[36] = 'j'; 698 scantokey[37] = 'k'; 699 scantokey[38] = 'l'; 700 scantokey[50] = 'm'; 701 scantokey[49] = 'n'; 702 scantokey[24] = 'o'; 703 scantokey[25] = 'p'; 704 scantokey[16] = 'q'; 705 scantokey[19] = 'r'; 706 scantokey[31] = 's'; 707 scantokey[20] = 't'; 708 scantokey[22] = 'u'; 709 scantokey[47] = 'v'; 710 scantokey[17] = 'w'; 711 scantokey[45] = 'x'; 712 scantokey[21] = 'y'; 713 scantokey[44] = 'z'; 714 715 if (keyboard_init()) 716 Sys_Error("keyboard_init() failed"); 717 keyboard_seteventhandler(keyhandler); 718 } 719 720} 721 722void VID_Update(vrect_t *rects) 723{ 724 if (!svgalib_inited) 725 return; 726 727 if (!vga_oktowrite()) 728 return; // can't update screen if it's not active 729 730 if (vid_waitforrefresh.value) 731 vga_waitretrace(); 732 733 if (VGA_planar) 734 VGA_UpdatePlanarScreen (vid.buffer); 735 736 else if (vid_redrawfull.value) { 737 int total = vid.rowbytes * vid.height; 738 int offset; 739 740 for (offset=0;offset<total;offset+=0x10000) { 741 vga_setpage(offset/0x10000); 742 memcpy(framebuffer_ptr, 743 vid.buffer + offset, 744 ((total-offset>0x10000)?0x10000:(total-offset))); 745 } 746 } else { 747 int ycount; 748 int offset; 749 int vidpage=0; 750 751 vga_setpage(0); 752 753 while (rects) 754 { 755 ycount = rects->height; 756 offset = rects->y * vid.rowbytes + rects->x; 757 while (ycount--) 758 { 759 register int i = offset % 0x10000; 760 761 if ((offset / 0x10000) != vidpage) { 762 vidpage=offset / 0x10000; 763 vga_setpage(vidpage); 764 } 765 if (rects->width + i > 0x10000) { 766 memcpy(framebuffer_ptr + i, 767 vid.buffer + offset, 768 0x10000 - i); 769 vga_setpage(++vidpage); 770 memcpy(framebuffer_ptr, 771 vid.buffer + offset + 0x10000 - i, 772 rects->width - 0x10000 + i); 773 } else 774 memcpy(framebuffer_ptr + i, 775 vid.buffer + offset, 776 rects->width); 777 offset += vid.rowbytes; 778 } 779 780 rects = rects->pnext; 781 } 782 } 783 784 if (vid_mode.value != current_mode) 785 VID_SetMode ((int)vid_mode.value, vid_current_palette); 786} 787 788static int dither; 789 790void VID_DitherOn(void) 791{ 792 if (dither == 0) 793 { 794// R_ViewChanged (&vrect, sb_lines, vid.aspect); 795 dither = 1; 796 } 797} 798 799void VID_DitherOff(void) 800{ 801 if (dither) 802 { 803// R_ViewChanged (&vrect, sb_lines, vid.aspect); 804 dither = 0; 805 } 806} 807 808void Sys_SendKeyEvents(void) 809{ 810 if (!svgalib_inited) 811 return; 812 813 if (UseKeyboard) 814 while (keyboard_update()); 815} 816 817void Force_CenterView_f (void) 818{ 819 cl.viewangles[PITCH] = 0; 820} 821 822 823void mousehandler(int buttonstate, int dx, int dy) 824{ 825 mouse_buttonstate = buttonstate; 826 mx += dx; 827 my += dy; 828} 829 830void IN_Init(void) 831{ 832 833 int mtype; 834 char *mousedev; 835 int mouserate; 836 837 if (UseMouse) 838 { 839 840 Cvar_RegisterVariable (&mouse_button_commands[0]); 841 Cvar_RegisterVariable (&mouse_button_commands[1]); 842 Cvar_RegisterVariable (&mouse_button_commands[2]); 843 Cvar_RegisterVariable (&m_filter); 844 Cmd_AddCommand ("force_centerview", Force_CenterView_f); 845 846 mouse_buttons = 3; 847 848 mtype = vga_getmousetype(); 849 850 mousedev = "/dev/mouse"; 851 if (getenv("MOUSEDEV")) mousedev = getenv("MOUSEDEV"); 852 if (COM_CheckParm("-mdev")) 853 mousedev = com_argv[COM_CheckParm("-mdev")+1]; 854 855 mouserate = 1200; 856 if (getenv("MOUSERATE")) mouserate = atoi(getenv("MOUSERATE")); 857 if (COM_CheckParm("-mrate")) 858 mouserate = atoi(com_argv[COM_CheckParm("-mrate")+1]); 859 860// printf("Mouse: dev=%s,type=%s,speed=%d\n", 861// mousedev, mice[mtype].name, mouserate); 862 if (mouse_init(mousedev, mtype, mouserate)) 863 { 864 Con_Printf("No mouse found\n"); 865 UseMouse = 0; 866 } 867 else 868 mouse_seteventhandler(mousehandler); 869 870 } 871 872} 873 874void IN_Shutdown(void) 875{ 876 if (UseMouse) 877 mouse_close(); 878} 879 880/* 881=========== 882IN_Commands 883=========== 884*/ 885void IN_Commands (void) 886{ 887 if (UseMouse && cls.state != ca_dedicated) 888 { 889 // poll mouse values 890 while (mouse_update()) 891 ; 892 893 // perform button actions 894 if ((mouse_buttonstate & MOUSE_LEFTBUTTON) && 895 !(mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) 896 Key_Event (K_MOUSE1, true); 897 else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) && 898 (mouse_oldbuttonstate & MOUSE_LEFTBUTTON)) 899 Key_Event (K_MOUSE1, false); 900 901 if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) && 902 !(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) 903 Key_Event (K_MOUSE2, true); 904 else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) && 905 (mouse_oldbuttonstate & MOUSE_RIGHTBUTTON)) 906 Key_Event (K_MOUSE2, false); 907 908 if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) && 909 !(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) 910 Key_Event (K_MOUSE3, true); 911 else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) && 912 (mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON)) 913 Key_Event (K_MOUSE3, false); 914 915 mouse_oldbuttonstate = mouse_buttonstate; 916 } 917} 918 919/* 920=========== 921IN_Move 922=========== 923*/ 924void IN_MouseMove (usercmd_t *cmd) 925{ 926 if (!UseMouse) 927 return; 928 929 // poll mouse values 930 while (mouse_update()) 931 ; 932 933 if (m_filter.value) 934 { 935 mouse_x = (mx + old_mouse_x) * 0.5; 936 mouse_y = (my + old_mouse_y) * 0.5; 937 } 938 else 939 { 940 mouse_x = mx; 941 mouse_y = my; 942 } 943 old_mouse_x = mx; 944 old_mouse_y = my; 945 mx = my = 0; // clear for next update 946 947 mouse_x *= sensitivity.value; 948 mouse_y *= sensitivity.value; 949 950// add mouse X/Y movement to cmd 951 if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) 952 cmd->sidemove += m_side.value * mouse_x; 953 else 954 cl.viewangles[YAW] -= m_yaw.value * mouse_x; 955 956 if (in_mlook.state & 1) 957 V_StopPitchDrift (); 958 959 if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) 960 { 961 cl.viewangles[PITCH] += m_pitch.value * mouse_y; 962 if (cl.viewangles[PITCH] > 80) 963 cl.viewangles[PITCH] = 80; 964 if (cl.viewangles[PITCH] < -70) 965 cl.viewangles[PITCH] = -70; 966 } 967 else 968 { 969 if ((in_strafe.state & 1) && noclip_anglehack) 970 cmd->upmove -= m_forward.value * mouse_y; 971 else 972 cmd->forwardmove -= m_forward.value * mouse_y; 973 } 974} 975 976void IN_Move (usercmd_t *cmd) 977{ 978 IN_MouseMove(cmd); 979} 980 981 982/* 983================ 984VID_ModeInfo 985================ 986*/ 987char *VID_ModeInfo (int modenum) 988{ 989 static char *badmodestr = "Bad mode number"; 990 static char modestr[40]; 991 992 if (modenum == 0) 993 { 994 sprintf (modestr, "%d x %d, %d bpp", 995 vid.width, vid.height, modes[current_mode].bytesperpixel*8); 996 return (modestr); 997 } 998 else 999 { 1000 return (badmodestr); 1001 } 1002} 1003 1004