Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, 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.  
  39. unsigned short       d_8to16table[256];
  40. static byte             *vid_surfcache;
  41. static int              VID_highhunkmark;
  42.  
  43. int num_modes;
  44. vga_modeinfo *modes;
  45. int current_mode;
  46.  
  47. int num_shades=32;
  48.  
  49. struct
  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.  
  63. static unsigned char scantokey[128];
  64. static byte vid_current_palette[768];
  65.  
  66. int num_mice = sizeof (mice) / sizeof(mice[0]);
  67.  
  68. int     d_con_indirect = 0;
  69.  
  70. int             svgalib_inited=0;
  71. int             UseMouse = 1;
  72. int             UseDisplay = 1;
  73. int             UseKeyboard = 1;
  74.  
  75. int             mouserate = MOUSE_DEFAULTSAMPLERATE;
  76.  
  77. cvar_t          vid_mode = {"vid_mode","5",false};
  78. cvar_t          vid_redrawfull = {"vid_redrawfull","0",false};
  79. cvar_t          vid_waitforrefresh = {"vid_waitforrefresh","0",true};
  80.  
  81. char    *framebuffer_ptr;
  82.  
  83. cvar_t  mouse_button_commands[3] =
  84. {
  85.     {"mouse1","+attack"},
  86.     {"mouse2","+strafe"},
  87.     {"mouse3","+forward"},
  88. };
  89.  
  90. int     mouse_buttons;
  91. int     mouse_buttonstate;
  92. int     mouse_oldbuttonstate;
  93. float   mouse_x, mouse_y;
  94. float   old_mouse_x, old_mouse_y;
  95. int             mx, my;
  96.  
  97. cvar_t  m_filter = {"m_filter","0"};
  98.  
  99. static byte     backingbuf[48*24];
  100.  
  101. int             VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
  102. byte    *VGA_pagebase;
  103.  
  104. void VGA_UpdatePlanarScreen (void *srcbuffer);
  105.  
  106. void 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.  
  170. void 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. =================
  231. VID_Gamma_f
  232.  
  233. Keybinding command
  234. =================
  235. */
  236. void 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.  
  263. void 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.  
  277. void 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. ================
  293. VID_NumModes
  294. ================
  295. */
  296. int 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.  
  305. void VID_NumModes_f (void)
  306. {
  307.         Con_Printf("%d modes\n",VID_NumModes());
  308. }
  309.  
  310. void 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.  
  320. void 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.  
  347. int 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.  
  387. int 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.  
  398. void 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.  
  415. void 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.  
  426. void 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.  
  442. void VID_ShiftPalette(unsigned char *p)
  443. {
  444.         VID_SetPalette(p);
  445. }
  446.  
  447. void 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.  
  472. int 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.  
  555. void 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.  
  722. void 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.  
  788. static int dither;
  789.  
  790. void VID_DitherOn(void)
  791. {
  792.     if (dither == 0)
  793.     {
  794. //              R_ViewChanged (&vrect, sb_lines, vid.aspect);
  795.         dither = 1;
  796.     }
  797. }
  798.  
  799. void VID_DitherOff(void)
  800. {
  801.     if (dither)
  802.     {
  803. //              R_ViewChanged (&vrect, sb_lines, vid.aspect);
  804.         dither = 0;
  805.     }
  806. }
  807.  
  808. void Sys_SendKeyEvents(void)
  809. {
  810.         if (!svgalib_inited)
  811.                 return;
  812.  
  813.         if (UseKeyboard)
  814.                 while (keyboard_update());
  815. }
  816.  
  817. void Force_CenterView_f (void)
  818. {
  819.         cl.viewangles[PITCH] = 0;
  820. }
  821.  
  822.  
  823. void mousehandler(int buttonstate, int dx, int dy)
  824. {
  825.         mouse_buttonstate = buttonstate;
  826.         mx += dx;
  827.         my += dy;
  828. }
  829.  
  830. void 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.  
  874. void IN_Shutdown(void)
  875. {
  876.         if (UseMouse)
  877.                 mouse_close();
  878. }
  879.  
  880. /*
  881. ===========
  882. IN_Commands
  883. ===========
  884. */
  885. void 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. ===========
  921. IN_Move
  922. ===========
  923. */
  924. void 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.  
  976. void IN_Move (usercmd_t *cmd)
  977. {
  978.         IN_MouseMove(cmd);
  979. }
  980.  
  981.  
  982. /*
  983. ================
  984. VID_ModeInfo
  985. ================
  986. */
  987. char *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.